mirror of
https://github.com/gryf/wmaker.git
synced 2026-03-19 17:23:33 +01:00
wmaker: add support for _NET_WM_MOVERESIZE
This patch adds support for _NET_WM_MOVERESIZE hint as defined in EWMH which allows a window without decorations to manage itself (moving/resizing). The purpose is to fix the issue mentioned at https://github.com/window-maker/wmaker/issues/20 Tested with VS Code, Google Chrome, Steam and Discord. Specs are available at https://specifications.freedesktop.org/wm/1.5/ar01s04.html#id-1.5.4
This commit is contained in:
committed by
Carlos R. Mafra
parent
ef1a504898
commit
6d0953bc22
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wconfig.h"
|
#include "wconfig.h"
|
||||||
|
#include "wmspec.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
@@ -1916,7 +1917,7 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (event.xbutton.button != ev->xbutton.button)
|
if (!wwin->moveresize.active && (event.xbutton.button != ev->xbutton.button))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (started) {
|
if (started) {
|
||||||
@@ -1964,6 +1965,10 @@ int wMouseMoveWindow(WWindow * wwin, XEvent * ev)
|
|||||||
WMUnmapWidget(scr->gview);
|
WMUnmapWidget(scr->gview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
wwin->moveresize.active = 0;
|
||||||
|
}
|
||||||
done = True;
|
done = True;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2101,8 +2106,13 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
wwarning("internal error: tryein");
|
wwarning("internal error: tryein");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
orig_x = ev->xbutton.x_root;
|
if (ev->type == MotionNotify) {
|
||||||
orig_y = ev->xbutton.y_root;
|
orig_x = ev->xmotion.x_root;
|
||||||
|
orig_y = ev->xmotion.y_root;
|
||||||
|
} else {
|
||||||
|
orig_x = ev->xbutton.x_root;
|
||||||
|
orig_y = ev->xbutton.y_root;
|
||||||
|
}
|
||||||
|
|
||||||
started = 0;
|
started = 0;
|
||||||
wUnselectWindows(scr);
|
wUnselectWindows(scr);
|
||||||
@@ -2113,6 +2123,29 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
shiftl = XKeysymToKeycode(dpy, XK_Shift_L);
|
shiftl = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||||
shiftr = XKeysymToKeycode(dpy, XK_Shift_R);
|
shiftr = XKeysymToKeycode(dpy, XK_Shift_R);
|
||||||
|
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
int direction = wwin->moveresize.resize_edge;
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
is_resizebar = 0;
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_SIZE_TOP)
|
||||||
|
res |= UP;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_BOTTOM)
|
||||||
|
res |= DOWN;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_LEFT)
|
||||||
|
res |= LEFT;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_RIGHT)
|
||||||
|
res |= RIGHT;
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_TOPLEFT)
|
||||||
|
res |= (UP | LEFT);
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_TOPRIGHT)
|
||||||
|
res |= (UP | RIGHT);
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)
|
||||||
|
res |= (DOWN | LEFT);
|
||||||
|
else if (direction == _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)
|
||||||
|
res |= (DOWN | RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
WMMaskEvent(dpy, KeyPressMask | ButtonMotionMask
|
WMMaskEvent(dpy, KeyPressMask | ButtonMotionMask
|
||||||
| ButtonReleaseMask | PointerMotionHintMask | ButtonPressMask | ExposureMask, &event);
|
| ButtonReleaseMask | PointerMotionHintMask | ButtonPressMask | ExposureMask, &event);
|
||||||
@@ -2269,7 +2302,7 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (event.xbutton.button != ev->xbutton.button)
|
if (!wwin->moveresize.active && (event.xbutton.button != ev->xbutton.button))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (started) {
|
if (started) {
|
||||||
@@ -2291,6 +2324,11 @@ void wMouseResizeWindow(WWindow * wwin, XEvent * ev)
|
|||||||
wWindowConfigure(wwin, fx, fy, fw, fh - vert_border);
|
wWindowConfigure(wwin, fx, fy, fw, fh - vert_border);
|
||||||
wWindowSynthConfigureNotify(wwin);
|
wWindowSynthConfigureNotify(wwin);
|
||||||
}
|
}
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
wwin->moveresize.active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -237,6 +237,12 @@ typedef struct WWindow {
|
|||||||
int cmap_window_no;
|
int cmap_window_no;
|
||||||
Window *cmap_windows;
|
Window *cmap_windows;
|
||||||
|
|
||||||
|
/* move/resize state for _NET_WM_MOVERESIZE support */
|
||||||
|
struct {
|
||||||
|
int active; /* 1 if move/resize is in progress */
|
||||||
|
int resize_edge; /* which edge for resize (0-7) */
|
||||||
|
} moveresize;
|
||||||
|
|
||||||
/* protocols */
|
/* protocols */
|
||||||
WProtocols protocols; /* accepted WM_PROTOCOLS */
|
WProtocols protocols; /* accepted WM_PROTOCOLS */
|
||||||
|
|
||||||
|
|||||||
113
src/wmspec.c
113
src/wmspec.c
@@ -71,7 +71,7 @@ static Atom net_showing_desktop;
|
|||||||
/* Other Root Window Messages */
|
/* Other Root Window Messages */
|
||||||
static Atom net_close_window;
|
static Atom net_close_window;
|
||||||
static Atom net_moveresize_window; /* TODO */
|
static Atom net_moveresize_window; /* TODO */
|
||||||
static Atom net_wm_moveresize; /* TODO */
|
static Atom net_wm_moveresize;
|
||||||
|
|
||||||
/* Application Window Properties */
|
/* Application Window Properties */
|
||||||
static Atom net_wm_name;
|
static Atom net_wm_name;
|
||||||
@@ -125,7 +125,7 @@ static Atom net_wm_strut;
|
|||||||
static Atom net_wm_strut_partial; /* TODO: doesn't really fit into the current strut scheme */
|
static Atom net_wm_strut_partial; /* TODO: doesn't really fit into the current strut scheme */
|
||||||
static Atom net_wm_icon_geometry; /* FIXME: should work together with net_wm_handled_icons, gnome-panel-2.2.0.1 doesn't use _NET_WM_HANDLED_ICONS, thus present situation. */
|
static Atom net_wm_icon_geometry; /* FIXME: should work together with net_wm_handled_icons, gnome-panel-2.2.0.1 doesn't use _NET_WM_HANDLED_ICONS, thus present situation. */
|
||||||
static Atom net_wm_icon;
|
static Atom net_wm_icon;
|
||||||
static Atom net_wm_pid; /* TODO */
|
static Atom net_wm_pid;
|
||||||
static Atom net_wm_handled_icons; /* FIXME: see net_wm_icon_geometry */
|
static Atom net_wm_handled_icons; /* FIXME: see net_wm_icon_geometry */
|
||||||
static Atom net_wm_window_opacity;
|
static Atom net_wm_window_opacity;
|
||||||
|
|
||||||
@@ -226,35 +226,6 @@ static atomitem_t atomNames[] = {
|
|||||||
#define _NET_WM_STATE_ADD 1
|
#define _NET_WM_STATE_ADD 1
|
||||||
#define _NET_WM_STATE_TOGGLE 2
|
#define _NET_WM_STATE_TOGGLE 2
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* These constant provide information on the kind of window move/resize when
|
|
||||||
* it is initiated by the application instead of by WindowMaker. They are
|
|
||||||
* parameter for the client message _NET_WM_MOVERESIZE, as defined by the
|
|
||||||
* FreeDesktop wm-spec standard:
|
|
||||||
* http://standards.freedesktop.org/wm-spec/1.5/ar01s04.html
|
|
||||||
*
|
|
||||||
* Today, WindowMaker does not support this at all (the corresponding Atom
|
|
||||||
* is not added to the list in setSupportedHints), probably because there is
|
|
||||||
* nothing it needs to do about it, the application is assumed to know what
|
|
||||||
* it is doing, and WindowMaker won't get in the way.
|
|
||||||
*
|
|
||||||
* The definition of the constants (taken from the standard) are disabled to
|
|
||||||
* avoid a spurious warning (-Wunused-macros).
|
|
||||||
*/
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
|
|
||||||
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
|
|
||||||
#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
|
|
||||||
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void observer(void *self, WMNotification *notif);
|
static void observer(void *self, WMNotification *notif);
|
||||||
static void wsobserver(void *self, WMNotification *notif);
|
static void wsobserver(void *self, WMNotification *notif);
|
||||||
|
|
||||||
@@ -294,9 +265,7 @@ static void setSupportedHints(WScreen *scr)
|
|||||||
atom[i++] = net_workarea;
|
atom[i++] = net_workarea;
|
||||||
atom[i++] = net_supporting_wm_check;
|
atom[i++] = net_supporting_wm_check;
|
||||||
atom[i++] = net_showing_desktop;
|
atom[i++] = net_showing_desktop;
|
||||||
#if 0
|
|
||||||
atom[i++] = net_wm_moveresize;
|
atom[i++] = net_wm_moveresize;
|
||||||
#endif
|
|
||||||
atom[i++] = net_wm_desktop;
|
atom[i++] = net_wm_desktop;
|
||||||
#ifdef USE_XINERAMA
|
#ifdef USE_XINERAMA
|
||||||
atom[i++] = net_wm_fullscreen_monitors;
|
atom[i++] = net_wm_fullscreen_monitors;
|
||||||
@@ -1814,6 +1783,84 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent *event)
|
|||||||
}
|
}
|
||||||
return True;
|
return True;
|
||||||
|
|
||||||
|
} else if (event->message_type == net_wm_moveresize) {
|
||||||
|
XEvent fake_event;
|
||||||
|
int direction = event->data.l[2];
|
||||||
|
int x_root = event->data.l[0];
|
||||||
|
int y_root = event->data.l[1];
|
||||||
|
int button = event->data.l[3];
|
||||||
|
int junk;
|
||||||
|
Window junkw;
|
||||||
|
unsigned int mask;
|
||||||
|
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_CANCEL) {
|
||||||
|
if (wwin->moveresize.active) {
|
||||||
|
memset(&fake_event, 0, sizeof(XEvent));
|
||||||
|
fake_event.type = ButtonRelease;
|
||||||
|
fake_event.xbutton.window = wwin->frame->core->window;
|
||||||
|
fake_event.xbutton.x_root = x_root;
|
||||||
|
fake_event.xbutton.y_root = y_root;
|
||||||
|
fake_event.xbutton.button = event->data.l[3];
|
||||||
|
XSendEvent(dpy, wwin->frame->core->window, False, ButtonReleaseMask, &fake_event);
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if already in progress */
|
||||||
|
if (wwin->moveresize.active)
|
||||||
|
return True;
|
||||||
|
|
||||||
|
/* Check if the initiating button is actually pressed */
|
||||||
|
if (!XQueryPointer(dpy, wwin->screen_ptr->root_win, &junkw, &junkw,
|
||||||
|
&junk, &junk, &junk, &junk, &mask))
|
||||||
|
return True;
|
||||||
|
|
||||||
|
if (button > 0) {
|
||||||
|
unsigned int expected =
|
||||||
|
button == 1 ? Button1Mask :
|
||||||
|
button == 2 ? Button2Mask :
|
||||||
|
button == 3 ? Button3Mask :
|
||||||
|
0;
|
||||||
|
|
||||||
|
if (expected && !(mask & expected))
|
||||||
|
/* Race: button already released */
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if operation is allowed */
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_MOVE) {
|
||||||
|
if (WFLAGP(wwin, no_movable))
|
||||||
|
return True;
|
||||||
|
} else if (direction <= _NET_WM_MOVERESIZE_SIZE_LEFT) {
|
||||||
|
if (WFLAGP(wwin, no_resizable))
|
||||||
|
return True;
|
||||||
|
} else {
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grab the pointer for the operation */
|
||||||
|
if (XGrabPointer(dpy, wwin->frame->core->window, False,
|
||||||
|
ButtonReleaseMask | PointerMotionMask | ButtonPressMask,
|
||||||
|
GrabModeAsync, GrabModeAsync,
|
||||||
|
None, None, CurrentTime) != GrabSuccess)
|
||||||
|
return True;
|
||||||
|
|
||||||
|
/* Set up the move/resize state */
|
||||||
|
wwin->moveresize.active = 1;
|
||||||
|
wwin->moveresize.resize_edge = direction;
|
||||||
|
|
||||||
|
memset(&fake_event, 0, sizeof(XEvent));
|
||||||
|
fake_event.type = MotionNotify;
|
||||||
|
fake_event.xmotion.x_root = x_root;
|
||||||
|
fake_event.xmotion.y_root = y_root;
|
||||||
|
fake_event.xmotion.window = wwin->frame->core->window;
|
||||||
|
if (direction == _NET_WM_MOVERESIZE_MOVE)
|
||||||
|
wMouseMoveWindow(wwin, &fake_event);
|
||||||
|
else
|
||||||
|
wMouseResizeWindow(wwin, &fake_event);
|
||||||
|
|
||||||
|
return True;
|
||||||
|
|
||||||
#ifdef USE_XINERAMA
|
#ifdef USE_XINERAMA
|
||||||
} else if (event->message_type == net_wm_fullscreen_monitors) {
|
} else if (event->message_type == net_wm_fullscreen_monitors) {
|
||||||
unsigned long top, bottom, left, right, src_indication;
|
unsigned long top, bottom, left, right, src_indication;
|
||||||
|
|||||||
20
src/wmspec.h
20
src/wmspec.h
@@ -28,6 +28,26 @@
|
|||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These constant provide information on the kind of window move/resize when
|
||||||
|
* it is initiated by the application instead of by WindowMaker. They are
|
||||||
|
* parameter for the client message _NET_WM_MOVERESIZE, as defined by the
|
||||||
|
* FreeDesktop wm-spec standard:
|
||||||
|
* http://standards.freedesktop.org/wm-spec/1.5/ar01s04.html
|
||||||
|
*/
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
|
||||||
|
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
|
||||||
|
#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
|
||||||
|
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
|
||||||
|
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
|
||||||
|
|
||||||
void wNETWMInitStuff(WScreen *scr);
|
void wNETWMInitStuff(WScreen *scr);
|
||||||
void wNETWMCleanup(WScreen *scr);
|
void wNETWMCleanup(WScreen *scr);
|
||||||
void wNETWMUpdateWorkarea(WScreen *scr);
|
void wNETWMUpdateWorkarea(WScreen *scr);
|
||||||
|
|||||||
Reference in New Issue
Block a user