chiark / gitweb /
remove unused includes
[elogind.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 <stdlib.h>
24 #include "consoled.h"
25 #include "grdev.h"
26 #include "idev.h"
27 #include "list.h"
28 #include "macro.h"
29 #include "sd-event.h"
30 #include "sysview.h"
31 #include "util.h"
32
33 static bool session_feed_keyboard(Session *s, idev_data *data) {
34         idev_data_keyboard *kdata = &data->keyboard;
35
36         if (!data->resync && kdata->value == 1 && kdata->n_syms == 1) {
37                 uint32_t nr;
38                 sysview_seat *seat;
39
40                 /* handle VT-switch requests */
41                 nr = 0;
42
43                 switch (kdata->keysyms[0]) {
44                 case XKB_KEY_F1 ... XKB_KEY_F12:
45                         if (IDEV_KBDMATCH(kdata,
46                                           IDEV_KBDMOD_CTRL | IDEV_KBDMOD_ALT,
47                                           kdata->keysyms[0]))
48                                 nr = kdata->keysyms[0] - XKB_KEY_F1 + 1;
49                         break;
50                 case XKB_KEY_XF86Switch_VT_1 ... XKB_KEY_XF86Switch_VT_12:
51                         nr = kdata->keysyms[0] - XKB_KEY_XF86Switch_VT_1 + 1;
52                         break;
53                 }
54
55                 if (nr != 0) {
56                         seat = sysview_session_get_seat(s->sysview);
57                         sysview_seat_switch_to(seat, nr);
58                         return true;
59                 }
60         }
61
62         return false;
63 }
64
65 static bool session_feed(Session *s, idev_data *data) {
66         switch (data->type) {
67         case IDEV_DATA_KEYBOARD:
68                 return session_feed_keyboard(s, data);
69         default:
70                 return false;
71         }
72 }
73
74 static int session_idev_fn(idev_session *idev, void *userdata, idev_event *event) {
75         Session *s = userdata;
76
77         switch (event->type) {
78         case IDEV_EVENT_DEVICE_ADD:
79                 idev_device_enable(event->device_add.device);
80                 break;
81         case IDEV_EVENT_DEVICE_REMOVE:
82                 idev_device_disable(event->device_remove.device);
83                 break;
84         case IDEV_EVENT_DEVICE_DATA:
85                 if (!session_feed(s, &event->device_data.data))
86                         workspace_feed(s->active_ws, &event->device_data.data);
87                 break;
88         }
89
90         return 0;
91 }
92
93 static void session_grdev_fn(grdev_session *grdev, void *userdata, grdev_event *event) {
94         grdev_display *display;
95         Session *s = userdata;
96         Display *d;
97         int r;
98
99         switch (event->type) {
100         case GRDEV_EVENT_DISPLAY_ADD:
101                 display = event->display_add.display;
102
103                 r = display_new(&d, s, display);
104                 if (r < 0) {
105                         log_error_errno(r, "Cannot create display '%s' on '%s': %m",
106                                         grdev_display_get_name(display), sysview_session_get_name(s->sysview));
107                         break;
108                 }
109
110                 grdev_display_set_userdata(display, d);
111                 workspace_refresh(s->active_ws);
112                 break;
113         case GRDEV_EVENT_DISPLAY_REMOVE:
114                 display = event->display_remove.display;
115                 d = grdev_display_get_userdata(display);
116                 if (!d)
117                         break;
118
119                 display_free(d);
120                 workspace_refresh(s->active_ws);
121                 break;
122         case GRDEV_EVENT_DISPLAY_CHANGE:
123                 display = event->display_remove.display;
124                 d = grdev_display_get_userdata(display);
125                 if (!d)
126                         break;
127
128                 display_refresh(d);
129                 workspace_refresh(s->active_ws);
130                 break;
131         case GRDEV_EVENT_DISPLAY_FRAME:
132                 display = event->display_remove.display;
133                 d = grdev_display_get_userdata(display);
134                 if (!d)
135                         break;
136
137                 session_dirty(s);
138                 break;
139         }
140 }
141
142 static int session_redraw_fn(sd_event_source *src, void *userdata) {
143         Session *s = userdata;
144         Display *d;
145
146         LIST_FOREACH(displays_by_session, d, s->display_list)
147                 display_render(d, s->active_ws);
148
149         grdev_session_commit(s->grdev);
150
151         return 0;
152 }
153
154 int session_new(Session **out, Manager *m, sysview_session *session) {
155         _cleanup_(session_freep) Session *s = NULL;
156         int r;
157
158         assert(out);
159         assert(m);
160         assert(session);
161
162         s = new0(Session, 1);
163         if (!s)
164                 return -ENOMEM;
165
166         s->manager = m;
167         s->sysview = session;
168
169         r = grdev_session_new(&s->grdev,
170                               m->grdev,
171                               GRDEV_SESSION_MANAGED,
172                               sysview_session_get_name(session),
173                               session_grdev_fn,
174                               s);
175         if (r < 0)
176                 return r;
177
178         r = idev_session_new(&s->idev,
179                              m->idev,
180                              IDEV_SESSION_MANAGED,
181                              sysview_session_get_name(session),
182                              session_idev_fn,
183                              s);
184         if (r < 0)
185                 return r;
186
187         r = workspace_new(&s->my_ws, m);
188         if (r < 0)
189                 return r;
190
191         s->active_ws = workspace_attach(s->my_ws, s);
192
193         r = sd_event_add_defer(m->event, &s->redraw_src, session_redraw_fn, s);
194         if (r < 0)
195                 return r;
196
197         grdev_session_enable(s->grdev);
198         idev_session_enable(s->idev);
199
200         *out = s;
201         s = NULL;
202         return 0;
203 }
204
205 Session *session_free(Session *s) {
206         if (!s)
207                 return NULL;
208
209         assert(!s->display_list);
210
211         sd_event_source_unref(s->redraw_src);
212
213         workspace_detach(s->active_ws, s);
214         workspace_unref(s->my_ws);
215
216         idev_session_free(s->idev);
217         grdev_session_free(s->grdev);
218         free(s);
219
220         return NULL;
221 }
222
223 void session_dirty(Session *s) {
224         int r;
225
226         assert(s);
227
228         r = sd_event_source_set_enabled(s->redraw_src, SD_EVENT_ONESHOT);
229         if (r < 0)
230                 log_error_errno(r, "Cannot enable redraw-source: %m");
231 }
232
233 void session_add_device(Session *s, sysview_device *device) {
234         unsigned int type;
235
236         assert(s);
237         assert(device);
238
239         type = sysview_device_get_type(device);
240         switch (type) {
241         case SYSVIEW_DEVICE_DRM:
242                 grdev_session_add_drm(s->grdev, sysview_device_get_ud(device));
243                 break;
244         case SYSVIEW_DEVICE_EVDEV:
245                 idev_session_add_evdev(s->idev, sysview_device_get_ud(device));
246                 break;
247         }
248 }
249
250 void session_remove_device(Session *s, sysview_device *device) {
251         unsigned int type;
252
253         assert(s);
254         assert(device);
255
256         type = sysview_device_get_type(device);
257         switch (type) {
258         case SYSVIEW_DEVICE_DRM:
259                 grdev_session_remove_drm(s->grdev, sysview_device_get_ud(device));
260                 break;
261         case SYSVIEW_DEVICE_EVDEV:
262                 idev_session_remove_evdev(s->idev, sysview_device_get_ud(device));
263                 break;
264         }
265 }
266
267 void session_refresh_device(Session *s, sysview_device *device, struct udev_device *ud) {
268         unsigned int type;
269
270         assert(s);
271         assert(device);
272
273         type = sysview_device_get_type(device);
274         switch (type) {
275         case SYSVIEW_DEVICE_DRM:
276                 grdev_session_hotplug_drm(s->grdev, sysview_device_get_ud(device));
277                 break;
278         }
279 }