MoveResizeWindow.c (Re: Moving and resizing windows inside window)
MoveResizeWindow.c (Re: Moving and resizing windows inside window)
- Subject: MoveResizeWindow.c (Re: Moving and resizing windows inside window)
- From: Eeri Kask <email@hidden>
- Date: Mon, 19 Oct 2009 15:03:36 +0200
Am 10/11/2009 09:07 PM, Doug Carter <email@hidden> schrieb:
> I think I need to clarify my request. It's not that I want to run twm,
> it's the functionality it provided. Specifically, the ability to move,
> resize and iconify windows by clicking anywhere inside a window. I know
> that twm has this ability, but wondered if there were XQuartz config
> options that would give me the same functionality.
>
> As stated in my original post, I found a utility for the Mac called
> Zooom, (http://coderage-software.com/zooom/) which lets me move and
> resize windows by clicking anywhere in a window. It works great for Mac
> application windows, but not for any X application windows.
Have you managed to solve this problem?
Otherwise maybe you take a look at the attached 200-lines small
utility I had to create a while ago partly out of this same
necessity and you find this helpful. :-)
Compile this piece twice as given in the top-comment, then start in
front of both all windows-creating applications and the window
manager in .xinitrc respectively
xmove_window 1 cs &
xmoveresize_window 3 cs &
which means --- for modifiers Control+Shift a "hotbutton-1" for
moving windows, and a "hotbutton-3" for resizing windows is
installed. (The first argument gives the button, the second the
needed modifiers: 'c' for Control, 's' Shift, 'l' Lock, '1'...'5'
for Mod1...Mod5 keys.)
In fact this tool has another, its most important "feature": being
an ordinary non-windows-creating X11-client it usually survives a
window manager (or desktop environment) collapse and lets you still
work with your applications, nearly as if nothing had happened. In
a window-manager-still-operational mode this tool having established
a "passive-grab" on each mapped client window ... as this grab
triggers, it "withdraws" the client from the window manager by
marking it "override_redirect", so from that moment on one can
manipulate the geometry of that client window unhindered arbitrarily
(move, resize, raise-lower, etc). If you are finished, that window
is made visible to the window manager again, and its updated
geometry is advertised.
This tool has proven a good replacement even for a window manager
altogether if all you need is move, resize and raise-lower windows.
Though, beware, it discloses lots of usual applications bugs if run
on a blank X11-server in the absence of a "conventional" window
manager where these bugs never show, like raising main window ontop
of its pull down menus; or some "Locally-Active"-focus client not
releasing focus if mouse has left, and the like.
Otherwise beware even further, as a second-layer window manager
beneath the desktop, if used "enthusiastically", like sqeezing or
moving the dock or the top-edge multifunctional menu-bar, or desktop
icons, or whatever out of the screen area, one can easily demolish
the desktop so its further behaviour becomes completely unpredictable.
I haven't tested it on MacOSX with quartz-wm until recently and it
appears working perfect. (Though it looks like quartz-wm marks all
managed clients "override_redirect" too so the above stealth-mode
has no effect.) As Xquartz is seemingly a usual client on Aqua
desktop, one has no access to Aqua items by this tool as opposed to
KDE/GNOME or the like, so one cannot screw Aqua that way.
Have fun, (if you find any bugs, or improvement ideas please let me
know) :-)
Eeri Kask
/*
gcc -O1 -o ${HBIN:-.}/xmoveresize_window MoveResizeWindow.c -L/usr/X11R6/lib -lX11 -lXmu -DCOMPILE_MAIN_MOVE_WINDOW -DMOVE_RESIZE_WINDOW
gcc -O1 -o ${HBIN:-.}/xmove_window MoveResizeWindow.c -L/usr/X11R6/lib -lX11 -lXmu -DCOMPILE_MAIN_MOVE_WINDOW
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h> /*XUniqueContext()*/
#include <X11/Xresource.h> /*XrmUniqueQuark()*/
static void SetOverrideRedirect (Display *dsp, Window win, Bool val)
{
XSetWindowAttributes a;
a.override_redirect = val;
XChangeWindowAttributes (dsp, win, CWOverrideRedirect, &a);
XSync (dsp, False);
}
static void RaiseLowerWindow (Display *dsp, Window win)
{
XWindowChanges c;
c.stack_mode = Opposite;
XConfigureWindow (dsp, win, CWStackMode, &c);
}
static void MoveResizeWindow (Display *dsp, Window ewin, Window mwin, /*ButtonPress*/ XEvent *e)
{
Bool o;
Window tmp;
int x, y, buttons;
unsigned w, h, b, d;
XWindowAttributes att;
XGetWindowAttributes (dsp, mwin, &att);
o = att.override_redirect;
if (o == False)
SetOverrideRedirect (dsp, mwin, True); /* "hide" window */
x = e->xbutton.x_root - att.x;
y = e->xbutton.y_root - att.y;
buttons = 1; /* <-- the caller 'ButtonPress' which initiated 'MoveResizeWindow()' */
do
{
XAllowEvents (dsp, SyncPointer, CurrentTime);
XWindowEvent (dsp, ewin, (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask), e);
switch (e->xany.type)
{
case ButtonPress:
buttons++;
break;
case ButtonRelease:
if (buttons > 0) /* there may have been some down before we started */
buttons--;
break;
case MotionNotify:
#ifdef MOVE_RESIZE_WINDOW
{
int x0 = att.x;
int y0 = att.y;
int dx = e->xmotion.x_root - x0 - x;
int dy = e->xmotion.y_root - y0 - y;
if (x < (att.width>>1)) {
x0 += dx;
dx = -dx;
}
if (y < (att.height>>1)) {
y0 += dy;
dy = -dy;
}
dx += att.width;
dy += att.height;
if (dx > 0 && dy > 0)
XMoveResizeWindow (dsp, mwin, x0, y0, dx, dy);
}
#else
XMoveWindow (dsp, mwin, e->xmotion.x_root-x, e->xmotion.y_root-y);
#endif
break;
}
} while (buttons != 0);
XGetGeometry (dsp, mwin, &tmp, &x, &y, &w, &h, &b, &d);
if (x == att.x && y == att.y && w == att.width && h == att.height)
RaiseLowerWindow (dsp, mwin); /* if neither move nor resize, then change stacking order */
if (o == False)
{
SetOverrideRedirect (dsp, mwin, False); /* "unhide" window */
#ifdef MOVE_RESIZE_WINDOW /* tell the window manager about geometry change and let check PResizeInc, PAspect etc */
XMoveResizeWindow (dsp, mwin, x, y, w, h);
#else
XMoveWindow (dsp, mwin, x, y);
#endif
}
}
void MoveResizePassiveGrabEvents (Display *dsp, Window ewin, unsigned but, unsigned mod, unsigned mask, Cursor c)
{
XPointer dummy;
XContext track = XUniqueContext();
XSelectInput (dsp, ewin, SubstructureNotifyMask);
for (;;)
{
XEvent e;
XNextEvent (dsp, &e);
switch (e.type)
{
case MapNotify:
XSaveContext (dsp, e.xmap.window, track, (XPointer)(0));
XGrabButton (dsp, but, mod, e.xmap.window, False,
(ButtonPressMask | ButtonReleaseMask | mask),
GrabModeSync, GrabModeAsync, e.xmap.event, c);
break;
case UnmapNotify:
if (XFindContext (dsp, e.xunmap.window, track, &dummy) == 0) {
XDeleteContext (dsp, e.xunmap.window, track);
XUngrabButton (dsp, but, mod, e.xunmap.window); /* 'failed-request-error' if client destroyed */
}
break;
case ButtonPress: /* passive grab: assuming button events are otherwise not selected */
MoveResizeWindow (dsp, e.xbutton.window, e.xbutton.window, &e);
break;
}
}
XSelectInput (dsp, ewin, NoEventMask);
}
#ifdef COMPILE_MAIN_MOVE_WINDOW
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <signal.h>
#include <X11/Xproto.h>
#include <X11/Xmu/Xmu.h>
#include <X11/cursorfont.h>
static int xerrors (Display *d, XErrorEvent *e)
{
#if 1
if (!(e->request_code == X_UngrabButton && e->error_code == BadWindow))
#endif
{
time_t moment = time (NULL);
fprintf (stderr, "MoveResizeWindow.c: %s", asctime(localtime(&moment)));
XmuPrintDefaultErrorMessage (d, e, stderr);
}
return 0;
}
static Display * dsp = 0;
static void term (int sig)
{
if (dsp)
XCloseDisplay (dsp);
exit (0);
}
int main (int argc, char * argv[])
{
if (argc == 2 && ((strcmp (argv[1], "-help") == 0) || (strcmp (argv[1], "?") == 0)))
{
fprintf (stderr, "Usage:\t%s 3 1\t\tInstalls 'Button3+Mod1' passive grab.\n\t\t\t\t\t(csl5 ~ Control Shift Lock Mod5)\n", argv[0]);
}
else
{
signal (SIGINT, (void(*)(int))(term));
signal (SIGTERM, (void(*)(int))(term));
dsp = XOpenDisplay (NULL);
if (dsp)
{
static unsigned button[] = { AnyButton, Button1, Button2, Button3, Button4, Button5 };
static unsigned bmask[] = { ButtonMotionMask, Button1MotionMask, Button2MotionMask, Button3MotionMask, Button4MotionMask, Button5MotionMask };
static unsigned mmask[] = { AnyModifier, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
unsigned bix, mod;
if (1 < argc && isdigit(argv[1][0]) && '0' <= argv[1][0] && argv[1][0] <= '5')
bix = argv[1][0] - '0';
else
#ifdef MOVE_RESIZE_WINDOW
bix = 3; /* Button3 */
#else
bix = 1; /* Button1 */
#endif
mod = 0;
if (2 < argc)
{
int i = strlen (argv[2]);
while (i--)
if (isdigit(argv[2][i]) && '0' <= argv[2][i] && argv[2][i] <= '5') {
mod |= mmask[argv[2][i] - '0'];
break;
}
if (strchr(argv[2], 'c') != NULL)
mod |= ControlMask;
if (strchr(argv[2], 's') != NULL)
mod |= ShiftMask;
if (strchr(argv[2], 'l') != NULL)
mod |= LockMask;
}
if (mod == 0)
mod = mmask[1]; /* Mod1Mask */
#ifdef MOVE_RESIZE_WINDOW
Cursor c = XCreateFontCursor (dsp, XC_sizing);
#else
Cursor c = XCreateFontCursor (dsp, XC_fleur);
#endif
XSetErrorHandler (xerrors);
MoveResizePassiveGrabEvents (dsp, XDefaultRootWindow(dsp), button[bix], mod, bmask[bix], c);
XFreeCursor (dsp, c);
term (SIGTERM);
}
}
return 1;
}
#endif
_______________________________________________
Do not post admin requests to the list. They will be ignored.
X11-users mailing list (email@hidden)
This email sent to email@hidden