From dd134a74efe547e373da476eefc2a7e8a9e2f573 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 11 Aug 2009 14:08:04 +0200 Subject: [PATCH 01/14] Implement support for width_inc and height_inc of size hints This fixes the problem where you saw old window contents when resizing a window (due to opening new windows or similar), especially in terminals. --- include/data.h | 5 +++++ src/handlers.c | 19 +++++++++++++------ src/layout.c | 14 ++++++++++++++ src/manage.c | 2 ++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/include/data.h b/include/data.h index f40de86e..440c9a8f 100644 --- a/include/data.h +++ b/include/data.h @@ -346,6 +346,11 @@ struct Client { int proportional_height; int proportional_width; + /** contains the minimum increment size as specified for the window + * (in pixels). */ + int width_increment; + int height_increment; + /** Height which was determined by reading the _NET_WM_STRUT_PARTIAL * top/bottom of the screen reservation */ int desired_height; diff --git a/src/handlers.c b/src/handlers.c index 3c13b8c4..0f450c70 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -1021,10 +1021,9 @@ int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_wi */ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, xcb_atom_t name, xcb_get_property_reply_t *reply) { - LOG("handle_normal_hints\n"); Client *client = table_get(&by_child, window); if (client == NULL) { - LOG("No such client\n"); + LOG("Received WM_SIZE_HINTS for unknown client\n"); return 1; } xcb_size_hints_t size_hints; @@ -1037,15 +1036,23 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w xcb_get_wm_normal_hints_reply(conn, xcb_get_wm_normal_hints_unchecked(conn, client->child), &size_hints, NULL); if ((size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) { - LOG("min size set\n"); - LOG("gots min_width = %d, min_height = %d\n", size_hints.min_width, size_hints.min_height); + LOG("Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height); + } + + if ((size_hints.flags & XCB_SIZE_HINT_P_RESIZE_INC)) { + if (size_hints.width_inc > 0) + client->width_increment = size_hints.width_inc; + if (size_hints.height_inc > 0) + client->height_increment = size_hints.height_inc; + + LOG("Updated client's width_increment to %d px, heigh_increment to %d px\n", + client->width_increment, client->height_increment); } /* If no aspect ratio was set or if it was invalid, we ignore the hints */ if (!(size_hints.flags & XCB_SIZE_HINT_P_ASPECT) || (size_hints.min_aspect_num <= 0) || (size_hints.min_aspect_den <= 0)) { - LOG("No aspect ratio set, ignoring\n"); return 1; } @@ -1070,7 +1077,7 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w double min_aspect = (double)size_hints.min_aspect_num / size_hints.min_aspect_den; double max_aspect = (double)size_hints.max_aspect_num / size_hints.min_aspect_den; - LOG("min_aspect = %f, max_aspect = %f\n", min_aspect, max_aspect); + LOG("Aspect ratio set: minimum %f, maximum %f\n", min_aspect, max_aspect); LOG("width = %f, height = %f\n", width, height); /* Sanity checks, this is user-input, in a way */ diff --git a/src/layout.c b/src/layout.c index b1fee1b0..d40cf431 100644 --- a/src/layout.c +++ b/src/layout.c @@ -288,6 +288,20 @@ void resize_client(xcb_connection_t *conn, Client *client) { LOG("new_height = %f, new_width = %d\n", new_height, new_width); } + if (client->height_increment > 1) { + int old_height = rect->height; + rect->height = ((int)(rect->height / client->height_increment) * client->height_increment) + 1; + LOG("Lost %d pixel due to client's height_increment (%d px)\n", + old_height - rect->height, client->height_increment); + } + + if (client->width_increment > 1) { + int old_width = rect->width; + rect->width = ((int)(rect->width / client->width_increment) * client->width_increment) + 1; + LOG("Lost %d pixel due to client's width_increment (%d px)\n", + old_width - rect->width, client->width_increment); + } + LOG("child will be at %dx%d with size %dx%d\n", rect->x, rect->y, rect->width, rect->height); xcb_configure_window(conn, client->child, mask, &(rect->x)); diff --git a/src/manage.c b/src/manage.c index a5a46237..af83d069 100644 --- a/src/manage.c +++ b/src/manage.c @@ -177,6 +177,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, new->child = child; new->rect.width = width; new->rect.height = height; + new->width_increment = 1; + new->height_increment = 1; /* Pre-initialize the values for floating */ new->floating_rect.x = -1; new->floating_rect.width = width; From 556f18029012792316ef847f4e24ef61e51daec6 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 11 Aug 2009 15:02:30 +0200 Subject: [PATCH 02/14] Bugfix: Fix screen wrapping, cleanup some log messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- include/client.h | 6 ++++ include/xinerama.h | 2 +- src/client.c | 8 ++++++ src/commands.c | 12 ++++---- src/handlers.c | 70 ++++++++++++++-------------------------------- src/layout.c | 5 ---- src/xinerama.c | 10 ++++++- 7 files changed, 51 insertions(+), 62 deletions(-) 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); From 44d9111d65691854360de67f9a7afa1a0d9a6e22 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 11 Aug 2009 15:23:58 +0200 Subject: [PATCH 03/14] More log cleanups --- include/client.h | 4 +++- src/client.c | 8 -------- src/commands.c | 2 -- src/config.c | 5 +---- src/handlers.c | 22 ++++++---------------- src/layout.c | 17 +---------------- src/manage.c | 19 +++++-------------- src/util.c | 6 ++---- src/xcb.c | 2 -- 9 files changed, 18 insertions(+), 67 deletions(-) diff --git a/include/client.h b/include/client.h index 9d47edaf..e43f81b9 100644 --- a/include/client.h +++ b/include/client.h @@ -101,6 +101,8 @@ void client_map(xcb_connection_t *conn, Client *client); * Pretty-prints the client’s information into the logfile. * */ -void client_log(Client *client); +#define CLIENT_LOG(client) do { \ + LOG("Window: frame 0x%08x, child 0x%08x\n", client->frame, client->child); \ + } while (0) #endif diff --git a/src/client.c b/src/client.c index 12125d8b..a4269805 100644 --- a/src/client.c +++ b/src/client.c @@ -314,11 +314,3 @@ 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 afb16704..802f0fd4 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1069,6 +1069,4 @@ void parse_command(xcb_connection_t *conn, const char *command) { continue; } } - - LOG("--- done ---\n"); } diff --git a/src/config.c b/src/config.c index 65bfd67d..0bd67808 100644 --- a/src/config.c +++ b/src/config.c @@ -50,9 +50,7 @@ static void replace_variable(char *buffer, const char *key, const char *value) { /* To prevent endless recursions when the user makes an error configuring, * we stop after 100 replacements. That should be vastly more than enough. */ int c = 0; - LOG("Replacing %s with %s\n", key, value); while ((pos = strcasestr(buffer, key)) != NULL && c++ < 100) { - LOG("replacing variable %s in \"%s\" with \"%s\"\n", key, buffer, value); char *rest = pos + strlen(key); *pos = '\0'; char *replaced; @@ -103,7 +101,6 @@ void grab_all_keys(xcb_connection_t *conn) { } /* We need to translate the symbol to a keycode */ - LOG("Translating symbol to keycode (\"%s\")\n", bind->symbol); xcb_keysym_t keysym = XStringToKeysym(bind->symbol); if (keysym == NoSymbol) { LOG("Could not translate string to key symbol: \"%s\"\n", bind->symbol); @@ -127,7 +124,7 @@ void grab_all_keys(xcb_connection_t *conn) { last_keycode = *walk; bind->number_keycodes++; } - LOG("Got %d different keycodes\n", bind->number_keycodes); + LOG("Translated symbol \"%s\" to %d keycode\n", bind->symbol, bind->number_keycodes); bind->translated_to = smalloc(bind->number_keycodes * sizeof(xcb_keycode_t)); memcpy(bind->translated_to, keycodes, bind->number_keycodes * sizeof(xcb_keycode_t)); free(keycodes); diff --git a/src/handlers.c b/src/handlers.c index 1e10705a..61d1b711 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -48,8 +48,6 @@ static void add_ignore_event(const int sequence) { event->sequence = sequence; event->added = time(NULL); - LOG("Adding sequence %d to ignorelist\n", sequence); - SLIST_INSERT_HEAD(&ignore_events, event, ignore_events); } @@ -71,7 +69,6 @@ static bool event_is_ignored(const int sequence) { SLIST_FOREACH(event, &ignore_events, ignore_events) { if (event->sequence == sequence) { - LOG("Ignoring event (sequence %d)\n", sequence); SLIST_REMOVE(&ignore_events, event, Ignore_Event, ignore_events); free(event); return true; @@ -87,7 +84,6 @@ static bool event_is_ignored(const int sequence) { * */ int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_release_event_t *event) { - LOG("got key release, just passing\n"); xcb_allow_events(conn, XCB_ALLOW_REPLAY_KEYBOARD, event->time); xcb_flush(conn); return 1; @@ -608,13 +604,12 @@ 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("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 */ add_ignore_event(event->sequence); add_ignore_event(event->sequence); if (event->event == root) { + LOG("event->x = %d, ->y = %d, ->width = %d, ->height = %d\n", event->x, event->y, event->width, event->height); LOG("reconfigure of the root window, need to xinerama\n"); /* FIXME: Somehow, this is occuring too often. Therefore, we check for 0/0, but is there a better way? */ @@ -640,7 +635,6 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti /* First, we need to check if the client is awaiting an unmap-request which was generated by us reparenting the window. In that case, we just ignore it. */ if (client != NULL && client->awaiting_useless_unmap) { - LOG("Dropping this unmap request, it was generated by reparenting\n"); client->awaiting_useless_unmap = false; return 1; } @@ -877,10 +871,8 @@ int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state, client->window_class = new_class; FREE(old_class); - if (!client->initialized) { - LOG("Client is not yet initialized, not putting it to floating\n"); + if (!client->initialized) return 1; - } if (strcmp(new_class, "tools") == 0 || strcmp(new_class, "Dialog") == 0) { LOG("tool/dialog window, should we put it floating?\n"); @@ -1007,7 +999,7 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w } xcb_size_hints_t size_hints; - client_log(client); + CLIENT_LOG(client); /* If the hints were already in this event, use them, if not, request them */ if (reply != NULL) @@ -1016,7 +1008,8 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w xcb_get_wm_normal_hints_reply(conn, xcb_get_wm_normal_hints_unchecked(conn, client->child), &size_hints, NULL); if ((size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)) { - LOG("Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height); + // TODO: Minimum size is not yet implemented + //LOG("Minimum size: %d (width) x %d (height)\n", size_hints.min_width, size_hints.min_height); } if ((size_hints.flags & XCB_SIZE_HINT_P_RESIZE_INC)) { @@ -1024,9 +1017,6 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w client->width_increment = size_hints.width_inc; if (size_hints.height_inc > 0) client->height_increment = size_hints.height_inc; - - LOG("Updated client's width_increment to %d px, heigh_increment to %d px\n", - client->width_increment, client->height_increment); } /* If no aspect ratio was set or if it was invalid, we ignore the hints */ @@ -1132,7 +1122,7 @@ int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state return 1; xcb_window_t *leader = xcb_get_property_value(prop); - if (leader == NULL) + if (leader == NULL || *leader == 0) return 1; LOG("Client leader changed to %08x\n", *leader); diff --git a/src/layout.c b/src/layout.c index d628ef8f..1d58097d 100644 --- a/src/layout.c +++ b/src/layout.c @@ -109,7 +109,6 @@ void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t draw if (client->dock) return; - LOG("redecorating child %08x\n", client->child); last_focused = SLIST_FIRST(&(client->workspace->focus_stack)); if (client_is_floating(client)) { if (last_focused == client) @@ -209,7 +208,6 @@ void reposition_client(xcb_connection_t *conn, Client *client) { LOG("Client is on workspace %p with screen %p\n", client->workspace, client->workspace->screen); LOG("but screen at %d, %d is %p\n", client->rect.x, client->rect.y, screen); floating_assign_to_workspace(client, &workspaces[screen->current_workspace]); - LOG("fixed that\n"); } /* @@ -325,7 +323,6 @@ void render_container(xcb_connection_t *conn, Container *container) { num_clients++; if (container->mode == MODE_DEFAULT) { - LOG("got %d clients in this default container.\n", num_clients); CIRCLEQ_FOREACH(client, &(container->clients), clients) { /* If the client is in fullscreen mode, it does not get reconfigured */ if (container->workspace->fullscreen_client == client) { @@ -535,8 +532,6 @@ void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws) /* Space for the internal bar */ height -= (font->height + 6); - LOG("got %d rows and %d cols\n", r_ws->rows, r_ws->cols); - int xoffset[r_ws->rows]; int yoffset[r_ws->cols]; /* Initialize offsets */ @@ -545,19 +540,12 @@ void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws) for (int rows = 0; rows < r_ws->rows; rows++) xoffset[rows] = r_ws->rect.x; - dump_table(conn, r_ws); - ignore_enter_notify_forall(conn, r_ws, true); /* Go through the whole table and render what’s necessary */ FOR_TABLE(r_ws) { Container *container = r_ws->table[cols][rows]; int single_width = -1, single_height; - LOG("\n"); - LOG("========\n"); - LOG("container has %d colspan, %d rowspan\n", - container->colspan, container->rowspan); - LOG("container at %d, %d\n", xoffset[rows], yoffset[cols]); /* Update position of the container */ container->row = rows; container->col = cols; @@ -585,7 +573,6 @@ void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws) xoffset[rows] += single_width; yoffset[cols] += single_height; - LOG("==========\n"); } ignore_enter_notify_forall(conn, r_ws, false); @@ -605,10 +592,8 @@ void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws) void render_layout(xcb_connection_t *conn) { i3Screen *screen; - TAILQ_FOREACH(screen, virtual_screens, screens) { - LOG("Rendering screen %d\n", screen->num); + TAILQ_FOREACH(screen, virtual_screens, screens) render_workspace(conn, screen, &(workspaces[screen->current_workspace])); - } xcb_flush(conn); } diff --git a/src/manage.c b/src/manage.c index af83d069..dd726c6e 100644 --- a/src/manage.c +++ b/src/manage.c @@ -68,7 +68,6 @@ void manage_existing_windows(xcb_connection_t *conn, xcb_property_handlers_t *pr void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn, xcb_window_t window, xcb_get_window_attributes_cookie_t cookie, bool needs_to_be_mapped) { - LOG("managing window.\n"); xcb_drawable_t d = { window }; xcb_get_geometry_cookie_t geomc; xcb_get_geometry_reply_t *geom; @@ -83,16 +82,12 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn, return; } - if (needs_to_be_mapped && attr->map_state != XCB_MAP_STATE_VIEWABLE) { - LOG("Window not mapped, not managing\n"); + if (needs_to_be_mapped && attr->map_state != XCB_MAP_STATE_VIEWABLE) goto out; - } /* Don’t manage clients with the override_redirect flag */ - if (attr->override_redirect) { - LOG("override_redirect set, not managing\n"); + if (attr->override_redirect) goto out; - } /* Check if the window is already managed */ if (table_get(&by_child, window)) @@ -158,7 +153,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, /* Events for already managed windows should already be filtered in manage_window() */ assert(new == NULL); - LOG("reparenting new client\n"); + LOG("Reparenting window 0x%08x\n", child); LOG("x = %d, y = %d, width = %d, height = %d\n", x, y, width, height); new = calloc(sizeof(Client), 1); new->force_reconfigure = true; @@ -194,8 +189,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, mask |= XCB_CW_EVENT_MASK; values[1] = FRAME_EVENT_MASK; - LOG("Reparenting 0x%08x under 0x%08x.\n", child, new->frame); - i3Font *font = load_font(conn, config.font); width = min(width, c_ws->rect.x + c_ws->rect.width); height = min(height, c_ws->rect.y + c_ws->rect.height); @@ -315,7 +308,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, preply = xcb_get_property_reply(conn, leader_cookie, NULL); handle_clientleader_change(NULL, conn, 0, new->child, atoms[WM_CLIENT_LEADER], preply); - LOG("DEBUG: should have all infos now\n"); struct Assignment *assign; TAILQ_FOREACH(assign, &assignments, assignments) { if (get_matching_client(conn, assign->windowclass_title, new) == NULL) @@ -437,10 +429,9 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, /* Map the window first to avoid flickering */ xcb_map_window(conn, child); - if (map_frame) { - LOG("Mapping client\n"); + if (map_frame) client_map(conn, new); - } + if (CUR_CELL->workspace->fullscreen_client == NULL && !new->dock) { /* Focus the new window if we’re not in fullscreen mode and if it is not a dock window */ if (new->workspace->fullscreen_client == NULL) { diff --git a/src/util.c b/src/util.c index d1acc744..8cb5409c 100644 --- a/src/util.c +++ b/src/util.c @@ -240,10 +240,8 @@ void set_focus(xcb_connection_t *conn, Client *client, bool set_anyways) { Client *old_client = SLIST_FIRST(&(c_ws->focus_stack)); /* Check if the focus needs to be changed at all */ - if (!set_anyways && (old_client == client)) { - LOG("old_client == client, not changing focus\n"); + if (!set_anyways && (old_client == client)) return; - } /* Store current_row/current_col */ c_ws->current_row = current_row; @@ -261,7 +259,7 @@ void set_focus(xcb_connection_t *conn, Client *client, bool set_anyways) { current_row = client->container->row; } - LOG("set_focus(frame %08x, child %08x, name %s)\n", client->frame, client->child, client->name); + CLIENT_LOG(client); /* Set focus to the entered window, and flush xcb buffer immediately */ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, client->child, XCB_CURRENT_TIME); //xcb_warp_pointer(conn, XCB_NONE, client->child, 0, 0, 0, 0, 10, 10); diff --git a/src/xcb.c b/src/xcb.c index 3f5d4280..4ed2f1aa 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -181,8 +181,6 @@ void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window) xcb_send_event(conn, false, window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char*)&generated_event); xcb_flush(conn); - - LOG("Told the client it is at %dx%d with %dx%d\n", r.x, r.y, r.width, r.height); } /* From 4b3ea4d5244f568400ce3b8ddf6bdfa2767673e5 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 10:56:42 +0200 Subject: [PATCH 04/14] =?UTF-8?q?Bugfix:=20Don=E2=80=99t=20crash=20when=20?= =?UTF-8?q?clients=20set=20an=20invalid=20leader=20hint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/handlers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/handlers.c b/src/handlers.c index 61d1b711..2f98f019 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -1115,6 +1115,8 @@ int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state if (prop == NULL) { prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL); + if (prop == NULL) + return 1; } Client *client = table_get(&by_child, window); From c38767603bdee5cefe4ba5eb9ee477ddefe307d3 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 12:59:13 +0200 Subject: [PATCH 05/14] Document commands and new configuration options in userguide --- docs/userguide | 271 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 230 insertions(+), 41 deletions(-) diff --git a/docs/userguide b/docs/userguide index 05593cd5..ba8a752e 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1,7 +1,7 @@ i3 User’s Guide =============== Michael Stapelberg -June 2009 +August 2009 This document contains all information you need to configuring and using the i3 window manager. If it does not, please contact me on IRC, Jabber or E-Mail and @@ -174,24 +174,40 @@ font:: === Keyboard bindings -You can use each command (see below) using keyboard bindings. At the moment, -keyboard bindings require you to specify the keycode (38) of the key, not its key -symbol ("a"). This has some advantages (keybindings make sense regardless of -the layout you type) and some disadvantages (hard to remember, you have to look -them up every time). +A keyboard binding makes i3 execute a command (see below) upon pressing a +specific key. i3 allows you to bind either on keycodes or on keysyms (you can +also mix your bindings, though i3 will not protect you from overlapping ones). + +* A keysym (key symbol) is a description for a specific symbol, like "a" or "b", + but also more strange ones like "underscore" instead of "_". These are the ones + you also use in Xmodmap to remap your keys. To get the current mapping of your + keys, use +xmodmap -pke+. + +* Keycodes however do not need to have a symbol assigned (handy for some hotkeys + on some notebooks) and they will not change their meaning as you switch to a + different keyboard layout. + +My recommendation is: If you often switch keyboard layouts because you try to +learn a different one, but you want to keep your bindings at the same place, +use keycodes. If you don’t switch layouts and like a clean and simple config +file, use keysyms. *Syntax*: --------------------------------- +---------------------------------- +bindsym [Modifiers+]keysym command bind [Modifiers+]keycode command --------------------------------- +---------------------------------- *Examples*: -------------------------------- # Fullscreen -bind Mod1+41 f +bind Mod1+f f # Restart -bind Mod1+Shift+27 restart +bind Mod1+Shift+r restart + +# Notebook-specific hotkeys +bind 214 exec /home/michael/toggle_beamer.sh -------------------------------- Available Modifiers: @@ -241,7 +257,7 @@ set name value *Examples*: ------------------------ set $m Mod1 -bind $m+Shift+27 restart +bindsym $m+Shift+r restart ------------------------ Variables are directly replaced in the file when parsing, there is no fancy @@ -259,8 +275,8 @@ i3 will get the title as soon as the application maps the window (mapping means actually displaying it on the screen), you’d need to have to match on Firefox in this case. -You can prefix or suffix workspaces with a +~+ to specify that matching clients -should be put into floating mode. If you specify only a +~+, the client will +You can prefix or suffix workspaces with a `~` to specify that matching clients +should be put into floating mode. If you specify only a `~`, the client will not be put onto any workspace, but will be set floating on the current one. *Syntax*: @@ -294,6 +310,181 @@ exec command exec sudo i3status | dzen2 -dock -------------------------------- +=== Automatically putting workspaces on specific screens + +If you use the assigning of clients to workspaces and start some clients +automatically, it might be handy to put the workspaces on specific screens. +Also, the assignment of workspaces to screens will determine the workspace +which i3 uses for a new screen when adding screens or when starting (e.g., by +default it will use 1 for the first screen, 2 for the second screen and so on). + +*Syntax*: +---------------------------------- +workspace screen +---------------------------------- + +Screen can be either a number (starting at 0 for the first screen) or a +position. When using numbers, it is not guaranteed that your screens always +get the same number. Though, unless you upgrade your X server or drivers, the +order usually stays the same. When using positions, you have to specify the +exact pixel where the screen *starts*, not a pixel which is contained by the +screen. Thus, if your first screen has the dimensions 1280x800, you can match +the second screen right of it by specifying 1280. You cannot use 1281. + +*Examples*: +--------------------------- +workspace 1 screen 0 +workspace 5 screen 1 + +workspace 1 screen 1280 +workspace 2 screen x800 +workspace 3 screen 1280x800 +--------------------------- + +=== Named workspaces + +If you always have a certain arrangement of workspaces, you might want to give +them names (of course UTF-8 is supported): + +*Syntax*: +--------------------------------------- +workspace +workspace screen name +--------------------------------------- + +For more details about the screen-part of this command, see above. + +*Examples*: +-------------------------- +workspace 1 www +workspace 2 work +workspace 3 i ♥ workspaces +-------------------------- + +=== Changing colors + +You can change all colors which i3 uses to draw the window decorations and the +bottom bar. + +*Syntax*: +-------------------------------------------- +colorclass border background text +-------------------------------------------- + +Where colorclass can be one of: + +client.focused:: + A client which currently has the focus. +client.focused_inactive:: + A client which is the focused one of its container, but it does not have + the focus at the moment. +client.unfocused:: + A client which is not the focused one of its container. +bar.focused:: + The current workspace in the bottom bar. +bar.unfocused:: + All other workspaces in the bottom bar. + +Colors are in HTML hex format, see below. + +*Examples*: +-------------------------------------- +# class border backgr. text +client.focused #2F343A #900000 #FFFFFF +-------------------------------------- + +=== Interprocess communication + +i3 uses unix sockets to provide an IPC interface. At the moment, this interface +is only useful for sending commands. To enable it, you have to configure a path +where the unix socket will be stored. The default path is +/tmp/i3-ipc.sock+. + +*Examples*: +---------------------------- +ipc-socket /tmp/i3-ipc.sock +---------------------------- + +You can then use the i3-msg command to perform any command listed in the next +section. + +== List of commands + +=== Manipulating layout + +To change the layout of the current container to stacking or back to default +layout, use +s+ or +d+. To make the current client (!) fullscreen, use +f+, to +make it floating (or tiling again) use +t+: + +*Examples*: +-------------- +bind Mod1+s s +bind Mod1+l d + +# Toggle fullscreen +bind Mod1+f f + +# Toggle floating/tiling +bind Mod1+t t +-------------- + +=== Focussing/Moving/Snapping clients/containers/screens + +To change the focus, use one of the +h+, +j+, +k+ and +l+ commands, meaning +respectively left, down, up, right. To focus a container, prefix it with +wc+, +to focus a screen, prefix it with +ws+. + +The same principle applies for moving and snapping, just prefix the command +with +m+ when moving and with +s+ when snapping: + +*Examples*: +---------------------- +# Focus clients on the left, bottom, top, right: +bindsym Mod1+j h +bindsym Mod1+k j +bindsym Mod1+j k +bindsym Mod1+semicolon l + +# Move client to the left, bottom, top, right: +bindsym Mod1+j mh +bindsym Mod1+k mj +bindsym Mod1+j mk +bindsym Mod1+semicolon ml + +# Snap client to the left, bottom, top, right: +bindsym Mod1+j sh +bindsym Mod1+k sj +bindsym Mod1+j sk +bindsym Mod1+semicolon sl + +# Focus container on the left, bottom, top, right: +bindsym Mod3+j wch +… +---------------------- + +=== Changing workspaces/moving clients to workspaces + +To change to a specific workspace, the command is just the number of the +workspace, e.g. +1+ or +3+. To move the current client to a specific workspace, +prefix the number with an +m+. + +Furthermore, you can switch to the next and previous workspace with the +commands +nw+ and +pw+, which is handy for example if you have workspace +1, 3, 4 and 9 and you want to cycle through them with a single key combination. + +*Examples*: +------------------------- +bindsym Mod1+1 1 +bindsym Mod1+2 2 +... + +bindsym Mod1+Shift+1 m1 +bindsym Mod1+Shift+2 m2 +... + +bindsym Mod1+o nw +bindsym Mod1+p pw +------------------------- + === Jumping to specific windows Especially when in a multi-monitor environment, you want to quickly jump to a specific @@ -340,34 +531,32 @@ ft:: If the current window is floating, the next tiling window will be selected and vice-versa. -=== Changing colors +=== Changing border style -You can change all colors which i3 uses to draw the window decorations and the -bottom bar. - -*Syntax*: --------------------------------------------- -colorclass border background text --------------------------------------------- - -Where colorclass can be one of: - -client.focused:: - A client which currently has the focus. -client.focused_inactive:: - A client which is the focused one of its container, but it does not have - the focus at the moment. -client.unfocused:: - A client which is not the focused one of its container. -bar.focused:: - The current workspace in the bottom bar. -bar.unfocused:: - All other workspaces in the bottom bar. - -Colors are in HTML hex format, see below. +To change the border of the current client, you can use +bn+ to use the normal +border (including window title), +bp+ to use a 1-pixel border (no window title) +and +bb+ to make the client borderless. *Examples*: --------------------------------------- -# class border backgr. text -client.focused #2F343A #900000 #FFFFFF --------------------------------------- +------------------ +bindsym Mod1+t bn +bindsym Mod1+y bp +bindsym Mod1+u bb +------------------ + +=== Reloading/Restarting/Exiting + +You can make i3 reload its configuration file with +reload+. You can also +restart i3 inplace with the +restart+ command to get it out of some weird state +(if that should ever happen) or to perform an upgrade without having to restart +your X session. However, your layout is not preserved at the moment, meaning +that all open windows will be in a single container in default layout. To exit +i3 properly, you can use the +exit+ command, however you don’t need to (e.g., +simply killing your X session is fine aswell). + +*Examples*: +---------------------------- +bindsym Mod1+Shift+r restart +bindsym Mod1+Shift+w reload +bindsym Mod1+Shift+e exit +---------------------------- From a0e26bd823c13b0782c995092756c6b9e98395aa Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 13:14:16 +0200 Subject: [PATCH 06/14] Update debian changelog --- debian/changelog | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 8bb2c846..2610fc58 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,14 +1,29 @@ -i3-wm (3.c-0) unstable; urgency=low +i3-wm (3.c-1) unstable; urgency=low * Implement a reload command + * Implement keysymbols in configuration file + * Implement assignments of workspaces to screens + * Implement named workspaces + * Implement borderless/1-px-border windows + * Implement command to focus screens * Implement IPC via unix sockets + * Correctly render decoration of floating windows + * Map floating windows requesting (0x0) to center of their leader/workspace * Optimization: Render stack windows on pixmaps to reduce flickering * Optimization: Directly position new windows to their final position * Bugfix: Repeatedly try to find screens if none are available * Bugfix: Correctly redecorate clients when changing focus * Bugfix: Don’t crash when clients reconfigure themselves + * Bugfix: Fix screen wrapping + * Bugfix: Fix selecting a different screen with your mouse when not having + any windows on the current workspace + * Bugfix: Correctly unmap stack windows and don’t re-map them too early + * Bugfix: Allow switching layout if there are no clients in the this container + * Bugfix: Set WM_STATE_WITHDRAWN when unmapping, unmap windows when + destroying + * Bugfix: Don’t hide assigned clients to inactive but visible workspaces - -- Michael Stapelberg Sun, 02 Aug 2009 20:05:58 +0200 + -- Michael Stapelberg Wed, 19 Aug 2009 13:07:58 +0200 i3-wm (3.b-1) unstable; urgency=low From 962bab7c1c644cf2d85852aca76ef4c08a981c36 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 13:15:14 +0200 Subject: [PATCH 07/14] Update examples to use bindsym instead of bind --- docs/userguide | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/userguide b/docs/userguide index ba8a752e..a358c9d7 100644 --- a/docs/userguide +++ b/docs/userguide @@ -201,10 +201,10 @@ bind [Modifiers+]keycode command *Examples*: -------------------------------- # Fullscreen -bind Mod1+f f +bindsym Mod1+f f # Restart -bind Mod1+Shift+r restart +bindsym Mod1+Shift+r restart # Notebook-specific hotkeys bind 214 exec /home/michael/toggle_beamer.sh @@ -417,14 +417,14 @@ make it floating (or tiling again) use +t+: *Examples*: -------------- -bind Mod1+s s -bind Mod1+l d +bindsym Mod1+s s +bindsym Mod1+l d # Toggle fullscreen -bind Mod1+f f +bindsym Mod1+f f # Toggle floating/tiling -bind Mod1+t t +bindsym Mod1+t t -------------- === Focussing/Moving/Snapping clients/containers/screens @@ -505,7 +505,7 @@ or you can specify the position of the client if you always use the same layout. *Examples*: -------------------------------------- # Get me to the next open VIM instance -bind Mod1+38 jump "urxvt/VIM" +bindsym Mod1+a jump "urxvt/VIM" -------------------------------------- === Traveling the focus stack From e35299d4df32218043603b64d18491307938dae1 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 13:23:26 +0200 Subject: [PATCH 08/14] userguide: s/j/l in examples --- docs/userguide | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/userguide b/docs/userguide index a358c9d7..25bca9cc 100644 --- a/docs/userguide +++ b/docs/userguide @@ -441,19 +441,19 @@ with +m+ when moving and with +s+ when snapping: # Focus clients on the left, bottom, top, right: bindsym Mod1+j h bindsym Mod1+k j -bindsym Mod1+j k +bindsym Mod1+l k bindsym Mod1+semicolon l # Move client to the left, bottom, top, right: bindsym Mod1+j mh bindsym Mod1+k mj -bindsym Mod1+j mk +bindsym Mod1+l mk bindsym Mod1+semicolon ml # Snap client to the left, bottom, top, right: bindsym Mod1+j sh bindsym Mod1+k sj -bindsym Mod1+j sk +bindsym Mod1+l sk bindsym Mod1+semicolon sl # Focus container on the left, bottom, top, right: From a84b2269c38f31137607fa53df049b24399d4f26 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 13:31:14 +0200 Subject: [PATCH 09/14] userguide: use space for toggling tiling/floating --- docs/userguide | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide b/docs/userguide index 25bca9cc..0d25300a 100644 --- a/docs/userguide +++ b/docs/userguide @@ -424,7 +424,7 @@ bindsym Mod1+l d bindsym Mod1+f f # Toggle floating/tiling -bindsym Mod1+t t +bindsym Mod1+space t -------------- === Focussing/Moving/Snapping clients/containers/screens From c10ff34ae73f5748cc7ab9d5e0cc520f8745509d Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 14:00:49 +0200 Subject: [PATCH 10/14] =?UTF-8?q?Add=20release=20notes=20for=203.=CE=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RELEASE-NOTES-3.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 RELEASE-NOTES-3.c diff --git a/RELEASE-NOTES-3.c b/RELEASE-NOTES-3.c new file mode 100644 index 00000000..8005d366 --- /dev/null +++ b/RELEASE-NOTES-3.c @@ -0,0 +1,41 @@ +Release notes for i3 v3.γ +----------------------------- + +This is the third version (3.γ, transcribed 3.c) of i3. It is considered stable. + +This release contains many small improvements like using keysymbols in the +configuration file, named workspaces, borderless windows, an IPC interface +etc. (see below for a complete list of changes) + +Thanks for this release go out to bapt, badboy, Atsutane, tsdh, xeen, mxf, +and all other people who reported bugs/made suggestions. + +Special thanks go to steckdenis, yellowiscool and farvardin who designed a logo +for i3. + +A list of changes follows: + + * Implement a reload command + * Implement keysymbols in configuration file + * Implement assignments of workspaces to screens + * Implement named workspaces + * Implement borderless/1-px-border windows + * Implement command to focus screens + * Implement IPC via unix sockets + * Correctly render decoration of floating windows + * Map floating windows requesting (0x0) to center of their leader/workspace + * Optimization: Render stack windows on pixmaps to reduce flickering + * Optimization: Directly position new windows to their final position + * Bugfix: Repeatedly try to find screens if none are available + * Bugfix: Correctly redecorate clients when changing focus + * Bugfix: Don’t crash when clients reconfigure themselves + * Bugfix: Fix screen wrapping + * Bugfix: Fix selecting a different screen with your mouse when not having + any windows on the current workspace + * Bugfix: Correctly unmap stack windows and don’t re-map them too early + * Bugfix: Allow switching layout if there are no clients in the this container + * Bugfix: Set WM_STATE_WITHDRAWN when unmapping, unmap windows when + destroying + * Bugfix: Don’t hide assigned clients to inactive but visible workspaces + +-- Michael Stapelberg, 2009-08-19 From 7469e35a8ba1aee5b106a8f9526f444b69ce95c7 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 14:07:52 +0200 Subject: [PATCH 11/14] Document new files in the hacking howto --- docs/hacking-howto | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/hacking-howto b/docs/hacking-howto index 22649c38..3a448537 100644 --- a/docs/hacking-howto +++ b/docs/hacking-howto @@ -127,6 +127,9 @@ src/handlers.c:: Contains all handlers for all kind of X events (new window title, new hints, unmapping, key presses, button presses, …). +src/ipc.c:: +Contains code for the IPC interface. + src/layout.c:: Renders your layout (screens, workspaces, containers). @@ -149,6 +152,9 @@ Manages the most important internal data structure, the design table. src/util.c:: Contains useful functions which are not really dependant on anything. +src/workspace.c:: +Contains all functions related to workspaces (displaying, hiding, renaming…) + src/xcb.c:: Contains wrappers to use xcb more easily. From 4be7a344705fcabbabd96b9169f549cc1789c422 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 14:32:51 +0200 Subject: [PATCH 12/14] Update manpage --- man/i3.man | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/man/i3.man b/man/i3.man index cf592c62..39260560 100644 --- a/man/i3.man +++ b/man/i3.man @@ -1,7 +1,7 @@ i3(1) ===== Michael Stapelberg -v3.beta, May 2009 +v3.gamma, August 2009 == NAME @@ -232,9 +232,13 @@ your login manager (xdm, slim, gdm, …) as soon as you login. # Disable DPMS turning off the screen xset dpms force on xset s off + # Disable bell xset -b +# Enable zapping (C-A- kills X) +setxkbmap -option terminate:ctrl_alt_bksp + # Enforce correct locales from the beginning unset LC_COLLATE export LC_CTYPE=de_DE.UTF-8 @@ -249,6 +253,9 @@ export LC_TELEPHONE=de_DE.UTF-8 export LC_MEASUREMENT=de_DE.UTF-8 export LC_IDENTIFICATION=de_DE.UTF-8 +# Use XToolkit in java applications +export AWT_TOOLKIT=XToolkit + # Set background color xsetroot -solid "#333333" From 0b7a27ea795b40669654abce42c194f01d455329 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 14:37:34 +0200 Subject: [PATCH 13/14] initialize last_keycode --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 0bd67808..a5f635dc 100644 --- a/src/config.c +++ b/src/config.c @@ -113,7 +113,7 @@ void grab_all_keys(xcb_connection_t *conn) { continue; } - uint32_t last_keycode; + uint32_t last_keycode = 0; bind->number_keycodes = 0; for (xcb_keycode_t *walk = keycodes; *walk != 0; walk++) { /* We hope duplicate keycodes will be returned in order From 74a6c7532db8ac3ef5dcdfe6df97a3101e895e82 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 19 Aug 2009 14:37:46 +0200 Subject: [PATCH 14/14] Update make dist --- Makefile | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 850693e3..419dc561 100644 --- a/Makefile +++ b/Makefile @@ -28,16 +28,19 @@ install: all $(INSTALL) -m 0644 i3.desktop $(DESTDIR)/usr/share/xsessions/ $(MAKE) TOPDIR=$(TOPDIR) -C i3-msg install -dist: clean +dist: distclean [ ! -d i3-${VERSION} ] || rm -rf i3-${VERSION} [ ! -e i3-${VERSION}.tar.bz2 ] || rm i3-${VERSION}.tar.bz2 mkdir i3-${VERSION} - cp DEPENDS GOALS LICENSE PACKAGE-MAINTAINER TODO RELEASE-* i3.config i3.desktop pseudo-doc.doxygen i3-${VERSION} - cp -r src include man i3-${VERSION} + cp DEPENDS GOALS LICENSE PACKAGE-MAINTAINER TODO RELEASE-NOTES-${VERSION} i3.config i3.desktop pseudo-doc.doxygen Makefile i3-${VERSION} + cp -r src i3-msg include man i3-${VERSION} # Only copy toplevel documentation (important stuff) mkdir i3-${VERSION}/docs find docs -maxdepth 1 -type f ! -name "*.xcf" -exec cp '{}' i3-${VERSION}/docs \; - sed -e 's/^GIT_VERSION=\(.*\)/GIT_VERSION=${GIT_VERSION}/g;s/^VERSION=\(.*\)/VERSION=${VERSION}/g' Makefile > i3-${VERSION}/Makefile + sed -e 's/^GIT_VERSION=\(.*\)/GIT_VERSION=${GIT_VERSION}/g;s/^VERSION=\(.*\)/VERSION=${VERSION}/g' common.mk > i3-${VERSION}/common.mk + # Pre-generate a manpage to allow distributors to skip this step and save some dependencies + make -C man + cp man/i3.1 i3-${VERSION}/man/i3.1 tar cf i3-${VERSION}.tar i3-${VERSION} bzip2 -9 i3-${VERSION}.tar rm -rf i3-${VERSION} @@ -50,3 +53,4 @@ clean: distclean: clean rm -f i3 + $(MAKE) TOPDIR=$(TOPDIR) -C i3-msg distclean