Codebase list i3-gaps / 45feaac
Introduce GET_BINDING_STATE IPC command fixes #3892 Michael Stapelberg 3 years ago
9 changed file(s) with 86 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
100100 use constant TYPE_GET_CONFIG => 9;
101101 use constant TYPE_SEND_TICK => 10;
102102 use constant TYPE_SYNC => 11;
103 use constant TYPE_GET_BINDING_STATE => 12;
103104
104105 our %EXPORT_TAGS = ( 'all' => [
105106 qw(i3 TYPE_RUN_COMMAND TYPE_COMMAND TYPE_GET_WORKSPACES TYPE_SUBSCRIBE TYPE_GET_OUTPUTS
106107 TYPE_GET_TREE TYPE_GET_MARKS TYPE_GET_BAR_CONFIG TYPE_GET_VERSION
107 TYPE_GET_BINDING_MODES TYPE_GET_CONFIG TYPE_SEND_TICK TYPE_SYNC)
108 TYPE_GET_BINDING_MODES TYPE_GET_CONFIG TYPE_SEND_TICK TYPE_SYNC
109 TYPE_GET_BINDING_STATE)
108110 ] );
109111
110112 our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
6565 | 9 | +GET_CONFIG+ | <<_config_reply,CONFIG>> | Returns the last loaded i3 config.
6666 | 10 | +SEND_TICK+ | <<_tick_reply,TICK>> | Sends a tick event with the specified payload.
6767 | 11 | +SYNC+ | <<_sync_reply,SYNC>> | Sends an i3 sync event with the specified random value to the specified window.
68 | 12 | +GET_BINDING_STATE+ | <<_binding_state_reply,BINDING_STATE>> | Request the current binding state, e.g. the currently active binding mode name.
6869 |======================================================
6970
7071 So, a typical message could look like this:
130131 Reply to the GET_CONFIG message.
131132 TICK (10)::
132133 Reply to the SEND_TICK message.
134 GET_BINDING_STATE (12)::
135 Reply to the GET_BINDING_STATE message.
133136
134137 [[_command_reply]]
135138 === COMMAND reply
708711 { "success": true }
709712 -------------------
710713
714 [[_binding_state_reply]]
715 === GET_BINDING_STATE reply
716
717 The binding_state reply is a map which currently only contains the "name"
718 member, which is the name of the currently active binding mode as a string.
719
720 *Example:*
721 -------------------
722 { "name": "default" }
723 -------------------
724
711725 == Events
712726
713727 [[events]]
6565 /** Trigger an i3 sync protocol message via IPC. */
6666 #define I3_IPC_MESSAGE_TYPE_SYNC 11
6767
68 /** Request the current binding state. */
69 #define I3_IPC_MESSAGE_TYPE_GET_BINDING_STATE 12
70
6871 /*
6972 * Messages from i3 to clients
7073 *
8184 #define I3_IPC_REPLY_TYPE_CONFIG 9
8285 #define I3_IPC_REPLY_TYPE_TICK 10
8386 #define I3_IPC_REPLY_TYPE_SYNC 11
87 #define I3_IPC_REPLY_TYPE_GET_BINDING_STATE 12
8488
8589 /*
8690 * Events from i3 to clients. Events have the first bit set high.
5757 extern Display *xlibdpy, *xkbdpy;
5858 extern int xkb_current_group;
5959 extern TAILQ_HEAD(bindings_head, Binding) * bindings;
60 extern const char *current_binding_mode;
6061 extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
6162 extern TAILQ_HEAD(autostarts_always_head, Autostart) autostarts_always;
6263 extern TAILQ_HEAD(ws_assignments_head, Workspace_Assignment) ws_assignments;
627627
628628 ungrab_all_keys(conn);
629629 bindings = mode->bindings;
630 current_binding_mode = mode->name;
630631 translate_keysyms();
631632 grab_all_keys(conn);
632633
173173 SLIST_INSERT_HEAD(&modes, default_mode, modes);
174174
175175 bindings = default_mode->bindings;
176 current_binding_mode = default_mode->name;
176177
177178 /* Clear the old config or initialize the data structure */
178179 memset(&config, 0, sizeof(config));
13361336 ipc_send_client_message(client, strlen(reply), I3_IPC_REPLY_TYPE_SYNC, (const uint8_t *)reply);
13371337 }
13381338
1339 IPC_HANDLER(get_binding_state) {
1340 yajl_gen gen = ygenalloc();
1341
1342 y(map_open);
1343
1344 ystr("name");
1345 ystr(current_binding_mode);
1346
1347 y(map_close);
1348
1349 const unsigned char *payload;
1350 ylength length;
1351 y(get_buf, &payload, &length);
1352
1353 ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_GET_BINDING_STATE, payload);
1354 y(free);
1355 }
1356
13391357 /* The index of each callback function corresponds to the numeric
13401358 * value of the message type (see include/i3/ipc.h) */
1341 handler_t handlers[12] = {
1359 handler_t handlers[13] = {
13421360 handle_run_command,
13431361 handle_get_workspaces,
13441362 handle_subscribe,
13511369 handle_get_config,
13521370 handle_send_tick,
13531371 handle_sync,
1372 handle_get_binding_state,
13541373 };
13551374
13561375 /*
7878
7979 /* The list of key bindings */
8080 struct bindings_head *bindings;
81 const char *current_binding_mode = NULL;
8182
8283 /* The list of exec-lines */
8384 struct autostarts_head autostarts = TAILQ_HEAD_INITIALIZER(autostarts);
0 #!perl
1 # vim:ts=4:sw=4:expandtab
2 #
3 # Please read the following documents before working on tests:
4 # • https://build.i3wm.org/docs/testsuite.html
5 # (or docs/testsuite)
6 #
7 # • https://build.i3wm.org/docs/lib-i3test.html
8 # (alternatively: perldoc ./testcases/lib/i3test.pm)
9 #
10 # • https://build.i3wm.org/docs/ipc.html
11 # (or docs/ipc)
12 #
13 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
14 # (unless you are already familiar with Perl)
15 #
16 # Verifies the GET_BINDING_MODE IPC command
17 # Ticket: #3892
18 # Bug still in: 4.18-318-g50160eb1
19 use i3test i3_config => <<EOT;
20 # i3 config file (v4)
21 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
22
23 mode "extra" {
24 bindsym Mod1+x nop foo
25 }
26 EOT
27
28 my $i3 = i3(get_socket_path());
29 $i3->connect->recv;
30 # TODO: use the symbolic name for the command/reply type instead of the
31 # numerical 12:
32 my $binding_state = $i3->message(12, "")->recv;
33 is($binding_state->{name}, 'default', 'at startup, binding mode is default');
34
35 cmd 'mode extra';
36
37 $binding_state = $i3->message(12, "")->recv;
38 is($binding_state->{name}, 'extra', 'after switching, binding mode is extra');
39
40 done_testing;