Merge branch 'next' into testcases

Conflicts:
	docs/userguide
This commit is contained in:
Michael Stapelberg 2009-08-21 11:45:59 +02:00
commit 4da54f1279
17 changed files with 173 additions and 130 deletions

View File

@ -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

41
RELEASE-NOTES-3.c Normal file
View File

@ -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: Dont 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 dont 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: Dont hide assigned clients to inactive but visible workspaces
-- Michael Stapelberg, 2009-08-19

19
debian/changelog vendored
View File

@ -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: Dont 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 dont 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: Dont hide assigned clients to inactive but visible workspaces
-- Michael Stapelberg <michael@stapelberg.de> Sun, 02 Aug 2009 20:05:58 +0200
-- Michael Stapelberg <michael@stapelberg.de> Wed, 19 Aug 2009 13:07:58 +0200
i3-wm (3.b-1) unstable; urgency=low

View File

@ -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.

View File

@ -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

View File

@ -97,4 +97,12 @@ void client_unmap(xcb_connection_t *conn, Client *client);
*/
void client_map(xcb_connection_t *conn, Client *client);
/**
* Pretty-prints the clients information into the logfile.
*
*/
#define CLIENT_LOG(client) do { \
LOG("Window: frame 0x%08x, child 0x%08x\n", client->frame, client->child); \
} while (0)
#endif

View File

@ -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;

View File

@ -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

View File

@ -1,7 +1,7 @@
i3(1)
=====
Michael Stapelberg <michael+i3@stapelberg.de>
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-<Bksp> 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"

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");
/* 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);
@ -1069,6 +1069,4 @@ void parse_command(xcb_connection_t *conn, const char *command) {
continue;
}
}
LOG("--- done ---\n");
}

View File

@ -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);
@ -116,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
@ -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);

View File

@ -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;
@ -248,7 +244,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 +260,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 +362,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 clients parent (= titlebar)… */
Client *client = table_get(&by_child, event->event);
bool border_click = false;
@ -523,13 +518,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,15 +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("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 */
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? */
@ -645,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;
}
@ -723,11 +712,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 +734,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 +748,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 dont update if so.
@ -773,7 +758,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 +794,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 +802,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 +814,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 dont 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 +852,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,15 +866,13 @@ 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);
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");
@ -935,11 +913,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 +951,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;
@ -1021,14 +992,14 @@ 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;
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)
@ -1037,20 +1008,24 @@ 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);
// 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)) {
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;
}
/* 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;
}
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.
@ -1070,7 +1045,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 */
@ -1105,7 +1080,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");
@ -1115,16 +1089,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) {
@ -1142,10 +1112,11 @@ 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);
if (prop == NULL)
return 1;
}
Client *client = table_get(&by_child, window);
@ -1153,10 +1124,10 @@ 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("changed to %08x\n", *leader);
LOG("Client leader changed to %08x\n", *leader);
client->leader = *leader;

View File

@ -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");
}
/*
@ -288,6 +286,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));
@ -311,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) {
@ -434,7 +445,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 };
@ -477,8 +487,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");
}
/*
@ -491,8 +499,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 */
@ -526,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 */
@ -536,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 whats 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;
@ -576,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);
@ -596,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);
}

View File

@ -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;
}
/* Dont 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;
@ -177,6 +172,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;
@ -192,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);
@ -313,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)
@ -435,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 were not in fullscreen mode and if it is not a dock window */
if (new->workspace->fullscreen_client == NULL) {

View File

@ -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);

View File

@ -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);
}
/*

View File

@ -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);