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 libraries 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.
31 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
36 #include "WmGlobal.h" /* This should be the first include */
40 #include <X11/keysymdef.h>
43 #define MOVE_OUTLINE_WIDTH 2
45 #define CONFIG_MASK (KeyPressMask|ButtonPressMask|\
46 ButtonReleaseMask|PointerMotionMask)
47 #define PGRAB_MASK (ButtonPressMask|ButtonReleaseMask|\
48 PointerMotionMask|PointerMotionHintMask)
64 #define ABS(x) ((x)>0?(x):(-(x)))
67 /* number of times to poll before blocking on a config event */
69 #define CONFIG_POLL_COUNT 300
71 /* mask for all buttons */
73 (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
76 * include extern functions
78 #include "WmWinConf.h"
83 #include "WmFeedback.h"
84 #include "WmFunction.h"
88 #include "WmIconBox.h"
89 #include "WmKeyFocus.h"
90 #include "WmProtocol.h"
91 #include "WmWinInfo.h"
98 * These statics are set up at the initiation of a configuration
99 * operation and used for succeeding events.
102 static int pointerX = -1;
103 static int pointerY = -1;
105 static int offsetX = 0;
106 static int offsetY = 0;
108 static int resizeX, resizeY; /* root coords of UL corner of frame */
109 static unsigned int resizeWidth, resizeHeight; /* size of frame */
110 static unsigned int resizeBigWidthInc, resizeBigHeightInc;
111 static int startX, startY;
112 static unsigned int startWidth, startHeight;
113 static unsigned int minWidth, minHeight, maxHeight, maxWidth;
114 static int marqueeX, marqueeY; /* root coords of UL corner of are */
115 static long marqueeWidth, marqueeHeight; /* size of area */
116 static unsigned int marqueeAnchor; /* id of anchor corner */
117 static long marqueeWidth0, marqueeHeight0; /* old size of area */
119 static int opaqueMoveX = 0; /* for cancel request on opaque moves */
120 static int opaqueMoveY = 0;
121 static int moveX = 0; /* root coords of UL corner of frame */
122 static int moveY = 0;
123 static int moveIBbbX = 0; /* root coords of icon box bulletin board */
124 static int moveIBbbY = 0;
125 static unsigned int moveWidth = 0; /* size of frame */
126 static unsigned int moveHeight = 0;
127 static int moveLastPointerX = 0; /* last pointer position */
128 static int moveLastPointerY= 0;
130 static Boolean anyMotion = FALSE;
131 static Boolean configGrab = FALSE;
133 Dimension clipWidth = 0;
134 Dimension clipHeight = 0;
140 /*************************************<->*************************************
142 * GetClipDimensions (pcd, fromRoot)
151 * pcd - pointer to client data
160 *************************************<->***********************************/
161 void GetClipDimensions (ClientData *pCD, Boolean fromRoot)
169 XtSetArg (getArgs[i], XmNwidth, (XtArgVal) &clipWidth ); i++;
170 XtSetArg (getArgs[i], XmNheight, (XtArgVal) &clipHeight ); i++;
171 XtSetArg (getArgs[i], XmNx, (XtArgVal) &tmpX ); i++;
172 XtSetArg (getArgs[i], XmNy, (XtArgVal) &tmpY ); i++;
174 XtGetValues (P_ICON_BOX(pCD)->clipWidget, getArgs, i);
178 XtTranslateCoords(P_ICON_BOX(pCD)->scrolledWidget,
188 } /* END OF FUNCTION GetClipDimensions */
192 /*************************************<->*************************************
194 * HandleClientFrameMove (pcd, pev)
199 * Provide visual feedback of interactive moving of the window.
204 * pcd - pointer to client data
205 * pev - pointer to event
214 *************************************<->***********************************/
215 void HandleClientFrameMove (ClientData *pcd, XEvent *pev)
217 int tmpX, tmpY, warpX, warpY;
220 Boolean control, moveDone;
222 int big_inc, keyMultiplier;
224 XEvent event, KeyEvent;
233 big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
237 * Do our grabs and initial setup if we're just starting out
240 if (!StartClientMove (pcd, pev))
242 /* configuration was not initiated */
247 grab_win = GrabWin (pcd, pev);
250 if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
252 GetClipDimensions (pcd, True);
261 /* handle the event we were called with first */
267 GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
268 moveLastPointerX, moveLastPointerY, moveX, moveY,
269 moveWidth, moveHeight, &event);
272 if (pev->type == KeyPress)
275 while (keyMultiplier <= big_inc &&
276 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
282 keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
283 control = (pev->xkey.state & ControlMask) != 0;
288 tmpX = keyMultiplier * ((control) ? (-big_inc) : (-1));
292 tmpY = keyMultiplier * ((control) ? (-big_inc) : (-1));
296 tmpX = keyMultiplier * ((control) ? big_inc : 1);
300 tmpY = keyMultiplier * ((control) ? big_inc : 1);
304 CompleteFrameConfig (pcd, pev);
308 CancelFrameConfig (pcd);
309 CheckEatButtonRelease (pcd, pev);
317 warpX = moveLastPointerX + tmpX;
318 warpY = moveLastPointerY + tmpY;
320 ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
322 if ((warpX != moveLastPointerX) || (warpY != moveLastPointerY))
324 SetPointerPosition (warpX, warpY, &newX, &newY);
326 tmpX = newX - moveLastPointerX;
327 tmpY = newY - moveLastPointerY;
328 moveLastPointerX = newX;
329 moveLastPointerY = newY;
336 * make like motion event and move frame.
343 else if (pev->type == ButtonRelease)
346 * Update (x,y) to the location of the button release
348 moveX += pev->xbutton.x_root - moveLastPointerX;
349 moveY += pev->xbutton.y_root - moveLastPointerY;
351 CompleteFrameConfig (pcd, pev);
354 else if (pev->type == MotionNotify)
356 tmpX = pev->xmotion.x_root - moveLastPointerX;
357 tmpY = pev->xmotion.y_root - moveLastPointerY;
358 moveLastPointerX = pev->xmotion.x_root;
359 moveLastPointerY = pev->xmotion.y_root;
365 /* draw outline if there is something to draw */
367 FixFrameValues (pcd, &moveX, &moveY, &moveWidth, &moveHeight,
368 FALSE /* no size checks */);
369 if (pcd->pSD->moveOpaque)
371 MoveOpaque (pcd, moveX, moveY, moveWidth, moveHeight);
375 MoveOutline(moveX, moveY, moveWidth, moveHeight);
378 if ( !wmGD.movingIcon &&
379 (wmGD.showFeedback & WM_SHOW_FB_MOVE))
381 DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight,
382 (unsigned long) 0, FALSE /* no size checks */);
387 } /* END OF FUNCTION HandleClientFrameMove */
391 /*************************************<->*************************************
393 * UpdateAndDrawResize ()
401 * pcd - pointer to client data
409 *************************************<->***********************************/
410 void UpdateAndDrawResize (ClientData *pcd)
412 int tmpHeight, tmpWidth;
415 * Handle a motion event or a keypress that's like a motion
421 switch (wmGD.configPart) {
422 case FRAME_RESIZE_NW:
424 case FRAME_RESIZE_NE:
425 tmpHeight = (int) startHeight + (startY - pointerY);
426 if (tmpHeight < (int) minHeight)
428 resizeHeight = minHeight;
429 resizeY = startY + startHeight - minHeight;
431 else if (pcd->pSD->limitResize
432 && (tmpHeight > (int) maxHeight)
433 && (!(pcd->clientFlags & ICON_BOX)))
435 resizeHeight = maxHeight;
436 resizeY = startY + startHeight - maxHeight;
440 resizeHeight = (unsigned int) tmpHeight;
445 case FRAME_RESIZE_SW:
447 case FRAME_RESIZE_SE:
449 tmpHeight = pointerY - startY + 1;
450 if (tmpHeight < (int) minHeight)
452 resizeHeight = minHeight;
454 else if (pcd->pSD->limitResize
455 && (tmpHeight > (int) maxHeight)
456 && (!(pcd->clientFlags & ICON_BOX)))
458 resizeHeight = maxHeight;
462 resizeHeight = (unsigned int) tmpHeight;
468 resizeHeight = startHeight;
475 switch (wmGD.configPart) {
476 case FRAME_RESIZE_NW:
478 case FRAME_RESIZE_SW:
479 tmpWidth = (int) startWidth + (startX - pointerX);
480 if (tmpWidth < (int) minWidth)
482 resizeWidth = minWidth;
483 resizeX = startX + startWidth - minWidth;
485 else if (pcd->pSD->limitResize
486 && (tmpWidth > (int) maxWidth)
487 && (!(pcd->clientFlags & ICON_BOX)))
489 resizeWidth = maxWidth;
490 resizeX = startX + startWidth - maxWidth;
494 resizeWidth = (unsigned int) tmpWidth;
499 case FRAME_RESIZE_NE:
501 case FRAME_RESIZE_SE:
503 tmpWidth = pointerX - startX + 1;
504 if (tmpWidth < (int) minWidth)
506 resizeWidth = minWidth;
508 else if (pcd->pSD->limitResize
509 && (tmpWidth > (int) maxWidth)
510 && (!(pcd->clientFlags & ICON_BOX)))
512 resizeWidth = maxWidth;
516 resizeWidth = (unsigned int) tmpWidth;
522 resizeWidth = startWidth;
526 FixFrameValues (pcd, &resizeX, &resizeY, &resizeWidth,
527 &resizeHeight, TRUE /* do size checks */);
528 MoveOutline (resizeX, resizeY, resizeWidth, resizeHeight);
529 if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
531 DoFeedback(pcd, resizeX, resizeY, resizeWidth, resizeHeight,
532 (unsigned long) 0, TRUE /* do size checks */);
537 /*************************************<->*************************************
539 * HandleClientFrameResize (pcd, pev)
544 * Provide visual feedback of interactive resizing of the window.
549 * pcd - pointer to client data
550 * pev - pointer to event
559 * o The window sizes refer to the frame, not the client window.
561 *************************************<->***********************************/
562 void HandleClientFrameResize (ClientData *pcd, XEvent *pev)
570 * Do our grabs the first time through
573 if (StartResizeConfig (pcd, pev))
579 /* resize could not be initiated */
584 grab_win = GrabWin (pcd, pev);
589 if (!pev) /* first time through will already have event */
593 GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
594 pointerX, pointerY, resizeX, resizeY,
595 resizeWidth, resizeHeight, &event);
598 if (pev->type == MotionNotify)
600 pointerX = pev->xmotion.x_root;
601 pointerY = pev->xmotion.y_root;
605 * Really start resizing once the pointer hits a resize area
606 * (This only applies to accelerator and keyboard resizing!)
608 if (!wmGD.configSet && !SetPointerResizePart (pcd, pev)) {
610 continue; /* ignore this event */
613 else if (pev->type == KeyPress) {
618 resizeDone = HandleResizeKeyPress (pcd, pev);
620 else if (pev->type == ButtonRelease) {
623 * Update (x,y) to the location of the button release
625 pointerX = pev->xbutton.x_root;
626 pointerY = pev->xbutton.y_root;
627 UpdateAndDrawResize(pcd);
629 CompleteFrameConfig (pcd, pev);
634 continue; /* ignore this event */
639 UpdateAndDrawResize(pcd);
642 pev = NULL; /* reset event pointer */
646 } /* END OF FUNCTION HandleClientFrameResize */
650 /*************************************<->*************************************
652 * HandleResizeKeyPress (pcd, pev)
657 * Handles keypress events during resize of window
662 * pcd - pointer to client data
663 * pev - pointer to event
668 * Return - True if this event completes (or cancels) resizing
674 *************************************<->***********************************/
675 Boolean HandleResizeKeyPress (ClientData *pcd, XEvent *pev)
679 int warpX, warpY, currentX = 0, currentY = 0, newX, newY;
685 * Compress repeated keys
688 while (keyMult <= 10 &&
689 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
695 keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
696 control = (pev->xkey.state & ControlMask) != 0;
700 switch (wmGD.configPart) {
702 wmGD.configPart = FRAME_RESIZE_W;
703 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
704 warpY = resizeY + resizeHeight/2;
705 warpX = resizeX + ((control) ?
706 (-resizeBigWidthInc) :
711 wmGD.configPart = FRAME_RESIZE_NW;
712 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
713 warpX = resizeX + ((control) ?
714 (-resizeBigWidthInc) :
720 wmGD.configPart = FRAME_RESIZE_SW;
721 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
722 warpX = resizeX + ((control) ?
723 (-resizeBigWidthInc) :
729 warpX = pointerX + ((control) ?
730 (-resizeBigWidthInc * keyMult) :
731 (-pcd->widthInc * keyMult));
738 switch (wmGD.configPart) {
740 wmGD.configPart = FRAME_RESIZE_N;
741 warpX = resizeX + resizeWidth/2;
742 warpY = resizeY + ((control) ?
743 (-resizeBigHeightInc) :
745 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
749 wmGD.configPart = FRAME_RESIZE_NW;
750 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
752 warpY = resizeY + ((control) ?
753 (-resizeBigHeightInc) :
758 wmGD.configPart = FRAME_RESIZE_NE;
759 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
761 warpY = resizeY + ((control) ?
762 (-resizeBigHeightInc) :
768 warpY = pointerY + ((control) ?
769 (-resizeBigHeightInc * keyMult) :
770 (-pcd->heightInc * keyMult));
776 switch (wmGD.configPart) {
778 wmGD.configPart = FRAME_RESIZE_E;
779 warpY = resizeY + resizeHeight/2;
780 warpX = resizeX + resizeWidth - 1 +
781 ((control) ? resizeBigWidthInc :
783 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
787 wmGD.configPart = FRAME_RESIZE_NE;
788 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
789 warpX = resizeX + resizeWidth - 1 +
790 ((control) ? resizeBigWidthInc :
796 wmGD.configPart = FRAME_RESIZE_SE;
797 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
798 warpX = resizeX + resizeWidth - 1 +
799 ((control) ? resizeBigWidthInc :
805 warpX = pointerX + ((control) ?
806 (resizeBigWidthInc * keyMult) :
807 (pcd->widthInc * keyMult));
814 switch (wmGD.configPart) {
816 wmGD.configPart = FRAME_RESIZE_S;
817 warpX = resizeX + resizeWidth/2;
818 warpY = resizeY + resizeHeight - 1 +
819 ((control) ? resizeBigHeightInc :
821 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
825 wmGD.configPart = FRAME_RESIZE_SE;
826 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
828 warpY = resizeY + resizeHeight - 1 +
829 ((control) ? resizeBigHeightInc :
834 wmGD.configPart = FRAME_RESIZE_SW;
835 ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
837 warpY = resizeY + resizeHeight - 1 +
838 ((control) ? resizeBigHeightInc :
844 warpY = pointerY + ((control) ?
845 (resizeBigHeightInc * keyMult) :
846 (pcd->heightInc * keyMult));
852 CompleteFrameConfig (pcd, pev);
856 CancelFrameConfig (pcd);
857 CheckEatButtonRelease (pcd, pev);
861 return (False); /* ignore this key */
863 } /* end switch(keysym) */
866 * Make sure the new pointer position is on screen before doing
867 * the warp. Warp only if the pointer position changes.
872 ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
875 * Don't query pointer if enable warp is off.
877 if (!wmGD.enableWarp ||
878 XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
879 ¤tX, ¤tY, &junk, &junk, (unsigned int *)&junk))
881 if ( (warpX != currentX) || (warpY != currentY) )
883 SetPointerPosition (warpX, warpY, &newX, &newY);
889 } /* END OF FUNCTION HandleResizeKeyPress */
892 /*************************************<->*************************************
894 * DoFeedback (pcd, x, y, width, height, newStyle, resizing)
899 * Start or update feedback of size/position info
904 * pcd - pointer to client data
909 * newStyle - style flags.
910 * resizing - check size constraints iff TRUE
919 * o If newStyle has FB_POSITION and/or FB_SIZE bits set, then it is
920 * assumed that this is an initial call and a feedback window of the
921 * desired style should be popped up. If newStyle is zero, then it
922 * is assumed that the feedback window is already up and the values
923 * passed in are updates.
925 *************************************<->***********************************/
926 void DoFeedback (ClientData *pcd, int x, int y, unsigned int width, unsigned int height, unsigned long newStyle, Boolean resizing)
930 unsigned int cwidth, cheight;
932 /* compute client window coordinates from frame coordinates */
933 FrameToClient (pcd, &cx, &cy, &width, &height);
935 /* use frame (not client) position if user wishes it */
936 if (wmGD.positionIsFrame) {
941 /* If resizing, make sure configuration is valid. */
944 FixWindowConfiguration (pcd, &width, &height,
945 (unsigned int) pcd->widthInc,
946 (unsigned int) pcd->heightInc);
950 * Put size in client specific units. Do not include base into calculations
951 * when increment is not specified (i.e. = 1).
953 cwidth = (width - ((pcd->widthInc==1) ? 0 : pcd->baseWidth))
955 cheight = (height - ((pcd->heightInc==1) ? 0 : pcd->baseHeight))
959 ShowFeedbackWindow (pcd->pSD, cx, cy, cwidth, cheight, newStyle);
962 UpdateFeedbackInfo (pcd->pSD, cx, cy, cwidth, cheight);
964 } /* END OF FUNCTION DoFeedback */
968 /*************************************<->*************************************
975 * Prevents icons in the icon box from being moved outside the clip window
980 * pcd - pointer to client data
991 *************************************<->***********************************/
993 Boolean CheckVisualPlace (ClientData *pCD, int tmpX, int tmpY)
1000 GetClipDimensions(pCD, True);
1004 * Get root coordinates of X and Y for icon.
1005 * We use root coordinates of clip window since clipX and
1006 * clipY are not 0, but the icon X and Y may be 0 in
1010 XTranslateCoordinates(DISPLAY, XtWindow(P_ICON_BOX(pCD)->bBoardWidget),
1011 ROOT_FOR_CLIENT(pCD), tmpX, tmpY,
1012 &newX, &newY, &child);
1025 if (((int)newX) > ((int)clipX +
1026 (int)clipWidth - ((int)ICON_WIDTH(pCD))))
1030 if (((int)newY) > ((int)clipY +
1031 (int)clipHeight - ((int)ICON_HEIGHT(pCD))))
1038 } /* END OF FUNCTION CheckVisualPlace */
1042 /*************************************<->*************************************
1044 * CompleteFrameConfig (pcd, pev)
1049 * Clean up graphic feedback when user stops configuring.
1054 * pcd - pointer to client data
1055 * pev - pointer to event
1064 * o This routine assumes that it is called in response to a button release
1067 *************************************<->***********************************/
1068 void CompleteFrameConfig (ClientData *pcd, XEvent *pev)
1070 unsigned int tmpWidth, tmpHeight;
1075 if (wmGD.configAction == RESIZE_CLIENT) {
1076 /* release the grabs */
1080 * Honor the implied constrained anchor points on the window
1081 * so that the resize doesn't cause the window to move
1085 #ifndef CONFIG_RELATIVE_TO_CLIENT
1090 /* Use dummy x,y so we don't add frame offset to client location */
1091 FrameToClient (pcd, &tmpX, &tmpY, &resizeWidth, &resizeHeight);
1093 FrameToClient (pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
1096 tmpWidth = resizeWidth;
1097 tmpHeight = resizeHeight;
1099 FixWindowConfiguration (pcd, &tmpWidth, &tmpHeight,
1100 (unsigned int) pcd->widthInc,
1101 (unsigned int) pcd->heightInc);
1103 AdjustPos (&resizeX, &resizeY,
1104 resizeWidth, resizeHeight, tmpWidth, tmpHeight);
1106 /* reconfigure the window(s) */
1107 ProcessNewConfiguration (pcd, resizeX, resizeY,
1108 resizeWidth, resizeHeight, FALSE);
1111 else if (wmGD.configAction == MOVE_CLIENT)
1113 /* release the grabs */
1116 /* make sure title bar is popped out */
1117 if ((wmGD.configAction == MOVE_CLIENT) &&
1118 (wmGD.gadgetClient == pcd) &&
1119 (wmGD.gadgetDepressed == FRAME_TITLE))
1121 PopGadgetOut (pcd, FRAME_TITLE);
1122 FrameExposureProc(pcd); /* repaint frame */
1125 /* handle both icon and normal frames */
1126 if (wmGD.movingIcon)
1129 inIconBox = (pcd->pSD->useIconBox && P_ICON_BOX(pcd));
1131 /* only need to move the icon */
1132 if (wmGD.iconAutoPlace || inIconBox)
1137 IconPlacementData *pIPD;
1140 * Get correct icon placement data
1144 pIPD = &P_ICON_BOX(pcd)->IPD;
1150 pIPD = &(ACTIVE_WS->IPData);
1154 * Check to make sure that there is an unoccupied place
1155 * where the icon is being moved to:
1158 centerX = moveX + ICON_WIDTH(pcd) / 2;
1159 centerY = moveY + ICON_HEIGHT(pcd) / 2;
1160 place = CvtIconPositionToPlace (pIPD, centerX, centerY);
1162 if (place != ICON_PLACE(pcd))
1164 if (pIPD->placeList[place].pCD)
1167 * Primary place occupied, try to find an unoccupied
1168 * place in the proximity.
1171 place = FindIconPlace (pcd, pIPD, centerX, centerY);
1172 if (place == NO_ICON_PLACE)
1175 * Can't find an unoccupied icon place.
1178 F_Beep (NULL, pcd, (XEvent *)NULL);
1180 if (pcd->pSD->moveOpaque && !inIconBox)
1183 * Replace icon into same place - as if it
1187 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1188 ICON_X(pcd), ICON_Y(pcd));
1189 if ((ICON_DECORATION(pcd) &
1190 ICON_ACTIVE_LABEL_PART) &&
1191 (wmGD.keyboardFocus == pcd))
1193 MoveActiveIconText(pcd);
1194 ShowActiveIconText(pcd);
1199 if ((place != NO_ICON_PLACE) &&
1200 (place != ICON_PLACE(pcd)))
1204 CvtIconPlaceToPosition (pIPD, place,
1206 if( (CheckIconBoxSize (P_ICON_BOX(pcd))) &&
1207 (CheckVisualPlace(pcd, tmpX, tmpY)))
1210 * Move the icon to the new place.
1213 MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
1214 CvtIconPlaceToPosition (pIPD, place,
1215 &ICON_X(pcd), &ICON_Y(pcd));
1219 pIPD->placeList[ICON_PLACE(pcd)].theWidget,
1220 ICON_X(pcd), ICON_Y(pcd));
1222 SetNewBounds (P_ICON_BOX(pcd));
1223 if (ICON_DECORATION(pcd) &
1224 ICON_ACTIVE_LABEL_PART)
1226 MoveActiveIconText(pcd);
1231 F_Beep (NULL, pcd, (XEvent *)NULL);
1237 * Move the icon to the new place.
1239 MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
1240 CvtIconPlaceToPosition (pIPD, place, &ICON_X(pcd),
1243 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1244 ICON_X(pcd), ICON_Y(pcd));
1246 if (pcd->pSD->moveOpaque &&
1247 (ICON_DECORATION(pcd) &
1248 ICON_ACTIVE_LABEL_PART) &&
1249 (wmGD.keyboardFocus == pcd))
1251 MoveActiveIconText(pcd);
1252 ShowActiveIconText(pcd);
1257 else if (pcd->pSD->moveOpaque && !inIconBox)
1260 * Replace icon into same place - as if it
1263 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
1264 ICON_X(pcd), ICON_Y(pcd));
1265 if ((ICON_DECORATION(pcd) &
1266 ICON_ACTIVE_LABEL_PART) &&
1267 (wmGD.keyboardFocus == pcd))
1269 MoveActiveIconText(pcd);
1270 ShowActiveIconText(pcd);
1276 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd), moveX, moveY);
1277 ICON_X(pcd) = moveX;
1278 ICON_Y(pcd) = moveY;
1280 if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
1281 (wmGD.keyboardFocus == pcd))
1283 MoveActiveIconText(pcd);
1286 else { /* assume normal window frame */
1287 /* reconfigure the window(s) */
1288 ProcessNewConfiguration (pcd,
1289 #ifndef CONFIG_RELATIVE_TO_CLIENT
1297 (moveWidth - 2*offsetX),
1299 (moveHeight - offsetX - offsetY),
1303 else if (wmGD.configAction == MARQUEE_SELECT)
1309 pSD = pcd ? pcd->pSD : ACTIVE_PSD;
1311 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END,
1312 marqueeX, marqueeY, marqueeWidth, marqueeHeight);
1316 * Clear configuration flags and data.
1319 wmGD.configAction = NO_ACTION;
1320 wmGD.configPart = FRAME_NONE;
1321 wmGD.configSet = False;
1324 wmGD.movingIcon = FALSE;
1328 /* hide the move/resize config data */
1329 HideFeedbackWindow(pcd->pSD);
1332 * Set the focus back to something reasonable
1337 } /* END OF FUNCTION CompleteFrameConfig */
1340 /*************************************<->*************************************
1342 * MoveOpaque (pcd, x, y, width, height)
1347 * Move a window or icon on the root or icon box.
1352 * pcd - client data pointer
1353 * x - x coordinate (on root)
1354 * y - y coordinate (on root)
1355 * width - pixel width of frame
1356 * height - pixel height of frame
1364 * o use MoveOutline() for icons in an icon box.
1366 *************************************<->***********************************/
1367 void MoveOpaque (ClientData *pcd, int x, int y,
1368 unsigned int width, unsigned int height)
1372 /* Check if moving icon */
1373 if (wmGD.movingIcon)
1375 if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
1378 * For now just fall back to move outline when the
1379 * icon is in the icon box
1382 MoveOutline (x, y, width, height);
1386 XMoveWindow (DISPLAY,ICON_FRAME_WIN(pcd) , x, y);
1391 /* This is a window */
1392 XMoveWindow (DISPLAY, pcd->clientFrameWin, x, y);
1396 /* cleanup exposed frame parts */
1397 PullExposureEvents ();
1399 } /* END OF FUNCTION MoveOpaque */
1403 /* thickness of outline */
1404 #define OUTLINE_WIDTH 2
1406 /* number of points to draw outline once */
1407 #define SEGS_PER_DRAW (4*OUTLINE_WIDTH)
1409 /* number of points to flash outline (draw then erase) */
1410 #define SEGS_PER_FLASH (2*SEGS_PER_DRAW)
1413 /*************************************<->*************************************
1415 * DrawSegments (dpy, win, gc, outline, nsegs)
1419 * Draw segments using either using normal X or using the ALLPLANES
1420 * extension, depending on #ifdef ALLPLANES and whether the server actually
1421 * supports the extension. This is a thin wrapper around the Xlib
1422 * XDrawSegments() call.
1426 * dpy - the X display
1427 * win - the window on which to draw
1428 * gc - the gc to use, typically whose function is GXxor
1429 * outline - array of segments
1430 * nsegs - number of segments in the outline array
1438 * Note: no GC is used when drawing with the ALLPLANES extension;
1439 * therefore, the GC parameter is ignored in that case.
1441 *************************************<->***********************************/
1445 DrawSegments (Display *dpy, Window win, GC gc, XSegment *outline, int nsegs)
1447 #if defined(sun) && defined(ALLPLANES)
1449 XAllPlanesDrawSegments(dpy, win, outline, nsegs);
1451 #endif /* defined(sun) && defined(ALLPLANES) */
1452 XDrawSegments(dpy, win, gc, outline, nsegs);
1453 } /* END OF FUNCTION DrawSegments */
1456 /*************************************<->*************************************
1458 * MoveOutline (x, y, width, height)
1463 * Draw a window outline on the root window.
1468 * x - x coordinate (on root)
1469 * y - y coordinate (on root)
1470 * width - pixel width of frame
1471 * height - pixel height of frame
1479 * o get display, root window ID, and xorGC out of global data.
1481 *************************************<->***********************************/
1482 void MoveOutline (int x, int y, unsigned int width, unsigned int height)
1484 if (wmGD.freezeOnConfig)
1486 DrawOutline (x, y, width, height);
1490 if (wmGD.useWindowOutline)
1491 WindowOutline(x,y,width,height);
1493 FlashOutline(x, y, width, height);
1495 } /* END OF FUNCTION MoveOutline */
1499 /*************************************<->*************************************
1506 * flash a window outline on the root window.
1511 * x - x coordinate (on root)
1512 * y - y coordinate (on root)
1513 * width - pixel width of frame
1514 * height - pixel height of frame
1522 * o get display, root window ID, and xorGC out of global data.
1523 * o draw on root and erase "atomically"
1525 *************************************<->***********************************/
1526 void FlashOutline (int x, int y, unsigned int width, unsigned int height)
1528 static XSegment outline[SEGS_PER_FLASH];
1531 * Do nothing if no box to draw
1533 if (x == 0 && y == 0 &&
1534 width == 0 && height == 0)
1538 * Draw outline an even number of times (draw then erase)
1540 SetOutline (outline, x, y, width, height, OUTLINE_WIDTH);
1541 memcpy ( (char *) &outline[SEGS_PER_DRAW], (char *) &outline[0],
1542 SEGS_PER_DRAW*sizeof(XSegment));
1545 * Flash the outline at least once, then as long as there's
1546 * nothing else going on
1548 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1549 outline, SEGS_PER_FLASH);
1550 XSync(DISPLAY, FALSE);
1552 while (!XtAppPending(wmGD.mwmAppContext)) {
1553 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1554 outline, SEGS_PER_FLASH);
1555 XSync(DISPLAY, FALSE);
1557 } /* END OF FUNCTION FlashOutline */
1560 /*************************************<->*************************************
1562 * CreateOutlineWindows (pSD)
1567 * create the outline windows
1578 * variables are affected:
1584 *************************************<->***********************************/
1586 CreateOutlineWindows (WmScreenData *pSD)
1588 XSetWindowAttributes xswa;
1589 unsigned int xswamask;
1590 int x, y, width, height;
1595 width = OUTLINE_WIDTH;
1596 height = OUTLINE_WIDTH;
1598 xswa.override_redirect = True;
1599 xswa.backing_store = NotUseful;
1600 xswa.save_under = True;
1601 xswa.background_pixmap = XmGetPixmap(
1602 XtScreen(pSD->screenTopLevelW),
1604 pSD->clientAppearance.foreground,
1605 pSD->clientAppearance.background);
1607 xswamask = (CWOverrideRedirect |
1612 pSD->woN = XCreateWindow(DISPLAY, pSD->rootWindow,
1613 x, y, width, height,
1615 XDefaultDepth(DISPLAY,pSD->screen),
1621 pSD->woS = XCreateWindow(DISPLAY, pSD->rootWindow,
1622 x, y, width, height,
1624 XDefaultDepth(DISPLAY,pSD->screen),
1630 pSD->woE = XCreateWindow(DISPLAY, pSD->rootWindow,
1631 x, y, width, height,
1633 XDefaultDepth(DISPLAY,pSD->screen),
1639 pSD->woW = XCreateWindow(DISPLAY, pSD->rootWindow,
1640 x, y, width, height,
1642 XDefaultDepth(DISPLAY,pSD->screen),
1648 } /* END OF FUNCTION CreateOutlineWindows */
1651 /*************************************<->*************************************
1658 * show an outline on the root window using windows.
1663 * x - x coordinate (on root)
1664 * y - y coordinate (on root)
1665 * width - pixel width of frame
1666 * height - pixel height of frame
1674 * Always unmap during move/resize of outline windows to let saveunder
1675 * stuff work. HP server's toss saveunder stuff for windows that
1676 * configure themselves while mapped.
1678 *************************************<->***********************************/
1679 void WindowOutline (int x, int y, unsigned int width, unsigned int height)
1681 static int lastOutlineX = 0;
1682 static int lastOutlineY = 0;
1683 static int lastOutlineWidth = 0;
1684 static int lastOutlineHeight = 0;
1685 WmScreenData *pSD = ACTIVE_PSD;
1689 if (pSD->woN == (Window)0L)
1691 CreateOutlineWindows(pSD);
1694 if (x == lastOutlineX && y == lastOutlineY &&
1695 width == lastOutlineWidth && height == lastOutlineHeight)
1697 return; /* no change */
1700 XUnmapWindow(DISPLAY, pSD->woN);
1701 XUnmapWindow(DISPLAY, pSD->woS);
1702 XUnmapWindow(DISPLAY, pSD->woE);
1703 XUnmapWindow(DISPLAY, pSD->woW);
1705 if ((width == 0) && (height == 0))
1707 lastOutlineWidth = lastOutlineHeight = 0;
1708 lastOutlineX = lastOutlineY = 0;
1718 XMoveResizeWindow (DISPLAY, pSD->woN, iX, iY, iW, iH);
1722 iY = y + OUTLINE_WIDTH;
1724 iH = (int) height - OUTLINE_WIDTH;
1726 XMoveResizeWindow (DISPLAY, pSD->woW, iX, iY, iW, iH);
1729 iX = x + (int)width - OUTLINE_WIDTH;
1730 iY = y + OUTLINE_WIDTH;
1732 iH = (int)height - OUTLINE_WIDTH;
1734 XMoveResizeWindow (DISPLAY, pSD->woE, iX, iY, iW, iH);
1737 iX = x + OUTLINE_WIDTH;
1738 iY = y + (int)height - OUTLINE_WIDTH;
1739 iW = (int)width - 2*OUTLINE_WIDTH;
1742 XMoveResizeWindow (DISPLAY, pSD->woS, iX, iY, iW, iH);
1746 lastOutlineWidth = width;
1747 lastOutlineHeight = height;
1749 XMapRaised (DISPLAY, pSD->woN);
1750 XMapRaised (DISPLAY, pSD->woS);
1751 XMapRaised (DISPLAY, pSD->woE);
1752 XMapRaised (DISPLAY, pSD->woW);
1754 /* cleanup exposed frame parts */
1755 PullExposureEvents ();
1758 } /* END OF FUNCTION WindowOutline */
1762 /*************************************<->*************************************
1764 * DrawOutline (x, y, width, height)
1769 * Draw a window outline on the root window.
1774 * x - x coordinate (on root)
1775 * y - y coordinate (on root)
1776 * width - pixel width of frame
1777 * height - pixel height of frame
1785 * o get display, root window ID, and xorGC out of global data.
1787 *************************************<->***********************************/
1788 void DrawOutline (int x, int y, unsigned int width, unsigned int height)
1790 static int lastOutlineX = 0;
1791 static int lastOutlineY = 0;
1792 static int lastOutlineWidth = 0;
1793 static int lastOutlineHeight = 0;
1794 XSegment outline[SEGS_PER_DRAW];
1797 if (x == lastOutlineX && y == lastOutlineY &&
1798 width == lastOutlineWidth && height == lastOutlineHeight)
1800 return; /* no change */
1803 if (lastOutlineWidth || lastOutlineHeight) {
1804 SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
1805 lastOutlineHeight, OUTLINE_WIDTH);
1807 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1808 outline, SEGS_PER_DRAW);
1813 lastOutlineWidth = width;
1814 lastOutlineHeight = height;
1816 if (lastOutlineWidth || lastOutlineHeight) {
1818 SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
1819 lastOutlineHeight, OUTLINE_WIDTH);
1821 DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
1822 outline, SEGS_PER_DRAW);
1824 } /* END OF FUNCTION DrawOutline */
1828 /*************************************<->*************************************
1830 * WindowIsOnScreen (pCD, dx, dy)
1835 * This function is used to check if a window is atleast partially on the
1836 * screen or not. If the window is completely off the screen, dx and dy
1837 * will contain the minimum distance to move some part of the window's frame
1838 * back onto the screen.
1843 * pCD - pointer to client data
1848 * dx - minimum x distance to move the window back to the screen
1849 * dy - minimum y distance to move the window back to the screen
1854 * true - if the window has some part on the screen
1855 * false - if the window is completely off the screen
1860 *************************************<->***********************************/
1862 Boolean WindowIsOnScreen (ClientData *pCD, int *dx, int *dy)
1864 int x1 = pCD->clientX;
1865 int x2 = pCD->clientX + pCD->clientWidth;
1866 int y1 = pCD->clientY;
1867 int y2 = pCD->clientY + pCD->clientHeight;
1868 int screenW = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
1869 int screenH = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pCD));
1873 if (x2 < 0) /* right frame border off left side of screen. */
1875 else if (x1 > screenW) /* left frame border off right side of screen. */
1878 if (y2 < 0) /* bottom frame border off top of screen. */
1880 else if (y1 > screenH) /* top frame border off bottom of screen. */
1883 return ((*dx == 0) && (*dy == 0));
1888 /*************************************<->*************************************
1890 * ProcessNewConfiguration (pCD, x, y, width, height, clientRequest)
1895 * This function is used to configure a client window following receipt of
1896 * a client request or an interactive configuration action.
1901 * pCD - pointer to client data
1902 * x - x coord of client window
1903 * y - y coord of client window
1904 * width - width of client window
1905 * height - height of client window
1906 * clientRequest - true if configuration requested by client program
1916 *************************************<->***********************************/
1918 void ProcessNewConfiguration (ClientData *pCD, int x, int y, unsigned int width, unsigned int height, Boolean clientRequest)
1920 unsigned int changedValues = 0;
1921 int xoff = 0, yoff = 0;
1923 Boolean originallyOnScreen = WindowIsOnScreen(pCD, &dx, &dy);
1924 Boolean newMax = False;
1925 Boolean toNewMax = False;
1928 * Fix the configuration values to be compatible with the configuration
1929 * constraints for this class of windows.
1934 FixWindowConfiguration (pCD, &width, &height,
1935 (unsigned int) pCD->widthInc,
1936 (unsigned int) pCD->heightInc);
1938 if ((pCD->maxWidth != pCD->oldMaxWidth) ||
1939 (pCD->maxHeight != pCD->oldMaxHeight))
1942 * We've got a new maximum size.
1948 * If the configuration has changed, update client data
1950 * Changes in width or height cause maximized windows to return to
1951 * normal state and update normal geometry (x, y, width, height)
1956 (pCD->maxWidth == width) &&
1957 (pCD->maxHeight == height))
1959 /* we're changing to the new max size */
1963 changedValues |= (width != pCD->oldMaxWidth) ? CWWidth : 0;
1964 changedValues |= (height != pCD->oldMaxHeight) ? CWHeight : 0;
1966 if (!toNewMax && (changedValues & CWWidth)) {
1968 * Hacked to update maxWidth for 'vertical' max clients
1970 if (IS_MAXIMIZE_VERTICAL(pCD)) {
1971 pCD->maxWidth = width;
1973 pCD->clientWidth = width;
1974 if (changedValues & CWHeight) {
1976 * Hacked to update maxHeight for 'horizontal' max client
1978 if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
1979 pCD->maxHeight = height;
1981 pCD->clientHeight = height;
1984 pCD->clientHeight = pCD->oldMaxHeight;
1987 else if (!toNewMax && (changedValues & CWHeight)) {
1989 * Hacked to update maxHeight for 'horizontal' max client
1991 if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
1992 pCD->maxHeight = height;
1994 pCD->clientHeight = height;
1995 pCD->clientWidth = pCD->oldMaxWidth;
1999 if (width != pCD->clientWidth)
2002 * Hacked to update maxWidth for 'vertical' max clients
2004 if (IS_MAXIMIZE_VERTICAL(pCD)) {
2005 pCD->maxWidth = width;
2008 changedValues |= CWWidth;
2009 pCD->clientWidth = width;
2013 if (height != pCD->clientHeight)
2016 * Hacked to update maxHeight for 'horizontal' max client
2018 if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
2019 pCD->maxHeight = height;
2022 changedValues |= CWHeight;
2023 pCD->clientHeight = height;
2027 #ifndef CONFIG_RELATIVE_TO_CLIENT
2029 * If positionIsFrame or user initiated configuration request,
2030 * then adjust client position to by frame_width and frame_height.
2032 if (wmGD.positionIsFrame || (!clientRequest))
2034 xoff = pCD->clientOffset.x;
2035 yoff = pCD->clientOffset.y;
2040 * Changes in position update maximum geometry on maximized windows
2041 * if there was no change in size.
2043 if (pCD->maxConfig) {
2044 if (x != pCD->maxX) {
2045 changedValues |= CWX;
2046 if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2047 pCD->clientX = x + xoff;
2049 pCD->maxX = x + xoff;
2051 else if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2053 pCD->clientX = pCD->maxX;
2056 if (y != pCD->maxY) {
2057 changedValues |= CWY;
2058 if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2059 pCD->clientY = y + yoff;
2061 pCD->maxY = y + yoff;
2063 else if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
2065 pCD->clientY = pCD->maxY;
2069 if (x + xoff != pCD->clientX) {
2070 changedValues |= CWX;
2071 pCD->clientX = x + xoff;
2074 if (y + yoff != pCD->clientY) {
2075 changedValues |= CWY;
2076 pCD->clientY = y + yoff;
2080 /* check if the window has reconfigured itself off the screen. */
2081 if (originallyOnScreen && !WindowIsOnScreen(pCD, &dx, &dy))
2085 changedValues |= CWX;
2091 changedValues |= CWY;
2098 * Resize the client window if necessary:
2101 if (changedValues & (CWWidth | CWHeight))
2107 /* maximized window resized, return to normal state */
2108 pCD->maxConfig = FALSE;
2109 pCD->clientState = NORMAL_STATE;
2113 XResizeWindow (DISPLAY, pCD->client, width, height);
2114 RegenerateClientFrame(pCD);
2116 if (changedValues & (CWX | CWY)) {
2120 * Fix for 5217 - If the request is from the client, use the clients
2121 * offsets instead of the static offsets
2125 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2126 pCD->maxX - pCD->clientOffset.x,
2127 pCD->maxY - pCD->clientOffset.y);
2131 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2132 pCD->maxX - offsetX,
2133 pCD->maxY - offsetY);
2141 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2142 pCD->clientX - pCD->clientOffset.x,
2143 pCD->clientY - pCD->clientOffset.y);
2147 XMoveWindow (DISPLAY, pCD->clientFrameWin,
2148 pCD->clientX - offsetX,
2149 pCD->clientY - offsetY);
2153 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
2155 /* turn off subpanel behavior if moved */
2156 pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUBPANEL;
2161 * Send a configure notify message if appropriate:
2162 * 1. rejected client configuration request.
2163 * 2. client request and move without resize
2167 if ((!changedValues && clientRequest) ||
2168 (changedValues && !(changedValues & (CWWidth | CWHeight))))
2170 SendConfigureNotify (pCD);
2174 * Try to send notice directly to icon box that the window
2178 if ((pCD->clientFlags & ICON_BOX) &&
2179 (changedValues & (CWWidth | CWHeight)))
2181 CheckIconBoxResize(pCD, changedValues, width, height);
2184 } /* END OF FUNCTION ProcessNewConfiguration */
2188 /*************************************<->*************************************
2190 * StartResizeConfig (pcd, pev)
2195 * Start resize of client window
2200 * pcd - pointer to client data
2201 * pev - pointer to event
2205 * return - true if configuration can begin, else false
2211 *************************************<->***********************************/
2213 Boolean StartResizeConfig (ClientData *pcd, XEvent *pev)
2215 Window grab_win, junk_win;
2217 int big_inc, tmp_inc;
2218 int junk, junkX, junkY;
2225 grab_win = GrabWin (pcd, pev);
2229 grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart),
2230 PGRAB_MASK, pev->xbutton.time, pcd, True);
2234 grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart),
2235 PGRAB_MASK, CurrentTime, pcd, True);
2245 /* continue with the configuration in progress (!!!) */
2250 * Set up static variables for succeeding events
2252 if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
2253 &pointerX, &pointerY, &junk, &junk, (unsigned int *)&junk))
2255 CancelFrameConfig (pcd); /* release grabs */
2258 wmGD.preMoveX = pointerX;
2259 wmGD.preMoveY = pointerY;
2262 offsetX = pcd->clientOffset.x;
2263 offsetY = pcd->clientOffset.y;
2266 * get window geometry information and convert to frame coordinates
2268 if (pcd->maxConfig) {
2269 resizeX = pcd->maxX;
2270 resizeY = pcd->maxY;
2271 resizeWidth = pcd->maxWidth;
2272 resizeHeight = pcd->maxHeight;
2275 resizeX = pcd->clientX;
2276 resizeY = pcd->clientY;
2277 resizeWidth = pcd->clientWidth;
2278 resizeHeight = pcd->clientHeight;
2280 ClientToFrame(pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
2282 /* save start values to see where we came from */
2285 startWidth = resizeWidth;
2286 startHeight = resizeHeight;
2288 /* get min and max frame sizes */
2289 minWidth = pcd->minWidth;
2290 minHeight = pcd->minHeight;
2292 ClientToFrame(pcd, &junkX, &junkY, &minWidth, &minHeight);
2295 * Hack to use maxHeightLimit and maxWidthLimit as the real max when
2296 * maximumClientSize is set to 'horizontal' or 'vertical', since
2297 * pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
2299 maxWidth = pcd->maxWidthLimit;
2300 maxHeight = pcd->maxHeightLimit;
2302 ClientToFrame(pcd, &junkX, &junkY, &maxWidth, &maxHeight);
2304 /* compute big increment values */
2305 big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
2307 tmp_inc = big_inc - big_inc%pcd->widthInc;
2308 if (tmp_inc > 5*pcd->widthInc)
2309 resizeBigWidthInc = tmp_inc;
2311 resizeBigWidthInc = 5*pcd->widthInc;
2313 tmp_inc = big_inc - big_inc%pcd->heightInc;
2314 if (tmp_inc > 5*pcd->heightInc)
2315 resizeBigHeightInc = tmp_inc;
2317 resizeBigHeightInc = 5*pcd->heightInc;
2319 /* pop up feedback window */
2320 if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
2322 DoFeedback (pcd, resizeX, resizeY, resizeWidth, resizeHeight,
2323 FB_SIZE, TRUE /* do size checks */);
2326 /* set configuring data */
2327 wmGD.configAction = RESIZE_CLIENT;
2328 wmGD.configButton = pev ? pev->xbutton.button: 0;
2332 } /* END OF FUNCTION StartResizeConfig */
2336 /*************************************<->*************************************
2338 * StartClientResize (pcd, pev)
2343 * Start resize of client window as invoked from menu
2348 * pcd - pointer to client data
2349 * pev - pointer to event
2357 * o This should only be called as the result of a Resize function
2358 * being selected from the system menu.
2360 *************************************<->***********************************/
2361 void StartClientResize (ClientData *pcd, XEvent *pev)
2364 /* do initial setup for resize */
2365 wmGD.configPart = FRAME_NONE; /* determined by later action */
2366 wmGD.configSet = False; /* don't know what it is yet */
2367 if (!StartResizeConfig (pcd, pev))
2369 /* resize could not be initiated */
2375 * Warp pointer to middle of window if started from the keyboard
2376 * or menu (no event).
2378 if ( !pev || pev->type == KeyPress )
2380 pointerX = resizeX + resizeWidth/2;
2381 pointerY = resizeY + resizeHeight/2;
2383 ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &pointerX, &pointerY);
2384 if (wmGD.enableWarp)
2386 XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd),
2387 0, 0, 0, 0, pointerX, pointerY);
2391 } /* END OF FUNCTION StartClientResize */
2394 /*************************************<->*************************************
2396 * StartClientMove (pcd, pev)
2401 * Handle move of client window as invoked from menu
2406 * pcd - pointer to client data
2407 * pev - pointer to event
2411 * Return - True if configuration was initiated, else False
2416 * o This should only be called as the result of a Move function
2417 * being selected from the system menu.
2419 *************************************<->***********************************/
2420 Boolean StartClientMove (ClientData *pcd, XEvent *pev)
2422 Window grab_win, junk_win;
2428 * Do our grabs if we're just starting out
2432 grab_win = GrabWin (pcd, pev);
2433 if (grab_win == ICON_FRAME_WIN(pcd))
2435 wmGD.movingIcon = True;
2440 grabbed = DoGrabs (grab_win, wmGD.configCursor,
2441 PGRAB_MASK, pev->xbutton.time, pcd, False);
2445 grabbed = DoGrabs (grab_win, wmGD.configCursor,
2446 PGRAB_MASK, CurrentTime, pcd, False);
2450 wmGD.movingIcon = False;
2457 * Set up static variables for succeeding events if we're not
2458 * entering with a motion event. If we are, we assume that the
2459 * preMove variables have been setup.
2461 if (pev && ((pev->type == ButtonPress) || (pev->type == ButtonRelease)))
2463 wmGD.preMoveX = pev->xbutton.x_root;
2464 wmGD.preMoveY = pev->xbutton.y_root;
2466 else if ((pev && (pev->type != MotionNotify)) || !pev)
2468 if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd),
2469 &junk_win, &junk_win,
2470 &(wmGD.preMoveX), &(wmGD.preMoveY),
2471 &junk, &junk, (unsigned int *)&junk))
2473 CancelFrameConfig (pcd);
2478 offsetX = pcd->clientOffset.x;
2479 offsetY = pcd->clientOffset.y;
2482 moveLastPointerX = wmGD.preMoveX;
2483 moveLastPointerY = wmGD.preMoveY;
2485 /* get frame window geometry */
2486 if (wmGD.movingIcon)
2488 moveWidth = ICON_WIDTH(pcd);
2489 moveHeight = ICON_HEIGHT(pcd);
2491 moveX = ICON_X(pcd);
2492 moveY = ICON_Y(pcd);
2494 if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
2496 /* get root coords of icon box bulletin board */
2497 XTranslateCoordinates(DISPLAY,
2498 XtWindow(P_ICON_BOX(pcd)->bBoardWidget), ROOT_FOR_CLIENT(pcd),
2499 0, 0, &moveIBbbX, &moveIBbbY, &child);
2504 else if (pcd->pSD->moveOpaque &&
2505 (ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
2506 (wmGD.keyboardFocus == pcd))
2508 HideActiveIconText ((WmScreenData *)NULL);
2513 if (pcd->maxConfig) { /* maximized */
2514 moveWidth = pcd->maxWidth;
2515 moveHeight = pcd->maxHeight;
2520 moveWidth = pcd->clientWidth;
2521 moveHeight = pcd->clientHeight;
2522 moveX = pcd->clientX;
2523 moveY = pcd->clientY;
2525 ClientToFrame (pcd, &moveX, &moveY, &moveWidth, &moveHeight);
2528 if (pcd->pSD->moveOpaque)
2530 opaqueMoveX = moveX;
2531 opaqueMoveY = moveY;
2535 * Warp pointer to middle of window if started from the menu (no event).
2537 if ( !pev || pev->type == KeyPress )
2539 moveLastPointerX = moveX + moveWidth/2;
2540 moveLastPointerY = moveY + moveHeight/2;
2542 ForceOnScreen (SCREEN_FOR_CLIENT(pcd),
2543 &moveLastPointerX, &moveLastPointerY);
2544 if (wmGD.enableWarp)
2546 XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd), 0, 0, 0, 0,
2547 moveLastPointerX, moveLastPointerY);
2551 /* pop up feedback window */
2552 if ( !wmGD.movingIcon && (wmGD.showFeedback & WM_SHOW_FB_MOVE))
2554 DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight,
2555 FB_POSITION, FALSE /* no size checks */);
2558 /* set configuring data */
2559 wmGD.configAction = MOVE_CLIENT;
2560 if (pev && pev->type != KeyPress)
2561 wmGD.configButton = pev->xbutton.button;
2563 wmGD.configButton = 0;
2569 } /* END OF FUNCTION StartClientMove */
2572 /*************************************<->*************************************
2574 * DoGrabs (grab_win, cursor, pmask, grabTime, alwaysGrab)
2579 * Do the grabs for window configuration
2584 * grab_win - window to grab on
2585 * cursor - cursor shape to attach to the pointer
2587 * grabTime - time stamp
2597 *************************************<->***********************************/
2598 Boolean DoGrabs (Window grab_win, Cursor cursor, unsigned int pmask, Time grabTime, ClientData *pCD, Boolean alwaysGrab)
2604 root = ROOT_FOR_CLIENT(pCD);
2606 root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
2608 if (pCD && pCD->pSD->useIconBox && wmGD.movingIcon && P_ICON_BOX(pCD))
2611 * Confine the pointer to the icon box clip window
2613 if (XGrabPointer(DISPLAY,
2615 FALSE, /* owner_events */
2617 GrabModeAsync, /* pointer_mode */
2618 GrabModeAsync, /* keyboard_mode */
2619 /* confine_to window */
2620 XtWindow(P_ICON_BOX(pCD)->clipWidget),
2622 grabTime) != GrabSuccess)
2630 * Just confine the pointer to the root window
2632 if (XGrabPointer(DISPLAY,
2634 FALSE, /* owner_events */
2636 GrabModeAsync, /* pointer_mode */
2637 GrabModeAsync, /* keyboard_mode */
2640 grabTime) != GrabSuccess)
2647 * Don't grab keyboard away from menu widget to prevent
2648 * hosing of traversal.
2650 if (!wmGD.menuActive)
2652 if ((XGrabKeyboard(DISPLAY,
2654 FALSE, /* owner_events */
2655 GrabModeAsync, /* pointer_mode */
2656 GrabModeAsync, /* keyboard_mode */
2657 grabTime)) != GrabSuccess)
2659 XUngrabPointer (DISPLAY, CurrentTime);
2665 if (wmGD.freezeOnConfig)
2668 if (!pCD || ((pCD->pSD->moveOpaque && alwaysGrab) ||
2669 (!(pCD->pSD->moveOpaque))))
2671 XGrabServer(DISPLAY);
2676 } /* END OF FUNCTION DoGrabs */
2679 /*************************************<->*************************************
2699 *************************************<->***********************************/
2700 void UndoGrabs (void)
2703 MoveOutline(0, 0, 0, 0);
2704 XSync (DISPLAY, FALSE /*don't discard events*/);
2707 if (wmGD.freezeOnConfig) {
2708 XUngrabServer(DISPLAY);
2712 * Don't Ungrab keyboard away from menu widget to prevent
2713 * hosing of traversal.
2715 if (!wmGD.menuActive)
2716 XUngrabKeyboard (DISPLAY,CurrentTime);
2718 XUngrabPointer (DISPLAY, CurrentTime); /* event time NOT used */
2721 } /* END OF FUNCTION UndoGrabs */
2725 /*************************************<->*************************************
2727 * CancelFrameConfig (pcd)
2732 * Cance a frame configuration (move/resize) operation.
2737 * pcd - pointer to client data
2747 *************************************<->***********************************/
2748 void CancelFrameConfig (ClientData *pcd)
2751 /* remove keyboard, pointer, and server grabs */
2754 /* turn off feedback window */
2757 HideFeedbackWindow(pcd->pSD);
2759 /* make sure title bar is popped out */
2760 if ((wmGD.configAction == MOVE_CLIENT) &&
2761 (wmGD.gadgetClient == pcd) && (wmGD.gadgetDepressed == FRAME_TITLE))
2763 PopGadgetOut (pcd, FRAME_TITLE);
2764 FrameExposureProc(pcd); /* repaint frame */
2766 if ((pcd->pSD->moveOpaque) &&
2767 (wmGD.configAction == MOVE_CLIENT))
2770 if ((pcd->clientState == MINIMIZED_STATE) &&
2771 (!(pcd->pSD->useIconBox && P_ICON_BOX(pcd))))
2774 * Replace icon into pre-move position
2777 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
2778 ICON_X(pcd), ICON_Y(pcd));
2779 if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART))
2781 ShowActiveIconText(pcd);
2784 else if (! wmGD.movingIcon) /* we are not moving in the iconbox */
2786 XMoveWindow (DISPLAY, pcd->clientFrameWin,
2787 opaqueMoveX, opaqueMoveY);
2791 if (wmGD.configAction == MARQUEE_SELECT)
2793 dtSendMarqueeSelectionNotification(ACTIVE_PSD, DT_MARQUEE_SELECT_CANCEL,
2794 marqueeX, marqueeY, 0, 0);
2797 /* replace pointer if no motion events received */
2799 if (!anyMotion && wmGD.enableWarp) {
2800 XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd),
2801 0, 0, 0, 0, wmGD.preMoveX, wmGD.preMoveY);
2805 /* Clear configuration flags and data */
2806 wmGD.configAction = NO_ACTION;
2807 wmGD.configPart = FRAME_NONE;
2808 wmGD.configSet = False;
2810 wmGD.movingIcon = FALSE;
2812 /* set the focus back to a reasonable window */
2814 } /* END OF FUNCTION CancelFrameConfig */
2818 /*************************************<->*************************************
2820 * CheckEatButtonRelease (pcd, pev)
2825 * Set up to eat button releases if buttons are down.
2830 * pcd - pointer to client data
2831 * pev - pointer to key event that caused cancel
2841 *************************************<->***********************************/
2843 CheckEatButtonRelease (ClientData *pcd, XEvent *pev)
2848 if (pcd != (ClientData *)NULL)
2849 root = ROOT_FOR_CLIENT(pcd);
2851 root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
2853 if (pcd == (ClientData *) NULL)
2856 grab_win = GrabWin(pcd, pev);
2858 if ((pev->type == KeyPress || pev->type == KeyRelease) &&
2859 (pev->xbutton.state & ButtonMask))
2862 * Some buttons are down...
2863 * Set up conditions to wait for these buttons to go up.
2865 if (XGrabPointer(DISPLAY,
2867 False, /* owner_events */
2869 GrabModeAsync, /* pointer_mode */
2870 GrabModeAsync, /* keyboard_mode */
2871 root, /* confine_to window */
2873 pev->xbutton.time) == GrabSuccess)
2875 EatButtonRelease (pev->xbutton.state & ButtonMask);
2881 /*************************************<->*************************************
2883 * EatButtonRelease (releaseButtons)
2888 * Eat up button release events
2893 * releaseButtons = button mask of button releases to eat
2903 *************************************<->***********************************/
2905 EatButtonRelease (unsigned int releaseButtons)
2907 unsigned int new_state;
2910 while (releaseButtons)
2912 PullExposureEvents ();
2913 XMaskEvent (DISPLAY, ButtonReleaseMask, &event);
2915 if (event.type == ButtonRelease)
2917 /* look at the state after this button is released */
2919 event.xbutton.state & ~ButtonStateBit(event.xbutton.button);
2921 if (!(new_state & releaseButtons))
2923 /* all the buttons we were waiting for have been
2927 XUngrabPointer (DISPLAY, event.xbutton.time);
2936 /*************************************<->*************************************
2938 * ButtonStateBit (button)
2943 * Converts a button number to a button state bit
2948 * button = button number (Button1, Button2, etc.)
2952 * Return = bit used in xbutton state field
2953 * (Button1Mask, Button2Mask,...)
2960 *************************************<->***********************************/
2962 ButtonStateBit (unsigned int button)
2964 #define MAX_BUTTON 5
2966 unsigned int button;
2967 unsigned int maskbit;
2970 static ButtonAssoc bmap[MAX_BUTTON] = {
2971 {Button1, Button1Mask},
2972 {Button2, Button2Mask},
2973 {Button3, Button3Mask},
2974 {Button4, Button4Mask},
2975 {Button5, Button5Mask},
2979 unsigned int rval = 0;
2981 for (i = 0; i < MAX_BUTTON; i++)
2983 if (bmap[i].button == button)
2985 rval = bmap[i].maskbit;
2994 /*************************************<->*************************************
2996 * ConfigCursor (frame_part)
3001 * return the config cursor that goes with the config part specified
3006 * frame_part - frame part id
3010 * return - cursor to use
3016 *************************************<->***********************************/
3017 Cursor ConfigCursor (int frame_part)
3021 switch (frame_part) {
3022 case FRAME_RESIZE_NW:
3023 cursor = wmGD.stretchCursors[STRETCH_NORTH_WEST];
3025 case FRAME_RESIZE_N:
3026 cursor = wmGD.stretchCursors[STRETCH_NORTH];
3028 case FRAME_RESIZE_NE:
3029 cursor = wmGD.stretchCursors[STRETCH_NORTH_EAST];
3031 case FRAME_RESIZE_E:
3032 cursor = wmGD.stretchCursors[STRETCH_EAST];
3034 case FRAME_RESIZE_SE:
3035 cursor = wmGD.stretchCursors[STRETCH_SOUTH_EAST];
3037 case FRAME_RESIZE_S:
3038 cursor = wmGD.stretchCursors[STRETCH_SOUTH];
3040 case FRAME_RESIZE_SW:
3041 cursor = wmGD.stretchCursors[STRETCH_SOUTH_WEST];
3043 case FRAME_RESIZE_W:
3044 cursor = wmGD.stretchCursors[STRETCH_WEST];
3047 cursor = wmGD.configCursor;
3052 } /* END OF FUNCTION ConfigCursor */
3055 /*************************************<->*************************************
3057 * ReGrabPointer (grab_win, grabTime)
3062 * Grab the pointer again to change the cursor
3068 * grabTime - time stamp
3077 *************************************<->***********************************/
3078 void ReGrabPointer (Window grab_win, Time grabTime)
3080 XGrabPointer(DISPLAY,
3082 FALSE, /* owner_events */
3084 GrabModeAsync, /* pointer_mode */
3085 GrabModeAsync, /* keyboard_mode */
3086 ACTIVE_ROOT, /* confine_to window */
3087 ConfigCursor((int)wmGD.configPart),
3090 } /* END OF FUNCTION ReGrabPointer */
3094 /*************************************<->*************************************
3096 * SetPointerResizePart (pcd, pev)
3101 * Sets the global configuration part for resize based on the current
3102 * configuration part and the location of the event
3107 * pcd - pointer to client data
3108 * pev - pointer to event
3113 * Return - TRUE if wmGD.configPart is a valid resize part
3118 * o Assumes the static data for resizing has been set up.
3119 *************************************<->***********************************/
3120 Boolean SetPointerResizePart (ClientData *pcd, XEvent *pev)
3125 newPart = ResizeType(pcd, pev); /* get part id for this event */
3126 grabTime = (pev) ? pev->xmotion.time : CurrentTime;
3128 switch (wmGD.configPart) {
3130 if (newPart == FRAME_NONE)
3131 return(FALSE); /* still not valid */
3133 wmGD.configPart = newPart;
3134 ReGrabPointer(pcd->clientFrameWin, grabTime);
3137 case FRAME_RESIZE_N:
3139 case FRAME_RESIZE_W:
3140 case FRAME_RESIZE_NW:
3141 wmGD.configPart = FRAME_RESIZE_NW;
3142 ReGrabPointer(pcd->clientFrameWin, grabTime);
3145 case FRAME_RESIZE_E:
3146 case FRAME_RESIZE_NE:
3147 wmGD.configPart = FRAME_RESIZE_NE;
3148 ReGrabPointer(pcd->clientFrameWin, grabTime);
3156 case FRAME_RESIZE_E:
3158 case FRAME_RESIZE_N:
3159 case FRAME_RESIZE_NE:
3160 wmGD.configPart = FRAME_RESIZE_NE;
3161 ReGrabPointer(pcd->clientFrameWin, grabTime);
3164 case FRAME_RESIZE_S:
3165 case FRAME_RESIZE_SE:
3166 wmGD.configPart = FRAME_RESIZE_SE;
3167 ReGrabPointer(pcd->clientFrameWin, grabTime);
3175 case FRAME_RESIZE_S:
3177 case FRAME_RESIZE_E:
3178 case FRAME_RESIZE_SE:
3179 wmGD.configPart = FRAME_RESIZE_SE;
3180 ReGrabPointer(pcd->clientFrameWin, grabTime);
3183 case FRAME_RESIZE_W:
3184 case FRAME_RESIZE_SW:
3185 wmGD.configPart = FRAME_RESIZE_SW;
3186 ReGrabPointer(pcd->clientFrameWin, grabTime);
3194 case FRAME_RESIZE_W:
3196 case FRAME_RESIZE_N:
3197 case FRAME_RESIZE_NW:
3198 wmGD.configPart = FRAME_RESIZE_NW;
3199 ReGrabPointer(pcd->clientFrameWin, grabTime);
3202 case FRAME_RESIZE_S:
3203 case FRAME_RESIZE_SW:
3204 wmGD.configPart = FRAME_RESIZE_SW;
3205 ReGrabPointer(pcd->clientFrameWin, grabTime);
3213 case FRAME_RESIZE_NW:
3214 case FRAME_RESIZE_NE:
3215 case FRAME_RESIZE_SW:
3216 case FRAME_RESIZE_SE:
3220 return(FALSE); /* not a valid resize part */
3224 } /* END OF FUNCTION SetPointerResizePart */
3227 /*************************************<->*************************************
3229 * ResizeType (pcd, pev)
3234 * Returns a resize part ID for an event outside of the current
3240 * pcd - pointer to client data
3241 * pev - pointer to event
3250 * o Assumes the static data for resizing has been set up.
3251 *************************************<->***********************************/
3252 int ResizeType (ClientData *pcd, XEvent *pev)
3256 if (!pev) return(FRAME_NONE);
3258 x = pev->xmotion.x_root;
3259 y = pev->xmotion.y_root;
3261 /* if inside all resize areas, then forget it */
3262 if ( (x > resizeX) &&
3264 (x < (resizeX + resizeWidth - 1)) &&
3265 (y < (resizeY + resizeHeight - 1)) )
3272 if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
3273 return (FRAME_RESIZE_NW);
3274 else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
3275 return (FRAME_RESIZE_SW);
3277 return (FRAME_RESIZE_W);
3281 if (x >= resizeX + resizeWidth - 1) {
3282 if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
3283 return (FRAME_RESIZE_NE);
3284 else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
3285 return (FRAME_RESIZE_SE);
3287 return (FRAME_RESIZE_E);
3292 if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
3293 return (FRAME_RESIZE_NW);
3294 else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
3295 return (FRAME_RESIZE_NE);
3297 return (FRAME_RESIZE_N);
3301 if (y >= resizeY + resizeHeight - 1) {
3302 if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
3303 return (FRAME_RESIZE_SW);
3304 else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
3305 return (FRAME_RESIZE_SE);
3307 return (FRAME_RESIZE_S);
3312 } /* END OF FUNCTION ResizeType */
3316 /*************************************<->*************************************
3318 * FixFrameValues (pcd, pfX, pfY, pfWidth, pfHeight, resizing)
3323 * Fix up the frame values so that they do not exceed maximum or minimum
3324 * size and that at least part of the frame is on screen
3329 * pcd - pointer to client data
3330 * pfX - pointer to frame x-coord
3331 * pfY - pointer to frame y-coord
3332 * pfWidth - pointer to frame width
3333 * pfHeight - pointer to frame height
3334 * resizing - check size constraints iff TRUE
3339 * *pfX - fixed up frame x-coord
3340 * *pfY - fixed up frame y-coord
3341 * *pfWidth - fixed up frame width
3342 * *pfHeight - fixed up frame height
3347 * 1. This could be more efficient
3348 * 2. Interactive resize with aspect ratio constraints may cause part of the
3349 * outline to disappear off screen. The critical case is when the title
3350 * bar disappears ABOVE the screen.
3352 *************************************<->***********************************/
3354 void FixFrameValues (ClientData *pcd, int *pfX, int *pfY, unsigned int *pfWidth, unsigned int *pfHeight, Boolean resizing)
3356 unsigned int lswidth;
3357 unsigned int oWidth, oHeight;
3361 * Fix size if resizing and not icon.
3364 if (resizing && !wmGD.movingIcon)
3366 FrameToClient(pcd, pfX, pfY, pfWidth, pfHeight);
3369 oHeight = *pfHeight;
3371 FixWindowSize (pcd, pfWidth, pfHeight, 1, 1);
3373 AdjustPos (pfX, pfY, oWidth, oHeight, *pfWidth, *pfHeight);
3375 ClientToFrame(pcd, pfX, pfY, pfWidth, pfHeight);
3379 * Don't move if we'd end up totally offscreen
3382 if (wmGD.movingIcon)
3384 lswidth = FRAME_BORDER_WIDTH(pcd);
3388 lswidth = pcd->frameInfo.lowerBorderWidth;
3390 if (lswidth < 5) lswidth = 5;
3392 if (wmGD.movingIcon && P_ICON_BOX(pcd))
3395 * Constrain outline to icon box
3397 /* left edge of outline */
3403 /* top of outline */
3409 /* right edge of outline */
3410 if (((int)*pfX) > ((int)clipX + (int)clipWidth - ((int)*pfWidth)))
3412 *pfX = clipX + clipWidth - *pfWidth;
3415 /* bottom edge of outline */
3416 if (((int)*pfY) > ((int)clipY + (int)clipHeight - ((int)*pfHeight)))
3418 *pfY = clipY + clipHeight - *pfHeight;
3425 * keep outline on screen
3429 /* keep right border on screen */
3430 if (*pfX < ((int) lswidth - (int) *pfWidth))
3432 *pfX = (int) lswidth - (int) *pfWidth;
3435 /* keep bottom border on screen */
3436 if (*pfY < ((int) lswidth - (int) *pfHeight))
3438 *pfY = (int) lswidth - (int) *pfHeight;
3441 /* keep left border on screen */
3442 if (*pfX > (DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
3445 *pfX = DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
3449 /* keep top border on screen */
3450 if (*pfY > (DisplayHeight(DISPLAY,SCREEN_FOR_CLIENT(pcd)) -
3453 *pfY = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
3458 } /* END OF FUNCTION FixFrameValues */
3462 /*************************************<->*************************************
3464 * ForceOnScreen (screen, pX, pY)
3469 * Correct (if necessary) the coords specified to make them on screen
3474 * screen - screen number
3475 * pX - pointer to x-coord
3476 * pY - pointer to y-coord
3480 * *pX - x-coord (on screen)
3481 * *pY - y-coord (on screen)
3488 *************************************<->***********************************/
3489 void ForceOnScreen (int screen, int *pX, int *pY)
3491 if (*pX >= (DisplayWidth(DISPLAY, screen)))
3492 *pX = DisplayWidth(DISPLAY, screen) - 1;
3496 if (*pY >= (DisplayHeight(DISPLAY, screen)))
3497 *pY = DisplayHeight(DISPLAY, screen) - 1;
3501 } /* END OF FUNCTION ForceOnScreen */
3504 /*************************************<->*************************************
3506 * SetPointerPosition (newX, newY, actualX, actualY)
3511 * Attempt to set the pointer to position at newX, newY.
3516 * newX - X-coordinate to set pointer at
3517 * newY - Y-coordinate to set pointer at
3522 * *actualX - actual X-coord of pointer on return
3523 * *actualY - actual Y-coord of pointer on return
3528 *************************************<->***********************************/
3529 void SetPointerPosition (int newX, int newY, int *actualX, int *actualY)
3537 if (wmGD.enableWarp)
3539 XWarpPointer(DISPLAY, None, ACTIVE_ROOT,
3540 0, 0, 0, 0, newX, newY);
3545 * Get pointer position
3546 * NOTE: if we are not warping, we don't want to do the Query pointer,
3547 * hence enableWarp is tested first.
3549 if (!wmGD.enableWarp ||
3550 !XQueryPointer (DISPLAY, ACTIVE_ROOT, &junk_win, &junk_win,
3551 actualX, actualY, &junk, &junk, (unsigned int *)&junk))
3554 /* failed to get pointer position or not warping, return something */
3559 } /* END OF FUNCTION SetPointerPositio */
3563 /*************************************<->*************************************
3565 * GetConfigEvent (display, window, mask, curX, curY, oX, oY,
3566 * oWidth, oHeight, pev,)
3571 * Get next configuration event
3576 * display - pointer to display
3577 * window - window to get event relative to
3578 * mask - event mask - acceptable events to return
3579 * pev - pointer to a place to put the event
3580 * curX - current X value of pointer
3581 * curY - current Y value of pointer
3582 * oX - X value of outline
3583 * oY - Y value of outline
3584 * oWidth - width of outline
3585 * oHeight - height of outline
3589 * *pev - event returned.
3594 *************************************<->***********************************/
3595 void GetConfigEvent (Display *display, Window window, unsigned long mask, int curX, int curY, int oX, int oY, unsigned oWidth, unsigned oHeight, XEvent *pev)
3597 Window root_ret, child_ret;
3598 int root_x, root_y, win_x, win_y;
3599 unsigned int mask_ret;
3603 Boolean eventToReturn = False;
3605 while (!eventToReturn)
3608 * Suck up pointer motion events
3611 while (XCheckWindowEvent(display, window, mask, pev))
3614 if (pev->type != MotionNotify)
3619 * Only poll if we are warping the pointer.
3620 * (uses PointerMotionHints exclusively).
3622 polling = wmGD.enableWarp;
3623 pollCount = CONFIG_POLL_COUNT;
3625 if (!gotEvent && (polling || !wmGD.freezeOnConfig))
3628 * poll for events and flash the frame outline
3629 * if not move opaque
3634 if (XCheckWindowEvent(display, window,
3635 (mask & ~PointerMotionMask), pev))
3641 if (!wmGD.freezeOnConfig && !wmGD.pActiveSD->moveOpaque)
3643 /* flash the outline if server is not grabbed */
3644 MoveOutline (oX, oY, oWidth, oHeight);
3647 if (!XQueryPointer (display, window, &root_ret, &child_ret,
3648 &root_x, &root_y, &win_x, &win_y, &mask_ret))
3650 continue; /* query failed, try again */
3653 if ((root_x != curX) || (root_y != curY))
3656 * Pointer moved to a new position.
3657 * Cobble a motion event together.
3658 * NOTE: SOME FIELDS NOT SET !!!
3661 pev->type = MotionNotify;
3662 /* pev->xmotion.serial = ??? */
3663 pev->xmotion.send_event = False;
3664 pev->xmotion.display = display;
3665 pev->xmotion.window = root_ret;
3666 pev->xmotion.subwindow = child_ret;
3667 pev->xmotion.time = CurrentTime; /* !!! !!! */
3668 pev->xmotion.x = root_x;
3669 pev->xmotion.y = root_y;
3670 pev->xmotion.x_root = root_x;
3671 pev->xmotion.y_root = root_y;
3672 /* pev->xmotion.state = ??? */
3673 /* pev->xmotion.is_hint = ???? */
3674 /* pev->xmotion.same_screen = ??? */
3676 eventToReturn = True;
3677 break; /* from while loop */
3679 else if (wmGD.freezeOnConfig)
3684 * No pointer motion in some time. Stop polling
3685 * and wait for next event.
3688 break; /* from while loop */
3694 if (!gotEvent && !polling && wmGD.freezeOnConfig)
3697 * Wait for next event on window
3700 XWindowEvent (display, window, mask, pev);
3706 eventToReturn = True;
3707 if (pev->type == MotionNotify &&
3708 pev->xmotion.is_hint == NotifyHint)
3711 * "Ack" the motion notify hint
3713 if ((XQueryPointer (display, window, &root_ret,
3714 &child_ret, &root_x, &root_y, &win_x,
3715 &win_y, &mask_ret)) &&
3716 ((root_x != curX) ||
3720 * The query pointer values say that the pointer
3721 * moved to a new location.
3723 pev->xmotion.window = root_ret;
3724 pev->xmotion.subwindow = child_ret;
3725 pev->xmotion.x = root_x;
3726 pev->xmotion.y = root_y;
3727 pev->xmotion.x_root = root_x;
3728 pev->xmotion.y_root = root_y;
3733 * Query failed. Change curX to force position
3734 * to be returned on first sucessful query.
3736 eventToReturn = False;
3743 } /* END OF FUNCTION GetConfigEvent */
3746 /*************************************<->*************************************
3748 * SetOutline (pOutline, x, y, width, height, fatness)
3753 * Sets the outline of for config/move/placement operations
3758 * pOutline - ptr to outline structure to fill in
3759 * x - x of upper-left corner of outline
3760 * y - y of upper-left corner of outline
3761 * width - width of outline.
3762 * height - height of outline.
3763 * fatness - pixel-width of outline
3770 * o Be sure that pOutline points to a big enough area of memory
3771 * for the outline to be set!
3773 *************************************<->***********************************/
3775 void SetOutline (XSegment *pOutline, int x, int y, unsigned int width, unsigned int height, int fatness)
3779 for (i=0; i<fatness; i++)
3783 pOutline->x2 = x + width -1;
3786 pOutline->x1 = x + width -1;
3788 pOutline->x2 = x + width -1;
3789 pOutline++->y2 = y + height - 1;
3791 pOutline->x1 = x + width -1;
3792 pOutline->y1 = y + height - 1;
3794 pOutline++->y2 = y + height - 1;
3797 pOutline->y1 = y + height - 1;
3802 * Modify values for next pass (if any)
3803 * Next outline will be on inside of current one.
3811 } /* END OF FUNCTION SetOutline */
3814 /*************************************<->*************************************
3816 * AdjustPos (pX, pY, oWidth, oHeight, nWidth, nHeight)
3821 * Adjusts the position according to wmGD.configPart and any change in
3827 * pX, pY -- pointers to positions
3828 * oWidth, oHeight -- original dimensions
3829 * nWidth, nHeight -- new dimensions
3834 * pX, pY -- pointers to adjusted positions
3839 *************************************<->***********************************/
3841 void AdjustPos (int *pX, int *pY, unsigned int oWidth, unsigned int oHeight, unsigned int nWidth, unsigned int nHeight)
3843 switch (wmGD.configPart)
3845 case FRAME_RESIZE_NW:
3846 /* anchor lower right corner */
3847 *pX += oWidth - nWidth;
3848 *pY += oHeight - nHeight;
3851 case FRAME_RESIZE_N:
3853 *pY += oHeight - nHeight;
3856 case FRAME_RESIZE_NE:
3857 /* anchor lower left corner */
3858 *pY += oHeight - nHeight;
3861 case FRAME_RESIZE_E:
3862 /* anchor left side */
3865 case FRAME_RESIZE_SE:
3866 /* anchor upper left corner */
3869 case FRAME_RESIZE_S:
3873 case FRAME_RESIZE_SW:
3874 /* anchor upper right corner */
3875 *pX += oWidth - nWidth;
3878 case FRAME_RESIZE_W:
3879 /* anchor right side */
3880 *pX += oWidth - nWidth;
3887 } /* END OF FUNCTION AdjustPos */
3891 /*************************************<->*************************************
3893 * GrabWin (pcd, pev)
3898 * return window to do grab on for config operation
3903 * pcd - ptr to client data
3904 * pev - ptr to event
3914 *************************************<->***********************************/
3915 Window GrabWin (ClientData *pcd, XEvent *pev)
3920 * The grab window is the icon if the client is minimized
3921 * or if the event was on a "normalized" icon in the icon box.
3924 if ((pcd->clientState == MINIMIZED_STATE) ||
3925 (pcd->pSD->useIconBox && pev &&
3926 ((pev->xany.window == ICON_FRAME_WIN(pcd)) ||
3927 (pev->xany.window == ACTIVE_ICON_TEXT_WIN))))
3929 grab_win = ICON_FRAME_WIN(pcd);
3932 (pev->xany.window == pcd->clientFrameWin ||
3933 pev->xany.window == pcd->clientBaseWin ))
3935 grab_win = pcd->clientFrameWin;
3937 else if (pcd->pSD->useIconBox &&
3939 wmGD.grabContext == F_SUBCONTEXT_IB_WICON)
3941 grab_win = ICON_FRAME_WIN(pcd);
3945 grab_win = pcd->clientFrameWin;
3950 } /* END OF FUNCTION GrabWin */
3952 /*************************************<->*************************************
3954 * HandleMarqueeSelect (pSD, event)
3959 * Does a marquee selection on the root window
3970 * Selection info is dumped into a root window property:
3971 * _DT_MARQUEE_SELECTION
3973 *************************************<->***********************************/
3975 HandleMarqueeSelect (WmScreenData *pSD, XEvent *pev)
3981 grab_win = RootWindow (DISPLAY, pSD->screen);
3984 while (!bDone && (wmGD.configAction == MARQUEE_SELECT))
3986 if (!pev) /* first time through will already have event */
3990 GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
3991 pointerX, pointerY, resizeX, resizeY,
3992 resizeWidth, resizeHeight, &event);
3995 if (pev->type == MotionNotify)
3997 pointerX = pev->xmotion.x_root;
3998 pointerY = pev->xmotion.y_root;
3999 UpdateMarqueeSelectData (pSD);
4001 else if (pev->type == KeyPress) {
4006 bDone = HandleMarqueeKeyPress (pSD, pev);
4008 else if (pev->type == ButtonRelease) {
4011 * Update (x,y) to the location of the button release
4013 pointerX = pev->xbutton.x_root;
4014 pointerY = pev->xbutton.y_root;
4015 UpdateMarqueeSelectData (pSD);
4016 CompleteFrameConfig ((ClientData *)NULL, pev);
4021 continue; /* ignore this event */
4026 MoveOutline (marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4029 pev = NULL; /* reset event pointer */
4033 } /* END OF FUNCTION HandleMarqueeSelect */
4036 /*************************************<->*************************************
4038 * StartMarqueeSelect ()
4043 * Start marquee selection on root window
4056 *************************************<->***********************************/
4058 StartMarqueeSelect(WmScreenData *pSD, XEvent *pev)
4060 Window grab_win, junk_win;
4065 if (!pSD->bMarqueeSelectionInitialized)
4068 * If we haven't initialized the marquee selection messaging
4069 * then do so here before we do any grabs. Sending a dummy
4072 * (If we move off of ICCCM messaging, then this can go away.)
4074 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END,
4076 pSD->bMarqueeSelectionInitialized = True;
4084 grab_win = RootWindow (DISPLAY, pSD->screen);
4088 grabbed = DoGrabs (grab_win, wmGD.configCursor,
4089 PGRAB_MASK, pev->xbutton.time, NULL, True);
4093 grabbed = DoGrabs (grab_win, wmGD.configCursor,
4094 PGRAB_MASK, CurrentTime, NULL, True);
4104 /* continue with the configuration in progress (!!!) */
4109 * Set up static variables for succeeding events
4111 if (pev && ((pev->type == ButtonPress) || (pev->type == ButtonRelease)))
4113 pointerX = pev->xbutton.x_root;
4114 pointerY = pev->xbutton.y_root;
4116 else if (!XQueryPointer (DISPLAY, pSD->rootWindow,
4117 &junk_win, &junk_win,
4118 &pointerX, &pointerY,
4119 &junk, &junk, (unsigned int *)&junk))
4121 CancelFrameConfig ((ClientData *)NULL); /* release grabs */
4125 /* save start values to see where we came from */
4126 marqueeX = startX = pointerX;
4127 marqueeY = startY = pointerY;
4128 marqueeWidth0 = marqueeWidth = 0;
4129 marqueeHeight0 = marqueeHeight = 0;
4130 marqueeAnchor = ANCHOR_NW;
4132 /* compute increment value for dynamic update */
4133 big_inc = DisplayWidth (DISPLAY, pSD->screen) / 20;
4135 /* set configuring data */
4136 wmGD.configAction = MARQUEE_SELECT;
4137 wmGD.configButton = pev ? pev->xbutton.button: 0;
4139 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_BEGIN,
4140 marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4142 } /* END OF FUNCTION StartMarqueeSelect */
4145 /*************************************<->*************************************
4147 * UpdateMarqueeSelectData ()
4155 * pSD - pointer to screen data
4163 *************************************<->***********************************/
4164 void UpdateMarqueeSelectData (WmScreenData *pSD)
4166 /* validate and update anchor point and marquee data */
4168 switch (marqueeAnchor)
4171 marqueeWidth = pointerX - marqueeX;
4172 marqueeHeight = pointerY - marqueeY;
4174 if (marqueeWidth < 0)
4176 marqueeWidth = -marqueeWidth;
4177 marqueeX = pointerX;
4179 if (marqueeHeight < 0)
4181 marqueeHeight = -marqueeHeight;
4182 marqueeY = pointerY;
4183 marqueeAnchor = ANCHOR_SE;
4187 marqueeAnchor = ANCHOR_NE;
4190 else if (marqueeHeight < 0)
4192 marqueeHeight = -marqueeHeight;
4193 marqueeY = pointerY;
4194 marqueeAnchor = ANCHOR_SW;
4199 marqueeWidth += marqueeX - pointerX;
4200 marqueeHeight = pointerY - marqueeY;
4201 marqueeX = pointerX;
4203 if (marqueeWidth < 0)
4205 marqueeWidth = -marqueeWidth;
4206 marqueeX = pointerX - marqueeWidth;
4208 if (marqueeHeight < 0)
4210 marqueeHeight = -marqueeHeight;
4211 marqueeY = pointerY;
4212 marqueeAnchor = ANCHOR_SW;
4216 marqueeAnchor = ANCHOR_NW;
4219 else if (marqueeHeight < 0)
4221 marqueeHeight = -marqueeHeight;
4222 marqueeY = pointerY;
4223 marqueeAnchor = ANCHOR_SE;
4228 marqueeWidth += marqueeX - pointerX;
4229 marqueeHeight += marqueeY - pointerY;
4230 marqueeX = pointerX;
4231 marqueeY = pointerY;
4233 if (marqueeWidth < 0)
4235 marqueeWidth = -marqueeWidth;
4236 marqueeX = pointerX - marqueeWidth;
4238 if (marqueeHeight < 0)
4240 marqueeHeight = -marqueeHeight;
4241 marqueeY = pointerY - marqueeHeight;
4242 marqueeAnchor = ANCHOR_NW;
4246 marqueeAnchor = ANCHOR_SW;
4249 else if (marqueeHeight < 0)
4251 marqueeHeight = -marqueeHeight;
4252 marqueeY = pointerY - marqueeHeight;
4253 marqueeAnchor = ANCHOR_NE;
4258 marqueeWidth = pointerX - marqueeX;
4259 marqueeHeight += marqueeY - pointerY;
4260 marqueeY = pointerY;
4262 if (marqueeWidth < 0)
4264 marqueeWidth = -marqueeWidth;
4265 marqueeX = pointerX;
4267 if (marqueeHeight < 0)
4269 marqueeHeight = -marqueeHeight;
4270 marqueeY = pointerY - marqueeHeight;
4271 marqueeAnchor = ANCHOR_NE;
4275 marqueeAnchor = ANCHOR_SE;
4278 else if (marqueeHeight < 0)
4280 marqueeHeight = -marqueeHeight;
4281 marqueeY = pointerY - marqueeHeight;
4282 marqueeAnchor = ANCHOR_NW;
4287 if ((wmGD.marqueeSelectGranularity > 0) &&
4288 ((ABS(marqueeWidth-marqueeWidth0) > wmGD.marqueeSelectGranularity) ||
4289 (ABS(marqueeHeight-marqueeHeight0)>wmGD.marqueeSelectGranularity)))
4291 dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_CONTINUE,
4292 marqueeX, marqueeY, marqueeWidth, marqueeHeight);
4294 marqueeWidth0 = marqueeWidth;
4295 marqueeHeight0 = marqueeHeight;
4300 /*************************************<->*************************************
4302 * HandleMarqueeKeyPress (pSD, pev)
4307 * Handles keypress events during resize of window
4312 * pSD - pointer to screen data
4313 * pev - pointer to event
4318 * Return - True if this event completes (or cancels) resizing
4324 *************************************<->***********************************/
4325 Boolean HandleMarqueeKeyPress (WmScreenData *pSD, XEvent *pev)
4333 * Compress repeated keys
4336 while (keyMult <= 10 &&
4337 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
4343 keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
4344 control = (pev->xkey.state & ControlMask) != 0;
4349 CompleteFrameConfig ((ClientData *)NULL, pev);
4353 CancelFrameConfig ((ClientData *)NULL);
4354 CheckEatButtonRelease ((ClientData *)NULL, pev);
4358 return (False); /* ignore this key */
4360 } /* end switch(keysym) */
4362 } /* END OF FUNCTION HandleResizeKeyPress */