diff --git a/src/handlers.c b/src/handlers.c index 5d21a985..65fa46a0 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -806,6 +806,38 @@ static void handle_client_message(xcb_client_message_event_t *event) { DLOG("Not handling WM_CHANGE_STATE request. (window = %d, state = %d)\n", event->window, event->data.data32[0]); } + } else if (event->type == A__NET_CURRENT_DESKTOP) { + /* This request is used by pagers and bars to change the current + * desktop likely as a result of some user action. We interpret this as + * a request to focus the given workspace. See + * http://standards.freedesktop.org/wm-spec/latest/ar01s03.html#idm140251368135008 + * */ + Con *output; + uint32_t idx = 0; + DLOG("Request to change current desktop to index %d\n", event->data.data32[0]); + + 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; + + if (idx == event->data.data32[0]) { + /* data32[1] is a timestamp used to prevent focus race conditions */ + if (event->data.data32[1]) + last_timestamp = event->data.data32[1]; + + DLOG("Handling request to focus workspace %s\n", ws->name); + + workspace_show(ws); + tree_render(); + + return; + } + + ++idx; + } + } } else { DLOG("unhandled clientmessage\n"); return; diff --git a/testcases/t/217-NET_CURRENT_DESKTOP.t b/testcases/t/217-NET_CURRENT_DESKTOP.t index fe2ea675..7ca6fbc2 100644 --- a/testcases/t/217-NET_CURRENT_DESKTOP.t +++ b/testcases/t/217-NET_CURRENT_DESKTOP.t @@ -71,6 +71,40 @@ is(current_desktop_index, 1, "Open on 0 and view 1"); cmd 'workspace 2'; is(current_desktop_index, 2, "Open and view empty"); +######################################################### +# Test the _NET_CURRENT_DESKTOP client request +# This request is sent by pagers and bars to switch the current desktop (which +# is like an ersatz workspace) to the given index +######################################################### + +sub send_current_desktop_request { + my ($idx) = @_; + + my $msg = pack "CCSLLLLLL", + X11::XCB::CLIENT_MESSAGE, # response_type + 32, # format + 0, # sequence + 0, + $_NET_CURRENT_DESKTOP, + $idx, # data32[0] (the desktop index) + 0, # data32[1] (can be a timestamp) + 0, # data32[2] + 0, # data32[3] + 0; # data32[4] + + $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg); +} + +send_current_desktop_request(1); +is(current_desktop_index, 1, 'current desktop request switched to desktop 1'); +# note that _NET_CURRENT_DESKTOP is an index and that in this case, workspace 1 +# is at index 1 as a convenience for the test +is(focused_ws, '1', 'current desktop request switched to workspace 1'); + +send_current_desktop_request(0); +is(current_desktop_index, 0, 'current desktop request switched to desktop 0'); +is(focused_ws, '0', 'current desktop request switched to workspace 0'); + exit_gracefully($pid); done_testing;