X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=events.c;h=74c3355bb6258e91eec46dc448ffdfca3a7bc3e1;hb=0b68e16fc8f9eb2baf3c1b491f7f6e5e81a6a9a0;hp=828443fe99fcbffe3d3acc7d92fb44062501f8f6;hpb=d5cb36c31fac55457aaad30111e3fd8958c7574d;p=bspwm.git diff --git a/events.c b/events.c index 828443f..74c3355 100644 --- a/events.c +++ b/events.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,7 +8,7 @@ #include "types.h" #include "bspwm.h" #include "settings.h" -#include "utils.h" +#include "misc.h" #include "window.h" #include "events.h" #include "tree.h" @@ -36,10 +37,15 @@ void handle_event(xcb_generic_event_t *evt) property_notify(evt); break; case XCB_BUTTON_PRESS: - PUTS("button press"); + button_press(evt); + break; + case XCB_MOTION_NOTIFY: + motion_notify(evt); + break; + case XCB_BUTTON_RELEASE: + button_release(evt); break; default: - /* PRINTF("received event %i\n", XCB_EVENT_RESPONSE_TYPE(evt)); */ break; } } @@ -61,25 +67,27 @@ void map_request(xcb_generic_event_t *evt) free(wa); client_t *c = make_client(win); - - xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL); - - if (geom) { - c->floating_rectangle = (xcb_rectangle_t) {geom->x, geom->y, geom->width, geom->height}; - free(geom); - } else { - c->floating_rectangle = (xcb_rectangle_t) {0, 0, 320, 240}; - } + update_floating_rectangle(c); bool floating = false, transient = false, fullscreen = false, takes_focus = true; handle_rules(win, &floating, &transient, &fullscreen, &takes_focus); + xcb_icccm_get_wm_class_reply_t reply; + if (xcb_icccm_get_wm_class_reply(dpy, xcb_icccm_get_wm_class(dpy, win), &reply, NULL) == 1) { + strcpy(c->class_name, reply.class_name); + xcb_icccm_get_wm_class_reply_wipe(&reply); + } + if (c->transient) floating = true; node_t *birth = make_node(); birth->client = c; + + if (floating) + split_mode = MODE_MANUAL; + insert_node(desk, birth); if (floating) @@ -103,7 +111,7 @@ void map_request(xcb_generic_event_t *evt) if (takes_focus) xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME); - uint32_t values[] = {XCB_EVENT_MASK_PROPERTY_CHANGE}; + uint32_t values[] = {CLIENT_EVENT_MASK}; xcb_change_window_attributes(dpy, c->window, XCB_CW_EVENT_MASK, values); num_clients++; @@ -168,10 +176,35 @@ void configure_request(xcb_generic_event_t *evt) } xcb_configure_window(dpy, e->window, mask, values); - } + if (is_managed) + window_draw_border(loc.node, (loc.node == loc.desktop->focus)); + } 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 = (xcb_rectangle_t) {0, 0, screen_width, screen_height}; + bw = 0; + } - if (is_managed && is_floating(loc.node->client)) - apply_layout(loc.desktop, loc.node, root_rect); + 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); + } } void destroy_notify(xcb_generic_event_t *evt) @@ -250,6 +283,126 @@ void client_message(xcb_generic_event_t *evt) } } +void button_press(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 %X %u %u\n", win, e->detail, e->state); + + 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.desktop, loc.node, true); + break; + case XCB_BUTTON_INDEX_1: + case XCB_BUTTON_INDEX_3: + if (!is_floating(loc.node->client)) + return; + PUTS("grab pointer from button press"); + 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; + } + } +} + +void motion_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; + + 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 %u\n", win, frozen_pointer->button); + + 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: + 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)); + } +} + +void button_release(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 release %X %u %u\n", win, e->detail, e->state); + + xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); + + window_location_t loc; + if (locate_window(win, &loc)) { + update_floating_rectangle(loc.node->client); + } +} + void handle_state(node_t *n, xcb_atom_t state, unsigned int action) { if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {