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