mirror of
https://github.com/NishiOwO/fvwm1.git
synced 2025-04-21 16:54:44 +00:00
663 lines
20 KiB
C
663 lines
20 KiB
C
/****************************************************************************
|
|
* This module is based on Twm, but has been siginificantly modified
|
|
* by Rob Nation
|
|
****************************************************************************/
|
|
/*****************************************************************************/
|
|
/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
|
|
/** Salt Lake City, Utah **/
|
|
/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
|
|
/** Cambridge, Massachusetts **/
|
|
/** **/
|
|
/** All Rights Reserved **/
|
|
/** **/
|
|
/** Permission to use, copy, modify, and distribute this software and **/
|
|
/** its documentation for any purpose and without fee is hereby **/
|
|
/** granted, provided that the above copyright notice appear in all **/
|
|
/** copies and that both that copyright notice and this permis- **/
|
|
/** sion notice appear in supporting documentation, and that the **/
|
|
/** names of Evans & Sutherland and M.I.T. not be used in advertising **/
|
|
/** in publicity pertaining to distribution of the software without **/
|
|
/** specific, written prior permission. **/
|
|
/** **/
|
|
/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
|
|
/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
|
|
/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
|
|
/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
|
|
/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
|
|
/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
|
|
/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
|
|
/** OR PERFORMANCE OF THIS SOFTWARE. **/
|
|
/*****************************************************************************/
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* window resizing borrowed from the "wm" window manager
|
|
*
|
|
***********************************************************************/
|
|
#include "../configure.h"
|
|
|
|
#include <stdio.h>
|
|
#include "fvwm.h"
|
|
#include "misc.h"
|
|
#include "screen.h"
|
|
#include "parse.h"
|
|
|
|
static int dragx; /* all these variables are used */
|
|
static int dragy; /* in resize operations */
|
|
static int dragWidth;
|
|
static int dragHeight;
|
|
|
|
static int origx;
|
|
static int origy;
|
|
static int origWidth;
|
|
static int origHeight;
|
|
|
|
static int ymotion, xmotion;
|
|
static int last_width,last_height;
|
|
extern int menuFromFrameOrWindowOrTitlebar;
|
|
extern Window PressedW;
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Starts a window resize operation
|
|
*
|
|
****************************************************************************/
|
|
void resize_window(Window w,FvwmWindow *tmp_win, int val1, int val2, int val1_unit, int val2_unit)
|
|
{
|
|
Bool finished = FALSE, done = FALSE;
|
|
int x,y,delta_x,delta_y;
|
|
Window ResizeWindow;
|
|
extern int Stashed_X, Stashed_Y;
|
|
Bool flags;
|
|
#ifndef NO_PAGER
|
|
extern Bool pagerOn;
|
|
#endif
|
|
|
|
if((w == None)||(tmp_win == NULL))
|
|
return;
|
|
|
|
/* Already checked this in functions.c, but its here too incase
|
|
* there's a resize on initial placement. */
|
|
if(check_allowed_function2(F_RESIZE,tmp_win) == 0)
|
|
{
|
|
XBell(dpy, Scr.screen);
|
|
return;
|
|
}
|
|
/* can't resize icons */
|
|
if(tmp_win->flags & ICONIFIED)
|
|
return;
|
|
|
|
ResizeWindow = tmp_win->frame;
|
|
|
|
if((val1 != 0)&&(val2 != 0))
|
|
{
|
|
int width,height;
|
|
|
|
dragWidth = val1*val1_unit/100;
|
|
dragHeight = val2*val2_unit/100;
|
|
|
|
ConstrainSize (tmp_win, &dragWidth, &dragHeight);
|
|
SetupFrame (tmp_win, tmp_win->frame_x,
|
|
tmp_win->frame_y ,dragWidth, dragHeight,FALSE);
|
|
|
|
ResizeWindow = None;
|
|
#ifndef NO_PAGER
|
|
RedrawPager();
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
InstallRootColormap();
|
|
if (menuFromFrameOrWindowOrTitlebar)
|
|
{
|
|
/* warp the pointer to the cursor position from before menu appeared*/
|
|
XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, Stashed_X,Stashed_Y);
|
|
XFlush(dpy);
|
|
}
|
|
|
|
if(!GrabEm(MOVE))
|
|
{
|
|
XBell(dpy,Scr.screen);
|
|
return;
|
|
}
|
|
|
|
if((!(Scr.flags & OpaqueResize))||
|
|
((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED))))
|
|
XGrabServer(dpy);
|
|
|
|
|
|
/* handle problems with edge-wrapping while resizing */
|
|
flags = Scr.flags;
|
|
Scr.flags &= ~(EdgeWrapX|EdgeWrapY);
|
|
|
|
#ifndef NO_PAGER
|
|
pagerOn = False;
|
|
#endif
|
|
XGetGeometry(dpy, (Drawable) ResizeWindow, &JunkRoot,
|
|
&dragx, &dragy, (unsigned int *)&dragWidth,
|
|
(unsigned int *)&dragHeight, &JunkBW,&JunkDepth);
|
|
|
|
dragx += tmp_win->bw;
|
|
dragy += tmp_win->bw;
|
|
origx = dragx;
|
|
origy = dragy;
|
|
origWidth = dragWidth;
|
|
origHeight = dragHeight;
|
|
ymotion=xmotion=0;
|
|
|
|
/* pop up a resize dimensions window */
|
|
XMapRaised(dpy, Scr.SizeWindow);
|
|
last_width = 0;
|
|
last_height = 0;
|
|
DisplaySize(tmp_win, origWidth, origHeight,True);
|
|
|
|
/* Get the current position to determine which border to resize */
|
|
if((PressedW != Scr.Root)&&(PressedW != None))
|
|
{
|
|
if(PressedW == tmp_win->sides[0]) /* top */
|
|
ymotion = 1;
|
|
if(PressedW == tmp_win->sides[1]) /* right */
|
|
xmotion = -1;
|
|
if(PressedW == tmp_win->sides[2]) /* bottom */
|
|
ymotion = -1;
|
|
if(PressedW == tmp_win->sides[3]) /* left */
|
|
xmotion = 1;
|
|
if(PressedW == tmp_win->corners[0]) /* upper-left */
|
|
{
|
|
ymotion = 1;
|
|
xmotion = 1;
|
|
}
|
|
if(PressedW == tmp_win->corners[1]) /* upper-right */
|
|
{
|
|
xmotion = -1;
|
|
ymotion = 1;
|
|
}
|
|
if(PressedW == tmp_win->corners[2]) /* lower right */
|
|
{
|
|
ymotion = -1;
|
|
xmotion = 1;
|
|
}
|
|
if(PressedW == tmp_win->corners[3]) /* lower left */
|
|
{
|
|
ymotion = -1;
|
|
xmotion = -1;
|
|
}
|
|
}
|
|
/* draw the rubber-band window */
|
|
if((!(Scr.flags & OpaqueResize))||
|
|
((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED))))
|
|
MoveOutline (Scr.Root, dragx - tmp_win->bw, dragy - tmp_win->bw, dragWidth + 2 * tmp_win->bw,
|
|
dragHeight + 2 * tmp_win->bw);
|
|
|
|
/* loop to resize */
|
|
while(!finished)
|
|
{
|
|
XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask |
|
|
ButtonMotionMask | PointerMotionMask | ExposureMask, &Event);
|
|
StashEventTime(&Event);
|
|
|
|
if (Event.type == MotionNotify)
|
|
/* discard any extra motion events before a release */
|
|
while(XCheckMaskEvent(dpy, ButtonMotionMask | ButtonReleaseMask |
|
|
PointerMotionMask,&Event))
|
|
{
|
|
StashEventTime(&Event);
|
|
if (Event.type == ButtonRelease) break;
|
|
}
|
|
|
|
done = FALSE;
|
|
/* Handle a limited number of key press events to allow mouseless
|
|
* operation */
|
|
if(Event.type == KeyPress)
|
|
Keyboard_shortcuts(&Event,ButtonRelease);
|
|
switch(Event.type)
|
|
{
|
|
case ButtonPress:
|
|
XAllowEvents(dpy,ReplayPointer,CurrentTime);
|
|
case KeyPress:
|
|
done = TRUE;
|
|
break;
|
|
|
|
case ButtonRelease:
|
|
finished = TRUE;
|
|
done = TRUE;
|
|
break;
|
|
|
|
case MotionNotify:
|
|
x = Event.xmotion.x_root;
|
|
y = Event.xmotion.y_root;
|
|
/* need to move the viewport */
|
|
HandlePaging(Scr.EdgeScrollX,Scr.EdgeScrollY,&x,&y,
|
|
&delta_x,&delta_y,False);
|
|
origx -= delta_x;
|
|
origy -= delta_y;
|
|
dragx -= delta_x;
|
|
dragy -= delta_y;
|
|
|
|
DoResize(x, y, tmp_win);
|
|
done = TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
if(!done)
|
|
{
|
|
if((!(Scr.flags & OpaqueResize))||
|
|
((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED))))
|
|
MoveOutline(Scr.Root,0,0,0,0);
|
|
|
|
DispatchEvent();
|
|
|
|
if((!(Scr.flags & OpaqueResize))||
|
|
((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED))))
|
|
MoveOutline(Scr.Root, dragx - tmp_win->bw, dragy - tmp_win->bw,
|
|
dragWidth + 2 * tmp_win->bw, dragHeight + 2 * tmp_win->bw);
|
|
|
|
}
|
|
}
|
|
|
|
/* erase the rubber-band */
|
|
if((!(Scr.flags & OpaqueResize))||
|
|
((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED))))
|
|
MoveOutline(Scr.Root, 0, 0, 0, 0);
|
|
|
|
/* pop down the size window */
|
|
XUnmapWindow(dpy, Scr.SizeWindow);
|
|
|
|
#ifndef NO_PAGER
|
|
pagerOn = True;
|
|
#endif
|
|
ConstrainSize (tmp_win, &dragWidth, &dragHeight);
|
|
SetupFrame (tmp_win, dragx - tmp_win->bw,
|
|
dragy - tmp_win->bw, dragWidth, dragHeight,FALSE);
|
|
|
|
UninstallRootColormap();
|
|
ResizeWindow = None;
|
|
XUngrabServer(dpy);
|
|
UngrabEm();
|
|
#ifndef NO_PAGER
|
|
RedrawPager();
|
|
#endif
|
|
Scr.flags |= flags & (EdgeWrapX|EdgeWrapY);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Procedure:
|
|
* DoResize - move the rubberband around. This is called for
|
|
* each motion event when we are resizing
|
|
*
|
|
* Inputs:
|
|
* x_root - the X corrdinate in the root window
|
|
* y_root - the Y corrdinate in the root window
|
|
* tmp_win - the current fvwm window
|
|
*
|
|
************************************************************************/
|
|
void DoResize(int x_root, int y_root, FvwmWindow *tmp_win)
|
|
{
|
|
int action=0;
|
|
#ifndef NO_PAGER
|
|
unsigned int width,height;
|
|
int ww,wh;
|
|
int wx,wy;
|
|
int MaxH,MaxW;
|
|
static int last_w = -10000, last_h = -10000;
|
|
#endif
|
|
|
|
if ((y_root <= origy)||((ymotion == 1)&&(y_root < origy+origHeight-1)))
|
|
{
|
|
dragy = y_root;
|
|
dragHeight = origy + origHeight - y_root;
|
|
action = 1;
|
|
ymotion = 1;
|
|
}
|
|
else if ((y_root >= origy + origHeight - 1)||
|
|
((ymotion == -1)&&(y_root > origy)))
|
|
{
|
|
dragy = origy;
|
|
dragHeight = 1 + y_root - dragy;
|
|
action = 1;
|
|
ymotion = -1;
|
|
}
|
|
|
|
if ((x_root <= origx)||
|
|
((xmotion == 1)&&(x_root < origx + origWidth - 1)))
|
|
{
|
|
dragx = x_root;
|
|
dragWidth = origx + origWidth - x_root;
|
|
action = 1;
|
|
xmotion = 1;
|
|
}
|
|
if ((x_root >= origx + origWidth - 1)||
|
|
((xmotion == -1)&&(x_root > origx)))
|
|
{
|
|
dragx = origx;
|
|
dragWidth = 1 + x_root - origx;
|
|
action = 1;
|
|
xmotion = -1;
|
|
}
|
|
|
|
if (action)
|
|
{
|
|
ConstrainSize (tmp_win, &dragWidth, &dragHeight);
|
|
if (xmotion == 1)
|
|
dragx = origx + origWidth - dragWidth;
|
|
if (ymotion == 1)
|
|
dragy = origy + origHeight - dragHeight;
|
|
|
|
#ifndef NO_PAGER
|
|
/* update size of the pager_view window */
|
|
if((Scr.FvwmPager != NULL)&&
|
|
(dragx < Scr.FvwmPager->frame_x + Scr.FvwmPager->frame_width)&&
|
|
(dragx+dragWidth > Scr.FvwmPager->frame_x)&&
|
|
(dragy < Scr.FvwmPager->frame_y + Scr.FvwmPager->frame_height)&&
|
|
(dragy+dragHeight > Scr.FvwmPager->frame_y)&&
|
|
((!(Scr.flags & OpaqueResize))||
|
|
((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED)))))
|
|
MoveOutline(Scr.Root,0,0,0,0);
|
|
if(Scr.FvwmPager)
|
|
{
|
|
width = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width;
|
|
height = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height
|
|
- 2*Scr.FvwmPager->boundary_width;
|
|
|
|
MaxW = Scr.VxMax + Scr.MyDisplayWidth;
|
|
MaxH = Scr.VyMax + Scr.MyDisplayHeight;
|
|
|
|
if(!(tmp_win->flags & STICKY)&&
|
|
(!(tmp_win->flags & ICONIFIED)||(!(Scr.flags & SuppressIcons)))&&
|
|
(!(tmp_win->flags & ICONIFIED)||(!(Scr.flags & StickyIcons))))
|
|
{
|
|
/* show the actual window */
|
|
wx = (dragx + Scr.Vx)*(int)width/MaxW;
|
|
wy = (dragy + Scr.Vy)*(int)height/MaxH;
|
|
ww = dragWidth*(int)width/MaxW;
|
|
wh = dragHeight*(int)height/MaxH;
|
|
|
|
if((last_w - ww >= 2)||(last_w - ww <= -2)||
|
|
(last_h - wh >= 2)||(last_h - wh <= -2))
|
|
{
|
|
if(ww<2)ww=2;
|
|
if(wh<2)wh=2;
|
|
XMoveResizeWindow(dpy, tmp_win->pager_view, wx, wy, ww, wh);
|
|
last_h = wh;
|
|
last_w = ww;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if((!(Scr.flags & OpaqueResize))||
|
|
((Scr.flags & OpaqueResize)&&(!(tmp_win->flags & MAPPED))))
|
|
{
|
|
MoveOutline(Scr.Root, dragx - tmp_win->bw,dragy - tmp_win->bw,
|
|
dragWidth + 2 * tmp_win->bw, dragHeight + 2 * tmp_win->bw);
|
|
}
|
|
else
|
|
{
|
|
SetupFrame (tmp_win, dragx - tmp_win->bw,
|
|
dragy - tmp_win->bw, dragWidth, dragHeight,FALSE);
|
|
}
|
|
}
|
|
DisplaySize(tmp_win, dragWidth, dragHeight,False);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Procedure:
|
|
* DisplaySize - display the size in the dimensions window
|
|
*
|
|
* Inputs:
|
|
* tmp_win - the current fvwm window
|
|
* width - the width of the rubber band
|
|
* height - the height of the rubber band
|
|
*
|
|
***********************************************************************/
|
|
void DisplaySize(FvwmWindow *tmp_win, int width, int height,Bool Init)
|
|
{
|
|
char str[100];
|
|
int dwidth,dheight,offset;
|
|
|
|
if (last_width == width && last_height == height)
|
|
return;
|
|
|
|
last_width = width;
|
|
last_height = height;
|
|
|
|
dheight = height - tmp_win->title_height - 2*tmp_win->boundary_width;
|
|
dwidth = width - 2*tmp_win->boundary_width;
|
|
|
|
dwidth -= tmp_win->hints.base_width;
|
|
dheight -= tmp_win->hints.base_height;
|
|
dwidth /= tmp_win->hints.width_inc;
|
|
dheight /= tmp_win->hints.height_inc;
|
|
|
|
(void) sprintf (str, " %4d x %-4d ", dwidth, dheight);
|
|
offset = (Scr.SizeStringWidth + SIZE_HINDENT*2
|
|
- XTextWidth(Scr.StdFont.font,str,strlen(str)))/2;
|
|
if(Init)
|
|
{
|
|
XClearWindow(dpy,Scr.SizeWindow);
|
|
if(Scr.d_depth >= 2)
|
|
RelieveWindow(tmp_win,
|
|
Scr.SizeWindow,0,0,Scr.SizeStringWidth+ SIZE_HINDENT*2,
|
|
Scr.StdFont.height + SIZE_VINDENT*2,
|
|
Scr.StdReliefGC,Scr.StdShadowGC,FULL_HILITE);
|
|
}
|
|
else
|
|
{
|
|
XClearArea(dpy,Scr.SizeWindow,SIZE_HINDENT,SIZE_VINDENT,Scr.SizeStringWidth,
|
|
Scr.StdFont.height,False);
|
|
}
|
|
|
|
XDrawString (dpy, Scr.SizeWindow, Scr.NormalGC,
|
|
offset, Scr.StdFont.font->ascent + SIZE_VINDENT, str, 13);
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Procedure:
|
|
* ConstrainSize - adjust the given width and height to account for the
|
|
* constraints imposed by size hints
|
|
*
|
|
* The general algorithm, especially the aspect ratio stuff, is
|
|
* borrowed from uwm's CheckConsistency routine.
|
|
*
|
|
***********************************************************************/
|
|
|
|
void ConstrainSize (FvwmWindow *tmp_win, int *widthp, int *heightp)
|
|
{
|
|
#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
|
|
#define _min(a,b) (((a) < (b)) ? (a) : (b))
|
|
int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
|
|
int baseWidth, baseHeight;
|
|
int dwidth = *widthp, dheight = *heightp;
|
|
|
|
dwidth -= 2 *tmp_win->boundary_width;
|
|
dheight -= (tmp_win->title_height + 2*tmp_win->boundary_width);
|
|
|
|
minWidth = tmp_win->hints.min_width;
|
|
minHeight = tmp_win->hints.min_height;
|
|
|
|
baseWidth = tmp_win->hints.base_width;
|
|
baseHeight = tmp_win->hints.base_height;
|
|
|
|
maxWidth = tmp_win->hints.max_width;
|
|
maxHeight = tmp_win->hints.max_height;
|
|
|
|
/* maxWidth = Scr.VxMax + Scr.MyDisplayWidth;
|
|
maxHeight = Scr.VyMax + Scr.MyDisplayHeight;*/
|
|
|
|
xinc = tmp_win->hints.width_inc;
|
|
yinc = tmp_win->hints.height_inc;
|
|
|
|
/*
|
|
* First, clamp to min and max values
|
|
*/
|
|
if (dwidth < minWidth) dwidth = minWidth;
|
|
if (dheight < minHeight) dheight = minHeight;
|
|
|
|
if (dwidth > maxWidth) dwidth = maxWidth;
|
|
if (dheight > maxHeight) dheight = maxHeight;
|
|
|
|
|
|
/*
|
|
* Second, fit to base + N * inc
|
|
*/
|
|
dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
|
|
dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
|
|
|
|
|
|
/*
|
|
* Third, adjust for aspect ratio
|
|
*/
|
|
#define maxAspectX tmp_win->hints.max_aspect.x
|
|
#define maxAspectY tmp_win->hints.max_aspect.y
|
|
#define minAspectX tmp_win->hints.min_aspect.x
|
|
#define minAspectY tmp_win->hints.min_aspect.y
|
|
/*
|
|
* The math looks like this:
|
|
*
|
|
* minAspectX dwidth maxAspectX
|
|
* ---------- <= ------- <= ----------
|
|
* minAspectY dheight maxAspectY
|
|
*
|
|
* If that is multiplied out, then the width and height are
|
|
* invalid in the following situations:
|
|
*
|
|
* minAspectX * dheight > minAspectY * dwidth
|
|
* maxAspectX * dheight < maxAspectY * dwidth
|
|
*
|
|
*/
|
|
|
|
if (tmp_win->hints.flags & PAspect)
|
|
{
|
|
if (minAspectX * dheight > minAspectY * dwidth)
|
|
{
|
|
delta = makemult(minAspectX * dheight / minAspectY - dwidth,
|
|
xinc);
|
|
if (dwidth + delta <= maxWidth)
|
|
dwidth += delta;
|
|
else
|
|
{
|
|
delta = makemult(dheight - dwidth*minAspectY/minAspectX,
|
|
yinc);
|
|
if (dheight - delta >= minHeight) dheight -= delta;
|
|
}
|
|
}
|
|
|
|
if (maxAspectX * dheight < maxAspectY * dwidth)
|
|
{
|
|
delta = makemult(dwidth * maxAspectY / maxAspectX - dheight,
|
|
yinc);
|
|
if (dheight + delta <= maxHeight)
|
|
dheight += delta;
|
|
else
|
|
{
|
|
delta = makemult(dwidth - maxAspectX*dheight/maxAspectY,
|
|
xinc);
|
|
if (dwidth - delta >= minWidth) dwidth -= delta;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Fourth, account for border width and title height
|
|
*/
|
|
*widthp = dwidth + 2*tmp_win->boundary_width;
|
|
*heightp = dheight + tmp_win->title_height + 2*tmp_win->boundary_width;
|
|
return;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Procedure:
|
|
* MoveOutline - move a window outline
|
|
*
|
|
* Inputs:
|
|
* root - the window we are outlining
|
|
* x - upper left x coordinate
|
|
* y - upper left y coordinate
|
|
* width - the width of the rectangle
|
|
* height - the height of the rectangle
|
|
*
|
|
***********************************************************************/
|
|
void MoveOutline(Window root, int x, int y, int width, int height)
|
|
{
|
|
static int lastx = 0;
|
|
static int lasty = 0;
|
|
static int lastWidth = 0;
|
|
static int lastHeight = 0;
|
|
XRectangle rects[5];
|
|
|
|
if (x == lastx && y == lasty && width == lastWidth && height == lastHeight)
|
|
return;
|
|
|
|
/* undraw the old one, if any */
|
|
if (lastWidth || lastHeight)
|
|
{
|
|
rects[0].x = lastx;
|
|
rects[0].y = lasty;
|
|
rects[0].width = lastWidth;
|
|
rects[0].height = lastHeight;
|
|
rects[1].x = lastx+1;
|
|
rects[1].y = lasty+1;
|
|
rects[1].width = lastWidth-2;
|
|
rects[1].height = lastHeight-2;
|
|
rects[2].x = lastx+2;
|
|
rects[2].y = lasty+2;
|
|
rects[2].width = lastWidth-4;
|
|
rects[2].height = lastHeight-4;
|
|
rects[3].x = lastx+3;
|
|
rects[3].y = lasty+3 + (lastHeight-6)/3;
|
|
rects[3].width = lastWidth-6;
|
|
rects[3].height = (lastHeight-6)/3;
|
|
rects[4].x = lastx+3 + (lastWidth-6)/3;
|
|
rects[4].y = lasty+3;
|
|
rects[4].width = (lastWidth-6)/3;
|
|
rects[4].height = (lastHeight-6);
|
|
XDrawRectangles(dpy,Scr.Root,Scr.DrawGC,rects,5);
|
|
}
|
|
|
|
lastx = x;
|
|
lasty = y;
|
|
lastWidth = width;
|
|
lastHeight = height;
|
|
|
|
/* draw the new one, if any */
|
|
if (lastWidth || lastHeight)
|
|
{
|
|
rects[0].x = lastx;
|
|
rects[0].y = lasty;
|
|
rects[0].width = lastWidth;
|
|
rects[0].height = lastHeight;
|
|
rects[1].x = lastx+1;
|
|
rects[1].y = lasty+1;
|
|
rects[1].width = lastWidth-2;
|
|
rects[1].height = lastHeight-2;
|
|
rects[2].x = lastx+2;
|
|
rects[2].y = lasty+2;
|
|
rects[2].width = lastWidth-4;
|
|
rects[2].height = lastHeight-4;
|
|
rects[3].x = lastx+3;
|
|
rects[3].y = lasty+3 + (lastHeight-6)/3;
|
|
rects[3].width = lastWidth-6;
|
|
rects[3].height = (lastHeight-6)/3;
|
|
rects[4].x = lastx+3 + (lastWidth-6)/3;
|
|
rects[4].y = lasty+3;
|
|
rects[4].width = (lastWidth-6)/3;
|
|
rects[4].height = (lastHeight-6);
|
|
XDrawRectangles(dpy,Scr.Root,Scr.DrawGC,rects,5);
|
|
}
|
|
}
|
|
|
|
|