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 OPEN SOFTWARE FOUNDATION, INC.
31 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
39 #include <X11/keysymdef.h>
41 /* absolute value macro */
43 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
46 #define GRAB_MASK (KeyPressMask | ButtonPressMask | ButtonReleaseMask |\
48 #define PGRAB_MASK (ButtonPressMask | ButtonReleaseMask |\
49 PointerMotionMask | PointerMotionHintMask)
51 #define NOFRZ_GRAB_MASK (KeyPressMask | ButtonPressMask |\
53 #define NOFRZ_PGRAB_MASK (ButtonPressMask | ButtonReleaseMask)
56 * include extern functions
60 #include "WmFeedback.h"
61 #include "WmWinConf.h"
68 static unsigned int placeWidth;
69 static unsigned int placeHeight;
71 static Boolean placeResize;
72 static Boolean placementDone;
73 static int placePointerX;
74 static int placePointerY;
75 static int placeKeyMultiplier;
77 static int placeOffsetX;
78 static int placeOffsetY;
82 /*************************************<->*************************************
84 * SetupPlacement (pcd)
89 * Perform the initialization for interactive placement
94 * pcd - pointer to client data
102 * o sets up global data and puts initial display on the screen
104 *************************************<->***********************************/
105 void SetupPlacement (ClientData *pcd)
111 * Restore the state of the last "depressed" frame gadget
114 if (wmGD.gadgetClient && wmGD.gadgetDepressed)
116 PopGadgetOut(wmGD.gadgetClient, wmGD.gadgetDepressed);
120 /* get offset of frame origin from window origin */
121 placeOffsetX = pcd->clientOffset.x;
122 placeOffsetY = pcd->clientOffset.y;
124 XQueryPointer (DISPLAY, ACTIVE_ROOT,
125 &junk_win, &junk_win,
126 &cX, &cY, &junk, &junk, (unsigned int *)&junk);
128 /* convert to frame coordinates */
129 placePointerX = placeX = cX;
130 placePointerY = placeY = cY;
131 placeWidth = pcd->clientWidth;
132 placeHeight = pcd->clientHeight;
133 ClientToFrame (pcd, &cX, &cY, &placeWidth, &placeHeight);
135 /* in "position" mode to start with */
137 wmGD.preMove = FALSE;
139 /* normal window being dealt with, not icon */
140 wmGD.movingIcon = FALSE;
142 if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
144 DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
145 (FB_SIZE | FB_POSITION), placeResize);
148 /* set up initial visual feedback */
149 MoveOutline (placeX, placeY, placeWidth, placeHeight);
151 } /* END OF FUNCTION SetupPlacement */
154 /*************************************<->*************************************
156 * IsRepeatedKeyEvent (dpy, pEvent, pOldEvent)
161 * Returns TRUE if the event passed in is a repeat of the key event
162 * indicated in pOldEvent
168 * pEvent - pointer to this event
169 * pOldEvent - pointer to previous event (cast to the correct type)
174 * IsRepeatedKeyEvent - True if the events are "the same,"
181 *************************************<->***********************************/
182 Bool IsRepeatedKeyEvent (Display *dpy, XEvent *pEvent, char *pOldEvent)
184 XEvent *pOld = (XEvent *) pOldEvent;
186 if ((pEvent->type == KeyPress) && /* key press event */
187 (pEvent->type == pOld->type) && /* same event type */
188 (pEvent->xkey.keycode == pOld->xkey.keycode) && /* same key code */
189 (pEvent->xkey.state == pOld->xkey.state) && /* same modifiers */
190 (pEvent->xkey.window == pOld->xkey.window) && /* same window */
191 (pEvent->xkey.root == pOld->xkey.root)) /* same root */
202 /*************************************<->*************************************
204 * StartInteractiveSizing (pcd, time)
209 * Switch from "position" mode to "resize" mode
214 * pcd - pointer to client data
215 * time - time stamp of event for pointer regrab
225 *************************************<->***********************************/
226 void StartInteractiveSizing (ClientData *pcd, Time time)
230 /* regrab pointer to change cursor */
231 gmask = (wmGD.freezeOnConfig)? PGRAB_MASK : NOFRZ_PGRAB_MASK;
232 XChangeActivePointerGrab (DISPLAY, gmask,
233 wmGD.sizePlacementCursor, time);
235 /* put cursor at lower-right corner */
238 XWarpPointer (DISPLAY, None, ACTIVE_ROOT, 0, 0, 0, 0,
239 (int) (placeX+placeWidth-1), (int) (placeY+placeHeight-1));
243 * Don't go into resize mode if resize is turned off.
245 if (pcd->clientFunctions & MWM_FUNC_RESIZE)
249 wmGD.preMove = FALSE;
254 /*************************************<->*************************************
256 * HandlePlacementKeyEvent (pcd, pev)
261 * Handle key presses during interactive placement
266 * pcd - pointer to client data
267 * pev - pointer to key press event
276 *************************************<->***********************************/
278 void HandlePlacementKeyEvent (ClientData *pcd, XKeyEvent *pev)
282 Boolean control, valid;
286 int warpX, warpY, newX, newY;
287 int keyPlaceX = placeX;
288 int keyPlaceY = placeY;
289 unsigned int keyPlaceWidth = placeWidth;
290 unsigned int keyPlaceHeight = placeHeight;
292 /* filter out repeating keys */
293 placeKeyMultiplier = 1;
294 if (pev->type == KeyPress)
296 while (placeKeyMultiplier <= 10 &&
297 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
300 placeKeyMultiplier++;
304 /* convert event data to useful key data */
305 keysym = XKeycodeToKeysym (DISPLAY, pev->keycode, 0);
306 control = (pev->state & ControlMask) != 0;
307 big_inc = DisplayWidth(DISPLAY, ACTIVE_PSD->screen) / 20;
309 /* interpret key data */
314 tmpX = (control) ? (-big_inc) : -1;
319 tmpY = (control) ? (-big_inc) : -1;
324 tmpX = (control) ? (big_inc) : 1;
329 tmpY = (control) ? (big_inc) : 1;
334 StartInteractiveSizing(pcd, pev->time);
338 placementDone = TRUE; /* global "done" flag */
346 /* if a valid key was pressed, then react to it */
348 tmpX *= placeKeyMultiplier;
349 tmpY *= placeKeyMultiplier;
353 keyPlaceWidth += tmpX; /* change size of outline */
354 keyPlaceHeight += tmpY;
356 FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth,
357 &keyPlaceHeight, placeResize);
359 warpX = keyPlaceX+keyPlaceWidth-1;
360 warpY = keyPlaceY+keyPlaceHeight-1;
362 SetPointerPosition (warpX, warpY, &newX, &newY);
364 if ((warpX == newX) && (warpY == newY))
366 placeWidth = keyPlaceWidth;
367 placeHeight = keyPlaceHeight;
371 placeWidth = newX - keyPlaceX + 1;
372 placeHeight = newY - keyPlaceY + 1;
377 keyPlaceX += tmpX; /* change position of outline */
380 FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth,
381 &keyPlaceHeight, placeResize);
386 SetPointerPosition (warpX, warpY, &newX, &newY);
391 placePointerX = newX;
392 placePointerY = newY;
394 FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight,
397 MoveOutline (placeX, placeY, placeWidth, placeHeight);
399 if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
401 DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
404 } /* END OF FUNCTION HandlePlacementKeyEvent */
407 /*************************************<->*************************************
409 * HandlePlacementButtonEvent (pev)
419 * pev - pointer to button event
428 *************************************<->***********************************/
430 void HandlePlacementButtonEvent (XButtonEvent *pev)
433 * Only listen to button 1
435 if (pev->button == 1)
438 * Complete interactive placement on button release
440 if (pev->type == ButtonRelease)
442 placementDone = TRUE; /* global done flag */
445 else if (pev->type == ButtonPress)
449 * Button press, go to pre-resize mode
451 wmGD.preMoveX = pev->x_root;
452 wmGD.preMoveY = pev->y_root;
460 /*************************************<->*************************************
462 * HandlePlacementMotionEvent (pcd, pev)
467 * Handles pointer motion events during interactive placement
472 * pcd - pointer to client data
473 * pev - pointer to mouse motion event
483 *************************************<->***********************************/
485 void HandlePlacementMotionEvent (ClientData *pcd, XMotionEvent *pev)
490 * If in pre-resize mode, check for motion crossing threshold before
494 diffx = pev->x_root - wmGD.preMoveX;
495 diffy = pev->y_root - wmGD.preMoveY;
496 if ((ABS(diffx) > wmGD.moveThreshold) ||
497 (ABS(diffy) > wmGD.moveThreshold))
499 StartInteractiveSizing(pcd, pev->time);
506 * Track lower right corner
508 if (pev->x_root > placeX)
509 placeWidth = pev->x_root - placeX + 1;
510 if (pev->y_root > placeY)
511 placeHeight = pev->y_root - placeY + 1;
515 * track window position
517 placeX = pev->x_root;
518 placeY = pev->y_root;
521 placePointerX = pev->x_root;
522 placePointerY = pev->y_root;
524 FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight,
527 MoveOutline (placeX, placeY, placeWidth, placeHeight);
529 if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
531 DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
534 } /* END OF FUNCTION HandlePlacementMotionEvent */
538 /*************************************<->*************************************
545 * Gets window configuration from the user via pointer/keyboard interaction
550 * pcd - pointer to client data
555 * pcd - clientX, clientY, clientWidth, and clientHeight members
560 * We try to be careful only to remove events that we need from the
561 * event queue while we're in our own event processing loop.
563 *************************************<->***********************************/
564 void DoPlacement (ClientData *pcd)
571 SetupPlacement (pcd);
576 placementDone = FALSE;
577 while (!placementDone)
579 GetConfigEvent (DISPLAY, ACTIVE_ROOT, GRAB_MASK,
580 placePointerX, placePointerY, placeX, placeY,
581 placeWidth, placeHeight, &event);
583 switch (event.type) {
585 HandlePlacementKeyEvent(pcd, (XKeyEvent *)&event);
589 HandlePlacementButtonEvent((XButtonEvent *)&event);
593 HandlePlacementButtonEvent((XButtonEvent *)&event);
597 HandlePlacementMotionEvent(pcd, (XMotionEvent *)&event);
603 /* copy back the configuration information */
604 pcd->clientX = placeX + placeOffsetX;
605 pcd->clientY = placeY + placeOffsetY;
606 pcd->clientWidth = placeWidth - 2*placeOffsetX;
607 pcd->clientHeight = placeHeight - placeOffsetX - placeOffsetY;
610 MoveOutline (0,0,0,0);
611 HideFeedbackWindow(pcd->pSD);
613 } /* END OF FUNCTION DoPlacement */
617 /*************************************<->*************************************
619 * PlaceWindowInteractively(pcd)
624 * Gets the clients size and position information interactively from the
630 * pcd - pointer to client data
640 *************************************<->***********************************/
641 void PlaceWindowInteractively (ClientData *pcd)
645 gmask = (wmGD.freezeOnConfig)? PGRAB_MASK : NOFRZ_PGRAB_MASK;
648 * Return if config is in progress or if grabs fail
650 if (!DoGrabs (ACTIVE_ROOT, wmGD.movePlacementCursor,
651 gmask, CurrentTime, pcd, True))
657 * Get the size and position of the window from the user.
658 * Do our own event processing until a button-up event occurs
663 * Finish up and return the data
666 wmGD.preMove = FALSE;