]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/console/consoled-session.c
treewide: auto-convert the simple cases to log_*_errno()
[thirdparty/systemd.git] / src / console / consoled-session.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <inttypes.h>
24 #include <libudev.h>
25 #include <stdlib.h>
26 #include "consoled.h"
27 #include "grdev.h"
28 #include "hashmap.h"
29 #include "idev.h"
30 #include "list.h"
31 #include "macro.h"
32 #include "sd-bus.h"
33 #include "sd-event.h"
34 #include "sysview.h"
35 #include "util.h"
36
37 static bool session_feed_keyboard(Session *s, idev_data *data) {
38 idev_data_keyboard *kdata = &data->keyboard;
39
40 if (!data->resync && kdata->value == 1 && kdata->n_syms == 1) {
41 uint32_t nr;
42 sysview_seat *seat;
43
44 /* handle VT-switch requests */
45 nr = 0;
46
47 switch (kdata->keysyms[0]) {
48 case XKB_KEY_F1 ... XKB_KEY_F12:
49 if (IDEV_KBDMATCH(kdata,
50 IDEV_KBDMOD_CTRL | IDEV_KBDMOD_ALT,
51 kdata->keysyms[0]))
52 nr = kdata->keysyms[0] - XKB_KEY_F1 + 1;
53 break;
54 case XKB_KEY_XF86Switch_VT_1 ... XKB_KEY_XF86Switch_VT_12:
55 nr = kdata->keysyms[0] - XKB_KEY_XF86Switch_VT_1 + 1;
56 break;
57 }
58
59 if (nr != 0) {
60 seat = sysview_session_get_seat(s->sysview);
61 sysview_seat_switch_to(seat, nr);
62 return true;
63 }
64 }
65
66 return false;
67 }
68
69 static bool session_feed(Session *s, idev_data *data) {
70 switch (data->type) {
71 case IDEV_DATA_KEYBOARD:
72 return session_feed_keyboard(s, data);
73 default:
74 return false;
75 }
76 }
77
78 static int session_idev_fn(idev_session *idev, void *userdata, idev_event *event) {
79 Session *s = userdata;
80
81 switch (event->type) {
82 case IDEV_EVENT_DEVICE_ADD:
83 idev_device_enable(event->device_add.device);
84 break;
85 case IDEV_EVENT_DEVICE_REMOVE:
86 idev_device_disable(event->device_remove.device);
87 break;
88 case IDEV_EVENT_DEVICE_DATA:
89 if (!session_feed(s, &event->device_data.data))
90 workspace_feed(s->active_ws, &event->device_data.data);
91 break;
92 }
93
94 return 0;
95 }
96
97 static void session_grdev_fn(grdev_session *grdev, void *userdata, grdev_event *event) {
98 grdev_display *display;
99 Session *s = userdata;
100 Display *d;
101 int r;
102
103 switch (event->type) {
104 case GRDEV_EVENT_DISPLAY_ADD:
105 display = event->display_add.display;
106
107 r = display_new(&d, s, display);
108 if (r < 0) {
109 log_error("Cannot create display '%s' on '%s': %s",
110 grdev_display_get_name(display), sysview_session_get_name(s->sysview), strerror(-r));
111 break;
112 }
113
114 grdev_display_set_userdata(display, d);
115 workspace_refresh(s->active_ws);
116 break;
117 case GRDEV_EVENT_DISPLAY_REMOVE:
118 display = event->display_remove.display;
119 d = grdev_display_get_userdata(display);
120 if (!d)
121 break;
122
123 display_free(d);
124 workspace_refresh(s->active_ws);
125 break;
126 case GRDEV_EVENT_DISPLAY_CHANGE:
127 display = event->display_remove.display;
128 d = grdev_display_get_userdata(display);
129 if (!d)
130 break;
131
132 display_refresh(d);
133 workspace_refresh(s->active_ws);
134 break;
135 case GRDEV_EVENT_DISPLAY_FRAME:
136 display = event->display_remove.display;
137 d = grdev_display_get_userdata(display);
138 if (!d)
139 break;
140
141 session_dirty(s);
142 break;
143 }
144 }
145
146 static int session_redraw_fn(sd_event_source *src, void *userdata) {
147 Session *s = userdata;
148 Display *d;
149
150 LIST_FOREACH(displays_by_session, d, s->display_list)
151 display_render(d, s->active_ws);
152
153 grdev_session_commit(s->grdev);
154
155 return 0;
156 }
157
158 int session_new(Session **out, Manager *m, sysview_session *session) {
159 _cleanup_(session_freep) Session *s = NULL;
160 int r;
161
162 assert(out);
163 assert(m);
164 assert(session);
165
166 s = new0(Session, 1);
167 if (!s)
168 return -ENOMEM;
169
170 s->manager = m;
171 s->sysview = session;
172
173 r = grdev_session_new(&s->grdev,
174 m->grdev,
175 GRDEV_SESSION_MANAGED,
176 sysview_session_get_name(session),
177 session_grdev_fn,
178 s);
179 if (r < 0)
180 return r;
181
182 r = idev_session_new(&s->idev,
183 m->idev,
184 IDEV_SESSION_MANAGED,
185 sysview_session_get_name(session),
186 session_idev_fn,
187 s);
188 if (r < 0)
189 return r;
190
191 r = workspace_new(&s->my_ws, m);
192 if (r < 0)
193 return r;
194
195 s->active_ws = workspace_attach(s->my_ws, s);
196
197 r = sd_event_add_defer(m->event, &s->redraw_src, session_redraw_fn, s);
198 if (r < 0)
199 return r;
200
201 grdev_session_enable(s->grdev);
202 idev_session_enable(s->idev);
203
204 *out = s;
205 s = NULL;
206 return 0;
207 }
208
209 Session *session_free(Session *s) {
210 if (!s)
211 return NULL;
212
213 assert(!s->display_list);
214
215 sd_event_source_unref(s->redraw_src);
216
217 workspace_detach(s->active_ws, s);
218 workspace_unref(s->my_ws);
219
220 idev_session_free(s->idev);
221 grdev_session_free(s->grdev);
222 free(s);
223
224 return NULL;
225 }
226
227 void session_dirty(Session *s) {
228 int r;
229
230 assert(s);
231
232 r = sd_event_source_set_enabled(s->redraw_src, SD_EVENT_ONESHOT);
233 if (r < 0)
234 log_error_errno(-r, "Cannot enable redraw-source: %m");
235 }
236
237 void session_add_device(Session *s, sysview_device *device) {
238 unsigned int type;
239
240 assert(s);
241 assert(device);
242
243 type = sysview_device_get_type(device);
244 switch (type) {
245 case SYSVIEW_DEVICE_DRM:
246 grdev_session_add_drm(s->grdev, sysview_device_get_ud(device));
247 break;
248 case SYSVIEW_DEVICE_EVDEV:
249 idev_session_add_evdev(s->idev, sysview_device_get_ud(device));
250 break;
251 }
252 }
253
254 void session_remove_device(Session *s, sysview_device *device) {
255 unsigned int type;
256
257 assert(s);
258 assert(device);
259
260 type = sysview_device_get_type(device);
261 switch (type) {
262 case SYSVIEW_DEVICE_DRM:
263 grdev_session_remove_drm(s->grdev, sysview_device_get_ud(device));
264 break;
265 case SYSVIEW_DEVICE_EVDEV:
266 idev_session_remove_evdev(s->idev, sysview_device_get_ud(device));
267 break;
268 }
269 }
270
271 void session_refresh_device(Session *s, sysview_device *device, struct udev_device *ud) {
272 unsigned int type;
273
274 assert(s);
275 assert(device);
276
277 type = sysview_device_get_type(device);
278 switch (type) {
279 case SYSVIEW_DEVICE_DRM:
280 grdev_session_hotplug_drm(s->grdev, sysview_device_get_ud(device));
281 break;
282 }
283 }