X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fhandlers.c;h=6e6626a9671f275f7a51141b42857fabfb8ced75;hb=2f992f5c0ed75452a61b19d6c118e5f5f3ba67e9;hp=03fd802c5046f072263989f825686175afc6b0c4;hpb=6fe0e58a6421bfcdea797fc3aed208cb4f0bc9da;p=i3%2Fi3 diff --git a/src/handlers.c b/src/handlers.c index 03fd802c..6e6626a9 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -28,30 +28,6 @@ void add_ignore_event(const int sequence) { SLIST_INSERT_HEAD(&ignore_events, event, ignore_events); } -/* - * Unignores the given sequence. Called when unmap events (generated by - * reparenting) should be ignored and the unmap event actually happens, in - * order to not ignore too many unmap events (leading to ghost window - * decorations). - * - */ -static void unignore_event(const int sequence) { - struct Ignore_Event *event; - for (event = SLIST_FIRST(&ignore_events); - event != SLIST_END(&ignore_events); - event = SLIST_NEXT(event, ignore_events)) { - if (event->sequence != sequence) - continue; - - DLOG("Unignoring sequence number %d\n", sequence); - struct Ignore_Event *save = event; - event = SLIST_NEXT(event, ignore_events); - SLIST_REMOVE(&ignore_events, save, Ignore_Event, ignore_events); - free(save); - break; - } -} - /* * Checks if the given sequence is ignored and returns true if so. * @@ -126,8 +102,6 @@ int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_ return 1; } -#if 0 - /* * Called with coordinates of an enter_notify event or motion_notify event * to check if the user crossed virtual screen boundaries and adjust the @@ -135,41 +109,30 @@ int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_ * */ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) { - Output *output; + Output *output; - if ((output = get_output_containing(x, y)) == NULL) { - ELOG("ERROR: No such screen\n"); - return; - } - if (output == c_ws->output) - return; - - c_ws->current_row = current_row; - c_ws->current_col = current_col; - c_ws = output->current_workspace; - current_row = c_ws->current_row; - current_col = c_ws->current_col; - DLOG("We're now on output %p\n", output); - - /* While usually this function is only called when the user switches - * to a different output using his mouse (and thus the output is - * empty), it may be that the following race condition occurs: - * 1) the user actives a new output (say VGA1). - * 2) the cursor is sent to the first pixel of the new VGA1, thus - * generating an enter_notify for the screen (the enter_notify - * is not yet received by i3). - * 3) i3 requeries screen configuration and maps a workspace onto the - * new output. - * 4) the enter_notify event arrives and c_ws is set to the new - * workspace but the existing windows on the new workspace are not - * focused. - * - * Therefore, we re-set the focus here to be sure it’s correct. */ - Client *first_client = SLIST_FIRST(&(c_ws->focus_stack)); - if (first_client != NULL) - set_focus(global_conn, first_client, true); + /* If the user disable focus follows mouse, we have nothing to do here */ + if (config.disable_focus_follows_mouse) + return; + + if ((output = get_output_containing(x, y)) == NULL) { + ELOG("ERROR: No such screen\n"); + return; + } + + if (output->con == NULL) { + ELOG("ERROR: The screen is not recognized by i3 (no container associated)\n"); + return; + } + + /* Focus the output on which the user moved his cursor */ + Con *old_focused = focused; + con_focus(con_descend_focused(output_get_content(output->con))); + + /* If the focus changed, we re-render to get updated decorations */ + if (old_focused != focused) + tree_render(); } -#endif /* * When the user moves the mouse pointer onto a window, this callback gets called. @@ -201,7 +164,12 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */ if (con == NULL) { DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y); - //check_crossing_screen_boundary(event->root_x, event->root_y); + check_crossing_screen_boundary(event->root_x, event->root_y); + return 1; + } + + if (con->parent->type == CT_DOCKAREA) { + DLOG("Ignoring, this is a dock client\n"); return 1; } @@ -234,16 +202,12 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, if (config.disable_focus_follows_mouse) return 1; - Con *next = con; - while (!TAILQ_EMPTY(&(next->focus_head))) - next = TAILQ_FIRST(&(next->focus_head)); - con_focus(next); - x_push_changes(croot); + con_focus(con_descend_focused(con)); + tree_render(); return 1; } -#if 0 /* * When the user moves the mouse but does not change the active window @@ -252,14 +216,39 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, * */ int handle_motion_notify(void *ignored, xcb_connection_t *conn, xcb_motion_notify_event_t *event) { - /* Skip events where the pointer was over a child window, we are only - * interested in events on the root window. */ - if (event->child != 0) - return 1; + /* Skip events where the pointer was over a child window, we are only + * interested in events on the root window. */ + if (event->child != 0) + return 1; + Con *con; + if ((con = con_by_frame_id(event->event)) == NULL) { check_crossing_screen_boundary(event->root_x, event->root_y); + return 1; + } + + if (config.disable_focus_follows_mouse) + return 1; + if (con->layout != L_DEFAULT) return 1; + + /* see over which rect the user is */ + Con *current; + TAILQ_FOREACH(current, &(con->nodes_head), nodes) { + if (!rect_contains(current->deco_rect, event->event_x, event->event_y)) + continue; + + /* We found the rect, let’s see if this window is focused */ + if (TAILQ_FIRST(&(con->focus_head)) == current) + return 1; + + con_focus(current); + x_push_changes(croot); + return 1; + } + + return 1; } /* @@ -268,23 +257,22 @@ int handle_motion_notify(void *ignored, xcb_connection_t *conn, xcb_motion_notif * */ int handle_mapping_notify(void *ignored, xcb_connection_t *conn, xcb_mapping_notify_event_t *event) { - if (event->request != XCB_MAPPING_KEYBOARD && - event->request != XCB_MAPPING_MODIFIER) - return 0; + if (event->request != XCB_MAPPING_KEYBOARD && + event->request != XCB_MAPPING_MODIFIER) + return 0; - DLOG("Received mapping_notify for keyboard or modifier mapping, re-grabbing keys\n"); - xcb_refresh_keyboard_mapping(keysyms, event); + DLOG("Received mapping_notify for keyboard or modifier mapping, re-grabbing keys\n"); + xcb_refresh_keyboard_mapping(keysyms, event); - xcb_get_numlock_mask(conn); + xcb_get_numlock_mask(conn); - ungrab_all_keys(conn); - translate_keysyms(); - grab_all_keys(conn, false); + ungrab_all_keys(conn); + translate_keysyms(); + grab_all_keys(conn, false); - return 0; + return 0; } -#endif /* * A new window appeared on the screen (=was mapped), so let’s manage it. * @@ -346,13 +334,14 @@ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure DLOG("Configure request!\n"); if (con_is_floating(con) && con_is_leaf(con)) { /* find the height for the decorations */ - i3Font *font = load_font(conn, config.font); - int deco_height = font->height + 5; + int deco_height = config.font.height + 5; /* we actually need to apply the size/position changes to the *parent* * container */ Rect bsr = con_border_style_rect(con); - if (con->border_style == BS_NORMAL) + if (con->border_style == BS_NORMAL) { + bsr.y += deco_height; bsr.height -= deco_height; + } con = con->parent; DLOG("Container is a floating leaf node, will do that.\n"); if (event->value_mask & XCB_CONFIG_WINDOW_X) { @@ -374,6 +363,8 @@ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure tree_render(); } + fake_absolute_configure_notify(con); + return 1; #if 0 /* Dock clients can be reconfigured in their height */ @@ -422,6 +413,7 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n return 1; } +#endif /* * Gets triggered upon a RandR screen change event, that is when the user @@ -430,15 +422,14 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n */ int handle_screen_change(void *prophs, xcb_connection_t *conn, xcb_generic_event_t *e) { - DLOG("RandR screen change\n"); + DLOG("RandR screen change\n"); - randr_query_outputs(conn); + randr_query_outputs(); - ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}"); + ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}"); - return 1; + return 1; } -#endif /* * Our window decorations were unmapped. That means, the window will be killed @@ -613,7 +604,7 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t * x_draw_decoration(parent); TAILQ_FOREACH(con, &(parent->nodes_head), nodes) { - LOG("expose for con %p / %s\n", con, con->name); + DLOG("expose for con %p / %s\n", con, con->name); if (con->window) x_draw_decoration(con); } @@ -621,49 +612,13 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t * /* We also need to render the decorations of other Cons nearby the Con * itself to not get overlapping decorations */ TAILQ_FOREACH(con, &(parent->parent->nodes_head), nodes) { - LOG("expose for con %p / %s\n", con, con->name); + DLOG("expose for con %p / %s\n", con, con->name); if (con->window) x_draw_decoration(con); } xcb_flush(conn); return 1; - -#if 0 - else { - uint32_t background_color; - if (client->urgent) - background_color = config.client.urgent.background; - /* Distinguish if the window is currently focused… */ - else if (CUR_CELL != NULL && CUR_CELL->currently_focused == client) - background_color = config.client.focused.background; - /* …or if it is the focused window in a not focused container */ - else background_color = config.client.focused_inactive.background; - - /* Set foreground color to current focused color, line width to 2 */ - uint32_t values[] = {background_color, 2}; - xcb_change_gc(conn, client->titlegc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values); - - /* Draw the border, the ±1 is for line width = 2 */ - xcb_point_t points[] = {{1, 0}, /* left upper edge */ - {1, client->rect.height-1}, /* left bottom edge */ - {client->rect.width-1, client->rect.height-1}, /* right bottom edge */ - {client->rect.width-1, 0}}; /* right upper edge */ - xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, client->frame, client->titlegc, 4, points); - - /* Draw a black background */ - xcb_change_gc_single(conn, client->titlegc, XCB_GC_FOREGROUND, get_colorpixel(conn, "#000000")); - if (client->titlebar_position == TITLEBAR_OFF && !client->borderless) { - xcb_rectangle_t crect = {1, 0, client->rect.width - (1 + 1), client->rect.height - 1}; - xcb_poly_fill_rectangle(conn, client->frame, client->titlegc, 1, &crect); - } else { - xcb_rectangle_t crect = {2, 0, client->rect.width - (2 + 2), client->rect.height - 2}; - xcb_poly_fill_rectangle(conn, client->frame, client->titlegc, 1, &crect); - } - } - xcb_flush(conn); - return 1; -#endif } /* @@ -784,7 +739,6 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w con->base_height = base_height; DLOG("client's base_height changed to %d\n", base_height); DLOG("client's base_width changed to %d\n", base_width); - changed = true; } /* If no aspect ratio was set or if it was invalid, we ignore the hints */