2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$XConsortium: WmWinConf.c /main/8 1996/10/30 11:15:17 drk $"
36 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
41 #include "WmGlobal.h" /* This should be the first include */
45 #include <X11/keysymdef.h>
48 #define MOVE_OUTLINE_WIDTH 2
50 #define CONFIG_MASK (KeyPressMask|ButtonPressMask|\
51 ButtonReleaseMask|PointerMotionMask)
52 #define PGRAB_MASK (ButtonPressMask|ButtonReleaseMask|\
53 PointerMotionMask|PointerMotionHintMask)
70 #define ABS(x) ((x)>0?(x):(-(x)))
74 /* number of times to poll before blocking on a config event */
76 #define CONFIG_POLL_COUNT 300
78 /* mask for all buttons */
80 (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
83 * include extern functions
85 #include "WmWinConf.h"
90 #include "WmFeedback.h"
91 #include "WmFunction.h"
94 #include "WmIconBox.h"
95 #include "WmKeyFocus.h"
96 #include "WmProtocol.h"
97 #include "WmWinInfo.h"
104 * These statics are set up at the initiation of a configuration
105 * operation and used for succeeding events.
108 static int pointerX = -1;
109 static int pointerY = -1;
111 static int offsetX = 0;
112 static int offsetY = 0;
114 static int resizeX, resizeY; /* root coords of UL corner of frame */
115 static unsigned int resizeWidth, resizeHeight; /* size of frame */
116 static unsigned int resizeBigWidthInc, resizeBigHeightInc;
117 static int startX, startY;
118 static unsigned int startWidth, startHeight;
119 static unsigned int minWidth, minHeight, maxHeight, maxWidth;
121 static int marqueeX, marqueeY; /* root coords of UL corner of are */
122 static long marqueeWidth, marqueeHeight; /* size of area */
123 static unsigned int marqueeAnchor; /* id of anchor corner */
124 static long marqueeWidth0, marqueeHeight0; /* old size of area */
127 static int opaqueMoveX = 0; /* for cancel request on opaque moves */
128 static int opaqueMoveY = 0;
129 static int moveX = 0; /* root coords of UL corner of frame */
130 static int moveY = 0;
131 static int moveIBbbX = 0; /* root coords of icon box bulletin board */
132 static int moveIBbbY = 0;
133 static unsigned int moveWidth = 0; /* size of frame */
134 static unsigned int moveHeight = 0;
135 static int moveLastPointerX = 0; /* last pointer position */
136 static int moveLastPointerY= 0;
138 static Boolean anyMotion = FALSE;
139 static Boolean configGrab = FALSE;
140 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
141 static Boolean grabServer = TRUE;
142 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
144 Dimension clipWidth = 0;
145 Dimension clipHeight = 0;
151 /*************************************<->*************************************
153 * GetClipDimensions (pcd, fromRoot)
162 * pcd - pointer to client data
171 *************************************<->***********************************/
172 void GetClipDimensions (ClientData *pCD, Boolean fromRoot)
180 XtSetArg (getArgs[i], XmNwidth, (XtArgVal) &clipWidth ); i++;
181 XtSetArg (getArgs[i], XmNheight, (XtArgVal) &clipHeight ); i++;
182 XtSetArg (getArgs[i], XmNx, (XtArgVal) &tmpX ); i++;
183 XtSetArg (getArgs[i], XmNy, (XtArgVal) &tmpY ); i++;
185 XtGetValues (P_ICON_BOX(pCD)->clipWidget, getArgs, i);
189 XtTranslateCoords(P_ICON_BOX(pCD)->scrolledWidget,
199 } /* END OF FUNCTION GetClipDimensions */
203 /*************************************<->*************************************
205 * HandleClientFrameMove (pcd, pev)
210 * Provide visual feedback of interactive moving of the window.
215 * pcd - pointer to client data
216 * pev - pointer to event
225 *************************************<->***********************************/
226 void HandleClientFrameMove (ClientData *pcd, XEvent *pev)
228 int tmpX, tmpY, warpX, warpY;
231 Boolean control, moveDone;
233 int big_inc, keyMultiplier;
235 XEvent event, KeyEvent;
244 big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
248 * Do our grabs and initial setup if we're just starting out
251 if (!StartClientMove (pcd, pev))
253 /* configuration was not initiated */
258 grab_win = GrabWin (pcd, pev);
261 if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
263 GetClipDimensions (pcd, True);
272 /* handle the event we were called with first */
278 GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
279 moveLastPointerX, moveLastPointerY, moveX, moveY,
280 moveWidth, moveHeight, &event);
283 if (pev->type == KeyPress)
286 while (keyMultiplier <= big_inc &&
287 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
293 keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
294 control = (pev->xkey.state & ControlMask) != 0;
299 tmpX = keyMultiplier * ((control) ? (-big_inc) : (-1));
303 tmpY = keyMultiplier * ((control) ? (-big_inc) : (-1));
307 tmpX = keyMultiplier * ((control) ? big_inc : 1);
311 tmpY = keyMultiplier * ((control) ? big_inc : 1);
315 CompleteFrameConfig (pcd, pev);
319 CancelFrameConfig (pcd);
320 CheckEatButtonRelease (pcd, pev);
328 warpX = moveLastPointerX + tmpX;
329 warpY = moveLastPointerY + tmpY;
331 ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
333 if ((warpX != moveLastPointerX) || (warpY != moveLastPointerY))
335 SetPointerPosition (warpX, warpY, &newX, &newY);
337 tmpX = newX - moveLastPointerX;
338 tmpY = newY - moveLastPointerY;
339 moveLastPointerX = newX;
340 moveLastPointerY = newY;
347 * make like motion event and move frame.
354 else if (pev->type == ButtonRelease)
357 * Update (x,y) to the location of the button release
359 moveX += pev->xbutton.x_root - moveLastPointerX;
360 moveY += pev->xbutton.y_root - moveLastPointerY;
362 CompleteFrameConfig (pcd, pev);
365 else if (pev->type == MotionNotify)
367 tmpX = pev->xmotion.x_root - moveLastPointerX;
368 tmpY = pev->xmotion.y_root - moveLastPointerY;
369 moveLastPointerX = pev->xmotion.x_root;
370 moveLastPointerY = pev->xmotion.y_root;
376 /* draw outline if there is something to draw */
378 FixFrameValues (pcd, &moveX, &moveY, &moveWidth, &moveHeight,
379 FALSE /* no size checks */);
380 if (pcd->pSD->moveOpaque)
382 MoveOpaque (pcd, moveX, moveY, moveWidth, moveHeight);
386 MoveOutline(moveX, moveY, moveWidth, moveHeight);
389 if ( !wmGD.movingIcon &&
390 (wmGD.showFeedback & WM_SHOW_FB_MOVE))
392 DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight,
393 (unsigned long) 0, FALSE /* no size checks */);
398 } /* END OF FUNCTION HandleClientFrameMove */
402 /*************************************<->*************************************
404 * UpdateAndDrawResize ()
412 * pcd - pointer to client data
420 *************************************<->***********************************/
421 void UpdateAndDrawResize (ClientData *pcd)
423 int tmpHeight, tmpWidth;
426 * Handle a motion event or a keypress that's like a motion
432 switch (wmGD.configPart) {
433 case FRAME_RESIZE_NW:
435 case FRAME_RESIZE_NE:
436 tmpHeight = (int) startHeight + (startY - pointerY);
437 if (tmpHeight < (int) minHeight)
439 resizeHeight = minHeight;
440 resizeY = startY + startHeight - minHeight;
442 else if (pcd->pSD->limitResize
443 && (tmpHeight > (int) maxHeight)
444 && (!(pcd->clientFlags & ICON_BOX)))
446 resizeHeight = maxHeight;
447 resizeY = startY + startHeight - maxHeight;
451 resizeHeight = (unsigned int) tmpHeight;
456 case FRAME_RESIZE_SW:
458 case FRAME_RESIZE_SE:
460 tmpHeight = pointerY - startY + 1;
461 if (tmpHeight < (int) minHeight)
463 resizeHeight = minHeight;
465 else if (pcd->pSD->limitResize
466 && (tmpHeight > (int) maxHeight)
467 && (!(pcd->clientFlags & ICON_BOX)))
469 resizeHeight = maxHeight;
473 resizeHeight = (unsigned int) tmpHeight;
479 resizeHeight = startHeight;
486 switch (wmGD.configPart) {
487 case FRAME_RESIZE_NW:
489 case FRAME_RESIZE_SW:
490 tmpWidth = (int) startWidth + (startX - pointerX);
491 if (tmpWidth < (int) minWidth)
493 resizeWidth = minWidth;
494 resizeX = startX + startWidth - minWidth;
496 else if (pcd->pSD->limitResize
497 && (tmpWidth > (int) maxWidth)
498 && (!(pcd->clientFlags & ICON_BOX)))
500 resizeWidth = maxWidth;
501 resizeX = startX + startWidth - maxWidth;
505 resizeWidth = (unsigned int) tmpWidth;
510 case FRAME_RESIZE_NE:
512 case FRAME_RESIZE_SE:
514 tmpWidth = pointerX - startX + 1;
515 if (tmpWidth < (int) minWidth)
517 resizeWidth = minWidth;
519 else if (pcd->pSD->limitResize
520 && (tmpWidth > (int) maxWidth)
521 && (!(pcd->clientFlags & ICON_BOX)))
523 resizeWidth = maxWidth;
527 resizeWidth = (unsigned int) tmpWidth;
533 resizeWidth = startWidth;
537 FixFrameValues (pcd, &resizeX, &resizeY, &resizeWidth,
538 &resizeHeight, TRUE /* do size checks */);
539 MoveOutline (resizeX, resizeY, resizeWidth, resizeHeight);
540 if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
542 DoFeedback(pcd, resizeX, resizeY, resizeWidth, resizeHeight,
543 (unsigned long) 0, TRUE /* do size checks */);
548 /*************************************<->*************************************
550 * HandleClientFrameResize (pcd, pev)
555 * Provide visual feedback of interactive resizing of the window.
560 * pcd - pointer to client data
561 * pev - pointer to event
570 * o The window sizes refer to the frame, not the client window.
572 *************************************<->***********************************/
573 void HandleClientFrameResize (ClientData *pcd, XEvent *pev)
581 * Do our grabs the first time through
584 if (StartResizeConfig (pcd, pev))
590 /* resize could not be initiated */
595 grab_win = GrabWin (pcd, pev);
600 if (!pev) /* first time through will already have event */
604 GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
605 pointerX, pointerY, resizeX, resizeY,
606 resizeWidth, resizeHeight, &event);
609 if (pev->type == MotionNotify)
611 pointerX = pev->xmotion.x_root;
612 pointerY = pev->xmotion.y_root;
616 * Really start resizing once the pointer hits a resize area
617 * (This only applies to accelerator and keyboard resizing!)
619 if (!wmGD.configSet && !SetPointerResizePart (pcd, pev)) {
621 continue; /* ignore this event */
624 else if (pev->type == KeyPress) {
629 resizeDone = HandleResizeKeyPress (pcd, pev);
631 else if (pev->type == ButtonRelease) {
634 * Update (x,y) to the location of the button release
636 pointerX = pev->xbutton.x_root;
637 pointerY = pev->xbutton.y_root;
638 UpdateAndDrawResize(pcd);
640 CompleteFrameConfig (pcd, pev);
645 continue; /* ignore this event */
650 UpdateAndDrawResize(pcd);
653 pev = NULL; /* reset event pointer */
657 } /* END OF FUNCTION HandleClientFrameResize */
661 /*************************************<->*************************************
663 * HandleResizeKeyPress (pcd, pev)
668 * Handles keypress events during resize of window
673 * pcd - pointer to client data
674 * pev - pointer to event
679 * Return - True if this event completes (or cancels) resizing
685 *************************************<->***********************************/
686 Boolean HandleResizeKeyPress (ClientData *pcd, XEvent *pev)
690 int warpX, warpY, currentX, currentY, newX, newY;
696 * Compress repeated keys
699 while (keyMult <= 10 &&
700 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
706 keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
707 control = (pev->xkey.state & ControlMask) != 0;
711 switch (wmGD.configPart) {
713 wmGD.configPart = FRAME_RESIZE_W;
714 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
715 warpY = resizeY + resizeHeight/2;
716 warpX = resizeX + ((control) ?
717 (-resizeBigWidthInc) :
722 wmGD.configPart = FRAME_RESIZE_NW;
723 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
724 warpX = resizeX + ((control) ?
725 (-resizeBigWidthInc) :
731 wmGD.configPart = FRAME_RESIZE_SW;
732 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
733 warpX = resizeX + ((control) ?
734 (-resizeBigWidthInc) :
740 warpX = pointerX + ((control) ?
741 (-resizeBigWidthInc * keyMult) :
742 (-pcd->widthInc * keyMult));
749 switch (wmGD.configPart) {
751 wmGD.configPart = FRAME_RESIZE_N;
752 warpX = resizeX + resizeWidth/2;
753 warpY = resizeY + ((control) ?
754 (-resizeBigHeightInc) :
756 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
760 wmGD.configPart = FRAME_RESIZE_NW;
761 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
763 warpY = resizeY + ((control) ?
764 (-resizeBigHeightInc) :
769 wmGD.configPart = FRAME_RESIZE_NE;
770 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
772 warpY = resizeY + ((control) ?
773 (-resizeBigHeightInc) :
779 warpY = pointerY + ((control) ?
780 (-resizeBigHeightInc * keyMult) :
781 (-pcd->heightInc * keyMult));
787 switch (wmGD.configPart) {
789 wmGD.configPart = FRAME_RESIZE_E;
790 warpY = resizeY + resizeHeight/2;
791 warpX = resizeX + resizeWidth - 1 +
792 ((control) ? resizeBigWidthInc :
794 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
798 wmGD.configPart = FRAME_RESIZE_NE;
799 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
800 warpX = resizeX + resizeWidth - 1 +
801 ((control) ? resizeBigWidthInc :
807 wmGD.configPart = FRAME_RESIZE_SE;
808 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
809 warpX = resizeX + resizeWidth - 1 +
810 ((control) ? resizeBigWidthInc :
816 warpX = pointerX + ((control) ?
817 (resizeBigWidthInc * keyMult) :
818 (pcd->widthInc * keyMult));
825 switch (wmGD.configPart) {
827 wmGD.configPart = FRAME_RESIZE_S;
828 warpX = resizeX + resizeWidth/2;
829 warpY = resizeY + resizeHeight - 1 +
830 ((control) ? resizeBigHeightInc :
832 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
836 wmGD.configPart = FRAME_RESIZE_SE;
837 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
839 warpY = resizeY + resizeHeight - 1 +
840 ((control) ? resizeBigHeightInc :
845 wmGD.configPart = FRAME_RESIZE_SW;
846 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
848 warpY = resizeY + resizeHeight - 1 +
849 ((control) ? resizeBigHeightInc :
855 warpY = pointerY + ((control) ?
856 (resizeBigHeightInc * keyMult) :
857 (pcd->heightInc * keyMult));
863 CompleteFrameConfig (pcd, pev);
867 CancelFrameConfig (pcd);
868 CheckEatButtonRelease (pcd, pev);
872 return (False); /* ignore this key */
874 } /* end switch(keysym) */
877 * Make sure the new pointer position is on screen before doing
878 * the warp. Warp only if the pointer position changes.
883 ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
886 * Don't query pointer if enable warp is off.
888 if (!wmGD.enableWarp ||
889 XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
890 ¤tX, ¤tY, &junk, &junk, (unsigned int *)&junk))
892 if ( (warpX != currentX) || (warpY != currentY) )
894 SetPointerPosition (warpX, warpY, &newX, &newY);
900 } /* END OF FUNCTION HandleResizeKeyPress */
903 /*************************************<->*************************************
905 * DoFeedback (pcd, x, y, width, height, newStyle, resizing)
910 * Start or update feedback of size/position info
915 * pcd - pointer to client data
920 * newStyle - style flags.
921 * resizing - check size constraints iff TRUE
930 * o If newStyle has FB_POSITION and/or FB_SIZE bits set, then it is
931 * assumed that this is an initial call and a feedback window of the
932 * desired style should be popped up. If newStyle is zero, then it
933 * is assumed that the feedback window is already up and the values
934 * passed in are updates.
936 *************************************<->***********************************/
937 void DoFeedback (ClientData *pcd, int x, int y, unsigned int width, unsigned int height, unsigned long newStyle, Boolean resizing)
941 unsigned int cwidth, cheight;
943 /* compute client window coordinates from frame coordinates */
944 FrameToClient (pcd, &cx, &cy, &width, &height);
946 /* use frame (not client) position if user wishes it */
947 if (wmGD.positionIsFrame) {
952 /* If resizing, make sure configuration is valid. */
955 FixWindowConfiguration (pcd, &width, &height,
956 (unsigned int) pcd->widthInc,
957 (unsigned int) pcd->heightInc);
961 * Put size in client specific units. Do not include base into calculations
962 * when increment is not specified (i.e. = 1).
964 cwidth = (width - ((pcd->widthInc==1) ? 0 : pcd->baseWidth))
966 cheight = (height - ((pcd->heightInc==1) ? 0 : pcd->baseHeight))
970 ShowFeedbackWindow (pcd->pSD, cx, cy, cwidth, cheight, newStyle);
973 UpdateFeedbackInfo (pcd->pSD, cx, cy, cwidth, cheight);
975 } /* END OF FUNCTION DoFeedback */
979 /*************************************<->*************************************
986 * Prevents icons in the icon box from being moved outside the clip window
991 * pcd - pointer to client data
1002 *************************************<->***********************************/
1004 Boolean CheckVisualPlace (ClientData *pCD, int tmpX, int tmpY)
1006 Boolean rval = True;
1011 GetClipDimensions(pCD, True);
1015 * Get root coordinates of X and Y for icon.
1016 * We use root coordinates of clip window since clipX and
1017 * clipY are not 0, but the icon X and Y may be 0 in
1021 XTranslateCoordinates(DISPLAY, XtWindow(P_ICON_BOX(pCD)->bBoardWidget),
1022 ROOT_FOR_CLIENT(pCD), tmpX, tmpY,
1023 &newX, &newY, &child);
1036 if (((int)newX) > ((int)clipX +
1037 (int)clipWidth - ((int)ICON_WIDTH(pCD))))
1041 if (((int)newY) > ((int)clipY +
1042 (int)clipHeight - ((int)ICON_HEIGHT(pCD))))
1049 } /* END OF FUNCTION CheckVisualPlace */
1053 /*************************************<->*************************************
1055 * CompleteFrameConfig (pcd, pev)
1060 * Clean up graphic feedback when user stops configuring.
1065 * pcd - pointer to client data
1066 * pev - pointer to event
1075 * o This routine assumes that it is called in response to a button release
1078 *************************************<->***********************************/
1079 void CompleteFrameConfig (ClientData *pcd, XEvent *pev)
1081 unsigned int tmpWidth, tmpHeight;
1086 if (wmGD.configAction == RESIZE_CLIENT) {
1087 /* release the grabs */
1091 * Honor the implied constrained anchor points on the window
1092 * so that the resize doesn't cause the window to move
1096 #ifndef CONFIG_RELATIVE_TO_CLIENT
1101 /* Use dummy x,y so we don't add frame offset to client location */
1102 FrameToClient (pcd, &tmpX, &tmpY, &resizeWidth, &resizeHeight);
1104 FrameToClient (pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
1107 tmpWidth = resizeWidth;
1108 tmpHeight = resizeHeight;
1110 FixWindowConfiguration (pcd, &tmpWidth, &tmpHeight,
1111 (unsigned int) pcd->widthInc,
1112 (unsigned int) pcd->heightInc);
1114 AdjustPos (&resizeX, &resizeY,
1115 resizeWidth, resizeHeight, tmpWidth, tmpHeight);
1117 /* reconfigure the window(s) */
1118 ProcessNewConfiguration (pcd, resizeX, resizeY,
1119 resizeWidth, resizeHeight, FALSE);
1122 else if (wmGD.configAction == MOVE_CLIENT)
1124 /* release the grabs */
1127 /* make sure title bar is popped out */
1128 if ((wmGD.configAction == MOVE_CLIENT) &&
1129 (wmGD.gadgetClient == pcd) &&
1130 (wmGD.gadgetDepressed == FRAME_TITLE))
1132 PopGadgetOut (pcd, FRAME_TITLE);
1133 FrameExposureProc(pcd); /* repaint frame */
1136 /* handle both icon and normal frames */
1137 if (wmGD.movingIcon)
1140 inIconBox = (pcd->pSD->useIconBox && P_ICON_BOX(pcd));
1142 /* only need to move the icon */
1143 if (wmGD.iconAutoPlace || inIconBox)
1148 IconPlacementData *pIPD;
1151 * Get correct icon placement data
1155 pIPD = &P_ICON_BOX(pcd)->IPD;
1161 pIPD = &(ACTIVE_WS->IPData);
1165 * Check to make sure that there is an unoccupied place
1166 * where the icon is being moved to:
1169 centerX = moveX + ICON_WIDTH(pcd) / 2;
1170 centerY = moveY + ICON_HEIGHT(pcd) / 2;
1171 place = CvtIconPositionToPlace (pIPD, centerX, centerY);
1173 if (place != ICON_PLACE(pcd))
1175 if (pIPD->placeList[place].pCD)
1178 * Primary place occupied, try to find an unoccupied
1179 * place in the proximity.
1182 place = FindIconPlace (pcd, pIPD, centerX, centerY);
1183 if (place == NO_ICON_PLACE)
1186 * Can't find an unoccupied icon place.
1189 F_Beep (NULL, pcd, (XEvent *)NULL);
1191 if (pcd->pSD->moveOpaque && !inIconBox)
1194 * Replace icon into same place - as if it
1198 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1199 ICON_X(pcd), ICON_Y(pcd));
1200 if ((ICON_DECORATION(pcd) &
1201 ICON_ACTIVE_LABEL_PART) &&
1202 (wmGD.keyboardFocus == pcd))
1204 MoveActiveIconText(pcd);
1205 ShowActiveIconText(pcd);
1210 if ((place != NO_ICON_PLACE) &&
1211 (place != ICON_PLACE(pcd)))
1215 CvtIconPlaceToPosition (pIPD, place,
1217 if( (CheckIconBoxSize (P_ICON_BOX(pcd))) &&
1218 (CheckVisualPlace(pcd, tmpX, tmpY)))
1221 * Move the icon to the new place.
1224 MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
1225 CvtIconPlaceToPosition (pIPD, place,
1226 &ICON_X(pcd), &ICON_Y(pcd));
1230 pIPD->placeList[ICON_PLACE(pcd)].theWidget,
1231 ICON_X(pcd), ICON_Y(pcd));
1233 SetNewBounds (P_ICON_BOX(pcd));
1234 if (ICON_DECORATION(pcd) &
1235 ICON_ACTIVE_LABEL_PART)
1237 MoveActiveIconText(pcd);
1242 F_Beep (NULL, pcd, (XEvent *)NULL);
1248 * Move the icon to the new place.
1250 MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
1251 CvtIconPlaceToPosition (pIPD, place, &ICON_X(pcd),
1254 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1255 ICON_X(pcd), ICON_Y(pcd));
1257 if (pcd->pSD->moveOpaque &&
1258 (ICON_DECORATION(pcd) &
1259 ICON_ACTIVE_LABEL_PART) &&
1260 (wmGD.keyboardFocus == pcd))
1262 MoveActiveIconText(pcd);
1263 ShowActiveIconText(pcd);
1268 else if (pcd->pSD->moveOpaque && !inIconBox)
1271 * Replace icon into same place - as if it
1274 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1275 ICON_X(pcd), ICON_Y(pcd));
1276 if ((ICON_DECORATION(pcd) &
1277 ICON_ACTIVE_LABEL_PART) &&
1278 (wmGD.keyboardFocus == pcd))
1280 MoveActiveIconText(pcd);
1281 ShowActiveIconText(pcd);
1287 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd), moveX, moveY);
1288 ICON_X(pcd) = moveX;
1289 ICON_Y(pcd) = moveY;
1291 if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
1292 (wmGD.keyboardFocus == pcd))
1294 MoveActiveIconText(pcd);
1297 else { /* assume normal window frame */
1298 /* reconfigure the window(s) */
1299 ProcessNewConfiguration (pcd,
1300 #ifndef CONFIG_RELATIVE_TO_CLIENT
1308 (moveWidth - 2*offsetX),
1310 (moveHeight - offsetX - offsetY),
1315 else if (wmGD.configAction == MARQUEE_SELECT)
1321 pSD = pcd ? pcd->pSD : ACTIVE_PSD;
1323 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END,
1324 marqueeX, marqueeY, marqueeWidth, marqueeHeight);
1329 * Clear configuration flags and data.
1332 wmGD.configAction = NO_ACTION;
1333 wmGD.configPart = FRAME_NONE;
1334 wmGD.configSet = False;
1337 wmGD.movingIcon = FALSE;
1343 /* hide the move/resize config data */
1344 HideFeedbackWindow(pcd->pSD);
1347 * Set the focus back to something reasonable
1354 } /* END OF FUNCTION CompleteFrameConfig */
1357 /*************************************<->*************************************
1359 * MoveOpaque (pcd, x, y, width, height)
1364 * Move a window or icon on the root or icon box.
1369 * pcd - client data pointer
1370 * x - x coordinate (on root)
1371 * y - y coordinate (on root)
1372 * width - pixel width of frame
1373 * height - pixel height of frame
1381 * o use MoveOutline() for icons in an icon box.
1383 *************************************<->***********************************/
1384 void MoveOpaque (ClientData *pcd, int x, int y,
1385 unsigned int width, unsigned int height)
1389 /* Check if moving icon */
1390 if (wmGD.movingIcon)
1392 if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
1395 * For now just fall back to move outline when the
1396 * icon is in the icon box
1399 MoveOutline (x, y, width, height);
1403 XMoveWindow (DISPLAY,ICON_FRAME_WIN(pcd) , x, y);
1408 /* This is a window */
1409 XMoveWindow (DISPLAY, pcd->clientFrameWin, x, y);
1413 /* cleanup exposed frame parts */
1414 PullExposureEvents ();
1416 } /* END OF FUNCTION MoveOpaque */
1420 /* thickness of outline */
1421 #define OUTLINE_WIDTH 2
1423 /* number of points to draw outline once */
1424 #define SEGS_PER_DRAW (4*OUTLINE_WIDTH)
1426 /* number of points to flash outline (draw then erase) */
1427 #define SEGS_PER_FLASH (2*SEGS_PER_DRAW)
1430 /*************************************<->*************************************
1432 * DrawSegments (dpy, win, gc, outline, nsegs)
1436 * Draw segments using either using normal X or using the ALLPLANES
1437 * extension, depending on #ifdef ALLPLANES and whether the server actually
1438 * supports the extension. This is a thin wrapper around the Xlib
1439 * XDrawSegments() call.
1443 * dpy - the X display
1444 * win - the window on which to draw
1445 * gc - the gc to use, typically whose function is GXxor
1446 * outline - array of segments
1447 * nsegs - number of segments in the outline array
1455 * Note: no GC is used when drawing with the ALLPLANES extension;
1456 * therefore, the GC parameter is ignored in that case.
1458 *************************************<->***********************************/
1462 DrawSegments (Display *dpy, Window win, GC gc, XSegment *outline, int nsegs)
1464 #if defined(sun) && defined(ALLPLANES)
1466 XAllPlanesDrawSegments(dpy, win, outline, nsegs);
1468 #endif /* defined(sun) && defined(ALLPLANES) */
1469 XDrawSegments(dpy, win, gc, outline, nsegs);
1470 } /* END OF FUNCTION DrawSegments */
1473 /*************************************<->*************************************
1475 * MoveOutline (x, y, width, height)
1480 * Draw a window outline on the root window.
1485 * x - x coordinate (on root)
1486 * y - y coordinate (on root)
1487 * width - pixel width of frame
1488 * height - pixel height of frame
1496 * o get display, root window ID, and xorGC out of global data.
1498 *************************************<->***********************************/
1499 void MoveOutline (int x, int y, unsigned int width, unsigned int height)
1501 if (wmGD.freezeOnConfig)
1503 DrawOutline (x, y, width, height);
1508 if (wmGD.useWindowOutline)
1509 WindowOutline(x,y,width,height);
1512 FlashOutline(x, y, width, height);
1514 } /* END OF FUNCTION MoveOutline */
1518 /*************************************<->*************************************
1525 * flash a window outline on the root window.
1530 * x - x coordinate (on root)
1531 * y - y coordinate (on root)
1532 * width - pixel width of frame
1533 * height - pixel height of frame
1541 * o get display, root window ID, and xorGC out of global data.
1542 * o draw on root and erase "atomically"
1544 *************************************<->***********************************/
1545 void FlashOutline (int x, int y, unsigned int width, unsigned int height)
1547 static XSegment outline[SEGS_PER_FLASH];
1550 * Do nothing if no box to draw
1552 if (x == 0 && y == 0 &&
1553 width == 0 && height == 0)
1557 * Draw outline an even number of times (draw then erase)
1559 SetOutline (outline, x, y, width, height, OUTLINE_WIDTH);
1560 memcpy ( (char *) &outline[SEGS_PER_DRAW], (char *) &outline[0],
1561 SEGS_PER_DRAW*sizeof(XSegment));
1564 * Flash the outline at least once, then as long as there's
1565 * nothing else going on
1567 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1568 outline, SEGS_PER_FLASH);
1569 XSync(DISPLAY, FALSE);
1571 while (!XtAppPending(wmGD.mwmAppContext)) {
1572 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1573 outline, SEGS_PER_FLASH);
1574 XSync(DISPLAY, FALSE);
1576 } /* END OF FUNCTION FlashOutline */
1580 /*************************************<->*************************************
1582 * CreateOutlineWindows (pSD)
1587 * create the outline windows
1598 * variables are affected:
1604 *************************************<->***********************************/
1606 CreateOutlineWindows (WmScreenData *pSD)
1608 XSetWindowAttributes xswa;
1609 unsigned int xswamask;
1610 int x, y, width, height;
1615 width = OUTLINE_WIDTH;
1616 height = OUTLINE_WIDTH;
1618 xswa.override_redirect = True;
1619 xswa.backing_store = NotUseful;
1620 xswa.save_under = True;
1621 xswa.background_pixmap = XmGetPixmap(
1622 XtScreen(pSD->screenTopLevelW),
1624 pSD->clientAppearance.foreground,
1625 pSD->clientAppearance.background);
1627 xswamask = (CWOverrideRedirect |
1632 pSD->woN = XCreateWindow(DISPLAY, pSD->rootWindow,
1633 x, y, width, height,
1635 XDefaultDepth(DISPLAY,pSD->screen),
1641 pSD->woS = XCreateWindow(DISPLAY, pSD->rootWindow,
1642 x, y, width, height,
1644 XDefaultDepth(DISPLAY,pSD->screen),
1650 pSD->woE = XCreateWindow(DISPLAY, pSD->rootWindow,
1651 x, y, width, height,
1653 XDefaultDepth(DISPLAY,pSD->screen),
1659 pSD->woW = XCreateWindow(DISPLAY, pSD->rootWindow,
1660 x, y, width, height,
1662 XDefaultDepth(DISPLAY,pSD->screen),
1668 } /* END OF FUNCTION CreateOutlineWindows */
1671 /*************************************<->*************************************
1678 * show an outline on the root window using windows.
1683 * x - x coordinate (on root)
1684 * y - y coordinate (on root)
1685 * width - pixel width of frame
1686 * height - pixel height of frame
1694 * Always unmap during move/resize of outline windows to let saveunder
1695 * stuff work. HP server's toss saveunder stuff for windows that
1696 * configure themselves while mapped.
1698 *************************************<->***********************************/
1699 void WindowOutline (int x, int y, unsigned int width, unsigned int height)
1701 static int lastOutlineX = 0;
1702 static int lastOutlineY = 0;
1703 static int lastOutlineWidth = 0;
1704 static int lastOutlineHeight = 0;
1705 WmScreenData *pSD = ACTIVE_PSD;
1709 if (pSD->woN == (Window)0L)
1711 CreateOutlineWindows(pSD);
1714 if (x == lastOutlineX && y == lastOutlineY &&
1715 width == lastOutlineWidth && height == lastOutlineHeight)
1717 return; /* no change */
1720 XUnmapWindow(DISPLAY, pSD->woN);
1721 XUnmapWindow(DISPLAY, pSD->woS);
1722 XUnmapWindow(DISPLAY, pSD->woE);
1723 XUnmapWindow(DISPLAY, pSD->woW);
1725 if ((width == 0) && (height == 0))
1727 lastOutlineWidth = lastOutlineHeight = 0;
1728 lastOutlineX = lastOutlineY = 0;
1738 XMoveResizeWindow (DISPLAY, pSD->woN, iX, iY, iW, iH);
1742 iY = y + OUTLINE_WIDTH;
1744 iH = (int) height - OUTLINE_WIDTH;
1746 XMoveResizeWindow (DISPLAY, pSD->woW, iX, iY, iW, iH);
1749 iX = x + (int)width - OUTLINE_WIDTH;
1750 iY = y + OUTLINE_WIDTH;
1752 iH = (int)height - OUTLINE_WIDTH;
1754 XMoveResizeWindow (DISPLAY, pSD->woE, iX, iY, iW, iH);
1757 iX = x + OUTLINE_WIDTH;
1758 iY = y + (int)height - OUTLINE_WIDTH;
1759 iW = (int)width - 2*OUTLINE_WIDTH;
1762 XMoveResizeWindow (DISPLAY, pSD->woS, iX, iY, iW, iH);
1766 lastOutlineWidth = width;
1767 lastOutlineHeight = height;
1769 XMapRaised (DISPLAY, pSD->woN);
1770 XMapRaised (DISPLAY, pSD->woS);
1771 XMapRaised (DISPLAY, pSD->woE);
1772 XMapRaised (DISPLAY, pSD->woW);
1774 /* cleanup exposed frame parts */
1775 PullExposureEvents ();
1778 } /* END OF FUNCTION WindowOutline */
1783 /*************************************<->*************************************
1785 * DrawOutline (x, y, width, height)
1790 * Draw a window outline on the root window.
1795 * x - x coordinate (on root)
1796 * y - y coordinate (on root)
1797 * width - pixel width of frame
1798 * height - pixel height of frame
1806 * o get display, root window ID, and xorGC out of global data.
1808 *************************************<->***********************************/
1809 void DrawOutline (int x, int y, unsigned int width, unsigned int height)
1811 static int lastOutlineX = 0;
1812 static int lastOutlineY = 0;
1813 static int lastOutlineWidth = 0;
1814 static int lastOutlineHeight = 0;
1815 XSegment outline[SEGS_PER_DRAW];
1818 if (x == lastOutlineX && y == lastOutlineY &&
1819 width == lastOutlineWidth && height == lastOutlineHeight)
1821 return; /* no change */
1824 if (lastOutlineWidth || lastOutlineHeight) {
1825 SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
1826 lastOutlineHeight, OUTLINE_WIDTH);
1828 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1829 outline, SEGS_PER_DRAW);
1834 lastOutlineWidth = width;
1835 lastOutlineHeight = height;
1837 if (lastOutlineWidth || lastOutlineHeight) {
1839 SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
1840 lastOutlineHeight, OUTLINE_WIDTH);
1842 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1843 outline, SEGS_PER_DRAW);
1845 } /* END OF FUNCTION DrawOutline */
1849 /*************************************<->*************************************
1851 * WindowIsOnScreen (pCD, dx, dy)
1856 * This function is used to check if a window is atleast partially on the
1857 * screen or not. If the window is completely off the screen, dx and dy
1858 * will contain the minimum distance to move some part of the window's frame
1859 * back onto the screen.
1864 * pCD - pointer to client data
1869 * dx - minimum x distance to move the window back to the screen
1870 * dy - minimum y distance to move the window back to the screen
1875 * true - if the window has some part on the screen
1876 * false - if the window is completely off the screen
1881 *************************************<->***********************************/
1883 Boolean WindowIsOnScreen (ClientData *pCD, int *dx, int *dy)
1885 int x1 = pCD->clientX;
1886 int x2 = pCD->clientX + pCD->clientWidth;
1887 int y1 = pCD->clientY;
1888 int y2 = pCD->clientY + pCD->clientHeight;
1889 int screenW = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
1890 int screenH = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pCD));
1894 if (x2 < 0) /* right frame border off left side of screen. */
1896 else if (x1 > screenW) /* left frame border off right side of screen. */
1899 if (y2 < 0) /* bottom frame border off top of screen. */
1901 else if (y1 > screenH) /* top frame border off bottom of screen. */
1904 return ((*dx == 0) && (*dy == 0));
1909 /*************************************<->*************************************
1911 * ProcessNewConfiguration (pCD, x, y, width, height, clientRequest)
1916 * This function is used to configure a client window following receipt of
1917 * a client request or an interactive configuration action.
1922 * pCD - pointer to client data
1923 * x - x coord of client window
1924 * y - y coord of client window
1925 * width - width of client window
1926 * height - height of client window
1927 * clientRequest - true if configuration requested by client program
1937 *************************************<->***********************************/
1939 void ProcessNewConfiguration (ClientData *pCD, int x, int y, unsigned int width, unsigned int height, Boolean clientRequest)
1941 unsigned int changedValues = 0;
1942 int xoff = 0, yoff = 0;
1944 Boolean originallyOnScreen = WindowIsOnScreen(pCD, &dx, &dy);
1945 Boolean newMax = False;
1946 Boolean toNewMax = False;
1949 * Fix the configuration values to be compatible with the configuration
1950 * constraints for this class of windows.
1955 FixWindowConfiguration (pCD, &width, &height,
1956 (unsigned int) pCD->widthInc,
1957 (unsigned int) pCD->heightInc);
1959 if ((pCD->maxWidth != pCD->oldMaxWidth) ||
1960 (pCD->maxHeight != pCD->oldMaxHeight))
1963 * We've got a new maximum size.
1969 * If the configuration has changed, update client data
1971 * Changes in width or height cause maximized windows to return to
1972 * normal state and update normal geometry (x, y, width, height)
1977 (pCD->maxWidth == width) &&
1978 (pCD->maxHeight == height))
1980 /* we're changing to the new max size */
1984 changedValues |= (width != pCD->oldMaxWidth) ? CWWidth : 0;
1985 changedValues |= (height != pCD->oldMaxHeight) ? CWHeight : 0;
1987 if (!toNewMax && (changedValues & CWWidth)) {
1989 * Hacked to update maxWidth for 'vertical' max clients
1991 if (IS_MAXIMIZE_VERTICAL(pCD)) {
1992 pCD->maxWidth = width;
1994 pCD->clientWidth = width;
1995 if (changedValues & CWHeight) {
1997 * Hacked to update maxHeight for 'horizontal' max client
1999 if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
2000 pCD->maxHeight = height;
2002 pCD->clientHeight = height;
2005 pCD->clientHeight = pCD->oldMaxHeight;
2008 else if (!toNewMax && (changedValues & CWHeight)) {
2010 * Hacked to update maxHeight for 'horizontal' max client
2012 if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
2013 pCD->maxHeight = height;
2015 pCD->clientHeight = height;
2016 pCD->clientWidth = pCD->oldMaxWidth;
2020 if (width != pCD->clientWidth)
2023 * Hacked to update maxWidth for 'vertical' max clients
2025 if (IS_MAXIMIZE_VERTICAL(pCD)) {
2026 pCD->maxWidth = width;
2029 changedValues |= CWWidth;
2030 pCD->clientWidth = width;
2034 if (height != pCD->clientHeight)
2037 * Hacked to update maxHeight for 'horizontal' max client
2039 if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
2040 pCD->maxHeight = height;
2043 changedValues |= CWHeight;
2044 pCD->clientHeight = height;
2048 #ifndef CONFIG_RELATIVE_TO_CLIENT
2050 * If positionIsFrame or user initiated configuration request,
2051 * then adjust client position to by frame_width and frame_height.
2053 if (wmGD.positionIsFrame || (!clientRequest))
2055 xoff = pCD->clientOffset.x;
2056 yoff = pCD->clientOffset.y;
2061 * Changes in position update maximum geometry on maximized windows
2062 * if there was no change in size.
2064 if (pCD->maxConfig) {
2065 if (x != pCD->maxX) {
2066 changedValues |= CWX;
2067 if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2068 pCD->clientX = x + xoff;
2070 pCD->maxX = x + xoff;
2072 else if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2074 pCD->clientX = pCD->maxX;
2077 if (y != pCD->maxY) {
2078 changedValues |= CWY;
2079 if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2080 pCD->clientY = y + yoff;
2082 pCD->maxY = y + yoff;
2084 else if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2086 pCD->clientY = pCD->maxY;
2090 if (x + xoff != pCD->clientX) {
2091 changedValues |= CWX;
2092 pCD->clientX = x + xoff;
2095 if (y + yoff != pCD->clientY) {
2096 changedValues |= CWY;
2097 pCD->clientY = y + yoff;
2101 /* check if the window has reconfigured itself off the screen. */
2102 if (originallyOnScreen && !WindowIsOnScreen(pCD, &dx, &dy))
2106 changedValues |= CWX;
2112 changedValues |= CWY;
2119 * Resize the client window if necessary:
2122 if (changedValues & (CWWidth | CWHeight))
2128 /* maximized window resized, return to normal state */
2129 pCD->maxConfig = FALSE;
2130 pCD->clientState = NORMAL_STATE;
2134 XResizeWindow (DISPLAY, pCD->client, width, height);
2135 RegenerateClientFrame(pCD);
2137 if (changedValues & (CWX | CWY)) {
2141 * Fix for 5217 - If the request is from the client, use the clients
2142 * offsets instead of the static offsets
2146 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2147 pCD->maxX - pCD->clientOffset.x,
2148 pCD->maxY - pCD->clientOffset.y);
2152 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2153 pCD->maxX - offsetX,
2154 pCD->maxY - offsetY);
2162 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2163 pCD->clientX - pCD->clientOffset.x,
2164 pCD->clientY - pCD->clientOffset.y);
2168 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2169 pCD->clientX - offsetX,
2170 pCD->clientY - offsetY);
2175 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
2177 /* turn off subpanel behavior if moved */
2178 pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUBPANEL;
2180 #endif /* PANELIST */
2184 * Send a configure notify message if appropriate:
2185 * 1. rejected client configuration request.
2186 * 2. client request and move without resize
2190 if ((!changedValues && clientRequest) ||
2191 (changedValues && !(changedValues & (CWWidth | CWHeight))))
2193 SendConfigureNotify (pCD);
2197 * Try to send notice directly to icon box that the window
2201 if ((pCD->clientFlags & ICON_BOX) &&
2202 (changedValues & (CWWidth | CWHeight)))
2204 CheckIconBoxResize(pCD, changedValues, width, height);
2207 } /* END OF FUNCTION ProcessNewConfiguration */
2211 /*************************************<->*************************************
2213 * StartResizeConfig (pcd, pev)
2218 * Start resize of client window
2223 * pcd - pointer to client data
2224 * pev - pointer to event
2228 * return - true if configuration can begin, else false
2234 *************************************<->***********************************/
2236 Boolean StartResizeConfig (ClientData *pcd, XEvent *pev)
2238 Window grab_win, junk_win;
2240 int big_inc, tmp_inc;
2241 int junk, junkX, junkY;
2248 grab_win = GrabWin (pcd, pev);
2252 grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart),
2253 PGRAB_MASK, pev->xbutton.time, pcd, True);
2257 grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart),
2258 PGRAB_MASK, CurrentTime, pcd, True);
2268 /* continue with the configuration in progress (!!!) */
2273 * Set up static variables for succeeding events
2275 if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
2276 &pointerX, &pointerY, &junk, &junk, (unsigned int *)&junk))
2278 CancelFrameConfig (pcd); /* release grabs */
2281 wmGD.preMoveX = pointerX;
2282 wmGD.preMoveY = pointerY;
2285 offsetX = pcd->clientOffset.x;
2286 offsetY = pcd->clientOffset.y;
2289 * get window geometry information and convert to frame coordinates
2291 if (pcd->maxConfig) {
2292 resizeX = pcd->maxX;
2293 resizeY = pcd->maxY;
2294 resizeWidth = pcd->maxWidth;
2295 resizeHeight = pcd->maxHeight;
2298 resizeX = pcd->clientX;
2299 resizeY = pcd->clientY;
2300 resizeWidth = pcd->clientWidth;
2301 resizeHeight = pcd->clientHeight;
2303 ClientToFrame(pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
2305 /* save start values to see where we came from */
2308 startWidth = resizeWidth;
2309 startHeight = resizeHeight;
2311 /* get min and max frame sizes */
2312 minWidth = pcd->minWidth;
2313 minHeight = pcd->minHeight;
2315 ClientToFrame(pcd, &junkX, &junkY, &minWidth, &minHeight);
2318 * Hack to use maxHeightLimit and maxWidthLimit as the real max when
2319 * maximumClientSize is set to 'horizontal' or 'vertical', since
2320 * pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
2322 maxWidth = pcd->maxWidthLimit;
2323 maxHeight = pcd->maxHeightLimit;
2325 ClientToFrame(pcd, &junkX, &junkY, &maxWidth, &maxHeight);
2327 /* compute big increment values */
2328 big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
2330 tmp_inc = big_inc - big_inc%pcd->widthInc;
2331 if (tmp_inc > 5*pcd->widthInc)
2332 resizeBigWidthInc = tmp_inc;
2334 resizeBigWidthInc = 5*pcd->widthInc;
2336 tmp_inc = big_inc - big_inc%pcd->heightInc;
2337 if (tmp_inc > 5*pcd->heightInc)
2338 resizeBigHeightInc = tmp_inc;
2340 resizeBigHeightInc = 5*pcd->heightInc;
2342 /* pop up feedback window */
2343 if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
2345 DoFeedback (pcd, resizeX, resizeY, resizeWidth, resizeHeight,
2346 FB_SIZE, TRUE /* do size checks */);
2349 /* set configuring data */
2350 wmGD.configAction = RESIZE_CLIENT;
2351 wmGD.configButton = pev ? pev->xbutton.button: 0;
2355 } /* END OF FUNCTION StartResizeConfig */
2359 /*************************************<->*************************************
2361 * StartClientResize (pcd, pev)
2366 * Start resize of client window as invoked from menu
2371 * pcd - pointer to client data
2372 * pev - pointer to event
2380 * o This should only be called as the result of a Resize function
2381 * being selected from the system menu.
2383 *************************************<->***********************************/
2384 void StartClientResize (ClientData *pcd, XEvent *pev)
2387 /* do initial setup for resize */
2388 wmGD.configPart = FRAME_NONE; /* determined by later action */
2389 wmGD.configSet = False; /* don't know what it is yet */
2390 if (!StartResizeConfig (pcd, pev))
2392 /* resize could not be initiated */
2398 * Warp pointer to middle of window if started from the keyboard
2399 * or menu (no event).
2401 if ( !pev || pev->type == KeyPress )
2403 pointerX = resizeX + resizeWidth/2;
2404 pointerY = resizeY + resizeHeight/2;
2406 ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &pointerX, &pointerY);
2407 if (wmGD.enableWarp)
2409 XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd),
2410 0, 0, 0, 0, pointerX, pointerY);
2414 } /* END OF FUNCTION StartClientResize */
2417 /*************************************<->*************************************
2419 * StartClientMove (pcd, pev)
2424 * Handle move of client window as invoked from menu
2429 * pcd - pointer to client data
2430 * pev - pointer to event
2434 * Return - True if configuration was initiated, else False
2439 * o This should only be called as the result of a Move function
2440 * being selected from the system menu.
2442 *************************************<->***********************************/
2443 Boolean StartClientMove (ClientData *pcd, XEvent *pev)
2445 Window grab_win, junk_win;
2451 * Do our grabs if we're just starting out
2455 grab_win = GrabWin (pcd, pev);
2456 if (grab_win == ICON_FRAME_WIN(pcd))
2458 wmGD.movingIcon = True;
2463 grabbed = DoGrabs (grab_win, wmGD.configCursor,
2464 PGRAB_MASK, pev->xbutton.time, pcd, False);
2468 grabbed = DoGrabs (grab_win, wmGD.configCursor,
2469 PGRAB_MASK, CurrentTime, pcd, False);
2473 wmGD.movingIcon = False;
2480 * Set up static variables for succeeding events if we're not
2481 * entering with a motion event. If we are, we assume that the
2482 * preMove variables have been setup.
2484 if (pev && ((pev->type == ButtonPress) || (pev->type == ButtonRelease)))
2486 wmGD.preMoveX = pev->xbutton.x_root;
2487 wmGD.preMoveY = pev->xbutton.y_root;
2489 else if ((pev && (pev->type != MotionNotify)) || !pev)
2491 if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd),
2492 &junk_win, &junk_win,
2493 &(wmGD.preMoveX), &(wmGD.preMoveY),
2494 &junk, &junk, (unsigned int *)&junk))
2496 CancelFrameConfig (pcd);
2501 offsetX = pcd->clientOffset.x;
2502 offsetY = pcd->clientOffset.y;
2505 moveLastPointerX = wmGD.preMoveX;
2506 moveLastPointerY = wmGD.preMoveY;
2508 /* get frame window geometry */
2509 if (wmGD.movingIcon)
2511 moveWidth = ICON_WIDTH(pcd);
2512 moveHeight = ICON_HEIGHT(pcd);
2514 moveX = ICON_X(pcd);
2515 moveY = ICON_Y(pcd);
2517 if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
2519 /* get root coords of icon box bulletin board */
2520 XTranslateCoordinates(DISPLAY,
2521 XtWindow(P_ICON_BOX(pcd)->bBoardWidget), ROOT_FOR_CLIENT(pcd),
2522 0, 0, &moveIBbbX, &moveIBbbY, &child);
2527 else if (pcd->pSD->moveOpaque &&
2528 (ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
2529 (wmGD.keyboardFocus == pcd))
2531 HideActiveIconText ((WmScreenData *)NULL);
2536 if (pcd->maxConfig) { /* maximized */
2537 moveWidth = pcd->maxWidth;
2538 moveHeight = pcd->maxHeight;
2543 moveWidth = pcd->clientWidth;
2544 moveHeight = pcd->clientHeight;
2545 moveX = pcd->clientX;
2546 moveY = pcd->clientY;
2548 ClientToFrame (pcd, &moveX, &moveY, &moveWidth, &moveHeight);
2551 if (pcd->pSD->moveOpaque)
2553 opaqueMoveX = moveX;
2554 opaqueMoveY = moveY;
2558 * Warp pointer to middle of window if started from the menu (no event).
2560 if ( !pev || pev->type == KeyPress )
2562 moveLastPointerX = moveX + moveWidth/2;
2563 moveLastPointerY = moveY + moveHeight/2;
2565 ForceOnScreen (SCREEN_FOR_CLIENT(pcd),
2566 &moveLastPointerX, &moveLastPointerY);
2567 if (wmGD.enableWarp)
2569 XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd), 0, 0, 0, 0,
2570 moveLastPointerX, moveLastPointerY);
2574 /* pop up feedback window */
2575 if ( !wmGD.movingIcon && (wmGD.showFeedback & WM_SHOW_FB_MOVE))
2577 DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight,
2578 FB_POSITION, FALSE /* no size checks */);
2581 /* set configuring data */
2582 wmGD.configAction = MOVE_CLIENT;
2583 if (pev && pev->type != KeyPress)
2584 wmGD.configButton = pev->xbutton.button;
2586 wmGD.configButton = 0;
2592 } /* END OF FUNCTION StartClientMove */
2595 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2596 /*************************************<->*************************************
2603 * Sets Boolean grabServer to False
2615 * This will only get called when an automated test is running. The
2616 * purpose of this is to prevent mwm from grbbing the server, since
2617 * this confuses the automation input synthesis code
2619 *************************************<->***********************************/
2620 void SetGrabServer (void)
2624 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2627 /*************************************<->*************************************
2629 * DoGrabs (grab_win, cursor, pmask, grabTime, alwaysGrab)
2634 * Do the grabs for window configuration
2639 * grab_win - window to grab on
2640 * cursor - cursor shape to attach to the pointer
2642 * grabTime - time stamp
2652 *************************************<->***********************************/
2653 Boolean DoGrabs (Window grab_win, Cursor cursor, unsigned int pmask, Time grabTime, ClientData *pCD, Boolean alwaysGrab)
2660 root = ROOT_FOR_CLIENT(pCD);
2662 root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
2664 if (pCD && pCD->pSD->useIconBox && wmGD.movingIcon && P_ICON_BOX(pCD))
2666 if (pCD->pSD->useIconBox && wmGD.movingIcon && P_ICON_BOX(pCD))
2670 * Confine the pointer to the icon box clip window
2672 if (XGrabPointer(DISPLAY,
2674 FALSE, /* owner_events */
2676 GrabModeAsync, /* pointer_mode */
2677 GrabModeAsync, /* keyboard_mode */
2678 /* confine_to window */
2679 XtWindow(P_ICON_BOX(pCD)->clipWidget),
2681 grabTime) != GrabSuccess)
2689 * Just confine the pointer to the root window
2691 if (XGrabPointer(DISPLAY,
2693 FALSE, /* owner_events */
2695 GrabModeAsync, /* pointer_mode */
2696 GrabModeAsync, /* keyboard_mode */
2700 ROOT_FOR_CLIENT(pCD), /* confine_to window */
2703 grabTime) != GrabSuccess)
2710 * Don't grab keyboard away from menu widget to prevent
2711 * hosing of traversal.
2713 if (!wmGD.menuActive)
2715 if ((XGrabKeyboard(DISPLAY,
2717 FALSE, /* owner_events */
2718 GrabModeAsync, /* pointer_mode */
2719 GrabModeAsync, /* keyboard_mode */
2720 grabTime)) != GrabSuccess)
2722 XUngrabPointer (DISPLAY, CurrentTime);
2729 * If running automation version of mwm, do not grab the server, since
2730 * this will confuse the automation input synthesis code.
2732 # if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2733 if (grabServer == TRUE)
2734 # endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2736 if (wmGD.freezeOnConfig)
2740 if (!pCD || ((pCD->pSD->moveOpaque && alwaysGrab) ||
2741 (!(pCD->pSD->moveOpaque))))
2743 if ((pCD->pSD->moveOpaque && alwaysGrab) ||
2744 (!(pCD->pSD->moveOpaque)))
2747 XGrabServer(DISPLAY);
2752 } /* END OF FUNCTION DoGrabs */
2755 /*************************************<->*************************************
2775 *************************************<->***********************************/
2776 void UndoGrabs (void)
2779 MoveOutline(0, 0, 0, 0);
2780 XSync (DISPLAY, FALSE /*don't discard events*/);
2783 if (wmGD.freezeOnConfig) {
2784 XUngrabServer(DISPLAY);
2788 * Don't Ungrab keyboard away from menu widget to prevent
2789 * hosing of traversal.
2791 if (!wmGD.menuActive)
2792 XUngrabKeyboard (DISPLAY,CurrentTime);
2794 XUngrabPointer (DISPLAY, CurrentTime); /* event time NOT used */
2797 } /* END OF FUNCTION UndoGrabs */
2801 /*************************************<->*************************************
2803 * CancelFrameConfig (pcd)
2808 * Cance a frame configuration (move/resize) operation.
2813 * pcd - pointer to client data
2823 *************************************<->***********************************/
2824 void CancelFrameConfig (ClientData *pcd)
2827 /* remove keyboard, pointer, and server grabs */
2830 /* turn off feedback window */
2835 HideFeedbackWindow(pcd->pSD);
2837 /* make sure title bar is popped out */
2838 if ((wmGD.configAction == MOVE_CLIENT) &&
2839 (wmGD.gadgetClient == pcd) && (wmGD.gadgetDepressed == FRAME_TITLE))
2841 PopGadgetOut (pcd, FRAME_TITLE);
2842 FrameExposureProc(pcd); /* repaint frame */
2844 if ((pcd->pSD->moveOpaque) &&
2845 (wmGD.configAction == MOVE_CLIENT))
2848 if ((pcd->clientState == MINIMIZED_STATE) &&
2849 (!(pcd->pSD->useIconBox && P_ICON_BOX(pcd))))
2852 * Replace icon into pre-move position
2855 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
2856 ICON_X(pcd), ICON_Y(pcd));
2857 if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART))
2859 ShowActiveIconText(pcd);
2862 else if (! wmGD.movingIcon) /* we are not moving in the iconbox */
2864 XMoveWindow (DISPLAY, pcd->clientFrameWin,
2865 opaqueMoveX, opaqueMoveY);
2870 if (wmGD.configAction == MARQUEE_SELECT)
2872 dtSendMarqueeSelectionNotification(ACTIVE_PSD, DT_MARQUEE_SELECT_CANCEL,
2873 marqueeX, marqueeY, 0, 0);
2877 /* replace pointer if no motion events received */
2881 if (!anyMotion && wmGD.enableWarp) {
2882 XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd),
2883 0, 0, 0, 0, wmGD.preMoveX, wmGD.preMoveY);
2887 /* Clear configuration flags and data */
2888 wmGD.configAction = NO_ACTION;
2889 wmGD.configPart = FRAME_NONE;
2890 wmGD.configSet = False;
2892 wmGD.movingIcon = FALSE;
2894 /* set the focus back to a reasonable window */
2896 } /* END OF FUNCTION CancelFrameConfig */
2900 /*************************************<->*************************************
2902 * CheckEatButtonRelease (pcd, pev)
2907 * Set up to eat button releases if buttons are down.
2912 * pcd - pointer to client data
2913 * pev - pointer to key event that caused cancel
2923 *************************************<->***********************************/
2925 CheckEatButtonRelease (ClientData *pcd, XEvent *pev)
2931 if (pcd != (ClientData *)NULL)
2932 root = ROOT_FOR_CLIENT(pcd);
2934 root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
2938 if (pcd == (ClientData *) NULL)
2942 grab_win = GrabWin(pcd, pev);
2944 if ((pev->type == KeyPress || pev->type == KeyRelease) &&
2945 (pev->xbutton.state & ButtonMask))
2948 * Some buttons are down...
2949 * Set up conditions to wait for these buttons to go up.
2951 if (XGrabPointer(DISPLAY,
2953 False, /* owner_events */
2955 GrabModeAsync, /* pointer_mode */
2956 GrabModeAsync, /* keyboard_mode */
2958 root, /* confine_to window */
2960 ROOT_FOR_CLIENT(pcd), /* confine_to window */
2963 pev->xbutton.time) == GrabSuccess)
2965 EatButtonRelease (pev->xbutton.state & ButtonMask);
2971 /*************************************<->*************************************
2973 * EatButtonRelease (releaseButtons)
2978 * Eat up button release events
2983 * releaseButtons = button mask of button releases to eat
2993 *************************************<->***********************************/
2995 EatButtonRelease (unsigned int releaseButtons)
2997 unsigned int new_state;
3000 while (releaseButtons)
3003 PullExposureEvents ();
3005 XMaskEvent (DISPLAY, ButtonReleaseMask, &event);
3007 if (event.type == ButtonRelease)
3009 /* look at the state after this button is released */
3011 event.xbutton.state & ~ButtonStateBit(event.xbutton.button);
3013 if (!(new_state & releaseButtons))
3015 /* all the buttons we were waiting for have been
3019 XUngrabPointer (DISPLAY, event.xbutton.time);
3028 /*************************************<->*************************************
3030 * ButtonStateBit (button)
3035 * Converts a button number to a button state bit
3040 * button = button number (Button1, Button2, etc.)
3044 * Return = bit used in xbutton state field
3045 * (Button1Mask, Button2Mask,...)
3052 *************************************<->***********************************/
3054 ButtonStateBit (unsigned int button)
3056 #define MAX_BUTTON 5
3058 unsigned int button;
3059 unsigned int maskbit;
3062 static ButtonAssoc bmap[MAX_BUTTON] = {
3063 {Button1, Button1Mask},
3064 {Button2, Button2Mask},
3065 {Button3, Button3Mask},
3066 {Button4, Button4Mask},
3067 {Button5, Button5Mask},
3071 unsigned int rval = 0;
3073 for (i = 0; i < MAX_BUTTON; i++)
3075 if (bmap[i].button == button)
3077 rval = bmap[i].maskbit;
3086 /*************************************<->*************************************
3088 * ConfigCursor (frame_part)
3093 * return the config cursor that goes with the config part specified
3098 * frame_part - frame part id
3102 * return - cursor to use
3108 *************************************<->***********************************/
3109 Cursor ConfigCursor (int frame_part)
3113 switch (frame_part) {
3114 case FRAME_RESIZE_NW:
3115 cursor = wmGD.stretchCursors[STRETCH_NORTH_WEST];
3117 case FRAME_RESIZE_N:
3118 cursor = wmGD.stretchCursors[STRETCH_NORTH];
3120 case FRAME_RESIZE_NE:
3121 cursor = wmGD.stretchCursors[STRETCH_NORTH_EAST];
3123 case FRAME_RESIZE_E:
3124 cursor = wmGD.stretchCursors[STRETCH_EAST];
3126 case FRAME_RESIZE_SE:
3127 cursor = wmGD.stretchCursors[STRETCH_SOUTH_EAST];
3129 case FRAME_RESIZE_S:
3130 cursor = wmGD.stretchCursors[STRETCH_SOUTH];
3132 case FRAME_RESIZE_SW:
3133 cursor = wmGD.stretchCursors[STRETCH_SOUTH_WEST];
3135 case FRAME_RESIZE_W:
3136 cursor = wmGD.stretchCursors[STRETCH_WEST];
3139 cursor = wmGD.configCursor;
3144 } /* END OF FUNCTION ConfigCursor */
3147 /*************************************<->*************************************
3149 * ReGrabPointer (grab_win, grabTime)
3154 * Grab the pointer again to change the cursor
3160 * grabTime - time stamp
3169 *************************************<->***********************************/
3170 void ReGrabPointer (Window grab_win, Time grabTime)
3172 XGrabPointer(DISPLAY,
3174 FALSE, /* owner_events */
3176 GrabModeAsync, /* pointer_mode */
3177 GrabModeAsync, /* keyboard_mode */
3178 ACTIVE_ROOT, /* confine_to window */
3179 ConfigCursor((int)wmGD.configPart),
3182 } /* END OF FUNCTION ReGrabPointer */
3186 /*************************************<->*************************************
3188 * SetPointerResizePart (pcd, pev)
3193 * Sets the global configuration part for resize based on the current
3194 * configuration part and the location of the event
3199 * pcd - pointer to client data
3200 * pev - pointer to event
3205 * Return - TRUE if wmGD.configPart is a valid resize part
3210 * o Assumes the static data for resizing has been set up.
3211 *************************************<->***********************************/
3212 Boolean SetPointerResizePart (ClientData *pcd, XEvent *pev)
3217 newPart = ResizeType(pcd, pev); /* get part id for this event */
3218 grabTime = (pev) ? pev->xmotion.time : CurrentTime;
3220 switch (wmGD.configPart) {
3222 if (newPart == FRAME_NONE)
3223 return(FALSE); /* still not valid */
3225 wmGD.configPart = newPart;
3226 ReGrabPointer(pcd->clientFrameWin, grabTime);
3229 case FRAME_RESIZE_N:
3231 case FRAME_RESIZE_W:
3232 case FRAME_RESIZE_NW:
3233 wmGD.configPart = FRAME_RESIZE_NW;
3234 ReGrabPointer(pcd->clientFrameWin, grabTime);
3237 case FRAME_RESIZE_E:
3238 case FRAME_RESIZE_NE:
3239 wmGD.configPart = FRAME_RESIZE_NE;
3240 ReGrabPointer(pcd->clientFrameWin, grabTime);
3248 case FRAME_RESIZE_E:
3250 case FRAME_RESIZE_N:
3251 case FRAME_RESIZE_NE:
3252 wmGD.configPart = FRAME_RESIZE_NE;
3253 ReGrabPointer(pcd->clientFrameWin, grabTime);
3256 case FRAME_RESIZE_S:
3257 case FRAME_RESIZE_SE:
3258 wmGD.configPart = FRAME_RESIZE_SE;
3259 ReGrabPointer(pcd->clientFrameWin, grabTime);
3267 case FRAME_RESIZE_S:
3269 case FRAME_RESIZE_E:
3270 case FRAME_RESIZE_SE:
3271 wmGD.configPart = FRAME_RESIZE_SE;
3272 ReGrabPointer(pcd->clientFrameWin, grabTime);
3275 case FRAME_RESIZE_W:
3276 case FRAME_RESIZE_SW:
3277 wmGD.configPart = FRAME_RESIZE_SW;
3278 ReGrabPointer(pcd->clientFrameWin, grabTime);
3286 case FRAME_RESIZE_W:
3288 case FRAME_RESIZE_N:
3289 case FRAME_RESIZE_NW:
3290 wmGD.configPart = FRAME_RESIZE_NW;
3291 ReGrabPointer(pcd->clientFrameWin, grabTime);
3294 case FRAME_RESIZE_S:
3295 case FRAME_RESIZE_SW:
3296 wmGD.configPart = FRAME_RESIZE_SW;
3297 ReGrabPointer(pcd->clientFrameWin, grabTime);
3305 case FRAME_RESIZE_NW:
3306 case FRAME_RESIZE_NE:
3307 case FRAME_RESIZE_SW:
3308 case FRAME_RESIZE_SE:
3312 return(FALSE); /* not a valid resize part */
3316 } /* END OF FUNCTION SetPointerResizePart */
3319 /*************************************<->*************************************
3321 * ResizeType (pcd, pev)
3326 * Returns a resize part ID for an event outside of the current
3332 * pcd - pointer to client data
3333 * pev - pointer to event
3342 * o Assumes the static data for resizing has been set up.
3343 *************************************<->***********************************/
3344 int ResizeType (ClientData *pcd, XEvent *pev)
3348 if (!pev) return(FRAME_NONE);
3350 x = pev->xmotion.x_root;
3351 y = pev->xmotion.y_root;
3353 /* if inside all resize areas, then forget it */
3354 if ( (x > resizeX) &&
3356 (x < (resizeX + resizeWidth - 1)) &&
3357 (y < (resizeY + resizeHeight - 1)) )
3364 if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
3365 return (FRAME_RESIZE_NW);
3366 else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
3367 return (FRAME_RESIZE_SW);
3369 return (FRAME_RESIZE_W);
3373 if (x >= resizeX + resizeWidth - 1) {
3374 if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
3375 return (FRAME_RESIZE_NE);
3376 else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
3377 return (FRAME_RESIZE_SE);
3379 return (FRAME_RESIZE_E);
3384 if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
3385 return (FRAME_RESIZE_NW);
3386 else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
3387 return (FRAME_RESIZE_NE);
3389 return (FRAME_RESIZE_N);
3393 if (y >= resizeY + resizeHeight - 1) {
3394 if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
3395 return (FRAME_RESIZE_SW);
3396 else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
3397 return (FRAME_RESIZE_SE);
3399 return (FRAME_RESIZE_S);
3404 } /* END OF FUNCTION ResizeType */
3408 /*************************************<->*************************************
3410 * FixFrameValues (pcd, pfX, pfY, pfWidth, pfHeight, resizing)
3415 * Fix up the frame values so that they do not exceed maximum or minimum
3416 * size and that at least part of the frame is on screen
3421 * pcd - pointer to client data
3422 * pfX - pointer to frame x-coord
3423 * pfY - pointer to frame y-coord
3424 * pfWidth - pointer to frame width
3425 * pfHeight - pointer to frame height
3426 * resizing - check size constraints iff TRUE
3431 * *pfX - fixed up frame x-coord
3432 * *pfY - fixed up frame y-coord
3433 * *pfWidth - fixed up frame width
3434 * *pfHeight - fixed up frame height
3439 * 1. This could be more efficient
3440 * 2. Interactive resize with aspect ratio constraints may cause part of the
3441 * outline to disappear off screen. The critical case is when the title
3442 * bar disappears ABOVE the screen.
3444 *************************************<->***********************************/
3446 void FixFrameValues (ClientData *pcd, int *pfX, int *pfY, unsigned int *pfWidth, unsigned int *pfHeight, Boolean resizing)
3448 unsigned int lswidth;
3449 unsigned int oWidth, oHeight;
3453 * Fix size if resizing and not icon.
3456 if (resizing && !wmGD.movingIcon)
3458 FrameToClient(pcd, pfX, pfY, pfWidth, pfHeight);
3461 oHeight = *pfHeight;
3463 FixWindowSize (pcd, pfWidth, pfHeight, 1, 1);
3465 AdjustPos (pfX, pfY, oWidth, oHeight, *pfWidth, *pfHeight);
3467 ClientToFrame(pcd, pfX, pfY, pfWidth, pfHeight);
3471 * Don't move if we'd end up totally offscreen
3474 if (wmGD.movingIcon)
3476 lswidth = FRAME_BORDER_WIDTH(pcd);
3480 lswidth = pcd->frameInfo.lowerBorderWidth;
3482 if (lswidth < 5) lswidth = 5;
3484 if (wmGD.movingIcon && P_ICON_BOX(pcd))
3487 * Constrain outline to icon box
3489 /* left edge of outline */
3495 /* top of outline */
3501 /* right edge of outline */
3502 if (((int)*pfX) > ((int)clipX + (int)clipWidth - ((int)*pfWidth)))
3504 *pfX = clipX + clipWidth - *pfWidth;
3507 /* bottom edge of outline */
3508 if (((int)*pfY) > ((int)clipY + (int)clipHeight - ((int)*pfHeight)))
3510 *pfY = clipY + clipHeight - *pfHeight;
3517 * keep outline on screen
3521 /* keep right border on screen */
3522 if (*pfX < ((int) lswidth - (int) *pfWidth))
3524 *pfX = (int) lswidth - (int) *pfWidth;
3527 /* keep bottom border on screen */
3528 if (*pfY < ((int) lswidth - (int) *pfHeight))
3530 *pfY = (int) lswidth - (int) *pfHeight;
3533 /* keep left border on screen */
3534 if (*pfX > (DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
3537 *pfX = DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
3541 /* keep top border on screen */
3542 if (*pfY > (DisplayHeight(DISPLAY,SCREEN_FOR_CLIENT(pcd)) -
3545 *pfY = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
3550 } /* END OF FUNCTION FixFrameValues */
3554 /*************************************<->*************************************
3556 * ForceOnScreen (screen, pX, pY)
3561 * Correct (if necessary) the coords specified to make them on screen
3566 * screen - screen number
3567 * pX - pointer to x-coord
3568 * pY - pointer to y-coord
3572 * *pX - x-coord (on screen)
3573 * *pY - y-coord (on screen)
3580 *************************************<->***********************************/
3581 void ForceOnScreen (int screen, int *pX, int *pY)
3583 if (*pX >= (DisplayWidth(DISPLAY, screen)))
3584 *pX = DisplayWidth(DISPLAY, screen) - 1;
3588 if (*pY >= (DisplayHeight(DISPLAY, screen)))
3589 *pY = DisplayHeight(DISPLAY, screen) - 1;
3593 } /* END OF FUNCTION ForceOnScreen */
3596 /*************************************<->*************************************
3598 * SetPointerPosition (newX, newY, actualX, actualY)
3603 * Attempt to set the pointer to position at newX, newY.
3608 * newX - X-coordinate to set pointer at
3609 * newY - Y-coordinate to set pointer at
3614 * *actualX - actual X-coord of pointer on return
3615 * *actualY - actual Y-coord of pointer on return
3620 *************************************<->***********************************/
3621 void SetPointerPosition (int newX, int newY, int *actualX, int *actualY)
3629 if (wmGD.enableWarp)
3631 XWarpPointer(DISPLAY, None, ACTIVE_ROOT,
3632 0, 0, 0, 0, newX, newY);
3637 * Get pointer position
3638 * NOTE: if we are not warping, we don't want to do the Query pointer,
3639 * hence enableWarp is tested first.
3641 if (!wmGD.enableWarp ||
3642 !XQueryPointer (DISPLAY, ACTIVE_ROOT, &junk_win, &junk_win,
3643 actualX, actualY, &junk, &junk, (unsigned int *)&junk))
3646 /* failed to get pointer position or not warping, return something */
3651 } /* END OF FUNCTION SetPointerPositio */
3655 /*************************************<->*************************************
3657 * GetConfigEvent (display, window, mask, curX, curY, oX, oY,
3658 * oWidth, oHeight, pev,)
3663 * Get next configuration event
3668 * display - pointer to display
3669 * window - window to get event relative to
3670 * mask - event mask - acceptable events to return
3671 * pev - pointer to a place to put the event
3672 * curX - current X value of pointer
3673 * curY - current Y value of pointer
3674 * oX - X value of outline
3675 * oY - Y value of outline
3676 * oWidth - width of outline
3677 * oHeight - height of outline
3681 * *pev - event returned.
3686 *************************************<->***********************************/
3687 void GetConfigEvent (Display *display, Window window, unsigned long mask, int curX, int curY, int oX, int oY, unsigned oWidth, unsigned oHeight, XEvent *pev)
3689 Window root_ret, child_ret;
3690 int root_x, root_y, win_x, win_y;
3691 unsigned int mask_ret;
3695 Boolean eventToReturn = False;
3697 while (!eventToReturn)
3700 * Suck up pointer motion events
3703 while (XCheckWindowEvent(display, window, mask, pev))
3706 if (pev->type != MotionNotify)
3711 * Only poll if we are warping the pointer.
3712 * (uses PointerMotionHints exclusively).
3714 polling = wmGD.enableWarp;
3715 pollCount = CONFIG_POLL_COUNT;
3717 if (!gotEvent && (polling || !wmGD.freezeOnConfig))
3720 * poll for events and flash the frame outline
3721 * if not move opaque
3726 if (XCheckWindowEvent(display, window,
3727 (mask & ~PointerMotionMask), pev))
3733 if (!wmGD.freezeOnConfig && !wmGD.pActiveSD->moveOpaque)
3735 /* flash the outline if server is not grabbed */
3736 MoveOutline (oX, oY, oWidth, oHeight);
3739 if (!XQueryPointer (display, window, &root_ret, &child_ret,
3740 &root_x, &root_y, &win_x, &win_y, &mask_ret))
3742 continue; /* query failed, try again */
3745 if ((root_x != curX) || (root_y != curY))
3748 * Pointer moved to a new position.
3749 * Cobble a motion event together.
3750 * NOTE: SOME FIELDS NOT SET !!!
3753 pev->type = MotionNotify;
3754 /* pev->xmotion.serial = ??? */
3755 pev->xmotion.send_event = False;
3756 pev->xmotion.display = display;
3757 pev->xmotion.window = root_ret;
3758 pev->xmotion.subwindow = child_ret;
3759 pev->xmotion.time = CurrentTime; /* !!! !!! */
3760 pev->xmotion.x = root_x;
3761 pev->xmotion.y = root_y;
3762 pev->xmotion.x_root = root_x;
3763 pev->xmotion.y_root = root_y;
3764 /* pev->xmotion.state = ??? */
3765 /* pev->xmotion.is_hint = ???? */
3766 /* pev->xmotion.same_screen = ??? */
3768 eventToReturn = True;
3769 break; /* from while loop */
3771 else if (wmGD.freezeOnConfig)
3776 * No pointer motion in some time. Stop polling
3777 * and wait for next event.
3780 break; /* from while loop */
3786 if (!gotEvent && !polling && wmGD.freezeOnConfig)
3789 * Wait for next event on window
3792 XWindowEvent (display, window, mask, pev);
3798 eventToReturn = True;
3799 if (pev->type == MotionNotify &&
3800 pev->xmotion.is_hint == NotifyHint)
3803 * "Ack" the motion notify hint
3805 if ((XQueryPointer (display, window, &root_ret,
3806 &child_ret, &root_x, &root_y, &win_x,
3807 &win_y, &mask_ret)) &&
3808 ((root_x != curX) ||
3812 * The query pointer values say that the pointer
3813 * moved to a new location.
3815 pev->xmotion.window = root_ret;
3816 pev->xmotion.subwindow = child_ret;
3817 pev->xmotion.x = root_x;
3818 pev->xmotion.y = root_y;
3819 pev->xmotion.x_root = root_x;
3820 pev->xmotion.y_root = root_y;
3825 * Query failed. Change curX to force position
3826 * to be returned on first sucessful query.
3828 eventToReturn = False;
3835 } /* END OF FUNCTION GetConfigEvent */
3838 /*************************************<->*************************************
3840 * SetOutline (pOutline, x, y, width, height, fatness)
3845 * Sets the outline of for config/move/placement operations
3850 * pOutline - ptr to outline structure to fill in
3851 * x - x of upper-left corner of outline
3852 * y - y of upper-left corner of outline
3853 * width - width of outline.
3854 * height - height of outline.
3855 * fatness - pixel-width of outline
3862 * o Be sure that pOutline points to a big enough area of memory
3863 * for the outline to be set!
3865 *************************************<->***********************************/
3867 void SetOutline (XSegment *pOutline, int x, int y, unsigned int width, unsigned int height, int fatness)
3871 for (i=0; i<fatness; i++)
3875 pOutline->x2 = x + width -1;
3878 pOutline->x1 = x + width -1;
3880 pOutline->x2 = x + width -1;
3881 pOutline++->y2 = y + height - 1;
3883 pOutline->x1 = x + width -1;
3884 pOutline->y1 = y + height - 1;
3886 pOutline++->y2 = y + height - 1;
3889 pOutline->y1 = y + height - 1;
3894 * Modify values for next pass (if any)
3895 * Next outline will be on inside of current one.
3903 } /* END OF FUNCTION SetOutline */
3906 /*************************************<->*************************************
3908 * AdjustPos (pX, pY, oWidth, oHeight, nWidth, nHeight)
3913 * Adjusts the position according to wmGD.configPart and any change in
3919 * pX, pY -- pointers to positions
3920 * oWidth, oHeight -- original dimensions
3921 * nWidth, nHeight -- new dimensions
3926 * pX, pY -- pointers to adjusted positions
3931 *************************************<->***********************************/
3933 void AdjustPos (int *pX, int *pY, unsigned int oWidth, unsigned int oHeight, unsigned int nWidth, unsigned int nHeight)
3935 switch (wmGD.configPart)
3937 case FRAME_RESIZE_NW:
3938 /* anchor lower right corner */
3939 *pX += oWidth - nWidth;
3940 *pY += oHeight - nHeight;
3943 case FRAME_RESIZE_N:
3945 *pY += oHeight - nHeight;
3948 case FRAME_RESIZE_NE:
3949 /* anchor lower left corner */
3950 *pY += oHeight - nHeight;
3953 case FRAME_RESIZE_E:
3954 /* anchor left side */
3957 case FRAME_RESIZE_SE:
3958 /* anchor upper left corner */
3961 case FRAME_RESIZE_S:
3965 case FRAME_RESIZE_SW:
3966 /* anchor upper right corner */
3967 *pX += oWidth - nWidth;
3970 case FRAME_RESIZE_W:
3971 /* anchor right side */
3972 *pX += oWidth - nWidth;
3979 } /* END OF FUNCTION AdjustPos */
3983 /*************************************<->*************************************
3985 * GrabWin (pcd, pev)
3990 * return window to do grab on for config operation
3995 * pcd - ptr to client data
3996 * pev - ptr to event
4006 *************************************<->***********************************/
4007 Window GrabWin (ClientData *pcd, XEvent *pev)
4012 * The grab window is the icon if the client is minimized
4013 * or if the event was on a "normalized" icon in the icon box.
4016 if ((pcd->clientState == MINIMIZED_STATE) ||
4017 (pcd->pSD->useIconBox && pev &&
4018 ((pev->xany.window == ICON_FRAME_WIN(pcd)) ||
4019 (pev->xany.window == ACTIVE_ICON_TEXT_WIN))))
4021 grab_win = ICON_FRAME_WIN(pcd);
4024 (pev->xany.window == pcd->clientFrameWin ||
4025 pev->xany.window == pcd->clientBaseWin ))
4027 grab_win = pcd->clientFrameWin;
4029 else if (pcd->pSD->useIconBox &&
4031 wmGD.grabContext == F_SUBCONTEXT_IB_WICON)
4033 grab_win = ICON_FRAME_WIN(pcd);
4037 grab_win = pcd->clientFrameWin;
4042 } /* END OF FUNCTION GrabWin */
4045 /*************************************<->*************************************
4047 * HandleMarqueeSelect (pSD, event)
4052 * Does a marquee selection on the root window
4063 * Selection info is dumped into a root window property:
4064 * _DT_MARQUEE_SELECTION
4066 *************************************<->***********************************/
4068 HandleMarqueeSelect (WmScreenData *pSD, XEvent *pev)
4074 grab_win = RootWindow (DISPLAY, pSD->screen);
4077 while (!bDone && (wmGD.configAction == MARQUEE_SELECT))
4079 if (!pev) /* first time through will already have event */
4083 GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
4084 pointerX, pointerY, resizeX, resizeY,
4085 resizeWidth, resizeHeight, &event);
4088 if (pev->type == MotionNotify)
4090 pointerX = pev->xmotion.x_root;
4091 pointerY = pev->xmotion.y_root;
4092 UpdateMarqueeSelectData (pSD);
4094 else if (pev->type == KeyPress) {
4099 bDone = HandleMarqueeKeyPress (pSD, pev);
4101 else if (pev->type == ButtonRelease) {
4104 * Update (x,y) to the location of the button release
4106 pointerX = pev->xbutton.x_root;
4107 pointerY = pev->xbutton.y_root;
4108 UpdateMarqueeSelectData (pSD);
4109 CompleteFrameConfig ((ClientData *)NULL, pev);
4114 continue; /* ignore this event */
4119 MoveOutline (marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4122 pev = NULL; /* reset event pointer */
4126 } /* END OF FUNCTION HandleMarqueeSelect */
4129 /*************************************<->*************************************
4131 * StartMarqueeSelect ()
4136 * Start marquee selection on root window
4149 *************************************<->***********************************/
4151 StartMarqueeSelect(WmScreenData *pSD, XEvent *pev)
4153 Window grab_win, junk_win;
4156 int junk, junkX, junkY;
4158 if (!pSD->bMarqueeSelectionInitialized)
4161 * If we haven't initialized the marquee selection messaging
4162 * then do so here before we do any grabs. Sending a dummy
4165 * (If we move off of ICCCM messaging, then this can go away.)
4167 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END,
4169 pSD->bMarqueeSelectionInitialized = True;
4177 grab_win = RootWindow (DISPLAY, pSD->screen);
4181 grabbed = DoGrabs (grab_win, wmGD.configCursor,
4182 PGRAB_MASK, pev->xbutton.time, NULL, True);
4186 grabbed = DoGrabs (grab_win, wmGD.configCursor,
4187 PGRAB_MASK, CurrentTime, NULL, True);
4197 /* continue with the configuration in progress (!!!) */
4202 * Set up static variables for succeeding events
4204 if ((pev->type == ButtonPress) || (pev->type == ButtonRelease))
4206 pointerX = pev->xbutton.x_root;
4207 pointerY = pev->xbutton.y_root;
4209 else if (!XQueryPointer (DISPLAY, pSD->rootWindow,
4210 &junk_win, &junk_win,
4211 &pointerX, &pointerY,
4212 &junk, &junk, (unsigned int *)&junk))
4214 CancelFrameConfig ((ClientData *)NULL); /* release grabs */
4218 /* save start values to see where we came from */
4219 marqueeX = startX = pointerX;
4220 marqueeY = startY = pointerY;
4221 marqueeWidth0 = marqueeWidth = 0;
4222 marqueeHeight0 = marqueeHeight = 0;
4223 marqueeAnchor = ANCHOR_NW;
4225 /* compute increment value for dynamic update */
4226 big_inc = DisplayWidth (DISPLAY, pSD->screen) / 20;
4228 /* set configuring data */
4229 wmGD.configAction = MARQUEE_SELECT;
4230 wmGD.configButton = pev ? pev->xbutton.button: 0;
4232 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_BEGIN,
4233 marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4235 } /* END OF FUNCTION StartMarqueeSelect */
4238 /*************************************<->*************************************
4240 * UpdateMarqueeSelectData ()
4248 * pSD - pointer to screen data
4256 *************************************<->***********************************/
4257 void UpdateMarqueeSelectData (WmScreenData *pSD)
4259 /* validate and update anchor point and marquee data */
4261 switch (marqueeAnchor)
4264 marqueeWidth = pointerX - marqueeX;
4265 marqueeHeight = pointerY - marqueeY;
4267 if (marqueeWidth < 0)
4269 marqueeWidth = -marqueeWidth;
4270 marqueeX = pointerX;
4272 if (marqueeHeight < 0)
4274 marqueeHeight = -marqueeHeight;
4275 marqueeY = pointerY;
4276 marqueeAnchor = ANCHOR_SE;
4280 marqueeAnchor = ANCHOR_NE;
4283 else if (marqueeHeight < 0)
4285 marqueeHeight = -marqueeHeight;
4286 marqueeY = pointerY;
4287 marqueeAnchor = ANCHOR_SW;
4292 marqueeWidth += marqueeX - pointerX;
4293 marqueeHeight = pointerY - marqueeY;
4294 marqueeX = pointerX;
4296 if (marqueeWidth < 0)
4298 marqueeWidth = -marqueeWidth;
4299 marqueeX = pointerX - marqueeWidth;
4301 if (marqueeHeight < 0)
4303 marqueeHeight = -marqueeHeight;
4304 marqueeY = pointerY;
4305 marqueeAnchor = ANCHOR_SW;
4309 marqueeAnchor = ANCHOR_NW;
4312 else if (marqueeHeight < 0)
4314 marqueeHeight = -marqueeHeight;
4315 marqueeY = pointerY;
4316 marqueeAnchor = ANCHOR_SE;
4321 marqueeWidth += marqueeX - pointerX;
4322 marqueeHeight += marqueeY - pointerY;
4323 marqueeX = pointerX;
4324 marqueeY = pointerY;
4326 if (marqueeWidth < 0)
4328 marqueeWidth = -marqueeWidth;
4329 marqueeX = pointerX - marqueeWidth;
4331 if (marqueeHeight < 0)
4333 marqueeHeight = -marqueeHeight;
4334 marqueeY = pointerY - marqueeHeight;
4335 marqueeAnchor = ANCHOR_NW;
4339 marqueeAnchor = ANCHOR_SW;
4342 else if (marqueeHeight < 0)
4344 marqueeHeight = -marqueeHeight;
4345 marqueeY = pointerY - marqueeHeight;
4346 marqueeAnchor = ANCHOR_NE;
4351 marqueeWidth = pointerX - marqueeX;
4352 marqueeHeight += marqueeY - pointerY;
4353 marqueeY = pointerY;
4355 if (marqueeWidth < 0)
4357 marqueeWidth = -marqueeWidth;
4358 marqueeX = pointerX;
4360 if (marqueeHeight < 0)
4362 marqueeHeight = -marqueeHeight;
4363 marqueeY = pointerY - marqueeHeight;
4364 marqueeAnchor = ANCHOR_NE;
4368 marqueeAnchor = ANCHOR_SE;
4371 else if (marqueeHeight < 0)
4373 marqueeHeight = -marqueeHeight;
4374 marqueeY = pointerY - marqueeHeight;
4375 marqueeAnchor = ANCHOR_NW;
4380 if ((wmGD.marqueeSelectGranularity > 0) &&
4381 ((ABS(marqueeWidth-marqueeWidth0) > wmGD.marqueeSelectGranularity) ||
4382 (ABS(marqueeHeight-marqueeHeight0)>wmGD.marqueeSelectGranularity)))
4384 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_CONTINUE,
4385 marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4387 marqueeWidth0 = marqueeWidth;
4388 marqueeHeight0 = marqueeHeight;
4393 /*************************************<->*************************************
4395 * HandleMarqueeKeyPress (pSD, pev)
4400 * Handles keypress events during resize of window
4405 * pSD - pointer to screen data
4406 * pev - pointer to event
4411 * Return - True if this event completes (or cancels) resizing
4417 *************************************<->***********************************/
4418 Boolean HandleMarqueeKeyPress (WmScreenData *pSD, XEvent *pev)
4426 * Compress repeated keys
4429 while (keyMult <= 10 &&
4430 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
4436 keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
4437 control = (pev->xkey.state & ControlMask) != 0;
4442 CompleteFrameConfig ((ClientData *)NULL, pev);
4446 CancelFrameConfig ((ClientData *)NULL);
4447 CheckEatButtonRelease ((ClientData *)NULL, pev);
4451 return (False); /* ignore this key */
4453 } /* end switch(keysym) */
4455 } /* END OF FUNCTION HandleResizeKeyPress */