From: Michael Stapelberg Date: Tue, 11 Aug 2009 13:02:30 +0000 (+0200) Subject: Bugfix: Fix screen wrapping, cleanup some log messages X-Git-Tag: 3.c~12 X-Git-Url: https://git.sur5r.net/?p=i3%2Fi3;a=commitdiff_plain;h=556f18029012792316ef847f4e24ef61e51daec6 Bugfix: Fix screen wrapping, cleanup some log messages Before this fix, you could go upwards and select the screen which was at the rightmost because it also was the one topmost (if all screen’s top position is equal). --- diff --git a/include/client.h b/include/client.h index 81cb5c6e..9d47edaf 100644 --- a/include/client.h +++ b/include/client.h @@ -97,4 +97,10 @@ void client_unmap(xcb_connection_t *conn, Client *client); */ void client_map(xcb_connection_t *conn, Client *client); +/** + * Pretty-prints the client’s information into the logfile. + * + */ +void client_log(Client *client); + #endif diff --git a/include/xinerama.h b/include/xinerama.h index d4e7bb56..135ab1ab 100644 --- a/include/xinerama.h +++ b/include/xinerama.h @@ -57,6 +57,6 @@ i3Screen *get_screen_containing(int x, int y); * This function always returns a screen. * */ -i3Screen *get_screen_most(direction_t direction); +i3Screen *get_screen_most(direction_t direction, i3Screen *current); #endif diff --git a/src/client.c b/src/client.c index a4269805..12125d8b 100644 --- a/src/client.c +++ b/src/client.c @@ -314,3 +314,11 @@ void client_map(xcb_connection_t *conn, Client *client) { xcb_map_window(conn, client->frame); } + +/* + * Pretty-prints the client’s information into the logfile. + * + */ +void client_log(Client *client) { + LOG("Window: frame 0x%08x, child 0x%08x\n", client->frame, client->child); +} diff --git a/src/commands.c b/src/commands.c index 6472d860..afb16704 100644 --- a/src/commands.c +++ b/src/commands.c @@ -104,12 +104,12 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t LOG("Target screen NULL\n"); /* Wrap around if the target screen is out of bounds */ if (direction == D_RIGHT) - target = get_screen_most(D_LEFT); + target = get_screen_most(D_LEFT, cs); else if (direction == D_LEFT) - target = get_screen_most(D_RIGHT); + target = get_screen_most(D_RIGHT, cs); else if (direction == D_UP) - target = get_screen_most(D_DOWN); - else target = get_screen_most(D_UP); + target = get_screen_most(D_DOWN, cs); + else target = get_screen_most(D_UP, cs); } LOG("Switching to ws %d\n", target->current_workspace + 1); @@ -146,7 +146,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t if ((screen = get_screen_containing(container->x, destination_y)) == NULL) { LOG("Wrapping screen around vertically\n"); /* No screen found? Then wrap */ - screen = get_screen_most((direction == D_UP ? D_DOWN : D_UP)); + screen = get_screen_most((direction == D_UP ? D_DOWN : D_UP), container->workspace->screen); } t_ws = &(workspaces[screen->current_workspace]); new_row = (direction == D_UP ? (t_ws->rows - 1) : 0); @@ -188,7 +188,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t int destination_x = (direction == D_LEFT ? (container->x - 1) : (container->x + container->width + 1)); if ((screen = get_screen_containing(destination_x, container->y)) == NULL) { LOG("Wrapping screen around horizontally\n"); - screen = get_screen_most((direction == D_LEFT ? D_RIGHT : D_LEFT)); + screen = get_screen_most((direction == D_LEFT ? D_RIGHT : D_LEFT), container->workspace->screen); } t_ws = &(workspaces[screen->current_workspace]); new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0); diff --git a/src/handlers.c b/src/handlers.c index 0f450c70..1e10705a 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -248,7 +248,10 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_ * */ int handle_motion_notify(void *ignored, xcb_connection_t *conn, xcb_motion_notify_event_t *event) { - LOG("pointer motion notify, getting screen at %d x %d\n", event->root_x, event->root_y); + /* 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; check_crossing_screen_boundary(event->root_x, event->root_y); @@ -261,20 +264,17 @@ 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) { - LOG("\n\nmapping notify\n\n"); - if (event->request != XCB_MAPPING_KEYBOARD && event->request != XCB_MAPPING_MODIFIER) return 0; + LOG("Received mapping_notify for keyboard or modifier mapping, re-grabbing keys\n"); xcb_refresh_keyboard_mapping(keysyms, event); xcb_get_numlock_mask(conn); ungrab_all_keys(conn); - LOG("Re-grabbing...\n"); grab_all_keys(conn); - LOG("Done\n"); return 0; } @@ -366,8 +366,7 @@ static bool button_press_bar(xcb_connection_t *conn, xcb_button_press_event_t *e } int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) { - LOG("button press!\n"); - LOG("state = %d\n", event->state); + LOG("Button %d pressed\n", event->state); /* This was either a focus for a client’s parent (= titlebar)… */ Client *client = table_get(&by_child, event->event); bool border_click = false; @@ -523,13 +522,11 @@ int handle_map_request(void *prophs, xcb_connection_t *conn, xcb_map_request_eve * */ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure_request_event_t *event) { - LOG("configure-request, serial %d\n", event->sequence); - LOG("event->window = %08x\n", event->window); - LOG("application wants to be at %dx%d with %dx%d\n", event->x, event->y, event->width, event->height); + LOG("window 0x%08x wants to be at %dx%d with %dx%d\n", + event->window, event->x, event->y, event->width, event->height); Client *client = table_get(&by_child, event->window); if (client == NULL) { - LOG("This client is not mapped, so we don't care and just tell the client that he will get its size\n"); uint32_t mask = 0; uint32_t values[7]; int c = 0; @@ -611,8 +608,6 @@ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event) { xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(conn)).data->root; - LOG("handle_configure_event for window %08x\n", event->window); - LOG("event->type = %d, \n", event->response_type); LOG("event->x = %d, ->y = %d, ->width = %d, ->height = %d\n", event->x, event->y, event->width, event->height); /* We ignore this sequence twice because events for child and frame should be ignored */ @@ -723,11 +718,8 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti break; } - if (workspace_empty) { - LOG("setting ws to NULL for workspace %d (%p)\n", client->workspace->num, - client->workspace); + if (workspace_empty) client->workspace->screen = NULL; - } FREE(client->window_class); FREE(client->name); @@ -748,7 +740,6 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti */ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) { - LOG("window's name changed.\n"); if (prop == NULL || xcb_get_property_value_length(prop) == 0) { LOG("_NET_WM_NAME not specified, not changing\n"); return 1; @@ -763,7 +754,7 @@ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state, asprintf(&new_name, "%.*s", xcb_get_property_value_length(prop), (char*)xcb_get_property_value(prop)); /* Convert it to UCS-2 here for not having to convert it later every time we want to pass it to X */ char *ucs2_name = convert_utf8_to_ucs2(new_name, &new_len); - LOG("Name should change to \"%s\"\n", new_name); + LOG("_NET_WM_NAME changed to \"%s\"\n", new_name); free(new_name); /* Check if they are the same and don’t update if so. @@ -773,7 +764,6 @@ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state, if ((new_len == client->name_len) && (client->name != NULL) && (memcmp(client->name, ucs2_name, new_len * 2) == 0)) { - LOG("Name did not change, not updating\n"); free(ucs2_name); return 1; } @@ -810,7 +800,6 @@ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state, */ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) { - LOG("window's name changed (legacy).\n"); if (prop == NULL || xcb_get_property_value_length(prop) == 0) { LOG("prop == NULL\n"); return 1; @@ -819,10 +808,9 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t if (client == NULL) return 1; - if (client->uses_net_wm_name) { - LOG("This client is capable of _NET_WM_NAME, ignoring legacy name\n"); + /* Client capable of _NET_WM_NAME, ignore legacy name changes */ + if (client->uses_net_wm_name) return 1; - } /* Save the old pointer to make the update atomic */ char *new_name; @@ -832,18 +820,17 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t return 1; } /* Convert it to UCS-2 here for not having to convert it later every time we want to pass it to X */ - LOG("Name should change to \"%s\"\n", new_name); + LOG("WM_NAME changed to \"%s\"\n", new_name); /* Check if they are the same and don’t update if so. */ if (client->name != NULL && strlen(new_name) == strlen(client->name) && strcmp(client->name, new_name) == 0) { - LOG("Name did not change, not updating\n"); free(new_name); return 1; } - LOG("Using legacy window title. Note that in order to get Unicode window titles in i3," + LOG("Using legacy window title. Note that in order to get Unicode window titles in i3, " "the application has to set _NET_WM_NAME which is in UTF-8 encoding.\n"); char *old_name = client->name; @@ -871,7 +858,6 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t */ int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) { - LOG("window class changed\n"); if (prop == NULL || xcb_get_property_value_length(prop) == 0) { LOG("prop == NULL\n"); return 1; @@ -886,7 +872,7 @@ int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state, return 1; } - LOG("changed to %s\n", new_class); + LOG("WM_CLASS changed to %s\n", new_class); char *old_class = client->window_class; client->window_class = new_class; FREE(old_class); @@ -935,11 +921,8 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t * return 1; } - LOG("got client %s\n", client->name); - if (client->dock) { - LOG("this is a dock\n"); + if (client->dock) return 1; - } if (client->container == NULL || client->container->mode != MODE_STACK) decorate_window(conn, client, client->frame, client->titlegc, 0); @@ -976,14 +959,10 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t * * */ int handle_client_message(void *data, xcb_connection_t *conn, xcb_client_message_event_t *event) { - LOG("client_message\n"); - if (event->type == atoms[_NET_WM_STATE]) { if (event->format != 32 || event->data.data32[1] != atoms[_NET_WM_STATE_FULLSCREEN]) return 0; - LOG("fullscreen\n"); - Client *client = table_get(&by_child, event->window); if (client == NULL) return 0; @@ -1027,7 +1006,8 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w return 1; } xcb_size_hints_t size_hints; - LOG("client is %08x / child %08x\n", client->frame, client->child); + + client_log(client); /* If the hints were already in this event, use them, if not, request them */ if (reply != NULL) @@ -1056,8 +1036,6 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w return 1; } - LOG("window is %08x / %s\n", client->child, client->name); - int base_width = 0, base_height = 0; /* base_width/height are the desired size of the window. @@ -1112,7 +1090,6 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w */ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *reply) { - LOG("Transient hint!\n"); Client *client = table_get(&by_child, window); if (client == NULL) { LOG("No such client\n"); @@ -1122,16 +1099,12 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_ xcb_window_t transient_for; if (reply != NULL) { - if (!xcb_get_wm_transient_for_from_reply(&transient_for, reply)) { - LOG("Not transient for any window\n"); + if (!xcb_get_wm_transient_for_from_reply(&transient_for, reply)) return 1; - } } else { if (!xcb_get_wm_transient_for_reply(conn, xcb_get_wm_transient_for_unchecked(conn, window), - &transient_for, NULL)) { - LOG("Not transient for any window\n"); + &transient_for, NULL)) return 1; - } } if (client->floating == FLOATING_AUTO_OFF) { @@ -1149,7 +1122,6 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_ */ int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *prop) { - LOG("client leader changed\n"); if (prop == NULL) { prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL); @@ -1163,7 +1135,7 @@ int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state if (leader == NULL) return 1; - LOG("changed to %08x\n", *leader); + LOG("Client leader changed to %08x\n", *leader); client->leader = *leader; diff --git a/src/layout.c b/src/layout.c index d40cf431..d628ef8f 100644 --- a/src/layout.c +++ b/src/layout.c @@ -448,7 +448,6 @@ static void render_bars(xcb_connection_t *conn, Workspace *r_ws, int width, int } static void render_internal_bar(xcb_connection_t *conn, Workspace *r_ws, int width, int height) { - LOG("Rendering internal bar\n"); i3Font *font = load_font(conn, config.font); i3Screen *screen = r_ws->screen; enum { SET_NORMAL = 0, SET_FOCUSED = 1 }; @@ -491,8 +490,6 @@ static void render_internal_bar(xcb_connection_t *conn, Workspace *r_ws, int wid (xcb_char2b_t*)ws->name); drawn += ws->text_width + 12; } - - LOG("done rendering internal\n"); } /* @@ -505,8 +502,6 @@ void ignore_enter_notify_forall(xcb_connection_t *conn, Workspace *workspace, bo Client *client; uint32_t values[1]; - LOG("Ignore enter_notify = %d\n", ignore_enter_notify); - FOR_TABLE(workspace) CIRCLEQ_FOREACH(client, &(workspace->table[cols][rows]->clients), clients) { /* Change event mask for the decorations */ diff --git a/src/xinerama.c b/src/xinerama.c index 3bf988e7..59e7e225 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -92,7 +92,7 @@ i3Screen *get_screen_containing(int x, int y) { * This function always returns a screen. * */ -i3Screen *get_screen_most(direction_t direction) { +i3Screen *get_screen_most(direction_t direction, i3Screen *current) { i3Screen *screen, *candidate = NULL; int position = 0; TAILQ_FOREACH(screen, virtual_screens, screens) { @@ -104,6 +104,14 @@ i3Screen *get_screen_most(direction_t direction) { } \ break; + if (((direction == D_UP) || (direction == D_DOWN)) && + (current->rect.x != screen->rect.x)) + continue; + + if (((direction == D_LEFT) || (direction == D_RIGHT)) && + (current->rect.y != screen->rect.y)) + continue; + switch (direction) { case D_UP: WIN(screen->rect.y, <= position);