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 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$XConsortium: WmCPlace.c /main/5 1996/08/09 15:18:04 rswiston $"
36 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
44 #include <X11/keysymdef.h>
46 /* absolute value macro */
48 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
51 #define GRAB_MASK (KeyPressMask | ButtonPressMask | ButtonReleaseMask |\
53 #define PGRAB_MASK (ButtonPressMask | ButtonReleaseMask |\
54 PointerMotionMask | PointerMotionHintMask)
56 #define NOFRZ_GRAB_MASK (KeyPressMask | ButtonPressMask |\
58 #define NOFRZ_PGRAB_MASK (ButtonPressMask | ButtonReleaseMask)
61 * include extern functions
65 #include "WmFeedback.h"
66 #include "WmWinConf.h"
73 static unsigned int placeWidth;
74 static unsigned int placeHeight;
76 static Boolean placeResize;
77 static Boolean placementDone;
78 static int placePointerX;
79 static int placePointerY;
80 static int placeKeyMultiplier;
82 static int placeOffsetX;
83 static int placeOffsetY;
87 /*************************************<->*************************************
89 * SetupPlacement (pcd)
94 * Perform the initialization for interactive placement
99 * pcd - pointer to client data
107 * o sets up global data and puts initial display on the screen
109 *************************************<->***********************************/
110 void SetupPlacement (ClientData *pcd)
116 * Restore the state of the last "depressed" frame gadget
119 if (wmGD.gadgetClient && wmGD.gadgetDepressed)
121 PopGadgetOut(wmGD.gadgetClient, wmGD.gadgetDepressed);
125 /* get offset of frame origin from window origin */
126 placeOffsetX = pcd->clientOffset.x;
127 placeOffsetY = pcd->clientOffset.y;
129 XQueryPointer (DISPLAY, ACTIVE_ROOT,
130 &junk_win, &junk_win,
131 &cX, &cY, &junk, &junk, (unsigned int *)&junk);
133 /* convert to frame coordinates */
134 placePointerX = placeX = cX;
135 placePointerY = placeY = cY;
136 placeWidth = pcd->clientWidth;
137 placeHeight = pcd->clientHeight;
138 ClientToFrame (pcd, &cX, &cY, &placeWidth, &placeHeight);
140 /* in "position" mode to start with */
142 wmGD.preMove = FALSE;
144 /* normal window being dealt with, not icon */
145 wmGD.movingIcon = FALSE;
147 if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
149 DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
150 (FB_SIZE | FB_POSITION), placeResize);
153 /* set up initial visual feedback */
154 MoveOutline (placeX, placeY, placeWidth, placeHeight);
156 } /* END OF FUNCTION SetupPlacement */
159 /*************************************<->*************************************
161 * IsRepeatedKeyEvent (dpy, pEvent, pOldEvent)
166 * Returns TRUE if the event passed in is a repeat of the key event
167 * indicated in pOldEvent
173 * pEvent - pointer to this event
174 * pOldEvent - pointer to previous event (cast to the correct type)
179 * IsRepeatedKeyEvent - True if the events are "the same,"
186 *************************************<->***********************************/
187 Bool IsRepeatedKeyEvent (Display *dpy, XEvent *pEvent, char *pOldEvent)
189 XEvent *pOld = (XEvent *) pOldEvent;
191 if ((pEvent->type == KeyPress) && /* key press event */
192 (pEvent->type == pOld->type) && /* same event type */
193 (pEvent->xkey.keycode == pOld->xkey.keycode) && /* same key code */
194 (pEvent->xkey.state == pOld->xkey.state) && /* same modifiers */
195 (pEvent->xkey.window == pOld->xkey.window) && /* same window */
196 (pEvent->xkey.root == pOld->xkey.root)) /* same root */
207 /*************************************<->*************************************
209 * StartInteractiveSizing (pcd, time)
214 * Switch from "position" mode to "resize" mode
219 * pcd - pointer to client data
220 * time - time stamp of event for pointer regrab
230 *************************************<->***********************************/
231 void StartInteractiveSizing (ClientData *pcd, Time time)
235 /* regrab pointer to change cursor */
236 gmask = (wmGD.freezeOnConfig)? PGRAB_MASK : NOFRZ_PGRAB_MASK;
237 XChangeActivePointerGrab (DISPLAY, gmask,
238 wmGD.sizePlacementCursor, time);
240 /* put cursor at lower-right corner */
243 XWarpPointer (DISPLAY, None, ACTIVE_ROOT, 0, 0, 0, 0,
244 (int) (placeX+placeWidth-1), (int) (placeY+placeHeight-1));
248 * Don't go into resize mode if resize is turned off.
250 if (pcd->clientFunctions & MWM_FUNC_RESIZE)
254 wmGD.preMove = FALSE;
259 /*************************************<->*************************************
261 * HandlePlacementKeyEvent (pcd, pev)
266 * Handle key presses during interactive placement
271 * pcd - pointer to client data
272 * pev - pointer to key press event
281 *************************************<->***********************************/
283 void HandlePlacementKeyEvent (ClientData *pcd, XKeyEvent *pev)
287 Boolean control, valid;
291 int warpX, warpY, newX, newY;
292 int keyPlaceX = placeX;
293 int keyPlaceY = placeY;
294 unsigned int keyPlaceWidth = placeWidth;
295 unsigned int keyPlaceHeight = placeHeight;
297 /* filter out repeating keys */
298 placeKeyMultiplier = 1;
299 if (pev->type == KeyPress)
301 while (placeKeyMultiplier <= 10 &&
302 XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
305 placeKeyMultiplier++;
309 /* convert event data to useful key data */
310 keysym = XKeycodeToKeysym (DISPLAY, pev->keycode, 0);
311 control = (pev->state & ControlMask) != 0;
312 big_inc = DisplayWidth(DISPLAY, ACTIVE_PSD->screen) / 20;
314 /* interpret key data */
319 tmpX = (control) ? (-big_inc) : -1;
324 tmpY = (control) ? (-big_inc) : -1;
329 tmpX = (control) ? (big_inc) : 1;
334 tmpY = (control) ? (big_inc) : 1;
339 StartInteractiveSizing(pcd, pev->time);
343 placementDone = TRUE; /* global "done" flag */
351 /* if a valid key was pressed, then react to it */
353 tmpX *= placeKeyMultiplier;
354 tmpY *= placeKeyMultiplier;
358 keyPlaceWidth += tmpX; /* change size of outline */
359 keyPlaceHeight += tmpY;
361 FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth,
362 &keyPlaceHeight, placeResize);
364 warpX = keyPlaceX+keyPlaceWidth-1;
365 warpY = keyPlaceY+keyPlaceHeight-1;
367 SetPointerPosition (warpX, warpY, &newX, &newY);
369 if ((warpX == newX) && (warpY == newY))
371 placeWidth = keyPlaceWidth;
372 placeHeight = keyPlaceHeight;
376 placeWidth = newX - keyPlaceX + 1;
377 placeHeight = newY - keyPlaceY + 1;
382 keyPlaceX += tmpX; /* change position of outline */
385 FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth,
386 &keyPlaceHeight, placeResize);
391 SetPointerPosition (warpX, warpY, &newX, &newY);
396 placePointerX = newX;
397 placePointerY = newY;
399 FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight,
402 MoveOutline (placeX, placeY, placeWidth, placeHeight);
404 if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
406 DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
409 } /* END OF FUNCTION HandlePlacementKeyEvent */
412 /*************************************<->*************************************
414 * HandlePlacementButtonEvent (pev)
424 * pev - pointer to button event
433 *************************************<->***********************************/
435 void HandlePlacementButtonEvent (XButtonEvent *pev)
438 * Only listen to button 1
440 if (pev->button == 1)
443 * Complete interactive placement on button release
445 if (pev->type == ButtonRelease)
447 placementDone = TRUE; /* global done flag */
450 else if (pev->type == ButtonPress)
454 * Button press, go to pre-resize mode
456 wmGD.preMoveX = pev->x_root;
457 wmGD.preMoveY = pev->y_root;
465 /*************************************<->*************************************
467 * HandlePlacementMotionEvent (pcd, pev)
472 * Handles pointer motion events during interactive placement
477 * pcd - pointer to client data
478 * pev - pointer to mouse motion event
488 *************************************<->***********************************/
490 void HandlePlacementMotionEvent (ClientData *pcd, XMotionEvent *pev)
495 * If in pre-resize mode, check for motion crossing threshhold before
499 diffx = pev->x_root - wmGD.preMoveX;
500 diffy = pev->y_root - wmGD.preMoveY;
501 if ((ABS(diffx) > wmGD.moveThreshold) ||
502 (ABS(diffy) > wmGD.moveThreshold))
504 StartInteractiveSizing(pcd, pev->time);
511 * Track lower right corner
513 if (pev->x_root > placeX)
514 placeWidth = pev->x_root - placeX + 1;
515 if (pev->y_root > placeY)
516 placeHeight = pev->y_root - placeY + 1;
520 * track window position
522 placeX = pev->x_root;
523 placeY = pev->y_root;
526 placePointerX = pev->x_root;
527 placePointerY = pev->y_root;
529 FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight,
532 MoveOutline (placeX, placeY, placeWidth, placeHeight);
534 if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT)
536 DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight,
539 } /* END OF FUNCTION HandlePlacementMotionEvent */
543 /*************************************<->*************************************
550 * Gets window configuration from the user via pointer/keyboard interaction
555 * pcd - pointer to client data
560 * pcd - clientX, clientY, clientWidth, and clientHeight members
565 * We try to be careful only to remove events that we need from the
566 * event queue while we're in our own event processing loop.
568 *************************************<->***********************************/
569 void DoPlacement (ClientData *pcd)
576 SetupPlacement (pcd);
581 placementDone = FALSE;
582 while (!placementDone)
584 GetConfigEvent (DISPLAY, ACTIVE_ROOT, GRAB_MASK,
585 placePointerX, placePointerY, placeX, placeY,
586 placeWidth, placeHeight, &event);
588 switch (event.type) {
590 HandlePlacementKeyEvent(pcd, (XKeyEvent *)&event);
594 HandlePlacementButtonEvent((XButtonEvent *)&event);
598 HandlePlacementButtonEvent((XButtonEvent *)&event);
602 HandlePlacementMotionEvent(pcd, (XMotionEvent *)&event);
608 /* copy back the configuration information */
609 pcd->clientX = placeX + placeOffsetX;
610 pcd->clientY = placeY + placeOffsetY;
611 pcd->clientWidth = placeWidth - 2*placeOffsetX;
612 pcd->clientHeight = placeHeight - placeOffsetX - placeOffsetY;
615 MoveOutline (0,0,0,0);
616 HideFeedbackWindow(pcd->pSD);
618 } /* END OF FUNCTION DoPlacement */
622 /*************************************<->*************************************
624 * PlaceWindowInteractively(pcd)
629 * Gets the clients size and position information interactively from the
635 * pcd - pointer to client data
645 *************************************<->***********************************/
646 void PlaceWindowInteractively (ClientData *pcd)
650 gmask = (wmGD.freezeOnConfig)? PGRAB_MASK : NOFRZ_PGRAB_MASK;
653 * Return if config is in progress or if grabs fail
655 if (!DoGrabs (ACTIVE_ROOT, wmGD.movePlacementCursor,
656 gmask, CurrentTime, pcd, True))
662 * Get the size and position of the window from the user.
663 * Do our own event processing until a button-up event occurs
668 * Finish up and return the data
671 wmGD.preMove = FALSE;