efl

Форк
0
/
ecore_wl.c 
897 строк · 24.6 Кб
1
#ifdef HAVE_CONFIG_H
2
# include <config.h>
3
#endif
4

5
#include <fcntl.h>
6
#include "ecore_wl_private.h"
7

8
/*
9
 * The subsurface protocol was moved into Wayland Core
10
 * around v1.3.90 (i.e. v1.4.0).
11
 * Test if subsurface protocol is part of wayland-client.h.
12
 * If not, we include our own copy of the protocol header.
13
 */
14
#include <wayland-client.h>
15
#ifndef WL_SUBSURFACE_ERROR_ENUM
16
# include <subsurface-client-protocol.h>
17
#endif
18

19
#include "xdg-shell-client-protocol.h"
20
#define XDG_VERSION 5
21

22
#include "session-recovery-client-protocol.h"
23

24
/* local function prototypes */
25
static int _ecore_wl_shutdown(Eina_Bool close);
26
static Eina_Bool _ecore_wl_cb_idle_enterer(void *data);
27
static Eina_Bool _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl);
28
static void _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version EINA_UNUSED);
29
static void _ecore_wl_cb_handle_global_remove(void *data, struct wl_registry *registry EINA_UNUSED, unsigned int id);
30
static Eina_Bool _ecore_wl_xkb_init(Ecore_Wl_Display *ewd);
31
static Eina_Bool _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd);
32
static void _ecore_wl_sync_wait(Ecore_Wl_Display *ewd);
33
static void _ecore_wl_sync_callback(void *data, struct wl_callback *callback, uint32_t serial);
34
static void _ecore_wl_animator_tick_cb_begin(void *data EINA_UNUSED);
35
static void _ecore_wl_animator_tick_cb_end(void *data EINA_UNUSED);
36
static void _ecore_wl_animator_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED);
37
static Eina_Bool _ecore_wl_animator_window_add(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED);
38
static void _ecore_wl_signal_exit(void);
39
static void _ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event);
40
static void _ecore_wl_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED);
41

42
/* local variables */
43
static int _ecore_wl_init_count = 0;
44
static Eina_Bool _ecore_wl_animator_busy = EINA_FALSE;
45
static Eina_Bool _ecore_wl_fatal_error = EINA_FALSE;
46
Eina_Bool _ecore_wl_server_mode = EINA_FALSE;
47

48
static const struct wl_registry_listener _ecore_wl_registry_listener =
49
{
50
   _ecore_wl_cb_handle_global,
51
   _ecore_wl_cb_handle_global_remove
52
};
53

54
static const struct wl_callback_listener _ecore_wl_sync_listener =
55
{
56
   _ecore_wl_sync_callback
57
};
58

59
static const struct wl_callback_listener _ecore_wl_init_sync_listener =
60
{
61
   _ecore_wl_init_callback
62
};
63

64
static const struct wl_callback_listener _ecore_wl_anim_listener =
65
{
66
   _ecore_wl_animator_callback
67
};
68

69
static void
70
xdg_shell_ping(void *data EINA_UNUSED, struct xdg_shell *shell, uint32_t serial)
71
{
72
   xdg_shell_pong(shell, serial);
73
}
74

75
static const struct xdg_shell_listener xdg_shell_listener =
76
{
77
   xdg_shell_ping,
78
};
79

80
/* external variables */
81
int _ecore_wl_log_dom = -1;
82
Ecore_Wl_Display *_ecore_wl_disp = NULL;
83

84
EAPI int ECORE_WL_EVENT_MOUSE_IN = 0;
85
EAPI int ECORE_WL_EVENT_MOUSE_OUT = 0;
86
EAPI int ECORE_WL_EVENT_FOCUS_IN = 0;
87
EAPI int ECORE_WL_EVENT_FOCUS_OUT = 0;
88
EAPI int ECORE_WL_EVENT_WINDOW_CONFIGURE = 0;
89
EAPI int ECORE_WL_EVENT_DND_ENTER = 0;
90
EAPI int ECORE_WL_EVENT_DND_POSITION = 0;
91
EAPI int ECORE_WL_EVENT_DND_LEAVE = 0;
92
EAPI int ECORE_WL_EVENT_DND_DROP = 0;
93
EAPI int ECORE_WL_EVENT_DND_OFFER = 0;
94
EAPI int ECORE_WL_EVENT_DND_END = 0;
95
EAPI int ECORE_WL_EVENT_DATA_SOURCE_TARGET = 0;
96
EAPI int ECORE_WL_EVENT_DATA_SOURCE_SEND = 0;
97
EAPI int ECORE_WL_EVENT_SELECTION_DATA_READY = 0;
98
EAPI int ECORE_WL_EVENT_DATA_SOURCE_CANCELLED = 0;
99
EAPI int ECORE_WL_EVENT_INTERFACES_BOUND = 0;
100

101
static void
102
_ecore_wl_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
103
{
104
   Ecore_Wl_Display *ewd = data;
105

106
   wl_callback_destroy(callback);
107
   ewd->init_done = EINA_TRUE;
108
}
109

110
static void
111
_ecore_wl_init_wait(void)
112
{
113
   int ret;
114
   while (!_ecore_wl_disp->init_done)
115
     {
116
        ret = wl_display_dispatch(_ecore_wl_disp->wl.display);
117
        if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
118
          {
119
             /* raise exit signal */
120
             ERR("Wayland socket error: %s", strerror(errno));
121
             abort();
122
             break;
123
          }
124
     }
125
}
126

127
EAPI int
128
ecore_wl_init(const char *name)
129
{
130
   struct wl_callback *callback;
131
   LOGFN;
132

133
   if (++_ecore_wl_init_count != 1) return _ecore_wl_init_count;
134

135
   if (!eina_init()) return --_ecore_wl_init_count;
136

137
   _ecore_wl_log_dom =
138
     eina_log_domain_register("ecore_wl", ECORE_WL_DEFAULT_LOG_COLOR);
139
   if (_ecore_wl_log_dom < 0)
140
     {
141
        EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland");
142
        goto exit_eina;
143
     }
144

145
   if (!ecore_init())
146
     {
147
        ERR("Could not initialize ecore");
148
        goto exit_ecore;
149
     }
150

151
   if (!ecore_event_init())
152
     {
153
        ERR("Could not initialize ecore_event");
154
        goto exit_ecore_event;
155
     }
156

157
   ECORE_WL_EVENT_MOUSE_IN = ecore_event_type_new();
158
   ECORE_WL_EVENT_MOUSE_OUT = ecore_event_type_new();
159
   ECORE_WL_EVENT_FOCUS_IN = ecore_event_type_new();
160
   ECORE_WL_EVENT_FOCUS_OUT = ecore_event_type_new();
161
   ECORE_WL_EVENT_WINDOW_CONFIGURE = ecore_event_type_new();
162
   ECORE_WL_EVENT_DND_ENTER = ecore_event_type_new();
163
   ECORE_WL_EVENT_DND_POSITION = ecore_event_type_new();
164
   ECORE_WL_EVENT_DND_LEAVE = ecore_event_type_new();
165
   ECORE_WL_EVENT_DND_DROP = ecore_event_type_new();
166
   ECORE_WL_EVENT_DND_OFFER = ecore_event_type_new();
167
   ECORE_WL_EVENT_DND_END = ecore_event_type_new();
168
   ECORE_WL_EVENT_DATA_SOURCE_TARGET = ecore_event_type_new();
169
   ECORE_WL_EVENT_DATA_SOURCE_SEND = ecore_event_type_new();
170
   ECORE_WL_EVENT_SELECTION_DATA_READY = ecore_event_type_new();
171
   ECORE_WL_EVENT_DATA_SOURCE_CANCELLED = ecore_event_type_new();
172
   ECORE_WL_EVENT_INTERFACES_BOUND = ecore_event_type_new();
173

174
   if (!(_ecore_wl_disp = calloc(1, sizeof(Ecore_Wl_Display))))
175
     {
176
        ERR("Could not allocate memory for Ecore_Wl_Display structure");
177
        goto exit_ecore_disp;
178
     }
179

180
   if (!(_ecore_wl_disp->wl.display = wl_display_connect(name)))
181
     {
182
        ERR("Could not connect to Wayland display");
183
        goto exit_ecore_disp_connect;
184
     }
185

186
   _ecore_wl_disp->fd = wl_display_get_fd(_ecore_wl_disp->wl.display);
187

188
   _ecore_wl_disp->fd_hdl =
189
     ecore_main_fd_handler_add(_ecore_wl_disp->fd,
190
                               ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR,
191
                               _ecore_wl_cb_handle_data, _ecore_wl_disp,
192
                               NULL, NULL);
193

194
   _ecore_wl_disp->idle_enterer =
195
     ecore_idle_enterer_add(_ecore_wl_cb_idle_enterer, _ecore_wl_disp);
196

197
   _ecore_wl_disp->wl.registry =
198
     wl_display_get_registry(_ecore_wl_disp->wl.display);
199
   wl_registry_add_listener(_ecore_wl_disp->wl.registry,
200
                            &_ecore_wl_registry_listener, _ecore_wl_disp);
201

202
   if (!_ecore_wl_xkb_init(_ecore_wl_disp))
203
     {
204
        ERR("Could not initialize XKB");
205
        goto exit_ecore_disp_connect;
206
     }
207

208
   _ecore_wl_window_init();
209
   _ecore_wl_events_init();
210

211
   _ecore_wl_disp->init_done = EINA_TRUE;
212
   if (!_ecore_wl_server_mode)
213
     {
214
        _ecore_wl_disp->init_done = EINA_FALSE;
215
        callback = wl_display_sync(_ecore_wl_disp->wl.display);
216
        wl_callback_add_listener(callback, &_ecore_wl_init_sync_listener,
217
                                 _ecore_wl_disp);
218
     }
219

220
   return _ecore_wl_init_count;
221

222
exit_ecore_disp_connect:
223
   free(_ecore_wl_disp);
224

225
exit_ecore_disp:
226
   ecore_event_shutdown();
227

228
exit_ecore_event:
229
   ecore_shutdown();
230

231
exit_ecore:
232
   eina_log_domain_unregister(_ecore_wl_log_dom);
233
   _ecore_wl_log_dom = -1;
234

235
exit_eina:
236
   eina_shutdown();
237
   return --_ecore_wl_init_count;
238
}
239

240
EAPI int
241
ecore_wl_shutdown(void)
242
{
243
   LOGFN;
244

245
   return _ecore_wl_shutdown(EINA_TRUE);
246
}
247

248
EAPI void
249
ecore_wl_flush(void)
250
{
251
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
252
   wl_display_flush(_ecore_wl_disp->wl.display);
253
}
254

255
EAPI void
256
ecore_wl_sync(void)
257
{
258
   int ret;
259
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
260
   _ecore_wl_sync_wait(_ecore_wl_disp);
261
   while (_ecore_wl_disp->sync_ref_count > 0)
262
     {
263
        ret = wl_display_dispatch(_ecore_wl_disp->wl.display);
264
        if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
265
          {
266
             /* raise exit signal */
267
             ERR("Wayland socket error: %s", strerror(errno));
268
             abort();
269
             break;
270
          }
271
     }
272
}
273

274
EAPI struct wl_shm *
275
ecore_wl_shm_get(void)
276
{
277
   if (!_ecore_wl_disp) return NULL;
278

279
   _ecore_wl_init_wait();
280

281
   return _ecore_wl_disp->wl.shm;
282
}
283

284
EAPI struct wl_display *
285
ecore_wl_display_get(void)
286
{
287
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
288
     return NULL;
289
   return _ecore_wl_disp->wl.display;
290
}
291

292
EAPI Eina_Inlist *
293
ecore_wl_globals_get(void)
294
{
295
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
296
     return NULL;
297

298
   _ecore_wl_init_wait();
299

300
   return _ecore_wl_disp->globals;
301
}
302

303
EAPI struct wl_registry *
304
ecore_wl_registry_get(void)
305
{
306
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
307
     return NULL;
308
   return _ecore_wl_disp->wl.registry;
309
}
310

311
struct wl_compositor *
312
_ecore_wl_compositor_get(void)
313
{
314
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
315
     return NULL;
316

317
   _ecore_wl_init_wait();
318

319
   return _ecore_wl_disp->wl.compositor;
320
}
321

322
struct wl_subcompositor *
323
_ecore_wl_subcompositor_get(void)
324
{
325
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display))
326
     return NULL;
327

328
   _ecore_wl_init_wait();
329

330
   return _ecore_wl_disp->wl.subcompositor;
331
}
332

333
EAPI void
334
ecore_wl_screen_size_get(int *w, int *h)
335
{
336
   Ecore_Wl_Output *out;
337
   Eina_Inlist *tmp;
338
   int ow = 0, oh = 0;
339

340
   LOGFN;
341

342
   if (w) *w = 0;
343
   if (h) *h = 0;
344

345
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
346

347
   _ecore_wl_init_wait();
348

349
   // the first sync is in case registry replies are not back yet
350
   if (!_ecore_wl_disp->output)
351
     {
352
        // second sync is in case bound object replies in registry are not back
353
        ecore_wl_sync();
354
        if (!_ecore_wl_disp->output) ecore_wl_sync();
355
     }
356

357
   EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->outputs, tmp, out)
358
     {
359
        switch (out->transform)
360
          {
361
           case WL_OUTPUT_TRANSFORM_90:
362
           case WL_OUTPUT_TRANSFORM_270:
363
           case WL_OUTPUT_TRANSFORM_FLIPPED_90:
364
           case WL_OUTPUT_TRANSFORM_FLIPPED_270:
365
             /* Swap width and height */
366
             ow += out->allocation.h;
367
             oh += out->allocation.w;
368
             break;
369
           default:
370
             ow += out->allocation.w;
371
             oh += out->allocation.h;
372
          }
373
     }
374

375
   if (w) *w = ow;
376
   if (h) *h = oh;
377
}
378

379
/* @since 1.2 */
380
EAPI void
381
ecore_wl_pointer_xy_get(int *x, int *y)
382
{
383
   LOGFN;
384

385
   _ecore_wl_input_pointer_xy_get(x, y);
386
}
387

388
EAPI int
389
ecore_wl_dpi_get(void)
390
{
391
   int w, mw;
392

393
   LOGFN;
394

395
   if (!_ecore_wl_disp) return 0;
396

397
   _ecore_wl_init_wait();
398

399
   if (!_ecore_wl_disp->output) return 75;
400

401
   mw = _ecore_wl_disp->output->mw;
402
   if (mw <= 0) return 75;
403

404
   w = _ecore_wl_disp->output->allocation.w;
405
   /* FIXME: NB: Hrrrmmm, need to verify this. xorg code is using a different
406
    * formula to calc this */
407
   return (((w * 254) / mw) + 5) / 10;
408
}
409

410
EAPI void
411
ecore_wl_display_iterate(void)
412
{
413
   int ret;
414
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return;
415
   if (!_ecore_wl_server_mode)
416
     {
417
        ret = wl_display_dispatch(_ecore_wl_disp->wl.display);
418
        if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
419
          {
420
             /* raise exit signal */
421
             ERR("Wayland socket error: %s", strerror(errno));
422
             abort();
423
          }
424
     }
425
}
426

427
/* @since 1.8 */
428
EAPI Eina_Bool
429
ecore_wl_animator_source_set(Ecore_Animator_Source source)
430
{
431
   LOGFN;
432

433
   if (_ecore_wl_server_mode) return EINA_FALSE;
434

435
   /* FIXME: check existing source. If custom, disable anim_callbacks */
436

437
   /* based on the animator source we are using, setup or destroy callbacks */
438
   switch (source)
439
     {
440
      case ECORE_ANIMATOR_SOURCE_CUSTOM:
441
        ecore_animator_custom_source_tick_begin_callback_set
442
          (_ecore_wl_animator_tick_cb_begin, NULL);
443
        ecore_animator_custom_source_tick_end_callback_set
444
          (_ecore_wl_animator_tick_cb_end, NULL);
445
        break;
446
      case ECORE_ANIMATOR_SOURCE_TIMER:
447
        ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
448
        ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
449
        break;
450
      default:
451
        break;
452
     }
453

454
   /* set the source of the animator */
455
   ecore_animator_source_set(source);
456

457
   return EINA_TRUE;
458
}
459

460
EAPI struct wl_cursor *
461
ecore_wl_cursor_get(const char *cursor_name)
462
{
463
   if ((!_ecore_wl_disp) || (!_ecore_wl_disp->cursor_theme))
464
     return NULL;
465

466
   return wl_cursor_theme_get_cursor(_ecore_wl_disp->cursor_theme,
467
                                     cursor_name);
468
}
469

470
EAPI void
471
ecore_wl_server_mode_set(Eina_Bool on)
472
{
473
   _ecore_wl_server_mode = on;
474
}
475

476
/* local functions */
477
static int
478
_ecore_wl_shutdown(Eina_Bool close)
479
{
480
   LOGFN;
481

482
   if (_ecore_wl_init_count < 1)
483
     {
484
        ERR("Ecore_Wayland Shutdown called without Ecore_Wayland Init");
485
        return 0;
486
     }
487

488
   if (--_ecore_wl_init_count != 0) return _ecore_wl_init_count;
489
   if (!_ecore_wl_disp) return _ecore_wl_init_count;
490

491
   ecore_event_type_flush(ECORE_WL_EVENT_MOUSE_IN,
492
                          ECORE_WL_EVENT_MOUSE_OUT,
493
                          ECORE_WL_EVENT_FOCUS_IN,
494
                          ECORE_WL_EVENT_FOCUS_OUT,
495
                          ECORE_WL_EVENT_WINDOW_CONFIGURE,
496
                          ECORE_WL_EVENT_DND_ENTER,
497
                          ECORE_WL_EVENT_DND_POSITION,
498
                          ECORE_WL_EVENT_DND_LEAVE,
499
                          ECORE_WL_EVENT_DND_DROP,
500
                          ECORE_WL_EVENT_DND_OFFER,
501
                          ECORE_WL_EVENT_DND_END,
502
                          ECORE_WL_EVENT_DATA_SOURCE_TARGET,
503
                          ECORE_WL_EVENT_DATA_SOURCE_SEND,
504
                          ECORE_WL_EVENT_SELECTION_DATA_READY,
505
                          ECORE_WL_EVENT_DATA_SOURCE_CANCELLED,
506
                          ECORE_WL_EVENT_INTERFACES_BOUND);
507

508
   _ecore_wl_events_shutdown();
509
   _ecore_wl_window_shutdown();
510

511
   if (_ecore_wl_disp->fd_hdl)
512
     ecore_main_fd_handler_del(_ecore_wl_disp->fd_hdl);
513
   if (_ecore_wl_disp->idle_enterer)
514
      ecore_idle_enterer_del(_ecore_wl_disp->idle_enterer);
515

516
   if ((close) && (!_ecore_wl_fatal_error))
517
     {
518
        Ecore_Wl_Output *out;
519
        Ecore_Wl_Input *in;
520
        Ecore_Wl_Global *global;
521
        Eina_Inlist *tmp;
522

523
        EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->outputs, tmp, out)
524
          _ecore_wl_output_del(out);
525

526
        EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->inputs, tmp, in)
527
          _ecore_wl_input_del(in);
528

529
        EINA_INLIST_FOREACH_SAFE(_ecore_wl_disp->globals, tmp, global)
530
          {
531
             _ecore_wl_disp->globals =
532
               eina_inlist_remove(_ecore_wl_disp->globals,
533
                                  EINA_INLIST_GET(global));
534
             free(global->interface);
535
             free(global);
536
          }
537

538
        _ecore_wl_xkb_shutdown(_ecore_wl_disp);
539

540
        if (_ecore_wl_disp->wl.session_recovery)
541
          zwp_e_session_recovery_destroy(_ecore_wl_disp->wl.session_recovery);
542
#ifdef USE_IVI_SHELL
543
        if (_ecore_wl_disp->wl.ivi_application)
544
          ivi_application_destroy(_ecore_wl_disp->wl.ivi_application);
545
#endif
546
        if (_ecore_wl_disp->wl.xdg_shell)
547
          xdg_shell_destroy(_ecore_wl_disp->wl.xdg_shell);
548
        if (_ecore_wl_disp->wl.shell)
549
          wl_shell_destroy(_ecore_wl_disp->wl.shell);
550
        if (_ecore_wl_disp->wl.shm) wl_shm_destroy(_ecore_wl_disp->wl.shm);
551
        if (_ecore_wl_disp->wl.data_device_manager)
552
          wl_data_device_manager_destroy(_ecore_wl_disp->wl.data_device_manager);
553
        if (_ecore_wl_disp->wl.compositor)
554
          wl_compositor_destroy(_ecore_wl_disp->wl.compositor);
555
        if (_ecore_wl_disp->wl.subcompositor)
556
          wl_subcompositor_destroy(_ecore_wl_disp->wl.subcompositor);
557
        if (_ecore_wl_disp->cursor_theme)
558
          wl_cursor_theme_destroy(_ecore_wl_disp->cursor_theme);
559
        if (_ecore_wl_disp->wl.display)
560
          {
561
             wl_registry_destroy(_ecore_wl_disp->wl.registry);
562
             wl_display_flush(_ecore_wl_disp->wl.display);
563
             wl_display_disconnect(_ecore_wl_disp->wl.display);
564
          }
565
        free(_ecore_wl_disp);
566
     }
567

568
   ecore_event_shutdown();
569
   ecore_shutdown();
570

571
   eina_log_domain_unregister(_ecore_wl_log_dom);
572
   _ecore_wl_log_dom = -1;
573
   eina_shutdown();
574

575
   return _ecore_wl_init_count;
576
}
577

578
static Eina_Bool
579
_ecore_wl_cb_idle_enterer(void *data)
580
{
581
   Ecore_Wl_Display *ewd;
582
   int ret = 0;
583

584
   if (_ecore_wl_fatal_error) return ECORE_CALLBACK_CANCEL;
585

586
   if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
587

588
   ret = wl_display_get_error(ewd->wl.display);
589
   if (ret < 0) goto err;
590

591
   ret = wl_display_dispatch_pending(ewd->wl.display);
592
   if (ret < 0) goto err;
593

594
   ret = wl_display_flush(ewd->wl.display);
595
   if ((ret < 0) && (errno == EAGAIN))
596
     ecore_main_fd_handler_active_set(ewd->fd_hdl,
597
                                      (ECORE_FD_READ | ECORE_FD_WRITE));
598

599
   return ECORE_CALLBACK_RENEW;
600

601
err:
602
   if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
603
     {
604
        _ecore_wl_fatal_error = EINA_TRUE;
605

606
        /* raise exit signal */
607
        ERR("Wayland socket error: %s", strerror(errno));
608
        _ecore_wl_signal_exit();
609

610
        return ECORE_CALLBACK_CANCEL;
611
     }
612

613
   return ECORE_CALLBACK_RENEW;
614
}
615

616
static Eina_Bool
617
_ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
618
{
619
   Ecore_Wl_Display *ewd;
620
   int ret = 0;
621

622
   /* LOGFN; */
623

624
   if (_ecore_wl_fatal_error) return ECORE_CALLBACK_CANCEL;
625

626
   if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
627

628
   if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
629
     {
630
        ERR("Received error on wayland display fd");
631
        _ecore_wl_fatal_error = EINA_TRUE;
632
        _ecore_wl_signal_exit();
633

634
        return ECORE_CALLBACK_CANCEL;
635
     }
636

637
   /* wl_display_dispatch_pending(ewd->wl.display); */
638

639
   if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
640
     ret = wl_display_dispatch(ewd->wl.display);
641
   else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
642
     {
643
        ret = wl_display_flush(ewd->wl.display);
644
        if (ret == 0)
645
          ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
646
     }
647

648
   if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
649
     {
650
        _ecore_wl_fatal_error = EINA_TRUE;
651

652
        /* raise exit signal */
653
        _ecore_wl_signal_exit();
654

655
        return ECORE_CALLBACK_CANCEL;
656
     }
657

658
   return ECORE_CALLBACK_RENEW;
659
}
660

661
static void
662
_ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version)
663
{
664
   Ecore_Wl_Display *ewd;
665
   Ecore_Wl_Global *global;
666

667
   LOGFN;
668

669
   ewd = data;
670

671
   if (!(global = calloc(1, sizeof(Ecore_Wl_Global)))) return;
672

673
   global->id = id;
674
   global->interface = strdup(interface);
675
   global->version = version;
676
   ewd->globals = eina_inlist_append(ewd->globals, EINA_INLIST_GET(global));
677

678
   if (!strcmp(interface, "wl_compositor"))
679
     {
680
        ewd->wl.compositor =
681
          wl_registry_bind(registry, id, &wl_compositor_interface, 3);
682
     }
683
   else if (!strcmp(interface, "wl_subcompositor"))
684
     {
685
        ewd->wl.subcompositor =
686
           wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
687
     }
688
   else if (!strcmp(interface, "wl_output"))
689
     _ecore_wl_output_add(ewd, id);
690
   else if (!strcmp(interface, "wl_seat"))
691
     _ecore_wl_input_add(ewd, id);
692
   else if (!strcmp(interface, "zwp_e_session_recovery") && getenv("EFL_WAYLAND_SESSION_RECOVERY"))
693
     {
694
        ewd->wl.session_recovery =
695
          wl_registry_bind(registry, id, &zwp_e_session_recovery_interface, 1);
696
     }
697
#ifdef USE_IVI_SHELL
698
   else if (!strcmp(interface, "ivi_application"))
699
     {
700
        ewd->wl.ivi_application =
701
          wl_registry_bind(registry, id, &ivi_application_interface, 1);
702
     }
703
#endif
704
   else if (!strcmp(interface, "xdg_shell") && !getenv("EFL_WAYLAND_DONT_USE_XDG_SHELL"))
705
     {
706
        Eina_Hash *h;
707
        Eina_Iterator *it;
708
        Ecore_Wl_Window *win;
709

710
        ewd->wl.xdg_shell =
711
          wl_registry_bind(registry, id, &xdg_shell_interface, 1);
712
        xdg_shell_use_unstable_version(ewd->wl.xdg_shell, XDG_VERSION);
713
        xdg_shell_add_listener(ewd->wl.xdg_shell, &xdg_shell_listener,
714
                               ewd->wl.display);
715
        h = _ecore_wl_window_hash_get();
716
        it = eina_hash_iterator_data_new(h);
717
        EINA_ITERATOR_FOREACH(it, win)
718
          if (win->surface)
719
            _ecore_wl_window_shell_surface_init(win);
720
     }
721
   else if (!strcmp(interface, "wl_shell"))
722
     {
723
        ewd->wl.shell =
724
          wl_registry_bind(registry, id, &wl_shell_interface, 1);
725
     }
726
   else if (!strcmp(interface, "wl_shm"))
727
     {
728
        ewd->wl.shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
729

730
        if (ewd->input)
731
          _ecore_wl_input_setup(ewd->input);
732
        else if (!ewd->cursor_theme)
733
          {
734
             ewd->cursor_theme =
735
               wl_cursor_theme_load(NULL, ECORE_WL_DEFAULT_CURSOR_SIZE,
736
                                    ewd->wl.shm);
737
          }
738
     }
739
   else if (!strcmp(interface, "wl_data_device_manager"))
740
     {
741
        ewd->wl.data_device_manager =
742
          wl_registry_bind(registry, id, &wl_data_device_manager_interface, 1);
743
     }
744

745
   if ((ewd->wl.compositor) && (ewd->wl.shm) &&
746
       ((ewd->wl.shell) || (ewd->wl.xdg_shell)))
747
     {
748
        Ecore_Wl_Event_Interfaces_Bound *ev;
749

750
        if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Interfaces_Bound))))
751
          return;
752

753
        ev->compositor = (ewd->wl.compositor != NULL);
754
        ev->shm = (ewd->wl.shm != NULL);
755
        ev->shell = ((ewd->wl.shell != NULL) || (ewd->wl.xdg_shell != NULL));
756
        ev->output = (ewd->output != NULL);
757
        ev->seat = (ewd->input != NULL);
758
        ev->data_device_manager = (ewd->wl.data_device_manager != NULL);
759
        ev->subcompositor = (ewd->wl.subcompositor != NULL);
760

761
        ecore_event_add(ECORE_WL_EVENT_INTERFACES_BOUND, ev, NULL, NULL);
762
     }
763
}
764

765
static void
766
_ecore_wl_cb_handle_global_remove(void *data, struct wl_registry *registry EINA_UNUSED, unsigned int id)
767
{
768
   Ecore_Wl_Display *ewd;
769
   Ecore_Wl_Global *global;
770
   Eina_Inlist *tmp;
771

772
   LOGFN;
773

774
   ewd = data;
775

776
   EINA_INLIST_FOREACH_SAFE(ewd->globals, tmp, global)
777
     {
778
        if (global->id != id) continue;
779
        ewd->globals =
780
          eina_inlist_remove(ewd->globals, EINA_INLIST_GET(global));
781
        free(global->interface);
782
        free(global);
783
     }
784
}
785

786
static Eina_Bool
787
_ecore_wl_xkb_init(Ecore_Wl_Display *ewd)
788
{
789
   LOGFN;
790

791
   if (!(ewd->xkb.context = xkb_context_new(0)))
792
     return EINA_FALSE;
793

794
   return EINA_TRUE;
795
}
796

797
static Eina_Bool
798
_ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd)
799
{
800
   LOGFN;
801

802
   xkb_context_unref(ewd->xkb.context);
803

804
   return EINA_TRUE;
805
}
806

807
static void
808
_ecore_wl_sync_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
809
{
810
   Ecore_Wl_Display *ewd = data;
811

812
   ewd->sync_ref_count--;
813
   wl_callback_destroy(callback);
814
}
815

816
static void
817
_ecore_wl_sync_wait(Ecore_Wl_Display *ewd)
818
{
819
   struct wl_callback *callback;
820

821
   ewd->sync_ref_count++;
822
   callback = wl_display_sync(ewd->wl.display);
823
   wl_callback_add_listener(callback, &_ecore_wl_sync_listener, ewd);
824
}
825

826
static void
827
_ecore_wl_animator_tick_cb_begin(void *data EINA_UNUSED)
828
{
829
   Eina_Hash *windows;
830

831
   _ecore_wl_animator_busy = EINA_TRUE;
832

833
   windows = _ecore_wl_window_hash_get();
834
   eina_hash_foreach(windows, _ecore_wl_animator_window_add, NULL);
835
}
836

837
static void
838
_ecore_wl_animator_tick_cb_end(void *data EINA_UNUSED)
839
{
840
   _ecore_wl_animator_busy = EINA_FALSE;
841
}
842

843
static void
844
_ecore_wl_animator_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
845
{
846
   Ecore_Wl_Window *win;
847

848
   if (!(win = data)) return;
849

850
   ecore_animator_custom_tick();
851

852
   wl_callback_destroy(callback);
853
   win->anim_callback = NULL;
854

855
   if (_ecore_wl_animator_busy)
856
     {
857
        win->anim_callback = wl_surface_frame(win->surface);
858
        wl_callback_add_listener(win->anim_callback,
859
                                 &_ecore_wl_anim_listener, win);
860
        ecore_wl_window_commit(win);
861
     }
862
}
863

864
static Eina_Bool
865
_ecore_wl_animator_window_add(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
866
{
867
   Ecore_Wl_Window *win;
868

869
   if (!(win = data)) return EINA_TRUE;
870
   if (!win->surface) return EINA_TRUE;
871
   if (win->anim_callback) return EINA_TRUE;
872

873
   win->anim_callback = wl_surface_frame(win->surface);
874
   wl_callback_add_listener(win->anim_callback, &_ecore_wl_anim_listener, win);
875
   ecore_wl_window_commit(win);
876

877
   return EINA_TRUE;
878
}
879

880
static void
881
_ecore_wl_signal_exit(void)
882
{
883
   Ecore_Event_Signal_Exit *ev;
884

885
   if (!(ev = calloc(1, sizeof(Ecore_Event_Signal_Exit))))
886
     return;
887

888
   ev->quit = 1;
889
   ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, ev,
890
                   _ecore_wl_signal_exit_free, NULL);
891
}
892

893
static void
894
_ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event)
895
{
896
   free(event);
897
}
898

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.