diff --git a/src/bspwm.c b/src/bspwm.c index dca03fde..5311760d 100644 --- a/src/bspwm.c +++ b/src/bspwm.c @@ -371,6 +371,7 @@ void setup(void) ewmh->_NET_CLOSE_WINDOW, ewmh->_NET_WM_STRUT_PARTIAL, ewmh->_NET_WM_DESKTOP, + ewmh->_NET_WM_MOVERESIZE, ewmh->_NET_WM_STATE, ewmh->_NET_WM_STATE_HIDDEN, ewmh->_NET_WM_STATE_FULLSCREEN, diff --git a/src/events.c b/src/events.c index 3b82c96f..5504bd3b 100644 --- a/src/events.c +++ b/src/events.c @@ -335,11 +335,59 @@ void client_message(xcb_generic_event_t *evt) if (ewmh_locate_desktop(e->data.data32[0], &dloc)) { transfer_node(loc.monitor, loc.desktop, loc.node, dloc.monitor, dloc.desktop, dloc.desktop->focus, false); } + } else if (e->type == ewmh->_NET_WM_MOVERESIZE) { + if (allow_net_wm_moveresize) { + wm_move_resize_node(e, loc); + } } else if (e->type == ewmh->_NET_CLOSE_WINDOW) { close_node(loc.node); } } +void wm_move_resize_node(xcb_client_message_event_t* e, coordinates_t loc) { + uint32_t direction = e->data.data32[2]; + + switch (direction) { + case XCB_EWMH_WM_MOVERESIZE_MOVE: + wm_move_node(e, loc); + break; + case XCB_EWMH_WM_MOVERESIZE_SIZE_TOPLEFT ... XCB_EWMH_WM_MOVERESIZE_SIZE_LEFT: + wm_resize_node(e, loc); + break; + default: + break; + } +} + +void wm_move_node(xcb_client_message_event_t* e, coordinates_t loc) { + // This logic comes from pointer.c function grab_pointer, + // we have that logic for the pac == ACTION_MOVE branches taken. + + xcb_window_t win = e->window; + xcb_point_t pos; + + query_pointer(&win, &pos); + + xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(dpy, xcb_grab_pointer(dpy, 0, root, XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME), NULL); + + if (reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) { + free(reply); + return; + } + free(reply); + + put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X move begin\n", loc.monitor->id, loc.desktop->id, loc.node->id); + + track_pointer(loc, ACTION_MOVE, pos); + +} + +void wm_resize_node(xcb_client_message_event_t* e, coordinates_t loc) { + // TODO resize window keeping the opposite 1 or 2 edges fixed + // Not sure if this is even possible as most tiling windows do not + // draw decorations with which the user could grab window edges. +} + void focus_in(xcb_generic_event_t *evt) { xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) evt; diff --git a/src/events.h b/src/events.h index f144dcc2..f02a7acd 100644 --- a/src/events.h +++ b/src/events.h @@ -27,6 +27,7 @@ #include #include +#include #define ERROR_CODE_BAD_WINDOW 3 @@ -41,6 +42,9 @@ void destroy_notify(xcb_generic_event_t *evt); void unmap_notify(xcb_generic_event_t *evt); void property_notify(xcb_generic_event_t *evt); void client_message(xcb_generic_event_t *evt); +void wm_move_resize_node(xcb_client_message_event_t* e, coordinates_t loc); +void wm_move_node(xcb_client_message_event_t* e, coordinates_t loc); +void wm_resize_node(xcb_client_message_event_t* e, coordinates_t loc); void focus_in(xcb_generic_event_t *evt); void button_press(xcb_generic_event_t *evt); void enter_notify(xcb_generic_event_t *evt); diff --git a/src/messages.c b/src/messages.c index 9d9f4678..8c98664d 100644 --- a/src/messages.c +++ b/src/messages.c @@ -1711,6 +1711,7 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp) SET_BOOL(center_pseudo_tiled) SET_BOOL(honor_size_hints) SET_BOOL(removal_adjustment) + SET_BOOL(allow_net_wm_moveresize) #undef SET_BOOL #define SET_MON_BOOL(s) \ } else if (streq(#s, name)) { \ @@ -1844,6 +1845,7 @@ void get_setting(coordinates_t loc, char *name, FILE* rsp) GET_BOOL(remove_disabled_monitors) GET_BOOL(remove_unplugged_monitors) GET_BOOL(merge_overlapping_monitors) + GET_BOOL(allow_net_wm_moveresize) #undef GET_BOOL } else { fail(rsp, "config: Unknown setting: '%s'.\n", name); diff --git a/src/settings.c b/src/settings.c index 15f652b6..b9e52b87 100644 --- a/src/settings.c +++ b/src/settings.c @@ -72,6 +72,8 @@ bool remove_disabled_monitors; bool remove_unplugged_monitors; bool merge_overlapping_monitors; +bool allow_net_wm_moveresize; + void run_config(int run_level) { if (fork() == 0) { @@ -133,4 +135,6 @@ void load_settings(void) remove_disabled_monitors = REMOVE_DISABLED_MONITORS; remove_unplugged_monitors = REMOVE_UNPLUGGED_MONITORS; merge_overlapping_monitors = MERGE_OVERLAPPING_MONITORS; + + allow_net_wm_moveresize = ALLOW_NET_WM_MOVERESIZE; } diff --git a/src/settings.h b/src/settings.h index f1cb85e8..13e74c9f 100644 --- a/src/settings.h +++ b/src/settings.h @@ -67,6 +67,8 @@ #define REMOVE_UNPLUGGED_MONITORS false #define MERGE_OVERLAPPING_MONITORS false +#define ALLOW_NET_WM_MOVERESIZE true + extern char external_rules_command[MAXLEN]; extern char status_prefix[MAXLEN]; @@ -111,6 +113,8 @@ extern bool remove_disabled_monitors; extern bool remove_unplugged_monitors; extern bool merge_overlapping_monitors; +extern bool allow_net_wm_moveresize; + void run_config(int run_level); void load_settings(void);