diff --git a/Makefile b/Makefile index 4b2f240e..991fb49f 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ include $(TOPDIR)/common.mk # Depend on the object files of all source-files in src/*.c and on all header files AUTOGENERATED:=src/cfgparse.tab.c src/cfgparse.yy.c src/cmdparse.tab.c src/cmdparse.yy.c -FILES:=src/ipc.c src/main.c src/log.c src/util.c src/tree.c src/xcb.c src/manage.c src/workspace.c src/x.c src/floating.c src/click.c src/config.c src/handlers.c src/randr.c src/xinerama.c src/con.c src/load_layout.c src/render.c src/window.c src/match.c src/xcursor.c src/resize.c src/sighandler.c src/move.c src/output.c +FILES:=src/ipc.c src/main.c src/log.c src/util.c src/tree.c src/xcb.c src/manage.c src/workspace.c src/x.c src/floating.c src/click.c src/config.c src/handlers.c src/randr.c src/xinerama.c src/con.c src/load_layout.c src/render.c src/window.c src/match.c src/xcursor.c src/resize.c src/sighandler.c src/move.c src/output.c src/ewmh.c FILES:=$(FILES:.c=.o) HEADERS:=$(filter-out include/loglevels.h,$(wildcard include/*.h)) diff --git a/include/all.h b/include/all.h index 23c7fe36..6251932c 100644 --- a/include/all.h +++ b/include/all.h @@ -56,5 +56,6 @@ #include "sighandler.h" #include "move.h" #include "output.h" +#include "ewmh.h" #endif diff --git a/include/ewmh.h b/include/ewmh.h index c73c4a45..2f2bf431 100644 --- a/include/ewmh.h +++ b/include/ewmh.h @@ -1,5 +1,5 @@ /* - * vim:ts=8:expandtab + * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager * diff --git a/src/ewmh.c b/src/ewmh.c index 6bfa3096..a8bc51c8 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -1,5 +1,5 @@ /* - * vim:ts=8:expandtab + * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager * @@ -10,16 +10,8 @@ * ewmh.c: Functions to get/set certain EWMH properties easily. * */ -#include -#include -#include -#include "data.h" -#include "table.h" -#include "i3.h" -#include "xcb.h" -#include "util.h" -#include "log.h" +#include "all.h" /* * Updates _NET_CURRENT_DESKTOP with the current desktop number. @@ -29,10 +21,20 @@ * */ void ewmh_update_current_desktop() { - uint32_t current_desktop = c_ws->num; - xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, - atoms[_NET_CURRENT_DESKTOP], CARDINAL, 32, 1, - ¤t_desktop); + Con *focused_ws = con_get_workspace(focused); + Con *output; + uint32_t idx = 0; + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + if (ws == focused_ws) { + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, + atoms[_NET_CURRENT_DESKTOP], CARDINAL, 32, 1, &idx); + return; + } + ++idx; + } + } } /* @@ -43,8 +45,8 @@ void ewmh_update_current_desktop() { * */ void ewmh_update_active_window(xcb_window_t window) { - xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, - atoms[_NET_ACTIVE_WINDOW], WINDOW, 32, 1, &window); + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, + atoms[_NET_ACTIVE_WINDOW], WINDOW, 32, 1, &window); } /* @@ -56,48 +58,53 @@ void ewmh_update_active_window(xcb_window_t window) { * */ void ewmh_update_workarea() { - Workspace *ws; - int num_workspaces = 0, count = 0; - Rect last_rect = {0, 0, 0, 0}; + int num_workspaces = 0, count = 0; + Rect last_rect = {0, 0, 0, 0}; + Con *output; - /* Get the number of workspaces */ - TAILQ_FOREACH(ws, workspaces, workspaces) { - /* Check if we need to initialize last_rect. The case that the - * first workspace is all-zero may happen when the user - * assigned workspace 2 for his first screen, for example. Thus - * we need an initialized last_rect in the very first run of - * the following loop. */ - if (last_rect.width == 0 && last_rect.height == 0 && + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + /* Check if we need to initialize last_rect. The case that the + * first workspace is all-zero may happen when the user + * assigned workspace 2 for his first screen, for example. Thus + * we need an initialized last_rect in the very first run of + * the following loop. */ + if (last_rect.width == 0 && last_rect.height == 0 && ws->rect.width != 0 && ws->rect.height != 0) { - memcpy(&last_rect, &(ws->rect), sizeof(Rect)); - } - num_workspaces++; - } - - DLOG("Got %d workspaces\n", num_workspaces); - uint8_t *workarea = smalloc(sizeof(Rect) * num_workspaces); - TAILQ_FOREACH(ws, workspaces, workspaces) { - DLOG("storing %d: %dx%d with %d x %d\n", count, ws->rect.x, - ws->rect.y, ws->rect.width, ws->rect.height); - /* If a workspace is not yet initialized and thus its - * dimensions are zero, we will instead put the dimensions - * of the last workspace in the list. For example firefox - * intersects all workspaces and does not cope so well with - * an all-zero workspace. */ - if (ws->rect.width == 0 || ws->rect.height == 0) { - DLOG("re-using last_rect (%dx%d, %d, %d)\n", - last_rect.x, last_rect.y, last_rect.width, - last_rect.height); - memcpy(workarea + (sizeof(Rect) * count++), &last_rect, sizeof(Rect)); - continue; - } - memcpy(workarea + (sizeof(Rect) * count++), &(ws->rect), sizeof(Rect)); memcpy(&last_rect, &(ws->rect), sizeof(Rect)); + } + num_workspaces++; } - xcb_change_property(global_conn, XCB_PROP_MODE_REPLACE, root, - atoms[_NET_WORKAREA], CARDINAL, 32, - num_workspaces * (sizeof(Rect) / sizeof(uint32_t)), - workarea); - free(workarea); - xcb_flush(global_conn); + } + + DLOG("Got %d workspaces\n", num_workspaces); + uint8_t *workarea = smalloc(sizeof(Rect) * num_workspaces); + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + DLOG("storing %d: %dx%d with %d x %d\n", count, ws->rect.x, + ws->rect.y, ws->rect.width, ws->rect.height); + /* If a workspace is not yet initialized and thus its + * dimensions are zero, we will instead put the dimensions + * of the last workspace in the list. For example firefox + * intersects all workspaces and does not cope so well with + * an all-zero workspace. */ + if (ws->rect.width == 0 || ws->rect.height == 0) { + DLOG("re-using last_rect (%dx%d, %d, %d)\n", + last_rect.x, last_rect.y, last_rect.width, + last_rect.height); + memcpy(workarea + (sizeof(Rect) * count++), &last_rect, sizeof(Rect)); + continue; + } + memcpy(workarea + (sizeof(Rect) * count++), &(ws->rect), sizeof(Rect)); + memcpy(&last_rect, &(ws->rect), sizeof(Rect)); + } + } + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, + atoms[_NET_WORKAREA], CARDINAL, 32, + num_workspaces * (sizeof(Rect) / sizeof(uint32_t)), + workarea); + free(workarea); + xcb_flush(conn); } diff --git a/src/randr.c b/src/randr.c index d4dc770b..acac36ca 100644 --- a/src/randr.c +++ b/src/randr.c @@ -665,7 +665,7 @@ void randr_query_outputs() { disable_randr(conn); } - //ewmh_update_workarea(); + ewmh_update_workarea(); #if 0 /* Just go through each active output and associate one workspace */ diff --git a/src/workspace.c b/src/workspace.c index 4d3c5218..77b5ceb2 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -70,8 +70,6 @@ Con *workspace_get(const char *num, bool *created) { *created = false; } - //ewmh_update_workarea(); - return workspace; } @@ -206,7 +204,8 @@ static void workspace_reassign_sticky(Con *con) { void workspace_show(const char *num) { Con *workspace, *current, *old = NULL; - workspace = workspace_get(num, NULL); + bool changed_num_workspaces; + workspace = workspace_get(num, &changed_num_workspaces); /* disable fullscreen for the other workspaces and get the workspace we are * currently on. */ @@ -241,6 +240,7 @@ void workspace_show(const char *num) { LOG("Closing old workspace (%p / %s), it is empty\n", old, old->name); tree_close(old, false, false); ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}"); + changed_num_workspaces = true; } } @@ -248,6 +248,11 @@ void workspace_show(const char *num) { workspace->fullscreen_mode = CF_OUTPUT; LOG("focused now = %p / %s\n", focused, focused->name); + /* Update the EWMH hints */ + if (changed_num_workspaces) + ewmh_update_workarea(); + ewmh_update_current_desktop(); + ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"focus\"}"); #if 0 diff --git a/src/x.c b/src/x.c index c055f649..64201ead 100644 --- a/src/x.c +++ b/src/x.c @@ -616,6 +616,7 @@ void x_push_changes(Con *con) { } else { DLOG("Updating focus (focused: %p / %s)\n", focused, focused->name); xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, to_focus, XCB_CURRENT_TIME); + ewmh_update_active_window(to_focus); focused_id = to_focus; } }