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).
This commit is contained in:
Michael Stapelberg 2009-08-11 15:02:30 +02:00
parent dd134a74ef
commit 556f180290
7 changed files with 51 additions and 62 deletions

View File

@ -97,4 +97,10 @@ void client_unmap(xcb_connection_t *conn, Client *client);
*/ */
void client_map(xcb_connection_t *conn, Client *client); void client_map(xcb_connection_t *conn, Client *client);
/**
* Pretty-prints the clients information into the logfile.
*
*/
void client_log(Client *client);
#endif #endif

View File

@ -57,6 +57,6 @@ i3Screen *get_screen_containing(int x, int y);
* This function always returns a screen. * This function always returns a screen.
* *
*/ */
i3Screen *get_screen_most(direction_t direction); i3Screen *get_screen_most(direction_t direction, i3Screen *current);
#endif #endif

View File

@ -314,3 +314,11 @@ void client_map(xcb_connection_t *conn, Client *client) {
xcb_map_window(conn, client->frame); xcb_map_window(conn, client->frame);
} }
/*
* Pretty-prints the clients information into the logfile.
*
*/
void client_log(Client *client) {
LOG("Window: frame 0x%08x, child 0x%08x\n", client->frame, client->child);
}

View File

@ -104,12 +104,12 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
LOG("Target screen NULL\n"); LOG("Target screen NULL\n");
/* Wrap around if the target screen is out of bounds */ /* Wrap around if the target screen is out of bounds */
if (direction == D_RIGHT) if (direction == D_RIGHT)
target = get_screen_most(D_LEFT); target = get_screen_most(D_LEFT, cs);
else if (direction == D_LEFT) else if (direction == D_LEFT)
target = get_screen_most(D_RIGHT); target = get_screen_most(D_RIGHT, cs);
else if (direction == D_UP) else if (direction == D_UP)
target = get_screen_most(D_DOWN); target = get_screen_most(D_DOWN, cs);
else target = get_screen_most(D_UP); else target = get_screen_most(D_UP, cs);
} }
LOG("Switching to ws %d\n", target->current_workspace + 1); 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) { if ((screen = get_screen_containing(container->x, destination_y)) == NULL) {
LOG("Wrapping screen around vertically\n"); LOG("Wrapping screen around vertically\n");
/* No screen found? Then wrap */ /* 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]); t_ws = &(workspaces[screen->current_workspace]);
new_row = (direction == D_UP ? (t_ws->rows - 1) : 0); 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)); int destination_x = (direction == D_LEFT ? (container->x - 1) : (container->x + container->width + 1));
if ((screen = get_screen_containing(destination_x, container->y)) == NULL) { if ((screen = get_screen_containing(destination_x, container->y)) == NULL) {
LOG("Wrapping screen around horizontally\n"); 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]); t_ws = &(workspaces[screen->current_workspace]);
new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0); new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0);

View File

@ -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) { 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); 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) { 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 && if (event->request != XCB_MAPPING_KEYBOARD &&
event->request != XCB_MAPPING_MODIFIER) event->request != XCB_MAPPING_MODIFIER)
return 0; return 0;
LOG("Received mapping_notify for keyboard or modifier mapping, re-grabbing keys\n");
xcb_refresh_keyboard_mapping(keysyms, event); xcb_refresh_keyboard_mapping(keysyms, event);
xcb_get_numlock_mask(conn); xcb_get_numlock_mask(conn);
ungrab_all_keys(conn); ungrab_all_keys(conn);
LOG("Re-grabbing...\n");
grab_all_keys(conn); grab_all_keys(conn);
LOG("Done\n");
return 0; 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) { int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
LOG("button press!\n"); LOG("Button %d pressed\n", event->state);
LOG("state = %d\n", event->state);
/* This was either a focus for a clients parent (= titlebar)… */ /* This was either a focus for a clients parent (= titlebar)… */
Client *client = table_get(&by_child, event->event); Client *client = table_get(&by_child, event->event);
bool border_click = false; 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) { 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("window 0x%08x wants to be at %dx%d with %dx%d\n",
LOG("event->window = %08x\n", event->window); event->window, event->x, event->y, event->width, event->height);
LOG("application wants to be at %dx%d with %dx%d\n", event->x, event->y, event->width, event->height);
Client *client = table_get(&by_child, event->window); Client *client = table_get(&by_child, event->window);
if (client == NULL) { 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 mask = 0;
uint32_t values[7]; uint32_t values[7];
int c = 0; 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) { 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; 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); 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 */ /* 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; break;
} }
if (workspace_empty) { if (workspace_empty)
LOG("setting ws to NULL for workspace %d (%p)\n", client->workspace->num,
client->workspace);
client->workspace->screen = NULL; client->workspace->screen = NULL;
}
FREE(client->window_class); FREE(client->window_class);
FREE(client->name); 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, 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) { 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) { if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
LOG("_NET_WM_NAME not specified, not changing\n"); LOG("_NET_WM_NAME not specified, not changing\n");
return 1; 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)); 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 */ /* 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); 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); free(new_name);
/* Check if they are the same and dont update if so. /* Check if they are the same and dont 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) && if ((new_len == client->name_len) &&
(client->name != NULL) && (client->name != NULL) &&
(memcmp(client->name, ucs2_name, new_len * 2) == 0)) { (memcmp(client->name, ucs2_name, new_len * 2) == 0)) {
LOG("Name did not change, not updating\n");
free(ucs2_name); free(ucs2_name);
return 1; 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, 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) { 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) { if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
LOG("prop == NULL\n"); LOG("prop == NULL\n");
return 1; return 1;
@ -819,10 +808,9 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t
if (client == NULL) if (client == NULL)
return 1; return 1;
if (client->uses_net_wm_name) { /* Client capable of _NET_WM_NAME, ignore legacy name changes */
LOG("This client is capable of _NET_WM_NAME, ignoring legacy name\n"); if (client->uses_net_wm_name)
return 1; return 1;
}
/* Save the old pointer to make the update atomic */ /* Save the old pointer to make the update atomic */
char *new_name; char *new_name;
@ -832,18 +820,17 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t
return 1; return 1;
} }
/* Convert it to UCS-2 here for not having to convert it later every time we want to pass it to X */ /* 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 dont update if so. */ /* Check if they are the same and dont update if so. */
if (client->name != NULL && if (client->name != NULL &&
strlen(new_name) == strlen(client->name) && strlen(new_name) == strlen(client->name) &&
strcmp(client->name, new_name) == 0) { strcmp(client->name, new_name) == 0) {
LOG("Name did not change, not updating\n");
free(new_name); free(new_name);
return 1; 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"); "the application has to set _NET_WM_NAME which is in UTF-8 encoding.\n");
char *old_name = client->name; 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, 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) { 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) { if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
LOG("prop == NULL\n"); LOG("prop == NULL\n");
return 1; return 1;
@ -886,7 +872,7 @@ int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state,
return 1; return 1;
} }
LOG("changed to %s\n", new_class); LOG("WM_CLASS changed to %s\n", new_class);
char *old_class = client->window_class; char *old_class = client->window_class;
client->window_class = new_class; client->window_class = new_class;
FREE(old_class); FREE(old_class);
@ -935,11 +921,8 @@ int handle_expose_event(void *data, xcb_connection_t *conn, xcb_expose_event_t *
return 1; return 1;
} }
LOG("got client %s\n", client->name); if (client->dock)
if (client->dock) {
LOG("this is a dock\n");
return 1; return 1;
}
if (client->container == NULL || client->container->mode != MODE_STACK) if (client->container == NULL || client->container->mode != MODE_STACK)
decorate_window(conn, client, client->frame, client->titlegc, 0); 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) { 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->type == atoms[_NET_WM_STATE]) {
if (event->format != 32 || event->data.data32[1] != atoms[_NET_WM_STATE_FULLSCREEN]) if (event->format != 32 || event->data.data32[1] != atoms[_NET_WM_STATE_FULLSCREEN])
return 0; return 0;
LOG("fullscreen\n");
Client *client = table_get(&by_child, event->window); Client *client = table_get(&by_child, event->window);
if (client == NULL) if (client == NULL)
return 0; return 0;
@ -1027,7 +1006,8 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
return 1; return 1;
} }
xcb_size_hints_t size_hints; 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 the hints were already in this event, use them, if not, request them */
if (reply != NULL) if (reply != NULL)
@ -1056,8 +1036,6 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
return 1; return 1;
} }
LOG("window is %08x / %s\n", client->child, client->name);
int base_width = 0, base_height = 0; int base_width = 0, base_height = 0;
/* base_width/height are the desired size of the window. /* 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, 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) { xcb_atom_t name, xcb_get_property_reply_t *reply) {
LOG("Transient hint!\n");
Client *client = table_get(&by_child, window); Client *client = table_get(&by_child, window);
if (client == NULL) { if (client == NULL) {
LOG("No such client\n"); 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; xcb_window_t transient_for;
if (reply != NULL) { if (reply != NULL) {
if (!xcb_get_wm_transient_for_from_reply(&transient_for, reply)) { if (!xcb_get_wm_transient_for_from_reply(&transient_for, reply))
LOG("Not transient for any window\n");
return 1; return 1;
}
} else { } else {
if (!xcb_get_wm_transient_for_reply(conn, xcb_get_wm_transient_for_unchecked(conn, window), if (!xcb_get_wm_transient_for_reply(conn, xcb_get_wm_transient_for_unchecked(conn, window),
&transient_for, NULL)) { &transient_for, NULL))
LOG("Not transient for any window\n");
return 1; return 1;
}
} }
if (client->floating == FLOATING_AUTO_OFF) { 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, 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) { xcb_atom_t name, xcb_get_property_reply_t *prop) {
LOG("client leader changed\n");
if (prop == NULL) { if (prop == NULL) {
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL); 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) if (leader == NULL)
return 1; return 1;
LOG("changed to %08x\n", *leader); LOG("Client leader changed to %08x\n", *leader);
client->leader = *leader; client->leader = *leader;

View File

@ -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) { 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); i3Font *font = load_font(conn, config.font);
i3Screen *screen = r_ws->screen; i3Screen *screen = r_ws->screen;
enum { SET_NORMAL = 0, SET_FOCUSED = 1 }; 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); (xcb_char2b_t*)ws->name);
drawn += ws->text_width + 12; 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; Client *client;
uint32_t values[1]; uint32_t values[1];
LOG("Ignore enter_notify = %d\n", ignore_enter_notify);
FOR_TABLE(workspace) FOR_TABLE(workspace)
CIRCLEQ_FOREACH(client, &(workspace->table[cols][rows]->clients), clients) { CIRCLEQ_FOREACH(client, &(workspace->table[cols][rows]->clients), clients) {
/* Change event mask for the decorations */ /* Change event mask for the decorations */

View File

@ -92,7 +92,7 @@ i3Screen *get_screen_containing(int x, int y) {
* This function always returns a screen. * 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; i3Screen *screen, *candidate = NULL;
int position = 0; int position = 0;
TAILQ_FOREACH(screen, virtual_screens, screens) { TAILQ_FOREACH(screen, virtual_screens, screens) {
@ -104,6 +104,14 @@ i3Screen *get_screen_most(direction_t direction) {
} \ } \
break; 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) { switch (direction) {
case D_UP: case D_UP:
WIN(screen->rect.y, <= position); WIN(screen->rect.y, <= position);