source: trunk/third/mwm/WmWinConf.c @ 9757

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