i3 - improved tiling WM


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;