chiark / gitweb /
debian/changelog: start -4~
[vtwm.git] / desktop.c
1 /*
2  * $Id: desktop.c,v 3.0 90/11/20 16:13:09 dme Exp Locker: dme $
3  *
4  * Copyright (c) 1990 Dave Edmondson.
5  * Copyright (c) 1990 Imperial College of Science, Technoology & Medicine
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose and without fee is hereby granted, provided
10  * that the above copyright notice appear in all copies and that both that
11  * copyright notice and this permission notice appear in supporting
12  * documentation, and that the names of Dave Edmondson or Imperial College
13  * not be used in advertising or publicity pertaining to distribution of the
14  * software without specific, written prior permission. Dave Edmondson and
15  * Imperial College make no representations about the suitability of this
16  * software for any purpose.  It is provided "as is" without express or
17  * implied warranty.
18  */
19
20 #include <stdio.h>
21 #include "twm.h"
22 #include "screen.h"
23 #include "add_window.h"
24 #include "menus.h"
25 #include "parse.h"
26 #include "events.h"
27 #include "desktop.h"
28
29 extern void SetRealScreenInternal();
30 extern void SetRealScreen();
31 extern void SnapRealScreen();
32 extern void SetMapStateProp();
33 extern void twmrc_error_prefix();
34
35 void SetVirtualPixmap();
36 void SetRealScreenPixmap();
37
38 /* djhjr - 4/27/98 */
39 static int starting_x, starting_y;
40
41 /* djhjr - 11/3/03 */
42 static int original_x, original_y;
43
44 static void GetDesktopWindowCoordinates(tmp_win, x, y, w, h)
45 TwmWindow *tmp_win;
46 int *x, *y, *w, *h;
47 {
48         /* djhjr - 4/27/98 */
49         int border = tmp_win->frame_bw + tmp_win->frame_bw3D;
50
51         /* Stig Ostholm <ostholm%ce.chalmers.se@uunet> */
52         if (tmp_win->nailed)
53         {       if (x)
54                         *x = tmp_win->frame_x / Scr->VirtualDesktopDScale;
55                 if (y)
56 /*                      *y = tmp_win->virtual_frame_y / Scr->VirtualDesktopDScale; */
57                         *y = tmp_win->frame_y / Scr->VirtualDesktopDScale; /* DSE */
58                 /* RFB 4/92 no SCALE_D */
59                 /* *x = SCALE_D(tmp_win->virtual_frame_x); */
60                 /* *y = SCALE_D(tmp_win->virtual_frame_y); */
61         } else {
62                 if (x)
63                         *x = tmp_win->virtual_frame_x / Scr->VirtualDesktopDScale;
64                 if (y)
65                         *y = tmp_win->virtual_frame_y / Scr->VirtualDesktopDScale;
66                 /* RFB 4/92 no SCALE_D */
67                 /* *x = SCALE_D(tmp_win->virtual_frame_x); */
68                 /* *y = SCALE_D(tmp_win->virtual_frame_y); */
69         }
70
71         if (w)
72         {       *w = SCALE_D(
73                         tmp_win->frame_width + Scr->VirtualDesktopDScale / 2
74
75 /* djhjr - 4/27/98
76                         + tmp_win->frame_bw + tmp_win->frame_bw )
77 */
78                         + (2 * border) )
79
80                         - 2;
81                 if ( *w <= 0 ) *w = 1;  /* 4/92 RFB */
82         }
83
84         if (h)
85         {       *h = SCALE_D(
86                         tmp_win->frame_height + Scr->VirtualDesktopDScale / 2
87 /* #ifdef SHAPE */
88                                 /* + tmp_win->title_height  */
89 /* #ifdef SHAPE */
90
91 /* djhjr - 4/27/98
92                         + tmp_win->frame_bw + tmp_win->frame_bw ) - 2;
93 */
94                         + (2 * border) ) - 2;
95
96 /* 4/92 RFB -- subtract borderwidth from windowwidth... */
97                 if ( *h <= 0 ) *h = 1;  /* 4/92 RFB */
98         }
99 }       /* Stig Ostholm <ostholm%ce.chalmers.se@uunet> */
100
101
102 /*
103  * create the virtual desktop display and store the window in the screen structure
104  */
105 void CreateDesktopDisplay()
106 {
107         int width, height;
108         int border;
109
110 /* djhjr - 5/17/98 */
111 #ifndef ORIGINAL_PIXMAPS
112         Pixmap pm = None;
113         GC gc;
114         XGCValues gcv;
115         XSetWindowAttributes attributes; /* attributes for create windows */
116         unsigned long valuemask;
117         unsigned int pm_numcolors;
118 #endif
119
120         if (!Scr->Virtual)
121                 return;
122
123         width = Scr->VirtualDesktopWidth / Scr->VirtualDesktopDScale;
124         height = Scr->VirtualDesktopHeight / Scr->VirtualDesktopDScale;
125
126 /* done in SetVirtualDesktop() - djhjr - 9/26/01
127         * we have some checking for negative (x,y) to do *
128         if (Scr->VirtualDesktopDX < 0) {
129                 Scr->VirtualDesktopDX = Scr->MyDisplayWidth - width -
130                         (2 * Scr->BorderWidth) + Scr->VirtualDesktopDX;
131         }
132         if (Scr->VirtualDesktopDY < 0) {
133                 Scr->VirtualDesktopDY = Scr->MyDisplayHeight - height -
134                         (2 * Scr->BorderWidth) + Scr->VirtualDesktopDY;
135         }
136 */
137
138         Scr->VirtualDesktopDisplayOuter =
139                 XCreateSimpleWindow(dpy, Scr->Root,
140                                     Scr->VirtualDesktopDX, Scr->VirtualDesktopDY,
141
142 /* djhjr - 2/7/99
143                                     width, height,
144 */
145                                     width + (Scr->VirtualDesktopBevelWidth * 2),
146                                     height + (Scr->VirtualDesktopBevelWidth * 2),
147
148 /* was 'Scr->BorderWidth' - submitted by Rolf Neugebauer */
149                                     0,
150                                     
151                                     Scr->Black, Scr->VirtualDesktopDisplayC.back);
152
153         /* djhjr - 2/7/99 */
154         {
155                 XSetWindowAttributes attr;
156
157                 attr.backing_store = True;
158                 XChangeWindowAttributes(dpy, Scr->VirtualDesktopDisplayOuter,
159                                 CWBackingStore, &attr);
160         }
161
162         if ( width != Scr->VirtualDesktopMaxWidth )
163                 Scr->VirtualDesktopMaxWidth = width;
164         if ( height != Scr->VirtualDesktopMaxHeight )
165                 Scr->VirtualDesktopMaxHeight = height;
166 /* vtwm 5.2: RFB growable but not unreasonable interior window! */
167
168 /*
169  * re-written to use an Image structure for XPM support
170  *
171  * djhjr - 5/17/98
172  */
173 #ifdef ORIGINAL_PIXMAPS
174         Scr->VirtualDesktopDisplay =
175                 XCreateSimpleWindow(dpy, Scr->VirtualDesktopDisplayOuter,
176
177 /* djhjr - 2/7/99
178                         0, 0,
179 */
180                         Scr->VirtualDesktopBevelWidth,
181                         Scr->VirtualDesktopBevelWidth, 
182
183                         Scr->VirtualDesktopMaxWidth,
184                         Scr->VirtualDesktopMaxHeight,
185                         0,
186                         Scr->VirtualDesktopDisplayBorder,
187                         Scr->VirtualC.back);/*RFB VCOLOR*/
188
189         XDefineCursor( dpy, Scr->VirtualDesktopDisplay,
190                 Scr->VirtualCursor );   /*RFBCURSOR*/
191
192         if ( Scr->virtualPm ) /*RFB PIXMAP*/
193         {       /* Background pixmap, copied from tvtwm */
194             Pixmap pm = None;
195             GC gc;
196             XGCValues gcv;
197
198                 pm = XCreatePixmap( dpy, Scr->VirtualDesktopDisplay,
199                                     Scr->virtual_pm_width, Scr->virtual_pm_height,
200                                     Scr->d_depth);
201                 gcv.foreground = Scr->VirtualC.fore;
202                 gcv.background = Scr->VirtualC.back;
203                 gcv.graphics_exposures = False;
204                 gc = XCreateGC (dpy, Scr->Root,
205                                 (GCForeground|GCBackground|GCGraphicsExposures),
206                                 &gcv);
207                 if (gc)
208                 {
209                         XCopyPlane (dpy, Scr->virtualPm, pm, gc, 0, 0,
210                                 Scr->virtual_pm_width, Scr->virtual_pm_height,
211                                 0, 0, 1);
212                     XFreeGC (dpy, gc);
213                         XSetWindowBackgroundPixmap( dpy, Scr->VirtualDesktopDisplay,
214                                 pm );
215                         XClearWindow( dpy, Scr->VirtualDesktopDisplay );
216                 }
217                 XFreePixmap (dpy, pm);
218         }
219 #else /* ORIGINAL_PIXMAPS */
220         pm_numcolors = 0;
221
222 /* djhjr - 5/23/98 9/2/98 */
223 #ifndef NO_XPM_SUPPORT
224         if (Scr->virtualPm)
225                 pm_numcolors = SetPixmapsBackground(Scr->virtualPm, Scr->Root,
226                                 Scr->VirtualC.back);
227 #endif
228
229         if (pm_numcolors > 2) /* not a bitmap */
230         {
231                 valuemask = CWBackPixmap;
232                 attributes.background_pixmap = Scr->virtualPm->pixmap;
233
234                 Scr->VirtualDesktopDisplay = XCreateWindow(dpy,
235                                 Scr->VirtualDesktopDisplayOuter,
236
237 /* djhjr - 2/7/99
238                                 0, 0,
239 */
240                                 Scr->VirtualDesktopBevelWidth,
241                                 Scr->VirtualDesktopBevelWidth, 
242
243                                 Scr->VirtualDesktopMaxWidth,
244                                 Scr->VirtualDesktopMaxHeight,
245                                 0,
246                                 Scr->d_depth, (unsigned int) CopyFromParent,
247                                 Scr->d_visual, valuemask, &attributes);
248         }
249         else
250         {
251                 Scr->VirtualDesktopDisplay = XCreateSimpleWindow(dpy,
252                                 Scr->VirtualDesktopDisplayOuter,
253
254 /* djhjr - 2/7/99
255                                 0, 0,
256 */
257                                 Scr->VirtualDesktopBevelWidth,
258                                 Scr->VirtualDesktopBevelWidth, 
259
260                                 Scr->VirtualDesktopMaxWidth,
261                                 Scr->VirtualDesktopMaxHeight,
262                                 0,
263                                 Scr->VirtualDesktopDisplayBorder,
264                                 Scr->VirtualC.back); /*RFB VCOLOR*/
265
266                 if (Scr->virtualPm)
267                 {
268                         pm = XCreatePixmap( dpy, Scr->VirtualDesktopDisplay,
269                                         Scr->virtualPm->width, Scr->virtualPm->height,
270                                         Scr->d_depth);
271
272                         gcv.foreground = Scr->VirtualC.fore;
273                         gcv.background = Scr->VirtualC.back;
274                         gcv.graphics_exposures = False;
275
276                         gc = XCreateGC(dpy, Scr->Root,
277                                         (GCForeground | GCBackground | GCGraphicsExposures),
278                                         &gcv);
279
280                         if (gc)
281                         {
282                                 XCopyPlane(dpy, Scr->virtualPm->pixmap, pm, gc, 0, 0,
283                                                 Scr->virtualPm->width, Scr->virtualPm->height,
284                                                 0, 0, 1);
285
286                                 XFreeGC (dpy, gc);
287
288                                 XSetWindowBackgroundPixmap(dpy, Scr->VirtualDesktopDisplay, pm);
289
290                                 XClearWindow(dpy, Scr->VirtualDesktopDisplay);
291                         }
292
293                         XFreePixmap(dpy, pm);
294                 }
295         }
296
297         XDefineCursor(dpy, Scr->VirtualDesktopDisplay, Scr->VirtualCursor); /*RFB CURSOR */
298 #endif /* ORIGINAL_PIXMAPS */
299
300         XSetStandardProperties(dpy, Scr->VirtualDesktopDisplayOuter,
301
302 /* djhjr - 4/27/96
303                                "Virtual Desktop", "Virtual Desktop",
304 */
305 /* djhjr - 5/19/98
306                                "VTWM Desktop", "VTWM Desktop",
307 */
308                                         VTWM_DESKTOP_CLASS, VTWM_DESKTOP_CLASS,
309
310                                None, NULL, 0, NULL);
311
312 /* Stig Ostholm moved a few lines away from here */
313
314 /* djhjr - 2/15/99
315         border = 0;
316         if ( Scr->UseRealScreenBorder )
317                 {
318                 * border = 2; *
319                 border = Scr->RealScreenBorderWidth; * DSE *
320                 }
321 */
322         border = Scr->RealScreenBorderWidth;
323
324 /*
325  * re-written to use an Image structure for XPM support
326  *
327  * djhjr - 5/17/98
328  */
329 #ifdef ORIGINAL_PIXMAPS
330         /* create the real screen display */
331         Scr->VirtualDesktopDScreen =
332                 XCreateSimpleWindow(dpy, Scr->VirtualDesktopDisplay,
333                                     0, 0,
334
335 /* djhjr - 2/15/99
336                                     SCALE_D(Scr->MyDisplayWidth - 2 * border),
337                                     SCALE_D(Scr->MyDisplayHeight - 2 * border),
338 */
339                                     SCALE_D(Scr->MyDisplayWidth) - 2 * border,
340                                     SCALE_D(Scr->MyDisplayHeight) - 2 * border,
341
342                                     border, /* make it distinctive */
343 /* RFB 4/92: make borderwidth 0 instead of 2 */
344 /* RFB 5.2: some people need the border... */
345                                     Scr->VirtualDesktopDisplayBorder,
346                                         Scr->RealScreenC.back ); /* RFB 4/92 */
347
348         if ( Scr->RealScreenPm ) /*RFB PIXMAP*/
349         {       /* Background pixmap */
350             Pixmap pm = None;
351             GC gc;
352             XGCValues gcv;
353
354                 pm = XCreatePixmap( dpy, Scr->VirtualDesktopDScreen,
355                                     Scr->RealScreen_pm_width, Scr->RealScreen_pm_height,
356                                     Scr->d_depth);
357                 gcv.foreground = Scr->RealScreenC.fore;
358                 gcv.background = Scr->RealScreenC.back;
359                 gcv.graphics_exposures = False;
360                 gc = XCreateGC (dpy, Scr->Root,
361                                 (GCForeground|GCBackground|GCGraphicsExposures),
362                                 &gcv);
363                 if (gc)
364                 {
365                         XCopyPlane (dpy, Scr->RealScreenPm, pm, gc, 0, 0,
366                                 Scr->RealScreen_pm_width, Scr->RealScreen_pm_height,
367                                 0, 0, 1);
368                     XFreeGC (dpy, gc);
369                         XSetWindowBackgroundPixmap( dpy, Scr->VirtualDesktopDScreen,
370                                 pm );
371                         XClearWindow( dpy, Scr->VirtualDesktopDScreen );
372                 }
373                 XFreePixmap (dpy, pm);
374         }
375 #else /* ORIGINAL_PIXMAPS */
376         pm_numcolors = 0;
377
378 /* djhjr - 5/23/98 9/2/98 */
379 #ifndef NO_XPM_SUPPORT
380         if (Scr->realscreenPm)
381                 pm_numcolors = SetPixmapsBackground(Scr->realscreenPm,
382                                 Scr->Root, Scr->RealScreenC.back);
383 #endif
384
385         if (pm_numcolors > 2) /* not a bitmap */
386         {
387                 valuemask = CWBackPixmap | CWBorderPixel;
388                 attributes.background_pixmap = Scr->realscreenPm->pixmap;
389                 attributes.border_pixel = Scr->VirtualDesktopDisplayBorder;
390
391                 Scr->VirtualDesktopDScreen = XCreateWindow(dpy,
392                                 Scr->VirtualDesktopDisplay,
393                                 0, 0,
394
395 /* djhjr - 2/15/99
396                                 SCALE_D(Scr->MyDisplayWidth - 2 * border),
397                                 SCALE_D(Scr->MyDisplayHeight - 2 * border),
398 */
399                                 SCALE_D(Scr->MyDisplayWidth) - 2 * border,
400                                 SCALE_D(Scr->MyDisplayHeight) - 2 * border,
401
402                                 border,
403                                 Scr->d_depth, (unsigned int) CopyFromParent,
404                                 Scr->d_visual, valuemask, &attributes);
405         }
406         else
407         {
408                 Scr->VirtualDesktopDScreen = XCreateSimpleWindow(dpy,
409                                 Scr->VirtualDesktopDisplay,
410                                 0, 0,
411
412 /* djhjr - 2/15/99
413                                 SCALE_D(Scr->MyDisplayWidth - 2 * border),
414                                 SCALE_D(Scr->MyDisplayHeight - 2 * border),
415 */
416                                 SCALE_D(Scr->MyDisplayWidth) - 2 * border,
417                                 SCALE_D(Scr->MyDisplayHeight) - 2 * border,
418
419                                 border, /* make it distinctive */
420 /* RFB 4/92: make borderwidth 0 instead of 2 */
421 /* RFB 5.2: some people need the border... */
422                                 Scr->VirtualDesktopDisplayBorder,
423                                 Scr->RealScreenC.back ); /* RFB 4/92 */
424
425                 if (Scr->realscreenPm)
426                 {
427                         pm = XCreatePixmap(dpy, Scr->VirtualDesktopDScreen,
428                                         Scr->realscreenPm->width, Scr->realscreenPm->height,
429                                         Scr->d_depth);
430
431                         gcv.foreground = Scr->RealScreenC.fore;
432                         gcv.background = Scr->RealScreenC.back;
433                         gcv.graphics_exposures = False;
434
435                         gc = XCreateGC(dpy, Scr->Root,
436                                         (GCForeground | GCBackground | GCGraphicsExposures),
437                                         &gcv);
438
439                         if (gc)
440                         {
441                                 XCopyPlane(dpy, Scr->realscreenPm->pixmap, pm, gc, 0, 0,
442                                                 Scr->realscreenPm->width, Scr->realscreenPm->height,
443                                                 0, 0, 1);
444
445                                 XFreeGC(dpy, gc);
446
447                                 XSetWindowBackgroundPixmap(dpy, Scr->VirtualDesktopDScreen, pm);
448
449                                 XClearWindow(dpy, Scr->VirtualDesktopDScreen);
450                         }
451
452                         XFreePixmap(dpy, pm);
453                 }
454         }
455 #endif /* ORIGINAL_PIXMAPS */
456
457         /* declare our interest */
458         XSelectInput(dpy, Scr->VirtualDesktopDisplay, ButtonPressMask | ButtonReleaseMask |
459                      KeyPressMask | KeyReleaseMask | ExposureMask);
460
461 /* Stig Ostholm moved some lines to here: */
462         Scr->VirtualDesktopDisplayTwin =
463                 AddWindow(Scr->VirtualDesktopDisplayOuter, FALSE, NULL);
464
465         /* djhjr - 5/19/98 */
466         Scr->VirtualDesktopDisplayTwin->class.res_name = strdup(VTWM_DESKTOP_CLASS);
467         Scr->VirtualDesktopDisplayTwin->class.res_class = strdup(VTWM_DESKTOP_CLASS);
468         XSetClassHint(dpy, Scr->VirtualDesktopDisplayOuter, &Scr->VirtualDesktopDisplayTwin->class);
469
470         /* limit the minimum size of the virtual desktop - djhjr - 2/23/99 */
471         Scr->VirtualDesktopDisplayTwin->hints.flags |= PMinSize;
472         Scr->VirtualDesktopDisplayTwin->hints.min_width =
473                 SCALE_D(Scr->MyDisplayWidth) + (Scr->VirtualDesktopBevelWidth * 2);
474         Scr->VirtualDesktopDisplayTwin->hints.min_height =
475                 SCALE_D(Scr->MyDisplayHeight) + (Scr->VirtualDesktopBevelWidth * 2);
476
477 #ifdef GROSS_HACK
478         /* this is a gross hack, but people wanted it */
479         Scr->VirtualDesktopDisplayTwin->nailed = TRUE;
480 #endif /* GROSS_HACK */
481
482         SetMapStateProp(Scr->VirtualDesktopDisplayTwin, NormalState);
483 /* :ereh ot senil emos devom mlohtsO gitS */
484
485         /* position the representation */
486         DisplayScreenOnDesktop();
487
488         /* map them all */
489         XMapWindow(dpy, Scr->VirtualDesktopDScreen);
490         XMapWindow(dpy, Scr->VirtualDesktopDisplay);
491         XMapWindow(dpy, Scr->VirtualDesktopDisplayOuter);
492
493         /* create the autopan windows if we are doing this */
494         if (Scr->AutoPanX > 0) {
495                 short l;
496
497                 /* left */
498                 Scr->VirtualDesktopAutoPan[0] = XCreateWindow(dpy, Scr->Root,
499                                                          0,
500                                                          0,
501                                                          AP_SIZE,
502                                                          Scr->MyDisplayHeight,
503                                                          0,
504                                                          CopyFromParent,
505                                                          InputOnly,
506                                                          CopyFromParent,
507                                                          0, NULL);
508                 /* right */
509                 Scr->VirtualDesktopAutoPan[1] = XCreateWindow(dpy, Scr->Root,
510                                                          Scr->MyDisplayWidth - AP_SIZE,
511                                                          0,
512                                                          AP_SIZE,
513                                                          Scr->MyDisplayHeight,
514                                                          0,
515                                                          CopyFromParent,
516                                                          InputOnly,
517                                                          CopyFromParent,
518                                                          0, NULL);
519                 /* top */
520                 Scr->VirtualDesktopAutoPan[2] = XCreateWindow(dpy, Scr->Root,
521                                                          0,
522                                                          0,
523                                                          Scr->MyDisplayWidth,
524                                                          AP_SIZE,
525                                                          0,
526                                                          CopyFromParent,
527                                                          InputOnly,
528                                                          CopyFromParent,
529                                                          0, NULL);
530                 /* bottom */
531                 Scr->VirtualDesktopAutoPan[3] = XCreateWindow(dpy, Scr->Root,
532                                                          0,
533                                                          Scr->MyDisplayHeight - AP_SIZE,
534                                                          Scr->MyDisplayWidth,
535                                                          AP_SIZE,
536                                                          0,
537                                                          CopyFromParent,
538                                                          InputOnly,
539                                                          CopyFromParent,
540                                                          0, NULL);
541
542                 /* set the event masks on the windows */
543                 for(l = 0; l <= 3; l++) {
544                         XSetStandardProperties(dpy, Scr->VirtualDesktopAutoPan[l],
545                                                "Automatic Pan", "Automatic Pan",
546                                                None, NULL, 0, NULL);
547
548                         /*
549                          * Added the leave event for pan resistance -
550                          * see events.c:HandleEnterNotify().
551                          *
552                          * djhjr - 11/16/98
553                          */
554                         XSelectInput(dpy, Scr->VirtualDesktopAutoPan[l],
555                                      EnterWindowMask | LeaveWindowMask);
556
557                         XMapWindow(dpy, Scr->VirtualDesktopAutoPan[l]);
558                 } /* end for l */
559         
560         } /* end if Scr->AutoPan */
561 }
562
563 /*
564  * re-written to use an Image structure for XPM support
565  *
566  * djhjr - 5/17/98
567  */
568 #ifdef ORIGINAL_PIXMAPS
569 void SetVirtualPixmap (filename)
570 char *filename;
571 {/*RFB PIXMAP*/
572     Pixmap pm = GetBitmap (filename);
573
574     if (pm) {
575         if (Scr->virtualPm) {
576             XFreePixmap (dpy, Scr->virtualPm);
577         }
578         Scr->virtualPm = pm;
579         Scr->virtual_pm_width = JunkWidth;
580         Scr->virtual_pm_height = JunkHeight;
581     }
582 }
583 #else /* ORIGINAL_PIXMAPS */
584 void SetVirtualPixmap (filename)
585 char *filename;
586 {
587         if (!Scr->virtualPm) Scr->virtualPm = SetPixmapsPixmap(filename);
588 }
589 #endif /* ORIGINAL_PIXMAPS */
590
591 /*
592  * re-written to use an Image structure for XPM support
593  *
594  * djhjr - 5/17/98
595  */
596 #ifdef ORIGINAL_PIXMAPS
597 void SetRealScreenPixmap (filename)
598 char *filename;
599 {/*RFB PIXMAP*/
600     Pixmap pm = GetBitmap (filename);
601
602     if (pm) {
603         if (Scr->RealScreenPm) {
604             XFreePixmap (dpy, Scr->RealScreenPm);
605         }
606         Scr->RealScreenPm = pm;
607         Scr->RealScreen_pm_width = JunkWidth;
608         Scr->RealScreen_pm_height = JunkHeight;
609     }
610 }
611 #else /* ORIGINAL_PIXMAPS */
612 void SetRealScreenPixmap (filename)
613 char *filename;
614 {
615         if (!Scr->realscreenPm) Scr->realscreenPm = SetPixmapsPixmap(filename);
616 }
617 #endif /* ORIGINAL_PIXMAPS */
618
619 /*
620  * add this window to the virtual desktop - aka nail it
621  */
622 void UpdateDesktop(tmp_win)
623 TwmWindow *tmp_win;
624 {
625         int x, y, width, height;
626         Window dwindow;
627
628         if (!Scr->Virtual)
629                 return;
630
631         if (!tmp_win->showindesktopdisplay)
632                 return;
633
634         if (tmp_win->icon) {
635                 XUnmapWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
636                 return;
637         }
638
639         GetDesktopWindowCoordinates(tmp_win, &x, &y, &width, &height);
640 /* Stig Ostholm <ostholm%ce.chalmers.se@uunet> these 3 lines */
641         dwindow = (tmp_win->nailed)
642                 ? Scr->VirtualDesktopDScreen : Scr->VirtualDesktopDisplay;
643
644         /* if it already has a vd display window, just move it to the right place
645            and map it, else actually create the window */
646         if (!tmp_win->VirtualDesktopDisplayWindow) {
647                 Pixel background, border;
648
649 #ifdef notdef
650                 if (!GetColorFromList(Scr->VirtualDesktopColorBL, tmp_win->full_name,
651                                      &tmp_win->class, &background) &&
652                     !GetColorFromList(Scr->TitleBackgroundL, tmp_win->full_name,
653                                       &tmp_win->class, &background))
654                         background = Scr->VirtualDesktopDisplayC.back;
655 #endif /* notdef */
656                 background = tmp_win->virtual.back;
657
658                 /* 7/10/90 - uses border list not foreground */
659                 if(!GetColorFromList(Scr->VirtualDesktopColorBoL, tmp_win->full_name,
660                                      &tmp_win->class, &border) &&
661                    !GetColorFromList(Scr->TitleForegroundL, tmp_win->full_name,
662                                      &tmp_win->class, &border))
663                         border = Scr->VirtualDesktopDisplayBorder;
664
665                 /* the position and size don't matter */
666                 tmp_win->VirtualDesktopDisplayWindow =
667                         XCreateSimpleWindow(dpy,
668                                 dwindow, x, y, width, height, /* Stig */
669                                 1, border, background);
670
671 /*RFBCURSOR*/XDefineCursor( dpy, tmp_win->VirtualDesktopDisplayWindow,
672 /*RFBCURSOR*/Scr->DesktopCursor );
673
674                 /* listen for expose events to redraw the name */
675                 if (Scr->NamesInVirtualDesktop)
676                         XSelectInput(dpy, tmp_win->VirtualDesktopDisplayWindow,
677                                      ExposureMask);
678
679                 /* save the twm window on the window */
680                 XSaveContext(dpy, tmp_win->VirtualDesktopDisplayWindow,
681                              VirtualContext, (caddr_t) tmp_win);
682                 XSaveContext(dpy, tmp_win->VirtualDesktopDisplayWindow,
683                              TwmContext, (caddr_t) tmp_win);
684
685
686 #if 0
687 0               /* Stig Ostholm <ostholm%ce.chalmers.se@uunet> */
688 0               /* comment out this section */
689 0       } else
690 0               /* unmap whilst we reconfigure it */
691 0               XUnmapWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
692 0
693 0       if (tmp_win->nailed) {
694 0               x = tmp_win->frame_x / Scr->VirtualDesktopDScale;
695 0               y = tmp_win->frame_y / Scr->VirtualDesktopDScale;
696 0/* RFB 4/92 no SCALE_D */
697 0               /* x = SCALE_D(tmp_win->frame_x); */
698 0               /* y = SCALE_D(tmp_win->frame_y); */
699 0
700 0               /* reparent this window into the little screen representation */
701 0               XReparentWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
702 0                               Scr->VirtualDesktopDScreen, x, y);
703 0       } else {
704 0               x = tmp_win->virtual_frame_x / Scr->VirtualDesktopDScale;
705 0               y = tmp_win->virtual_frame_y / Scr->VirtualDesktopDScale;
706 0/* RFB 4/92 no SCALE_D */
707 0               /* x = SCALE_D(tmp_win->virtual_frame_x); */
708 0               /* y = SCALE_D(tmp_win->virtual_frame_y); */
709 0
710 0               XReparentWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
711 0                               Scr->VirtualDesktopDisplay, x, y);
712 0       }
713 0
714 0       /* calculate the sizes and position */
715 0       width = SCALE_D(
716 0               tmp_win->frame_width + Scr->VirtualDesktopDScale / 2
717 0               + tmp_win->frame_bw + tmp_win->frame_bw )
718 0               - 2;
719 0       height = SCALE_D(
720 0               tmp_win->frame_height + Scr->VirtualDesktopDScale / 2
721 0/* #ifdef SHAPE */
722 0                       /* + tmp_win->title_height  */
723 0/* #endif */
724 0               + tmp_win->frame_bw + tmp_win->frame_bw ) - 2;
725 0/* 4/92 RFB -- subtract borderwidth from windowwidth... */
726 0       if ( width <= 0 ) width = 1;    /* 4/92 RFB */
727 0       if ( height <= 0 ) height = 1;  /* 4/92 RFB */
728 0
729 0#ifdef DEBUG
730 0       fprintf(stderr, "%d*%d+%d+%d\n", x, y, width, height);
731 0#endif /* DEBUG */
732 0
733 0       /* move and size it */
734 0       XMoveWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
735 0                   x, y);
736 0       XResizeWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
737 0                     width, height);
738 #else   /* 0, Stig */
739         } else {        /* Unmapping is fixed by XReparentWindow */
740                 XReparentWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
741                         dwindow, x, y);
742                 XResizeWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
743                         width, height);
744         }
745 #endif
746         XMapWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
747 }
748
749 #if 0   /* Stig */
750 0/* Stig Ostholm <ostholm%ce.chalmers.se@uunet> */
751 0/*
752 0 * remove a window from the desktop display - aka unnail it
753 0 */
754 0void RemoveFromDesktop(tmp_win)
755 0TwmWindow *tmp_win;
756 0{
757 0       int x, y;
758 0
759 0       if (!Scr->Virtual)
760 0               return;
761 0
762 0       /*
763 0       if (tmp_win->VirtualDesktopDisplayWindow)
764 0               XUnmapWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
765 0       */
766 0       /* reparent its representation out of the real screen window */
767 0       x = tmp_win->virtual_frame_x /Scr->VirtualDesktopDScale;
768 0       y = tmp_win->virtual_frame_y / Scr->VirtualDesktopDScale;
769 0/* RFB 4/92 no SCALE_D */
770 0       /* x = SCALE_D(tmp_win->virtual_frame_x); */
771 0       /* y = SCALE_D(tmp_win->virtual_frame_y); */
772 0
773 0       XReparentWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
774 0                       Scr->VirtualDesktopDisplay, x, y);
775 0}
776 #endif /* 0, Stig */
777
778 /* Stig Ostholm <ostholm%ce.chalmers.se@uunet>
779  * Nail/unnail a window on the desktop display.
780  */
781 void NailDesktop(tmp_win)
782 TwmWindow *tmp_win;
783 {
784         int x, y;
785
786         if (!tmp_win->VirtualDesktopDisplayWindow
787         || !Scr->Virtual
788         || tmp_win->icon)
789                 return;
790
791         GetDesktopWindowCoordinates(tmp_win, &x, &y, (int *) 0, (int *) 0);
792         XReparentWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
793                 (tmp_win->nailed)
794                         ? Scr->VirtualDesktopDScreen
795                         : Scr->VirtualDesktopDisplay,
796                 x, y);
797         XMapWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
798 }
799
800 /*
801  * state during the move
802  */
803 static unsigned int moving_x, moving_y, moving_w, moving_h, moving_bw;
804 static unsigned int moving_off_x, moving_off_y;
805 Window moving_window;
806 TwmWindow *moving_twindow;
807
808 /**********************************************************/
809 /*                                                        */
810 /*  RFB 7/16/93 -- moved these static variables up to     */
811 /*  this part of the file so that I could use moving_bw   */
812 /*  in DisplayScreenOnDesktop().                          */
813 /*                                                        */
814 /*  Note that moving_bw is set to 0 if you clicked *in*   */
815 /*  the window; therefore it can only have a non-zero     */
816 /*  value if you clicked at a random location in the      */
817 /*  panner, making the RealScreen jump to the pointer,    */
818 /*  AND you also had RealScreenBorderWidth set.           */
819 /*                                                        */
820 /*  This is almost the final step in getting the panner   */
821 /*  to behave pefectly! It still jitters a bit at the     */
822 /*  edges...                                              */
823 /*                                                        */
824 /**********************************************************/
825
826 /*
827  * correctly position the real screen representation on the virtual desktop display
828  */
829 void DisplayScreenOnDesktop()
830 {
831         int border;
832
833         if (!Scr->Virtual)
834                 return;
835
836 /* djhjr - 2/15/99
837         border = ( Scr->UseRealScreenBorder ) ? moving_bw : 0;
838         moving_bw = 0;
839 */
840         border = moving_bw = 0;
841
842         /* the -3 is to account for the 2 pixel border and the 1 pixel
843          * offset added by SCALE_D.... */
844         XMoveWindow(dpy, Scr->VirtualDesktopDScreen,
845                 Scr->VirtualDesktopX / Scr->VirtualDesktopDScale - border,
846                 Scr->VirtualDesktopY / Scr->VirtualDesktopDScale - border
847                     /* SCALE_D(Scr->VirtualDesktopX), */ /* - RFB changed 3 to 1 */
848                     /* SCALE_D(Scr->VirtualDesktopY) */ /* - RFB changed 3 to 1 */
849                         );
850 /* 4/92 RFB -- simply use SCALE_D; well, no...
851 ** the problem is that SCALE_D adds 1 if the result is 0, but
852 ** just gives the right result otherwise.
853 */
854
855         /* Way back, somebody wrote:    */
856         /* I've convinced myself that this is not necessary */
857         /* XLowerWindow(dpy, Scr->VirtualDesktopDScreen); */
858 }
859
860 void ResizeDesktopDisplay(w, h)
861 int w, h;
862 {
863         int bw, x, y, np;
864
865         if (!Scr->Virtual)
866                 return;
867
868
869         /* added compensation for the titlebar - djhjr - 2/23/99 */
870         h -= Scr->VirtualDesktopDisplayTwin->title_height;
871
872         /* added compensation for frame and bevel widths - djhjr - 2/7/99 */
873         bw = Scr->VirtualDesktopBevelWidth * 2;
874         if (Scr->BorderBevelWidth) bw += Scr->BorderWidth * 2;
875
876         np = 0;
877         if ( w - bw != Scr->VirtualDesktopMaxWidth )
878         {       Scr->VirtualDesktopMaxWidth = w - bw;
879                 np = 1;
880         }
881         if ( h - bw != Scr->VirtualDesktopMaxHeight )
882         {       Scr->VirtualDesktopMaxHeight = h - bw;
883                 np = 1;
884         }
885         if ( np )
886         {       XResizeWindow( dpy, Scr->VirtualDesktopDisplay,
887                         Scr->VirtualDesktopMaxWidth,
888                         Scr->VirtualDesktopMaxHeight );
889         }
890
891         /* calculate the new vd size */
892         Scr->VirtualDesktopWidth = SCALE_U(w - bw);
893         Scr->VirtualDesktopHeight = SCALE_U(h - bw);
894
895         x = SCALE_D(Scr->VirtualDesktopX);
896         y = SCALE_D(Scr->VirtualDesktopY);
897
898         /* redraw it so that the real screen representation ends up on the display */
899         np = SCALE_D(Scr->VirtualDesktopWidth) - SCALE_D(Scr->MyDisplayWidth);
900         if (x > np)
901                 x = np;
902
903         np = SCALE_D(Scr->VirtualDesktopHeight) - SCALE_D(Scr->MyDisplayHeight);
904         if (y > np)
905                 y = np;
906
907 #ifdef FUDGING
908         /* this is a bit of a fudge factor to account for the borderwidth */
909         x -= 2;
910         y -= 2;
911 #endif /* FUDGING */
912
913         SetRealScreen(SCALE_U(x), SCALE_U(y));
914
915         /* done in setrealscreen now */
916 #ifdef notdef
917         /* move the display window */
918         XMoveWindow(dpy, Scr->VirtualDesktopDScreen, x - 1, y - 1);
919 #endif /* notdef */
920 }
921
922
923 /*
924  * F_MOVESCREEN function
925  * move a window in the desktop display - possible including the `real' screen
926  */
927 void StartMoveWindowInDesktop(ev)
928 XMotionEvent ev;
929 {
930         int xoff, yoff;
931 #ifdef notdef
932         TwmWindow *Tmp_win;
933 #endif /* notdef */
934
935         if (!Scr->Virtual)
936                 return;
937
938         moving_window = ev.subwindow;
939
940         if (!moving_window)
941                 moving_window = Scr->VirtualDesktopDScreen;
942
943         XGrabPointer(dpy, Scr->VirtualDesktopDisplayOuter, True,
944                      ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
945                      GrabModeAsync, GrabModeAsync,
946                      Scr->VirtualDesktopDisplay, Scr->NoCursor, CurrentTime);
947
948         moving_x = ev.x;
949         moving_y = ev.y;
950
951         /* djhjr - 4/27/98 */
952         starting_x = ev.x;
953         starting_y = ev.y;
954
955         /* find the window by looking at the context on the little window */
956         if ((moving_window != Scr->VirtualDesktopDScreen) &&
957             (XFindContext(dpy, moving_window, VirtualContext,
958                           (caddr_t *) &moving_twindow) == XCNOENT)) {
959                 /* i don't think that this should _ever_ happen */
960                 moving_window = None;
961                 moving_twindow = NULL;
962                 return;
963         }
964
965         /* use Junk globals - djhjr - 4/28/98 */
966         XGetGeometry(dpy, moving_window, &JunkChild, &xoff, &yoff,
967                         &moving_w, &moving_h, &moving_bw, &JunkMask);
968
969         moving_off_x = moving_off_y = 0;
970         if ( xoff <= moving_x && moving_x <= ( xoff + moving_w )
971         &&   yoff <= moving_y && moving_y <= ( yoff + moving_h ))
972         {       /* The pointer is IN the window.
973                 ** don't start by moving the window so its upper-left is at
974                 ** the cursor! RFB
975                 */
976                 moving_off_x = xoff - moving_x;
977                 moving_off_y = yoff - moving_y;
978                 moving_bw = 0;
979         }
980
981         /* djhjr - 4/28/98 */
982         XMapRaised(dpy, Scr->SizeWindow);
983         InstallRootColormap();
984         if (moving_window == Scr->VirtualDesktopDScreen)
985                 JunkX = JunkY = 0;
986         else
987         {
988                 XGetGeometry(dpy, moving_twindow->frame, &JunkChild, &JunkX, &JunkY,
989                                 &JunkWidth, &JunkHeight, &JunkBW, &JunkMask);
990
991                 /* djhjr - 9/28/99 */
992                 {
993                         int hilite = moving_twindow->highlight;
994
995                         moving_twindow->highlight = True;
996                         SetBorder(moving_twindow, (hilite) ? True : False);
997                         moving_twindow->highlight = hilite;
998
999                         Scr->Focus = moving_twindow; /* evil */
1000
1001                         EventHandler[EnterNotify] = HandleUnknown;
1002                         EventHandler[LeaveNotify] = HandleUnknown;
1003                 }
1004
1005                 /* djhjr - 10/2/02 */
1006                 if (Scr->VirtualSendsMotionEvents &&
1007                         (moving_window != Scr->VirtualDesktopDScreen && !moving_twindow->opaque_move))
1008                                 MoveOutline(Scr->Root,
1009                                             JunkX, JunkY,
1010                                             moving_twindow->frame_width,
1011                                             moving_twindow->frame_height,
1012                                             moving_twindow->frame_bw,
1013                                             moving_twindow->title_height + moving_twindow->frame_bw3D);
1014
1015         }
1016
1017         /* added 'original_? = ' - djhjr - 11/3/03 */
1018         original_x = JunkX + Scr->VirtualDesktopX;
1019         original_y = JunkY + Scr->VirtualDesktopY;
1020         DisplayPosition(original_x, original_y);
1021
1022         /* get things going */
1023         DoMoveWindowOnDesktop(ev.x, ev.y);
1024 }
1025
1026 void DoMoveWindowOnDesktop(x, y)
1027 int x, y;
1028 {
1029         if (!Scr->Virtual)
1030                 return;
1031
1032         /*
1033          * cancel the effects of scaling errors by skipping the code
1034          * if nothing is actually moved - djhjr - 4/27/98
1035          */
1036         if (x == starting_x && y == starting_y)
1037                 return;
1038
1039         /* djhjr - 2/7/99 */
1040         x -= Scr->VirtualDesktopBevelWidth;
1041         y -= Scr->VirtualDesktopBevelWidth;
1042
1043         x += moving_off_x;
1044         y += moving_off_y;
1045         /* check that we are legit */
1046         if (x < 0)
1047                 x = 0;
1048         else {
1049
1050                 /* added real screen's border!? - djhjr - 2/15/99 */
1051                 int np = ( Scr->VirtualDesktopWidth /
1052                         Scr->VirtualDesktopDScale ) - moving_w -
1053                         Scr->RealScreenBorderWidth * 2;
1054
1055 /* RFB 4/92 no SCALE_D */
1056                 if (x > np)
1057                         x = np;
1058         }
1059         if (y < 0)
1060                 y = 0;
1061         else {
1062
1063                 /* added real screen's border!? - djhjr - 2/15/99 */
1064                 int np = ( Scr->VirtualDesktopHeight /
1065                         Scr->VirtualDesktopDScale ) - moving_h -
1066                         Scr->RealScreenBorderWidth * 2;
1067
1068 /* RFB 4/92 no SCALE_D */
1069                 if (y > np)
1070                         y = np;
1071         }
1072
1073         moving_x = x;
1074         moving_y = y;
1075
1076         /* move the display window */
1077         /* removed '- moving_bw' - djhjr - 2/15/99 */
1078         XMoveWindow(dpy, moving_window, x/* - moving_bw*/, y/* - moving_bw*/);
1079
1080         /* djhjr - 4/28/98 */
1081         DisplayPosition(SCALE_U(x), SCALE_U(y));
1082
1083 /* nah... it's pretty easy! - djhjr - 4/17/98
1084         * move the real window *
1085         * this is very difficult on anything not very powerful *
1086         * XMoveWindow(dpy, moving_twindow->frame, SCALE_U(x), SCALE_U(y)); *
1087 */
1088         if (Scr->VirtualSendsMotionEvents)
1089                 if (moving_window != Scr->VirtualDesktopDScreen)
1090                 {
1091                         if (moving_twindow->opaque_move)
1092                                 XMoveWindow(dpy, moving_twindow->frame,
1093                                         SCALE_U(x) - Scr->VirtualDesktopX,
1094                                         SCALE_U(y) - Scr->VirtualDesktopY);
1095                         else
1096                                 MoveOutline(Scr->Root,
1097                                         SCALE_U(x) - Scr->VirtualDesktopX,
1098                                         SCALE_U(y) - Scr->VirtualDesktopY,
1099                                         moving_twindow->frame_width,
1100                                         moving_twindow->frame_height,
1101                                         moving_twindow->frame_bw,
1102                                         moving_twindow->title_height + moving_twindow->frame_bw3D);
1103
1104                         /* djhjr - 9/28/99 */
1105                         Scr->Focus = moving_twindow; /* evil */
1106                 }
1107 }
1108
1109 void EndMoveWindowOnDesktop()
1110 {
1111         if (!Scr->Virtual)
1112                 return;
1113
1114         /* djhjr - 4/28/98 */
1115         XUnmapWindow(dpy, Scr->SizeWindow);
1116         UninstallRootColormap();
1117
1118         if (moving_window == Scr->VirtualDesktopDScreen) {
1119                 /* added '(Cancel) ? ... :' - djhjr - 11/3/03 */
1120                 SetRealScreen((Cancel) ? original_x : SCALE_U(moving_x),/* - moving_bw,*/
1121                         (Cancel) ? original_y : SCALE_U(moving_y) /*- moving_bw*/ );
1122         } else {
1123                 /* djhjr - 4/17/98 10/2/02 */
1124                 if (Scr->VirtualSendsMotionEvents &&
1125                         (moving_window != Scr->VirtualDesktopDScreen && !moving_twindow->opaque_move))
1126                                 /* erase the move outline */
1127                                 MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
1128
1129                 /* same little check as at the top of DoMoveWindowOnDesktop() - djhjr - 4/27/98 */
1130                 if (moving_x != starting_x || moving_y != starting_y)
1131                 {
1132                 /* move the window in virtual space */
1133                 /* added '(Cancel) ? ... :' - djhjr - 11/3/03 */
1134                 moving_twindow->virtual_frame_x =
1135                                 (Cancel) ? original_x : SCALE_U(moving_x);
1136                 moving_twindow->virtual_frame_y =
1137                                 (Cancel) ? original_y : SCALE_U(moving_y);
1138
1139                 /* move it in real space */
1140                 moving_twindow->frame_x = V_TO_R_X(moving_twindow->virtual_frame_x);
1141                 moving_twindow->frame_y = V_TO_R_Y(moving_twindow->virtual_frame_y);
1142
1143                 /* djhjr - 11/3/03 */
1144                 if (Cancel)
1145                         XMoveWindow(dpy, moving_window,
1146                                 SCALE_D(original_x), SCALE_D(original_y));
1147
1148                 XMoveWindow(dpy, moving_twindow->frame,
1149                             moving_twindow->frame_x, moving_twindow->frame_y);
1150
1151                 /* notify the window */
1152                 SendConfigureNotify(moving_twindow,
1153                             moving_twindow->frame_x, moving_twindow->frame_y);
1154                 }
1155
1156                 /* djhjr - 9/28/99 */
1157                 {
1158                         int hilite = moving_twindow->highlight;
1159
1160                         moving_twindow->highlight = True;
1161                         SetBorder(moving_twindow, False);
1162                         moving_twindow->highlight = hilite;
1163
1164                         Scr->Focus = NULL; /* evil */
1165
1166                         EventHandler[EnterNotify] = HandleEnterNotify;
1167                         EventHandler[LeaveNotify] = HandleLeaveNotify;
1168                 }
1169
1170                 /* added '!Cancel &&' - djhjr - 11/3/03 */
1171                 if (!Cancel && !Scr->NoRaiseMove) {
1172                         XRaiseWindow(dpy, moving_twindow->frame);
1173                         XRaiseWindow(dpy, moving_twindow->VirtualDesktopDisplayWindow);
1174
1175                         RaiseStickyAbove(); /* DSE */
1176                         RaiseAutoPan();
1177                 }
1178
1179                 /* djhjr - 6/4/98 */
1180                 if (Scr->VirtualSendsMotionEvents && !moving_twindow->opaque_move)
1181                 {
1182                         XUnmapWindow(dpy, Scr->VirtualDesktopDisplay);
1183                         XMapWindow(dpy, Scr->VirtualDesktopDisplay);
1184                 }
1185
1186                 moving_window = None;
1187
1188                 return;
1189         }
1190         moving_window = None;
1191         moving_twindow = NULL;
1192 }
1193
1194 /* Stig Ostholm <ostholm%ce.chalmers.se@uunet>
1195  * move and resize a window on the desktop.
1196  */
1197 void MoveResizeDesktop(tmp_win, noraise)
1198 TwmWindow *tmp_win;
1199 int noraise;
1200 {
1201         int x, y, w, h;
1202
1203         if (!tmp_win->VirtualDesktopDisplayWindow
1204         || !Scr->Virtual
1205         || tmp_win->icon)
1206                 return;
1207
1208         GetDesktopWindowCoordinates(tmp_win, &x, &y, &w, &h);
1209         /* Resize the desktop representation window */
1210         XMoveResizeWindow(dpy, tmp_win->VirtualDesktopDisplayWindow,
1211                 x, y, w, h);
1212         if (!noraise)
1213                 XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
1214 }
1215
1216 void SetVirtualDesktop(geom, scale)
1217 char *geom;
1218 int scale;
1219 {
1220
1221         if (Scr->Virtual) {
1222                 twmrc_error_prefix();
1223                 fprintf(stderr, "VirtualDesktop already defined -- ignored.\n");
1224                 return;
1225         }
1226
1227         if (scale < 0) {
1228                 twmrc_error_prefix();
1229                 fprintf(stderr,
1230                         "VirtualDesktop scale must be positive, not %d\n", scale);
1231                 return;
1232         }
1233         Scr->VirtualDesktopDScale = scale;
1234
1235         JunkMask = XParseGeometry (geom, &JunkX, &JunkY, &JunkWidth, &JunkHeight);
1236
1237         if ((JunkMask & (WidthValue | HeightValue)) !=
1238             (WidthValue | HeightValue)) {
1239             twmrc_error_prefix();
1240             fprintf (stderr, "bad VirtualDesktop \"%s\"\n", geom);
1241             return;
1242         }
1243         if (JunkWidth <= 0 || JunkHeight <= 0) {
1244             twmrc_error_prefix();
1245             fprintf (stderr, "VirtualDesktop \"%s\" must be positive\n", geom);
1246             return;
1247         }
1248
1249         /*
1250          * More flexible way of selecting size of virtual desktop (ala tvtwm)
1251          * M.J.E. Mol marcel@duteca.et.tudelft.nl
1252          */
1253         if (JunkWidth > Scr->MyDisplayWidth)
1254                 /* specified as total pixels */
1255                 JunkWidth /= Scr->VirtualDesktopDScale;
1256         else if (JunkWidth*Scr->VirtualDesktopDScale < Scr->MyDisplayWidth) {
1257                 /* specified as number of physical screens */
1258                 JunkWidth *= Scr->MyDisplayWidth;
1259                 JunkWidth /= Scr->VirtualDesktopDScale;
1260         }
1261         /* else specified as size of panner window */
1262
1263         if (JunkHeight > Scr->MyDisplayHeight)
1264                 /* specified as total pixels */
1265                 JunkHeight /= Scr->VirtualDesktopDScale;
1266         else if (JunkHeight*Scr->VirtualDesktopDScale < Scr->MyDisplayHeight) {
1267                 /* specified as number of physical screens */
1268                 JunkHeight *= Scr->MyDisplayHeight;
1269                 JunkHeight /= Scr->VirtualDesktopDScale;
1270         }
1271         /* else specified as size of panner window */
1272
1273         /* tar@math.ksu.edu: fix handling of -0 X and Y geometry */
1274 /* account for VirtualDesktopBevelWidth - djhjr - 9/26/01 */
1275         if (JunkMask & XValue) {
1276                 if (JunkMask & XNegative) {
1277                         Scr->VirtualDesktopDX = Scr->MyDisplayWidth
1278                             - JunkWidth - (2 * Scr->BorderWidth)
1279                             - (2 * Scr->VirtualDesktopBevelWidth) + JunkX;
1280                 }
1281                 else    Scr->VirtualDesktopDX = JunkX;
1282         }
1283         if (JunkMask & YValue) {
1284                 if (JunkMask & YNegative) {
1285                         Scr->VirtualDesktopDY = Scr->MyDisplayHeight
1286                             - JunkHeight - (2 * Scr->BorderWidth)
1287                             - (2 * Scr->VirtualDesktopBevelWidth) + JunkY;
1288                 }
1289                 else    Scr->VirtualDesktopDY = JunkY;
1290         }
1291
1292         JunkWidth *= Scr->VirtualDesktopDScale;
1293         JunkHeight *= Scr->VirtualDesktopDScale;
1294
1295         /* check that the vd is at least as big as the screen */
1296 /* handled above, M.J.E. Mol
1297 **      if ((JunkWidth < Scr->MyDisplayWidth)
1298 **          || (JunkHeight < Scr->MyDisplayHeight))
1299 **      {
1300 **              twmrc_error_prefix();
1301 **              fprintf(stderr,
1302 **                      "VirtualDesktop must be larger than screen (%dx%d)\n",
1303 **                      Scr->MyDisplayWidth, Scr->MyDisplayHeight);
1304 **              return;
1305 **      }
1306 */
1307         Scr->VirtualDesktopWidth = JunkWidth;
1308         Scr->VirtualDesktopHeight = JunkHeight;
1309
1310         /* all of the values looked reasonable */
1311         Scr->Virtual = TRUE;
1312 }
1313
1314 void VirtualMoveWindow(t, x, y)
1315 TwmWindow *t;
1316 int x, y;
1317 {
1318         if (!Scr->Virtual)
1319                 return;
1320
1321         /* move  window in virtual space */
1322         t->virtual_frame_x = x;
1323         t->virtual_frame_y = y;
1324
1325         /* move it in real space */
1326         t->frame_x = V_TO_R_X(x);
1327         t->frame_y = V_TO_R_Y(y);
1328
1329         XMoveWindow(dpy, t->frame,
1330                     t->frame_x, t->frame_y);
1331
1332         /* update the display */
1333         /* UpdateDesktop(t); Stig */
1334         MoveResizeDesktop(t, FALSE); /* Stig */
1335
1336         if (!Scr->NoRaiseMove) {
1337                 XRaiseWindow(dpy, t->frame);
1338                 /* XRaiseWindow(dpy, t->VirtualDesktopDisplayWindow); Stig */
1339
1340                 RaiseStickyAbove(); /* DSE */
1341                 RaiseAutoPan();
1342         }
1343 }
1344
1345 /*
1346  * F_SNAP function
1347  * for Kevin Twidle <kpt@doc.ic.ac.uk>
1348  * this snaps the real screen to a grid defined by the pandistance values.
1349  */
1350 void SnapRealScreen()
1351 {
1352         int newx, newy;
1353         int mod, div;
1354
1355         mod = Scr->VirtualDesktopX % Scr->VirtualDesktopPanDistanceX;
1356         div = Scr->VirtualDesktopX / Scr->VirtualDesktopPanDistanceX;
1357
1358         if (mod > (Scr->VirtualDesktopPanDistanceX / 2))
1359                 newx = Scr->VirtualDesktopPanDistanceX * (div + 1);
1360         else
1361                 newx = Scr->VirtualDesktopPanDistanceX * div;
1362
1363         mod = Scr->VirtualDesktopY % Scr->VirtualDesktopPanDistanceY;
1364         div = Scr->VirtualDesktopY / Scr->VirtualDesktopPanDistanceY;
1365
1366         if (mod > (Scr->VirtualDesktopPanDistanceY / 2))
1367                 newy = Scr->VirtualDesktopPanDistanceY * (div + 1);
1368         else
1369                 newy = Scr->VirtualDesktopPanDistanceY * div;
1370
1371         SetRealScreenInternal(newx, newy, FALSE, NULL, NULL); /* DSE */
1372 }
1373
1374
1375 void SetRealScreen(x, y)
1376 int x, y;
1377 {
1378         if (Scr->snapRealScreen)
1379                 SetRealScreenInternal(x, y, TRUE, NULL, NULL); /* DSE */
1380         else
1381                 SetRealScreenInternal(x, y, FALSE, NULL, NULL); /* DSE */
1382 }
1383
1384 /*
1385  * handles the possibility of snapping
1386  */
1387 void SetRealScreenInternal(x, y, dosnap, dx, dy)
1388 int x, y;
1389 int *dx, *dy; /* a pointer to an integer that contains the value
1390                  (AutoPanBorderWidth + AutoPanExtraWarp) is passed in to
1391                  both dx and dy when autopanning, or NULL is passed.  On
1392                  return, the value is modified to store how much the pointer
1393                  should actually be warped, in case
1394                  AutoPanWarpWithRespectToRealScreen is nonzero. -- DSE */
1395 short dosnap;
1396 {
1397         int xdiff, ydiff;
1398         TwmWindow *Tmp_win;
1399
1400         /* check bounds */
1401         if (x < 0) x = 0;
1402         if (y < 0) y = 0;
1403         if (x > (Scr->VirtualDesktopWidth - Scr->MyDisplayWidth))
1404                 x = Scr->VirtualDesktopWidth - Scr->MyDisplayWidth;
1405         if (y > (Scr->VirtualDesktopHeight - Scr->MyDisplayHeight))
1406                 y = Scr->VirtualDesktopHeight - Scr->MyDisplayHeight;
1407
1408         /* if ( Scr->RealScreenBorderWidth ) */
1409         /* {    x -= 2; */
1410                 /* y -= 2; */
1411         /* } */
1412
1413         /* how big a move is this ? */
1414         xdiff = Scr->VirtualDesktopX - x;
1415         ydiff = Scr->VirtualDesktopY - y;
1416
1417                 {
1418                 /* calculate how much we might warp the pointer */
1419                 int x_warp = ((xdiff<0) ? -1 : 1) * 
1420                   ((50 + abs(xdiff) * Scr->AutoPanWarpWithRespectToRealScreen) / 100);
1421                 int y_warp = ((ydiff<0) ? -1 : 1) *
1422                   ((50 + abs(ydiff) * Scr->AutoPanWarpWithRespectToRealScreen) / 100);
1423                 
1424                 /* make sure the pointer warps enought with respect to the real screen
1425                    so that it can get out of the autopan windows. */
1426                 if (dx)
1427                         if ( abs (*dx) < abs(x_warp) ) *dx = x_warp;
1428                 if (dy)
1429                         if ( abs (*dx) < abs(y_warp) ) *dy = y_warp;
1430                 }
1431                 
1432         /* make sure it isn't warped too much in case ``AutoPan 100'' and
1433            ``AutoPanWarpWithRespectToRealScreen 100'' (also known as
1434            ``NaturalAutopanBehavior'') are set. -- DSE */
1435                 {
1436                 int max_x_warp = ((xdiff<0) ? -1 : 1) *
1437                         (Scr->MyDisplayWidth - 2 * Scr->AutoPanBorderWidth);
1438                 int max_y_warp = ((ydiff<0) ? -1 : 1) *
1439                         (Scr->MyDisplayHeight - 2 * Scr->AutoPanBorderWidth);
1440                 if (dx)
1441                         if ( abs(*dx) > abs(max_x_warp) ) *dx = max_x_warp;
1442                 if (dy)
1443                         if ( abs(*dy) > abs(max_y_warp) ) *dy = max_y_warp;
1444                 }
1445
1446         /* move all of the windows by walking the twm list */
1447         for (Tmp_win = Scr->TwmRoot.next; Tmp_win != NULL; Tmp_win = Tmp_win->next)
1448         {
1449                 if (Scr->StaticIconPositions && Tmp_win->icon && Tmp_win->icon_w)
1450                 {
1451                         /*
1452                          * Make icons "stay put" on the virtual desktop when
1453                          * not otherwise nailed - djhjr - 12/14/98
1454                          */
1455                         XGetGeometry(dpy, Tmp_win->icon_w, &JunkRoot, &JunkX, &JunkY,
1456                                         &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth);
1457
1458                         XMoveWindow(dpy, Tmp_win->icon_w,
1459                                         JunkX + xdiff, JunkY + ydiff);
1460                 }
1461
1462                 if (Tmp_win->nailed || (Scr->DeIconifyToScreen && Tmp_win->icon))
1463                 {
1464                         /*
1465                          * The window is nailed or...
1466                          * The window is currently an icon, we are trying to
1467                          * keep things on the screen, so move it around the
1468                          * virtual desktop so that it stays on the real screen
1469                          */
1470                         Tmp_win->virtual_frame_x -= xdiff;
1471                         Tmp_win->virtual_frame_y -= ydiff;
1472                 }
1473                 else
1474                 {
1475                         /*
1476                          * move the window
1477                          */
1478                         Tmp_win->frame_x += xdiff;
1479                         Tmp_win->frame_y += ydiff;
1480
1481                         if (!dosnap)
1482                         {
1483                                 XMoveWindow(dpy, Tmp_win->frame,
1484                                                 Tmp_win->frame_x, Tmp_win->frame_y);
1485                                 SendConfigureNotify(Tmp_win,
1486                                                 Tmp_win->frame_x, Tmp_win->frame_y);
1487                         }
1488                 }
1489         }
1490
1491         Scr->VirtualDesktopX = x;
1492         Scr->VirtualDesktopY = y;
1493
1494         if (dosnap)
1495                 SnapRealScreen();
1496         else
1497                 DisplayScreenOnDesktop();
1498 }
1499
1500 /*
1501  * pan the real screen on the virtual desktop by (xoff, yoff)
1502  */
1503 void PanRealScreen(xoff, yoff, dx, dy)
1504 int xoff, yoff;
1505 int *dx, *dy; /* DSE */
1506 {
1507         /* panning the screen can never mean that you need to snap */
1508         SetRealScreenInternal(Scr->VirtualDesktopX + xoff, Scr->VirtualDesktopY + yoff,
1509 /* why not? - djhjr - 1/24/98
1510                               FALSE, dx, dy);
1511 */
1512                               Scr->snapRealScreen, dx, dy);
1513                                      /* DSE */
1514 }
1515
1516 /*
1517  * raise the auto-pan windows if needed
1518  */
1519
1520 void RaiseAutoPan()
1521 {
1522         int i;
1523         if (Scr->AutoPanX > 0)
1524                 for (i = 0; i <= 3; i++)
1525                         XRaiseWindow(dpy, Scr->VirtualDesktopAutoPan[i]);
1526 }
1527
1528 /*
1529  *      Raise sticky windows if StickyAbove is set. -- DSE
1530  */
1531
1532 void RaiseStickyAbove () {
1533         if (Scr->StickyAbove) {
1534                 TwmWindow *Tmp_win;
1535                 for (Tmp_win = Scr->TwmRoot.next; Tmp_win != NULL;
1536                 Tmp_win = Tmp_win->next)
1537                         if (Tmp_win->nailed) {
1538                                 XRaiseWindow(dpy,Tmp_win->w);
1539                                 XRaiseWindow(dpy,Tmp_win->VirtualDesktopDisplayWindow);
1540                                 XRaiseWindow(dpy,Tmp_win->frame);
1541                         }
1542         }
1543 }
1544
1545 /*
1546  *      Lower sticky windows. -- DSE
1547  */
1548
1549 void LowerSticky () {
1550         TwmWindow *Tmp_win;
1551         for (Tmp_win = Scr->TwmRoot.next; Tmp_win != NULL;
1552         Tmp_win = Tmp_win->next)
1553                 if (Tmp_win->nailed) {
1554                         XLowerWindow(dpy,Tmp_win->w);
1555                         XLowerWindow(dpy,Tmp_win->VirtualDesktopDisplayWindow);
1556                         XLowerWindow(dpy,Tmp_win->frame);
1557                 }
1558 }
1559