Use C++ linker
[oweals/cde.git] / cde / programs / dtwm / WmWinConf.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* 
24  * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2.2
29 */ 
30 #ifdef REV_INFO
31 #ifndef lint
32 static char rcsid[] = "$XConsortium: WmWinConf.c /main/8 1996/10/30 11:15:17 drk $"
33 #endif
34 #endif
35 /*
36  * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
37
38 /*
39  * Included Files:
40  */
41 #include "WmGlobal.h"   /* This should be the first include */
42 #include <X11/X.h>
43
44 #define XK_MISCELLANY
45 #include <X11/keysymdef.h>
46
47
48 #define MOVE_OUTLINE_WIDTH      2
49
50 #define CONFIG_MASK (KeyPressMask|ButtonPressMask|\
51                          ButtonReleaseMask|PointerMotionMask)
52 #define PGRAB_MASK (ButtonPressMask|ButtonReleaseMask|\
53                     PointerMotionMask|PointerMotionHintMask)
54
55 /* grab types */
56
57 #define NotGrabbed      0
58 #define ResizeGrab      1
59 #define MoveGrab        2
60 #ifdef WSM
61
62 /* Anchors */
63 #define ANCHOR_NONE     0
64 #define ANCHOR_NW       1
65 #define ANCHOR_NE       2
66 #define ANCHOR_SE       3
67 #define ANCHOR_SW       4
68
69 #ifndef ABS
70 #define ABS(x) ((x)>0?(x):(-(x)))
71 #endif /* ABS */
72 #endif /* WSM */
73
74 /* number of times to poll before blocking on a config event */
75
76 #define CONFIG_POLL_COUNT       300
77
78 /* mask for all buttons */
79 #define ButtonMask      \
80     (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
81
82 /*
83  * include extern functions
84  */
85 #include "WmWinConf.h"
86 #include "WmCDInfo.h"
87 #include "WmCDecor.h"
88 #include "WmCPlace.h"
89 #include "WmEvent.h"
90 #include "WmFeedback.h"
91 #include "WmFunction.h"
92 #include "WmIDecor.h"
93 #include "WmIPlace.h"
94 #include "WmIconBox.h"
95 #include "WmKeyFocus.h"
96 #include "WmProtocol.h"
97 #include "WmWinInfo.h"
98
99
100
101 /*
102  * Global Variables:
103  *
104  * These statics are set up at the initiation of a configuration 
105  * operation and used for succeeding events.
106  */
107
108 static int pointerX = -1;
109 static int pointerY = -1;
110
111 static int offsetX = 0;
112 static int offsetY = 0;
113
114 static int resizeX, resizeY;    /* root coords of UL corner of frame */
115 static unsigned int resizeWidth, resizeHeight;  /* size of frame */
116 static unsigned int resizeBigWidthInc, resizeBigHeightInc;
117 static int startX, startY; 
118 static unsigned int startWidth, startHeight;
119 static unsigned int minWidth, minHeight, maxHeight, maxWidth;
120 #ifdef WSM
121 static int marqueeX, marqueeY;  /* root coords of UL corner of are */
122 static long marqueeWidth, marqueeHeight;        /* size of area */
123 static unsigned int marqueeAnchor;      /* id of anchor corner */
124 static long marqueeWidth0, marqueeHeight0;      /* old size of area */
125 #endif /* WSM */
126
127 static int opaqueMoveX = 0;    /* for cancel request on opaque moves */
128 static int opaqueMoveY = 0;
129 static int moveX = 0;           /* root coords of UL corner of frame */
130 static int moveY = 0;
131 static int moveIBbbX = 0;       /* root coords of icon box bulletin board */
132 static int moveIBbbY = 0;
133 static unsigned int moveWidth = 0;      /* size of frame */
134 static unsigned int moveHeight = 0;
135 static int moveLastPointerX = 0;        /* last pointer position */
136 static int moveLastPointerY= 0;
137
138 static Boolean anyMotion = FALSE;
139 static Boolean configGrab = FALSE;
140 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
141 static Boolean grabServer = TRUE;
142 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
143
144 Dimension clipWidth = 0;
145 Dimension clipHeight = 0;
146 Position clipX = 0;
147 Position clipY = 0;
148
149
150 \f
151 /*************************************<->*************************************
152  *
153  *  GetClipDimensions (pcd, fromRoot)
154  *
155  *
156  *  Description:
157  *  -----------
158  *
159  *
160  *  Inputs:
161  *  ------
162  *  pcd         - pointer to client data
163  *
164  * 
165  *  Outputs:
166  *  -------
167  *
168  *
169  *  Comments:
170  *  --------
171  *************************************<->***********************************/
172 void GetClipDimensions (ClientData *pCD, Boolean fromRoot)
173 {
174
175     int i;
176     Arg getArgs[5];
177     Position tmpX, tmpY;
178
179     i=0;
180     XtSetArg (getArgs[i], XmNwidth, (XtArgVal) &clipWidth ); i++;
181     XtSetArg (getArgs[i], XmNheight, (XtArgVal) &clipHeight ); i++;
182     XtSetArg (getArgs[i], XmNx, (XtArgVal) &tmpX ); i++;
183     XtSetArg (getArgs[i], XmNy, (XtArgVal) &tmpY ); i++;
184
185     XtGetValues (P_ICON_BOX(pCD)->clipWidget, getArgs, i);
186
187     if (fromRoot)
188     {
189         XtTranslateCoords(P_ICON_BOX(pCD)->scrolledWidget,
190                         tmpX, tmpY,
191                         &clipX, &clipY);
192     }
193     else
194     {
195         clipX = tmpX;
196         clipY = tmpY;      
197     }                   
198
199 } /* END OF FUNCTION GetClipDimensions */
200
201
202 \f
203 /*************************************<->*************************************
204  *
205  *  HandleClientFrameMove (pcd, pev)
206  *
207  *
208  *  Description:
209  *  -----------
210  *  Provide visual feedback of interactive moving of the window.
211  *
212  *
213  *  Inputs:
214  *  ------
215  *  pcd         - pointer to client data
216  *  pev         - pointer to event
217  *
218  * 
219  *  Outputs:
220  *  -------
221  *
222  *
223  *  Comments:
224  *  --------
225  *************************************<->***********************************/
226 void HandleClientFrameMove (ClientData *pcd, XEvent *pev)
227 {
228     int tmpX, tmpY, warpX, warpY;
229     Window grab_win;
230     KeySym keysym;
231     Boolean control, moveDone;
232     Boolean firstTime;
233     int big_inc, keyMultiplier;
234     int newX, newY;
235     XEvent event, KeyEvent;
236
237     if (pev) {
238         firstTime = True;
239     }
240     else {
241         firstTime = False;
242     }
243
244     big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
245
246
247     /*
248      *  Do our grabs and initial setup if we're just starting out
249      */
250     if (!configGrab) {
251         if (!StartClientMove (pcd, pev))
252         {
253             /* configuration was not initiated */
254             return;
255         }
256     }
257
258     grab_win = GrabWin (pcd, pev);
259
260     
261     if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
262     {
263         GetClipDimensions (pcd, True);
264     }
265
266     moveDone = False;
267     while (!moveDone) 
268     {
269         tmpX = tmpY = 0;
270
271         if (firstTime) {
272             /* handle the event we were called with first */
273             firstTime = False;
274         }
275         else 
276         {
277             pev = &event;
278             GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK, 
279                 moveLastPointerX, moveLastPointerY, moveX, moveY,
280                 moveWidth, moveHeight, &event);
281         }
282
283         if (pev->type == KeyPress) 
284         {
285             keyMultiplier = 1;
286             while (keyMultiplier <= big_inc && 
287                       XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent, 
288                       (char *) pev))
289             {
290                   keyMultiplier++;
291             }
292
293             keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
294             control = (pev->xkey.state & ControlMask) != 0;
295             tmpX = tmpY = 0;
296
297             switch (keysym) {
298                 case XK_Left:
299                     tmpX = keyMultiplier * ((control) ? (-big_inc) : (-1));
300                     break;
301
302                 case XK_Up:
303                     tmpY = keyMultiplier * ((control) ? (-big_inc) : (-1));
304                     break;
305
306                 case XK_Right:
307                     tmpX = keyMultiplier * ((control) ? big_inc : 1);
308                     break;
309
310                 case XK_Down:
311                     tmpY = keyMultiplier * ((control) ? big_inc : 1);
312                     break;
313
314                 case XK_Return:
315                     CompleteFrameConfig (pcd, pev);
316                     return;
317
318                 case XK_Escape:
319                     CancelFrameConfig (pcd);
320                     CheckEatButtonRelease (pcd, pev);
321                     return;
322
323                 default:
324                     break;
325             }
326
327             if (tmpX || tmpY)  {
328                 warpX = moveLastPointerX + tmpX;
329                 warpY = moveLastPointerY + tmpY;
330
331                 ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
332
333                 if ((warpX != moveLastPointerX) || (warpY != moveLastPointerY))
334                 {
335                     SetPointerPosition (warpX, warpY, &newX, &newY);
336
337                     tmpX = newX - moveLastPointerX;
338                     tmpY = newY - moveLastPointerY;
339                     moveLastPointerX = newX;
340                     moveLastPointerY = newY;
341                     moveX += tmpX;
342                     moveY += tmpY;
343                 }
344                 else 
345                 {
346                     /*
347                      * make like motion event and move frame.
348                      */
349                     moveX += tmpX;
350                     moveY += tmpY;
351                 }
352             }
353         }
354         else if (pev->type == ButtonRelease) 
355         {
356             /*
357              *  Update (x,y) to the location of the button release
358              */
359             moveX += pev->xbutton.x_root - moveLastPointerX;
360             moveY += pev->xbutton.y_root - moveLastPointerY;
361
362             CompleteFrameConfig (pcd, pev);
363             moveDone = True;
364         }
365         else if (pev->type == MotionNotify) 
366         {       
367             tmpX = pev->xmotion.x_root - moveLastPointerX;
368             tmpY = pev->xmotion.y_root - moveLastPointerY;
369             moveLastPointerX = pev->xmotion.x_root;
370             moveLastPointerY = pev->xmotion.y_root;
371             moveX += tmpX;
372             moveY += tmpY;
373             anyMotion = True;
374         }
375
376         /* draw outline if there is something to draw */
377         if (tmpX || tmpY) {
378             FixFrameValues (pcd, &moveX, &moveY, &moveWidth, &moveHeight,
379                             FALSE /* no size checks */);
380             if (pcd->pSD->moveOpaque)
381             {
382                 MoveOpaque (pcd, moveX, moveY, moveWidth, moveHeight);
383             }
384             else
385             {
386                 MoveOutline(moveX, moveY, moveWidth, moveHeight);
387             }
388             
389             if ( !wmGD.movingIcon &&
390                  (wmGD.showFeedback & WM_SHOW_FB_MOVE))
391             {
392                 DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight, 
393                             (unsigned long) 0, FALSE /* no size checks */);
394             }
395         }
396     }
397
398 } /* END OF FUNCTION HandleClientFrameMove */
399
400
401 \f
402 /*************************************<->*************************************
403  *
404  *  UpdateAndDrawResize ()
405  *
406  *
407  *  Description:
408  *  -----------
409  *
410  *  Inputs:
411  *  ------
412  *  pcd         - pointer to client data
413  * 
414  *  Outputs:
415  *  -------
416  *
417  *
418  *  Comments:
419  *  --------
420  *************************************<->***********************************/
421 void UpdateAndDrawResize (ClientData *pcd)
422 {
423     int tmpHeight, tmpWidth;
424     
425     /* 
426      * Handle a motion event or a keypress that's like a motion 
427      * event
428      */
429     
430     /* set height */
431     
432     switch (wmGD.configPart) {
433       case FRAME_RESIZE_NW:
434       case FRAME_RESIZE_N:
435       case FRAME_RESIZE_NE:
436         tmpHeight = (int) startHeight + (startY - pointerY);
437         if (tmpHeight < (int) minHeight)
438         {
439             resizeHeight = minHeight;
440             resizeY = startY + startHeight - minHeight;
441         }
442         else if (pcd->pSD->limitResize 
443                  && (tmpHeight > (int) maxHeight)
444                  && (!(pcd->clientFlags & ICON_BOX)))
445         {
446             resizeHeight = maxHeight;
447             resizeY = startY + startHeight - maxHeight;
448         }
449         else
450         {
451             resizeHeight = (unsigned int) tmpHeight;
452             resizeY = pointerY;
453         }
454         break;
455         
456       case FRAME_RESIZE_SW:
457       case FRAME_RESIZE_S:
458       case FRAME_RESIZE_SE:
459         resizeY = startY;
460         tmpHeight = pointerY - startY + 1;
461         if (tmpHeight < (int) minHeight)
462         {
463             resizeHeight = minHeight;
464         }
465         else if (pcd->pSD->limitResize 
466                  && (tmpHeight > (int) maxHeight)
467                  && (!(pcd->clientFlags & ICON_BOX)))
468         {
469             resizeHeight = maxHeight;
470         }
471         else
472         {
473             resizeHeight = (unsigned int) tmpHeight;
474         }
475         break;
476         
477       default:
478         resizeY = startY;
479         resizeHeight = startHeight;
480         break;
481         
482     }
483     
484     /* set width */
485     
486     switch (wmGD.configPart) {
487       case FRAME_RESIZE_NW:
488       case FRAME_RESIZE_W:
489       case FRAME_RESIZE_SW:
490         tmpWidth = (int) startWidth + (startX - pointerX);
491         if (tmpWidth < (int) minWidth)
492         {
493             resizeWidth = minWidth;
494             resizeX = startX + startWidth - minWidth;
495         }
496         else if (pcd->pSD->limitResize 
497                  && (tmpWidth > (int) maxWidth)
498                  && (!(pcd->clientFlags & ICON_BOX)))
499         {
500             resizeWidth = maxWidth;
501             resizeX = startX + startWidth - maxWidth;
502         }
503         else
504         {
505             resizeWidth = (unsigned int) tmpWidth;
506             resizeX = pointerX;
507         }
508         break;
509         
510       case FRAME_RESIZE_NE:
511       case FRAME_RESIZE_E:
512       case FRAME_RESIZE_SE:
513         resizeX = startX;
514         tmpWidth = pointerX - startX + 1;
515         if (tmpWidth < (int) minWidth)
516         {
517             resizeWidth = minWidth;
518         }
519         else if (pcd->pSD->limitResize 
520                  && (tmpWidth > (int) maxWidth)
521                  && (!(pcd->clientFlags & ICON_BOX)))
522         {
523             resizeWidth = maxWidth;
524         }
525         else
526         {
527             resizeWidth = (unsigned int) tmpWidth;
528         }
529         break;
530         
531       default:
532         resizeX = startX;
533         resizeWidth = startWidth;
534         break;
535     }
536     
537     FixFrameValues (pcd, &resizeX, &resizeY, &resizeWidth, 
538                     &resizeHeight, TRUE /* do size checks */);
539     MoveOutline (resizeX, resizeY, resizeWidth, resizeHeight);
540     if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
541     {
542         DoFeedback(pcd, resizeX, resizeY, resizeWidth, resizeHeight,
543                    (unsigned long) 0, TRUE /* do size checks */);
544     }
545 }
546
547 \f
548 /*************************************<->*************************************
549  *
550  *  HandleClientFrameResize (pcd, pev)
551  *
552  *
553  *  Description:
554  *  -----------
555  *  Provide visual feedback of interactive resizing of the window.
556  *
557  *
558  *  Inputs:
559  *  ------
560  *  pcd         - pointer to client data
561  *  pev         - pointer to event
562  *
563  * 
564  *  Outputs:
565  *  -------
566  *
567  *
568  *  Comments:
569  *  --------
570  *  o The window sizes refer to the frame, not the client window.
571  * 
572  *************************************<->***********************************/
573 void HandleClientFrameResize (ClientData *pcd, XEvent *pev)
574 {
575     Window grab_win;
576     Boolean resizeDone;
577     XEvent event;
578
579
580     /*
581      * Do our grabs the first time through
582      */
583     if (!configGrab) {
584         if (StartResizeConfig (pcd, pev))
585         {
586             configGrab = TRUE;
587         }
588         else
589         {
590             /* resize could not be initiated */
591             return;
592         }
593     }
594
595     grab_win = GrabWin (pcd, pev);
596
597     resizeDone = False;
598     while (!resizeDone) 
599     {
600         if (!pev)       /* first time through will already have event */
601         {
602             pev = &event;
603
604             GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK, 
605                 pointerX, pointerY, resizeX, resizeY,
606                 resizeWidth, resizeHeight, &event);
607         }
608
609         if (pev->type == MotionNotify)
610         {
611             pointerX = pev->xmotion.x_root;
612             pointerY = pev->xmotion.y_root;
613             anyMotion = TRUE;
614
615             /*
616              * Really start resizing once the pointer hits a resize area
617              * (This only applies to accelerator and keyboard resizing!)
618              */
619             if (!wmGD.configSet && !SetPointerResizePart (pcd, pev)) {
620                 pev = NULL;
621                 continue;               /* ignore this event */
622             }
623         }
624         else if (pev->type == KeyPress) {
625
626             /* 
627              * Handle key event. 
628              */
629             resizeDone = HandleResizeKeyPress (pcd, pev);
630         }
631         else if (pev->type == ButtonRelease) {
632
633             /*
634              *  Update (x,y) to the location of the button release
635              */
636             pointerX = pev->xbutton.x_root;
637             pointerY = pev->xbutton.y_root;
638             UpdateAndDrawResize(pcd);
639
640             CompleteFrameConfig (pcd, pev);
641             resizeDone = True;
642         }
643         else  {
644             pev = NULL;
645             continue;                   /* ignore this event */
646         }
647
648         if (!resizeDone)
649         {
650             UpdateAndDrawResize(pcd);
651         }
652
653         pev = NULL;     /* reset event pointer */
654
655     }  /* end while */
656
657 } /* END OF FUNCTION HandleClientFrameResize */
658
659
660 \f
661 /*************************************<->*************************************
662  *
663  *  HandleResizeKeyPress (pcd, pev)
664  *
665  *
666  *  Description:
667  *  -----------
668  *  Handles keypress events during resize of window
669  *
670  *
671  *  Inputs:
672  *  ------
673  *  pcd         - pointer to client data
674  *  pev         - pointer to event
675  *
676  * 
677  *  Outputs:
678  *  -------
679  *  Return      - True if this event completes (or cancels) resizing 
680  * 
681  *
682  *  Comments:
683  *  --------
684  * 
685  *************************************<->***********************************/
686 Boolean HandleResizeKeyPress (ClientData *pcd, XEvent *pev)
687 {
688     KeySym keysym;
689     Boolean control;
690     int warpX, warpY, currentX, currentY, newX, newY;
691     int junk, keyMult;
692     Window junk_win;
693     XEvent KeyEvent;
694
695     /*
696      * Compress repeated keys 
697      */
698     keyMult = 1;
699     while (keyMult <= 10 && 
700               XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent, 
701               (char *) pev))
702     {
703           keyMult++;
704     }
705
706     keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
707     control = (pev->xkey.state & ControlMask) != 0;
708
709     switch (keysym) {
710         case XK_Left:
711             switch (wmGD.configPart) {
712                 case FRAME_NONE:
713                     wmGD.configPart = FRAME_RESIZE_W;
714                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
715                     warpY = resizeY + resizeHeight/2;
716                     warpX = resizeX + ((control) ? 
717                                           (-resizeBigWidthInc) : 
718                                           (-pcd->widthInc));
719                     break;
720
721                 case FRAME_RESIZE_N:
722                     wmGD.configPart = FRAME_RESIZE_NW;
723                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
724                     warpX = resizeX + ((control) ? 
725                                           (-resizeBigWidthInc) : 
726                                           (-pcd->widthInc));
727                     warpY = pointerY;
728                     break;
729
730                 case FRAME_RESIZE_S:
731                     wmGD.configPart = FRAME_RESIZE_SW;
732                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
733                     warpX = resizeX + ((control) ? 
734                                           (-resizeBigWidthInc) : 
735                                           (-pcd->widthInc));
736                     warpY = pointerY;
737                     break;
738                 
739                 default:
740                     warpX = pointerX + ((control) ? 
741                                         (-resizeBigWidthInc * keyMult) : 
742                                         (-pcd->widthInc * keyMult));
743                     warpY = pointerY;
744                     break;
745             }
746             break;
747
748         case XK_Up:
749             switch (wmGD.configPart) {
750                 case FRAME_NONE:
751                     wmGD.configPart = FRAME_RESIZE_N;
752                     warpX = resizeX + resizeWidth/2;
753                     warpY = resizeY + ((control) ? 
754                                           (-resizeBigHeightInc) : 
755                                           (-pcd->heightInc));
756                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
757                     break;
758
759                 case FRAME_RESIZE_W:
760                     wmGD.configPart = FRAME_RESIZE_NW;
761                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
762                     warpX = pointerX;
763                     warpY = resizeY + ((control) ? 
764                                           (-resizeBigHeightInc) : 
765                                           (-pcd->heightInc));
766                     break;
767
768                 case FRAME_RESIZE_E:
769                     wmGD.configPart = FRAME_RESIZE_NE;
770                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
771                     warpX = pointerX;
772                     warpY = resizeY + ((control) ? 
773                                               (-resizeBigHeightInc) : 
774                                               (-pcd->heightInc));
775                     break;
776
777                 default: 
778                     warpX = pointerX;
779                     warpY = pointerY + ((control) ? 
780                                         (-resizeBigHeightInc * keyMult) : 
781                                         (-pcd->heightInc * keyMult));
782                     break;
783             }
784             break;
785
786         case XK_Right:
787             switch (wmGD.configPart) {
788                 case FRAME_NONE:
789                     wmGD.configPart = FRAME_RESIZE_E;
790                     warpY = resizeY + resizeHeight/2;
791                     warpX = resizeX + resizeWidth - 1 + 
792                                ((control) ? resizeBigWidthInc : 
793                                             pcd->widthInc);
794                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
795                     break;
796
797                 case FRAME_RESIZE_N:
798                     wmGD.configPart = FRAME_RESIZE_NE;
799                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
800                     warpX = resizeX + resizeWidth - 1 + 
801                                ((control) ? resizeBigWidthInc : 
802                                             pcd->widthInc);
803                     warpY = pointerY;
804                     break;
805
806                 case FRAME_RESIZE_S:
807                     wmGD.configPart = FRAME_RESIZE_SE;
808                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
809                     warpX = resizeX + resizeWidth - 1 + 
810                                ((control) ? resizeBigWidthInc : 
811                                             pcd->widthInc);
812                     warpY = pointerY;
813                     break;
814
815                 default:
816                     warpX = pointerX + ((control) ? 
817                                         (resizeBigWidthInc * keyMult) : 
818                                         (pcd->widthInc * keyMult));
819                     warpY = pointerY;
820                     break;
821             }
822             break;
823
824         case XK_Down:
825             switch (wmGD.configPart) {
826                 case FRAME_NONE:
827                     wmGD.configPart = FRAME_RESIZE_S;
828                     warpX = resizeX + resizeWidth/2;
829                     warpY = resizeY + resizeHeight - 1 + 
830                                ((control) ? resizeBigHeightInc : 
831                                             pcd->heightInc);
832                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
833                     break;
834
835                 case FRAME_RESIZE_E:
836                     wmGD.configPart = FRAME_RESIZE_SE;
837                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
838                     warpX = pointerX;
839                     warpY = resizeY + resizeHeight - 1 + 
840                                ((control) ? resizeBigHeightInc : 
841                                             pcd->heightInc);
842                     break;
843
844                 case FRAME_RESIZE_W:
845                     wmGD.configPart = FRAME_RESIZE_SW;
846                     ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
847                     warpX = pointerX;
848                     warpY = resizeY + resizeHeight - 1 + 
849                                ((control) ? resizeBigHeightInc : 
850                                             pcd->heightInc);
851                     break;
852
853                 default:
854                     warpX = pointerX;
855                     warpY = pointerY + ((control) ? 
856                                         (resizeBigHeightInc * keyMult) : 
857                                         (pcd->heightInc * keyMult));
858                     break;
859             }
860             break;
861
862         case XK_Return:
863             CompleteFrameConfig (pcd, pev);
864             return (True);
865
866         case XK_Escape:
867             CancelFrameConfig (pcd);
868             CheckEatButtonRelease (pcd, pev);
869             return (True);
870
871         default:
872             return (False);             /* ignore this key */
873
874     } /* end switch(keysym) */
875
876     /*
877      * Make sure the new pointer position is on screen before doing
878      * the warp. Warp only if the pointer position changes.
879      */
880     pointerX = warpX;
881     pointerY = warpY;
882
883     ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
884
885     /*
886      * Don't query pointer if enable warp is off.
887      */
888     if (!wmGD.enableWarp ||
889         XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
890                &currentX, &currentY, &junk, &junk, (unsigned int *)&junk))
891     {
892         if ( (warpX != currentX) || (warpY != currentY) ) 
893         {
894             SetPointerPosition (warpX, warpY, &newX, &newY);
895             return (False);
896         }
897     }
898     return (False);
899
900 } /* END OF FUNCTION HandleResizeKeyPress */
901
902 \f
903 /*************************************<->*************************************
904  *
905  *  DoFeedback (pcd, x, y, width, height, newStyle, resizing)
906  *
907  *
908  *  Description:
909  *  -----------
910  *  Start or update feedback of size/position info
911  *
912  *
913  *  Inputs:
914  *  ------
915  *  pcd         - pointer to client data
916  *  x           -
917  *  y           -
918  *  width       - 
919  *  height      -
920  *  newStyle    - style flags. 
921  *  resizing    - check size constraints iff TRUE
922  *  
923  * 
924  *  Outputs:
925  *  -------
926  *
927  *
928  *  Comments:
929  *  --------
930  *  o If newStyle has FB_POSITION  and/or FB_SIZE bits set, then it is
931  *    assumed that this is an initial call and a feedback window of the
932  *    desired style should be popped up. If newStyle is zero, then it
933  *    is assumed that the feedback window is already up and the values
934  *    passed in are updates.
935  * 
936  *************************************<->***********************************/
937 void DoFeedback (ClientData *pcd, int x, int y, unsigned int width, unsigned int height, unsigned long newStyle, Boolean resizing)
938 {
939     int cx = x;
940     int cy = y;
941     unsigned int cwidth, cheight;
942
943     /* compute client window coordinates from frame coordinates */
944     FrameToClient (pcd, &cx, &cy, &width, &height);
945
946     /* use frame (not client) position if user wishes it */
947     if (wmGD.positionIsFrame) {
948         cx = x;
949         cy = y;
950     }
951
952     /* If resizing, make sure configuration is valid. */
953     if (resizing)
954     {
955         FixWindowConfiguration (pcd, &width, &height,
956                                  (unsigned int) pcd->widthInc, 
957                                  (unsigned int) pcd->heightInc);
958     }
959
960     /*
961      * Put size in client specific units.  Do not include base into calculations
962      * when increment is not specified (i.e. = 1).
963      */
964     cwidth = (width - ((pcd->widthInc==1) ? 0 : pcd->baseWidth))
965                 / pcd->widthInc;
966     cheight = (height - ((pcd->heightInc==1) ? 0 : pcd->baseHeight))
967                 / pcd->heightInc;
968
969     if (newStyle) {
970         ShowFeedbackWindow (pcd->pSD, cx, cy, cwidth, cheight, newStyle);
971     }
972     else {
973         UpdateFeedbackInfo (pcd->pSD, cx, cy, cwidth, cheight);
974     }
975 } /* END OF FUNCTION DoFeedback  */
976
977
978 \f
979 /*************************************<->*************************************
980  *
981  *  CheckVisualPlace
982  *
983  *
984  *  Description:
985  *  -----------
986  *  Prevents icons in the icon box from being moved outside the clip window
987  *
988  *
989  *  Inputs:
990  *  ------
991  *  pcd         - pointer to client data
992
993  *
994  * 
995  *  Outputs:
996  *  -------
997  *
998  *
999  *  Comments:
1000  *  --------
1001  * 
1002  *************************************<->***********************************/
1003
1004 Boolean CheckVisualPlace (ClientData *pCD, int tmpX, int tmpY)
1005 {
1006     Boolean rval = True;
1007     Window child;
1008     int newX;
1009     int newY;
1010     
1011     GetClipDimensions(pCD, True);
1012
1013
1014     /* 
1015      * Get root coordinates of X and Y for icon.
1016      * We use root coordinates of clip window since clipX and
1017      * clipY are not 0, but the icon X and Y may be 0 in
1018      * local coordinates
1019      */
1020      
1021     XTranslateCoordinates(DISPLAY, XtWindow(P_ICON_BOX(pCD)->bBoardWidget),
1022                           ROOT_FOR_CLIENT(pCD), tmpX, tmpY,
1023                           &newX, &newY, &child);
1024
1025
1026     if (newX < clipX) 
1027     {
1028         return(False);
1029     }
1030     if (newY < clipY) 
1031     {
1032         return(False);
1033     }
1034
1035
1036     if (((int)newX) > ((int)clipX + 
1037         (int)clipWidth - ((int)ICON_WIDTH(pCD)))) 
1038     {
1039         return(False);
1040     }
1041     if (((int)newY) > ((int)clipY + 
1042         (int)clipHeight - ((int)ICON_HEIGHT(pCD))))
1043     {
1044         return(False);
1045     }
1046     
1047     return (rval);
1048  
1049 } /* END OF FUNCTION CheckVisualPlace */
1050
1051
1052 \f
1053 /*************************************<->*************************************
1054  *
1055  *  CompleteFrameConfig (pcd, pev)
1056  *
1057  *
1058  *  Description:
1059  *  -----------
1060  *  Clean up graphic feedback when user stops configuring.
1061  *
1062  *
1063  *  Inputs:
1064  *  ------
1065  *  pcd         - pointer to client data
1066  *  pev         - pointer to event
1067  *
1068  * 
1069  *  Outputs:
1070  *  -------
1071  *
1072  *
1073  *  Comments:
1074  *  --------
1075  *  o This routine assumes that it is called in response to a button release
1076  *    event.
1077  * 
1078  *************************************<->***********************************/
1079 void CompleteFrameConfig (ClientData *pcd, XEvent *pev)
1080 {
1081     unsigned int tmpWidth, tmpHeight;
1082     int tmpX, tmpY;
1083     Boolean inIconBox;
1084     
1085     
1086     if (wmGD.configAction == RESIZE_CLIENT) {
1087         /* release the grabs */
1088         UndoGrabs();
1089
1090         /*
1091          * Honor the implied constrained anchor points on the window
1092          * so that the resize doesn't cause the window to move 
1093          * unexpectedly.
1094          */
1095
1096 #ifndef CONFIG_RELATIVE_TO_CLIENT
1097
1098         tmpX = resizeX;
1099         tmpY = resizeY;
1100
1101         /* Use dummy x,y so we don't add frame offset to client location */
1102         FrameToClient (pcd, &tmpX, &tmpY, &resizeWidth, &resizeHeight);
1103 #else
1104         FrameToClient (pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
1105 #endif
1106
1107         tmpWidth = resizeWidth;
1108         tmpHeight = resizeHeight;
1109
1110         FixWindowConfiguration (pcd, &tmpWidth, &tmpHeight,
1111                                      (unsigned int) pcd->widthInc, 
1112                                      (unsigned int) pcd->heightInc);
1113
1114         AdjustPos (&resizeX, &resizeY,
1115                    resizeWidth, resizeHeight, tmpWidth, tmpHeight);
1116
1117         /* reconfigure the window(s) */
1118         ProcessNewConfiguration (pcd, resizeX, resizeY, 
1119                                  resizeWidth, resizeHeight, FALSE);
1120
1121     }
1122     else if (wmGD.configAction == MOVE_CLIENT)
1123     {
1124         /* release the grabs */
1125         UndoGrabs();
1126
1127         /* make sure title bar is popped out */
1128         if ((wmGD.configAction == MOVE_CLIENT) &&
1129             (wmGD.gadgetClient == pcd) && 
1130             (wmGD.gadgetDepressed == FRAME_TITLE))
1131         {
1132             PopGadgetOut (pcd, FRAME_TITLE);
1133             FrameExposureProc(pcd);                     /* repaint frame */
1134         }
1135
1136         /* handle both icon and normal frames */
1137         if (wmGD.movingIcon)
1138         {
1139
1140             inIconBox = (pcd->pSD->useIconBox && P_ICON_BOX(pcd));
1141
1142             /* only need to move the icon */
1143             if (wmGD.iconAutoPlace || inIconBox)
1144             {
1145                 int centerX;
1146                 int centerY;
1147                 int place;
1148                 IconPlacementData *pIPD;
1149
1150                 /* 
1151                  * Get correct icon placement data
1152                  */
1153                 if (inIconBox) 
1154                 {
1155                     pIPD = &P_ICON_BOX(pcd)->IPD;
1156                     moveX -= moveIBbbX;
1157                     moveY -= moveIBbbY;
1158                 }
1159                 else
1160                 {
1161                     pIPD = &(ACTIVE_WS->IPData);
1162                 }
1163
1164                 /*
1165                  * Check to make sure that there is an unoccupied place
1166                  * where the icon is being moved to:
1167                  */
1168
1169                 centerX = moveX + ICON_WIDTH(pcd) / 2;
1170                 centerY = moveY + ICON_HEIGHT(pcd) / 2;
1171                 place = CvtIconPositionToPlace (pIPD, centerX, centerY);
1172
1173                 if (place != ICON_PLACE(pcd))
1174                 {
1175                     if (pIPD->placeList[place].pCD)
1176                     {
1177                         /*
1178                          * Primary place occupied, try to find an unoccupied
1179                          * place in the proximity.
1180                          */
1181
1182                         place = FindIconPlace (pcd, pIPD, centerX, centerY);
1183                         if (place == NO_ICON_PLACE)
1184                         {
1185                             /*
1186                              * Can't find an unoccupied icon place.
1187                              */
1188
1189                             F_Beep (NULL, pcd, (XEvent *)NULL);
1190
1191                             if (pcd->pSD->moveOpaque && !inIconBox)
1192                             {
1193                                 /*
1194                                  * Replace icon into same place - as if it
1195                                  * didn't move.
1196                                  */
1197                                 
1198                                 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1199                                              ICON_X(pcd), ICON_Y(pcd));
1200                                 if ((ICON_DECORATION(pcd) & 
1201                                      ICON_ACTIVE_LABEL_PART) &&
1202                                     (wmGD.keyboardFocus == pcd))
1203                                 {
1204                                     MoveActiveIconText(pcd);
1205                                     ShowActiveIconText(pcd);
1206                                 }
1207                             }
1208                         }
1209                     }
1210                     if ((place != NO_ICON_PLACE) && 
1211                         (place != ICON_PLACE(pcd)))
1212                     {
1213                         if (inIconBox)
1214                         {
1215                             CvtIconPlaceToPosition (pIPD, place,
1216                                                 &tmpX, &tmpY);
1217                             if( (CheckIconBoxSize (P_ICON_BOX(pcd))) &&
1218                                 (CheckVisualPlace(pcd, tmpX, tmpY)))
1219                             {
1220                                 /*
1221                                  * Move the icon to the new place.
1222                                  */
1223
1224                                 MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
1225                                 CvtIconPlaceToPosition (pIPD, place, 
1226                                                 &ICON_X(pcd), &ICON_Y(pcd));
1227
1228
1229                                 XtMoveWidget (
1230                                     pIPD->placeList[ICON_PLACE(pcd)].theWidget,
1231                                     ICON_X(pcd), ICON_Y(pcd));
1232
1233                                 SetNewBounds (P_ICON_BOX(pcd));
1234                                 if (ICON_DECORATION(pcd) &
1235                                     ICON_ACTIVE_LABEL_PART)
1236                                 {
1237                                     MoveActiveIconText(pcd);
1238                                 }
1239                             }
1240                             else
1241                             {
1242                                 F_Beep (NULL, pcd, (XEvent *)NULL);
1243                             }
1244                         }
1245                         else 
1246                         {
1247                             /*
1248                              * Move the icon to the new place.
1249                              */
1250                             MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
1251                             CvtIconPlaceToPosition (pIPD, place, &ICON_X(pcd), 
1252                                                     &ICON_Y(pcd));
1253
1254                             XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd), 
1255                                          ICON_X(pcd), ICON_Y(pcd));
1256
1257                             if (pcd->pSD->moveOpaque &&
1258                                 (ICON_DECORATION(pcd) & 
1259                                  ICON_ACTIVE_LABEL_PART) &&
1260                                 (wmGD.keyboardFocus == pcd))
1261                             {
1262                                 MoveActiveIconText(pcd);
1263                                 ShowActiveIconText(pcd);
1264                             }
1265                         }
1266                     }
1267                 }
1268                 else if (pcd->pSD->moveOpaque && !inIconBox)
1269                 {
1270                     /*
1271                      * Replace icon into same place - as if it
1272                      * didn't move.
1273                      */
1274                     XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1275                                  ICON_X(pcd), ICON_Y(pcd));
1276                     if ((ICON_DECORATION(pcd) & 
1277                          ICON_ACTIVE_LABEL_PART) &&
1278                         (wmGD.keyboardFocus == pcd))
1279                     {
1280                         MoveActiveIconText(pcd);
1281                         ShowActiveIconText(pcd);
1282                     }
1283                 }
1284             }
1285             else
1286             {
1287                 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd), moveX, moveY);
1288                 ICON_X(pcd) = moveX;
1289                 ICON_Y(pcd) = moveY;
1290             }
1291             if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
1292                 (wmGD.keyboardFocus == pcd))
1293             {
1294                 MoveActiveIconText(pcd);
1295             }
1296         }
1297         else {  /* assume normal window frame */
1298             /* reconfigure the window(s) */
1299             ProcessNewConfiguration (pcd, 
1300 #ifndef CONFIG_RELATIVE_TO_CLIENT
1301                                      moveX,
1302                                      moveY,
1303 #else
1304                                      moveX + offsetX,
1305                                      moveY + offsetY,
1306 #endif
1307                                      (unsigned int) 
1308                                          (moveWidth - 2*offsetX),
1309                                      (unsigned int) 
1310                                          (moveHeight - offsetX - offsetY),
1311                                      FALSE);
1312         }
1313     }
1314 #ifdef WSM
1315     else if (wmGD.configAction == MARQUEE_SELECT)
1316     {
1317         WmScreenData *pSD;
1318
1319         UndoGrabs();
1320
1321         pSD = pcd ? pcd->pSD : ACTIVE_PSD;
1322
1323         dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END, 
1324                         marqueeX, marqueeY, marqueeWidth, marqueeHeight);
1325     }
1326 #endif /* WSM */
1327
1328     /*
1329      * Clear configuration flags and data.
1330      */
1331
1332     wmGD.configAction = NO_ACTION;
1333     wmGD.configPart = FRAME_NONE;
1334     wmGD.configSet = False;
1335     configGrab = FALSE;
1336     anyMotion = FALSE;
1337     wmGD.movingIcon = FALSE;
1338
1339 #ifdef WSM
1340     if (pcd)
1341     {
1342 #endif /* WSM */
1343     /* hide the move/resize config data */
1344     HideFeedbackWindow(pcd->pSD);
1345
1346     /*
1347      * Set the focus back to something reasonable
1348      */
1349     RepairFocus ();     
1350 #ifdef WSM
1351     }
1352 #endif /* WSM */
1353
1354 } /* END OF FUNCTION CompleteFrameConfig */
1355
1356 \f
1357 /*************************************<->*************************************
1358  *
1359  *  MoveOpaque (pcd, x, y, width, height)
1360  *
1361  *
1362  *  Description:
1363  *  -----------
1364  *  Move a window or icon on the root or icon box.
1365  *
1366  *
1367  *  Inputs:
1368  *  ------
1369  *  pcd         - client data pointer
1370  *  x           - x coordinate (on root)
1371  *  y           - y coordinate (on root)
1372  *  width       - pixel width of frame
1373  *  height      - pixel height of frame
1374  * 
1375  *  Outputs:
1376  *  -------
1377  *
1378  *
1379  *  Comments:
1380  *  --------
1381  *  o use MoveOutline() for icons in an icon box.
1382  *  
1383  *************************************<->***********************************/
1384 void MoveOpaque (ClientData *pcd, int x, int y,
1385                  unsigned int width, unsigned int height)
1386
1387
1388 {
1389     /* Check if moving icon */
1390     if (wmGD.movingIcon)
1391     {
1392         if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
1393         {
1394             /*
1395              * For now just fall back to move outline when the
1396              * icon is in the icon box
1397              */   
1398             
1399             MoveOutline (x, y, width, height);
1400         }
1401         else
1402         {
1403             XMoveWindow (DISPLAY,ICON_FRAME_WIN(pcd) , x, y);
1404         }
1405     }
1406     else
1407     {
1408         /* This is a window */
1409         XMoveWindow (DISPLAY, pcd->clientFrameWin, x, y);
1410         
1411     }
1412     
1413     /* cleanup exposed frame parts */
1414     PullExposureEvents ();
1415     
1416 } /* END OF FUNCTION MoveOpaque */
1417
1418
1419 \f
1420 /* thickness of outline */
1421 #define OUTLINE_WIDTH   2
1422
1423 /* number of points to draw outline once */
1424 #define SEGS_PER_DRAW   (4*OUTLINE_WIDTH)
1425
1426 /* number of points to flash outline (draw then erase) */
1427 #define SEGS_PER_FLASH  (2*SEGS_PER_DRAW)
1428
1429
1430 /*************************************<->*************************************
1431  *
1432  *  DrawSegments (dpy, win, gc, outline, nsegs)
1433  *
1434  *  Description:
1435  *  -----------
1436  *  Draw segments using either using normal X or using the ALLPLANES
1437  *  extension, depending on #ifdef ALLPLANES and whether the server actually
1438  *  supports the extension.  This is a thin wrapper around the Xlib
1439  *  XDrawSegments() call.
1440  *
1441  *  Inputs:
1442  *  ------
1443  *  dpy         - the X display
1444  *  win         - the window on which to draw
1445  *  gc          - the gc to use, typically whose function is GXxor
1446  *  outline     - array of segments
1447  *  nsegs       - number of segments in the outline array
1448  * 
1449  *  Outputs:
1450  *  -------
1451  *  (none)
1452  *
1453  *  Comments:
1454  *  --------
1455  *  Note: no GC is used when drawing with the ALLPLANES extension;
1456  *  therefore, the GC parameter is ignored in that case.
1457  * 
1458  *************************************<->***********************************/
1459
1460
1461 static void
1462 DrawSegments (Display *dpy, Window win, GC gc, XSegment *outline, int nsegs)
1463 {
1464 #if defined(sun) && defined(ALLPLANES)
1465         if (wmGD.allplanes)
1466             XAllPlanesDrawSegments(dpy, win, outline, nsegs);
1467         else
1468 #endif /* defined(sun) && defined(ALLPLANES) */
1469             XDrawSegments(dpy, win, gc, outline, nsegs);
1470 } /* END OF FUNCTION  DrawSegments */
1471
1472
1473 /*************************************<->*************************************
1474  *
1475  *  MoveOutline (x, y, width, height)
1476  *
1477  *
1478  *  Description:
1479  *  -----------
1480  *  Draw a window outline on the root window.
1481  *
1482  *
1483  *  Inputs:
1484  *  ------
1485  *  x           - x coordinate (on root)
1486  *  y           - y coordinate (on root)
1487  *  width       - pixel width of frame
1488  *  height      - pixel height of frame
1489  * 
1490  *  Outputs:
1491  *  -------
1492  *
1493  *
1494  *  Comments:
1495  *  --------
1496  *  o get display, root window ID, and xorGC out of global data.  
1497  * 
1498  *************************************<->***********************************/
1499 void MoveOutline (int x, int y, unsigned int width, unsigned int height)
1500 {
1501     if (wmGD.freezeOnConfig)
1502     {
1503         DrawOutline (x, y, width, height);
1504     }
1505     else
1506     {
1507 #ifdef WSM
1508       if (wmGD.useWindowOutline)
1509         WindowOutline(x,y,width,height);
1510       else
1511 #endif
1512         FlashOutline(x, y, width, height);
1513     }
1514 } /* END OF FUNCTION  MoveOutline */
1515
1516
1517 \f
1518 /*************************************<->*************************************
1519  *
1520  *  FlashOutline ()
1521  *
1522  *
1523  *  Description:
1524  *  -----------
1525  *  flash a window outline on the root window.
1526  *
1527  *
1528  *  Inputs:
1529  *  ------
1530  *  x           - x coordinate (on root)
1531  *  y           - y coordinate (on root)
1532  *  width       - pixel width of frame
1533  *  height      - pixel height of frame
1534  * 
1535  *  Outputs:
1536  *  -------
1537  *
1538  *
1539  *  Comments:
1540  *  --------
1541  *  o get display, root window ID, and xorGC out of global data.  
1542  *  o draw on root and erase "atomically"
1543  * 
1544  *************************************<->***********************************/
1545 void FlashOutline (int x, int y, unsigned int width, unsigned int height)
1546 {
1547     static XSegment  outline[SEGS_PER_FLASH];
1548
1549     /*
1550      * Do nothing if no box to draw 
1551      */
1552     if (x == 0 && y == 0 &&
1553         width == 0 && height == 0)
1554         return;
1555
1556     /*
1557      * Draw outline an even number of times (draw then erase)
1558      */
1559     SetOutline (outline, x, y, width, height, OUTLINE_WIDTH);
1560     memcpy ( (char *) &outline[SEGS_PER_DRAW], (char *) &outline[0], 
1561         SEGS_PER_DRAW*sizeof(XSegment));
1562
1563     /*
1564      * Flash the outline at least once, then as long as there's 
1565      * nothing else going on
1566      */
1567     DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1568                         outline, SEGS_PER_FLASH);
1569     XSync(DISPLAY, FALSE);
1570
1571     while (!XtAppPending(wmGD.mwmAppContext)) {
1572         DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC, 
1573                         outline, SEGS_PER_FLASH);
1574         XSync(DISPLAY, FALSE);
1575     }
1576 } /* END OF FUNCTION  FlashOutline */
1577
1578 #ifdef WSM
1579 \f
1580 /*************************************<->*************************************
1581  *
1582  *  CreateOutlineWindows (pSD)
1583  *
1584  *
1585  *  Description:
1586  *  -----------
1587  *  create the outline windows
1588  *
1589  *
1590  *  Inputs:
1591  *  ------
1592  * 
1593  *  Outputs:
1594  *  -------
1595  *
1596  *  Comments:
1597  *  --------
1598  *  variables are affected:
1599  *      woN
1600  *      woS
1601  *      woE
1602  *      woW
1603  * 
1604  *************************************<->***********************************/
1605 static void 
1606 CreateOutlineWindows (WmScreenData *pSD)
1607 {
1608     XSetWindowAttributes xswa;
1609     unsigned int xswamask;
1610     int x, y, width, height;
1611
1612
1613     x = -10;
1614     y = -10;
1615     width = OUTLINE_WIDTH;
1616     height = OUTLINE_WIDTH;
1617
1618     xswa.override_redirect = True;    
1619     xswa.backing_store = NotUseful;
1620     xswa.save_under = True;
1621     xswa.background_pixmap = XmGetPixmap(
1622                                 XtScreen(pSD->screenTopLevelW),
1623                                 "50_foreground", 
1624                                 pSD->clientAppearance.foreground,
1625                                 pSD->clientAppearance.background);
1626
1627     xswamask = (CWOverrideRedirect | 
1628                 CWBackingStore | 
1629                 CWBackPixmap |
1630                 CWSaveUnder);
1631     
1632     pSD->woN = XCreateWindow(DISPLAY, pSD->rootWindow, 
1633                        x, y, width, height,
1634                        0, 
1635                        XDefaultDepth(DISPLAY,pSD->screen), 
1636                        CopyFromParent,
1637                        CopyFromParent, 
1638                        xswamask, 
1639                        &xswa);
1640
1641     pSD->woS = XCreateWindow(DISPLAY, pSD->rootWindow, 
1642                        x, y, width, height,
1643                        0, 
1644                        XDefaultDepth(DISPLAY,pSD->screen), 
1645                        CopyFromParent,
1646                        CopyFromParent, 
1647                        xswamask, 
1648                        &xswa);
1649
1650     pSD->woE = XCreateWindow(DISPLAY, pSD->rootWindow, 
1651                        x, y, width, height,
1652                        0, 
1653                        XDefaultDepth(DISPLAY,pSD->screen), 
1654                        CopyFromParent,
1655                        CopyFromParent, 
1656                        xswamask, 
1657                        &xswa);
1658
1659     pSD->woW = XCreateWindow(DISPLAY, pSD->rootWindow, 
1660                        x, y, width, height,
1661                        0, 
1662                        XDefaultDepth(DISPLAY,pSD->screen), 
1663                        CopyFromParent,
1664                        CopyFromParent, 
1665                        xswamask, 
1666                        &xswa);
1667
1668 } /* END OF FUNCTION  CreateOutlineWindows */
1669
1670 \f
1671 /*************************************<->*************************************
1672  *
1673  *  WindowOutline ()
1674  *
1675  *
1676  *  Description:
1677  *  -----------
1678  *  show an outline on the root window using windows.
1679  *
1680  *
1681  *  Inputs:
1682  *  ------
1683  *  x           - x coordinate (on root)
1684  *  y           - y coordinate (on root)
1685  *  width       - pixel width of frame
1686  *  height      - pixel height of frame
1687  * 
1688  *  Outputs:
1689  *  -------
1690  *
1691  *
1692  *  Comments:
1693  *  --------
1694  *  Always unmap during move/resize of outline windows to let saveunder
1695  *  stuff work. HP server's toss saveunder stuff for windows that
1696  *  configure themselves while mapped.
1697  * 
1698  *************************************<->***********************************/
1699 void WindowOutline (int x, int y, unsigned int width, unsigned int height)
1700 {
1701     static int  lastOutlineX = 0;
1702     static int  lastOutlineY = 0;
1703     static int  lastOutlineWidth = 0;
1704     static int  lastOutlineHeight = 0;
1705     WmScreenData *pSD = ACTIVE_PSD;
1706     int iX, iY;
1707     int iW, iH;
1708
1709     if (pSD->woN == (Window)0L)
1710     {
1711         CreateOutlineWindows(pSD);
1712     }
1713
1714     if (x == lastOutlineX && y == lastOutlineY && 
1715         width == lastOutlineWidth && height == lastOutlineHeight)
1716     {
1717         return;         /* no change */
1718     }
1719
1720     XUnmapWindow(DISPLAY, pSD->woN);
1721     XUnmapWindow(DISPLAY, pSD->woS);
1722     XUnmapWindow(DISPLAY, pSD->woE);
1723     XUnmapWindow(DISPLAY, pSD->woW);
1724
1725     if ((width == 0) && (height == 0))
1726     {
1727         lastOutlineWidth = lastOutlineHeight = 0;
1728         lastOutlineX = lastOutlineY = 0;
1729     }
1730     else
1731     {
1732         /* North */
1733         iX = x;
1734         iY = y;
1735         iW = (int) width;
1736         iH = OUTLINE_WIDTH;
1737         if (iW < 0) iW = 1;
1738         XMoveResizeWindow (DISPLAY, pSD->woN, iX, iY, iW, iH);
1739
1740         /* West */
1741         iX = x;
1742         iY = y + OUTLINE_WIDTH;
1743         iW = OUTLINE_WIDTH;
1744         iH = (int) height - OUTLINE_WIDTH;
1745         if (iH < 0) iH = 1;
1746         XMoveResizeWindow (DISPLAY, pSD->woW, iX, iY, iW, iH);
1747
1748         /* East */
1749         iX = x + (int)width - OUTLINE_WIDTH;
1750         iY = y + OUTLINE_WIDTH;
1751         iW = OUTLINE_WIDTH;
1752         iH = (int)height - OUTLINE_WIDTH;
1753         if (iH < 0) iH = 1;
1754         XMoveResizeWindow (DISPLAY, pSD->woE, iX, iY, iW, iH);
1755
1756         /* South */
1757         iX = x + OUTLINE_WIDTH;
1758         iY = y + (int)height - OUTLINE_WIDTH;
1759         iW = (int)width - 2*OUTLINE_WIDTH;
1760         iH = OUTLINE_WIDTH;
1761         if (iW < 0) iW = 1;
1762         XMoveResizeWindow (DISPLAY, pSD->woS, iX, iY, iW, iH);
1763
1764         lastOutlineX = x;
1765         lastOutlineY = y;
1766         lastOutlineWidth = width;
1767         lastOutlineHeight = height;
1768
1769         XMapRaised (DISPLAY, pSD->woN);
1770         XMapRaised (DISPLAY, pSD->woS);
1771         XMapRaised (DISPLAY, pSD->woE);
1772         XMapRaised (DISPLAY, pSD->woW);
1773
1774         /* cleanup exposed frame parts */
1775         PullExposureEvents ();
1776     }
1777
1778 } /* END OF FUNCTION  WindowOutline */
1779
1780 #endif /* WSM */
1781
1782 \f
1783 /*************************************<->*************************************
1784  *
1785  *  DrawOutline (x, y, width, height)
1786  *
1787  *
1788  *  Description:
1789  *  -----------
1790  *  Draw a window outline on the root window.
1791  *
1792  *
1793  *  Inputs:
1794  *  ------
1795  *  x           - x coordinate (on root)
1796  *  y           - y coordinate (on root)
1797  *  width       - pixel width of frame
1798  *  height      - pixel height of frame
1799  * 
1800  *  Outputs:
1801  *  -------
1802  *
1803  *
1804  *  Comments:
1805  *  --------
1806  *  o get display, root window ID, and xorGC out of global data.  
1807  * 
1808  *************************************<->***********************************/
1809 void DrawOutline (int x, int y, unsigned int width, unsigned int height)
1810 {
1811     static int  lastOutlineX = 0;
1812     static int  lastOutlineY = 0;
1813     static int  lastOutlineWidth = 0;
1814     static int  lastOutlineHeight = 0;
1815     XSegment  outline[SEGS_PER_DRAW];
1816
1817
1818     if (x == lastOutlineX && y == lastOutlineY && 
1819         width == lastOutlineWidth && height == lastOutlineHeight)
1820     {
1821         return;         /* no change */
1822     }
1823
1824     if (lastOutlineWidth || lastOutlineHeight) {
1825         SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
1826             lastOutlineHeight, OUTLINE_WIDTH);
1827
1828         DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC, 
1829                         outline, SEGS_PER_DRAW);
1830     }
1831
1832     lastOutlineX = x;
1833     lastOutlineY = y;
1834     lastOutlineWidth = width;
1835     lastOutlineHeight = height;
1836
1837     if (lastOutlineWidth || lastOutlineHeight) {
1838
1839         SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
1840             lastOutlineHeight, OUTLINE_WIDTH);
1841
1842         DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC, 
1843                         outline, SEGS_PER_DRAW);
1844     }
1845 } /* END OF FUNCTION  DrawOutline */
1846
1847
1848 \f
1849 /*************************************<->*************************************
1850  *
1851  *  WindowIsOnScreen (pCD, dx, dy)
1852  *
1853  *
1854  *  Description:
1855  *  -----------
1856  *  This function is used to check if a window is atleast partially on the
1857  *  screen or not.  If the window is completely off the screen, dx and dy
1858  *  will contain the minimum distance to move some part of the window's frame
1859  *  back onto the screen.
1860  *
1861  *
1862  *  Inputs:
1863  *  ------
1864  *  pCD         - pointer to client data
1865  *
1866  * 
1867  *  Outputs:
1868  *  -------
1869  *  dx          - minimum x distance to move the window back to the screen
1870  *  dy          - minimum y distance to move the window back to the screen
1871  *
1872  *
1873  *  Returns:
1874  *  --------
1875  *  true        - if the window has some part on the screen
1876  *  false       - if the window is completely off the screen
1877  *
1878  *  Comments:
1879  *  --------
1880  * 
1881  *************************************<->***********************************/
1882
1883 Boolean WindowIsOnScreen (ClientData *pCD, int *dx, int *dy)
1884 {
1885   int x1 = pCD->clientX;
1886   int x2 = pCD->clientX + pCD->clientWidth;
1887   int y1 = pCD->clientY;
1888   int y2 = pCD->clientY + pCD->clientHeight;
1889   int screenW = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
1890   int screenH = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pCD));
1891
1892   *dx = *dy = 0;
1893   
1894   if (x2 < 0)                   /* right frame border off left side of screen. */
1895     *dx =  -x2;
1896   else if (x1 > screenW)        /* left frame border off right side of screen. */
1897     *dx = screenW - x1;
1898   
1899   if (y2 < 0)                   /* bottom frame border off top of screen. */
1900     *dy = -y2;
1901   else if (y1 > screenH)        /* top frame border off bottom of screen. */
1902     *dy = screenH - y1;
1903   
1904   return ((*dx == 0) && (*dy == 0));
1905 }
1906
1907
1908 \f
1909 /*************************************<->*************************************
1910  *
1911  *  ProcessNewConfiguration (pCD, x, y, width, height, clientRequest)
1912  *
1913  *
1914  *  Description:
1915  *  -----------
1916  *  This function is used to configure a client window following receipt of
1917  *  a client request or an interactive configuration action.
1918  *
1919  *
1920  *  Inputs:
1921  *  ------
1922  *  pCD         - pointer to client data
1923  *  x           - x coord of client window
1924  *  y           - y coord of client window
1925  *  width       - width of client window
1926  *  height      - height of client window
1927  *  clientRequest       - true if configuration requested by client program
1928  *
1929  * 
1930  *  Outputs:
1931  *  -------
1932  *
1933  *
1934  *  Comments:
1935  *  --------
1936  * 
1937  *************************************<->***********************************/
1938
1939 void ProcessNewConfiguration (ClientData *pCD, int x, int y, unsigned int width, unsigned int height, Boolean clientRequest)
1940 {
1941     unsigned int changedValues = 0;
1942     int          xoff = 0, yoff = 0;
1943     int          dx, dy;
1944     Boolean      originallyOnScreen = WindowIsOnScreen(pCD, &dx, &dy);
1945     Boolean newMax = False;
1946     Boolean toNewMax = False;
1947
1948     /*
1949      * Fix the configuration values to be compatible with the configuration
1950      * constraints for this class of windows.
1951      */
1952
1953     
1954
1955     FixWindowConfiguration (pCD, &width, &height,
1956                                  (unsigned int) pCD->widthInc, 
1957                                  (unsigned int) pCD->heightInc);
1958
1959     if ((pCD->maxWidth != pCD->oldMaxWidth) ||
1960          (pCD->maxHeight != pCD->oldMaxHeight))
1961     {
1962         /*
1963          * We've got a new maximum size.
1964          */
1965         newMax = True;
1966     }
1967
1968     /*
1969      * If the configuration has changed, update client data
1970      * 
1971      * Changes in width or height cause maximized windows to return to
1972      * normal state and update normal geometry (x, y, width, height)
1973      */
1974     if (pCD->maxConfig) 
1975     {
1976         if (newMax &&
1977             (pCD->maxWidth == width) &&
1978             (pCD->maxHeight == height))
1979         {
1980             /* we're changing to the new max size */
1981             toNewMax = True;
1982         }
1983
1984         changedValues |= (width != pCD->oldMaxWidth) ? CWWidth : 0;
1985         changedValues |= (height != pCD->oldMaxHeight) ? CWHeight : 0;
1986
1987         if (!toNewMax && (changedValues & CWWidth)) {
1988             /*
1989              * Hacked to update maxWidth for 'vertical' max clients
1990              */
1991             if (IS_MAXIMIZE_VERTICAL(pCD)) {
1992                 pCD->maxWidth = width;
1993             }
1994             pCD->clientWidth = width;
1995             if (changedValues & CWHeight) {
1996                 /*
1997                  * Hacked to update maxHeight for 'horizontal' max client
1998                  */
1999                 if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
2000                     pCD->maxHeight = height;
2001                 }
2002                 pCD->clientHeight = height;
2003             }
2004             else {
2005                 pCD->clientHeight = pCD->oldMaxHeight;
2006             }
2007         }
2008         else if (!toNewMax && (changedValues & CWHeight)) {
2009             /*
2010              * Hacked to update maxHeight for 'horizontal' max client
2011              */
2012             if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
2013                 pCD->maxHeight = height;
2014             }
2015             pCD->clientHeight = height;
2016             pCD->clientWidth = pCD->oldMaxWidth;
2017         }
2018     }
2019     else {
2020         if (width != pCD->clientWidth)
2021         {
2022             /*
2023              * Hacked to update maxWidth for 'vertical' max clients
2024              */
2025             if (IS_MAXIMIZE_VERTICAL(pCD)) {
2026                 pCD->maxWidth = width;
2027             }
2028
2029             changedValues |= CWWidth;
2030             pCD->clientWidth = width;
2031
2032         }
2033
2034         if (height != pCD->clientHeight)
2035         {
2036             /*
2037              * Hacked to update maxHeight for 'horizontal' max client
2038              */
2039             if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
2040                 pCD->maxHeight = height;
2041             }
2042
2043             changedValues |= CWHeight;
2044             pCD->clientHeight = height;
2045         }
2046     }
2047
2048 #ifndef CONFIG_RELATIVE_TO_CLIENT
2049     /*
2050      * If positionIsFrame or user initiated configuration request,
2051      * then adjust client position to by frame_width and frame_height.
2052      */
2053     if (wmGD.positionIsFrame || (!clientRequest))
2054     {
2055         xoff = pCD->clientOffset.x;
2056         yoff = pCD->clientOffset.y;
2057     }
2058 #endif
2059
2060     /*
2061      * Changes in position update maximum geometry on maximized windows
2062      * if there was no change in size.
2063      */
2064     if (pCD->maxConfig) {
2065         if (x != pCD->maxX) {
2066             changedValues |= CWX;
2067             if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2068                 pCD->clientX = x + xoff;
2069             else
2070                 pCD->maxX = x + xoff;
2071         }
2072         else if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2073         {
2074             pCD->clientX = pCD->maxX;
2075         }
2076
2077         if (y != pCD->maxY) {
2078             changedValues |= CWY;
2079             if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2080                 pCD->clientY = y + yoff;
2081             else
2082                 pCD->maxY = y + yoff;
2083         }
2084         else if (!toNewMax && (changedValues & (CWWidth | CWHeight))) 
2085         {
2086             pCD->clientY = pCD->maxY;
2087         }
2088     }
2089     else {
2090         if (x + xoff != pCD->clientX) {
2091             changedValues |= CWX;
2092             pCD->clientX = x + xoff;
2093         }
2094
2095         if (y + yoff != pCD->clientY) {
2096             changedValues |= CWY;
2097             pCD->clientY = y + yoff;
2098         }
2099     }
2100
2101     /* check if the window has reconfigured itself off the screen. */
2102     if (originallyOnScreen && !WindowIsOnScreen(pCD, &dx, &dy))
2103       {
2104         if (dx != 0)
2105           {
2106             changedValues |= CWX;
2107             pCD->clientX += dx;
2108           }
2109
2110         if (dy != 0)
2111           {
2112             changedValues |= CWY;
2113             pCD->clientY += dy;
2114           }
2115       }
2116
2117
2118     /*
2119      * Resize the client window if necessary:
2120      */
2121
2122     if (changedValues & (CWWidth | CWHeight))
2123     {
2124         if (pCD->maxConfig) 
2125         {
2126             if (!toNewMax)
2127             {
2128                 /* maximized window resized, return to normal state */
2129                 pCD->maxConfig = FALSE;
2130                 pCD->clientState = NORMAL_STATE;
2131             }
2132         }
2133
2134         XResizeWindow (DISPLAY, pCD->client, width, height);
2135         RegenerateClientFrame(pCD);
2136     }
2137     if (changedValues & (CWX | CWY)) {
2138         if (pCD->maxConfig)
2139         {
2140           /*
2141            * Fix for 5217 - If the request is from the client, use the clients
2142            *                offsets instead of the static offsets
2143            */
2144           if (clientRequest)
2145             {
2146               XMoveWindow (DISPLAY, pCD->clientFrameWin,
2147                            pCD->maxX - pCD->clientOffset.x,
2148                            pCD->maxY - pCD->clientOffset.y);
2149             }
2150           else
2151             {
2152               XMoveWindow (DISPLAY, pCD->clientFrameWin, 
2153                            pCD->maxX - offsetX,
2154                            pCD->maxY - offsetY);
2155             }
2156           /* End fix 5217 */
2157         }
2158         else 
2159         {
2160             if (clientRequest)
2161             {
2162                 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2163                              pCD->clientX - pCD->clientOffset.x,
2164                              pCD->clientY - pCD->clientOffset.y);
2165             }
2166             else
2167             {
2168                 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2169                              pCD->clientX - offsetX,
2170                              pCD->clientY - offsetY);
2171             }
2172         }
2173         SetFrameInfo (pCD);
2174 #ifdef PANELIST
2175         if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
2176         {
2177             /* turn off subpanel behavior if moved */
2178             pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUBPANEL;
2179         }
2180 #endif /* PANELIST */
2181     }
2182
2183     /*
2184      * Send a configure notify  message if appropriate:
2185      *   1. rejected client configuration request.
2186      *   2. client request and move without resize 
2187      */
2188
2189
2190     if ((!changedValues && clientRequest) ||
2191         (changedValues && !(changedValues & (CWWidth | CWHeight))))
2192     {
2193         SendConfigureNotify (pCD);
2194     }
2195
2196     /*
2197      * Try to send notice directly to icon box that the window
2198      * has changed size
2199      */
2200
2201     if ((pCD->clientFlags & ICON_BOX) && 
2202         (changedValues & (CWWidth | CWHeight)))
2203     {
2204         CheckIconBoxResize(pCD, changedValues, width, height);
2205     }
2206
2207 } /* END OF FUNCTION ProcessNewConfiguration */
2208
2209
2210 \f
2211 /*************************************<->*************************************
2212  *
2213  *  StartResizeConfig (pcd, pev)
2214  *
2215  *
2216  *  Description:
2217  *  -----------
2218  *  Start resize of client window 
2219  *
2220  *
2221  *  Inputs:
2222  *  ------
2223  *  pcd         - pointer to client data
2224  *  pev         - pointer to event
2225  * 
2226  *  Outputs:
2227  *  -------
2228  *  return      - true if configuration can begin, else false
2229  *
2230  *
2231  *  Comments:
2232  *  --------
2233  * 
2234  *************************************<->***********************************/
2235
2236 Boolean StartResizeConfig (ClientData *pcd, XEvent *pev)
2237 {
2238     Window grab_win, junk_win;
2239     Boolean grabbed;
2240     int big_inc, tmp_inc;
2241     int junk, junkX, junkY;
2242
2243     /*
2244      *  Do our grabs 
2245      */
2246     if (!configGrab)
2247     {
2248         grab_win = GrabWin (pcd, pev);
2249
2250         if (pev)
2251         {
2252             grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart), 
2253                         PGRAB_MASK, pev->xbutton.time, pcd, True);
2254         }
2255         else
2256         {
2257             grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart), 
2258                         PGRAB_MASK, CurrentTime, pcd, True);
2259         }
2260         if (!grabbed)
2261         {
2262             return (False);
2263         }
2264         configGrab = TRUE;
2265     }
2266     else
2267     {
2268         /* continue with the configuration in progress (!!!) */
2269         return (True);
2270     }
2271
2272     /* 
2273      * Set up static variables for succeeding events 
2274      */
2275     if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
2276                    &pointerX, &pointerY, &junk, &junk, (unsigned int *)&junk))
2277     {
2278         CancelFrameConfig (pcd);        /* release grabs */
2279         return (False);
2280     };
2281     wmGD.preMoveX = pointerX;
2282     wmGD.preMoveY = pointerY;
2283     anyMotion = FALSE;
2284
2285     offsetX = pcd->clientOffset.x;
2286     offsetY = pcd->clientOffset.y;
2287
2288     /* 
2289      * get window geometry information and convert to frame coordinates
2290      */
2291     if (pcd->maxConfig) {
2292         resizeX = pcd->maxX;
2293         resizeY = pcd->maxY;
2294         resizeWidth = pcd->maxWidth;
2295         resizeHeight = pcd->maxHeight;
2296     }
2297     else {
2298         resizeX = pcd->clientX;
2299         resizeY = pcd->clientY;
2300         resizeWidth = pcd->clientWidth;
2301         resizeHeight = pcd->clientHeight;
2302     }
2303     ClientToFrame(pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
2304
2305     /* save start values to see where we came from */
2306     startX = resizeX;
2307     startY = resizeY;
2308     startWidth = resizeWidth;
2309     startHeight = resizeHeight;
2310
2311     /* get min and max frame sizes */
2312     minWidth = pcd->minWidth;
2313     minHeight = pcd->minHeight;
2314     junkX = junkY = 0;
2315     ClientToFrame(pcd, &junkX, &junkY, &minWidth, &minHeight);
2316
2317     /*
2318      * Hack to use maxHeightLimit and maxWidthLimit as the real max when
2319      * maximumClientSize is set to 'horizontal' or 'vertical', since
2320      * pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
2321      */
2322     maxWidth = pcd->maxWidthLimit;
2323     maxHeight = pcd->maxHeightLimit;
2324     junkX = junkY = 0;
2325     ClientToFrame(pcd, &junkX, &junkY, &maxWidth, &maxHeight);
2326
2327     /* compute big increment values */
2328     big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
2329
2330     tmp_inc = big_inc - big_inc%pcd->widthInc;
2331     if (tmp_inc > 5*pcd->widthInc)
2332         resizeBigWidthInc = tmp_inc;
2333     else 
2334         resizeBigWidthInc = 5*pcd->widthInc;
2335
2336     tmp_inc = big_inc - big_inc%pcd->heightInc;
2337     if (tmp_inc > 5*pcd->heightInc)
2338         resizeBigHeightInc = tmp_inc;
2339     else 
2340         resizeBigHeightInc = 5*pcd->heightInc;
2341
2342     /* pop up feedback window */
2343     if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
2344     {
2345         DoFeedback (pcd, resizeX, resizeY, resizeWidth, resizeHeight, 
2346                     FB_SIZE, TRUE /* do size checks */);
2347     }
2348
2349     /* set configuring data */
2350     wmGD.configAction = RESIZE_CLIENT;
2351     wmGD.configButton = pev ? pev->xbutton.button: 0;
2352
2353     return (True);
2354
2355 } /* END OF FUNCTION StartResizeConfig */
2356
2357
2358 \f
2359 /*************************************<->*************************************
2360  *
2361  *  StartClientResize (pcd, pev)
2362  *
2363  *
2364  *  Description:
2365  *  -----------
2366  *  Start resize of client window as invoked from menu
2367  *
2368  *
2369  *  Inputs:
2370  *  ------
2371  *  pcd         - pointer to client data
2372  *  pev         - pointer to event
2373  * 
2374  *  Outputs:
2375  *  -------
2376  *
2377  *
2378  *  Comments:
2379  *  --------
2380  *  o This should only be called as the result of a Resize function 
2381  *    being selected from the system menu.
2382  * 
2383  *************************************<->***********************************/
2384 void StartClientResize (ClientData *pcd, XEvent *pev)
2385 {
2386
2387     /* do initial setup for resize */
2388     wmGD.configPart = FRAME_NONE;       /* determined by later action */
2389     wmGD.configSet = False;             /* don't know what it is yet */
2390     if (!StartResizeConfig (pcd, pev))
2391     {
2392         /* resize could not be initiated */
2393         return;
2394     }
2395
2396
2397     /*
2398      *  Warp pointer to middle of window if started from the keyboard
2399      *  or menu (no event).
2400      */
2401     if ( !pev || pev->type == KeyPress )
2402     {
2403         pointerX = resizeX + resizeWidth/2;
2404         pointerY = resizeY + resizeHeight/2;
2405
2406         ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &pointerX, &pointerY);
2407         if (wmGD.enableWarp)
2408         {
2409             XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd), 
2410                      0, 0, 0, 0, pointerX, pointerY);
2411         }
2412     }
2413
2414 } /* END OF FUNCTION StartClientResize  */
2415
2416 \f
2417 /*************************************<->*************************************
2418  *
2419  *  StartClientMove (pcd, pev)
2420  *
2421  *
2422  *  Description:
2423  *  -----------
2424  *  Handle move of client window as invoked from menu
2425  *
2426  *
2427  *  Inputs:
2428  *  ------
2429  *  pcd         - pointer to client data
2430  *  pev         - pointer to event
2431  * 
2432  *  Outputs:
2433  *  -------
2434  *  Return      - True if configuration was initiated, else False
2435  *
2436  *
2437  *  Comments:
2438  *  --------
2439  *  o This should only be called as the result of a Move function 
2440  *    being selected from the system menu.
2441  * 
2442  *************************************<->***********************************/
2443 Boolean StartClientMove (ClientData *pcd, XEvent *pev)
2444 {
2445     Window grab_win, junk_win;
2446     Boolean grabbed;
2447     int junk;
2448     Window child;
2449
2450     /*
2451      *  Do our grabs if we're just starting out
2452      */
2453     if (!configGrab)
2454     {
2455         grab_win = GrabWin (pcd, pev);
2456         if (grab_win == ICON_FRAME_WIN(pcd))
2457         {
2458             wmGD.movingIcon = True;
2459         }
2460
2461         if (pev)
2462         {
2463             grabbed = DoGrabs (grab_win, wmGD.configCursor, 
2464                         PGRAB_MASK, pev->xbutton.time, pcd, False);
2465         }
2466         else
2467         {
2468             grabbed = DoGrabs (grab_win, wmGD.configCursor, 
2469                         PGRAB_MASK, CurrentTime, pcd, False);
2470         }
2471         if (!grabbed)
2472         {
2473             wmGD.movingIcon = False;
2474             return (False);
2475         }
2476         configGrab = TRUE;
2477     }
2478
2479     /* 
2480      * Set up static variables for succeeding events if we're not 
2481      * entering with a motion event. If we are, we assume that the
2482      * preMove variables have been setup.
2483      */
2484     if (pev && ((pev->type == ButtonPress) || (pev->type == ButtonRelease)))
2485     {
2486         wmGD.preMoveX = pev->xbutton.x_root;
2487         wmGD.preMoveY = pev->xbutton.y_root;
2488     }
2489     else if ((pev && (pev->type != MotionNotify)) || !pev)
2490     {
2491         if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), 
2492                    &junk_win, &junk_win,
2493                    &(wmGD.preMoveX), &(wmGD.preMoveY),
2494                    &junk, &junk, (unsigned int *)&junk))
2495         {
2496             CancelFrameConfig (pcd);
2497             return (False);
2498         }
2499     }
2500
2501     offsetX = pcd->clientOffset.x;
2502     offsetY = pcd->clientOffset.y;
2503
2504     anyMotion = FALSE;
2505     moveLastPointerX = wmGD.preMoveX;
2506     moveLastPointerY = wmGD.preMoveY;
2507
2508     /* get frame window geometry */
2509     if (wmGD.movingIcon)
2510     {
2511         moveWidth = ICON_WIDTH(pcd);
2512         moveHeight = ICON_HEIGHT(pcd);
2513
2514         moveX = ICON_X(pcd);
2515         moveY = ICON_Y(pcd);
2516
2517         if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
2518         {
2519             /* get root coords of icon box bulletin board */
2520             XTranslateCoordinates(DISPLAY, 
2521                 XtWindow(P_ICON_BOX(pcd)->bBoardWidget), ROOT_FOR_CLIENT(pcd), 
2522                 0, 0, &moveIBbbX, &moveIBbbY, &child);
2523
2524             moveX += moveIBbbX;
2525             moveY += moveIBbbY;
2526         }
2527         else if (pcd->pSD->moveOpaque &&
2528                  (ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
2529                  (wmGD.keyboardFocus == pcd))
2530         {
2531             HideActiveIconText ((WmScreenData *)NULL);
2532         }
2533     }
2534     else 
2535     {
2536         if (pcd->maxConfig) {   /* maximized */
2537             moveWidth = pcd->maxWidth;
2538             moveHeight = pcd->maxHeight;
2539             moveX = pcd->maxX;
2540             moveY = pcd->maxY;
2541         }
2542         else {                  /* normal */
2543             moveWidth = pcd->clientWidth;
2544             moveHeight = pcd->clientHeight;
2545             moveX = pcd->clientX;
2546             moveY = pcd->clientY;
2547         }
2548         ClientToFrame (pcd, &moveX, &moveY, &moveWidth, &moveHeight);
2549     }
2550
2551     if (pcd->pSD->moveOpaque)
2552     {
2553         opaqueMoveX = moveX;
2554         opaqueMoveY = moveY;
2555     }
2556
2557     /*
2558      *  Warp pointer to middle of window if started from the menu (no event).
2559      */
2560     if ( !pev || pev->type == KeyPress )
2561     {
2562         moveLastPointerX = moveX + moveWidth/2;
2563         moveLastPointerY = moveY + moveHeight/2;
2564
2565         ForceOnScreen (SCREEN_FOR_CLIENT(pcd), 
2566                        &moveLastPointerX, &moveLastPointerY);
2567         if (wmGD.enableWarp)
2568         {
2569             XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd), 0, 0, 0, 0, 
2570                 moveLastPointerX, moveLastPointerY);
2571         }
2572     }
2573
2574     /* pop up feedback window */
2575     if ( !wmGD.movingIcon && (wmGD.showFeedback & WM_SHOW_FB_MOVE))
2576     {
2577         DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight, 
2578                     FB_POSITION, FALSE /* no size checks */);
2579     }
2580     
2581     /* set configuring data */
2582     wmGD.configAction = MOVE_CLIENT;
2583     if (pev && pev->type != KeyPress)
2584         wmGD.configButton = pev->xbutton.button;
2585     else 
2586         wmGD.configButton = 0;
2587
2588
2589     return (True);
2590
2591
2592 } /* END OF FUNCTION StartClientMove */
2593
2594
2595 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2596 /*************************************<->*************************************
2597  *
2598  *  SetGrabServer ()
2599  *
2600  *
2601  *  Description:
2602  *  -----------
2603  *  Sets Boolean grabServer to False
2604  *
2605  *  Inputs:
2606  *  ------
2607  *  None
2608  *  
2609  *  Outputs:
2610  *  -------
2611  *  None
2612  *  
2613  *  Comments
2614  *  -------
2615  *  This will only get called when an automated test is running. The
2616  *  purpose of this is to prevent mwm from grbbing the server, since
2617  *  this confuses the automation input synthesis code
2618  *  
2619  *************************************<->***********************************/
2620 void SetGrabServer (void)
2621 {
2622     grabServer = FALSE;
2623 }
2624 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2625
2626 \f
2627 /*************************************<->*************************************
2628  *
2629  *  DoGrabs (grab_win, cursor, pmask, grabTime, alwaysGrab)
2630  *
2631  *
2632  *  Description:
2633  *  -----------
2634  *  Do the grabs for window configuration
2635  *
2636  *
2637  *  Inputs:
2638  *  ------
2639  *  grab_win    - window to grab on
2640  *  cursor      - cursor shape to attach to the pointer
2641  *  pmask       -
2642  *  grabTime    - time stamp
2643  *  alwaysGrab  - 
2644  *
2645  * 
2646  *  Outputs:
2647  *  -------
2648  *
2649  *  Comments:
2650  *  --------
2651  * 
2652  *************************************<->***********************************/
2653 Boolean DoGrabs (Window grab_win, Cursor cursor, unsigned int pmask, Time grabTime, ClientData *pCD, Boolean alwaysGrab)
2654 {
2655
2656 #ifdef WSM
2657     Window root;
2658
2659     if (pCD)
2660         root = ROOT_FOR_CLIENT(pCD);
2661     else
2662         root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
2663
2664     if (pCD && pCD->pSD->useIconBox && wmGD.movingIcon && P_ICON_BOX(pCD))
2665 #else
2666     if (pCD->pSD->useIconBox && wmGD.movingIcon && P_ICON_BOX(pCD))
2667 #endif
2668     {
2669         /*
2670          * Confine the pointer to the icon box clip window
2671          */
2672         if (XGrabPointer(DISPLAY, 
2673                          grab_win,
2674                          FALSE,                 /* owner_events */
2675                          pmask,
2676                          GrabModeAsync,         /* pointer_mode */
2677                          GrabModeAsync,         /* keyboard_mode */
2678                                                 /* confine_to window */
2679                          XtWindow(P_ICON_BOX(pCD)->clipWidget),
2680                          cursor,
2681                          grabTime) != GrabSuccess)
2682         {       
2683             return(FALSE);
2684         }
2685     }
2686     else
2687     {
2688         /*
2689          * Just confine the pointer to the root window
2690          */
2691         if (XGrabPointer(DISPLAY, 
2692                          grab_win,
2693                          FALSE,                 /* owner_events */
2694                          pmask,
2695                          GrabModeAsync,         /* pointer_mode */
2696                          GrabModeAsync,         /* keyboard_mode */
2697 #ifdef WSM
2698                          root,
2699 #else
2700                          ROOT_FOR_CLIENT(pCD),          /* confine_to window */
2701 #endif
2702                          cursor,
2703                          grabTime) != GrabSuccess)
2704         {
2705             return(FALSE);
2706         }
2707     }
2708
2709     /*
2710      * Don't grab keyboard away from menu widget to prevent 
2711      * hosing of traversal.
2712      */
2713     if (!wmGD.menuActive) 
2714     {
2715         if ((XGrabKeyboard(DISPLAY, 
2716                            grab_win,
2717                            FALSE,                       /* owner_events */
2718                            GrabModeAsync,               /* pointer_mode */
2719                            GrabModeAsync,               /* keyboard_mode */
2720                            grabTime)) != GrabSuccess)
2721         {
2722             XUngrabPointer (DISPLAY, CurrentTime);
2723             return(FALSE);
2724         }
2725     }
2726     
2727     
2728         /* 
2729          * If running automation version of mwm, do not grab the server, since
2730          * this will confuse the automation input synthesis code.
2731          */
2732 # if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2733 if (grabServer == TRUE)
2734 # endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2735
2736     if (wmGD.freezeOnConfig) 
2737         
2738     {
2739 #ifdef WSM
2740         if (!pCD || ((pCD->pSD->moveOpaque && alwaysGrab) ||
2741                    (!(pCD->pSD->moveOpaque))))
2742 #else /* WSM */
2743         if ((pCD->pSD->moveOpaque && alwaysGrab) ||
2744             (!(pCD->pSD->moveOpaque)))
2745 #endif /* WSM */
2746         {
2747             XGrabServer(DISPLAY);
2748         }
2749     }
2750     
2751     return(TRUE);
2752 } /* END OF FUNCTION DoGrabs   */
2753
2754 \f
2755 /*************************************<->*************************************
2756  *
2757  *  UndoGrabs ()
2758  *
2759  *
2760  *  Description:
2761  *  -----------
2762  *  Release the grabs
2763  *
2764  *
2765  *  Inputs:
2766  *  ------
2767  *
2768  * 
2769  *  Outputs:
2770  *  -------
2771  *
2772  *  Comments:
2773  *  --------
2774  * 
2775  *************************************<->***********************************/
2776 void UndoGrabs (void)
2777 {
2778     /* erase outline */
2779     MoveOutline(0, 0, 0, 0);
2780     XSync (DISPLAY, FALSE /*don't discard events*/);
2781
2782     /* give up grabs */
2783     if (wmGD.freezeOnConfig) {
2784         XUngrabServer(DISPLAY);
2785     }
2786
2787     /*
2788      * Don't Ungrab keyboard away from menu widget to prevent 
2789      * hosing of traversal.
2790      */
2791     if (!wmGD.menuActive)
2792         XUngrabKeyboard (DISPLAY,CurrentTime);
2793
2794     XUngrabPointer (DISPLAY, CurrentTime);      /* event time NOT used */
2795     XFlush (DISPLAY);
2796
2797 } /* END OF FUNCTION UndoGrabs  */
2798
2799
2800 \f
2801 /*************************************<->*************************************
2802  *
2803  *  CancelFrameConfig (pcd)
2804  *
2805  *
2806  *  Description:
2807  *  -----------
2808  *  Cance a frame configuration (move/resize) operation.
2809  *
2810  *
2811  *  Inputs:
2812  *  ------
2813  *  pcd         - pointer to client data
2814  *
2815  * 
2816  *  Outputs:
2817  *  -------
2818  *
2819  *
2820  *  Comments:
2821  *  --------
2822  * 
2823  *************************************<->***********************************/
2824 void CancelFrameConfig (ClientData *pcd)
2825 {
2826
2827     /* remove keyboard, pointer, and server grabs */
2828     UndoGrabs();
2829
2830     /* turn off feedback window */
2831 #ifdef WSM
2832     if (pcd)
2833     {
2834 #endif /* WSM */
2835     HideFeedbackWindow(pcd->pSD);
2836
2837     /* make sure title bar is popped out */
2838     if ((wmGD.configAction == MOVE_CLIENT) &&
2839         (wmGD.gadgetClient == pcd) && (wmGD.gadgetDepressed == FRAME_TITLE))
2840     {
2841         PopGadgetOut (pcd, FRAME_TITLE);
2842         FrameExposureProc(pcd);                 /* repaint frame */
2843     }
2844     if ((pcd->pSD->moveOpaque) &&
2845         (wmGD.configAction == MOVE_CLIENT))
2846         
2847     {
2848         if ((pcd->clientState == MINIMIZED_STATE) &&
2849             (!(pcd->pSD->useIconBox && P_ICON_BOX(pcd))))
2850         {
2851             /*
2852              * Replace icon into pre-move position
2853              */
2854
2855             XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
2856                          ICON_X(pcd),  ICON_Y(pcd));
2857             if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART))
2858             {
2859                 ShowActiveIconText(pcd);
2860             }
2861         }
2862         else if (! wmGD.movingIcon) /* we are not moving in the iconbox */
2863         {
2864             XMoveWindow (DISPLAY, pcd->clientFrameWin, 
2865                          opaqueMoveX, opaqueMoveY);
2866         }
2867     }
2868 #ifdef WSM
2869     }
2870     if (wmGD.configAction == MARQUEE_SELECT)
2871     {
2872        dtSendMarqueeSelectionNotification(ACTIVE_PSD, DT_MARQUEE_SELECT_CANCEL, 
2873                             marqueeX, marqueeY, 0, 0);
2874     }
2875 #endif /* WSM */
2876
2877     /* replace pointer if no motion events received */
2878 #ifdef WSM
2879     if (pcd)
2880 #endif /* WSM */
2881     if (!anyMotion && wmGD.enableWarp) {
2882         XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd), 
2883                          0, 0, 0, 0, wmGD.preMoveX, wmGD.preMoveY);
2884     }
2885     anyMotion = FALSE;
2886
2887     /* Clear configuration flags and data */
2888     wmGD.configAction = NO_ACTION;
2889     wmGD.configPart = FRAME_NONE;
2890     wmGD.configSet = False;
2891     configGrab = FALSE;
2892     wmGD.movingIcon = FALSE;
2893     
2894     /* set the focus back to a reasonable window */
2895     RepairFocus ();     
2896 } /* END OF FUNCTION  CancelFrameConfig */
2897
2898
2899 \f
2900 /*************************************<->*************************************
2901  *
2902  *  CheckEatButtonRelease (pcd, pev)
2903  *
2904  *
2905  *  Description:
2906  *  -----------
2907  *  Set up to eat button releases if buttons are down.
2908  *
2909  *
2910  *  Inputs:
2911  *  ------
2912  *  pcd  - pointer to client data
2913  *  pev  - pointer to key event that caused cancel
2914  * 
2915  *  Outputs:
2916  *  -------
2917  *  none
2918  *
2919  *
2920  *  Comments:
2921  *  --------
2922  * 
2923  *************************************<->***********************************/
2924 void
2925 CheckEatButtonRelease (ClientData *pcd, XEvent *pev)
2926 {
2927     Window grab_win;
2928 #ifdef WSM
2929     Window root;
2930
2931     if (pcd != (ClientData *)NULL)
2932         root = ROOT_FOR_CLIENT(pcd);
2933     else
2934         root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
2935 #endif /* WSM */
2936
2937 #ifdef WSM
2938     if (pcd == (ClientData *) NULL)
2939         grab_win = root;
2940     else
2941 #endif /* WSM */
2942     grab_win = GrabWin(pcd, pev);
2943
2944     if ((pev->type == KeyPress || pev->type == KeyRelease) &&
2945         (pev->xbutton.state & ButtonMask))
2946     {
2947         /*
2948          * Some buttons are down... 
2949          * Set up conditions to wait for these buttons to go up.
2950          */
2951         if (XGrabPointer(DISPLAY, 
2952                          grab_win,
2953                          False,                 /* owner_events */
2954                          ButtonReleaseMask,
2955                          GrabModeAsync,         /* pointer_mode */
2956                          GrabModeAsync,         /* keyboard_mode */
2957 #ifdef WSM
2958                          root,                  /* confine_to window */
2959 #else /* WSM */
2960                          ROOT_FOR_CLIENT(pcd),  /* confine_to window */
2961 #endif /* WSM */
2962                          wmGD.configCursor,
2963                          pev->xbutton.time) == GrabSuccess)
2964         {
2965             EatButtonRelease (pev->xbutton.state & ButtonMask);
2966         }
2967     }
2968 }
2969
2970 \f
2971 /*************************************<->*************************************
2972  *
2973  *  EatButtonRelease (releaseButtons)
2974  *
2975  *
2976  *  Description:
2977  *  -----------
2978  *  Eat up button release events
2979  *
2980  *
2981  *  Inputs:
2982  *  ------
2983  *  releaseButtons = button mask of button releases to eat
2984  * 
2985  *  Outputs:
2986  *  -------
2987  *  none
2988  *
2989  *
2990  *  Comments:
2991  *  --------
2992  * 
2993  *************************************<->***********************************/
2994 void
2995 EatButtonRelease (unsigned int releaseButtons)
2996 {
2997     unsigned int new_state;
2998     XEvent event;
2999
3000     while (releaseButtons)
3001     {
3002 #ifdef WSM
3003         PullExposureEvents ();
3004 #endif /* WSM */
3005         XMaskEvent (DISPLAY, ButtonReleaseMask, &event);
3006
3007         if (event.type == ButtonRelease)
3008         {
3009             /* look at the state after this button is released */
3010             new_state = 
3011                 event.xbutton.state & ~ButtonStateBit(event.xbutton.button);
3012
3013             if (!(new_state & releaseButtons))
3014             {
3015                 /* all the buttons we were waiting for have been
3016                  * released.
3017                  */
3018
3019                 XUngrabPointer (DISPLAY, event.xbutton.time);
3020                 releaseButtons = 0;
3021             }
3022         }
3023     }
3024 }
3025
3026
3027 \f
3028 /*************************************<->*************************************
3029  *
3030  *  ButtonStateBit (button)
3031  *
3032  *
3033  *  Description:
3034  *  -----------
3035  *  Converts a button number to a button state bit
3036  *
3037  *
3038  *  Inputs:
3039  *  ------
3040  *  button = button number (Button1, Button2, etc.)
3041  * 
3042  *  Outputs:
3043  *  -------
3044  *  Return = bit used in xbutton state field 
3045  *              (Button1Mask, Button2Mask,...)
3046  *
3047  *
3048  *  Comments:
3049  *  --------
3050  *  
3051  * 
3052  *************************************<->***********************************/
3053 unsigned int
3054 ButtonStateBit (unsigned int button)
3055 {
3056 #define MAX_BUTTON 5
3057     typedef struct {
3058         unsigned int button;
3059         unsigned int maskbit;
3060     } ButtonAssoc;
3061
3062     static ButtonAssoc bmap[MAX_BUTTON] = {
3063          {Button1, Button1Mask},
3064          {Button2, Button2Mask},
3065          {Button3, Button3Mask},
3066          {Button4, Button4Mask},
3067          {Button5, Button5Mask},
3068     };
3069
3070     int i;
3071     unsigned int rval = 0;
3072
3073     for (i = 0; i < MAX_BUTTON; i++)
3074     {
3075         if (bmap[i].button == button)
3076         {
3077             rval = bmap[i].maskbit;
3078             break;
3079         }
3080     }
3081
3082     return (rval);
3083
3084 }
3085 \f
3086 /*************************************<->*************************************
3087  *
3088  *  ConfigCursor (frame_part)
3089  *
3090  *
3091  *  Description:
3092  *  -----------
3093  *  return the config cursor that goes with the config part specified
3094  *
3095  *
3096  *  Inputs:
3097  *  ------
3098  *  frame_part  - frame part id
3099  * 
3100  *  Outputs:
3101  *  -------
3102  *  return      - cursor to use 
3103  *
3104  *
3105  *  Comments:
3106  *  --------
3107  * 
3108  *************************************<->***********************************/
3109 Cursor ConfigCursor (int frame_part)
3110 {
3111     Cursor cursor;
3112
3113     switch (frame_part) {
3114         case FRAME_RESIZE_NW:
3115             cursor = wmGD.stretchCursors[STRETCH_NORTH_WEST];
3116             break;
3117         case FRAME_RESIZE_N:
3118             cursor = wmGD.stretchCursors[STRETCH_NORTH];
3119             break;
3120         case FRAME_RESIZE_NE:
3121             cursor = wmGD.stretchCursors[STRETCH_NORTH_EAST];
3122             break;
3123         case FRAME_RESIZE_E:
3124             cursor = wmGD.stretchCursors[STRETCH_EAST];
3125             break;
3126         case FRAME_RESIZE_SE:
3127             cursor = wmGD.stretchCursors[STRETCH_SOUTH_EAST];
3128             break;
3129         case FRAME_RESIZE_S:
3130             cursor = wmGD.stretchCursors[STRETCH_SOUTH];
3131             break;
3132         case FRAME_RESIZE_SW:
3133             cursor = wmGD.stretchCursors[STRETCH_SOUTH_WEST];
3134             break;
3135         case FRAME_RESIZE_W:
3136             cursor = wmGD.stretchCursors[STRETCH_WEST];
3137             break;
3138         default:
3139             cursor = wmGD.configCursor;
3140     }
3141
3142     return(cursor);
3143
3144 } /* END OF FUNCTION ConfigCursor  */
3145
3146 \f
3147 /*************************************<->*************************************
3148  *
3149  *  ReGrabPointer (grab_win, grabTime)
3150  *
3151  *
3152  *  Description:
3153  *  -----------
3154  *  Grab the pointer again to change the cursor
3155  *
3156  *
3157  *  Inputs:
3158  *  ------
3159  *  grab_win    - 
3160  *  grabTime    - time stamp
3161  * 
3162  *  Outputs:
3163  *  -------
3164  *
3165  *
3166  *  Comments:
3167  *  --------
3168  * 
3169  *************************************<->***********************************/
3170 void ReGrabPointer (Window grab_win, Time grabTime)
3171 {
3172     XGrabPointer(DISPLAY, 
3173                  grab_win,
3174                  FALSE,                 /* owner_events */
3175                  PGRAB_MASK,
3176                  GrabModeAsync,         /* pointer_mode */
3177                  GrabModeAsync,         /* keyboard_mode */
3178                  ACTIVE_ROOT,           /* confine_to window */
3179                  ConfigCursor((int)wmGD.configPart),
3180                  grabTime);
3181
3182 } /* END OF FUNCTION  ReGrabPointer */
3183
3184
3185 \f
3186 /*************************************<->*************************************
3187  *
3188  *  SetPointerResizePart (pcd, pev)
3189  *
3190  *
3191  *  Description:
3192  *  -----------
3193  *  Sets the global configuration part for resize based on the current
3194  *  configuration part and the location of the event
3195  *
3196  *
3197  *  Inputs:
3198  *  ------
3199  *  pcd         - pointer to client data
3200  *  pev         - pointer to event
3201  *
3202  * 
3203  *  Outputs:
3204  *  -------
3205  *  Return      - TRUE if wmGD.configPart is a valid resize part
3206  *
3207  *
3208  *  Comments:
3209  *  --------
3210  *  o Assumes the static data for resizing has been set up.
3211  *************************************<->***********************************/
3212 Boolean SetPointerResizePart (ClientData *pcd, XEvent *pev)
3213 {
3214     int newPart;
3215     Time grabTime;
3216
3217     newPart = ResizeType(pcd, pev);     /* get part id for this event */
3218     grabTime = (pev) ? pev->xmotion.time : CurrentTime;
3219
3220     switch (wmGD.configPart) {
3221         case FRAME_NONE:
3222             if (newPart == FRAME_NONE)
3223                 return(FALSE);          /* still not valid */
3224
3225             wmGD.configPart = newPart;
3226             ReGrabPointer(pcd->clientFrameWin, grabTime);
3227             return(TRUE);
3228
3229         case FRAME_RESIZE_N:
3230             switch (newPart) {
3231                 case FRAME_RESIZE_W:
3232                 case FRAME_RESIZE_NW:
3233                     wmGD.configPart = FRAME_RESIZE_NW;
3234                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3235                     break;
3236
3237                 case FRAME_RESIZE_E:
3238                 case FRAME_RESIZE_NE:
3239                     wmGD.configPart = FRAME_RESIZE_NE;
3240                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3241                     break;
3242
3243                 default:
3244                     break;
3245             }
3246             break;
3247
3248         case FRAME_RESIZE_E:
3249             switch (newPart) {
3250                 case FRAME_RESIZE_N:
3251                 case FRAME_RESIZE_NE:
3252                     wmGD.configPart = FRAME_RESIZE_NE;
3253                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3254                     break;
3255
3256                 case FRAME_RESIZE_S:
3257                 case FRAME_RESIZE_SE:
3258                     wmGD.configPart = FRAME_RESIZE_SE;
3259                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3260                     break;
3261
3262                 default:
3263                     break;
3264             }
3265             break;
3266
3267         case FRAME_RESIZE_S:
3268             switch (newPart) {
3269                 case FRAME_RESIZE_E:
3270                 case FRAME_RESIZE_SE:
3271                     wmGD.configPart = FRAME_RESIZE_SE;
3272                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3273                     break;
3274
3275                 case FRAME_RESIZE_W:
3276                 case FRAME_RESIZE_SW:
3277                     wmGD.configPart = FRAME_RESIZE_SW;
3278                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3279                     break;
3280
3281                 default:
3282                     break;
3283             }
3284             break;
3285
3286         case FRAME_RESIZE_W:
3287             switch (newPart) {
3288                 case FRAME_RESIZE_N:
3289                 case FRAME_RESIZE_NW:
3290                     wmGD.configPart = FRAME_RESIZE_NW;
3291                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3292                     break;
3293
3294                 case FRAME_RESIZE_S:
3295                 case FRAME_RESIZE_SW:
3296                     wmGD.configPart = FRAME_RESIZE_SW;
3297                     ReGrabPointer(pcd->clientFrameWin, grabTime);
3298                     break;
3299
3300                 default:
3301                     break;
3302             }
3303             break;
3304
3305         case FRAME_RESIZE_NW:
3306         case FRAME_RESIZE_NE:
3307         case FRAME_RESIZE_SW:
3308         case FRAME_RESIZE_SE:
3309             break;
3310
3311         default:
3312             return(FALSE);      /* not a valid resize part */
3313     }
3314     return(TRUE);
3315
3316 } /* END OF FUNCTION  SetPointerResizePart */
3317
3318 \f
3319 /*************************************<->*************************************
3320  *
3321  *  ResizeType (pcd, pev)
3322  *
3323  *
3324  *  Description:
3325  *  -----------
3326  *  Returns a resize part ID for an event outside of the current 
3327  *  resize area.
3328  *
3329  *
3330  *  Inputs:
3331  *  ------
3332  *  pcd         - pointer to client data
3333  *  pev         - pointer to event
3334  *
3335  * 
3336  *  Outputs:
3337  *  -------
3338  *
3339  *
3340  *  Comments:
3341  *  --------
3342  *  o Assumes the static data for resizing has been set up.
3343  *************************************<->***********************************/
3344 int ResizeType (ClientData *pcd, XEvent *pev)
3345 {
3346     int x, y;
3347
3348     if (!pev) return(FRAME_NONE);
3349
3350     x = pev->xmotion.x_root;
3351     y = pev->xmotion.y_root;
3352
3353     /* if inside all resize areas, then forget it */
3354     if ( (x > resizeX) &&
3355          (y > resizeY) &&
3356          (x < (resizeX + resizeWidth - 1)) &&
3357          (y < (resizeY + resizeHeight - 1)) )
3358     {
3359         return(FRAME_NONE);
3360     }
3361
3362     /* left side */
3363     if (x <= resizeX) {
3364         if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
3365             return (FRAME_RESIZE_NW);
3366         else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
3367             return (FRAME_RESIZE_SW);
3368         else 
3369             return (FRAME_RESIZE_W);
3370     } 
3371
3372     /* right side */
3373     if (x >= resizeX + resizeWidth - 1) {
3374         if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
3375             return (FRAME_RESIZE_NE);
3376         else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
3377             return (FRAME_RESIZE_SE);
3378         else 
3379             return (FRAME_RESIZE_E);
3380     } 
3381
3382     /* top side */
3383     if (y <= resizeY) {
3384         if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
3385             return (FRAME_RESIZE_NW);
3386         else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
3387             return (FRAME_RESIZE_NE);
3388         else 
3389             return (FRAME_RESIZE_N);
3390     } 
3391
3392     /* bottom side */
3393     if (y >= resizeY + resizeHeight - 1) {
3394         if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
3395             return (FRAME_RESIZE_SW);
3396         else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
3397             return (FRAME_RESIZE_SE);
3398         else 
3399             return (FRAME_RESIZE_S);
3400     } 
3401
3402     return(FRAME_NONE);
3403
3404 } /* END OF FUNCTION  ResizeType */
3405
3406
3407 \f
3408 /*************************************<->*************************************
3409  *
3410  *  FixFrameValues (pcd, pfX, pfY, pfWidth, pfHeight, resizing)
3411  *
3412  *
3413  *  Description:
3414  *  -----------
3415  *  Fix up the frame values so that they do not exceed maximum or minimum
3416  *  size and that at least part of the frame is on screen
3417  *
3418  *
3419  *  Inputs:
3420  *  ------
3421  *  pcd         - pointer to client data
3422  *  pfX         - pointer to frame x-coord
3423  *  pfY         - pointer to frame y-coord
3424  *  pfWidth     - pointer to frame width
3425  *  pfHeight    - pointer to frame height
3426  *  resizing      - check size constraints iff TRUE
3427  *
3428  * 
3429  *  Outputs:
3430  *  -------
3431  *  *pfX        - fixed up frame x-coord
3432  *  *pfY        - fixed up frame y-coord
3433  *  *pfWidth    - fixed up frame width
3434  *  *pfHeight   - fixed up frame height
3435  *
3436  *
3437  *  Comments:
3438  *  --------
3439  *  1. This could be more efficient
3440  *  2. Interactive resize with aspect ratio constraints may cause part of the
3441  *     outline to disappear off screen.  The critical case is when the title 
3442  *     bar disappears ABOVE the screen. 
3443  * 
3444  *************************************<->***********************************/
3445
3446 void FixFrameValues (ClientData *pcd, int *pfX, int *pfY, unsigned int *pfWidth, unsigned int *pfHeight, Boolean resizing)
3447 {
3448     unsigned int lswidth;
3449     unsigned int oWidth, oHeight;
3450
3451
3452     /* 
3453      * Fix size if resizing and not icon.
3454      */
3455
3456     if (resizing && !wmGD.movingIcon)
3457     {
3458         FrameToClient(pcd, pfX, pfY, pfWidth, pfHeight);
3459     
3460         oWidth = *pfWidth;
3461         oHeight = *pfHeight;
3462
3463         FixWindowSize (pcd, pfWidth, pfHeight, 1, 1);
3464
3465         AdjustPos (pfX, pfY, oWidth, oHeight, *pfWidth, *pfHeight);
3466
3467         ClientToFrame(pcd, pfX, pfY, pfWidth, pfHeight);
3468     }
3469
3470     /* 
3471      * Don't move if we'd end up totally offscreen 
3472      */
3473
3474     if (wmGD.movingIcon)
3475     {
3476         lswidth = FRAME_BORDER_WIDTH(pcd);
3477     }
3478     else
3479     {
3480         lswidth = pcd->frameInfo.lowerBorderWidth;
3481     }
3482     if (lswidth < 5) lswidth = 5;
3483
3484     if (wmGD.movingIcon && P_ICON_BOX(pcd))
3485     {
3486         /* 
3487          *  Constrain outline to icon box
3488          */
3489         /* left edge of outline */
3490         if (*pfX < clipX)
3491         {
3492             *pfX = clipX;
3493         }
3494
3495         /* top of outline */
3496         if (*pfY < clipY)
3497         {
3498             *pfY = clipY;
3499         }
3500
3501         /* right edge of outline */
3502         if (((int)*pfX) > ((int)clipX + (int)clipWidth - ((int)*pfWidth)))
3503         {
3504             *pfX = clipX + clipWidth - *pfWidth;
3505         }
3506
3507         /* bottom edge of outline */
3508         if (((int)*pfY) > ((int)clipY + (int)clipHeight - ((int)*pfHeight)))
3509         {
3510             *pfY = clipY + clipHeight - *pfHeight;
3511         }
3512
3513     }
3514     else
3515     {
3516         /* 
3517          * keep outline on screen 
3518          */
3519
3520
3521         /* keep right border on screen */
3522         if (*pfX < ((int) lswidth - (int) *pfWidth))
3523         {
3524             *pfX = (int) lswidth - (int) *pfWidth;
3525         }
3526
3527         /* keep bottom border on screen */
3528         if (*pfY < ((int) lswidth - (int) *pfHeight))
3529         {
3530             *pfY = (int) lswidth - (int) *pfHeight;
3531         }
3532
3533         /* keep left border on screen */
3534         if (*pfX > (DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) - 
3535             (int) lswidth))
3536         {
3537             *pfX = DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) - 
3538                 (int) lswidth;
3539         }
3540
3541         /* keep top border on screen */
3542         if (*pfY > (DisplayHeight(DISPLAY,SCREEN_FOR_CLIENT(pcd)) - 
3543             (int) lswidth))
3544         {
3545             *pfY = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pcd)) - 
3546                  (int) lswidth;
3547         }
3548     }
3549
3550 } /* END OF FUNCTION FixFrameValues */
3551
3552
3553 \f
3554 /*************************************<->*************************************
3555  *
3556  *  ForceOnScreen (screen, pX, pY)
3557  *
3558  *
3559  *  Description:
3560  *  -----------
3561  *  Correct (if necessary) the coords specified to make them on screen
3562  *
3563  *
3564  *  Inputs:
3565  *  ------
3566  *  screen      - screen number
3567  *  pX          - pointer to x-coord
3568  *  pY          - pointer to y-coord
3569  * 
3570  *  Outputs:
3571  *  -------
3572  *  *pX         - x-coord (on screen)
3573  *  *pY         - y-coord (on screen)
3574  *
3575  *
3576  *  Comments:
3577  *  --------
3578  *  XXComments ...
3579  * 
3580  *************************************<->***********************************/
3581 void ForceOnScreen (int screen, int *pX, int *pY)
3582 {
3583     if (*pX >= (DisplayWidth(DISPLAY, screen)))
3584         *pX = DisplayWidth(DISPLAY, screen) - 1;
3585     else if (*pX < 0)
3586         *pX = 0;
3587
3588     if (*pY >= (DisplayHeight(DISPLAY, screen)))
3589         *pY = DisplayHeight(DISPLAY, screen) - 1;
3590     else if (*pY < 0)
3591         *pY = 0;
3592
3593 } /* END OF FUNCTION  ForceOnScreen  */
3594
3595 \f
3596 /*************************************<->*************************************
3597  *
3598  *  SetPointerPosition (newX, newY, actualX, actualY)
3599  *
3600  *
3601  *  Description:
3602  *  -----------
3603  *  Attempt to set the pointer to position at newX, newY. 
3604  *
3605  *
3606  *  Inputs:
3607  *  ------
3608  *  newX        - X-coordinate to set pointer at
3609  *  newY        - Y-coordinate to set pointer at
3610  *
3611  * 
3612  *  Outputs:
3613  *  -------
3614  *  *actualX    - actual X-coord of pointer on return
3615  *  *actualY    - actual Y-coord of pointer on return
3616  *
3617  *  Comments:
3618  *  --------
3619  * 
3620  *************************************<->***********************************/
3621 void SetPointerPosition (int newX, int newY, int *actualX, int *actualY)
3622 {
3623     int junk;
3624     Window junk_win;
3625
3626     /*
3627      * Warp pointer ...
3628      */
3629     if (wmGD.enableWarp)
3630     {
3631         XWarpPointer(DISPLAY, None, ACTIVE_ROOT, 
3632              0, 0, 0, 0, newX, newY);
3633     }
3634
3635
3636     /*
3637      * Get pointer position
3638      * NOTE: if we are not warping, we don't want to do the Query pointer,
3639      *       hence enableWarp is tested first.
3640      */
3641     if (!wmGD.enableWarp || 
3642         !XQueryPointer (DISPLAY, ACTIVE_ROOT, &junk_win, &junk_win, 
3643                 actualX, actualY, &junk, &junk, (unsigned int *)&junk))
3644
3645     {
3646         /* failed to get pointer position or not warping, return something */
3647         *actualX = newX;
3648         *actualY = newY;
3649     }
3650
3651 } /* END OF FUNCTION SetPointerPositio  */
3652
3653
3654 \f
3655 /*************************************<->*************************************
3656  *
3657  *  GetConfigEvent (display, window, mask, curX, curY, oX, oY, 
3658  *     oWidth, oHeight, pev,)
3659  *
3660  *
3661  *  Description:
3662  *  -----------
3663  *  Get next configuration event
3664  *
3665  *
3666  *  Inputs:
3667  *  ------
3668  *  display     - pointer to display
3669  *  window      - window to get event relative to
3670  *  mask        - event mask - acceptable events to return
3671  *  pev         - pointer to a place to put the event
3672  *  curX        - current X value of pointer
3673  *  curY        - current Y value of pointer
3674  *  oX          - X value of outline
3675  *  oY          - Y value of outline
3676  *  oWidth      - width of outline
3677  *  oHeight     - height of outline
3678  * 
3679  *  Outputs:
3680  *  -------
3681  *  *pev        - event returned.
3682  *
3683  *  Comments:
3684  *  --------
3685  * 
3686  *************************************<->***********************************/
3687 void GetConfigEvent (Display *display, Window window, unsigned long mask, int curX, int curY, int oX, int oY, unsigned oWidth, unsigned oHeight, XEvent *pev)
3688 {
3689     Window root_ret, child_ret;
3690     int root_x, root_y, win_x, win_y;
3691     unsigned int mask_ret;
3692     Boolean polling;
3693     int pollCount;
3694     Boolean gotEvent;
3695     Boolean eventToReturn = False;
3696
3697     while (!eventToReturn)
3698     {
3699         /* 
3700          * Suck up pointer motion events 
3701          */
3702         gotEvent = False;
3703         while (XCheckWindowEvent(display, window, mask, pev))
3704         {
3705             gotEvent = True;
3706             if (pev->type != MotionNotify)
3707                 break;
3708         }
3709
3710         /*
3711          * Only poll if we are warping the pointer. 
3712          * (uses PointerMotionHints exclusively).
3713          */
3714         polling = wmGD.enableWarp;
3715         pollCount = CONFIG_POLL_COUNT;
3716
3717         if (!gotEvent && (polling || !wmGD.freezeOnConfig))
3718         {
3719             /*
3720              * poll for events and flash the frame outline 
3721              * if not move opaque
3722              */
3723
3724             while (True)
3725             {
3726                 if (XCheckWindowEvent(display, window, 
3727                                       (mask & ~PointerMotionMask), pev))
3728                 {
3729                     gotEvent = True;
3730                     break;
3731                 }
3732                 
3733                 if (!wmGD.freezeOnConfig && !wmGD.pActiveSD->moveOpaque)
3734                 {
3735                     /* flash the outline if server is not grabbed */
3736                     MoveOutline (oX, oY, oWidth, oHeight);
3737                 }
3738
3739                 if (!XQueryPointer (display, window, &root_ret, &child_ret, 
3740                         &root_x, &root_y, &win_x, &win_y, &mask_ret))
3741                 {
3742                     continue;   /* query failed, try again */
3743                 }
3744
3745                 if ((root_x != curX) || (root_y != curY))
3746                 {
3747                     /* 
3748                      * Pointer moved to a new position.
3749                      * Cobble a motion event together. 
3750                      * NOTE: SOME FIELDS NOT SET !!! 
3751                      */
3752
3753                     pev->type = MotionNotify;
3754                     /* pev->xmotion.serial = ??? */
3755                     pev->xmotion.send_event = False;
3756                     pev->xmotion.display = display;
3757                     pev->xmotion.window = root_ret;
3758                     pev->xmotion.subwindow = child_ret;
3759                     pev->xmotion.time = CurrentTime;            /* !!! !!! */
3760                     pev->xmotion.x = root_x;
3761                     pev->xmotion.y = root_y;
3762                     pev->xmotion.x_root = root_x;
3763                     pev->xmotion.y_root = root_y;
3764                     /* pev->xmotion.state = ??? */
3765                     /* pev->xmotion.is_hint  = ???? */
3766                     /* pev->xmotion.same_screen = ??? */
3767
3768                     eventToReturn = True;
3769                     break;      /* from while loop */
3770                 }
3771                 else if (wmGD.freezeOnConfig)
3772                 {
3773                     if (!(--pollCount))
3774                     {
3775                         /* 
3776                          * No pointer motion in some time. Stop polling
3777                          * and wait for next event.
3778                          */
3779                         polling = False;
3780                         break; /* from while loop */ 
3781                     }
3782                 }
3783             }  /* end while */
3784         }
3785
3786         if (!gotEvent && !polling && wmGD.freezeOnConfig) 
3787         {
3788             /* 
3789              * Wait for next event on window 
3790              */
3791
3792             XWindowEvent (display, window, mask, pev);
3793             gotEvent = True;
3794         }
3795
3796         if (gotEvent)
3797         {
3798             eventToReturn = True;
3799             if (pev->type == MotionNotify &&
3800                 pev->xmotion.is_hint == NotifyHint)
3801             {
3802                 /* 
3803                  * "Ack" the motion notify hint 
3804                  */
3805                 if ((XQueryPointer (display, window, &root_ret, 
3806                         &child_ret, &root_x, &root_y, &win_x, 
3807                         &win_y, &mask_ret)) &&
3808                     ((root_x != curX) ||
3809                      (root_y != curY)))
3810                 {
3811                     /*
3812                      * The query pointer values say that the pointer
3813                      * moved to a new location.
3814                      */
3815                     pev->xmotion.window = root_ret;
3816                     pev->xmotion.subwindow = child_ret;
3817                     pev->xmotion.x = root_x;
3818                     pev->xmotion.y = root_y;
3819                     pev->xmotion.x_root = root_x;
3820                     pev->xmotion.y_root = root_y;
3821
3822                 }
3823                 else {
3824                     /*
3825                      * Query failed. Change curX to force position
3826                      * to be returned on first sucessful query.
3827                      */
3828                     eventToReturn = False;
3829                     curX++;
3830                 }
3831             }
3832         }
3833     } /* end while */
3834
3835 } /* END OF FUNCTION GetConfigEvent  */
3836
3837 \f
3838 /*************************************<->*************************************
3839  *
3840  *  SetOutline (pOutline, x, y, width, height, fatness)
3841  *
3842  *
3843  *  Description:
3844  *  -----------
3845  *  Sets the outline of for config/move/placement operations
3846  *
3847  *
3848  *  Inputs:
3849  *  ------
3850  *  pOutline    - ptr to outline structure to fill in
3851  *  x           - x of upper-left corner of outline
3852  *  y           - y of upper-left corner of outline
3853  *  width       - width of outline.
3854  *  height      - height of outline.
3855  *  fatness     - pixel-width of outline
3856  * 
3857  *  Outputs:
3858  *  -------
3859  *
3860  *  Comments:
3861  *  --------
3862  *  o Be sure that pOutline points to a big enough area of memory 
3863  *    for the outline to be set!
3864  * 
3865  *************************************<->***********************************/
3866
3867 void SetOutline (XSegment *pOutline, int x, int y, unsigned int width, unsigned int height, int fatness)
3868 {
3869     int i;
3870
3871     for (i=0; i<fatness; i++)
3872     {
3873         pOutline->x1 = x;
3874         pOutline->y1 = y;
3875         pOutline->x2 = x + width -1;
3876         pOutline++->y2 = y;
3877
3878         pOutline->x1 = x + width -1;
3879         pOutline->y1 = y;
3880         pOutline->x2 = x + width -1;
3881         pOutline++->y2 = y + height - 1;
3882
3883         pOutline->x1 = x + width -1;
3884         pOutline->y1 = y + height - 1;
3885         pOutline->x2 = x;
3886         pOutline++->y2 = y + height - 1;
3887
3888         pOutline->x1 = x;
3889         pOutline->y1 = y + height - 1;
3890         pOutline->x2 = x;
3891         pOutline++->y2 = y;
3892
3893         /*
3894          * Modify values for next pass (if any)
3895          * Next outline will be on inside of current one.
3896          */
3897         x += 1;
3898         y += 1;
3899         width -= 2;
3900         height -= 2;
3901     }
3902
3903 } /* END OF FUNCTION SetOutline  */
3904
3905 \f
3906 /*************************************<->*************************************
3907  *
3908  *  AdjustPos (pX, pY, oWidth, oHeight, nWidth, nHeight)
3909  *
3910  *
3911  *  Description:
3912  *  -----------
3913  *  Adjusts the position according to wmGD.configPart and any change in
3914  *  client size.
3915  *
3916  *
3917  *  Inputs:
3918  *  ------
3919  *  pX, pY -- pointers to positions
3920  *  oWidth, oHeight -- original dimensions
3921  *  nWidth, nHeight -- new dimensions
3922  *  wmGD.configPart
3923  * 
3924  *  Outputs:
3925  *  -------
3926  *  pX, pY -- pointers to adjusted positions
3927  *
3928  *  Comments:
3929  *  --------
3930  * 
3931  *************************************<->***********************************/
3932
3933 void AdjustPos (int *pX, int *pY, unsigned int oWidth, unsigned int oHeight, unsigned int nWidth, unsigned int nHeight)
3934 {
3935     switch (wmGD.configPart) 
3936     {
3937         case FRAME_RESIZE_NW:
3938             /* anchor lower right corner */
3939             *pX += oWidth - nWidth;
3940             *pY += oHeight - nHeight;
3941             break;
3942
3943         case FRAME_RESIZE_N:
3944             /* anchor bottom */
3945             *pY += oHeight - nHeight;
3946             break;
3947
3948         case FRAME_RESIZE_NE:
3949             /* anchor lower left corner */
3950             *pY += oHeight - nHeight;
3951             break;
3952
3953         case FRAME_RESIZE_E:
3954             /* anchor left side */
3955             break;
3956
3957         case FRAME_RESIZE_SE:
3958             /* anchor upper left corner */
3959             break;
3960
3961         case FRAME_RESIZE_S:
3962             /* anchor top */
3963             break;
3964
3965         case FRAME_RESIZE_SW:
3966             /* anchor upper right corner */
3967             *pX += oWidth - nWidth;
3968             break;
3969
3970         case FRAME_RESIZE_W:
3971             /* anchor right side */
3972             *pX += oWidth - nWidth;
3973             break;
3974
3975         default:
3976             break;
3977     }
3978
3979 } /* END OF FUNCTION AdjustPos */
3980
3981
3982 \f
3983 /*************************************<->*************************************
3984  *
3985  *  GrabWin (pcd, pev)
3986  *
3987  *
3988  *  Description:
3989  *  -----------
3990  *  return window to do grab on for config operation
3991  *
3992  *
3993  *  Inputs:
3994  *  ------
3995  *  pcd         - ptr to client data
3996  *  pev         - ptr to event
3997  *
3998  *  Outputs:
3999  *  -------
4000  *  Return      - window 
4001  *
4002  *
4003  *  Comments:
4004  *  --------
4005  * 
4006  *************************************<->***********************************/
4007 Window GrabWin (ClientData *pcd, XEvent *pev)
4008 {
4009     Window grab_win;
4010     
4011     /*
4012      * The grab window is the icon if the client is minimized
4013      * or if the event was on a "normalized" icon in the icon box.
4014      */
4015
4016     if ((pcd->clientState == MINIMIZED_STATE) ||
4017         (pcd->pSD->useIconBox && pev &&
4018          ((pev->xany.window == ICON_FRAME_WIN(pcd)) ||
4019           (pev->xany.window == ACTIVE_ICON_TEXT_WIN))))
4020     {
4021         grab_win = ICON_FRAME_WIN(pcd);
4022     }
4023     else if (pev &&
4024              (pev->xany.window == pcd->clientFrameWin ||
4025               pev->xany.window == pcd->clientBaseWin ))
4026     {
4027         grab_win = pcd->clientFrameWin;
4028     }
4029     else if (pcd->pSD->useIconBox  &&
4030              P_ICON_BOX(pcd) &&
4031              wmGD.grabContext == F_SUBCONTEXT_IB_WICON)
4032     {
4033         grab_win = ICON_FRAME_WIN(pcd);
4034     }
4035     else
4036     {
4037         grab_win = pcd->clientFrameWin;
4038     }
4039
4040     return (grab_win);
4041
4042 } /* END OF FUNCTION GrabWin */
4043 #ifdef WSM
4044 \f
4045 /*************************************<->*************************************
4046  *
4047  *  HandleMarqueeSelect (pSD, event)
4048  *
4049  *
4050  *  Description:
4051  *  -----------
4052  *  Does a marquee selection on the root window
4053  *
4054  *
4055  *  Inputs:
4056  *  ------
4057  *
4058  *  Outputs:
4059  *  -------
4060  *
4061  *  Comments:
4062  *  --------
4063  *  Selection info is dumped into a root window property:
4064  *    _DT_MARQUEE_SELECTION
4065  * 
4066  *************************************<->***********************************/
4067 void
4068 HandleMarqueeSelect (WmScreenData *pSD, XEvent *pev)
4069 {
4070     Window grab_win;
4071     Boolean bDone;
4072     XEvent event;
4073
4074     grab_win = RootWindow (DISPLAY, pSD->screen);
4075     bDone = False;
4076
4077     while (!bDone && (wmGD.configAction == MARQUEE_SELECT))
4078     {
4079         if (!pev)       /* first time through will already have event */
4080         {
4081             pev = &event;
4082
4083             GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK, 
4084                 pointerX, pointerY, resizeX, resizeY,
4085                 resizeWidth, resizeHeight, &event);
4086         }
4087
4088         if (pev->type == MotionNotify)
4089         {
4090             pointerX = pev->xmotion.x_root;
4091             pointerY = pev->xmotion.y_root;
4092             UpdateMarqueeSelectData (pSD);
4093         }
4094         else if (pev->type == KeyPress) {
4095
4096             /* 
4097              * Handle key event. 
4098              */
4099             bDone = HandleMarqueeKeyPress (pSD, pev);
4100         }
4101         else if (pev->type == ButtonRelease) {
4102
4103             /*
4104              *  Update (x,y) to the location of the button release
4105              */
4106             pointerX = pev->xbutton.x_root;
4107             pointerY = pev->xbutton.y_root;
4108             UpdateMarqueeSelectData (pSD);
4109             CompleteFrameConfig ((ClientData *)NULL, pev);
4110             bDone = True;
4111         }
4112         else  {
4113             pev = NULL;
4114             continue;                   /* ignore this event */
4115         }
4116
4117         if (!bDone)
4118         {
4119             MoveOutline (marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4120         }
4121
4122         pev = NULL;     /* reset event pointer */
4123
4124     }  /* end while */
4125
4126 } /* END OF FUNCTION HandleMarqueeSelect */
4127
4128 \f
4129 /*************************************<->*************************************
4130  *
4131  *  StartMarqueeSelect ()
4132  *
4133  *
4134  *  Description:
4135  *  -----------
4136  *  Start marquee selection on root window
4137  *
4138  *
4139  *  Inputs:
4140  *  ------
4141  * 
4142  *  Outputs:
4143  *  -------
4144  *
4145  *
4146  *  Comments:
4147  *  --------
4148  * 
4149  *************************************<->***********************************/
4150 void
4151 StartMarqueeSelect(WmScreenData *pSD, XEvent *pev)
4152 {
4153     Window grab_win, junk_win;
4154     Boolean grabbed;
4155     int big_inc;
4156     int junk, junkX, junkY;
4157
4158     if (!pSD->bMarqueeSelectionInitialized)
4159     {
4160         /* 
4161          * If we haven't initialized the marquee selection messaging
4162          * then do so here before we do any grabs. Sending a dummy
4163          * message will do.
4164          *
4165          * (If we move off of ICCCM messaging, then this can go away.)
4166          */
4167         dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END, 
4168                                 0, 0, 0, 0);
4169         pSD->bMarqueeSelectionInitialized = True;
4170     }
4171
4172     /*
4173      *  Do our grabs 
4174      */
4175     if (!configGrab)
4176     {
4177         grab_win = RootWindow (DISPLAY, pSD->screen);
4178
4179         if (pev)
4180         {
4181             grabbed = DoGrabs (grab_win, wmGD.configCursor, 
4182                         PGRAB_MASK, pev->xbutton.time, NULL, True);
4183         }
4184         else
4185         {
4186             grabbed = DoGrabs (grab_win, wmGD.configCursor, 
4187                         PGRAB_MASK, CurrentTime, NULL, True);
4188         }
4189         if (!grabbed)
4190         {
4191             return;
4192         }
4193         configGrab = TRUE;
4194     }
4195     else
4196     {
4197         /* continue with the configuration in progress (!!!) */
4198         return;
4199     }
4200
4201     /* 
4202      * Set up static variables for succeeding events 
4203      */
4204     if ((pev->type == ButtonPress) || (pev->type == ButtonRelease))
4205     {
4206         pointerX = pev->xbutton.x_root;
4207         pointerY = pev->xbutton.y_root;
4208     }
4209     else if (!XQueryPointer (DISPLAY, pSD->rootWindow,
4210                         &junk_win, &junk_win,
4211                         &pointerX, &pointerY, 
4212                         &junk, &junk, (unsigned int *)&junk))
4213     {
4214         CancelFrameConfig ((ClientData *)NULL); /* release grabs */
4215         return;
4216     }
4217
4218     /* save start values to see where we came from */
4219     marqueeX = startX = pointerX;
4220     marqueeY = startY = pointerY;
4221     marqueeWidth0 = marqueeWidth = 0;
4222     marqueeHeight0 = marqueeHeight = 0;
4223     marqueeAnchor = ANCHOR_NW;
4224
4225     /* compute increment value for dynamic update */
4226     big_inc = DisplayWidth (DISPLAY, pSD->screen) / 20;
4227
4228     /* set configuring data */
4229     wmGD.configAction = MARQUEE_SELECT;
4230     wmGD.configButton = pev ? pev->xbutton.button: 0;
4231
4232     dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_BEGIN, 
4233             marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4234
4235 } /* END OF FUNCTION StartMarqueeSelect  */
4236
4237 \f
4238 /*************************************<->*************************************
4239  *
4240  *  UpdateMarqueeSelectData ()
4241  *
4242  *
4243  *  Description:
4244  *  -----------
4245  *
4246  *  Inputs:
4247  *  ------
4248  *  pSD         - pointer to screen data
4249  * 
4250  *  Outputs:
4251  *  -------
4252  *
4253  *
4254  *  Comments:
4255  *  --------
4256  *************************************<->***********************************/
4257 void UpdateMarqueeSelectData (WmScreenData *pSD)
4258 {
4259     /* validate and update anchor point and marquee data */
4260     
4261     switch (marqueeAnchor) 
4262     {
4263       case ANCHOR_NW:
4264         marqueeWidth = pointerX - marqueeX;
4265         marqueeHeight = pointerY - marqueeY;
4266
4267         if (marqueeWidth < 0)
4268         {
4269             marqueeWidth = -marqueeWidth;
4270             marqueeX = pointerX;
4271
4272             if (marqueeHeight < 0)
4273             {
4274                 marqueeHeight = -marqueeHeight;
4275                 marqueeY = pointerY;
4276                 marqueeAnchor = ANCHOR_SE;
4277             }
4278             else
4279             {
4280                 marqueeAnchor = ANCHOR_NE;
4281             }
4282         }
4283         else if (marqueeHeight < 0)
4284         {
4285             marqueeHeight = -marqueeHeight;
4286             marqueeY = pointerY;
4287             marqueeAnchor = ANCHOR_SW;
4288         }
4289         break;
4290
4291       case ANCHOR_NE:
4292         marqueeWidth += marqueeX - pointerX;
4293         marqueeHeight = pointerY - marqueeY;
4294         marqueeX = pointerX;
4295
4296         if (marqueeWidth < 0)
4297         {
4298             marqueeWidth = -marqueeWidth;
4299             marqueeX = pointerX - marqueeWidth;
4300
4301             if (marqueeHeight < 0)
4302             {
4303                 marqueeHeight = -marqueeHeight;
4304                 marqueeY = pointerY;
4305                 marqueeAnchor = ANCHOR_SW;
4306             }
4307             else
4308             {
4309                 marqueeAnchor = ANCHOR_NW;
4310             }
4311         }
4312         else if (marqueeHeight < 0)
4313         {
4314             marqueeHeight = -marqueeHeight;
4315             marqueeY = pointerY;
4316             marqueeAnchor = ANCHOR_SE;
4317         }
4318         break;
4319
4320       case ANCHOR_SE:
4321         marqueeWidth += marqueeX - pointerX;
4322         marqueeHeight += marqueeY - pointerY;
4323         marqueeX = pointerX;
4324         marqueeY = pointerY;
4325
4326         if (marqueeWidth < 0)
4327         {
4328             marqueeWidth = -marqueeWidth;
4329             marqueeX = pointerX - marqueeWidth;
4330
4331             if (marqueeHeight < 0)
4332             {
4333                 marqueeHeight = -marqueeHeight;
4334                 marqueeY = pointerY - marqueeHeight;
4335                 marqueeAnchor = ANCHOR_NW;
4336             }
4337             else
4338             {
4339                 marqueeAnchor = ANCHOR_SW;
4340             }
4341         }
4342         else if (marqueeHeight < 0)
4343         {
4344             marqueeHeight = -marqueeHeight;
4345             marqueeY = pointerY - marqueeHeight;
4346             marqueeAnchor = ANCHOR_NE;
4347         }
4348         break;
4349
4350       case ANCHOR_SW:
4351         marqueeWidth = pointerX - marqueeX;
4352         marqueeHeight += marqueeY - pointerY;
4353         marqueeY = pointerY;
4354
4355         if (marqueeWidth < 0)
4356         {
4357             marqueeWidth = -marqueeWidth;
4358             marqueeX = pointerX;
4359
4360             if (marqueeHeight < 0)
4361             {
4362                 marqueeHeight = -marqueeHeight;
4363                 marqueeY = pointerY - marqueeHeight;
4364                 marqueeAnchor = ANCHOR_NE;
4365             }
4366             else
4367             {
4368                 marqueeAnchor = ANCHOR_SE;
4369             }
4370         }
4371         else if (marqueeHeight < 0)
4372         {
4373             marqueeHeight = -marqueeHeight;
4374             marqueeY = pointerY - marqueeHeight;
4375             marqueeAnchor = ANCHOR_NW;
4376         }
4377         break;
4378     }
4379
4380     if ((wmGD.marqueeSelectGranularity > 0) &&
4381         ((ABS(marqueeWidth-marqueeWidth0) > wmGD.marqueeSelectGranularity) ||
4382          (ABS(marqueeHeight-marqueeHeight0)>wmGD.marqueeSelectGranularity)))
4383     {
4384         dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_CONTINUE, 
4385                 marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4386
4387         marqueeWidth0 = marqueeWidth;
4388         marqueeHeight0 = marqueeHeight;
4389     }
4390 }
4391
4392 \f
4393 /*************************************<->*************************************
4394  *
4395  *  HandleMarqueeKeyPress (pSD, pev)
4396  *
4397  *
4398  *  Description:
4399  *  -----------
4400  *  Handles keypress events during resize of window
4401  *
4402  *
4403  *  Inputs:
4404  *  ------
4405  *  pSD         - pointer to screen data
4406  *  pev         - pointer to event
4407  *
4408  * 
4409  *  Outputs:
4410  *  -------
4411  *  Return      - True if this event completes (or cancels) resizing 
4412  * 
4413  * 
4414  *  Comments: 
4415  *  --------
4416  * 
4417  *************************************<->***********************************/
4418 Boolean HandleMarqueeKeyPress (WmScreenData *pSD, XEvent *pev)
4419 {
4420     KeySym keysym;
4421     Boolean control;
4422     int keyMult;
4423     XEvent KeyEvent;
4424
4425     /*
4426      * Compress repeated keys 
4427      */
4428     keyMult = 1;
4429     while (keyMult <= 10 && 
4430               XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent, 
4431               (char *) pev))
4432     {
4433           keyMult++;
4434     }
4435
4436     keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
4437     control = (pev->xkey.state & ControlMask) != 0;
4438
4439     switch (keysym) {
4440
4441         case XK_Return:
4442             CompleteFrameConfig ((ClientData *)NULL, pev);
4443             return (True);
4444
4445         case XK_Escape:
4446             CancelFrameConfig ((ClientData *)NULL);
4447             CheckEatButtonRelease ((ClientData *)NULL, pev);
4448             return (True);
4449
4450         default:
4451             return (False);             /* ignore this key */
4452
4453     } /* end switch(keysym) */
4454
4455 } /* END OF FUNCTION HandleResizeKeyPress */
4456 #endif /* WSM */