Include workspace con in workspace event
Send the affected workspace in the "current" property for each workspace event for any type of workspace event that affects a particular workspace. fixes #1411
This commit is contained in:
parent
04fa40d3e5
commit
823b46a544
17
docs/ipc
17
docs/ipc
|
@ -668,15 +668,16 @@ if ($is_event) {
|
||||||
|
|
||||||
This event consists of a single serialized map containing a property
|
This event consists of a single serialized map containing a property
|
||||||
+change (string)+ which indicates the type of the change ("focus", "init",
|
+change (string)+ which indicates the type of the change ("focus", "init",
|
||||||
"empty", "urgent").
|
"empty", "urgent"). A +current (object)+ property will be present with the
|
||||||
|
affected workspace whenever the type of event affects a workspace (otherwise,
|
||||||
|
it will be +null).
|
||||||
|
|
||||||
Moreover, when the change is "focus", an +old (object)+ and a +current
|
When the change is "focus", an +old (object)+ property will be present with the
|
||||||
(object)+ properties will be present with the previous and current
|
previous workspace. When the first switch occurs (when i3 focuses the
|
||||||
workspace respectively. When the first switch occurs (when i3 focuses
|
workspace visible at the beginning) there is no previous workspace, and the
|
||||||
the workspace visible at the beginning) there is no previous
|
+old+ property will be set to +null+. Also note that if the previous is empty
|
||||||
workspace, and the +old+ property will be set to +null+. Also note
|
it will get destroyed when switching, but will still be present in the "old"
|
||||||
that if the previous is empty it will get destroyed when switching,
|
property.
|
||||||
but will still be present in the "old" property.
|
|
||||||
|
|
||||||
*Example:*
|
*Example:*
|
||||||
---------------------
|
---------------------
|
||||||
|
|
|
@ -89,11 +89,17 @@ void ipc_shutdown(void);
|
||||||
void dump_node(yajl_gen gen, Con *con, bool inplace_restart);
|
void dump_node(yajl_gen gen, Con *con, bool inplace_restart);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the workspace "focus" event we send, along the usual "change" field,
|
* Generates a json workspace event. Returns a dynamically allocated yajl
|
||||||
* also the current and previous workspace, in "current" and "old"
|
* generator. Free with yajl_gen_free().
|
||||||
* respectively.
|
|
||||||
*/
|
*/
|
||||||
void ipc_send_workspace_focus_event(Con *current, Con *old);
|
yajl_gen ipc_marshal_workspace_event(const char *change, Con *current, Con *old);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the workspace events we send, along with the usual "change" field, also
|
||||||
|
* the workspace container in "current". For focus events, we send the
|
||||||
|
* previously focused workspace in "old".
|
||||||
|
*/
|
||||||
|
void ipc_send_workspace_event(const char *change, Con *current, Con *old);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the window events we send, along the usual "change" field,
|
* For the window events we send, along the usual "change" field,
|
||||||
|
|
|
@ -944,7 +944,7 @@ void cmd_append_layout(I3_CMD, char *path) {
|
||||||
restore_open_placeholder_windows(parent);
|
restore_open_placeholder_windows(parent);
|
||||||
|
|
||||||
if (content == JSON_CONTENT_WORKSPACE)
|
if (content == JSON_CONTENT_WORKSPACE)
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"restored\"}");
|
ipc_send_workspace_event("restored", parent, NULL);
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
}
|
}
|
||||||
|
@ -1313,7 +1313,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
||||||
create_workspace_on_output(current_output, ws->parent);
|
create_workspace_on_output(current_output, ws->parent);
|
||||||
|
|
||||||
/* notify the IPC listeners */
|
/* notify the IPC listeners */
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
|
ipc_send_workspace_event("init", ws, NULL);
|
||||||
}
|
}
|
||||||
DLOG("Detaching\n");
|
DLOG("Detaching\n");
|
||||||
|
|
||||||
|
@ -1334,7 +1334,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
|
||||||
TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
|
TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
|
||||||
floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
|
floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
|
||||||
|
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"move\"}");
|
ipc_send_workspace_event("move", ws, NULL);
|
||||||
if (workspace_was_visible) {
|
if (workspace_was_visible) {
|
||||||
/* Focus the moved workspace on the destination output. */
|
/* Focus the moved workspace on the destination output. */
|
||||||
workspace_show(ws);
|
workspace_show(ws);
|
||||||
|
@ -1761,7 +1761,7 @@ void cmd_reload(I3_CMD) {
|
||||||
load_configuration(conn, NULL, true);
|
load_configuration(conn, NULL, true);
|
||||||
x_set_i3_atoms();
|
x_set_i3_atoms();
|
||||||
/* Send an IPC event just in case the ws names have changed */
|
/* Send an IPC event just in case the ws names have changed */
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"reload\"}");
|
ipc_send_workspace_event("reload", NULL, NULL);
|
||||||
/* Send an update event for the barconfig just in case it has changed */
|
/* Send an update event for the barconfig just in case it has changed */
|
||||||
update_barconfig();
|
update_barconfig();
|
||||||
|
|
||||||
|
@ -2040,7 +2040,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
ysuccess(true);
|
ysuccess(true);
|
||||||
|
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"rename\"}");
|
ipc_send_workspace_event("rename", workspace, NULL);
|
||||||
ewmh_update_desktop_names();
|
ewmh_update_desktop_names();
|
||||||
ewmh_update_desktop_viewport();
|
ewmh_update_desktop_viewport();
|
||||||
ewmh_update_current_desktop();
|
ewmh_update_current_desktop();
|
||||||
|
|
10
src/con.c
10
src/con.c
|
@ -12,6 +12,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
#include "yajl_utils.h"
|
||||||
|
|
||||||
static void con_on_remove_child(Con *con);
|
static void con_on_remove_child(Con *con);
|
||||||
|
|
||||||
|
@ -1435,8 +1436,15 @@ static void con_on_remove_child(Con *con) {
|
||||||
if (con->type == CT_WORKSPACE) {
|
if (con->type == CT_WORKSPACE) {
|
||||||
if (TAILQ_EMPTY(&(con->focus_head)) && !workspace_is_visible(con)) {
|
if (TAILQ_EMPTY(&(con->focus_head)) && !workspace_is_visible(con)) {
|
||||||
LOG("Closing old workspace (%p / %s), it is empty\n", con, con->name);
|
LOG("Closing old workspace (%p / %s), it is empty\n", con, con->name);
|
||||||
|
yajl_gen gen = ipc_marshal_workspace_event("empty", con, NULL);
|
||||||
tree_close(con, DONT_KILL_WINDOW, false, false);
|
tree_close(con, DONT_KILL_WINDOW, false, false);
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
|
|
||||||
|
const unsigned char *payload;
|
||||||
|
ylength length;
|
||||||
|
y(get_buf, &payload, &length);
|
||||||
|
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
|
||||||
|
|
||||||
|
y(free);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
27
src/ipc.c
27
src/ipc.c
|
@ -1120,20 +1120,22 @@ int ipc_create_socket(const char *filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the workspace "focus" event we send, along the usual "change" field,
|
* Generates a json workspace event. Returns a dynamically allocated yajl
|
||||||
* also the current and previous workspace, in "current" and "old"
|
* generator. Free with yajl_gen_free().
|
||||||
* respectively.
|
|
||||||
*/
|
*/
|
||||||
void ipc_send_workspace_focus_event(Con *current, Con *old) {
|
yajl_gen ipc_marshal_workspace_event(const char *change, Con *current, Con *old) {
|
||||||
setlocale(LC_NUMERIC, "C");
|
setlocale(LC_NUMERIC, "C");
|
||||||
yajl_gen gen = ygenalloc();
|
yajl_gen gen = ygenalloc();
|
||||||
|
|
||||||
y(map_open);
|
y(map_open);
|
||||||
|
|
||||||
ystr("change");
|
ystr("change");
|
||||||
ystr("focus");
|
ystr(change);
|
||||||
|
|
||||||
ystr("current");
|
ystr("current");
|
||||||
|
if (current == NULL)
|
||||||
|
y(null);
|
||||||
|
else
|
||||||
dump_node(gen, current, false);
|
dump_node(gen, current, false);
|
||||||
|
|
||||||
ystr("old");
|
ystr("old");
|
||||||
|
@ -1144,13 +1146,26 @@ void ipc_send_workspace_focus_event(Con *current, Con *old) {
|
||||||
|
|
||||||
y(map_close);
|
y(map_close);
|
||||||
|
|
||||||
|
setlocale(LC_NUMERIC, "");
|
||||||
|
|
||||||
|
return gen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the workspace events we send, along with the usual "change" field, also
|
||||||
|
* the workspace container in "current". For focus events, we send the
|
||||||
|
* previously focused workspace in "old".
|
||||||
|
*/
|
||||||
|
void ipc_send_workspace_event(const char *change, Con *current, Con *old) {
|
||||||
|
yajl_gen gen = ipc_marshal_workspace_event(change, current, old);
|
||||||
|
|
||||||
const unsigned char *payload;
|
const unsigned char *payload;
|
||||||
ylength length;
|
ylength length;
|
||||||
y(get_buf, &payload, &length);
|
y(get_buf, &payload, &length);
|
||||||
|
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
|
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
|
||||||
|
|
||||||
y(free);
|
y(free);
|
||||||
setlocale(LC_NUMERIC, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -128,7 +128,7 @@ static void move_to_output_directed(Con *con, direction_t direction) {
|
||||||
|
|
||||||
tree_flatten(croot);
|
tree_flatten(croot);
|
||||||
|
|
||||||
ipc_send_workspace_focus_event(ws, old_ws);
|
ipc_send_workspace_event("focus", ws, old_ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
#include "yajl_utils.h"
|
||||||
|
|
||||||
/* Stores a copy of the name of the last used workspace for the workspace
|
/* Stores a copy of the name of the last used workspace for the workspace
|
||||||
* back-and-forth switching. */
|
* back-and-forth switching. */
|
||||||
|
@ -91,7 +92,7 @@ Con *workspace_get(const char *num, bool *created) {
|
||||||
|
|
||||||
con_attach(workspace, content, false);
|
con_attach(workspace, content, false);
|
||||||
|
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
|
ipc_send_workspace_event("init", workspace, NULL);
|
||||||
ewmh_update_number_of_desktops();
|
ewmh_update_number_of_desktops();
|
||||||
ewmh_update_desktop_names();
|
ewmh_update_desktop_names();
|
||||||
ewmh_update_desktop_viewport();
|
ewmh_update_desktop_viewport();
|
||||||
|
@ -409,7 +410,7 @@ static void _workspace_show(Con *workspace) {
|
||||||
} else
|
} else
|
||||||
con_focus(next);
|
con_focus(next);
|
||||||
|
|
||||||
ipc_send_workspace_focus_event(workspace, current);
|
ipc_send_workspace_event("focus", workspace, current);
|
||||||
|
|
||||||
DLOG("old = %p / %s\n", old, (old ? old->name : "(null)"));
|
DLOG("old = %p / %s\n", old, (old ? old->name : "(null)"));
|
||||||
/* Close old workspace if necessary. This must be done *after* doing
|
/* Close old workspace if necessary. This must be done *after* doing
|
||||||
|
@ -421,8 +422,16 @@ static void _workspace_show(Con *workspace) {
|
||||||
/* check if this workspace is currently visible */
|
/* check if this workspace is currently visible */
|
||||||
if (!workspace_is_visible(old)) {
|
if (!workspace_is_visible(old)) {
|
||||||
LOG("Closing old workspace (%p / %s), it is empty\n", old, old->name);
|
LOG("Closing old workspace (%p / %s), it is empty\n", old, old->name);
|
||||||
|
yajl_gen gen = ipc_marshal_workspace_event("empty", old, NULL);
|
||||||
tree_close(old, DONT_KILL_WINDOW, false, false);
|
tree_close(old, DONT_KILL_WINDOW, false, false);
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
|
|
||||||
|
const unsigned char *payload;
|
||||||
|
ylength length;
|
||||||
|
y(get_buf, &payload, &length);
|
||||||
|
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
|
||||||
|
|
||||||
|
y(free);
|
||||||
|
|
||||||
ewmh_update_number_of_desktops();
|
ewmh_update_number_of_desktops();
|
||||||
ewmh_update_desktop_names();
|
ewmh_update_desktop_names();
|
||||||
ewmh_update_desktop_viewport();
|
ewmh_update_desktop_viewport();
|
||||||
|
@ -766,7 +775,7 @@ void workspace_update_urgent_flag(Con *ws) {
|
||||||
DLOG("Workspace urgency flag changed from %d to %d\n", old_flag, ws->urgent);
|
DLOG("Workspace urgency flag changed from %d to %d\n", old_flag, ws->urgent);
|
||||||
|
|
||||||
if (old_flag != ws->urgent)
|
if (old_flag != ws->urgent)
|
||||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"urgent\"}");
|
ipc_send_workspace_event("urgent", ws, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -23,7 +23,7 @@ $i3->connect()->recv;
|
||||||
# Workspaces requests and events
|
# Workspaces requests and events
|
||||||
################################
|
################################
|
||||||
|
|
||||||
my $focused = get_ws(focused_ws());
|
my $old_ws = get_ws(focused_ws());
|
||||||
|
|
||||||
# Events
|
# Events
|
||||||
|
|
||||||
|
@ -36,15 +36,11 @@ $i3->subscribe({
|
||||||
workspace => sub {
|
workspace => sub {
|
||||||
my ($event) = @_;
|
my ($event) = @_;
|
||||||
if ($event->{change} eq 'init') {
|
if ($event->{change} eq 'init') {
|
||||||
$init->send(1);
|
$init->send($event);
|
||||||
} elsif ($event->{change} eq 'focus') {
|
} elsif ($event->{change} eq 'focus') {
|
||||||
# Check that we have the old and new workspace
|
$focus->send($event);
|
||||||
$focus->send(
|
|
||||||
$event->{current}->{name} == '2' &&
|
|
||||||
$event->{old}->{name} == $focused->{name}
|
|
||||||
);
|
|
||||||
} elsif ($event->{change} eq 'empty') {
|
} elsif ($event->{change} eq 'empty') {
|
||||||
$empty->send(1);
|
$empty->send($event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})->recv;
|
})->recv;
|
||||||
|
@ -61,8 +57,20 @@ $t = AnyEvent->timer(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ok($init->recv, 'Workspace "init" event received');
|
my $init_event = $init->recv;
|
||||||
ok($focus->recv, 'Workspace "focus" event received');
|
my $focus_event = $focus->recv;
|
||||||
ok($empty->recv, 'Workspace "empty" event received');
|
my $empty_event = $empty->recv;
|
||||||
|
|
||||||
|
my $current_ws = get_ws(focused_ws());
|
||||||
|
|
||||||
|
ok($init_event, 'workspace "init" event received');
|
||||||
|
is($init_event->{current}->{id}, $current_ws->{id}, 'the "current" property should contain the initted workspace con');
|
||||||
|
|
||||||
|
ok($focus_event, 'workspace "focus" event received');
|
||||||
|
is($focus_event->{current}->{id}, $current_ws->{id}, 'the "current" property should contain the focused workspace con');
|
||||||
|
is($focus_event->{old}->{id}, $old_ws->{id}, 'the "old" property should contain the workspace con that was focused last');
|
||||||
|
|
||||||
|
ok($empty_event, 'workspace "empty" event received');
|
||||||
|
is($empty_event->{current}->{id}, $old_ws->{id}, 'the "current" property should contain the emptied workspace con');
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
|
|
@ -50,6 +50,7 @@ subtest 'Workspace empty event upon switch', sub {
|
||||||
|
|
||||||
my $event = $cond->recv;
|
my $event = $cond->recv;
|
||||||
is($event->{change}, 'empty', '"Empty" event received upon workspace switch');
|
is($event->{change}, 'empty', '"Empty" event received upon workspace switch');
|
||||||
|
is($event->{current}->{name}, $ws1, '"current" property should be set to the workspace con');
|
||||||
};
|
};
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -116,6 +117,7 @@ subtest 'Workspace empty event upon window close', sub {
|
||||||
|
|
||||||
my $event = $cond->recv;
|
my $event = $cond->recv;
|
||||||
is($event->{change}, 'empty', '"Empty" event received upon window close');
|
is($event->{change}, 'empty', '"Empty" event received upon window close');
|
||||||
|
is($event->{current}->{name}, $ws1, '"current" property should be set to the workspace con');
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue