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