4363 lines
97 KiB
C
4363 lines
97 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
|
|
* ALL RIGHTS RESERVED
|
|
*/
|
|
/*
|
|
* Motif Release 1.2.2
|
|
*/
|
|
/*
|
|
* (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
|
|
|
|
/*
|
|
* Included Files:
|
|
*/
|
|
#include "WmGlobal.h" /* This should be the first include */
|
|
#include <X11/X.h>
|
|
|
|
#define XK_MISCELLANY
|
|
#include <X11/keysymdef.h>
|
|
|
|
|
|
#define MOVE_OUTLINE_WIDTH 2
|
|
|
|
#define CONFIG_MASK (KeyPressMask|ButtonPressMask|\
|
|
ButtonReleaseMask|PointerMotionMask)
|
|
#define PGRAB_MASK (ButtonPressMask|ButtonReleaseMask|\
|
|
PointerMotionMask|PointerMotionHintMask)
|
|
|
|
/* grab types */
|
|
|
|
#define NotGrabbed 0
|
|
#define ResizeGrab 1
|
|
#define MoveGrab 2
|
|
|
|
/* Anchors */
|
|
#define ANCHOR_NONE 0
|
|
#define ANCHOR_NW 1
|
|
#define ANCHOR_NE 2
|
|
#define ANCHOR_SE 3
|
|
#define ANCHOR_SW 4
|
|
|
|
#ifndef ABS
|
|
#define ABS(x) ((x)>0?(x):(-(x)))
|
|
#endif /* ABS */
|
|
|
|
/* number of times to poll before blocking on a config event */
|
|
|
|
#define CONFIG_POLL_COUNT 300
|
|
|
|
/* mask for all buttons */
|
|
#define ButtonMask \
|
|
(Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
|
|
|
|
/*
|
|
* include extern functions
|
|
*/
|
|
#include "WmWinConf.h"
|
|
#include "WmCDInfo.h"
|
|
#include "WmCDecor.h"
|
|
#include "WmCPlace.h"
|
|
#include "WmEvent.h"
|
|
#include "WmFeedback.h"
|
|
#include "WmFunction.h"
|
|
#include "WmIDecor.h"
|
|
#include "WmIPC.h"
|
|
#include "WmIPlace.h"
|
|
#include "WmIconBox.h"
|
|
#include "WmKeyFocus.h"
|
|
#include "WmProtocol.h"
|
|
#include "WmWinInfo.h"
|
|
|
|
|
|
|
|
/*
|
|
* Global Variables:
|
|
*
|
|
* These statics are set up at the initiation of a configuration
|
|
* operation and used for succeeding events.
|
|
*/
|
|
|
|
static int pointerX = -1;
|
|
static int pointerY = -1;
|
|
|
|
static int offsetX = 0;
|
|
static int offsetY = 0;
|
|
|
|
static int resizeX, resizeY; /* root coords of UL corner of frame */
|
|
static unsigned int resizeWidth, resizeHeight; /* size of frame */
|
|
static unsigned int resizeBigWidthInc, resizeBigHeightInc;
|
|
static int startX, startY;
|
|
static unsigned int startWidth, startHeight;
|
|
static unsigned int minWidth, minHeight, maxHeight, maxWidth;
|
|
static int marqueeX, marqueeY; /* root coords of UL corner of are */
|
|
static long marqueeWidth, marqueeHeight; /* size of area */
|
|
static unsigned int marqueeAnchor; /* id of anchor corner */
|
|
static long marqueeWidth0, marqueeHeight0; /* old size of area */
|
|
|
|
static int opaqueMoveX = 0; /* for cancel request on opaque moves */
|
|
static int opaqueMoveY = 0;
|
|
static int moveX = 0; /* root coords of UL corner of frame */
|
|
static int moveY = 0;
|
|
static int moveIBbbX = 0; /* root coords of icon box bulletin board */
|
|
static int moveIBbbY = 0;
|
|
static unsigned int moveWidth = 0; /* size of frame */
|
|
static unsigned int moveHeight = 0;
|
|
static int moveLastPointerX = 0; /* last pointer position */
|
|
static int moveLastPointerY= 0;
|
|
|
|
static Boolean anyMotion = FALSE;
|
|
static Boolean configGrab = FALSE;
|
|
|
|
Dimension clipWidth = 0;
|
|
Dimension clipHeight = 0;
|
|
Position clipX = 0;
|
|
Position clipY = 0;
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* GetClipDimensions (pcd, fromRoot)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*************************************<->***********************************/
|
|
void GetClipDimensions (ClientData *pCD, Boolean fromRoot)
|
|
{
|
|
|
|
int i;
|
|
Arg getArgs[5];
|
|
Position tmpX, tmpY;
|
|
|
|
i=0;
|
|
XtSetArg (getArgs[i], XmNwidth, (XtArgVal) &clipWidth ); i++;
|
|
XtSetArg (getArgs[i], XmNheight, (XtArgVal) &clipHeight ); i++;
|
|
XtSetArg (getArgs[i], XmNx, (XtArgVal) &tmpX ); i++;
|
|
XtSetArg (getArgs[i], XmNy, (XtArgVal) &tmpY ); i++;
|
|
|
|
XtGetValues (P_ICON_BOX(pCD)->clipWidget, getArgs, i);
|
|
|
|
if (fromRoot)
|
|
{
|
|
XtTranslateCoords(P_ICON_BOX(pCD)->scrolledWidget,
|
|
tmpX, tmpY,
|
|
&clipX, &clipY);
|
|
}
|
|
else
|
|
{
|
|
clipX = tmpX;
|
|
clipY = tmpY;
|
|
}
|
|
|
|
} /* END OF FUNCTION GetClipDimensions */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* HandleClientFrameMove (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Provide visual feedback of interactive moving of the window.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*************************************<->***********************************/
|
|
void HandleClientFrameMove (ClientData *pcd, XEvent *pev)
|
|
{
|
|
int tmpX, tmpY, warpX, warpY;
|
|
Window grab_win;
|
|
KeySym keysym;
|
|
Boolean control, moveDone;
|
|
Boolean firstTime;
|
|
int big_inc, keyMultiplier;
|
|
int newX, newY;
|
|
XEvent event, KeyEvent;
|
|
|
|
if (pev) {
|
|
firstTime = True;
|
|
}
|
|
else {
|
|
firstTime = False;
|
|
}
|
|
|
|
big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
|
|
|
|
|
|
/*
|
|
* Do our grabs and initial setup if we're just starting out
|
|
*/
|
|
if (!configGrab) {
|
|
if (!StartClientMove (pcd, pev))
|
|
{
|
|
/* configuration was not initiated */
|
|
return;
|
|
}
|
|
}
|
|
|
|
grab_win = GrabWin (pcd, pev);
|
|
|
|
|
|
if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
|
|
{
|
|
GetClipDimensions (pcd, True);
|
|
}
|
|
|
|
moveDone = False;
|
|
while (!moveDone)
|
|
{
|
|
tmpX = tmpY = 0;
|
|
|
|
if (firstTime) {
|
|
/* handle the event we were called with first */
|
|
firstTime = False;
|
|
}
|
|
else
|
|
{
|
|
pev = &event;
|
|
GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
|
|
moveLastPointerX, moveLastPointerY, moveX, moveY,
|
|
moveWidth, moveHeight, &event);
|
|
}
|
|
|
|
if (pev->type == KeyPress)
|
|
{
|
|
keyMultiplier = 1;
|
|
while (keyMultiplier <= big_inc &&
|
|
XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
|
|
(char *) pev))
|
|
{
|
|
keyMultiplier++;
|
|
}
|
|
|
|
keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
|
|
control = (pev->xkey.state & ControlMask) != 0;
|
|
tmpX = tmpY = 0;
|
|
|
|
switch (keysym) {
|
|
case XK_Left:
|
|
tmpX = keyMultiplier * ((control) ? (-big_inc) : (-1));
|
|
break;
|
|
|
|
case XK_Up:
|
|
tmpY = keyMultiplier * ((control) ? (-big_inc) : (-1));
|
|
break;
|
|
|
|
case XK_Right:
|
|
tmpX = keyMultiplier * ((control) ? big_inc : 1);
|
|
break;
|
|
|
|
case XK_Down:
|
|
tmpY = keyMultiplier * ((control) ? big_inc : 1);
|
|
break;
|
|
|
|
case XK_Return:
|
|
CompleteFrameConfig (pcd, pev);
|
|
return;
|
|
|
|
case XK_Escape:
|
|
CancelFrameConfig (pcd);
|
|
CheckEatButtonRelease (pcd, pev);
|
|
return;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (tmpX || tmpY) {
|
|
warpX = moveLastPointerX + tmpX;
|
|
warpY = moveLastPointerY + tmpY;
|
|
|
|
ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
|
|
|
|
if ((warpX != moveLastPointerX) || (warpY != moveLastPointerY))
|
|
{
|
|
SetPointerPosition (warpX, warpY, &newX, &newY);
|
|
|
|
tmpX = newX - moveLastPointerX;
|
|
tmpY = newY - moveLastPointerY;
|
|
moveLastPointerX = newX;
|
|
moveLastPointerY = newY;
|
|
moveX += tmpX;
|
|
moveY += tmpY;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* make like motion event and move frame.
|
|
*/
|
|
moveX += tmpX;
|
|
moveY += tmpY;
|
|
}
|
|
}
|
|
}
|
|
else if (pev->type == ButtonRelease)
|
|
{
|
|
/*
|
|
* Update (x,y) to the location of the button release
|
|
*/
|
|
moveX += pev->xbutton.x_root - moveLastPointerX;
|
|
moveY += pev->xbutton.y_root - moveLastPointerY;
|
|
|
|
CompleteFrameConfig (pcd, pev);
|
|
moveDone = True;
|
|
}
|
|
else if (pev->type == MotionNotify)
|
|
{
|
|
tmpX = pev->xmotion.x_root - moveLastPointerX;
|
|
tmpY = pev->xmotion.y_root - moveLastPointerY;
|
|
moveLastPointerX = pev->xmotion.x_root;
|
|
moveLastPointerY = pev->xmotion.y_root;
|
|
moveX += tmpX;
|
|
moveY += tmpY;
|
|
anyMotion = True;
|
|
}
|
|
|
|
/* draw outline if there is something to draw */
|
|
if (tmpX || tmpY) {
|
|
FixFrameValues (pcd, &moveX, &moveY, &moveWidth, &moveHeight,
|
|
FALSE /* no size checks */);
|
|
if (pcd->pSD->moveOpaque)
|
|
{
|
|
MoveOpaque (pcd, moveX, moveY, moveWidth, moveHeight);
|
|
}
|
|
else
|
|
{
|
|
MoveOutline(moveX, moveY, moveWidth, moveHeight);
|
|
}
|
|
|
|
if ( !wmGD.movingIcon &&
|
|
(wmGD.showFeedback & WM_SHOW_FB_MOVE))
|
|
{
|
|
DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight,
|
|
(unsigned long) 0, FALSE /* no size checks */);
|
|
}
|
|
}
|
|
}
|
|
|
|
} /* END OF FUNCTION HandleClientFrameMove */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* UpdateAndDrawResize ()
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*************************************<->***********************************/
|
|
void UpdateAndDrawResize (ClientData *pcd)
|
|
{
|
|
int tmpHeight, tmpWidth;
|
|
|
|
/*
|
|
* Handle a motion event or a keypress that's like a motion
|
|
* event
|
|
*/
|
|
|
|
/* set height */
|
|
|
|
switch (wmGD.configPart) {
|
|
case FRAME_RESIZE_NW:
|
|
case FRAME_RESIZE_N:
|
|
case FRAME_RESIZE_NE:
|
|
tmpHeight = (int) startHeight + (startY - pointerY);
|
|
if (tmpHeight < (int) minHeight)
|
|
{
|
|
resizeHeight = minHeight;
|
|
resizeY = startY + startHeight - minHeight;
|
|
}
|
|
else if (pcd->pSD->limitResize
|
|
&& (tmpHeight > (int) maxHeight)
|
|
&& (!(pcd->clientFlags & ICON_BOX)))
|
|
{
|
|
resizeHeight = maxHeight;
|
|
resizeY = startY + startHeight - maxHeight;
|
|
}
|
|
else
|
|
{
|
|
resizeHeight = (unsigned int) tmpHeight;
|
|
resizeY = pointerY;
|
|
}
|
|
break;
|
|
|
|
case FRAME_RESIZE_SW:
|
|
case FRAME_RESIZE_S:
|
|
case FRAME_RESIZE_SE:
|
|
resizeY = startY;
|
|
tmpHeight = pointerY - startY + 1;
|
|
if (tmpHeight < (int) minHeight)
|
|
{
|
|
resizeHeight = minHeight;
|
|
}
|
|
else if (pcd->pSD->limitResize
|
|
&& (tmpHeight > (int) maxHeight)
|
|
&& (!(pcd->clientFlags & ICON_BOX)))
|
|
{
|
|
resizeHeight = maxHeight;
|
|
}
|
|
else
|
|
{
|
|
resizeHeight = (unsigned int) tmpHeight;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
resizeY = startY;
|
|
resizeHeight = startHeight;
|
|
break;
|
|
|
|
}
|
|
|
|
/* set width */
|
|
|
|
switch (wmGD.configPart) {
|
|
case FRAME_RESIZE_NW:
|
|
case FRAME_RESIZE_W:
|
|
case FRAME_RESIZE_SW:
|
|
tmpWidth = (int) startWidth + (startX - pointerX);
|
|
if (tmpWidth < (int) minWidth)
|
|
{
|
|
resizeWidth = minWidth;
|
|
resizeX = startX + startWidth - minWidth;
|
|
}
|
|
else if (pcd->pSD->limitResize
|
|
&& (tmpWidth > (int) maxWidth)
|
|
&& (!(pcd->clientFlags & ICON_BOX)))
|
|
{
|
|
resizeWidth = maxWidth;
|
|
resizeX = startX + startWidth - maxWidth;
|
|
}
|
|
else
|
|
{
|
|
resizeWidth = (unsigned int) tmpWidth;
|
|
resizeX = pointerX;
|
|
}
|
|
break;
|
|
|
|
case FRAME_RESIZE_NE:
|
|
case FRAME_RESIZE_E:
|
|
case FRAME_RESIZE_SE:
|
|
resizeX = startX;
|
|
tmpWidth = pointerX - startX + 1;
|
|
if (tmpWidth < (int) minWidth)
|
|
{
|
|
resizeWidth = minWidth;
|
|
}
|
|
else if (pcd->pSD->limitResize
|
|
&& (tmpWidth > (int) maxWidth)
|
|
&& (!(pcd->clientFlags & ICON_BOX)))
|
|
{
|
|
resizeWidth = maxWidth;
|
|
}
|
|
else
|
|
{
|
|
resizeWidth = (unsigned int) tmpWidth;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
resizeX = startX;
|
|
resizeWidth = startWidth;
|
|
break;
|
|
}
|
|
|
|
FixFrameValues (pcd, &resizeX, &resizeY, &resizeWidth,
|
|
&resizeHeight, TRUE /* do size checks */);
|
|
MoveOutline (resizeX, resizeY, resizeWidth, resizeHeight);
|
|
if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
|
|
{
|
|
DoFeedback(pcd, resizeX, resizeY, resizeWidth, resizeHeight,
|
|
(unsigned long) 0, TRUE /* do size checks */);
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* HandleClientFrameResize (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Provide visual feedback of interactive resizing of the window.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o The window sizes refer to the frame, not the client window.
|
|
*
|
|
*************************************<->***********************************/
|
|
void HandleClientFrameResize (ClientData *pcd, XEvent *pev)
|
|
{
|
|
Window grab_win;
|
|
Boolean resizeDone;
|
|
XEvent event;
|
|
|
|
|
|
/*
|
|
* Do our grabs the first time through
|
|
*/
|
|
if (!configGrab) {
|
|
if (StartResizeConfig (pcd, pev))
|
|
{
|
|
configGrab = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* resize could not be initiated */
|
|
return;
|
|
}
|
|
}
|
|
|
|
grab_win = GrabWin (pcd, pev);
|
|
|
|
resizeDone = False;
|
|
while (!resizeDone)
|
|
{
|
|
if (!pev) /* first time through will already have event */
|
|
{
|
|
pev = &event;
|
|
|
|
GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
|
|
pointerX, pointerY, resizeX, resizeY,
|
|
resizeWidth, resizeHeight, &event);
|
|
}
|
|
|
|
if (pev->type == MotionNotify)
|
|
{
|
|
pointerX = pev->xmotion.x_root;
|
|
pointerY = pev->xmotion.y_root;
|
|
anyMotion = TRUE;
|
|
|
|
/*
|
|
* Really start resizing once the pointer hits a resize area
|
|
* (This only applies to accelerator and keyboard resizing!)
|
|
*/
|
|
if (!wmGD.configSet && !SetPointerResizePart (pcd, pev)) {
|
|
pev = NULL;
|
|
continue; /* ignore this event */
|
|
}
|
|
}
|
|
else if (pev->type == KeyPress) {
|
|
|
|
/*
|
|
* Handle key event.
|
|
*/
|
|
resizeDone = HandleResizeKeyPress (pcd, pev);
|
|
}
|
|
else if (pev->type == ButtonRelease) {
|
|
|
|
/*
|
|
* Update (x,y) to the location of the button release
|
|
*/
|
|
pointerX = pev->xbutton.x_root;
|
|
pointerY = pev->xbutton.y_root;
|
|
UpdateAndDrawResize(pcd);
|
|
|
|
CompleteFrameConfig (pcd, pev);
|
|
resizeDone = True;
|
|
}
|
|
else {
|
|
pev = NULL;
|
|
continue; /* ignore this event */
|
|
}
|
|
|
|
if (!resizeDone)
|
|
{
|
|
UpdateAndDrawResize(pcd);
|
|
}
|
|
|
|
pev = NULL; /* reset event pointer */
|
|
|
|
} /* end while */
|
|
|
|
} /* END OF FUNCTION HandleClientFrameResize */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* HandleResizeKeyPress (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Handles keypress events during resize of window
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return - True if this event completes (or cancels) resizing
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
Boolean HandleResizeKeyPress (ClientData *pcd, XEvent *pev)
|
|
{
|
|
KeySym keysym;
|
|
Boolean control;
|
|
int warpX, warpY, currentX = 0, currentY = 0, newX, newY;
|
|
int junk, keyMult;
|
|
Window junk_win;
|
|
XEvent KeyEvent;
|
|
|
|
/*
|
|
* Compress repeated keys
|
|
*/
|
|
keyMult = 1;
|
|
while (keyMult <= 10 &&
|
|
XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
|
|
(char *) pev))
|
|
{
|
|
keyMult++;
|
|
}
|
|
|
|
keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
|
|
control = (pev->xkey.state & ControlMask) != 0;
|
|
|
|
switch (keysym) {
|
|
case XK_Left:
|
|
switch (wmGD.configPart) {
|
|
case FRAME_NONE:
|
|
wmGD.configPart = FRAME_RESIZE_W;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpY = resizeY + resizeHeight/2;
|
|
warpX = resizeX + ((control) ?
|
|
(-resizeBigWidthInc) :
|
|
(-pcd->widthInc));
|
|
break;
|
|
|
|
case FRAME_RESIZE_N:
|
|
wmGD.configPart = FRAME_RESIZE_NW;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = resizeX + ((control) ?
|
|
(-resizeBigWidthInc) :
|
|
(-pcd->widthInc));
|
|
warpY = pointerY;
|
|
break;
|
|
|
|
case FRAME_RESIZE_S:
|
|
wmGD.configPart = FRAME_RESIZE_SW;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = resizeX + ((control) ?
|
|
(-resizeBigWidthInc) :
|
|
(-pcd->widthInc));
|
|
warpY = pointerY;
|
|
break;
|
|
|
|
default:
|
|
warpX = pointerX + ((control) ?
|
|
(-resizeBigWidthInc * keyMult) :
|
|
(-pcd->widthInc * keyMult));
|
|
warpY = pointerY;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case XK_Up:
|
|
switch (wmGD.configPart) {
|
|
case FRAME_NONE:
|
|
wmGD.configPart = FRAME_RESIZE_N;
|
|
warpX = resizeX + resizeWidth/2;
|
|
warpY = resizeY + ((control) ?
|
|
(-resizeBigHeightInc) :
|
|
(-pcd->heightInc));
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
break;
|
|
|
|
case FRAME_RESIZE_W:
|
|
wmGD.configPart = FRAME_RESIZE_NW;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = pointerX;
|
|
warpY = resizeY + ((control) ?
|
|
(-resizeBigHeightInc) :
|
|
(-pcd->heightInc));
|
|
break;
|
|
|
|
case FRAME_RESIZE_E:
|
|
wmGD.configPart = FRAME_RESIZE_NE;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = pointerX;
|
|
warpY = resizeY + ((control) ?
|
|
(-resizeBigHeightInc) :
|
|
(-pcd->heightInc));
|
|
break;
|
|
|
|
default:
|
|
warpX = pointerX;
|
|
warpY = pointerY + ((control) ?
|
|
(-resizeBigHeightInc * keyMult) :
|
|
(-pcd->heightInc * keyMult));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case XK_Right:
|
|
switch (wmGD.configPart) {
|
|
case FRAME_NONE:
|
|
wmGD.configPart = FRAME_RESIZE_E;
|
|
warpY = resizeY + resizeHeight/2;
|
|
warpX = resizeX + resizeWidth - 1 +
|
|
((control) ? resizeBigWidthInc :
|
|
pcd->widthInc);
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
break;
|
|
|
|
case FRAME_RESIZE_N:
|
|
wmGD.configPart = FRAME_RESIZE_NE;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = resizeX + resizeWidth - 1 +
|
|
((control) ? resizeBigWidthInc :
|
|
pcd->widthInc);
|
|
warpY = pointerY;
|
|
break;
|
|
|
|
case FRAME_RESIZE_S:
|
|
wmGD.configPart = FRAME_RESIZE_SE;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = resizeX + resizeWidth - 1 +
|
|
((control) ? resizeBigWidthInc :
|
|
pcd->widthInc);
|
|
warpY = pointerY;
|
|
break;
|
|
|
|
default:
|
|
warpX = pointerX + ((control) ?
|
|
(resizeBigWidthInc * keyMult) :
|
|
(pcd->widthInc * keyMult));
|
|
warpY = pointerY;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case XK_Down:
|
|
switch (wmGD.configPart) {
|
|
case FRAME_NONE:
|
|
wmGD.configPart = FRAME_RESIZE_S;
|
|
warpX = resizeX + resizeWidth/2;
|
|
warpY = resizeY + resizeHeight - 1 +
|
|
((control) ? resizeBigHeightInc :
|
|
pcd->heightInc);
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
break;
|
|
|
|
case FRAME_RESIZE_E:
|
|
wmGD.configPart = FRAME_RESIZE_SE;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = pointerX;
|
|
warpY = resizeY + resizeHeight - 1 +
|
|
((control) ? resizeBigHeightInc :
|
|
pcd->heightInc);
|
|
break;
|
|
|
|
case FRAME_RESIZE_W:
|
|
wmGD.configPart = FRAME_RESIZE_SW;
|
|
ReGrabPointer(pcd->clientFrameWin, pev->xkey.time);
|
|
warpX = pointerX;
|
|
warpY = resizeY + resizeHeight - 1 +
|
|
((control) ? resizeBigHeightInc :
|
|
pcd->heightInc);
|
|
break;
|
|
|
|
default:
|
|
warpX = pointerX;
|
|
warpY = pointerY + ((control) ?
|
|
(resizeBigHeightInc * keyMult) :
|
|
(pcd->heightInc * keyMult));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case XK_Return:
|
|
CompleteFrameConfig (pcd, pev);
|
|
return (True);
|
|
|
|
case XK_Escape:
|
|
CancelFrameConfig (pcd);
|
|
CheckEatButtonRelease (pcd, pev);
|
|
return (True);
|
|
|
|
default:
|
|
return (False); /* ignore this key */
|
|
|
|
} /* end switch(keysym) */
|
|
|
|
/*
|
|
* Make sure the new pointer position is on screen before doing
|
|
* the warp. Warp only if the pointer position changes.
|
|
*/
|
|
pointerX = warpX;
|
|
pointerY = warpY;
|
|
|
|
ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &warpX, &warpY);
|
|
|
|
/*
|
|
* Don't query pointer if enable warp is off.
|
|
*/
|
|
if (!wmGD.enableWarp ||
|
|
XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
|
|
¤tX, ¤tY, &junk, &junk, (unsigned int *)&junk))
|
|
{
|
|
if ( (warpX != currentX) || (warpY != currentY) )
|
|
{
|
|
SetPointerPosition (warpX, warpY, &newX, &newY);
|
|
return (False);
|
|
}
|
|
}
|
|
return (False);
|
|
|
|
} /* END OF FUNCTION HandleResizeKeyPress */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* DoFeedback (pcd, x, y, width, height, newStyle, resizing)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Start or update feedback of size/position info
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* x -
|
|
* y -
|
|
* width -
|
|
* height -
|
|
* newStyle - style flags.
|
|
* resizing - check size constraints iff TRUE
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o If newStyle has FB_POSITION and/or FB_SIZE bits set, then it is
|
|
* assumed that this is an initial call and a feedback window of the
|
|
* desired style should be popped up. If newStyle is zero, then it
|
|
* is assumed that the feedback window is already up and the values
|
|
* passed in are updates.
|
|
*
|
|
*************************************<->***********************************/
|
|
void DoFeedback (ClientData *pcd, int x, int y, unsigned int width, unsigned int height, unsigned long newStyle, Boolean resizing)
|
|
{
|
|
int cx = x;
|
|
int cy = y;
|
|
unsigned int cwidth, cheight;
|
|
|
|
/* compute client window coordinates from frame coordinates */
|
|
FrameToClient (pcd, &cx, &cy, &width, &height);
|
|
|
|
/* use frame (not client) position if user wishes it */
|
|
if (wmGD.positionIsFrame) {
|
|
cx = x;
|
|
cy = y;
|
|
}
|
|
|
|
/* If resizing, make sure configuration is valid. */
|
|
if (resizing)
|
|
{
|
|
FixWindowConfiguration (pcd, &width, &height,
|
|
(unsigned int) pcd->widthInc,
|
|
(unsigned int) pcd->heightInc);
|
|
}
|
|
|
|
/*
|
|
* Put size in client specific units. Do not include base into calculations
|
|
* when increment is not specified (i.e. = 1).
|
|
*/
|
|
cwidth = (width - ((pcd->widthInc==1) ? 0 : pcd->baseWidth))
|
|
/ pcd->widthInc;
|
|
cheight = (height - ((pcd->heightInc==1) ? 0 : pcd->baseHeight))
|
|
/ pcd->heightInc;
|
|
|
|
if (newStyle) {
|
|
ShowFeedbackWindow (pcd->pSD, cx, cy, cwidth, cheight, newStyle);
|
|
}
|
|
else {
|
|
UpdateFeedbackInfo (pcd->pSD, cx, cy, cwidth, cheight);
|
|
}
|
|
} /* END OF FUNCTION DoFeedback */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* CheckVisualPlace
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Prevents icons in the icon box from being moved outside the clip window
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
Boolean CheckVisualPlace (ClientData *pCD, int tmpX, int tmpY)
|
|
{
|
|
Boolean rval = True;
|
|
Window child;
|
|
int newX;
|
|
int newY;
|
|
|
|
GetClipDimensions(pCD, True);
|
|
|
|
|
|
/*
|
|
* Get root coordinates of X and Y for icon.
|
|
* We use root coordinates of clip window since clipX and
|
|
* clipY are not 0, but the icon X and Y may be 0 in
|
|
* local coordinates
|
|
*/
|
|
|
|
XTranslateCoordinates(DISPLAY, XtWindow(P_ICON_BOX(pCD)->bBoardWidget),
|
|
ROOT_FOR_CLIENT(pCD), tmpX, tmpY,
|
|
&newX, &newY, &child);
|
|
|
|
|
|
if (newX < clipX)
|
|
{
|
|
return(False);
|
|
}
|
|
if (newY < clipY)
|
|
{
|
|
return(False);
|
|
}
|
|
|
|
|
|
if (((int)newX) > ((int)clipX +
|
|
(int)clipWidth - ((int)ICON_WIDTH(pCD))))
|
|
{
|
|
return(False);
|
|
}
|
|
if (((int)newY) > ((int)clipY +
|
|
(int)clipHeight - ((int)ICON_HEIGHT(pCD))))
|
|
{
|
|
return(False);
|
|
}
|
|
|
|
return (rval);
|
|
|
|
} /* END OF FUNCTION CheckVisualPlace */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* CompleteFrameConfig (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Clean up graphic feedback when user stops configuring.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o This routine assumes that it is called in response to a button release
|
|
* event.
|
|
*
|
|
*************************************<->***********************************/
|
|
void CompleteFrameConfig (ClientData *pcd, XEvent *pev)
|
|
{
|
|
unsigned int tmpWidth, tmpHeight;
|
|
int tmpX, tmpY;
|
|
Boolean inIconBox;
|
|
|
|
|
|
if (wmGD.configAction == RESIZE_CLIENT) {
|
|
/* release the grabs */
|
|
UndoGrabs();
|
|
|
|
/*
|
|
* Honor the implied constrained anchor points on the window
|
|
* so that the resize doesn't cause the window to move
|
|
* unexpectedly.
|
|
*/
|
|
|
|
#ifndef CONFIG_RELATIVE_TO_CLIENT
|
|
|
|
tmpX = resizeX;
|
|
tmpY = resizeY;
|
|
|
|
/* Use dummy x,y so we don't add frame offset to client location */
|
|
FrameToClient (pcd, &tmpX, &tmpY, &resizeWidth, &resizeHeight);
|
|
#else
|
|
FrameToClient (pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
|
|
#endif
|
|
|
|
tmpWidth = resizeWidth;
|
|
tmpHeight = resizeHeight;
|
|
|
|
FixWindowConfiguration (pcd, &tmpWidth, &tmpHeight,
|
|
(unsigned int) pcd->widthInc,
|
|
(unsigned int) pcd->heightInc);
|
|
|
|
AdjustPos (&resizeX, &resizeY,
|
|
resizeWidth, resizeHeight, tmpWidth, tmpHeight);
|
|
|
|
/* reconfigure the window(s) */
|
|
ProcessNewConfiguration (pcd, resizeX, resizeY,
|
|
resizeWidth, resizeHeight, FALSE);
|
|
|
|
}
|
|
else if (wmGD.configAction == MOVE_CLIENT)
|
|
{
|
|
/* release the grabs */
|
|
UndoGrabs();
|
|
|
|
/* make sure title bar is popped out */
|
|
if ((wmGD.configAction == MOVE_CLIENT) &&
|
|
(wmGD.gadgetClient == pcd) &&
|
|
(wmGD.gadgetDepressed == FRAME_TITLE))
|
|
{
|
|
PopGadgetOut (pcd, FRAME_TITLE);
|
|
FrameExposureProc(pcd); /* repaint frame */
|
|
}
|
|
|
|
/* handle both icon and normal frames */
|
|
if (wmGD.movingIcon)
|
|
{
|
|
|
|
inIconBox = (pcd->pSD->useIconBox && P_ICON_BOX(pcd));
|
|
|
|
/* only need to move the icon */
|
|
if (wmGD.iconAutoPlace || inIconBox)
|
|
{
|
|
int centerX;
|
|
int centerY;
|
|
int place;
|
|
IconPlacementData *pIPD;
|
|
|
|
/*
|
|
* Get correct icon placement data
|
|
*/
|
|
if (inIconBox)
|
|
{
|
|
pIPD = &P_ICON_BOX(pcd)->IPD;
|
|
moveX -= moveIBbbX;
|
|
moveY -= moveIBbbY;
|
|
}
|
|
else
|
|
{
|
|
pIPD = &(ACTIVE_WS->IPData);
|
|
}
|
|
|
|
/*
|
|
* Check to make sure that there is an unoccupied place
|
|
* where the icon is being moved to:
|
|
*/
|
|
|
|
centerX = moveX + ICON_WIDTH(pcd) / 2;
|
|
centerY = moveY + ICON_HEIGHT(pcd) / 2;
|
|
place = CvtIconPositionToPlace (pIPD, centerX, centerY);
|
|
|
|
if (place != ICON_PLACE(pcd))
|
|
{
|
|
if (pIPD->placeList[place].pCD)
|
|
{
|
|
/*
|
|
* Primary place occupied, try to find an unoccupied
|
|
* place in the proximity.
|
|
*/
|
|
|
|
place = FindIconPlace (pcd, pIPD, centerX, centerY);
|
|
if (place == NO_ICON_PLACE)
|
|
{
|
|
/*
|
|
* Can't find an unoccupied icon place.
|
|
*/
|
|
|
|
F_Beep (NULL, pcd, (XEvent *)NULL);
|
|
|
|
if (pcd->pSD->moveOpaque && !inIconBox)
|
|
{
|
|
/*
|
|
* Replace icon into same place - as if it
|
|
* didn't move.
|
|
*/
|
|
|
|
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
|
|
ICON_X(pcd), ICON_Y(pcd));
|
|
if ((ICON_DECORATION(pcd) &
|
|
ICON_ACTIVE_LABEL_PART) &&
|
|
(wmGD.keyboardFocus == pcd))
|
|
{
|
|
MoveActiveIconText(pcd);
|
|
ShowActiveIconText(pcd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((place != NO_ICON_PLACE) &&
|
|
(place != ICON_PLACE(pcd)))
|
|
{
|
|
if (inIconBox)
|
|
{
|
|
CvtIconPlaceToPosition (pIPD, place,
|
|
&tmpX, &tmpY);
|
|
if( (CheckIconBoxSize (P_ICON_BOX(pcd))) &&
|
|
(CheckVisualPlace(pcd, tmpX, tmpY)))
|
|
{
|
|
/*
|
|
* Move the icon to the new place.
|
|
*/
|
|
|
|
MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
|
|
CvtIconPlaceToPosition (pIPD, place,
|
|
&ICON_X(pcd), &ICON_Y(pcd));
|
|
|
|
|
|
XtMoveWidget (
|
|
pIPD->placeList[ICON_PLACE(pcd)].theWidget,
|
|
ICON_X(pcd), ICON_Y(pcd));
|
|
|
|
SetNewBounds (P_ICON_BOX(pcd));
|
|
if (ICON_DECORATION(pcd) &
|
|
ICON_ACTIVE_LABEL_PART)
|
|
{
|
|
MoveActiveIconText(pcd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
F_Beep (NULL, pcd, (XEvent *)NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Move the icon to the new place.
|
|
*/
|
|
MoveIconInfo (pIPD, ICON_PLACE(pcd), place);
|
|
CvtIconPlaceToPosition (pIPD, place, &ICON_X(pcd),
|
|
&ICON_Y(pcd));
|
|
|
|
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
|
|
ICON_X(pcd), ICON_Y(pcd));
|
|
|
|
if (pcd->pSD->moveOpaque &&
|
|
(ICON_DECORATION(pcd) &
|
|
ICON_ACTIVE_LABEL_PART) &&
|
|
(wmGD.keyboardFocus == pcd))
|
|
{
|
|
MoveActiveIconText(pcd);
|
|
ShowActiveIconText(pcd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pcd->pSD->moveOpaque && !inIconBox)
|
|
{
|
|
/*
|
|
* Replace icon into same place - as if it
|
|
* didn't move.
|
|
*/
|
|
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
|
|
ICON_X(pcd), ICON_Y(pcd));
|
|
if ((ICON_DECORATION(pcd) &
|
|
ICON_ACTIVE_LABEL_PART) &&
|
|
(wmGD.keyboardFocus == pcd))
|
|
{
|
|
MoveActiveIconText(pcd);
|
|
ShowActiveIconText(pcd);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd), moveX, moveY);
|
|
ICON_X(pcd) = moveX;
|
|
ICON_Y(pcd) = moveY;
|
|
}
|
|
if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
|
|
(wmGD.keyboardFocus == pcd))
|
|
{
|
|
MoveActiveIconText(pcd);
|
|
}
|
|
}
|
|
else { /* assume normal window frame */
|
|
/* reconfigure the window(s) */
|
|
ProcessNewConfiguration (pcd,
|
|
#ifndef CONFIG_RELATIVE_TO_CLIENT
|
|
moveX,
|
|
moveY,
|
|
#else
|
|
moveX + offsetX,
|
|
moveY + offsetY,
|
|
#endif
|
|
(unsigned int)
|
|
(moveWidth - 2*offsetX),
|
|
(unsigned int)
|
|
(moveHeight - offsetX - offsetY),
|
|
FALSE);
|
|
}
|
|
}
|
|
else if (wmGD.configAction == MARQUEE_SELECT)
|
|
{
|
|
WmScreenData *pSD;
|
|
|
|
UndoGrabs();
|
|
|
|
pSD = pcd ? pcd->pSD : ACTIVE_PSD;
|
|
|
|
dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END,
|
|
marqueeX, marqueeY, marqueeWidth, marqueeHeight);
|
|
}
|
|
|
|
/*
|
|
* Clear configuration flags and data.
|
|
*/
|
|
|
|
wmGD.configAction = NO_ACTION;
|
|
wmGD.configPart = FRAME_NONE;
|
|
wmGD.configSet = False;
|
|
configGrab = FALSE;
|
|
anyMotion = FALSE;
|
|
wmGD.movingIcon = FALSE;
|
|
|
|
if (pcd)
|
|
{
|
|
/* hide the move/resize config data */
|
|
HideFeedbackWindow(pcd->pSD);
|
|
|
|
/*
|
|
* Set the focus back to something reasonable
|
|
*/
|
|
RepairFocus ();
|
|
}
|
|
|
|
} /* END OF FUNCTION CompleteFrameConfig */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* MoveOpaque (pcd, x, y, width, height)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Move a window or icon on the root or icon box.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - client data pointer
|
|
* x - x coordinate (on root)
|
|
* y - y coordinate (on root)
|
|
* width - pixel width of frame
|
|
* height - pixel height of frame
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o use MoveOutline() for icons in an icon box.
|
|
*
|
|
*************************************<->***********************************/
|
|
void MoveOpaque (ClientData *pcd, int x, int y,
|
|
unsigned int width, unsigned int height)
|
|
|
|
|
|
{
|
|
/* Check if moving icon */
|
|
if (wmGD.movingIcon)
|
|
{
|
|
if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
|
|
{
|
|
/*
|
|
* For now just fall back to move outline when the
|
|
* icon is in the icon box
|
|
*/
|
|
|
|
MoveOutline (x, y, width, height);
|
|
}
|
|
else
|
|
{
|
|
XMoveWindow (DISPLAY,ICON_FRAME_WIN(pcd) , x, y);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* This is a window */
|
|
XMoveWindow (DISPLAY, pcd->clientFrameWin, x, y);
|
|
|
|
}
|
|
|
|
/* cleanup exposed frame parts */
|
|
PullExposureEvents ();
|
|
|
|
} /* END OF FUNCTION MoveOpaque */
|
|
|
|
|
|
|
|
/* thickness of outline */
|
|
#define OUTLINE_WIDTH 2
|
|
|
|
/* number of points to draw outline once */
|
|
#define SEGS_PER_DRAW (4*OUTLINE_WIDTH)
|
|
|
|
/* number of points to flash outline (draw then erase) */
|
|
#define SEGS_PER_FLASH (2*SEGS_PER_DRAW)
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* DrawSegments (dpy, win, gc, outline, nsegs)
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Draw segments using either using normal X or using the ALLPLANES
|
|
* extension, depending on #ifdef ALLPLANES and whether the server actually
|
|
* supports the extension. This is a thin wrapper around the Xlib
|
|
* XDrawSegments() call.
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* dpy - the X display
|
|
* win - the window on which to draw
|
|
* gc - the gc to use, typically whose function is GXxor
|
|
* outline - array of segments
|
|
* nsegs - number of segments in the outline array
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* (none)
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* Note: no GC is used when drawing with the ALLPLANES extension;
|
|
* therefore, the GC parameter is ignored in that case.
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
|
|
static void
|
|
DrawSegments (Display *dpy, Window win, GC gc, XSegment *outline, int nsegs)
|
|
{
|
|
#if defined(sun) && defined(ALLPLANES)
|
|
if (wmGD.allplanes)
|
|
XAllPlanesDrawSegments(dpy, win, outline, nsegs);
|
|
else
|
|
#endif /* defined(sun) && defined(ALLPLANES) */
|
|
XDrawSegments(dpy, win, gc, outline, nsegs);
|
|
} /* END OF FUNCTION DrawSegments */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* MoveOutline (x, y, width, height)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Draw a window outline on the root window.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* x - x coordinate (on root)
|
|
* y - y coordinate (on root)
|
|
* width - pixel width of frame
|
|
* height - pixel height of frame
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o get display, root window ID, and xorGC out of global data.
|
|
*
|
|
*************************************<->***********************************/
|
|
void MoveOutline (int x, int y, unsigned int width, unsigned int height)
|
|
{
|
|
if (wmGD.freezeOnConfig)
|
|
{
|
|
DrawOutline (x, y, width, height);
|
|
}
|
|
else
|
|
{
|
|
if (wmGD.useWindowOutline)
|
|
WindowOutline(x,y,width,height);
|
|
else
|
|
FlashOutline(x, y, width, height);
|
|
}
|
|
} /* END OF FUNCTION MoveOutline */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* FlashOutline ()
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* flash a window outline on the root window.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* x - x coordinate (on root)
|
|
* y - y coordinate (on root)
|
|
* width - pixel width of frame
|
|
* height - pixel height of frame
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o get display, root window ID, and xorGC out of global data.
|
|
* o draw on root and erase "atomically"
|
|
*
|
|
*************************************<->***********************************/
|
|
void FlashOutline (int x, int y, unsigned int width, unsigned int height)
|
|
{
|
|
static XSegment outline[SEGS_PER_FLASH];
|
|
|
|
/*
|
|
* Do nothing if no box to draw
|
|
*/
|
|
if (x == 0 && y == 0 &&
|
|
width == 0 && height == 0)
|
|
return;
|
|
|
|
/*
|
|
* Draw outline an even number of times (draw then erase)
|
|
*/
|
|
SetOutline (outline, x, y, width, height, OUTLINE_WIDTH);
|
|
memcpy ( (char *) &outline[SEGS_PER_DRAW], (char *) &outline[0],
|
|
SEGS_PER_DRAW*sizeof(XSegment));
|
|
|
|
/*
|
|
* Flash the outline at least once, then as long as there's
|
|
* nothing else going on
|
|
*/
|
|
DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
|
|
outline, SEGS_PER_FLASH);
|
|
XSync(DISPLAY, FALSE);
|
|
|
|
while (!XtAppPending(wmGD.mwmAppContext)) {
|
|
DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
|
|
outline, SEGS_PER_FLASH);
|
|
XSync(DISPLAY, FALSE);
|
|
}
|
|
} /* END OF FUNCTION FlashOutline */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* CreateOutlineWindows (pSD)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* create the outline windows
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* variables are affected:
|
|
* woN
|
|
* woS
|
|
* woE
|
|
* woW
|
|
*
|
|
*************************************<->***********************************/
|
|
static void
|
|
CreateOutlineWindows (WmScreenData *pSD)
|
|
{
|
|
XSetWindowAttributes xswa;
|
|
unsigned int xswamask;
|
|
int x, y, width, height;
|
|
|
|
|
|
x = -10;
|
|
y = -10;
|
|
width = OUTLINE_WIDTH;
|
|
height = OUTLINE_WIDTH;
|
|
|
|
xswa.override_redirect = True;
|
|
xswa.backing_store = NotUseful;
|
|
xswa.save_under = True;
|
|
xswa.background_pixmap = XmGetPixmap(
|
|
XtScreen(pSD->screenTopLevelW),
|
|
"50_foreground",
|
|
pSD->clientAppearance.foreground,
|
|
pSD->clientAppearance.background);
|
|
|
|
xswamask = (CWOverrideRedirect |
|
|
CWBackingStore |
|
|
CWBackPixmap |
|
|
CWSaveUnder);
|
|
|
|
pSD->woN = XCreateWindow(DISPLAY, pSD->rootWindow,
|
|
x, y, width, height,
|
|
0,
|
|
XDefaultDepth(DISPLAY,pSD->screen),
|
|
CopyFromParent,
|
|
CopyFromParent,
|
|
xswamask,
|
|
&xswa);
|
|
|
|
pSD->woS = XCreateWindow(DISPLAY, pSD->rootWindow,
|
|
x, y, width, height,
|
|
0,
|
|
XDefaultDepth(DISPLAY,pSD->screen),
|
|
CopyFromParent,
|
|
CopyFromParent,
|
|
xswamask,
|
|
&xswa);
|
|
|
|
pSD->woE = XCreateWindow(DISPLAY, pSD->rootWindow,
|
|
x, y, width, height,
|
|
0,
|
|
XDefaultDepth(DISPLAY,pSD->screen),
|
|
CopyFromParent,
|
|
CopyFromParent,
|
|
xswamask,
|
|
&xswa);
|
|
|
|
pSD->woW = XCreateWindow(DISPLAY, pSD->rootWindow,
|
|
x, y, width, height,
|
|
0,
|
|
XDefaultDepth(DISPLAY,pSD->screen),
|
|
CopyFromParent,
|
|
CopyFromParent,
|
|
xswamask,
|
|
&xswa);
|
|
|
|
} /* END OF FUNCTION CreateOutlineWindows */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* WindowOutline ()
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* show an outline on the root window using windows.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* x - x coordinate (on root)
|
|
* y - y coordinate (on root)
|
|
* width - pixel width of frame
|
|
* height - pixel height of frame
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* Always unmap during move/resize of outline windows to let saveunder
|
|
* stuff work. HP server's toss saveunder stuff for windows that
|
|
* configure themselves while mapped.
|
|
*
|
|
*************************************<->***********************************/
|
|
void WindowOutline (int x, int y, unsigned int width, unsigned int height)
|
|
{
|
|
static int lastOutlineX = 0;
|
|
static int lastOutlineY = 0;
|
|
static int lastOutlineWidth = 0;
|
|
static int lastOutlineHeight = 0;
|
|
WmScreenData *pSD = ACTIVE_PSD;
|
|
int iX, iY;
|
|
int iW, iH;
|
|
|
|
if (pSD->woN == (Window)0L)
|
|
{
|
|
CreateOutlineWindows(pSD);
|
|
}
|
|
|
|
if (x == lastOutlineX && y == lastOutlineY &&
|
|
width == lastOutlineWidth && height == lastOutlineHeight)
|
|
{
|
|
return; /* no change */
|
|
}
|
|
|
|
XUnmapWindow(DISPLAY, pSD->woN);
|
|
XUnmapWindow(DISPLAY, pSD->woS);
|
|
XUnmapWindow(DISPLAY, pSD->woE);
|
|
XUnmapWindow(DISPLAY, pSD->woW);
|
|
|
|
if ((width == 0) && (height == 0))
|
|
{
|
|
lastOutlineWidth = lastOutlineHeight = 0;
|
|
lastOutlineX = lastOutlineY = 0;
|
|
}
|
|
else
|
|
{
|
|
/* North */
|
|
iX = x;
|
|
iY = y;
|
|
iW = (int) width;
|
|
iH = OUTLINE_WIDTH;
|
|
if (iW < 0) iW = 1;
|
|
XMoveResizeWindow (DISPLAY, pSD->woN, iX, iY, iW, iH);
|
|
|
|
/* West */
|
|
iX = x;
|
|
iY = y + OUTLINE_WIDTH;
|
|
iW = OUTLINE_WIDTH;
|
|
iH = (int) height - OUTLINE_WIDTH;
|
|
if (iH < 0) iH = 1;
|
|
XMoveResizeWindow (DISPLAY, pSD->woW, iX, iY, iW, iH);
|
|
|
|
/* East */
|
|
iX = x + (int)width - OUTLINE_WIDTH;
|
|
iY = y + OUTLINE_WIDTH;
|
|
iW = OUTLINE_WIDTH;
|
|
iH = (int)height - OUTLINE_WIDTH;
|
|
if (iH < 0) iH = 1;
|
|
XMoveResizeWindow (DISPLAY, pSD->woE, iX, iY, iW, iH);
|
|
|
|
/* South */
|
|
iX = x + OUTLINE_WIDTH;
|
|
iY = y + (int)height - OUTLINE_WIDTH;
|
|
iW = (int)width - 2*OUTLINE_WIDTH;
|
|
iH = OUTLINE_WIDTH;
|
|
if (iW < 0) iW = 1;
|
|
XMoveResizeWindow (DISPLAY, pSD->woS, iX, iY, iW, iH);
|
|
|
|
lastOutlineX = x;
|
|
lastOutlineY = y;
|
|
lastOutlineWidth = width;
|
|
lastOutlineHeight = height;
|
|
|
|
XMapRaised (DISPLAY, pSD->woN);
|
|
XMapRaised (DISPLAY, pSD->woS);
|
|
XMapRaised (DISPLAY, pSD->woE);
|
|
XMapRaised (DISPLAY, pSD->woW);
|
|
|
|
/* cleanup exposed frame parts */
|
|
PullExposureEvents ();
|
|
}
|
|
|
|
} /* END OF FUNCTION WindowOutline */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* DrawOutline (x, y, width, height)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Draw a window outline on the root window.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* x - x coordinate (on root)
|
|
* y - y coordinate (on root)
|
|
* width - pixel width of frame
|
|
* height - pixel height of frame
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o get display, root window ID, and xorGC out of global data.
|
|
*
|
|
*************************************<->***********************************/
|
|
void DrawOutline (int x, int y, unsigned int width, unsigned int height)
|
|
{
|
|
static int lastOutlineX = 0;
|
|
static int lastOutlineY = 0;
|
|
static int lastOutlineWidth = 0;
|
|
static int lastOutlineHeight = 0;
|
|
XSegment outline[SEGS_PER_DRAW];
|
|
|
|
|
|
if (x == lastOutlineX && y == lastOutlineY &&
|
|
width == lastOutlineWidth && height == lastOutlineHeight)
|
|
{
|
|
return; /* no change */
|
|
}
|
|
|
|
if (lastOutlineWidth || lastOutlineHeight) {
|
|
SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
|
|
lastOutlineHeight, OUTLINE_WIDTH);
|
|
|
|
DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
|
|
outline, SEGS_PER_DRAW);
|
|
}
|
|
|
|
lastOutlineX = x;
|
|
lastOutlineY = y;
|
|
lastOutlineWidth = width;
|
|
lastOutlineHeight = height;
|
|
|
|
if (lastOutlineWidth || lastOutlineHeight) {
|
|
|
|
SetOutline (outline, lastOutlineX, lastOutlineY, lastOutlineWidth,
|
|
lastOutlineHeight, OUTLINE_WIDTH);
|
|
|
|
DrawSegments(DISPLAY, ACTIVE_ROOT, ACTIVE_PSD->xorGC,
|
|
outline, SEGS_PER_DRAW);
|
|
}
|
|
} /* END OF FUNCTION DrawOutline */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* WindowIsOnScreen (pCD, dx, dy)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* This function is used to check if a window is atleast partially on the
|
|
* screen or not. If the window is completely off the screen, dx and dy
|
|
* will contain the minimum distance to move some part of the window's frame
|
|
* back onto the screen.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pCD - pointer to client data
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* dx - minimum x distance to move the window back to the screen
|
|
* dy - minimum y distance to move the window back to the screen
|
|
*
|
|
*
|
|
* Returns:
|
|
* --------
|
|
* true - if the window has some part on the screen
|
|
* false - if the window is completely off the screen
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
Boolean WindowIsOnScreen (ClientData *pCD, int *dx, int *dy)
|
|
{
|
|
int x1 = pCD->clientX;
|
|
int x2 = pCD->clientX + pCD->clientWidth;
|
|
int y1 = pCD->clientY;
|
|
int y2 = pCD->clientY + pCD->clientHeight;
|
|
int screenW = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
|
|
int screenH = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pCD));
|
|
|
|
*dx = *dy = 0;
|
|
|
|
if (x2 < 0) /* right frame border off left side of screen. */
|
|
*dx = -x2;
|
|
else if (x1 > screenW) /* left frame border off right side of screen. */
|
|
*dx = screenW - x1;
|
|
|
|
if (y2 < 0) /* bottom frame border off top of screen. */
|
|
*dy = -y2;
|
|
else if (y1 > screenH) /* top frame border off bottom of screen. */
|
|
*dy = screenH - y1;
|
|
|
|
return ((*dx == 0) && (*dy == 0));
|
|
}
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* ProcessNewConfiguration (pCD, x, y, width, height, clientRequest)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* This function is used to configure a client window following receipt of
|
|
* a client request or an interactive configuration action.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pCD - pointer to client data
|
|
* x - x coord of client window
|
|
* y - y coord of client window
|
|
* width - width of client window
|
|
* height - height of client window
|
|
* clientRequest - true if configuration requested by client program
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
void ProcessNewConfiguration (ClientData *pCD, int x, int y, unsigned int width, unsigned int height, Boolean clientRequest)
|
|
{
|
|
unsigned int changedValues = 0;
|
|
int xoff = 0, yoff = 0;
|
|
int dx, dy;
|
|
Boolean originallyOnScreen = WindowIsOnScreen(pCD, &dx, &dy);
|
|
Boolean newMax = False;
|
|
Boolean toNewMax = False;
|
|
|
|
/*
|
|
* Fix the configuration values to be compatible with the configuration
|
|
* constraints for this class of windows.
|
|
*/
|
|
|
|
|
|
|
|
FixWindowConfiguration (pCD, &width, &height,
|
|
(unsigned int) pCD->widthInc,
|
|
(unsigned int) pCD->heightInc);
|
|
|
|
if ((pCD->maxWidth != pCD->oldMaxWidth) ||
|
|
(pCD->maxHeight != pCD->oldMaxHeight))
|
|
{
|
|
/*
|
|
* We've got a new maximum size.
|
|
*/
|
|
newMax = True;
|
|
}
|
|
|
|
/*
|
|
* If the configuration has changed, update client data
|
|
*
|
|
* Changes in width or height cause maximized windows to return to
|
|
* normal state and update normal geometry (x, y, width, height)
|
|
*/
|
|
if (pCD->maxConfig)
|
|
{
|
|
if (newMax &&
|
|
(pCD->maxWidth == width) &&
|
|
(pCD->maxHeight == height))
|
|
{
|
|
/* we're changing to the new max size */
|
|
toNewMax = True;
|
|
}
|
|
|
|
changedValues |= (width != pCD->oldMaxWidth) ? CWWidth : 0;
|
|
changedValues |= (height != pCD->oldMaxHeight) ? CWHeight : 0;
|
|
|
|
if (!toNewMax && (changedValues & CWWidth)) {
|
|
/*
|
|
* Hacked to update maxWidth for 'vertical' max clients
|
|
*/
|
|
if (IS_MAXIMIZE_VERTICAL(pCD)) {
|
|
pCD->maxWidth = width;
|
|
}
|
|
pCD->clientWidth = width;
|
|
if (changedValues & CWHeight) {
|
|
/*
|
|
* Hacked to update maxHeight for 'horizontal' max client
|
|
*/
|
|
if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
|
|
pCD->maxHeight = height;
|
|
}
|
|
pCD->clientHeight = height;
|
|
}
|
|
else {
|
|
pCD->clientHeight = pCD->oldMaxHeight;
|
|
}
|
|
}
|
|
else if (!toNewMax && (changedValues & CWHeight)) {
|
|
/*
|
|
* Hacked to update maxHeight for 'horizontal' max client
|
|
*/
|
|
if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
|
|
pCD->maxHeight = height;
|
|
}
|
|
pCD->clientHeight = height;
|
|
pCD->clientWidth = pCD->oldMaxWidth;
|
|
}
|
|
}
|
|
else {
|
|
if (width != pCD->clientWidth)
|
|
{
|
|
/*
|
|
* Hacked to update maxWidth for 'vertical' max clients
|
|
*/
|
|
if (IS_MAXIMIZE_VERTICAL(pCD)) {
|
|
pCD->maxWidth = width;
|
|
}
|
|
|
|
changedValues |= CWWidth;
|
|
pCD->clientWidth = width;
|
|
|
|
}
|
|
|
|
if (height != pCD->clientHeight)
|
|
{
|
|
/*
|
|
* Hacked to update maxHeight for 'horizontal' max client
|
|
*/
|
|
if (IS_MAXIMIZE_HORIZONTAL(pCD)) {
|
|
pCD->maxHeight = height;
|
|
}
|
|
|
|
changedValues |= CWHeight;
|
|
pCD->clientHeight = height;
|
|
}
|
|
}
|
|
|
|
#ifndef CONFIG_RELATIVE_TO_CLIENT
|
|
/*
|
|
* If positionIsFrame or user initiated configuration request,
|
|
* then adjust client position to by frame_width and frame_height.
|
|
*/
|
|
if (wmGD.positionIsFrame || (!clientRequest))
|
|
{
|
|
xoff = pCD->clientOffset.x;
|
|
yoff = pCD->clientOffset.y;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Changes in position update maximum geometry on maximized windows
|
|
* if there was no change in size.
|
|
*/
|
|
if (pCD->maxConfig) {
|
|
if (x != pCD->maxX) {
|
|
changedValues |= CWX;
|
|
if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
|
|
pCD->clientX = x + xoff;
|
|
else
|
|
pCD->maxX = x + xoff;
|
|
}
|
|
else if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
|
|
{
|
|
pCD->clientX = pCD->maxX;
|
|
}
|
|
|
|
if (y != pCD->maxY) {
|
|
changedValues |= CWY;
|
|
if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
|
|
pCD->clientY = y + yoff;
|
|
else
|
|
pCD->maxY = y + yoff;
|
|
}
|
|
else if (!toNewMax && (changedValues & (CWWidth | CWHeight)))
|
|
{
|
|
pCD->clientY = pCD->maxY;
|
|
}
|
|
}
|
|
else {
|
|
if (x + xoff != pCD->clientX) {
|
|
changedValues |= CWX;
|
|
pCD->clientX = x + xoff;
|
|
}
|
|
|
|
if (y + yoff != pCD->clientY) {
|
|
changedValues |= CWY;
|
|
pCD->clientY = y + yoff;
|
|
}
|
|
}
|
|
|
|
/* check if the window has reconfigured itself off the screen. */
|
|
if (originallyOnScreen && !WindowIsOnScreen(pCD, &dx, &dy))
|
|
{
|
|
if (dx != 0)
|
|
{
|
|
changedValues |= CWX;
|
|
pCD->clientX += dx;
|
|
}
|
|
|
|
if (dy != 0)
|
|
{
|
|
changedValues |= CWY;
|
|
pCD->clientY += dy;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Resize the client window if necessary:
|
|
*/
|
|
|
|
if (changedValues & (CWWidth | CWHeight))
|
|
{
|
|
if (pCD->maxConfig)
|
|
{
|
|
if (!toNewMax)
|
|
{
|
|
/* maximized window resized, return to normal state */
|
|
pCD->maxConfig = FALSE;
|
|
pCD->clientState = NORMAL_STATE;
|
|
}
|
|
}
|
|
|
|
XResizeWindow (DISPLAY, pCD->client, width, height);
|
|
RegenerateClientFrame(pCD);
|
|
}
|
|
if (changedValues & (CWX | CWY)) {
|
|
if (pCD->maxConfig)
|
|
{
|
|
/*
|
|
* Fix for 5217 - If the request is from the client, use the clients
|
|
* offsets instead of the static offsets
|
|
*/
|
|
if (clientRequest)
|
|
{
|
|
XMoveWindow (DISPLAY, pCD->clientFrameWin,
|
|
pCD->maxX - pCD->clientOffset.x,
|
|
pCD->maxY - pCD->clientOffset.y);
|
|
}
|
|
else
|
|
{
|
|
XMoveWindow (DISPLAY, pCD->clientFrameWin,
|
|
pCD->maxX - offsetX,
|
|
pCD->maxY - offsetY);
|
|
}
|
|
/* End fix 5217 */
|
|
}
|
|
else
|
|
{
|
|
if (clientRequest)
|
|
{
|
|
XMoveWindow (DISPLAY, pCD->clientFrameWin,
|
|
pCD->clientX - pCD->clientOffset.x,
|
|
pCD->clientY - pCD->clientOffset.y);
|
|
}
|
|
else
|
|
{
|
|
XMoveWindow (DISPLAY, pCD->clientFrameWin,
|
|
pCD->clientX - offsetX,
|
|
pCD->clientY - offsetY);
|
|
}
|
|
}
|
|
SetFrameInfo (pCD);
|
|
if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
|
|
{
|
|
/* turn off subpanel behavior if moved */
|
|
pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUBPANEL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Send a configure notify message if appropriate:
|
|
* 1. rejected client configuration request.
|
|
* 2. client request and move without resize
|
|
*/
|
|
|
|
|
|
if ((!changedValues && clientRequest) ||
|
|
(changedValues && !(changedValues & (CWWidth | CWHeight))))
|
|
{
|
|
SendConfigureNotify (pCD);
|
|
}
|
|
|
|
/*
|
|
* Try to send notice directly to icon box that the window
|
|
* has changed size
|
|
*/
|
|
|
|
if ((pCD->clientFlags & ICON_BOX) &&
|
|
(changedValues & (CWWidth | CWHeight)))
|
|
{
|
|
CheckIconBoxResize(pCD, changedValues, width, height);
|
|
}
|
|
|
|
} /* END OF FUNCTION ProcessNewConfiguration */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* StartResizeConfig (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Start resize of client window
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* return - true if configuration can begin, else false
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
Boolean StartResizeConfig (ClientData *pcd, XEvent *pev)
|
|
{
|
|
Window grab_win, junk_win;
|
|
Boolean grabbed;
|
|
int big_inc, tmp_inc;
|
|
int junk, junkX, junkY;
|
|
|
|
/*
|
|
* Do our grabs
|
|
*/
|
|
if (!configGrab)
|
|
{
|
|
grab_win = GrabWin (pcd, pev);
|
|
|
|
if (pev)
|
|
{
|
|
grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart),
|
|
PGRAB_MASK, pev->xbutton.time, pcd, True);
|
|
}
|
|
else
|
|
{
|
|
grabbed = DoGrabs (grab_win, ConfigCursor((int) wmGD.configPart),
|
|
PGRAB_MASK, CurrentTime, pcd, True);
|
|
}
|
|
if (!grabbed)
|
|
{
|
|
return (False);
|
|
}
|
|
configGrab = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* continue with the configuration in progress (!!!) */
|
|
return (True);
|
|
}
|
|
|
|
/*
|
|
* Set up static variables for succeeding events
|
|
*/
|
|
if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd), &junk_win, &junk_win,
|
|
&pointerX, &pointerY, &junk, &junk, (unsigned int *)&junk))
|
|
{
|
|
CancelFrameConfig (pcd); /* release grabs */
|
|
return (False);
|
|
};
|
|
wmGD.preMoveX = pointerX;
|
|
wmGD.preMoveY = pointerY;
|
|
anyMotion = FALSE;
|
|
|
|
offsetX = pcd->clientOffset.x;
|
|
offsetY = pcd->clientOffset.y;
|
|
|
|
/*
|
|
* get window geometry information and convert to frame coordinates
|
|
*/
|
|
if (pcd->maxConfig) {
|
|
resizeX = pcd->maxX;
|
|
resizeY = pcd->maxY;
|
|
resizeWidth = pcd->maxWidth;
|
|
resizeHeight = pcd->maxHeight;
|
|
}
|
|
else {
|
|
resizeX = pcd->clientX;
|
|
resizeY = pcd->clientY;
|
|
resizeWidth = pcd->clientWidth;
|
|
resizeHeight = pcd->clientHeight;
|
|
}
|
|
ClientToFrame(pcd, &resizeX, &resizeY, &resizeWidth, &resizeHeight);
|
|
|
|
/* save start values to see where we came from */
|
|
startX = resizeX;
|
|
startY = resizeY;
|
|
startWidth = resizeWidth;
|
|
startHeight = resizeHeight;
|
|
|
|
/* get min and max frame sizes */
|
|
minWidth = pcd->minWidth;
|
|
minHeight = pcd->minHeight;
|
|
junkX = junkY = 0;
|
|
ClientToFrame(pcd, &junkX, &junkY, &minWidth, &minHeight);
|
|
|
|
/*
|
|
* Hack to use maxHeightLimit and maxWidthLimit as the real max when
|
|
* maximumClientSize is set to 'horizontal' or 'vertical', since
|
|
* pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
|
|
*/
|
|
maxWidth = pcd->maxWidthLimit;
|
|
maxHeight = pcd->maxHeightLimit;
|
|
junkX = junkY = 0;
|
|
ClientToFrame(pcd, &junkX, &junkY, &maxWidth, &maxHeight);
|
|
|
|
/* compute big increment values */
|
|
big_inc = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pcd)) / 20;
|
|
|
|
tmp_inc = big_inc - big_inc%pcd->widthInc;
|
|
if (tmp_inc > 5*pcd->widthInc)
|
|
resizeBigWidthInc = tmp_inc;
|
|
else
|
|
resizeBigWidthInc = 5*pcd->widthInc;
|
|
|
|
tmp_inc = big_inc - big_inc%pcd->heightInc;
|
|
if (tmp_inc > 5*pcd->heightInc)
|
|
resizeBigHeightInc = tmp_inc;
|
|
else
|
|
resizeBigHeightInc = 5*pcd->heightInc;
|
|
|
|
/* pop up feedback window */
|
|
if (wmGD.showFeedback & WM_SHOW_FB_RESIZE)
|
|
{
|
|
DoFeedback (pcd, resizeX, resizeY, resizeWidth, resizeHeight,
|
|
FB_SIZE, TRUE /* do size checks */);
|
|
}
|
|
|
|
/* set configuring data */
|
|
wmGD.configAction = RESIZE_CLIENT;
|
|
wmGD.configButton = pev ? pev->xbutton.button: 0;
|
|
|
|
return (True);
|
|
|
|
} /* END OF FUNCTION StartResizeConfig */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* StartClientResize (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Start resize of client window as invoked from menu
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o This should only be called as the result of a Resize function
|
|
* being selected from the system menu.
|
|
*
|
|
*************************************<->***********************************/
|
|
void StartClientResize (ClientData *pcd, XEvent *pev)
|
|
{
|
|
|
|
/* do initial setup for resize */
|
|
wmGD.configPart = FRAME_NONE; /* determined by later action */
|
|
wmGD.configSet = False; /* don't know what it is yet */
|
|
if (!StartResizeConfig (pcd, pev))
|
|
{
|
|
/* resize could not be initiated */
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* Warp pointer to middle of window if started from the keyboard
|
|
* or menu (no event).
|
|
*/
|
|
if ( !pev || pev->type == KeyPress )
|
|
{
|
|
pointerX = resizeX + resizeWidth/2;
|
|
pointerY = resizeY + resizeHeight/2;
|
|
|
|
ForceOnScreen(SCREEN_FOR_CLIENT(pcd), &pointerX, &pointerY);
|
|
if (wmGD.enableWarp)
|
|
{
|
|
XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd),
|
|
0, 0, 0, 0, pointerX, pointerY);
|
|
}
|
|
}
|
|
|
|
} /* END OF FUNCTION StartClientResize */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* StartClientMove (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Handle move of client window as invoked from menu
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return - True if configuration was initiated, else False
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o This should only be called as the result of a Move function
|
|
* being selected from the system menu.
|
|
*
|
|
*************************************<->***********************************/
|
|
Boolean StartClientMove (ClientData *pcd, XEvent *pev)
|
|
{
|
|
Window grab_win, junk_win;
|
|
Boolean grabbed;
|
|
int junk;
|
|
Window child;
|
|
|
|
/*
|
|
* Do our grabs if we're just starting out
|
|
*/
|
|
if (!configGrab)
|
|
{
|
|
grab_win = GrabWin (pcd, pev);
|
|
if (grab_win == ICON_FRAME_WIN(pcd))
|
|
{
|
|
wmGD.movingIcon = True;
|
|
}
|
|
|
|
if (pev)
|
|
{
|
|
grabbed = DoGrabs (grab_win, wmGD.configCursor,
|
|
PGRAB_MASK, pev->xbutton.time, pcd, False);
|
|
}
|
|
else
|
|
{
|
|
grabbed = DoGrabs (grab_win, wmGD.configCursor,
|
|
PGRAB_MASK, CurrentTime, pcd, False);
|
|
}
|
|
if (!grabbed)
|
|
{
|
|
wmGD.movingIcon = False;
|
|
return (False);
|
|
}
|
|
configGrab = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Set up static variables for succeeding events if we're not
|
|
* entering with a motion event. If we are, we assume that the
|
|
* preMove variables have been setup.
|
|
*/
|
|
if (pev && ((pev->type == ButtonPress) || (pev->type == ButtonRelease)))
|
|
{
|
|
wmGD.preMoveX = pev->xbutton.x_root;
|
|
wmGD.preMoveY = pev->xbutton.y_root;
|
|
}
|
|
else if ((pev && (pev->type != MotionNotify)) || !pev)
|
|
{
|
|
if (!XQueryPointer (DISPLAY, ROOT_FOR_CLIENT(pcd),
|
|
&junk_win, &junk_win,
|
|
&(wmGD.preMoveX), &(wmGD.preMoveY),
|
|
&junk, &junk, (unsigned int *)&junk))
|
|
{
|
|
CancelFrameConfig (pcd);
|
|
return (False);
|
|
}
|
|
}
|
|
|
|
offsetX = pcd->clientOffset.x;
|
|
offsetY = pcd->clientOffset.y;
|
|
|
|
anyMotion = FALSE;
|
|
moveLastPointerX = wmGD.preMoveX;
|
|
moveLastPointerY = wmGD.preMoveY;
|
|
|
|
/* get frame window geometry */
|
|
if (wmGD.movingIcon)
|
|
{
|
|
moveWidth = ICON_WIDTH(pcd);
|
|
moveHeight = ICON_HEIGHT(pcd);
|
|
|
|
moveX = ICON_X(pcd);
|
|
moveY = ICON_Y(pcd);
|
|
|
|
if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
|
|
{
|
|
/* get root coords of icon box bulletin board */
|
|
XTranslateCoordinates(DISPLAY,
|
|
XtWindow(P_ICON_BOX(pcd)->bBoardWidget), ROOT_FOR_CLIENT(pcd),
|
|
0, 0, &moveIBbbX, &moveIBbbY, &child);
|
|
|
|
moveX += moveIBbbX;
|
|
moveY += moveIBbbY;
|
|
}
|
|
else if (pcd->pSD->moveOpaque &&
|
|
(ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART) &&
|
|
(wmGD.keyboardFocus == pcd))
|
|
{
|
|
HideActiveIconText ((WmScreenData *)NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pcd->maxConfig) { /* maximized */
|
|
moveWidth = pcd->maxWidth;
|
|
moveHeight = pcd->maxHeight;
|
|
moveX = pcd->maxX;
|
|
moveY = pcd->maxY;
|
|
}
|
|
else { /* normal */
|
|
moveWidth = pcd->clientWidth;
|
|
moveHeight = pcd->clientHeight;
|
|
moveX = pcd->clientX;
|
|
moveY = pcd->clientY;
|
|
}
|
|
ClientToFrame (pcd, &moveX, &moveY, &moveWidth, &moveHeight);
|
|
}
|
|
|
|
if (pcd->pSD->moveOpaque)
|
|
{
|
|
opaqueMoveX = moveX;
|
|
opaqueMoveY = moveY;
|
|
}
|
|
|
|
/*
|
|
* Warp pointer to middle of window if started from the menu (no event).
|
|
*/
|
|
if ( !pev || pev->type == KeyPress )
|
|
{
|
|
moveLastPointerX = moveX + moveWidth/2;
|
|
moveLastPointerY = moveY + moveHeight/2;
|
|
|
|
ForceOnScreen (SCREEN_FOR_CLIENT(pcd),
|
|
&moveLastPointerX, &moveLastPointerY);
|
|
if (wmGD.enableWarp)
|
|
{
|
|
XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd), 0, 0, 0, 0,
|
|
moveLastPointerX, moveLastPointerY);
|
|
}
|
|
}
|
|
|
|
/* pop up feedback window */
|
|
if ( !wmGD.movingIcon && (wmGD.showFeedback & WM_SHOW_FB_MOVE))
|
|
{
|
|
DoFeedback (pcd, moveX, moveY, moveWidth, moveHeight,
|
|
FB_POSITION, FALSE /* no size checks */);
|
|
}
|
|
|
|
/* set configuring data */
|
|
wmGD.configAction = MOVE_CLIENT;
|
|
if (pev && pev->type != KeyPress)
|
|
wmGD.configButton = pev->xbutton.button;
|
|
else
|
|
wmGD.configButton = 0;
|
|
|
|
|
|
return (True);
|
|
|
|
|
|
} /* END OF FUNCTION StartClientMove */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* DoGrabs (grab_win, cursor, pmask, grabTime, alwaysGrab)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Do the grabs for window configuration
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* grab_win - window to grab on
|
|
* cursor - cursor shape to attach to the pointer
|
|
* pmask -
|
|
* grabTime - time stamp
|
|
* alwaysGrab -
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
Boolean DoGrabs (Window grab_win, Cursor cursor, unsigned int pmask, Time grabTime, ClientData *pCD, Boolean alwaysGrab)
|
|
{
|
|
|
|
Window root;
|
|
|
|
if (pCD)
|
|
root = ROOT_FOR_CLIENT(pCD);
|
|
else
|
|
root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
|
|
|
|
if (pCD && pCD->pSD->useIconBox && wmGD.movingIcon && P_ICON_BOX(pCD))
|
|
{
|
|
/*
|
|
* Confine the pointer to the icon box clip window
|
|
*/
|
|
if (XGrabPointer(DISPLAY,
|
|
grab_win,
|
|
FALSE, /* owner_events */
|
|
pmask,
|
|
GrabModeAsync, /* pointer_mode */
|
|
GrabModeAsync, /* keyboard_mode */
|
|
/* confine_to window */
|
|
XtWindow(P_ICON_BOX(pCD)->clipWidget),
|
|
cursor,
|
|
grabTime) != GrabSuccess)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Just confine the pointer to the root window
|
|
*/
|
|
if (XGrabPointer(DISPLAY,
|
|
grab_win,
|
|
FALSE, /* owner_events */
|
|
pmask,
|
|
GrabModeAsync, /* pointer_mode */
|
|
GrabModeAsync, /* keyboard_mode */
|
|
root,
|
|
cursor,
|
|
grabTime) != GrabSuccess)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Don't grab keyboard away from menu widget to prevent
|
|
* hosing of traversal.
|
|
*/
|
|
if (!wmGD.menuActive)
|
|
{
|
|
if ((XGrabKeyboard(DISPLAY,
|
|
grab_win,
|
|
FALSE, /* owner_events */
|
|
GrabModeAsync, /* pointer_mode */
|
|
GrabModeAsync, /* keyboard_mode */
|
|
grabTime)) != GrabSuccess)
|
|
{
|
|
XUngrabPointer (DISPLAY, CurrentTime);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
if (wmGD.freezeOnConfig)
|
|
|
|
{
|
|
if (!pCD || ((pCD->pSD->moveOpaque && alwaysGrab) ||
|
|
(!(pCD->pSD->moveOpaque))))
|
|
{
|
|
XGrabServer(DISPLAY);
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
} /* END OF FUNCTION DoGrabs */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* UndoGrabs ()
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Release the grabs
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void UndoGrabs (void)
|
|
{
|
|
/* erase outline */
|
|
MoveOutline(0, 0, 0, 0);
|
|
XSync (DISPLAY, FALSE /*don't discard events*/);
|
|
|
|
/* give up grabs */
|
|
if (wmGD.freezeOnConfig) {
|
|
XUngrabServer(DISPLAY);
|
|
}
|
|
|
|
/*
|
|
* Don't Ungrab keyboard away from menu widget to prevent
|
|
* hosing of traversal.
|
|
*/
|
|
if (!wmGD.menuActive)
|
|
XUngrabKeyboard (DISPLAY,CurrentTime);
|
|
|
|
XUngrabPointer (DISPLAY, CurrentTime); /* event time NOT used */
|
|
XFlush (DISPLAY);
|
|
|
|
} /* END OF FUNCTION UndoGrabs */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* CancelFrameConfig (pcd)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Cance a frame configuration (move/resize) operation.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void CancelFrameConfig (ClientData *pcd)
|
|
{
|
|
|
|
/* remove keyboard, pointer, and server grabs */
|
|
UndoGrabs();
|
|
|
|
/* turn off feedback window */
|
|
if (pcd)
|
|
{
|
|
HideFeedbackWindow(pcd->pSD);
|
|
|
|
/* make sure title bar is popped out */
|
|
if ((wmGD.configAction == MOVE_CLIENT) &&
|
|
(wmGD.gadgetClient == pcd) && (wmGD.gadgetDepressed == FRAME_TITLE))
|
|
{
|
|
PopGadgetOut (pcd, FRAME_TITLE);
|
|
FrameExposureProc(pcd); /* repaint frame */
|
|
}
|
|
if ((pcd->pSD->moveOpaque) &&
|
|
(wmGD.configAction == MOVE_CLIENT))
|
|
|
|
{
|
|
if ((pcd->clientState == MINIMIZED_STATE) &&
|
|
(!(pcd->pSD->useIconBox && P_ICON_BOX(pcd))))
|
|
{
|
|
/*
|
|
* Replace icon into pre-move position
|
|
*/
|
|
|
|
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pcd),
|
|
ICON_X(pcd), ICON_Y(pcd));
|
|
if ((ICON_DECORATION(pcd) & ICON_ACTIVE_LABEL_PART))
|
|
{
|
|
ShowActiveIconText(pcd);
|
|
}
|
|
}
|
|
else if (! wmGD.movingIcon) /* we are not moving in the iconbox */
|
|
{
|
|
XMoveWindow (DISPLAY, pcd->clientFrameWin,
|
|
opaqueMoveX, opaqueMoveY);
|
|
}
|
|
}
|
|
}
|
|
if (wmGD.configAction == MARQUEE_SELECT)
|
|
{
|
|
dtSendMarqueeSelectionNotification(ACTIVE_PSD, DT_MARQUEE_SELECT_CANCEL,
|
|
marqueeX, marqueeY, 0, 0);
|
|
}
|
|
|
|
/* replace pointer if no motion events received */
|
|
if (pcd)
|
|
if (!anyMotion && wmGD.enableWarp) {
|
|
XWarpPointer(DISPLAY, None, ROOT_FOR_CLIENT(pcd),
|
|
0, 0, 0, 0, wmGD.preMoveX, wmGD.preMoveY);
|
|
}
|
|
anyMotion = FALSE;
|
|
|
|
/* Clear configuration flags and data */
|
|
wmGD.configAction = NO_ACTION;
|
|
wmGD.configPart = FRAME_NONE;
|
|
wmGD.configSet = False;
|
|
configGrab = FALSE;
|
|
wmGD.movingIcon = FALSE;
|
|
|
|
/* set the focus back to a reasonable window */
|
|
RepairFocus ();
|
|
} /* END OF FUNCTION CancelFrameConfig */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* CheckEatButtonRelease (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Set up to eat button releases if buttons are down.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to key event that caused cancel
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* none
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void
|
|
CheckEatButtonRelease (ClientData *pcd, XEvent *pev)
|
|
{
|
|
Window grab_win;
|
|
Window root;
|
|
|
|
if (pcd != (ClientData *)NULL)
|
|
root = ROOT_FOR_CLIENT(pcd);
|
|
else
|
|
root = RootWindow (DISPLAY, ACTIVE_PSD->screen);
|
|
|
|
if (pcd == (ClientData *) NULL)
|
|
grab_win = root;
|
|
else
|
|
grab_win = GrabWin(pcd, pev);
|
|
|
|
if ((pev->type == KeyPress || pev->type == KeyRelease) &&
|
|
(pev->xbutton.state & ButtonMask))
|
|
{
|
|
/*
|
|
* Some buttons are down...
|
|
* Set up conditions to wait for these buttons to go up.
|
|
*/
|
|
if (XGrabPointer(DISPLAY,
|
|
grab_win,
|
|
False, /* owner_events */
|
|
ButtonReleaseMask,
|
|
GrabModeAsync, /* pointer_mode */
|
|
GrabModeAsync, /* keyboard_mode */
|
|
root, /* confine_to window */
|
|
wmGD.configCursor,
|
|
pev->xbutton.time) == GrabSuccess)
|
|
{
|
|
EatButtonRelease (pev->xbutton.state & ButtonMask);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* EatButtonRelease (releaseButtons)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Eat up button release events
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* releaseButtons = button mask of button releases to eat
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* none
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void
|
|
EatButtonRelease (unsigned int releaseButtons)
|
|
{
|
|
unsigned int new_state;
|
|
XEvent event;
|
|
|
|
while (releaseButtons)
|
|
{
|
|
PullExposureEvents ();
|
|
XMaskEvent (DISPLAY, ButtonReleaseMask, &event);
|
|
|
|
if (event.type == ButtonRelease)
|
|
{
|
|
/* look at the state after this button is released */
|
|
new_state =
|
|
event.xbutton.state & ~ButtonStateBit(event.xbutton.button);
|
|
|
|
if (!(new_state & releaseButtons))
|
|
{
|
|
/* all the buttons we were waiting for have been
|
|
* released.
|
|
*/
|
|
|
|
XUngrabPointer (DISPLAY, event.xbutton.time);
|
|
releaseButtons = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* ButtonStateBit (button)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Converts a button number to a button state bit
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* button = button number (Button1, Button2, etc.)
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return = bit used in xbutton state field
|
|
* (Button1Mask, Button2Mask,...)
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*
|
|
*************************************<->***********************************/
|
|
unsigned int
|
|
ButtonStateBit (unsigned int button)
|
|
{
|
|
#define MAX_BUTTON 5
|
|
typedef struct {
|
|
unsigned int button;
|
|
unsigned int maskbit;
|
|
} ButtonAssoc;
|
|
|
|
static ButtonAssoc bmap[MAX_BUTTON] = {
|
|
{Button1, Button1Mask},
|
|
{Button2, Button2Mask},
|
|
{Button3, Button3Mask},
|
|
{Button4, Button4Mask},
|
|
{Button5, Button5Mask},
|
|
};
|
|
|
|
int i;
|
|
unsigned int rval = 0;
|
|
|
|
for (i = 0; i < MAX_BUTTON; i++)
|
|
{
|
|
if (bmap[i].button == button)
|
|
{
|
|
rval = bmap[i].maskbit;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (rval);
|
|
|
|
}
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* ConfigCursor (frame_part)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* return the config cursor that goes with the config part specified
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* frame_part - frame part id
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* return - cursor to use
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
Cursor ConfigCursor (int frame_part)
|
|
{
|
|
Cursor cursor;
|
|
|
|
switch (frame_part) {
|
|
case FRAME_RESIZE_NW:
|
|
cursor = wmGD.stretchCursors[STRETCH_NORTH_WEST];
|
|
break;
|
|
case FRAME_RESIZE_N:
|
|
cursor = wmGD.stretchCursors[STRETCH_NORTH];
|
|
break;
|
|
case FRAME_RESIZE_NE:
|
|
cursor = wmGD.stretchCursors[STRETCH_NORTH_EAST];
|
|
break;
|
|
case FRAME_RESIZE_E:
|
|
cursor = wmGD.stretchCursors[STRETCH_EAST];
|
|
break;
|
|
case FRAME_RESIZE_SE:
|
|
cursor = wmGD.stretchCursors[STRETCH_SOUTH_EAST];
|
|
break;
|
|
case FRAME_RESIZE_S:
|
|
cursor = wmGD.stretchCursors[STRETCH_SOUTH];
|
|
break;
|
|
case FRAME_RESIZE_SW:
|
|
cursor = wmGD.stretchCursors[STRETCH_SOUTH_WEST];
|
|
break;
|
|
case FRAME_RESIZE_W:
|
|
cursor = wmGD.stretchCursors[STRETCH_WEST];
|
|
break;
|
|
default:
|
|
cursor = wmGD.configCursor;
|
|
}
|
|
|
|
return(cursor);
|
|
|
|
} /* END OF FUNCTION ConfigCursor */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* ReGrabPointer (grab_win, grabTime)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Grab the pointer again to change the cursor
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* grab_win -
|
|
* grabTime - time stamp
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void ReGrabPointer (Window grab_win, Time grabTime)
|
|
{
|
|
XGrabPointer(DISPLAY,
|
|
grab_win,
|
|
FALSE, /* owner_events */
|
|
PGRAB_MASK,
|
|
GrabModeAsync, /* pointer_mode */
|
|
GrabModeAsync, /* keyboard_mode */
|
|
ACTIVE_ROOT, /* confine_to window */
|
|
ConfigCursor((int)wmGD.configPart),
|
|
grabTime);
|
|
|
|
} /* END OF FUNCTION ReGrabPointer */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* SetPointerResizePart (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Sets the global configuration part for resize based on the current
|
|
* configuration part and the location of the event
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return - TRUE if wmGD.configPart is a valid resize part
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o Assumes the static data for resizing has been set up.
|
|
*************************************<->***********************************/
|
|
Boolean SetPointerResizePart (ClientData *pcd, XEvent *pev)
|
|
{
|
|
int newPart;
|
|
Time grabTime;
|
|
|
|
newPart = ResizeType(pcd, pev); /* get part id for this event */
|
|
grabTime = (pev) ? pev->xmotion.time : CurrentTime;
|
|
|
|
switch (wmGD.configPart) {
|
|
case FRAME_NONE:
|
|
if (newPart == FRAME_NONE)
|
|
return(FALSE); /* still not valid */
|
|
|
|
wmGD.configPart = newPart;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
return(TRUE);
|
|
|
|
case FRAME_RESIZE_N:
|
|
switch (newPart) {
|
|
case FRAME_RESIZE_W:
|
|
case FRAME_RESIZE_NW:
|
|
wmGD.configPart = FRAME_RESIZE_NW;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
case FRAME_RESIZE_E:
|
|
case FRAME_RESIZE_NE:
|
|
wmGD.configPart = FRAME_RESIZE_NE;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case FRAME_RESIZE_E:
|
|
switch (newPart) {
|
|
case FRAME_RESIZE_N:
|
|
case FRAME_RESIZE_NE:
|
|
wmGD.configPart = FRAME_RESIZE_NE;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
case FRAME_RESIZE_S:
|
|
case FRAME_RESIZE_SE:
|
|
wmGD.configPart = FRAME_RESIZE_SE;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case FRAME_RESIZE_S:
|
|
switch (newPart) {
|
|
case FRAME_RESIZE_E:
|
|
case FRAME_RESIZE_SE:
|
|
wmGD.configPart = FRAME_RESIZE_SE;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
case FRAME_RESIZE_W:
|
|
case FRAME_RESIZE_SW:
|
|
wmGD.configPart = FRAME_RESIZE_SW;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case FRAME_RESIZE_W:
|
|
switch (newPart) {
|
|
case FRAME_RESIZE_N:
|
|
case FRAME_RESIZE_NW:
|
|
wmGD.configPart = FRAME_RESIZE_NW;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
case FRAME_RESIZE_S:
|
|
case FRAME_RESIZE_SW:
|
|
wmGD.configPart = FRAME_RESIZE_SW;
|
|
ReGrabPointer(pcd->clientFrameWin, grabTime);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case FRAME_RESIZE_NW:
|
|
case FRAME_RESIZE_NE:
|
|
case FRAME_RESIZE_SW:
|
|
case FRAME_RESIZE_SE:
|
|
break;
|
|
|
|
default:
|
|
return(FALSE); /* not a valid resize part */
|
|
}
|
|
return(TRUE);
|
|
|
|
} /* END OF FUNCTION SetPointerResizePart */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* ResizeType (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Returns a resize part ID for an event outside of the current
|
|
* resize area.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pev - pointer to event
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o Assumes the static data for resizing has been set up.
|
|
*************************************<->***********************************/
|
|
int ResizeType (ClientData *pcd, XEvent *pev)
|
|
{
|
|
int x, y;
|
|
|
|
if (!pev) return(FRAME_NONE);
|
|
|
|
x = pev->xmotion.x_root;
|
|
y = pev->xmotion.y_root;
|
|
|
|
/* if inside all resize areas, then forget it */
|
|
if ( (x > resizeX) &&
|
|
(y > resizeY) &&
|
|
(x < (resizeX + resizeWidth - 1)) &&
|
|
(y < (resizeY + resizeHeight - 1)) )
|
|
{
|
|
return(FRAME_NONE);
|
|
}
|
|
|
|
/* left side */
|
|
if (x <= resizeX) {
|
|
if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
|
|
return (FRAME_RESIZE_NW);
|
|
else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
|
|
return (FRAME_RESIZE_SW);
|
|
else
|
|
return (FRAME_RESIZE_W);
|
|
}
|
|
|
|
/* right side */
|
|
if (x >= resizeX + resizeWidth - 1) {
|
|
if (y < resizeY + (int)pcd->frameInfo.cornerHeight)
|
|
return (FRAME_RESIZE_NE);
|
|
else if (y >= resizeY + resizeHeight -(int)pcd->frameInfo.cornerHeight)
|
|
return (FRAME_RESIZE_SE);
|
|
else
|
|
return (FRAME_RESIZE_E);
|
|
}
|
|
|
|
/* top side */
|
|
if (y <= resizeY) {
|
|
if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
|
|
return (FRAME_RESIZE_NW);
|
|
else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
|
|
return (FRAME_RESIZE_NE);
|
|
else
|
|
return (FRAME_RESIZE_N);
|
|
}
|
|
|
|
/* bottom side */
|
|
if (y >= resizeY + resizeHeight - 1) {
|
|
if (x < resizeX + (int)pcd->frameInfo.cornerWidth)
|
|
return (FRAME_RESIZE_SW);
|
|
else if (x >= resizeX + resizeWidth - (int)pcd->frameInfo.cornerWidth)
|
|
return (FRAME_RESIZE_SE);
|
|
else
|
|
return (FRAME_RESIZE_S);
|
|
}
|
|
|
|
return(FRAME_NONE);
|
|
|
|
} /* END OF FUNCTION ResizeType */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* FixFrameValues (pcd, pfX, pfY, pfWidth, pfHeight, resizing)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Fix up the frame values so that they do not exceed maximum or minimum
|
|
* size and that at least part of the frame is on screen
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - pointer to client data
|
|
* pfX - pointer to frame x-coord
|
|
* pfY - pointer to frame y-coord
|
|
* pfWidth - pointer to frame width
|
|
* pfHeight - pointer to frame height
|
|
* resizing - check size constraints iff TRUE
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* *pfX - fixed up frame x-coord
|
|
* *pfY - fixed up frame y-coord
|
|
* *pfWidth - fixed up frame width
|
|
* *pfHeight - fixed up frame height
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* 1. This could be more efficient
|
|
* 2. Interactive resize with aspect ratio constraints may cause part of the
|
|
* outline to disappear off screen. The critical case is when the title
|
|
* bar disappears ABOVE the screen.
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
void FixFrameValues (ClientData *pcd, int *pfX, int *pfY, unsigned int *pfWidth, unsigned int *pfHeight, Boolean resizing)
|
|
{
|
|
unsigned int lswidth;
|
|
unsigned int oWidth, oHeight;
|
|
|
|
|
|
/*
|
|
* Fix size if resizing and not icon.
|
|
*/
|
|
|
|
if (resizing && !wmGD.movingIcon)
|
|
{
|
|
FrameToClient(pcd, pfX, pfY, pfWidth, pfHeight);
|
|
|
|
oWidth = *pfWidth;
|
|
oHeight = *pfHeight;
|
|
|
|
FixWindowSize (pcd, pfWidth, pfHeight, 1, 1);
|
|
|
|
AdjustPos (pfX, pfY, oWidth, oHeight, *pfWidth, *pfHeight);
|
|
|
|
ClientToFrame(pcd, pfX, pfY, pfWidth, pfHeight);
|
|
}
|
|
|
|
/*
|
|
* Don't move if we'd end up totally offscreen
|
|
*/
|
|
|
|
if (wmGD.movingIcon)
|
|
{
|
|
lswidth = FRAME_BORDER_WIDTH(pcd);
|
|
}
|
|
else
|
|
{
|
|
lswidth = pcd->frameInfo.lowerBorderWidth;
|
|
}
|
|
if (lswidth < 5) lswidth = 5;
|
|
|
|
if (wmGD.movingIcon && P_ICON_BOX(pcd))
|
|
{
|
|
/*
|
|
* Constrain outline to icon box
|
|
*/
|
|
/* left edge of outline */
|
|
if (*pfX < clipX)
|
|
{
|
|
*pfX = clipX;
|
|
}
|
|
|
|
/* top of outline */
|
|
if (*pfY < clipY)
|
|
{
|
|
*pfY = clipY;
|
|
}
|
|
|
|
/* right edge of outline */
|
|
if (((int)*pfX) > ((int)clipX + (int)clipWidth - ((int)*pfWidth)))
|
|
{
|
|
*pfX = clipX + clipWidth - *pfWidth;
|
|
}
|
|
|
|
/* bottom edge of outline */
|
|
if (((int)*pfY) > ((int)clipY + (int)clipHeight - ((int)*pfHeight)))
|
|
{
|
|
*pfY = clipY + clipHeight - *pfHeight;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* keep outline on screen
|
|
*/
|
|
|
|
|
|
/* keep right border on screen */
|
|
if (*pfX < ((int) lswidth - (int) *pfWidth))
|
|
{
|
|
*pfX = (int) lswidth - (int) *pfWidth;
|
|
}
|
|
|
|
/* keep bottom border on screen */
|
|
if (*pfY < ((int) lswidth - (int) *pfHeight))
|
|
{
|
|
*pfY = (int) lswidth - (int) *pfHeight;
|
|
}
|
|
|
|
/* keep left border on screen */
|
|
if (*pfX > (DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
|
|
(int) lswidth))
|
|
{
|
|
*pfX = DisplayWidth(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
|
|
(int) lswidth;
|
|
}
|
|
|
|
/* keep top border on screen */
|
|
if (*pfY > (DisplayHeight(DISPLAY,SCREEN_FOR_CLIENT(pcd)) -
|
|
(int) lswidth))
|
|
{
|
|
*pfY = DisplayHeight(DISPLAY, SCREEN_FOR_CLIENT(pcd)) -
|
|
(int) lswidth;
|
|
}
|
|
}
|
|
|
|
} /* END OF FUNCTION FixFrameValues */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* ForceOnScreen (screen, pX, pY)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Correct (if necessary) the coords specified to make them on screen
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* screen - screen number
|
|
* pX - pointer to x-coord
|
|
* pY - pointer to y-coord
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* *pX - x-coord (on screen)
|
|
* *pY - y-coord (on screen)
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* XXComments ...
|
|
*
|
|
*************************************<->***********************************/
|
|
void ForceOnScreen (int screen, int *pX, int *pY)
|
|
{
|
|
if (*pX >= (DisplayWidth(DISPLAY, screen)))
|
|
*pX = DisplayWidth(DISPLAY, screen) - 1;
|
|
else if (*pX < 0)
|
|
*pX = 0;
|
|
|
|
if (*pY >= (DisplayHeight(DISPLAY, screen)))
|
|
*pY = DisplayHeight(DISPLAY, screen) - 1;
|
|
else if (*pY < 0)
|
|
*pY = 0;
|
|
|
|
} /* END OF FUNCTION ForceOnScreen */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* SetPointerPosition (newX, newY, actualX, actualY)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Attempt to set the pointer to position at newX, newY.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* newX - X-coordinate to set pointer at
|
|
* newY - Y-coordinate to set pointer at
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* *actualX - actual X-coord of pointer on return
|
|
* *actualY - actual Y-coord of pointer on return
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void SetPointerPosition (int newX, int newY, int *actualX, int *actualY)
|
|
{
|
|
int junk;
|
|
Window junk_win;
|
|
|
|
/*
|
|
* Warp pointer ...
|
|
*/
|
|
if (wmGD.enableWarp)
|
|
{
|
|
XWarpPointer(DISPLAY, None, ACTIVE_ROOT,
|
|
0, 0, 0, 0, newX, newY);
|
|
}
|
|
|
|
|
|
/*
|
|
* Get pointer position
|
|
* NOTE: if we are not warping, we don't want to do the Query pointer,
|
|
* hence enableWarp is tested first.
|
|
*/
|
|
if (!wmGD.enableWarp ||
|
|
!XQueryPointer (DISPLAY, ACTIVE_ROOT, &junk_win, &junk_win,
|
|
actualX, actualY, &junk, &junk, (unsigned int *)&junk))
|
|
|
|
{
|
|
/* failed to get pointer position or not warping, return something */
|
|
*actualX = newX;
|
|
*actualY = newY;
|
|
}
|
|
|
|
} /* END OF FUNCTION SetPointerPositio */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* GetConfigEvent (display, window, mask, curX, curY, oX, oY,
|
|
* oWidth, oHeight, pev,)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Get next configuration event
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* display - pointer to display
|
|
* window - window to get event relative to
|
|
* mask - event mask - acceptable events to return
|
|
* pev - pointer to a place to put the event
|
|
* curX - current X value of pointer
|
|
* curY - current Y value of pointer
|
|
* oX - X value of outline
|
|
* oY - Y value of outline
|
|
* oWidth - width of outline
|
|
* oHeight - height of outline
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* *pev - event returned.
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void GetConfigEvent (Display *display, Window window, unsigned long mask, int curX, int curY, int oX, int oY, unsigned oWidth, unsigned oHeight, XEvent *pev)
|
|
{
|
|
Window root_ret, child_ret;
|
|
int root_x, root_y, win_x, win_y;
|
|
unsigned int mask_ret;
|
|
Boolean polling;
|
|
int pollCount;
|
|
Boolean gotEvent;
|
|
Boolean eventToReturn = False;
|
|
|
|
while (!eventToReturn)
|
|
{
|
|
/*
|
|
* Suck up pointer motion events
|
|
*/
|
|
gotEvent = False;
|
|
while (XCheckWindowEvent(display, window, mask, pev))
|
|
{
|
|
gotEvent = True;
|
|
if (pev->type != MotionNotify)
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Only poll if we are warping the pointer.
|
|
* (uses PointerMotionHints exclusively).
|
|
*/
|
|
polling = wmGD.enableWarp;
|
|
pollCount = CONFIG_POLL_COUNT;
|
|
|
|
if (!gotEvent && (polling || !wmGD.freezeOnConfig))
|
|
{
|
|
/*
|
|
* poll for events and flash the frame outline
|
|
* if not move opaque
|
|
*/
|
|
|
|
while (True)
|
|
{
|
|
if (XCheckWindowEvent(display, window,
|
|
(mask & ~PointerMotionMask), pev))
|
|
{
|
|
gotEvent = True;
|
|
break;
|
|
}
|
|
|
|
if (!wmGD.freezeOnConfig && !wmGD.pActiveSD->moveOpaque)
|
|
{
|
|
/* flash the outline if server is not grabbed */
|
|
MoveOutline (oX, oY, oWidth, oHeight);
|
|
}
|
|
|
|
if (!XQueryPointer (display, window, &root_ret, &child_ret,
|
|
&root_x, &root_y, &win_x, &win_y, &mask_ret))
|
|
{
|
|
continue; /* query failed, try again */
|
|
}
|
|
|
|
if ((root_x != curX) || (root_y != curY))
|
|
{
|
|
/*
|
|
* Pointer moved to a new position.
|
|
* Cobble a motion event together.
|
|
* NOTE: SOME FIELDS NOT SET !!!
|
|
*/
|
|
|
|
pev->type = MotionNotify;
|
|
/* pev->xmotion.serial = ??? */
|
|
pev->xmotion.send_event = False;
|
|
pev->xmotion.display = display;
|
|
pev->xmotion.window = root_ret;
|
|
pev->xmotion.subwindow = child_ret;
|
|
pev->xmotion.time = CurrentTime; /* !!! !!! */
|
|
pev->xmotion.x = root_x;
|
|
pev->xmotion.y = root_y;
|
|
pev->xmotion.x_root = root_x;
|
|
pev->xmotion.y_root = root_y;
|
|
/* pev->xmotion.state = ??? */
|
|
/* pev->xmotion.is_hint = ???? */
|
|
/* pev->xmotion.same_screen = ??? */
|
|
|
|
eventToReturn = True;
|
|
break; /* from while loop */
|
|
}
|
|
else if (wmGD.freezeOnConfig)
|
|
{
|
|
if (!(--pollCount))
|
|
{
|
|
/*
|
|
* No pointer motion in some time. Stop polling
|
|
* and wait for next event.
|
|
*/
|
|
polling = False;
|
|
break; /* from while loop */
|
|
}
|
|
}
|
|
} /* end while */
|
|
}
|
|
|
|
if (!gotEvent && !polling && wmGD.freezeOnConfig)
|
|
{
|
|
/*
|
|
* Wait for next event on window
|
|
*/
|
|
|
|
XWindowEvent (display, window, mask, pev);
|
|
gotEvent = True;
|
|
}
|
|
|
|
if (gotEvent)
|
|
{
|
|
eventToReturn = True;
|
|
if (pev->type == MotionNotify &&
|
|
pev->xmotion.is_hint == NotifyHint)
|
|
{
|
|
/*
|
|
* "Ack" the motion notify hint
|
|
*/
|
|
if ((XQueryPointer (display, window, &root_ret,
|
|
&child_ret, &root_x, &root_y, &win_x,
|
|
&win_y, &mask_ret)) &&
|
|
((root_x != curX) ||
|
|
(root_y != curY)))
|
|
{
|
|
/*
|
|
* The query pointer values say that the pointer
|
|
* moved to a new location.
|
|
*/
|
|
pev->xmotion.window = root_ret;
|
|
pev->xmotion.subwindow = child_ret;
|
|
pev->xmotion.x = root_x;
|
|
pev->xmotion.y = root_y;
|
|
pev->xmotion.x_root = root_x;
|
|
pev->xmotion.y_root = root_y;
|
|
|
|
}
|
|
else {
|
|
/*
|
|
* Query failed. Change curX to force position
|
|
* to be returned on first sucessful query.
|
|
*/
|
|
eventToReturn = False;
|
|
curX++;
|
|
}
|
|
}
|
|
}
|
|
} /* end while */
|
|
|
|
} /* END OF FUNCTION GetConfigEvent */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* SetOutline (pOutline, x, y, width, height, fatness)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Sets the outline of for config/move/placement operations
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pOutline - ptr to outline structure to fill in
|
|
* x - x of upper-left corner of outline
|
|
* y - y of upper-left corner of outline
|
|
* width - width of outline.
|
|
* height - height of outline.
|
|
* fatness - pixel-width of outline
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* o Be sure that pOutline points to a big enough area of memory
|
|
* for the outline to be set!
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
void SetOutline (XSegment *pOutline, int x, int y, unsigned int width, unsigned int height, int fatness)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<fatness; i++)
|
|
{
|
|
pOutline->x1 = x;
|
|
pOutline->y1 = y;
|
|
pOutline->x2 = x + width -1;
|
|
pOutline++->y2 = y;
|
|
|
|
pOutline->x1 = x + width -1;
|
|
pOutline->y1 = y;
|
|
pOutline->x2 = x + width -1;
|
|
pOutline++->y2 = y + height - 1;
|
|
|
|
pOutline->x1 = x + width -1;
|
|
pOutline->y1 = y + height - 1;
|
|
pOutline->x2 = x;
|
|
pOutline++->y2 = y + height - 1;
|
|
|
|
pOutline->x1 = x;
|
|
pOutline->y1 = y + height - 1;
|
|
pOutline->x2 = x;
|
|
pOutline++->y2 = y;
|
|
|
|
/*
|
|
* Modify values for next pass (if any)
|
|
* Next outline will be on inside of current one.
|
|
*/
|
|
x += 1;
|
|
y += 1;
|
|
width -= 2;
|
|
height -= 2;
|
|
}
|
|
|
|
} /* END OF FUNCTION SetOutline */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* AdjustPos (pX, pY, oWidth, oHeight, nWidth, nHeight)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Adjusts the position according to wmGD.configPart and any change in
|
|
* client size.
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pX, pY -- pointers to positions
|
|
* oWidth, oHeight -- original dimensions
|
|
* nWidth, nHeight -- new dimensions
|
|
* wmGD.configPart
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* pX, pY -- pointers to adjusted positions
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
|
|
void AdjustPos (int *pX, int *pY, unsigned int oWidth, unsigned int oHeight, unsigned int nWidth, unsigned int nHeight)
|
|
{
|
|
switch (wmGD.configPart)
|
|
{
|
|
case FRAME_RESIZE_NW:
|
|
/* anchor lower right corner */
|
|
*pX += oWidth - nWidth;
|
|
*pY += oHeight - nHeight;
|
|
break;
|
|
|
|
case FRAME_RESIZE_N:
|
|
/* anchor bottom */
|
|
*pY += oHeight - nHeight;
|
|
break;
|
|
|
|
case FRAME_RESIZE_NE:
|
|
/* anchor lower left corner */
|
|
*pY += oHeight - nHeight;
|
|
break;
|
|
|
|
case FRAME_RESIZE_E:
|
|
/* anchor left side */
|
|
break;
|
|
|
|
case FRAME_RESIZE_SE:
|
|
/* anchor upper left corner */
|
|
break;
|
|
|
|
case FRAME_RESIZE_S:
|
|
/* anchor top */
|
|
break;
|
|
|
|
case FRAME_RESIZE_SW:
|
|
/* anchor upper right corner */
|
|
*pX += oWidth - nWidth;
|
|
break;
|
|
|
|
case FRAME_RESIZE_W:
|
|
/* anchor right side */
|
|
*pX += oWidth - nWidth;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
} /* END OF FUNCTION AdjustPos */
|
|
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* GrabWin (pcd, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* return window to do grab on for config operation
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pcd - ptr to client data
|
|
* pev - ptr to event
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return - window
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
Window GrabWin (ClientData *pcd, XEvent *pev)
|
|
{
|
|
Window grab_win;
|
|
|
|
/*
|
|
* The grab window is the icon if the client is minimized
|
|
* or if the event was on a "normalized" icon in the icon box.
|
|
*/
|
|
|
|
if ((pcd->clientState == MINIMIZED_STATE) ||
|
|
(pcd->pSD->useIconBox && pev &&
|
|
((pev->xany.window == ICON_FRAME_WIN(pcd)) ||
|
|
(pev->xany.window == ACTIVE_ICON_TEXT_WIN))))
|
|
{
|
|
grab_win = ICON_FRAME_WIN(pcd);
|
|
}
|
|
else if (pev &&
|
|
(pev->xany.window == pcd->clientFrameWin ||
|
|
pev->xany.window == pcd->clientBaseWin ))
|
|
{
|
|
grab_win = pcd->clientFrameWin;
|
|
}
|
|
else if (pcd->pSD->useIconBox &&
|
|
P_ICON_BOX(pcd) &&
|
|
wmGD.grabContext == F_SUBCONTEXT_IB_WICON)
|
|
{
|
|
grab_win = ICON_FRAME_WIN(pcd);
|
|
}
|
|
else
|
|
{
|
|
grab_win = pcd->clientFrameWin;
|
|
}
|
|
|
|
return (grab_win);
|
|
|
|
} /* END OF FUNCTION GrabWin */
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* HandleMarqueeSelect (pSD, event)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Does a marquee selection on the root window
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
* Comments:
|
|
* --------
|
|
* Selection info is dumped into a root window property:
|
|
* _DT_MARQUEE_SELECTION
|
|
*
|
|
*************************************<->***********************************/
|
|
void
|
|
HandleMarqueeSelect (WmScreenData *pSD, XEvent *pev)
|
|
{
|
|
Window grab_win;
|
|
Boolean bDone;
|
|
XEvent event;
|
|
|
|
grab_win = RootWindow (DISPLAY, pSD->screen);
|
|
bDone = False;
|
|
|
|
while (!bDone && (wmGD.configAction == MARQUEE_SELECT))
|
|
{
|
|
if (!pev) /* first time through will already have event */
|
|
{
|
|
pev = &event;
|
|
|
|
GetConfigEvent(DISPLAY, grab_win, CONFIG_MASK,
|
|
pointerX, pointerY, resizeX, resizeY,
|
|
resizeWidth, resizeHeight, &event);
|
|
}
|
|
|
|
if (pev->type == MotionNotify)
|
|
{
|
|
pointerX = pev->xmotion.x_root;
|
|
pointerY = pev->xmotion.y_root;
|
|
UpdateMarqueeSelectData (pSD);
|
|
}
|
|
else if (pev->type == KeyPress) {
|
|
|
|
/*
|
|
* Handle key event.
|
|
*/
|
|
bDone = HandleMarqueeKeyPress (pSD, pev);
|
|
}
|
|
else if (pev->type == ButtonRelease) {
|
|
|
|
/*
|
|
* Update (x,y) to the location of the button release
|
|
*/
|
|
pointerX = pev->xbutton.x_root;
|
|
pointerY = pev->xbutton.y_root;
|
|
UpdateMarqueeSelectData (pSD);
|
|
CompleteFrameConfig ((ClientData *)NULL, pev);
|
|
bDone = True;
|
|
}
|
|
else {
|
|
pev = NULL;
|
|
continue; /* ignore this event */
|
|
}
|
|
|
|
if (!bDone)
|
|
{
|
|
MoveOutline (marqueeX, marqueeY, marqueeWidth, marqueeHeight);
|
|
}
|
|
|
|
pev = NULL; /* reset event pointer */
|
|
|
|
} /* end while */
|
|
|
|
} /* END OF FUNCTION HandleMarqueeSelect */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* StartMarqueeSelect ()
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Start marquee selection on root window
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
void
|
|
StartMarqueeSelect(WmScreenData *pSD, XEvent *pev)
|
|
{
|
|
Window grab_win, junk_win;
|
|
Boolean grabbed;
|
|
int big_inc;
|
|
int junk;
|
|
|
|
if (!pSD->bMarqueeSelectionInitialized)
|
|
{
|
|
/*
|
|
* If we haven't initialized the marquee selection messaging
|
|
* then do so here before we do any grabs. Sending a dummy
|
|
* message will do.
|
|
*
|
|
* (If we move off of ICCCM messaging, then this can go away.)
|
|
*/
|
|
dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_END,
|
|
0, 0, 0, 0);
|
|
pSD->bMarqueeSelectionInitialized = True;
|
|
}
|
|
|
|
/*
|
|
* Do our grabs
|
|
*/
|
|
if (!configGrab)
|
|
{
|
|
grab_win = RootWindow (DISPLAY, pSD->screen);
|
|
|
|
if (pev)
|
|
{
|
|
grabbed = DoGrabs (grab_win, wmGD.configCursor,
|
|
PGRAB_MASK, pev->xbutton.time, NULL, True);
|
|
}
|
|
else
|
|
{
|
|
grabbed = DoGrabs (grab_win, wmGD.configCursor,
|
|
PGRAB_MASK, CurrentTime, NULL, True);
|
|
}
|
|
if (!grabbed)
|
|
{
|
|
return;
|
|
}
|
|
configGrab = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* continue with the configuration in progress (!!!) */
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Set up static variables for succeeding events
|
|
*/
|
|
if (pev && (pev->type == ButtonPress) || (pev->type == ButtonRelease))
|
|
{
|
|
pointerX = pev->xbutton.x_root;
|
|
pointerY = pev->xbutton.y_root;
|
|
}
|
|
else if (!XQueryPointer (DISPLAY, pSD->rootWindow,
|
|
&junk_win, &junk_win,
|
|
&pointerX, &pointerY,
|
|
&junk, &junk, (unsigned int *)&junk))
|
|
{
|
|
CancelFrameConfig ((ClientData *)NULL); /* release grabs */
|
|
return;
|
|
}
|
|
|
|
/* save start values to see where we came from */
|
|
marqueeX = startX = pointerX;
|
|
marqueeY = startY = pointerY;
|
|
marqueeWidth0 = marqueeWidth = 0;
|
|
marqueeHeight0 = marqueeHeight = 0;
|
|
marqueeAnchor = ANCHOR_NW;
|
|
|
|
/* compute increment value for dynamic update */
|
|
big_inc = DisplayWidth (DISPLAY, pSD->screen) / 20;
|
|
|
|
/* set configuring data */
|
|
wmGD.configAction = MARQUEE_SELECT;
|
|
wmGD.configButton = pev ? pev->xbutton.button: 0;
|
|
|
|
dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_BEGIN,
|
|
marqueeX, marqueeY, marqueeWidth, marqueeHeight);
|
|
|
|
} /* END OF FUNCTION StartMarqueeSelect */
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* UpdateMarqueeSelectData ()
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pSD - pointer to screen data
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*************************************<->***********************************/
|
|
void UpdateMarqueeSelectData (WmScreenData *pSD)
|
|
{
|
|
/* validate and update anchor point and marquee data */
|
|
|
|
switch (marqueeAnchor)
|
|
{
|
|
case ANCHOR_NW:
|
|
marqueeWidth = pointerX - marqueeX;
|
|
marqueeHeight = pointerY - marqueeY;
|
|
|
|
if (marqueeWidth < 0)
|
|
{
|
|
marqueeWidth = -marqueeWidth;
|
|
marqueeX = pointerX;
|
|
|
|
if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY;
|
|
marqueeAnchor = ANCHOR_SE;
|
|
}
|
|
else
|
|
{
|
|
marqueeAnchor = ANCHOR_NE;
|
|
}
|
|
}
|
|
else if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY;
|
|
marqueeAnchor = ANCHOR_SW;
|
|
}
|
|
break;
|
|
|
|
case ANCHOR_NE:
|
|
marqueeWidth += marqueeX - pointerX;
|
|
marqueeHeight = pointerY - marqueeY;
|
|
marqueeX = pointerX;
|
|
|
|
if (marqueeWidth < 0)
|
|
{
|
|
marqueeWidth = -marqueeWidth;
|
|
marqueeX = pointerX - marqueeWidth;
|
|
|
|
if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY;
|
|
marqueeAnchor = ANCHOR_SW;
|
|
}
|
|
else
|
|
{
|
|
marqueeAnchor = ANCHOR_NW;
|
|
}
|
|
}
|
|
else if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY;
|
|
marqueeAnchor = ANCHOR_SE;
|
|
}
|
|
break;
|
|
|
|
case ANCHOR_SE:
|
|
marqueeWidth += marqueeX - pointerX;
|
|
marqueeHeight += marqueeY - pointerY;
|
|
marqueeX = pointerX;
|
|
marqueeY = pointerY;
|
|
|
|
if (marqueeWidth < 0)
|
|
{
|
|
marqueeWidth = -marqueeWidth;
|
|
marqueeX = pointerX - marqueeWidth;
|
|
|
|
if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY - marqueeHeight;
|
|
marqueeAnchor = ANCHOR_NW;
|
|
}
|
|
else
|
|
{
|
|
marqueeAnchor = ANCHOR_SW;
|
|
}
|
|
}
|
|
else if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY - marqueeHeight;
|
|
marqueeAnchor = ANCHOR_NE;
|
|
}
|
|
break;
|
|
|
|
case ANCHOR_SW:
|
|
marqueeWidth = pointerX - marqueeX;
|
|
marqueeHeight += marqueeY - pointerY;
|
|
marqueeY = pointerY;
|
|
|
|
if (marqueeWidth < 0)
|
|
{
|
|
marqueeWidth = -marqueeWidth;
|
|
marqueeX = pointerX;
|
|
|
|
if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY - marqueeHeight;
|
|
marqueeAnchor = ANCHOR_NE;
|
|
}
|
|
else
|
|
{
|
|
marqueeAnchor = ANCHOR_SE;
|
|
}
|
|
}
|
|
else if (marqueeHeight < 0)
|
|
{
|
|
marqueeHeight = -marqueeHeight;
|
|
marqueeY = pointerY - marqueeHeight;
|
|
marqueeAnchor = ANCHOR_NW;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ((wmGD.marqueeSelectGranularity > 0) &&
|
|
((ABS(marqueeWidth-marqueeWidth0) > wmGD.marqueeSelectGranularity) ||
|
|
(ABS(marqueeHeight-marqueeHeight0)>wmGD.marqueeSelectGranularity)))
|
|
{
|
|
dtSendMarqueeSelectionNotification(pSD, DT_MARQUEE_SELECT_CONTINUE,
|
|
marqueeX, marqueeY, marqueeWidth, marqueeHeight);
|
|
|
|
marqueeWidth0 = marqueeWidth;
|
|
marqueeHeight0 = marqueeHeight;
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************<->*************************************
|
|
*
|
|
* HandleMarqueeKeyPress (pSD, pev)
|
|
*
|
|
*
|
|
* Description:
|
|
* -----------
|
|
* Handles keypress events during resize of window
|
|
*
|
|
*
|
|
* Inputs:
|
|
* ------
|
|
* pSD - pointer to screen data
|
|
* pev - pointer to event
|
|
*
|
|
*
|
|
* Outputs:
|
|
* -------
|
|
* Return - True if this event completes (or cancels) resizing
|
|
*
|
|
*
|
|
* Comments:
|
|
* --------
|
|
*
|
|
*************************************<->***********************************/
|
|
Boolean HandleMarqueeKeyPress (WmScreenData *pSD, XEvent *pev)
|
|
{
|
|
KeySym keysym;
|
|
Boolean control;
|
|
int keyMult;
|
|
XEvent KeyEvent;
|
|
|
|
/*
|
|
* Compress repeated keys
|
|
*/
|
|
keyMult = 1;
|
|
while (keyMult <= 10 &&
|
|
XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent,
|
|
(char *) pev))
|
|
{
|
|
keyMult++;
|
|
}
|
|
|
|
keysym = XKeycodeToKeysym (DISPLAY, pev->xkey.keycode, 0);
|
|
control = (pev->xkey.state & ControlMask) != 0;
|
|
|
|
switch (keysym) {
|
|
|
|
case XK_Return:
|
|
CompleteFrameConfig ((ClientData *)NULL, pev);
|
|
return (True);
|
|
|
|
case XK_Escape:
|
|
CancelFrameConfig ((ClientData *)NULL);
|
|
CheckEatButtonRelease ((ClientData *)NULL, pev);
|
|
return (True);
|
|
|
|
default:
|
|
return (False); /* ignore this key */
|
|
|
|
} /* end switch(keysym) */
|
|
|
|
} /* END OF FUNCTION HandleResizeKeyPress */
|