-
Notifications
You must be signed in to change notification settings - Fork 1
/
remote.c
145 lines (115 loc) · 3.09 KB
/
remote.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <string.h>
#include <errno.h>
#include "types.h"
#include "platform.h"
#include "misc.h"
/* msgchan attached to stdin & stdout */
struct msgchan stdio_msgchan;
static int initialized = 0;
static void shutdown_remote(void)
{
mc_close(&stdio_msgchan);
if (initialized)
platform_exit();
}
static void enqueue_message(struct message* msg)
{
if (mc_enqueue_message(&stdio_msgchan, msg)) {
/* This isn't likely to actually get anywhere, but... */
errlog("failed to enqueue message\n");
exit(1);
}
}
static void handle_message(const struct message* msg)
{
struct message* resp;
switch (msg->body.type) {
case MT_MOVEREL:
move_mousepos(MB(msg, moverel).dx, MB(msg, moverel).dy);
resp = new_message(MT_MOUSEPOS);
MB(resp, mousepos).pt = get_mousepos();
enqueue_message(resp);
break;
case MT_MOVEABS:
set_mousepos(MB(msg, moveabs).pt);
break;
case MT_CLICKEVENT:
do_clickevent(MB(msg, clickevent).button,
MB(msg, clickevent).pressrel);
break;
case MT_KEYEVENT:
do_keyevent(MB(msg, keyevent).keycode, MB(msg, keyevent).pressrel);
break;
case MT_GETCLIPBOARD:
resp = new_message(MT_SETCLIPBOARD);
MB(resp, setclipboard).text = get_clipboard_text();
enqueue_message(resp);
break;
case MT_SETCLIPBOARD:
set_clipboard_text(MB(msg, setclipboard).text);
break;
case MT_SETBRIGHTNESS:
set_display_brightness(MB(msg, setbrightness).brightness);
break;
case MT_SETLOGLEVEL:
set_loglevel(MB(msg, setloglevel).loglevel);
break;
default:
errlog("unhandled message type: %u\n", msg->body.type);
shutdown_remote();
exit(1);
}
}
/* Initialize the remote after receiving a SETUP message */
static void handle_setup_msg(const struct message* msg)
{
struct message* readymsg;
struct kvmap* params;
if (msg->body.type != MT_SETUP) {
errlog("unexpected message type %u instead of SETUP\n", msg->body.type);
exit(1);
}
if (MB(msg, setup).prot_vers != PROT_VERSION) {
errlog("unsupported protocol version %d\n", MB(msg, setup).prot_vers);
exit(1);
}
set_loglevel(MB(msg, setup).loglevel);
params = unflatten_kvmap(MB(msg, setup).params.params_val,
MB(msg, setup).params.params_len);
if (!params) {
errlog("failed to unflatted remote-params kvmap\n");
exit(1);
}
if (platform_init(params, NULL) < 0) {
errlog("platform_init() failed\n");
exit(1);
}
destroy_kvmap(params);
readymsg = new_message(MT_READY);
get_screen_dimensions(&MB(readymsg, ready).screendim);
enqueue_message(readymsg);
}
/* msgchan callback to handle received messages */
static void mc_read_cb(struct msgchan* mc, struct message* msg, void* arg)
{
if (msg->body.type != MT_MOVEREL)
debug2("received %s\n", msgtype_name(msg->body.type));
if (!initialized) {
handle_setup_msg(msg);
initialized = 1;
} else {
handle_message(msg);
}
}
static void mc_err_cb(struct msgchan* mc, void* arg, int err)
{
errlog("msgchan error, remote terminating: %s\n", strerror(err));
shutdown_remote();
exit(1);
}
void run_remote(void)
{
mc_init(&stdio_msgchan, STDOUT_FILENO, STDIN_FILENO,
mc_read_cb, mc_err_cb, NULL);
run_event_loop();
}