From 4205973135f28a0ab0e25a63dbc8c6fff0d3539e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 22 Jun 2014 15:20:14 -0400 Subject: [PATCH] feature: implement ewmh desktop viewport property Set and update the _NET_DESKTOP_VIEWPORT property http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140146176862048 > _NET_DESKTOP_VIEWPORT x, y, CARDINAL[][2]/32 > Array of pairs of cardinals that define the top left corner of each > desktop's viewport. --- include/atoms.xmacro | 1 + include/ewmh.h | 6 ++++++ src/ewmh.c | 39 ++++++++++++++++++++++++++++++++++++++- src/main.c | 1 + src/workspace.c | 2 ++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/atoms.xmacro b/include/atoms.xmacro index 12e9ee28..ccae87c5 100644 --- a/include/atoms.xmacro +++ b/include/atoms.xmacro @@ -17,6 +17,7 @@ xmacro(_NET_CLIENT_LIST) xmacro(_NET_CLIENT_LIST_STACKING) xmacro(_NET_CURRENT_DESKTOP) xmacro(_NET_NUMBER_OF_DESKTOPS) +xmacro(_NET_DESKTOP_VIEWPORT) xmacro(_NET_ACTIVE_WINDOW) xmacro(_NET_STARTUP_ID) xmacro(_NET_WORKAREA) diff --git a/include/ewmh.h b/include/ewmh.h index 38d612da..99ff655e 100644 --- a/include/ewmh.h +++ b/include/ewmh.h @@ -24,6 +24,12 @@ void ewmh_update_current_desktop(void); */ void ewmh_update_number_of_desktops(void); +/** + * Updates _NET_DESKTOP_VIEWPORT, which is an array of pairs of cardinals that + * define the top left corner of each desktop's viewport. + */ +void ewmh_update_desktop_viewport(void); + /** * Updates _NET_ACTIVE_WINDOW with the currently focused window. * diff --git a/src/ewmh.c b/src/ewmh.c index 3ef79937..433a202b 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -61,6 +61,43 @@ void ewmh_update_number_of_desktops(void) { A__NET_NUMBER_OF_DESKTOPS, XCB_ATOM_CARDINAL, 32, 1, &idx); } +/* + * Updates _NET_DESKTOP_VIEWPORT, which is an array of pairs of cardinals that + * define the top left corner of each desktop's viewport. + */ +void ewmh_update_desktop_viewport(void) { + Con *output; + int num_desktops = 0; + /* count number of desktops */ + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + if (STARTS_WITH(ws->name, "__")) + continue; + + num_desktops++; + } + } + + uint32_t viewports[num_desktops * 2]; + + int current_position = 0; + /* fill the viewport buffer */ + TAILQ_FOREACH(output, &(croot->nodes_head), nodes) { + Con *ws; + TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) { + if (STARTS_WITH(ws->name, "__")) + continue; + + viewports[current_position++] = output->rect.x; + viewports[current_position++] = output->rect.y; + } + } + + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, + A__NET_DESKTOP_VIEWPORT, XCB_ATOM_CARDINAL, 32, current_position, &viewports); +} + /* * Updates _NET_ACTIVE_WINDOW with the currently focused window. * @@ -159,5 +196,5 @@ void ewmh_setup_hints(void) { /* I’m not entirely sure if we need to keep _NET_WM_NAME on root. */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3"); - xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 19, supported_atoms); + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 20, supported_atoms); } diff --git a/src/main.c b/src/main.c index ac112446..67024e6e 100644 --- a/src/main.c +++ b/src/main.c @@ -674,6 +674,7 @@ int main(int argc, char *argv[]) { /* Set the ewmh desktop properties. */ ewmh_update_current_desktop(); ewmh_update_number_of_desktops(); + ewmh_update_desktop_viewport(); struct ev_io *xcb_watcher = scalloc(sizeof(struct ev_io)); xcb_check = scalloc(sizeof(struct ev_check)); diff --git a/src/workspace.c b/src/workspace.c index 54a2bd33..2dcab4fa 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -93,6 +93,7 @@ Con *workspace_get(const char *num, bool *created) { ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}"); ewmh_update_number_of_desktops(); + ewmh_update_desktop_viewport(); if (created != NULL) *created = true; } else if (created != NULL) { @@ -418,6 +419,7 @@ static void _workspace_show(Con *workspace) { tree_close(old, DONT_KILL_WINDOW, false, false); ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}"); ewmh_update_number_of_desktops(); + ewmh_update_desktop_viewport(); } }