diff options
author | Mike Blumenkrantz <zmike@osg.samsung.com> | 2016-05-24 16:11:20 -0400 |
---|---|---|
committer | Mike Blumenkrantz <zmike@osg.samsung.com> | 2016-05-25 12:57:27 -0400 |
commit | 5f088b026d8f39aafc6b6e70fe3b04dff79b179e (patch) | |
tree | 06909671c2b23b105009d19608f7a7d7e108cf2a /src/lib/elput | |
parent | 33a5d44dcf36557b13aeba1088461504bae97373 (diff) |
elput: define and implement an async device opening interface for libinput
this adds an overly-complex method of removing blocking dbus calls from libinput's
synchronous device initialization architecture. libinput was clearly never meant
to be used in this way, but we're doing it anyway because we're efl.
#SamsungFeatures
Diffstat (limited to 'src/lib/elput')
-rw-r--r-- | src/lib/elput/Elput.h | 3 | ||||
-rw-r--r-- | src/lib/elput/elput_input.c | 191 | ||||
-rw-r--r-- | src/lib/elput/elput_logind.c | 226 | ||||
-rw-r--r-- | src/lib/elput/elput_manager.c | 8 | ||||
-rw-r--r-- | src/lib/elput/elput_private.h | 16 |
5 files changed, 299 insertions, 145 deletions
diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 07ebfa2f97..2f311608a4 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h | |||
@@ -240,14 +240,13 @@ EAPI const Eina_List *elput_manager_seats_get(Elput_Manager *manager); | |||
240 | * Initialize input | 240 | * Initialize input |
241 | * | 241 | * |
242 | * @param manager | 242 | * @param manager |
243 | * @param seat | ||
244 | * | 243 | * |
245 | * @return EINA_TRUE on success, EINA_FALSE on failure | 244 | * @return EINA_TRUE on success, EINA_FALSE on failure |
246 | * | 245 | * |
247 | * @ingroup Elput_Input_Group | 246 | * @ingroup Elput_Input_Group |
248 | * @since 1.18 | 247 | * @since 1.18 |
249 | */ | 248 | */ |
250 | EAPI Eina_Bool elput_input_init(Elput_Manager *manager, const char *seat); | 249 | EAPI Eina_Bool elput_input_init(Elput_Manager *manager); |
251 | 250 | ||
252 | /** | 251 | /** |
253 | * Shutdown input | 252 | * Shutdown input |
diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c index d49a2d0236..8431c290b5 100644 --- a/src/lib/elput/elput_input.c +++ b/src/lib/elput/elput_input.c | |||
@@ -1,12 +1,82 @@ | |||
1 | #include "elput_private.h" | 1 | #include "elput_private.h" |
2 | #include <libudev.h> | ||
3 | |||
4 | void | ||
5 | _elput_input_window_update(Elput_Manager *manager) | ||
6 | { | ||
7 | Eina_List *l, *ll; | ||
8 | Elput_Seat *seat; | ||
9 | Elput_Device *device; | ||
10 | |||
11 | if (manager->input.thread) return; | ||
12 | EINA_LIST_FOREACH(manager->input.seats, l, seat) | ||
13 | EINA_LIST_FOREACH(seat->devices, ll, device) | ||
14 | device->window = manager->window; | ||
15 | } | ||
16 | |||
17 | void | ||
18 | _elput_input_pointer_max_update(Elput_Manager *manager) | ||
19 | { | ||
20 | Eina_List *l; | ||
21 | Elput_Seat *eseat; | ||
22 | |||
23 | if (manager->input.thread) return; | ||
24 | EINA_LIST_FOREACH(manager->input.seats, l, eseat) | ||
25 | { | ||
26 | if (!eseat->ptr) continue; | ||
27 | |||
28 | eseat->ptr->maxw = manager->input.pointer_w; | ||
29 | eseat->ptr->maxh = manager->input.pointer_h; | ||
30 | } | ||
31 | } | ||
2 | 32 | ||
3 | static int | 33 | static int |
4 | _cb_open_restricted(const char *path, int flags, void *data) | 34 | _cb_open_restricted(const char *path, int flags, void *data) |
5 | { | 35 | { |
6 | Elput_Manager *em; | 36 | Elput_Manager *em = data; |
7 | 37 | int ret = -1; | |
8 | em = data; | 38 | Elput_Async_Open *ao; |
9 | return elput_manager_open(em, path, flags); | 39 | int p[2]; |
40 | |||
41 | if (!em->input.thread) | ||
42 | return em->interface->open(em, path, flags); | ||
43 | if (!em->interface->open_async) return ret; | ||
44 | ao = calloc(1, sizeof(Elput_Async_Open)); | ||
45 | if (!ao) return ret; | ||
46 | if (pipe2(p, O_CLOEXEC) < 0) | ||
47 | { | ||
48 | free(ao); | ||
49 | return ret; | ||
50 | } | ||
51 | ao->manager = em; | ||
52 | ao->path = strdup(path); | ||
53 | ao->flags = flags; | ||
54 | em->input.pipe = p[1]; | ||
55 | ecore_thread_feedback(em->input.thread, ao); | ||
56 | while (!ecore_thread_check(em->input.thread)) | ||
57 | { | ||
58 | int avail, fd; | ||
59 | fd_set rfds, wfds, exfds; | ||
60 | struct timeval tv, *t; | ||
61 | |||
62 | FD_ZERO(&rfds); | ||
63 | FD_ZERO(&wfds); | ||
64 | FD_ZERO(&exfds); | ||
65 | FD_SET(p[0], &rfds); | ||
66 | tv.tv_sec = 0; | ||
67 | tv.tv_usec = 300; | ||
68 | t = &tv; | ||
69 | avail = select(p[0] + 1, &rfds, &wfds, &exfds, t); | ||
70 | if (avail > 0) | ||
71 | { | ||
72 | read(p[0], &fd, sizeof(int)); | ||
73 | ret = fd; | ||
74 | break; | ||
75 | } | ||
76 | if (avail < 0) break; | ||
77 | } | ||
78 | close(p[0]); | ||
79 | return ret; | ||
10 | } | 80 | } |
11 | 81 | ||
12 | static void | 82 | static void |
@@ -209,52 +279,91 @@ _cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) | |||
209 | return EINA_TRUE; | 279 | return EINA_TRUE; |
210 | } | 280 | } |
211 | 281 | ||
212 | EAPI Eina_Bool | 282 | static void |
213 | elput_input_init(Elput_Manager *manager, const char *seat) | 283 | _elput_input_init_cancel(void *data, Ecore_Thread *eth EINA_UNUSED) |
214 | { | 284 | { |
215 | int fd; | 285 | Elput_Manager *manager = data; |
216 | |||
217 | EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE); | ||
218 | 286 | ||
219 | memset(&manager->input, 0, sizeof(Elput_Input)); | 287 | manager->input.thread = NULL; |
220 | 288 | if (manager->input.current_pending) | |
221 | manager->input.lib = | ||
222 | libinput_udev_create_context(&_input_interface, manager, eeze_udev_get()); | ||
223 | if (!manager->input.lib) | ||
224 | { | 289 | { |
225 | ERR("libinput could not create udev context"); | 290 | eldbus_pending_cancel(manager->input.current_pending); |
226 | goto udev_err; | 291 | if (manager->input.pipe >= 0) |
292 | close(manager->input.pipe); | ||
227 | } | 293 | } |
294 | if (manager->del) | ||
295 | elput_manager_disconnect(manager); | ||
296 | } | ||
228 | 297 | ||
229 | /* if not seat name is passed in, just use default seat name */ | 298 | static void |
230 | if (!seat) seat = "seat0"; | 299 | _elput_input_init_end(void *data, Ecore_Thread *eth EINA_UNUSED) |
300 | { | ||
301 | Elput_Manager *manager = data; | ||
231 | 302 | ||
232 | if (libinput_udev_assign_seat(manager->input.lib, seat) != 0) | 303 | manager->input.thread = NULL; |
304 | if (!manager->input.lib) return; | ||
305 | manager->input.hdlr = | ||
306 | ecore_main_fd_handler_add(libinput_get_fd(manager->input.lib), ECORE_FD_READ, | ||
307 | _cb_input_dispatch, &manager->input, NULL, NULL); | ||
308 | |||
309 | if (manager->input.hdlr) | ||
233 | { | 310 | { |
234 | ERR("libinput could not assign udev seat"); | 311 | _process_events(&manager->input); |
235 | goto seat_err; | 312 | _elput_input_window_update(manager); |
313 | _elput_input_pointer_max_update(manager); | ||
314 | } | ||
315 | else | ||
316 | { | ||
317 | ERR("Could not create input fd handler"); | ||
318 | libinput_unref(manager->input.lib); | ||
319 | manager->input.lib = NULL; | ||
236 | } | 320 | } |
321 | } | ||
237 | 322 | ||
238 | _process_events(&manager->input); | 323 | static void |
324 | _elput_input_init_notify(void *data EINA_UNUSED, Ecore_Thread *eth EINA_UNUSED, void *msg_data) | ||
325 | { | ||
326 | Elput_Async_Open *ao = msg_data; | ||
239 | 327 | ||
240 | fd = libinput_get_fd(manager->input.lib); | 328 | ao->manager->interface->open_async(ao->manager, ao->path, ao->flags); |
329 | free(ao->path); | ||
330 | free(ao); | ||
331 | } | ||
241 | 332 | ||
242 | manager->input.hdlr = | 333 | static void |
243 | ecore_main_fd_handler_add(fd, ECORE_FD_READ, _cb_input_dispatch, | 334 | _elput_input_init_thread(void *data, Ecore_Thread *eth EINA_UNUSED) |
244 | &manager->input, NULL, NULL); | 335 | { |
245 | if (!manager->input.hdlr) | 336 | Elput_Manager *manager = data; |
337 | struct udev *udev = udev_new(); | ||
338 | |||
339 | manager->input.lib = | ||
340 | libinput_udev_create_context(&_input_interface, manager, udev); | ||
341 | if (!manager->input.lib) | ||
246 | { | 342 | { |
247 | ERR("Could not create input fd handler"); | 343 | ERR("libinput could not create udev context"); |
248 | goto hdlr_err; | 344 | return; |
249 | } | 345 | } |
346 | udev_unref(udev); | ||
250 | 347 | ||
251 | return EINA_TRUE; | 348 | if (libinput_udev_assign_seat(manager->input.lib, manager->seat)) |
349 | { | ||
350 | ERR("libinput could not assign udev seat"); | ||
351 | libinput_unref(manager->input.lib); | ||
352 | manager->input.lib = NULL; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | EAPI Eina_Bool | ||
357 | elput_input_init(Elput_Manager *manager) | ||
358 | { | ||
359 | EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE); | ||
360 | EINA_SAFETY_ON_TRUE_RETURN_VAL(!!manager->input.hdlr, EINA_TRUE); | ||
252 | 361 | ||
253 | hdlr_err: | 362 | memset(&manager->input, 0, sizeof(Elput_Input)); |
254 | seat_err: | 363 | manager->input.thread = |
255 | libinput_unref(manager->input.lib); | 364 | ecore_thread_feedback_run(_elput_input_init_thread, _elput_input_init_notify, |
256 | udev_err: | 365 | _elput_input_init_end, _elput_input_init_cancel, manager, 1); |
257 | return EINA_FALSE; | 366 | return !!manager->input.thread; |
258 | } | 367 | } |
259 | 368 | ||
260 | EAPI void | 369 | EAPI void |
@@ -263,14 +372,18 @@ elput_input_shutdown(Elput_Manager *manager) | |||
263 | Elput_Seat *seat; | 372 | Elput_Seat *seat; |
264 | 373 | ||
265 | EINA_SAFETY_ON_NULL_RETURN(manager); | 374 | EINA_SAFETY_ON_NULL_RETURN(manager); |
266 | EINA_SAFETY_ON_NULL_RETURN(&manager->input); | ||
267 | 375 | ||
268 | if (manager->input.hdlr) ecore_main_fd_handler_del(manager->input.hdlr); | 376 | ecore_main_fd_handler_del(manager->input.hdlr); |
269 | 377 | ||
270 | EINA_LIST_FREE(manager->input.seats, seat) | 378 | EINA_LIST_FREE(manager->input.seats, seat) |
271 | _udev_seat_destroy(seat); | 379 | _udev_seat_destroy(seat); |
272 | 380 | if (manager->input.thread) | |
273 | libinput_unref(manager->input.lib); | 381 | ecore_thread_cancel(manager->input.thread); |
382 | else | ||
383 | { | ||
384 | libinput_unref(manager->input.lib); | ||
385 | manager->input.lib = NULL; | ||
386 | } | ||
274 | } | 387 | } |
275 | 388 | ||
276 | EAPI void | 389 | EAPI void |
diff --git a/src/lib/elput/elput_logind.c b/src/lib/elput/elput_logind.c index 3beb8b4eae..8db4a113fa 100644 --- a/src/lib/elput/elput_logind.c +++ b/src/lib/elput/elput_logind.c | |||
@@ -30,31 +30,19 @@ _logind_session_active_send(Elput_Manager *em, Eina_Bool active) | |||
30 | static void | 30 | static void |
31 | _logind_device_pause_complete(Elput_Manager *em, uint32_t major, uint32_t minor) | 31 | _logind_device_pause_complete(Elput_Manager *em, uint32_t major, uint32_t minor) |
32 | { | 32 | { |
33 | Eldbus_Proxy *proxy; | ||
34 | Eldbus_Message *msg; | 33 | Eldbus_Message *msg; |
35 | 34 | ||
36 | proxy = | 35 | msg = eldbus_proxy_method_call_new(em->dbus.session, "PauseDeviceComplete"); |
37 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); | ||
38 | if (!proxy) | ||
39 | { | ||
40 | ERR("Could not get proxy for session"); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | msg = eldbus_proxy_method_call_new(proxy, "PauseDeviceComplete"); | ||
45 | if (!msg) | 36 | if (!msg) |
46 | { | 37 | { |
47 | ERR("Could not create method call for proxy"); | 38 | ERR("Could not create method call for proxy"); |
48 | goto end; | 39 | eldbus_message_unref(msg); |
40 | return; | ||
49 | } | 41 | } |
50 | 42 | ||
51 | eldbus_message_arguments_append(msg, "uu", major, minor); | 43 | eldbus_message_arguments_append(msg, "uu", major, minor); |
52 | 44 | ||
53 | eldbus_proxy_send(proxy, msg, NULL, NULL, -1); | 45 | eldbus_proxy_send(em->dbus.session, msg, NULL, NULL, -1); |
54 | |||
55 | end: | ||
56 | eldbus_message_unref(msg); | ||
57 | eldbus_proxy_unref(proxy); | ||
58 | } | 46 | } |
59 | 47 | ||
60 | static void | 48 | static void |
@@ -194,10 +182,10 @@ _logind_dbus_setup(Elput_Manager *em) | |||
194 | ERR("Could not get dbus proxy"); | 182 | ERR("Could not get dbus proxy"); |
195 | goto proxy_err; | 183 | goto proxy_err; |
196 | } | 184 | } |
185 | em->dbus.manager = proxy; | ||
197 | 186 | ||
198 | eldbus_proxy_signal_handler_add(proxy, "SessionRemoved", | 187 | eldbus_proxy_signal_handler_add(proxy, "SessionRemoved", |
199 | _cb_session_removed, em); | 188 | _cb_session_removed, em); |
200 | eldbus_proxy_unref(proxy); | ||
201 | 189 | ||
202 | proxy = | 190 | proxy = |
203 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); | 191 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); |
@@ -206,13 +194,12 @@ _logind_dbus_setup(Elput_Manager *em) | |||
206 | ERR("Could not get dbus proxy"); | 194 | ERR("Could not get dbus proxy"); |
207 | goto proxy_err; | 195 | goto proxy_err; |
208 | } | 196 | } |
197 | em->dbus.session = proxy; | ||
209 | 198 | ||
210 | eldbus_proxy_signal_handler_add(proxy, "PauseDevice", | 199 | eldbus_proxy_signal_handler_add(proxy, "PauseDevice", |
211 | _cb_device_paused, em); | 200 | _cb_device_paused, em); |
212 | eldbus_proxy_signal_handler_add(proxy, "ResumeDevice", | 201 | eldbus_proxy_signal_handler_add(proxy, "ResumeDevice", |
213 | _cb_device_resumed, em); | 202 | _cb_device_resumed, em); |
214 | eldbus_proxy_unref(proxy); | ||
215 | |||
216 | proxy = | 203 | proxy = |
217 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.DBus.Properties"); | 204 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.DBus.Properties"); |
218 | if (!proxy) | 205 | if (!proxy) |
@@ -235,173 +222,189 @@ obj_err: | |||
235 | static Eina_Bool | 222 | static Eina_Bool |
236 | _logind_control_take(Elput_Manager *em) | 223 | _logind_control_take(Elput_Manager *em) |
237 | { | 224 | { |
238 | Eldbus_Proxy *proxy; | ||
239 | Eldbus_Message *msg, *reply; | 225 | Eldbus_Message *msg, *reply; |
240 | const char *errname, *errmsg; | 226 | const char *errname, *errmsg; |
241 | 227 | ||
242 | proxy = | 228 | msg = eldbus_proxy_method_call_new(em->dbus.session, "TakeControl"); |
243 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); | ||
244 | if (!proxy) | ||
245 | { | ||
246 | ERR("Could not get proxy for session"); | ||
247 | return EINA_FALSE; | ||
248 | } | ||
249 | |||
250 | msg = eldbus_proxy_method_call_new(proxy, "TakeControl"); | ||
251 | if (!msg) | 229 | if (!msg) |
252 | { | 230 | { |
253 | ERR("Could not create method call for proxy"); | 231 | ERR("Could not create method call for proxy"); |
254 | goto msg_err; | 232 | return EINA_FALSE; |
255 | } | 233 | } |
256 | 234 | ||
257 | eldbus_message_arguments_append(msg, "b", EINA_FALSE); | 235 | eldbus_message_arguments_append(msg, "b", EINA_FALSE); |
258 | 236 | ||
259 | reply = eldbus_proxy_send_and_block(proxy, msg, -1); | 237 | reply = eldbus_proxy_send_and_block(em->dbus.session, msg, -1); |
260 | if (eldbus_message_error_get(reply, &errname, &errmsg)) | 238 | if (eldbus_message_error_get(reply, &errname, &errmsg)) |
261 | { | 239 | { |
262 | ERR("Eldbus Message Error: %s %s", errname, errmsg); | 240 | ERR("Eldbus Message Error: %s %s", errname, errmsg); |
263 | goto msg_err; | 241 | return EINA_FALSE; |
264 | } | 242 | } |
265 | 243 | ||
266 | eldbus_message_unref(reply); | 244 | eldbus_message_unref(reply); |
267 | eldbus_proxy_unref(proxy); | ||
268 | 245 | ||
269 | return EINA_TRUE; | 246 | return EINA_TRUE; |
270 | |||
271 | msg_err: | ||
272 | eldbus_proxy_unref(proxy); | ||
273 | return EINA_FALSE; | ||
274 | } | 247 | } |
275 | 248 | ||
276 | static void | 249 | static void |
277 | _logind_control_release(Elput_Manager *em) | 250 | _logind_control_release(Elput_Manager *em) |
278 | { | 251 | { |
279 | Eldbus_Proxy *proxy; | ||
280 | Eldbus_Message *msg; | 252 | Eldbus_Message *msg; |
281 | 253 | ||
282 | proxy = | 254 | msg = eldbus_proxy_method_call_new(em->dbus.session, "ReleaseControl"); |
283 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); | 255 | if (!msg) |
284 | if (!proxy) | ||
285 | { | 256 | { |
286 | ERR("Could not get proxy for session"); | 257 | ERR("Could not create method call for proxy"); |
287 | return; | 258 | return; |
288 | } | 259 | } |
289 | 260 | ||
290 | msg = eldbus_proxy_method_call_new(proxy, "ReleaseControl"); | 261 | eldbus_proxy_send(em->dbus.session, msg, NULL, NULL, -1); |
262 | } | ||
263 | |||
264 | static void | ||
265 | _logind_device_release(Elput_Manager *em, uint32_t major, uint32_t minor) | ||
266 | { | ||
267 | Eldbus_Message *msg; | ||
268 | |||
269 | msg = eldbus_proxy_method_call_new(em->dbus.session, "ReleaseDevice"); | ||
291 | if (!msg) | 270 | if (!msg) |
292 | { | 271 | { |
293 | ERR("Could not create method call for proxy"); | 272 | ERR("Could not create method call for proxy"); |
294 | goto end; | 273 | return; |
295 | } | 274 | } |
296 | 275 | ||
297 | eldbus_proxy_send(proxy, msg, NULL, NULL, -1); | 276 | eldbus_message_arguments_append(msg, "uu", major, minor); |
298 | 277 | ||
299 | end: | 278 | eldbus_proxy_send(em->dbus.session, msg, NULL, NULL, -1); |
300 | eldbus_proxy_unref(proxy); | ||
301 | } | 279 | } |
302 | 280 | ||
303 | static int | 281 | static void |
304 | _logind_device_take(Elput_Manager *em, uint32_t major, uint32_t minor) | 282 | _logind_pipe_write_fd(Elput_Manager *em, int fd) |
283 | { | ||
284 | write(em->input.pipe, &fd, sizeof(int)); | ||
285 | close(em->input.pipe); | ||
286 | em->input.pipe = -1; | ||
287 | } | ||
288 | |||
289 | static void | ||
290 | _logind_device_take_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) | ||
305 | { | 291 | { |
306 | Eldbus_Proxy *proxy; | ||
307 | Eldbus_Message *msg, *reply; | ||
308 | Eina_Bool p = EINA_FALSE; | 292 | Eina_Bool p = EINA_FALSE; |
309 | const char *errname, *errmsg; | 293 | const char *errname, *errmsg; |
310 | int fd = -1; | 294 | int ret, fd = -1; |
311 | 295 | int fl, flags; | |
312 | proxy = | 296 | Elput_Manager *em = data; |
313 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); | ||
314 | if (!proxy) | ||
315 | { | ||
316 | ERR("Could not get dbus proxy"); | ||
317 | return -1; | ||
318 | } | ||
319 | |||
320 | msg = eldbus_proxy_method_call_new(proxy, "TakeDevice"); | ||
321 | if (!msg) | ||
322 | { | ||
323 | ERR("Could not create method call for proxy"); | ||
324 | goto err; | ||
325 | } | ||
326 | 297 | ||
327 | eldbus_message_arguments_append(msg, "uu", major, minor); | 298 | if (em->input.current_pending == pending) |
299 | em->input.current_pending = NULL; | ||
328 | 300 | ||
329 | reply = eldbus_proxy_send_and_block(proxy, msg, -1); | 301 | if (eldbus_message_error_get(msg, &errname, &errmsg)) |
330 | if (eldbus_message_error_get(reply, &errname, &errmsg)) | ||
331 | { | 302 | { |
332 | ERR("Eldbus Message Error: %s %s", errname, errmsg); | 303 | ERR("Eldbus Message Error: %s %s", errname, errmsg); |
333 | goto err; | 304 | goto err; |
334 | } | 305 | } |
335 | 306 | ||
336 | if (!eldbus_message_arguments_get(reply, "hb", &fd, &p)) | 307 | if (!eldbus_message_arguments_get(msg, "hb", &fd, &p)) |
337 | ERR("Could not get UNIX_FD from dbus message"); | 308 | ERR("Could not get UNIX_FD from dbus message"); |
338 | 309 | ||
339 | eldbus_message_unref(reply); | 310 | if (fd < 0) goto err; |
311 | |||
312 | fl = fcntl(fd, F_GETFL); | ||
313 | if (fl < 0) goto err; | ||
314 | |||
315 | flags = (intptr_t)eldbus_pending_data_get(pending, "flags"); | ||
316 | |||
317 | if (flags & O_NONBLOCK) | ||
318 | fl |= O_NONBLOCK; | ||
319 | |||
320 | ret = fcntl(fd, F_SETFL, fl); | ||
321 | if (ret < 0) goto err; | ||
322 | |||
323 | _logind_pipe_write_fd(em, fd); | ||
324 | return; | ||
340 | 325 | ||
341 | err: | 326 | err: |
342 | eldbus_proxy_unref(proxy); | 327 | if (fd >= 0) |
343 | return fd; | 328 | { |
329 | uintptr_t majo, mino; | ||
330 | |||
331 | close(fd); | ||
332 | majo = (uintptr_t)eldbus_pending_data_get(pending, "major"); | ||
333 | mino = (uintptr_t)eldbus_pending_data_get(pending, "minor"); | ||
334 | _logind_device_release(em, majo, mino); | ||
335 | } | ||
336 | fd = -1; | ||
337 | _logind_pipe_write_fd(em, fd); | ||
344 | } | 338 | } |
345 | 339 | ||
346 | static void | 340 | static void |
347 | _logind_device_release(Elput_Manager *em, uint32_t major, uint32_t minor) | 341 | _logind_device_take_async(Elput_Manager *em, int flags, uint32_t major, uint32_t minor) |
348 | { | 342 | { |
349 | Eldbus_Proxy *proxy; | ||
350 | Eldbus_Message *msg; | 343 | Eldbus_Message *msg; |
344 | intptr_t fd = -1; | ||
351 | 345 | ||
352 | proxy = | 346 | msg = eldbus_proxy_method_call_new(em->dbus.session, "TakeDevice"); |
353 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); | 347 | if (!msg) |
354 | if (!proxy) | ||
355 | { | 348 | { |
356 | ERR("Could not get proxy for session"); | 349 | ERR("Could not create method call for proxy"); |
350 | _logind_pipe_write_fd(em, fd); | ||
357 | return; | 351 | return; |
358 | } | 352 | } |
359 | 353 | ||
360 | msg = eldbus_proxy_method_call_new(proxy, "ReleaseDevice"); | 354 | eldbus_message_arguments_append(msg, "uu", major, minor); |
355 | |||
356 | em->input.current_pending = eldbus_proxy_send(em->dbus.session, msg, _logind_device_take_cb, em, -1); | ||
357 | if (!em->input.current_pending) CRIT("FAIL!"); | ||
358 | eldbus_pending_data_set(em->input.current_pending, "major", (uintptr_t*)(uintptr_t)major); | ||
359 | eldbus_pending_data_set(em->input.current_pending, "minor", (uintptr_t*)(uintptr_t)minor); | ||
360 | eldbus_pending_data_set(em->input.current_pending, "flags", (intptr_t*)(intptr_t)flags); | ||
361 | } | ||
362 | |||
363 | static int | ||
364 | _logind_device_take(Elput_Manager *em, uint32_t major, uint32_t minor) | ||
365 | { | ||
366 | Eldbus_Message *msg, *reply; | ||
367 | Eina_Bool p = EINA_FALSE; | ||
368 | const char *errname, *errmsg; | ||
369 | int fd = -1; | ||
370 | |||
371 | msg = eldbus_proxy_method_call_new(em->dbus.session, "TakeDevice"); | ||
361 | if (!msg) | 372 | if (!msg) |
362 | { | 373 | { |
363 | ERR("Could not create method call for proxy"); | 374 | ERR("Could not create method call for proxy"); |
364 | goto end; | 375 | return -1; |
365 | } | 376 | } |
366 | 377 | ||
367 | eldbus_message_arguments_append(msg, "uu", major, minor); | 378 | eldbus_message_arguments_append(msg, "uu", major, minor); |
368 | 379 | ||
369 | eldbus_proxy_send(proxy, msg, NULL, NULL, -1); | 380 | reply = eldbus_proxy_send_and_block(em->dbus.session, msg, -1); |
381 | if (eldbus_message_error_get(reply, &errname, &errmsg)) | ||
382 | { | ||
383 | ERR("Eldbus Message Error: %s %s", errname, errmsg); | ||
384 | return -1; | ||
385 | } | ||
370 | 386 | ||
371 | end: | 387 | if (!eldbus_message_arguments_get(reply, "hb", &fd, &p)) |
372 | eldbus_proxy_unref(proxy); | 388 | ERR("Could not get UNIX_FD from dbus message"); |
389 | |||
390 | eldbus_message_unref(reply); | ||
391 | return fd; | ||
373 | } | 392 | } |
374 | 393 | ||
375 | static Eina_Bool | 394 | static Eina_Bool |
376 | _logind_activate(Elput_Manager *em) | 395 | _logind_activate(Elput_Manager *em) |
377 | { | 396 | { |
378 | Eldbus_Proxy *proxy; | ||
379 | Eldbus_Message *msg; | 397 | Eldbus_Message *msg; |
380 | 398 | ||
381 | proxy = | 399 | msg = eldbus_proxy_method_call_new(em->dbus.session, "Activate"); |
382 | eldbus_proxy_get(em->dbus.obj, "org.freedesktop.login1.Session"); | ||
383 | if (!proxy) | ||
384 | { | ||
385 | ERR("Could not get proxy for session"); | ||
386 | return EINA_FALSE; | ||
387 | } | ||
388 | |||
389 | msg = eldbus_proxy_method_call_new(proxy, "Activate"); | ||
390 | if (!msg) | 400 | if (!msg) |
391 | { | 401 | { |
392 | ERR("Could not create method call for proxy"); | 402 | ERR("Could not create method call for proxy"); |
393 | goto msg_err; | 403 | return EINA_FALSE; |
394 | } | 404 | } |
395 | 405 | ||
396 | eldbus_proxy_send(proxy, msg, NULL, NULL, -1); | 406 | eldbus_proxy_send(em->dbus.session, msg, NULL, NULL, -1); |
397 | |||
398 | eldbus_proxy_unref(proxy); | ||
399 | |||
400 | return EINA_TRUE; | 407 | return EINA_TRUE; |
401 | |||
402 | msg_err: | ||
403 | eldbus_proxy_unref(proxy); | ||
404 | return EINA_FALSE; | ||
405 | } | 408 | } |
406 | 409 | ||
407 | static Eina_Bool | 410 | static Eina_Bool |
@@ -498,6 +501,8 @@ static void | |||
498 | _logind_disconnect(Elput_Manager *em) | 501 | _logind_disconnect(Elput_Manager *em) |
499 | { | 502 | { |
500 | _logind_control_release(em); | 503 | _logind_control_release(em); |
504 | eldbus_proxy_unref(em->dbus.manager); | ||
505 | eldbus_proxy_unref(em->dbus.session); | ||
501 | eldbus_object_unref(em->dbus.obj); | 506 | eldbus_object_unref(em->dbus.obj); |
502 | free(em->dbus.path); | 507 | free(em->dbus.path); |
503 | _logind_dbus_close(em->dbus.conn); | 508 | _logind_dbus_close(em->dbus.conn); |
@@ -506,6 +511,18 @@ _logind_disconnect(Elput_Manager *em) | |||
506 | free(em); | 511 | free(em); |
507 | } | 512 | } |
508 | 513 | ||
514 | static void | ||
515 | _logind_open_async(Elput_Manager *em, const char *path, int flags) | ||
516 | { | ||
517 | struct stat st; | ||
518 | intptr_t fd = -1; | ||
519 | |||
520 | if ((stat(path, &st) < 0) || (!S_ISCHR(st.st_mode))) | ||
521 | _logind_pipe_write_fd(em, fd); | ||
522 | else | ||
523 | _logind_device_take_async(em, flags, major(st.st_rdev), minor(st.st_rdev)); | ||
524 | } | ||
525 | |||
509 | static int | 526 | static int |
510 | _logind_open(Elput_Manager *em, const char *path, int flags) | 527 | _logind_open(Elput_Manager *em, const char *path, int flags) |
511 | { | 528 | { |
@@ -606,6 +623,7 @@ Elput_Interface _logind_interface = | |||
606 | _logind_connect, | 623 | _logind_connect, |
607 | _logind_disconnect, | 624 | _logind_disconnect, |
608 | _logind_open, | 625 | _logind_open, |
626 | _logind_open_async, | ||
609 | _logind_close, | 627 | _logind_close, |
610 | _logind_vt_set, | 628 | _logind_vt_set, |
611 | }; | 629 | }; |
diff --git a/src/lib/elput/elput_manager.c b/src/lib/elput/elput_manager.c index b1378f55b0..3b127afdc7 100644 --- a/src/lib/elput/elput_manager.c +++ b/src/lib/elput/elput_manager.c | |||
@@ -58,6 +58,14 @@ elput_manager_disconnect(Elput_Manager *manager) | |||
58 | EINA_SAFETY_ON_NULL_RETURN(manager); | 58 | EINA_SAFETY_ON_NULL_RETURN(manager); |
59 | EINA_SAFETY_ON_NULL_RETURN(manager->interface); | 59 | EINA_SAFETY_ON_NULL_RETURN(manager->interface); |
60 | 60 | ||
61 | |||
62 | if (manager->input.thread) | ||
63 | { | ||
64 | ecore_thread_cancel(manager->input.thread); | ||
65 | manager->del = 1; | ||
66 | return; | ||
67 | } | ||
68 | |||
61 | if (manager->interface->disconnect) | 69 | if (manager->interface->disconnect) |
62 | manager->interface->disconnect(manager); | 70 | manager->interface->disconnect(manager); |
63 | } | 71 | } |
diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index c2f4b007ea..a934bf1d23 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h | |||
@@ -71,6 +71,7 @@ typedef struct _Elput_Interface | |||
71 | Eina_Bool (*connect)(Elput_Manager **manager, const char *seat, unsigned int tty); | 71 | Eina_Bool (*connect)(Elput_Manager **manager, const char *seat, unsigned int tty); |
72 | void (*disconnect)(Elput_Manager *manager); | 72 | void (*disconnect)(Elput_Manager *manager); |
73 | int (*open)(Elput_Manager *manager, const char *path, int flags); | 73 | int (*open)(Elput_Manager *manager, const char *path, int flags); |
74 | void (*open_async)(Elput_Manager *manager, const char *path, int flags); | ||
74 | void (*close)(Elput_Manager *manager, int fd); | 75 | void (*close)(Elput_Manager *manager, int fd); |
75 | Eina_Bool (*vt_set)(Elput_Manager *manager, int vt); | 76 | Eina_Bool (*vt_set)(Elput_Manager *manager, int vt); |
76 | } Elput_Interface; | 77 | } Elput_Interface; |
@@ -82,6 +83,9 @@ typedef struct _Elput_Input | |||
82 | Ecore_Fd_Handler *hdlr; | 83 | Ecore_Fd_Handler *hdlr; |
83 | 84 | ||
84 | Eina_List *seats; | 85 | Eina_List *seats; |
86 | Ecore_Thread *thread; | ||
87 | Eldbus_Pending *current_pending; | ||
88 | int pipe; | ||
85 | 89 | ||
86 | Eina_Bool suspended : 1; | 90 | Eina_Bool suspended : 1; |
87 | } Elput_Input; | 91 | } Elput_Input; |
@@ -224,18 +228,30 @@ struct _Elput_Manager | |||
224 | char *sid; | 228 | char *sid; |
225 | const char *seat; | 229 | const char *seat; |
226 | unsigned int vt_num; | 230 | unsigned int vt_num; |
231 | int vt_fd; | ||
227 | Ecore_Event_Handler *vt_hdlr; | 232 | Ecore_Event_Handler *vt_hdlr; |
233 | uint32_t window; | ||
228 | 234 | ||
229 | struct | 235 | struct |
230 | { | 236 | { |
231 | char *path; | 237 | char *path; |
232 | Eldbus_Object *obj; | 238 | Eldbus_Object *obj; |
233 | Eldbus_Connection *conn; | 239 | Eldbus_Connection *conn; |
240 | Eldbus_Proxy *session; | ||
241 | Eldbus_Proxy *manager; | ||
234 | } dbus; | 242 | } dbus; |
235 | 243 | ||
236 | Elput_Input input; | 244 | Elput_Input input; |
245 | Eina_Bool del : 1; | ||
237 | }; | 246 | }; |
238 | 247 | ||
248 | typedef struct _Elput_Async_Open | ||
249 | { | ||
250 | Elput_Manager *manager; | ||
251 | char *path; | ||
252 | int flags; | ||
253 | } Elput_Async_Open; | ||
254 | |||
239 | int _evdev_event_process(struct libinput_event *event); | 255 | int _evdev_event_process(struct libinput_event *event); |
240 | Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device); | 256 | Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device); |
241 | void _evdev_device_destroy(Elput_Device *edev); | 257 | void _evdev_device_destroy(Elput_Device *edev); |