X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=events.c;h=1e8c8292a5da29d9285b55e36ce6e55af79c8848;hb=b0e8dd383e906589113b75fdfcb9ce9d20a863f4;hp=0a424a592d1dd04cb0e1f6e4a77106a306ab08cf;hpb=1ab44c41323dc739bdd71d0ba61ff984a075b8cd;p=bspwm.git diff --git a/events.c b/events.c index 0a424a5..1e8c829 100644 --- a/events.c +++ b/events.c @@ -1,374 +1,390 @@ -#include +/* Copyright (c) 2012, Bastien Dejean + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include -#include -#include -#include -#include -#include "types.h" #include "bspwm.h" +#include "ewmh.h" +#include "monitor.h" +#include "query.h" #include "settings.h" -#include "helpers.h" +#include "tree.h" #include "window.h" #include "events.h" -#include "tree.h" -#include "rules.h" -#include "ewmh.h" void handle_event(xcb_generic_event_t *evt) { - switch (XCB_EVENT_RESPONSE_TYPE(evt)) { - case XCB_MAP_REQUEST: - map_request(evt); - break; - case XCB_DESTROY_NOTIFY: - destroy_notify(evt); - break; - case XCB_UNMAP_NOTIFY: - unmap_notify(evt); - break; - case XCB_CLIENT_MESSAGE: - client_message(evt); - break; - case XCB_CONFIGURE_REQUEST: - configure_request(evt); - break; - case XCB_PROPERTY_NOTIFY: - property_notify(evt); - break; - case XCB_ENTER_NOTIFY: - enter_notify(evt); - break; - case XCB_BUTTON_PRESS: - button_press(evt); - break; - case XCB_MOTION_NOTIFY: - motion_notify(evt); - break; - case XCB_BUTTON_RELEASE: - button_release(); - break; - default: - break; - } + uint8_t resp_type = XCB_EVENT_RESPONSE_TYPE(evt); + switch (resp_type) { + case XCB_MAP_REQUEST: + map_request(evt); + break; + case XCB_DESTROY_NOTIFY: + destroy_notify(evt); + break; + case XCB_UNMAP_NOTIFY: + unmap_notify(evt); + break; + case XCB_CLIENT_MESSAGE: + client_message(evt); + break; + case XCB_CONFIGURE_REQUEST: + configure_request(evt); + break; + case XCB_PROPERTY_NOTIFY: + property_notify(evt); + break; + case XCB_ENTER_NOTIFY: + enter_notify(evt); + break; + case XCB_MOTION_NOTIFY: + motion_notify(evt); + break; + case XCB_FOCUS_IN: + focus_in(evt); + break; + default: + if (randr && resp_type == randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) + update_monitors(); + break; + } } void map_request(xcb_generic_event_t *evt) { - xcb_map_request_event_t *e = (xcb_map_request_event_t *) evt; + xcb_map_request_event_t *e = (xcb_map_request_event_t *) evt; - PRINTF("map request %X\n", e->window); + PRINTF("map request %X\n", e->window); - manage_window(mon, mon->desk, e->window); + schedule_window(e->window); } void configure_request(xcb_generic_event_t *evt) { - xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt; - - PRINTF("configure request %X\n", e->window); - - window_location_t loc; - bool is_managed = locate_window(e->window, &loc); - - if (!is_managed || is_floating(loc.node->client)) { - uint16_t mask = 0; - uint32_t values[7]; - unsigned short i = 0; - - if (e->value_mask & XCB_CONFIG_WINDOW_X) { - mask |= XCB_CONFIG_WINDOW_X; - values[i++] = e->x; - if (is_managed) - loc.node->client->floating_rectangle.x = e->x; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_Y) { - mask |= XCB_CONFIG_WINDOW_Y; - values[i++] = e->y; - if (is_managed) - loc.node->client->floating_rectangle.y = e->y; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { - mask |= XCB_CONFIG_WINDOW_WIDTH; - values[i++] = e->width; - if (is_managed) - loc.node->client->floating_rectangle.width = e->width; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { - mask |= XCB_CONFIG_WINDOW_HEIGHT; - values[i++] = e->height; - if (is_managed) - loc.node->client->floating_rectangle.height = e->height; - } - - if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { - mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH; - values[i++] = e->border_width; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { - mask |= XCB_CONFIG_WINDOW_SIBLING; - values[i++] = e->sibling; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { - mask |= XCB_CONFIG_WINDOW_STACK_MODE; - values[i++] = e->stack_mode; - } - - xcb_configure_window(dpy, e->window, mask, values); - if (is_managed) - window_draw_border(loc.node, loc.node == loc.desktop->focus, loc.monitor == mon); - } else { - xcb_configure_notify_event_t evt; - xcb_rectangle_t rect; - unsigned int bw; - xcb_window_t win = loc.node->client->window; - - if (is_tiled(loc.node->client)) { - rect = loc.node->client->tiled_rectangle; - bw = border_width; - } else { - rect = loc.monitor->rectangle; - bw = 0; - } - - evt.response_type = XCB_CONFIGURE_NOTIFY; - evt.event = win; - evt.window = win; - evt.above_sibling = XCB_NONE; - evt.x = rect.x; - evt.y = rect.y; - evt.width = rect.width; - evt.height = rect.height; - evt.border_width = bw; - evt.override_redirect = false; - - xcb_send_event(dpy, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt); - } + xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt; + + PRINTF("configure request %X\n", e->window); + + coordinates_t loc; + bool is_managed = locate_window(e->window, &loc); + client_t *c = (is_managed ? loc.node->client : NULL); + int w = 0, h = 0; + + if (is_managed && !is_floating(c)) { + if (e->value_mask & XCB_CONFIG_WINDOW_X) + c->floating_rectangle.x = e->x; + if (e->value_mask & XCB_CONFIG_WINDOW_Y) + c->floating_rectangle.y = e->y; + if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) + w = e->width; + if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) + h = e->height; + + if (w != 0) { + restrain_floating_width(c, &w); + c->floating_rectangle.width = w; + } + + if (h != 0) { + restrain_floating_height(c, &h); + c->floating_rectangle.height = h; + } + + xcb_configure_notify_event_t evt; + xcb_rectangle_t rect; + xcb_window_t win = c->window; + unsigned int bw = c->border_width; + + if (c->fullscreen) + rect = loc.monitor->rectangle; + else + rect = c->tiled_rectangle; + + evt.response_type = XCB_CONFIGURE_NOTIFY; + evt.event = win; + evt.window = win; + evt.above_sibling = XCB_NONE; + evt.x = rect.x; + evt.y = rect.y; + evt.width = rect.width; + evt.height = rect.height; + evt.border_width = bw; + evt.override_redirect = false; + + xcb_send_event(dpy, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt); + + if (c->pseudo_tiled) + arrange(loc.monitor, loc.desktop); + } else { + uint16_t mask = 0; + uint32_t values[7]; + unsigned short i = 0; + + if (e->value_mask & XCB_CONFIG_WINDOW_X) { + mask |= XCB_CONFIG_WINDOW_X; + values[i++] = e->x; + if (is_managed) + c->floating_rectangle.x = e->x; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_Y) { + mask |= XCB_CONFIG_WINDOW_Y; + values[i++] = e->y; + if (is_managed) + c->floating_rectangle.y = e->y; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { + mask |= XCB_CONFIG_WINDOW_WIDTH; + w = e->width; + if (is_managed) { + restrain_floating_width(c, &w); + c->floating_rectangle.width = w; + } + values[i++] = w; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { + mask |= XCB_CONFIG_WINDOW_HEIGHT; + h = e->height; + if (is_managed) { + restrain_floating_height(c, &h); + c->floating_rectangle.height = h; + } + values[i++] = h; + } + + if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { + mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH; + values[i++] = e->border_width; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { + mask |= XCB_CONFIG_WINDOW_SIBLING; + values[i++] = e->sibling; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { + mask |= XCB_CONFIG_WINDOW_STACK_MODE; + values[i++] = e->stack_mode; + } + + xcb_configure_window(dpy, e->window, mask, values); + } + + if (is_managed) + translate_client(monitor_from_client(c), loc.monitor, c); } void destroy_notify(xcb_generic_event_t *evt) { - xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *) evt; + xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *) evt; - PRINTF("destroy notify %X\n", e->window); + PRINTF("destroy notify %X\n", e->window); - window_location_t loc; - if (locate_window(e->window, &loc)) { - remove_node(loc.desktop, loc.node); - arrange(loc.monitor, loc.desktop); - } + unmanage_window(e->window); } void unmap_notify(xcb_generic_event_t *evt) { - xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *) evt; + xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *) evt; - PRINTF("unmap notify %X\n", e->window); + PRINTF("unmap notify %X\n", e->window); - window_location_t loc; - if (locate_window(e->window, &loc)) { - remove_node(loc.desktop, loc.node); - arrange(loc.monitor, loc.desktop); - } + unmanage_window(e->window); } void property_notify(xcb_generic_event_t *evt) { - xcb_property_notify_event_t *e = (xcb_property_notify_event_t *) evt; - xcb_icccm_wm_hints_t hints; - - /* PRINTF("property notify %X\n", e->window); */ - - if (e->atom != XCB_ATOM_WM_HINTS) - return; - - window_location_t loc; - if (locate_window(e->window, &loc)) { - if (loc.node == loc.desktop->focus) - return; - if (xcb_icccm_get_wm_hints_reply(dpy, xcb_icccm_get_wm_hints(dpy, e->window), &hints, NULL) == 1) { - loc.node->client->urgent = (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY); - if (loc.monitor->desk == loc.desktop) - arrange(loc.monitor, loc.desktop); - } - } -} - -void enter_notify(xcb_generic_event_t *evt) -{ - xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt; - - PRINTF("enter notify %X %d %d\n", e->event, e->mode, e->detail); - - if (!focus_follows_mouse - || (e->mode != XCB_NOTIFY_MODE_NORMAL && e->detail == XCB_NOTIFY_DETAIL_INFERIOR) - || (pointer_position.x == e->root_x && pointer_position.y == e->root_y)) - return; - - window_location_t loc; - if (locate_window(e->event, &loc)) { - select_monitor(loc.monitor); - focus_node(loc.monitor, loc.desktop, loc.node, true); - pointer_position = (xcb_point_t) {e->root_x, e->root_y}; - } + xcb_property_notify_event_t *e = (xcb_property_notify_event_t *) evt; + + /* PRINTF("property notify %X\n", e->window); */ + + if (e->atom != XCB_ATOM_WM_HINTS && e->atom != XCB_ATOM_WM_NORMAL_HINTS) + return; + + coordinates_t loc; + if (!locate_window(e->window, &loc)) + return; + + if (e->atom == XCB_ATOM_WM_HINTS) { + xcb_icccm_wm_hints_t hints; + if (xcb_icccm_get_wm_hints_reply(dpy, xcb_icccm_get_wm_hints(dpy, e->window), &hints, NULL) == 1 && + (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY)) + set_urgency(loc.monitor, loc.desktop, loc.node, xcb_icccm_wm_hints_get_urgency(&hints)); + } else if (e->atom == XCB_ATOM_WM_NORMAL_HINTS) { + client_t *c = loc.node->client; + xcb_size_hints_t size_hints; + if (xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, e->window), &size_hints, NULL) == 1 && + (size_hints.flags & (XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_P_MAX_SIZE))) { + c->min_width = size_hints.min_width; + c->max_width = size_hints.max_width; + c->min_height = size_hints.min_height; + c->max_height = size_hints.max_height; + int w = c->floating_rectangle.width; + int h = c->floating_rectangle.height; + restrain_floating_size(c, &w, &h); + c->floating_rectangle.width = w; + c->floating_rectangle.height = h; + arrange(loc.monitor, loc.desktop); + } + } } void client_message(xcb_generic_event_t *evt) { - xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt; - - PRINTF("client message %X\n", e->window); - - window_location_t loc; - - if (!locate_window(e->window, &loc)) - return; - - if (e->type == ewmh->_NET_WM_STATE) { - handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[1], e->data.data32[0]); - handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[2], e->data.data32[0]); - } else if (e->type == ewmh->_NET_ACTIVE_WINDOW) { - if (loc.desktop->focus->client->fullscreen && loc.desktop->focus != loc.node) - toggle_fullscreen(loc.monitor, loc.desktop->focus->client); - select_monitor(loc.monitor); - select_desktop(loc.desktop); - focus_node(loc.monitor, loc.desktop, loc.node, true); - arrange(loc.monitor, loc.desktop); - } + xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt; + + PRINTF("client message %X %u\n", e->window, e->type); + + if (e->type == ewmh->_NET_CURRENT_DESKTOP) { + coordinates_t loc; + if (ewmh_locate_desktop(e->data.data32[0], &loc)) + focus_node(loc.monitor, loc.desktop, loc.desktop->focus); + return; + } + + coordinates_t loc; + if (!locate_window(e->window, &loc)) + return; + + if (e->type == ewmh->_NET_WM_STATE) { + handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[1], e->data.data32[0]); + handle_state(loc.monitor, loc.desktop, loc.node, e->data.data32[2], e->data.data32[0]); + } else if (e->type == ewmh->_NET_ACTIVE_WINDOW) { + if ((ignore_ewmh_focus && e->data.data32[0] == XCB_EWMH_CLIENT_SOURCE_TYPE_NORMAL) || + loc.node == mon->desk->focus) + return; + if (loc.desktop->focus->client->fullscreen && loc.desktop->focus != loc.node) { + set_fullscreen(loc.desktop->focus, false); + arrange(loc.monitor, loc.desktop); + } + focus_node(loc.monitor, loc.desktop, loc.node); + } else if (e->type == ewmh->_NET_WM_DESKTOP) { + coordinates_t dloc; + if (ewmh_locate_desktop(e->data.data32[0], &dloc)) + transfer_node(loc.monitor, loc.desktop, loc.node, dloc.monitor, dloc.desktop, dloc.desktop->focus); + } else if (e->type == ewmh->_NET_CLOSE_WINDOW) { + window_close(loc.node); + } } -void button_press(xcb_generic_event_t *evt) +void focus_in(xcb_generic_event_t *evt) { - xcb_button_press_event_t *e = (xcb_button_press_event_t *) evt; - xcb_window_t win = e->child; - - PRINTF("button press %u %X\n", e->detail, win); - - window_location_t loc; - if (locate_window(win, &loc)) { - client_t *c = loc.node->client; - switch (e->detail) { - case XCB_BUTTON_INDEX_2: - focus_node(loc.monitor, loc.desktop, loc.node, true); - break; - case XCB_BUTTON_INDEX_1: - case XCB_BUTTON_INDEX_3: - if (is_tiled(loc.node->client)) { - loc.node->client->floating_rectangle = loc.node->client->tiled_rectangle; - toggle_floating(loc.node); - arrange(loc.monitor, loc.desktop); - } else if (loc.node->client->fullscreen) { - return; - } - frozen_pointer->desktop = loc.desktop; - frozen_pointer->node = loc.node; - frozen_pointer->rectangle = c->floating_rectangle; - frozen_pointer->position = (xcb_point_t) {e->root_x, e->root_y}; - frozen_pointer->button = e->detail; - if (e->detail == XCB_BUTTON_INDEX_3) { - int16_t mid_x, mid_y; - mid_x = c->floating_rectangle.x + (c->floating_rectangle.width / 2); - mid_y = c->floating_rectangle.y + (c->floating_rectangle.height / 2); - if (e->root_x > mid_x) { - if (e->root_y > mid_y) - frozen_pointer->corner = BOTTOM_RIGHT; - else - frozen_pointer->corner = TOP_RIGHT; - } else { - if (e->root_y > mid_y) - frozen_pointer->corner = BOTTOM_LEFT; - else - frozen_pointer->corner = TOP_LEFT; - } - } - xcb_grab_pointer(dpy, false, screen->root, XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME); - break; - } - } + xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) evt; + + /* PRINTF("focus in %X %d %d\n", e->event, e->mode, e->detail); */ + + if (e->mode == XCB_NOTIFY_MODE_GRAB || + e->mode == XCB_NOTIFY_MODE_UNGRAB) + return; + /* prevent focus stealing */ + if ((e->detail == XCB_NOTIFY_DETAIL_ANCESTOR || + e->detail == XCB_NOTIFY_DETAIL_INFERIOR || + e->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL || + e->detail == XCB_NOTIFY_DETAIL_NONLINEAR) && + (mon->desk->focus == NULL || + mon->desk->focus->client->window != e->event)) + update_input_focus(); } -void motion_notify(xcb_generic_event_t *evt) +void enter_notify(xcb_generic_event_t *evt) { - xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt; - - int16_t delta_x, delta_y, x, y, w, h; - uint16_t width, height; - - monitor_t *m = frozen_pointer->monitor; - desktop_t *d = frozen_pointer->desktop; - node_t *n = frozen_pointer->node; - client_t *c = n->client; - xcb_rectangle_t rect = frozen_pointer->rectangle; - xcb_window_t win = c->window; - - /* PRINTF("motion notify %X\n", win); */ - - delta_x = e->root_x - frozen_pointer->position.x; - delta_y = e->root_y - frozen_pointer->position.y; - - switch (frozen_pointer->button) { - case XCB_BUTTON_INDEX_1: - x = rect.x + delta_x; - y = rect.y + delta_y; - window_move(win, x, y); - break; - case XCB_BUTTON_INDEX_3: - switch (frozen_pointer->corner) { - case TOP_LEFT: - x = rect.x + delta_x; - y = rect.y + delta_y; - w = rect.width - delta_x; - h = rect.height - delta_y; - break; - case TOP_RIGHT: - x = rect.x; - y = rect.y + delta_y; - w = rect.width + delta_x; - h = rect.height - delta_y; - break; - case BOTTOM_LEFT: - x = rect.x + delta_x; - y = rect.y; - w = rect.width - delta_x; - h = rect.height + delta_y; - break; - case BOTTOM_RIGHT: - default: - x = rect.x; - y = rect.y; - w = rect.width + delta_x; - h = rect.height + delta_y; - break; - } - width = MAX(1, w); - height = MAX(1, h); - window_move_resize(win, x, y, width, height); - c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height}; - window_draw_border(n, d->focus == n, mon == m); - } + xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt; + xcb_window_t win = e->event; + + PRINTF("enter notify %X %d %d\n", win, e->mode, e->detail); + + if (e->mode != XCB_NOTIFY_MODE_NORMAL || + (mon->desk->focus != NULL && + mon->desk->focus->client->window == win)) + return; + + enable_motion_recorder(); } -void button_release(void) +void motion_notify(xcb_generic_event_t *evt) { - PUTS("button release"); - - xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); - update_floating_rectangle(frozen_pointer->node->client); + PUTS("motion notify"); + + xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt; + + int dtime = e->time - last_motion_time; + if (dtime > 1000) { + last_motion_time = e->time; + last_motion_x = e->event_x; + last_motion_y = e->event_y; + return; + } + + int mdist = abs(e->event_x - last_motion_x) + abs(e->event_y - last_motion_y); + if (mdist < 10) + return; + + disable_motion_recorder(); + + xcb_window_t win = XCB_NONE; + xcb_point_t pt = {e->root_x, e->root_y}; + query_pointer(&win, NULL); + + bool pfm_backup = pointer_follows_monitor; + bool pff_backup = pointer_follows_focus; + auto_raise = false; + pointer_follows_monitor = false; + pointer_follows_focus = false; + if (!window_focus(win)) { + monitor_t *m = monitor_from_point(pt); + if (m != NULL && m != mon) + focus_node(m, m->desk, m->desk->focus); + } + pointer_follows_monitor = pfm_backup; + pointer_follows_focus = pff_backup; + auto_raise = true; } void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action) { - if (state == ewmh->_NET_WM_STATE_FULLSCREEN) { - bool fs = n->client->fullscreen; - if (action == XCB_EWMH_WM_STATE_TOGGLE - || (fs && action == XCB_EWMH_WM_STATE_REMOVE) - || (!fs && action == XCB_EWMH_WM_STATE_ADD)) { - toggle_fullscreen(m, n->client); - arrange(m, d); - } - } + if (state == ewmh->_NET_WM_STATE_FULLSCREEN) { + if (action == XCB_EWMH_WM_STATE_ADD) + set_fullscreen(n, true); + else if (action == XCB_EWMH_WM_STATE_REMOVE) + set_fullscreen(n, false); + else if (action == XCB_EWMH_WM_STATE_TOGGLE) + set_fullscreen(n, !n->client->fullscreen); + arrange(m, d); + } else if (state == ewmh->_NET_WM_STATE_STICKY) { + if (action == XCB_EWMH_WM_STATE_ADD) + set_sticky(m, d, n, true); + else if (action == XCB_EWMH_WM_STATE_REMOVE) + set_sticky(m, d, n, false); + else if (action == XCB_EWMH_WM_STATE_TOGGLE) + set_sticky(m, d, n, !n->client->sticky); + } else if (state == ewmh->_NET_WM_STATE_DEMANDS_ATTENTION) { + if (action == XCB_EWMH_WM_STATE_ADD) + set_urgency(m, d, n, true); + else if (action == XCB_EWMH_WM_STATE_REMOVE) + set_urgency(m, d, n, false); + else if (action == XCB_EWMH_WM_STATE_TOGGLE) + set_urgency(m, d, n, !n->client->urgent); + } }