IPC: Custom 'event' command
Patch status: needinfo
Patch by Paul Grove
To apply this patch, use:
curl http://cr.i3wm.org/patch/274/raw.patch | git am
b/include/commands.h
| 19 |
@@ -289,4 +289,10 @@ void cmd_shmlog(I3_CMD, char *argument); |
| 20 |
*/ |
| 21 |
void cmd_debuglog(I3_CMD, char *argument); |
| 22 |
|
| 23 |
+/** |
| 24 |
+ * Implementation of 'event <name> [data]'. |
| 25 |
+ * |
| 26 |
+ */ |
| 27 |
+void cmd_event(I3_CMD, char *event, char *payload); |
| 28 |
+ |
| 29 |
#endif |
b/include/i3/ipc.h
| 34 |
@@ -102,4 +102,7 @@ typedef struct i3_ipc_header {
|
| 35 |
/** Bar config update will be triggered to update the bar config */ |
| 36 |
#define I3_IPC_EVENT_BARCONFIG_UPDATE (I3_IPC_EVENT_MASK | 4) |
| 37 |
|
| 38 |
+/** Custom event channel for events send via the event command */ |
| 39 |
+#define I3_IPC_EVENT_CUSTOM (I3_IPC_EVENT_MASK | 5) |
| 40 |
+ |
| 41 |
#endif |
b/parser-specs/commands.spec
| 46 |
@@ -39,6 +39,7 @@ state INITIAL: |
| 47 |
'scratchpad' -> SCRATCHPAD |
| 48 |
'mode' -> MODE |
| 49 |
'bar' -> BAR |
| 50 |
+ 'event' -> EVENT |
| 51 |
|
| 52 |
state CRITERIA: |
| 53 |
ctype = 'class' -> CRITERION |
| 54 |
@@ -362,3 +363,12 @@ state BAR_W_ID: |
| 55 |
-> |
| 56 |
end |
| 57 |
-> call cmd_bar($bar_type, $bar_value, $bar_id) |
| 58 |
+ |
| 59 |
+# event <event> [payload] |
| 60 |
+state EVENT: |
| 61 |
+ event = word |
| 62 |
+ -> EVENT_PAYLOAD |
| 63 |
+ |
| 64 |
+state EVENT_PAYLOAD: |
| 65 |
+ payload = string |
| 66 |
+ -> call cmd_event($event, $payload) |
b/src/commands.c
| 71 |
@@ -2044,3 +2044,33 @@ void cmd_debuglog(I3_CMD, char *argument) {
|
| 72 |
// XXX: default reply for now, make this a better reply |
| 73 |
ysuccess(true); |
| 74 |
} |
| 75 |
+ |
| 76 |
+/* |
| 77 |
+ * Implementation of 'event <event_name> [event_data]'. |
| 78 |
+ * |
| 79 |
+ */ |
| 80 |
+void cmd_event (I3_CMD, char *event, char *payload) {
|
| 81 |
+ const unsigned char *payload_json; |
| 82 |
+#if YAJL_MAJOR >= 2 |
| 83 |
+ size_t length; |
| 84 |
+ yajl_gen gen = yajl_gen_alloc(NULL); |
| 85 |
+#else |
| 86 |
+ unsigned int length; |
| 87 |
+ yajl_gen gen = yajl_gen_alloc(NULL, NULL); |
| 88 |
+#endif |
| 89 |
+ |
| 90 |
+ yajl_gen_map_open(gen); |
| 91 |
+ yajl_gen_string(gen, (unsigned char*)"event", strlen("event"));
|
| 92 |
+ yajl_gen_string(gen, (unsigned char*)event, strlen(event)); |
| 93 |
+ yajl_gen_string(gen, (unsigned char*)"payload", strlen("payload"));
|
| 94 |
+ yajl_gen_string(gen, (unsigned char*)payload, strlen(payload)); |
| 95 |
+ yajl_gen_map_close(gen); |
| 96 |
+ yajl_gen_get_buf(gen, &payload_json, &length); |
| 97 |
+ |
| 98 |
+ ipc_send_event(event, I3_IPC_EVENT_CUSTOM, (const char *)payload_json); |
| 99 |
+ |
| 100 |
+ yajl_gen_free(gen); |
| 101 |
+ |
| 102 |
+ ysuccess(true); |
| 103 |
+} |
| 104 |
+ |
b/testcases/t/187-commands-parser.t
| 109 |
@@ -144,7 +144,7 @@ is(parser_calls("\nworkspace test"),
|
| 110 |
################################################################################ |
| 111 |
|
| 112 |
is(parser_calls('unknown_literal'),
|
| 113 |
- "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" . |
| 114 |
+ "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar', 'event'\n" . |
| 115 |
"ERROR: Your command: unknown_literal\n" . |
| 116 |
"ERROR: ^^^^^^^^^^^^^^^", |
| 117 |
'error for unknown literal ok'); |
b/testcases/t/212-cmd_event.t
| 123 |
@@ -0,0 +1,52 @@ |
| 124 |
+#!perl |
| 125 |
+# vim:ts=4:sw=4:expandtab |
| 126 |
+# |
| 127 |
+# Please read the following documents before working on tests: |
| 128 |
+# • http://build.i3wm.org/docs/testsuite.html |
| 129 |
+# (or docs/testsuite) |
| 130 |
+# |
| 131 |
+# • http://build.i3wm.org/docs/lib-i3test.html |
| 132 |
+# (alternatively: perldoc ./testcases/lib/i3test.pm) |
| 133 |
+# |
| 134 |
+# • http://build.i3wm.org/docs/ipc.html |
| 135 |
+# (or docs/ipc) |
| 136 |
+# |
| 137 |
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf |
| 138 |
+# (unless you are already familiar with Perl) |
| 139 |
+ |
| 140 |
+use i3test; |
| 141 |
+ |
| 142 |
+use Data::Dumper; |
| 143 |
+ |
| 144 |
+SKIP: {
|
| 145 |
+ |
| 146 |
+ skip "AnyEvent::I3 too old (need >= 0.16)", 1 if $AnyEvent::I3::VERSION < 0.16; |
| 147 |
+ |
| 148 |
+ my $i3 = i3(get_socket_path()); |
| 149 |
+ $i3->connect()->recv; |
| 150 |
+ |
| 151 |
+ ######## |
| 152 |
+ # cmd_event |
| 153 |
+ ######## |
| 154 |
+ |
| 155 |
+ my $condvar = AnyEvent->condvar; |
| 156 |
+ |
| 157 |
+ my $event_name = "testevent"; |
| 158 |
+ my $event_payload = "Test Text"; |
| 159 |
+ |
| 160 |
+ $i3->subscribe({
|
| 161 |
+ $event_name => sub {
|
| 162 |
+ my ($event) = @_; |
| 163 |
+ $condvar->send($event->{event} eq $event_name
|
| 164 |
+ && $event->{payload} eq $event_payload);
|
| 165 |
+ } |
| 166 |
+ })->recv; |
| 167 |
+ |
| 168 |
+ cmd "event $event_name \"$event_payload\""; |
| 169 |
+ |
| 170 |
+ my $t; $t = AnyEvent->timer(after => 0.5, cb => sub {$condvar->send(0)});
|
| 171 |
+ |
| 172 |
+ ok($condvar->recv, "Receive custom event"); |
| 173 |
+ |
| 174 |
+} |
| 175 |
+done_testing; |