Blender  V2.93
GHOST_SystemWayland.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "GHOST_SystemWayland.h"
22 #include "GHOST_Event.h"
23 #include "GHOST_EventButton.h"
24 #include "GHOST_EventCursor.h"
25 #include "GHOST_EventDragnDrop.h"
26 #include "GHOST_EventKey.h"
27 #include "GHOST_EventWheel.h"
28 #include "GHOST_TimerManager.h"
29 #include "GHOST_WindowManager.h"
30 
31 #include "GHOST_ContextEGL.h"
32 
33 #include <EGL/egl.h>
34 #include <wayland-egl.h>
35 
36 #include <algorithm>
37 #include <atomic>
38 #include <stdexcept>
39 #include <thread>
40 #include <unordered_map>
41 #include <unordered_set>
42 
43 #include <pointer-constraints-client-protocol.h>
44 #include <relative-pointer-client-protocol.h>
45 #include <wayland-cursor.h>
46 #include <xkbcommon/xkbcommon.h>
47 
48 #include <fcntl.h>
49 #include <linux/input-event-codes.h>
50 #include <sys/mman.h>
51 #include <unistd.h>
52 
53 #include <cstring>
54 
55 struct output_t {
56  struct wl_output *output;
58  int transform;
59  int scale;
60  std::string make;
61  std::string model;
62 };
63 
64 struct buffer_t {
65  void *data;
66  size_t size;
67 };
68 
69 struct cursor_t {
70  bool visible;
71  struct wl_surface *surface = nullptr;
72  struct wl_buffer *buffer;
73  struct wl_cursor_image image;
74  struct buffer_t *file_buffer = nullptr;
75 };
76 
77 struct data_offer_t {
78  std::unordered_set<std::string> types;
81  struct wl_data_offer *id;
82  std::atomic<bool> in_use;
83  struct {
84  int x, y;
85  } dnd;
86 };
87 
88 struct data_source_t {
89  struct wl_data_source *data_source;
92  char *buffer_out;
93 };
94 
100 };
101 
102 struct input_t {
104 
105  std::string name;
106  struct wl_seat *seat;
107  struct wl_pointer *pointer = nullptr;
108  struct wl_keyboard *keyboard = nullptr;
109 
111  int x, y;
113  struct cursor_t cursor;
114 
115  struct zwp_relative_pointer_v1 *relative_pointer;
116  struct zwp_locked_pointer_v1 *locked_pointer;
117 
120  struct {
121  /* Key repetition in character per second. */
123  /* Time (milliseconds) after which to start repeating keys. */
125  /* Timer for key repeats. */
128 
129  struct wl_surface *focus_pointer = nullptr;
130  struct wl_surface *focus_keyboard = nullptr;
131 
132  struct wl_data_device *data_device = nullptr;
133  struct data_offer_t *data_offer_dnd; /* Drag & Drop. */
134  struct data_offer_t *data_offer_copy_paste; /* Copy & Paste. */
135 
137 };
138 
139 struct display_t {
141 
142  struct wl_display *display;
143  struct wl_compositor *compositor = nullptr;
144  struct xdg_wm_base *xdg_shell = nullptr;
145  struct wl_shm *shm = nullptr;
146  std::vector<output_t *> outputs;
147  std::vector<input_t *> inputs;
148  struct wl_cursor_theme *cursor_theme = nullptr;
149  struct wl_data_device_manager *data_device_manager = nullptr;
150  struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
151  struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
152 
153  std::vector<struct wl_surface *> os_surfaces;
154  std::vector<struct wl_egl_window *> os_egl_windows;
155 };
156 
157 static void display_destroy(display_t *d)
158 {
159  if (d->data_device_manager) {
160  wl_data_device_manager_destroy(d->data_device_manager);
161  }
162 
163  for (output_t *output : d->outputs) {
164  wl_output_destroy(output->output);
165  delete output;
166  }
167 
168  for (input_t *input : d->inputs) {
169  if (input->data_source) {
170  free(input->data_source->buffer_out);
171  if (input->data_source->data_source) {
172  wl_data_source_destroy(input->data_source->data_source);
173  }
174  delete input->data_source;
175  }
176  if (input->data_offer_copy_paste) {
177  wl_data_offer_destroy(input->data_offer_copy_paste->id);
178  delete input->data_offer_copy_paste;
179  }
180  if (input->data_device) {
181  wl_data_device_release(input->data_device);
182  }
183  if (input->pointer) {
184  if (input->cursor.file_buffer) {
185  munmap(input->cursor.file_buffer->data, input->cursor.file_buffer->size);
186  delete input->cursor.file_buffer;
187  }
188  if (input->cursor.surface) {
189  wl_surface_destroy(input->cursor.surface);
190  }
191  if (input->pointer) {
192  wl_pointer_destroy(input->pointer);
193  }
194  }
195  if (input->keyboard) {
196  if (input->key_repeat.timer) {
197  delete static_cast<key_repeat_payload_t *>(input->key_repeat.timer->getUserData());
198  input->system->removeTimer(input->key_repeat.timer);
199  input->key_repeat.timer = nullptr;
200  }
201  wl_keyboard_destroy(input->keyboard);
202  }
203  if (input->xkb_state) {
204  xkb_state_unref(input->xkb_state);
205  }
206  if (input->xkb_context) {
207  xkb_context_unref(input->xkb_context);
208  }
209  wl_seat_destroy(input->seat);
210  delete input;
211  }
212 
213  if (d->cursor_theme) {
214  wl_cursor_theme_destroy(d->cursor_theme);
215  }
216 
217  if (d->shm) {
218  wl_shm_destroy(d->shm);
219  }
220 
221  if (d->relative_pointer_manager) {
222  zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager);
223  }
224 
225  if (d->pointer_constraints) {
226  zwp_pointer_constraints_v1_destroy(d->pointer_constraints);
227  }
228 
229  for (wl_egl_window *os_egl_window : d->os_egl_windows) {
230  wl_egl_window_destroy(os_egl_window);
231  }
232 
233  for (wl_surface *os_surface : d->os_surfaces) {
234  wl_surface_destroy(os_surface);
235  }
236 
237  if (d->compositor) {
238  wl_compositor_destroy(d->compositor);
239  }
240 
241  if (d->xdg_shell) {
242  xdg_wm_base_destroy(d->xdg_shell);
243  }
244 
245  if (eglGetDisplay) {
246  ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
247  }
248 
249  if (d->display) {
250  wl_display_disconnect(d->display);
251  }
252 
253  delete d;
254 }
255 
256 static GHOST_TKey xkb_map_gkey(const xkb_keysym_t &sym)
257 {
258 
259  GHOST_TKey gkey;
260  if (sym >= XKB_KEY_0 && sym <= XKB_KEY_9) {
261  gkey = GHOST_TKey(sym);
262  }
263  else if (sym >= XKB_KEY_KP_0 && sym <= XKB_KEY_KP_9) {
264  gkey = GHOST_TKey(GHOST_kKeyNumpad0 + sym - XKB_KEY_KP_0);
265  }
266  else if (sym >= XKB_KEY_A && sym <= XKB_KEY_Z) {
267  gkey = GHOST_TKey(sym);
268  }
269  else if (sym >= XKB_KEY_a && sym <= XKB_KEY_z) {
270  gkey = GHOST_TKey(sym - XKB_KEY_a + XKB_KEY_A);
271  }
272  else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F24) {
273  gkey = GHOST_TKey(GHOST_kKeyF1 + sym - XKB_KEY_F1);
274  }
275  else {
276 
277 #define GXMAP(k, x, y) \
278  case x: \
279  k = y; \
280  break
281 
282  switch (sym) {
283  GXMAP(gkey, XKB_KEY_BackSpace, GHOST_kKeyBackSpace);
284  GXMAP(gkey, XKB_KEY_Tab, GHOST_kKeyTab);
285  GXMAP(gkey, XKB_KEY_Linefeed, GHOST_kKeyLinefeed);
286  GXMAP(gkey, XKB_KEY_Clear, GHOST_kKeyClear);
287  GXMAP(gkey, XKB_KEY_Return, GHOST_kKeyEnter);
288 
289  GXMAP(gkey, XKB_KEY_Escape, GHOST_kKeyEsc);
290  GXMAP(gkey, XKB_KEY_space, GHOST_kKeySpace);
291  GXMAP(gkey, XKB_KEY_apostrophe, GHOST_kKeyQuote);
292  GXMAP(gkey, XKB_KEY_comma, GHOST_kKeyComma);
293  GXMAP(gkey, XKB_KEY_minus, GHOST_kKeyMinus);
294  GXMAP(gkey, XKB_KEY_plus, GHOST_kKeyPlus);
295  GXMAP(gkey, XKB_KEY_period, GHOST_kKeyPeriod);
296  GXMAP(gkey, XKB_KEY_slash, GHOST_kKeySlash);
297 
298  GXMAP(gkey, XKB_KEY_semicolon, GHOST_kKeySemicolon);
299  GXMAP(gkey, XKB_KEY_equal, GHOST_kKeyEqual);
300 
301  GXMAP(gkey, XKB_KEY_bracketleft, GHOST_kKeyLeftBracket);
302  GXMAP(gkey, XKB_KEY_bracketright, GHOST_kKeyRightBracket);
303  GXMAP(gkey, XKB_KEY_backslash, GHOST_kKeyBackslash);
304  GXMAP(gkey, XKB_KEY_grave, GHOST_kKeyAccentGrave);
305 
306  GXMAP(gkey, XKB_KEY_Shift_L, GHOST_kKeyLeftShift);
307  GXMAP(gkey, XKB_KEY_Shift_R, GHOST_kKeyRightShift);
308  GXMAP(gkey, XKB_KEY_Control_L, GHOST_kKeyLeftControl);
309  GXMAP(gkey, XKB_KEY_Control_R, GHOST_kKeyRightControl);
310  GXMAP(gkey, XKB_KEY_Alt_L, GHOST_kKeyLeftAlt);
311  GXMAP(gkey, XKB_KEY_Alt_R, GHOST_kKeyRightAlt);
312  GXMAP(gkey, XKB_KEY_Super_L, GHOST_kKeyOS);
313  GXMAP(gkey, XKB_KEY_Super_R, GHOST_kKeyOS);
314  GXMAP(gkey, XKB_KEY_Menu, GHOST_kKeyApp);
315 
316  GXMAP(gkey, XKB_KEY_Caps_Lock, GHOST_kKeyCapsLock);
317  GXMAP(gkey, XKB_KEY_Num_Lock, GHOST_kKeyNumLock);
318  GXMAP(gkey, XKB_KEY_Scroll_Lock, GHOST_kKeyScrollLock);
319 
320  GXMAP(gkey, XKB_KEY_Left, GHOST_kKeyLeftArrow);
321  GXMAP(gkey, XKB_KEY_Right, GHOST_kKeyRightArrow);
322  GXMAP(gkey, XKB_KEY_Up, GHOST_kKeyUpArrow);
323  GXMAP(gkey, XKB_KEY_Down, GHOST_kKeyDownArrow);
324 
325  GXMAP(gkey, XKB_KEY_Print, GHOST_kKeyPrintScreen);
326  GXMAP(gkey, XKB_KEY_Pause, GHOST_kKeyPause);
327 
328  GXMAP(gkey, XKB_KEY_Insert, GHOST_kKeyInsert);
329  GXMAP(gkey, XKB_KEY_Delete, GHOST_kKeyDelete);
330  GXMAP(gkey, XKB_KEY_Home, GHOST_kKeyHome);
331  GXMAP(gkey, XKB_KEY_End, GHOST_kKeyEnd);
332  GXMAP(gkey, XKB_KEY_Page_Up, GHOST_kKeyUpPage);
333  GXMAP(gkey, XKB_KEY_Page_Down, GHOST_kKeyDownPage);
334 
335  GXMAP(gkey, XKB_KEY_KP_Decimal, GHOST_kKeyNumpadPeriod);
336  GXMAP(gkey, XKB_KEY_KP_Enter, GHOST_kKeyNumpadEnter);
337  GXMAP(gkey, XKB_KEY_KP_Add, GHOST_kKeyNumpadPlus);
338  GXMAP(gkey, XKB_KEY_KP_Subtract, GHOST_kKeyNumpadMinus);
339  GXMAP(gkey, XKB_KEY_KP_Multiply, GHOST_kKeyNumpadAsterisk);
340  GXMAP(gkey, XKB_KEY_KP_Divide, GHOST_kKeyNumpadSlash);
341 
342  GXMAP(gkey, XKB_KEY_XF86AudioPlay, GHOST_kKeyMediaPlay);
343  GXMAP(gkey, XKB_KEY_XF86AudioStop, GHOST_kKeyMediaStop);
344  GXMAP(gkey, XKB_KEY_XF86AudioPrev, GHOST_kKeyMediaFirst);
345  GXMAP(gkey, XKB_KEY_XF86AudioNext, GHOST_kKeyMediaLast);
346  default:
347  GHOST_PRINT("unhandled key: " << std::hex << std::showbase << sym << std::dec << " ("
348  << sym << ")" << std::endl);
349  gkey = GHOST_kKeyUnknown;
350  }
351 #undef GXMAP
352  }
353 
354  return gkey;
355 }
356 
357 static const int default_cursor_size = 24;
358 
359 static const std::unordered_map<GHOST_TStandardCursor, std::string> cursors = {
360  {GHOST_kStandardCursorDefault, "left_ptr"},
361  {GHOST_kStandardCursorRightArrow, "right_ptr"},
362  {GHOST_kStandardCursorLeftArrow, "left_ptr"},
365  {GHOST_kStandardCursorHelp, "question_arrow"},
366  {GHOST_kStandardCursorWait, "watch"},
367  {GHOST_kStandardCursorText, "xterm"},
368  {GHOST_kStandardCursorCrosshair, "crosshair"},
373  {GHOST_kStandardCursorUpArrow, "sb_up_arrow"},
374  {GHOST_kStandardCursorDownArrow, "sb_down_arrow"},
382  {GHOST_kStandardCursorMove, "move"},
387  {GHOST_kStandardCursorUpDown, "sb_v_double_arrow"},
388  {GHOST_kStandardCursorLeftRight, "sb_h_double_arrow"},
389  {GHOST_kStandardCursorTopSide, "top_side"},
390  {GHOST_kStandardCursorBottomSide, "bottom_side"},
391  {GHOST_kStandardCursorLeftSide, "left_side"},
392  {GHOST_kStandardCursorRightSide, "right_side"},
393  {GHOST_kStandardCursorTopLeftCorner, "top_left_corner"},
394  {GHOST_kStandardCursorTopRightCorner, "top_right_corner"},
395  {GHOST_kStandardCursorBottomRightCorner, "bottom_right_corner"},
396  {GHOST_kStandardCursorBottomLeftCorner, "bottom_left_corner"},
397  {GHOST_kStandardCursorCopy, "copy"},
398 };
399 
400 static constexpr const char *mime_text_plain = "text/plain";
401 static constexpr const char *mime_text_utf8 = "text/plain;charset=utf-8";
402 static constexpr const char *mime_text_uri = "text/uri-list";
403 
404 static const std::unordered_map<std::string, GHOST_TDragnDropTypes> mime_dnd = {
408 };
409 
410 static const std::vector<std::string> mime_preference_order = {
414 };
415 
416 static const std::vector<std::string> mime_send = {
417  "UTF8_STRING",
418  "COMPOUND_TEXT",
419  "TEXT",
420  "STRING",
421  "text/plain;charset=utf-8",
422  "text/plain",
423 };
424 
425 /* -------------------------------------------------------------------- */
433  void *data,
434  struct zwp_relative_pointer_v1 * /*zwp_relative_pointer_v1*/,
435  uint32_t /*utime_hi*/,
436  uint32_t /*utime_lo*/,
437  wl_fixed_t dx,
438  wl_fixed_t dy,
439  wl_fixed_t /*dx_unaccel*/,
440  wl_fixed_t /*dy_unaccel*/)
441 {
442  input_t *input = static_cast<input_t *>(data);
443 
444  input->x += wl_fixed_to_int(dx);
445  input->y += wl_fixed_to_int(dy);
446 
447  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
448  wl_surface_get_user_data(input->focus_pointer));
449 
452  win,
453  input->x,
454  input->y,
456 }
457 
458 static const zwp_relative_pointer_v1_listener relative_pointer_listener = {
460 };
461 
462 static void dnd_events(const input_t *const input, const GHOST_TEventType event)
463 {
464  const GHOST_TUns64 time = input->system->getMilliSeconds();
465  GHOST_IWindow *const window = static_cast<GHOST_WindowWayland *>(
466  wl_surface_get_user_data(input->focus_pointer));
467  for (const std::string &type : mime_preference_order) {
469  event,
470  mime_dnd.at(type),
471  window,
472  input->data_offer_dnd->dnd.x,
473  input->data_offer_dnd->dnd.y,
474  nullptr));
475  }
476 }
477 
478 static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive)
479 {
480  int pipefd[2];
481  pipe(pipefd);
482  wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
483  close(pipefd[1]);
484 
485  std::string data;
486  ssize_t len;
487  char buffer[4096];
488  while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
489  data.insert(data.end(), buffer, buffer + len);
490  }
491  close(pipefd[0]);
492  data_offer->in_use.store(false);
493 
494  return data;
495 }
496 
503 static void data_source_target(void * /*data*/,
504  struct wl_data_source * /*wl_data_source*/,
505  const char * /*mime_type*/)
506 {
507  /* pass */
508 }
509 
510 static void data_source_send(void *data,
511  struct wl_data_source * /*wl_data_source*/,
512  const char * /*mime_type*/,
513  int32_t fd)
514 {
515  const char *const buffer = static_cast<char *>(data);
516  write(fd, buffer, strlen(buffer) + 1);
517  close(fd);
518 }
519 
520 static void data_source_cancelled(void * /*data*/, struct wl_data_source *wl_data_source)
521 {
522  wl_data_source_destroy(wl_data_source);
523 }
524 
532 static void data_source_dnd_drop_performed(void * /*data*/,
533  struct wl_data_source * /*wl_data_source*/)
534 {
535  /* pass */
536 }
537 
545 static void data_source_dnd_finished(void * /*data*/, struct wl_data_source * /*wl_data_source*/)
546 {
547  /* pass */
548 }
549 
557 static void data_source_action(void * /*data*/,
558  struct wl_data_source * /*wl_data_source*/,
559  uint32_t /*dnd_action*/)
560 {
561  /* pass */
562 }
563 
564 static const struct wl_data_source_listener data_source_listener = {
571 };
572 
573 static void data_offer_offer(void *data,
574  struct wl_data_offer * /*wl_data_offer*/,
575  const char *mime_type)
576 {
577  static_cast<data_offer_t *>(data)->types.insert(mime_type);
578 }
579 
580 static void data_offer_source_actions(void *data,
581  struct wl_data_offer * /*wl_data_offer*/,
582  uint32_t source_actions)
583 {
584  static_cast<data_offer_t *>(data)->source_actions = source_actions;
585 }
586 
587 static void data_offer_action(void *data,
588  struct wl_data_offer * /*wl_data_offer*/,
589  uint32_t dnd_action)
590 {
591  static_cast<data_offer_t *>(data)->dnd_action = dnd_action;
592 }
593 
594 static const struct wl_data_offer_listener data_offer_listener = {
598 };
599 
600 static void data_device_data_offer(void * /*data*/,
601  struct wl_data_device * /*wl_data_device*/,
602  struct wl_data_offer *id)
603 {
604  data_offer_t *data_offer = new data_offer_t;
605  data_offer->id = id;
606  wl_data_offer_add_listener(id, &data_offer_listener, data_offer);
607 }
608 
609 static void data_device_enter(void *data,
610  struct wl_data_device * /*wl_data_device*/,
611  uint32_t serial,
612  struct wl_surface * /*surface*/,
613  wl_fixed_t x,
614  wl_fixed_t y,
615  struct wl_data_offer *id)
616 {
617  input_t *input = static_cast<input_t *>(data);
618  input->data_offer_dnd = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id));
619  data_offer_t *data_offer = input->data_offer_dnd;
620 
621  data_offer->in_use.store(true);
622  data_offer->dnd.x = wl_fixed_to_int(x);
623  data_offer->dnd.y = wl_fixed_to_int(y);
624 
625  wl_data_offer_set_actions(id,
626  WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
627  WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
628  WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
629 
630  for (const std::string &type : mime_preference_order) {
631  wl_data_offer_accept(id, serial, type.c_str());
632  }
633 
635 }
636 
637 static void data_device_leave(void *data, struct wl_data_device * /*wl_data_device*/)
638 {
639  input_t *input = static_cast<input_t *>(data);
640 
642 
643  if (input->data_offer_dnd && !input->data_offer_dnd->in_use.load()) {
644  wl_data_offer_destroy(input->data_offer_dnd->id);
645  delete input->data_offer_dnd;
646  input->data_offer_dnd = nullptr;
647  }
648 }
649 
650 static void data_device_motion(void *data,
651  struct wl_data_device * /*wl_data_device*/,
652  uint32_t /*time*/,
653  wl_fixed_t x,
654  wl_fixed_t y)
655 {
656  input_t *input = static_cast<input_t *>(data);
657  input->data_offer_dnd->dnd.x = wl_fixed_to_int(x);
658  input->data_offer_dnd->dnd.y = wl_fixed_to_int(y);
660 }
661 
662 static void data_device_drop(void *data, struct wl_data_device * /*wl_data_device*/)
663 {
664  input_t *input = static_cast<input_t *>(data);
665  data_offer_t *data_offer = input->data_offer_dnd;
666 
667  const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(),
668  mime_preference_order.end(),
669  data_offer->types.begin(),
670  data_offer->types.end());
671 
672  auto read_uris = [](input_t *const input,
673  data_offer_t *data_offer,
674  const std::string mime_receive) {
675  const int x = data_offer->dnd.x;
676  const int y = data_offer->dnd.y;
677 
678  const std::string data = read_pipe(data_offer, mime_receive);
679 
680  wl_data_offer_finish(data_offer->id);
681  wl_data_offer_destroy(data_offer->id);
682 
683  delete data_offer;
684  data_offer = nullptr;
685 
686  GHOST_SystemWayland *const system = input->system;
687 
688  if (mime_receive == mime_text_uri) {
689  static constexpr const char *file_proto = "file://";
690  static constexpr const char *crlf = "\r\n";
691 
692  std::vector<std::string> uris;
693 
694  size_t pos = 0;
695  while (true) {
696  pos = data.find(file_proto, pos);
697  const size_t start = pos + sizeof(file_proto) - 1;
698  pos = data.find(crlf, pos);
699  const size_t end = pos;
700 
701  if (pos == std::string::npos) {
702  break;
703  }
704  uris.push_back(data.substr(start, end - start));
705  }
706 
707  GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>(
708  malloc(sizeof(GHOST_TStringArray)));
709  flist->count = int(uris.size());
710  flist->strings = static_cast<GHOST_TUns8 **>(malloc(uris.size() * sizeof(GHOST_TUns8 *)));
711  for (size_t i = 0; i < uris.size(); i++) {
712  flist->strings[i] = static_cast<GHOST_TUns8 *>(
713  malloc((uris[i].size() + 1) * sizeof(GHOST_TUns8)));
714  memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1);
715  }
716  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
717  wl_surface_get_user_data(input->focus_pointer));
718  system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
721  win,
722  x,
723  y,
724  flist));
725  }
726  else if (mime_receive == mime_text_plain || mime_receive == mime_text_utf8) {
727  /* TODO: enable use of internal functions 'txt_insert_buf' and
728  * 'text_update_edited' to behave like dropped text was pasted. */
729  }
730  wl_display_roundtrip(system->display());
731  };
732 
733  std::thread read_thread(read_uris, input, data_offer, mime_receive);
734  read_thread.detach();
735 }
736 
737 static void data_device_selection(void *data,
738  struct wl_data_device * /*wl_data_device*/,
739  struct wl_data_offer *id)
740 {
741  input_t *input = static_cast<input_t *>(data);
742  data_offer_t *data_offer = input->data_offer_copy_paste;
743 
744  /* Delete old data offer. */
745  if (data_offer != nullptr) {
746  wl_data_offer_destroy(data_offer->id);
747  delete data_offer;
748  data_offer = nullptr;
749  }
750 
751  if (id == nullptr) {
752  return;
753  }
754 
755  /* Get new data offer. */
756  data_offer = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id));
757  input->data_offer_copy_paste = data_offer;
758 
759  std::string mime_receive;
760  for (const std::string &type : {mime_text_utf8, mime_text_plain}) {
761  if (data_offer->types.count(type)) {
762  mime_receive = type;
763  break;
764  }
765  }
766 
767  auto read_selection = [](GHOST_SystemWayland *const system,
768  data_offer_t *data_offer,
769  const std::string mime_receive) {
770  const std::string data = read_pipe(data_offer, mime_receive);
771  system->setSelection(data);
772  };
773 
774  std::thread read_thread(read_selection, input->system, data_offer, mime_receive);
775  read_thread.detach();
776 }
777 
778 static const struct wl_data_device_listener data_device_listener = {
785 };
786 
787 static void cursor_buffer_release(void *data, struct wl_buffer *wl_buffer)
788 {
789  cursor_t *cursor = static_cast<cursor_t *>(data);
790 
791  wl_buffer_destroy(wl_buffer);
792  cursor->buffer = nullptr;
793 }
794 
795 const struct wl_buffer_listener cursor_buffer_listener = {
797 };
798 
799 static void pointer_enter(void *data,
800  struct wl_pointer * /*wl_pointer*/,
801  uint32_t serial,
802  struct wl_surface *surface,
803  wl_fixed_t surface_x,
804  wl_fixed_t surface_y)
805 {
806  if (!surface) {
807  return;
808  }
809  input_t *input = static_cast<input_t *>(data);
810  input->pointer_serial = serial;
811  input->x = wl_fixed_to_int(surface_x);
812  input->y = wl_fixed_to_int(surface_y);
813  input->focus_pointer = surface;
814 
815  input->system->pushEvent(
818  static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface)),
819  input->x,
820  input->y,
822 }
823 
824 static void pointer_leave(void *data,
825  struct wl_pointer * /*wl_pointer*/,
826  uint32_t /*serial*/,
827  struct wl_surface *surface)
828 {
829  if (surface != nullptr) {
830  static_cast<input_t *>(data)->focus_pointer = nullptr;
831  }
832 }
833 
834 static void pointer_motion(void *data,
835  struct wl_pointer * /*wl_pointer*/,
836  uint32_t /*time*/,
837  wl_fixed_t surface_x,
838  wl_fixed_t surface_y)
839 {
840  input_t *input = static_cast<input_t *>(data);
841 
842  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
843  wl_surface_get_user_data(input->focus_pointer));
844 
845  if (!win) {
846  return;
847  }
848 
849  input->x = wl_fixed_to_int(surface_x);
850  input->y = wl_fixed_to_int(surface_y);
851 
854  win,
855  wl_fixed_to_int(surface_x),
856  wl_fixed_to_int(surface_y),
858 }
859 
860 static void pointer_button(void *data,
861  struct wl_pointer * /*wl_pointer*/,
862  uint32_t serial,
863  uint32_t /*time*/,
864  uint32_t button,
865  uint32_t state)
866 {
868  switch (state) {
869  case WL_POINTER_BUTTON_STATE_RELEASED:
870  etype = GHOST_kEventButtonUp;
871  break;
872  case WL_POINTER_BUTTON_STATE_PRESSED:
873  etype = GHOST_kEventButtonDown;
874  break;
875  }
876 
878  switch (button) {
879  case BTN_LEFT:
880  ebutton = GHOST_kButtonMaskLeft;
881  break;
882  case BTN_MIDDLE:
883  ebutton = GHOST_kButtonMaskMiddle;
884  break;
885  case BTN_RIGHT:
886  ebutton = GHOST_kButtonMaskRight;
887  break;
888  }
889 
890  input_t *input = static_cast<input_t *>(data);
891  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
892  wl_surface_get_user_data(input->focus_pointer));
893  input->data_source->source_serial = serial;
894  input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
895  input->system->pushEvent(new GHOST_EventButton(
896  input->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE));
897 }
898 
899 static void pointer_axis(void *data,
900  struct wl_pointer * /*wl_pointer*/,
901  uint32_t /*time*/,
902  uint32_t axis,
903  wl_fixed_t value)
904 {
905  if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
906  return;
907  }
908  input_t *input = static_cast<input_t *>(data);
909  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
910  wl_surface_get_user_data(input->focus_pointer));
911  input->system->pushEvent(
912  new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1));
913 }
914 
915 static const struct wl_pointer_listener pointer_listener = {
920  pointer_axis,
921 };
922 
923 static void keyboard_keymap(
924  void *data, struct wl_keyboard * /*wl_keyboard*/, uint32_t format, int32_t fd, uint32_t size)
925 {
926  input_t *input = static_cast<input_t *>(data);
927 
928  if ((!data) || (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)) {
929  close(fd);
930  return;
931  }
932 
933  char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0));
934  if (map_str == MAP_FAILED) {
935  close(fd);
936  throw std::runtime_error("keymap mmap failed: " + std::string(std::strerror(errno)));
937  }
938 
939  struct xkb_keymap *keymap = xkb_keymap_new_from_string(
940  input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
941  munmap(map_str, size);
942  close(fd);
943 
944  if (!keymap) {
945  return;
946  }
947 
948  input->xkb_state = xkb_state_new(keymap);
949 
950  xkb_keymap_unref(keymap);
951 }
952 
959 static void keyboard_enter(void *data,
960  struct wl_keyboard * /*wl_keyboard*/,
961  uint32_t /*serial*/,
962  struct wl_surface *surface,
963  struct wl_array * /*keys*/)
964 {
965  if (surface != nullptr) {
966  static_cast<input_t *>(data)->focus_keyboard = surface;
967  }
968 }
969 
976 static void keyboard_leave(void *data,
977  struct wl_keyboard * /*wl_keyboard*/,
978  uint32_t /*serial*/,
979  struct wl_surface *surface)
980 {
981  if (surface != nullptr) {
982  static_cast<input_t *>(data)->focus_keyboard = nullptr;
983  }
984 }
985 
990 static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(struct xkb_state *xkb_state,
991  xkb_keycode_t key)
992 {
993  /* Use an empty keyboard state to access key symbol without modifiers. */
994  xkb_state_get_keymap(xkb_state);
995  struct xkb_keymap *keymap = xkb_state_get_keymap(xkb_state);
996  struct xkb_state *xkb_state_empty = xkb_state_new(keymap);
997 
998  /* Enable number-lock. */
999  {
1000  const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
1001  const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock");
1002  if (num != XKB_MOD_INVALID && mod2 != XKB_MOD_INVALID) {
1003  xkb_state_update_mask(xkb_state_empty, (1 << mod2), 0, (1 << num), 0, 0, 0);
1004  }
1005  }
1006 
1007  const xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state_empty, key);
1008  xkb_state_unref(xkb_state_empty);
1009  return sym;
1010 }
1011 
1012 static void keyboard_key(void *data,
1013  struct wl_keyboard * /*wl_keyboard*/,
1014  uint32_t serial,
1015  uint32_t /*time*/,
1016  uint32_t key,
1017  uint32_t state)
1018 {
1019  input_t *input = static_cast<input_t *>(data);
1020 
1022  switch (state) {
1023  case WL_KEYBOARD_KEY_STATE_RELEASED:
1024  etype = GHOST_kEventKeyUp;
1025  break;
1026  case WL_KEYBOARD_KEY_STATE_PRESSED:
1027  etype = GHOST_kEventKeyDown;
1028  break;
1029  }
1030 
1031  const xkb_keysym_t sym = xkb_state_key_get_one_sym_without_modifiers(input->xkb_state, key + 8);
1032 
1033  if (sym == XKB_KEY_NoSymbol) {
1034  return;
1035  }
1036  const GHOST_TKey gkey = xkb_map_gkey(sym);
1037 
1038  /* Delete previous timer. */
1039  if (xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key + 8) &&
1040  input->key_repeat.timer) {
1041  delete static_cast<key_repeat_payload_t *>(input->key_repeat.timer->getUserData());
1042  input->system->removeTimer(input->key_repeat.timer);
1043  input->key_repeat.timer = nullptr;
1044  }
1045 
1046  GHOST_TEventKeyData key_data;
1047 
1048  if (etype == GHOST_kEventKeyDown) {
1049  xkb_state_key_get_utf8(
1050  input->xkb_state, key + 8, key_data.utf8_buf, sizeof(GHOST_TEventKeyData::utf8_buf));
1051  }
1052  else {
1053  key_data.utf8_buf[0] = '\0';
1054  }
1055 
1056  input->data_source->source_serial = serial;
1057 
1058  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
1059  wl_surface_get_user_data(input->focus_keyboard));
1060  input->system->pushEvent(new GHOST_EventKey(
1061  input->system->getMilliSeconds(), etype, win, gkey, '\0', key_data.utf8_buf, false));
1062 
1063  /* Start timer for repeating key, if applicable. */
1064  if (input->key_repeat.rate > 0 &&
1065  xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key + 8) &&
1066  etype == GHOST_kEventKeyDown) {
1067 
1069  .system = input->system,
1070  .window = win,
1071  .key = gkey,
1072  .key_data = key_data,
1073  });
1074 
1075  auto cb = [](GHOST_ITimerTask *task, GHOST_TUns64 /*time*/) {
1076  struct key_repeat_payload_t *payload = static_cast<key_repeat_payload_t *>(
1077  task->getUserData());
1078  payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(),
1080  payload->window,
1081  payload->key,
1082  '\0',
1083  payload->key_data.utf8_buf,
1084  true));
1085  };
1086  input->key_repeat.timer = input->system->installTimer(
1087  input->key_repeat.delay, 1000 / input->key_repeat.rate, cb, payload);
1088  }
1089 }
1090 
1091 static void keyboard_modifiers(void *data,
1092  struct wl_keyboard * /*wl_keyboard*/,
1093  uint32_t /*serial*/,
1094  uint32_t mods_depressed,
1095  uint32_t mods_latched,
1096  uint32_t mods_locked,
1097  uint32_t group)
1098 {
1099  xkb_state_update_mask(static_cast<input_t *>(data)->xkb_state,
1100  mods_depressed,
1101  mods_latched,
1102  mods_locked,
1103  0,
1104  0,
1105  group);
1106 }
1107 
1108 static void keyboard_repeat_info(void *data,
1109  struct wl_keyboard * /*wl_keyboard*/,
1110  int32_t rate,
1111  int32_t delay)
1112 {
1113  input_t *input = static_cast<input_t *>(data);
1114 
1115  input->key_repeat.rate = rate;
1116  input->key_repeat.delay = delay;
1117 }
1118 
1119 static const struct wl_keyboard_listener keyboard_listener = {
1123  keyboard_key,
1126 };
1127 
1128 static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
1129 {
1130  input_t *input = static_cast<input_t *>(data);
1131  input->pointer = nullptr;
1132  input->keyboard = nullptr;
1133 
1134  if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
1135  input->pointer = wl_seat_get_pointer(wl_seat);
1136  input->cursor.surface = wl_compositor_create_surface(input->system->compositor());
1137  input->cursor.visible = true;
1138  input->cursor.buffer = nullptr;
1139  input->cursor.file_buffer = new buffer_t;
1140  wl_pointer_add_listener(input->pointer, &pointer_listener, data);
1141  }
1142 
1143  if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
1144  input->keyboard = wl_seat_get_keyboard(wl_seat);
1145  wl_keyboard_add_listener(input->keyboard, &keyboard_listener, data);
1146  }
1147 }
1148 
1149 static void seat_name(void *data, struct wl_seat * /*wl_seat*/, const char *name)
1150 {
1151  static_cast<input_t *>(data)->name = std::string(name);
1152 }
1153 
1154 static const struct wl_seat_listener seat_listener = {
1156  seat_name,
1157 };
1158 
1159 static void output_geometry(void *data,
1160  struct wl_output * /*wl_output*/,
1161  int32_t /*x*/,
1162  int32_t /*y*/,
1163  int32_t /*physical_width*/,
1164  int32_t /*physical_height*/,
1165  int32_t /*subpixel*/,
1166  const char *make,
1167  const char *model,
1169 {
1170  output_t *output = static_cast<output_t *>(data);
1171  output->transform = transform;
1172  output->make = std::string(make);
1173  output->model = std::string(model);
1174 }
1175 
1176 static void output_mode(void *data,
1177  struct wl_output * /*wl_output*/,
1178  uint32_t /*flags*/,
1179  int32_t width,
1180  int32_t height,
1181  int32_t /*refresh*/)
1182 {
1183  output_t *output = static_cast<output_t *>(data);
1184  output->width = width;
1185  output->height = height;
1186 }
1187 
1196 static void output_done(void * /*data*/, struct wl_output * /*wl_output*/)
1197 {
1198 }
1199 
1200 static void output_scale(void *data, struct wl_output * /*wl_output*/, int32_t factor)
1201 {
1202  static_cast<output_t *>(data)->scale = factor;
1203 }
1204 
1205 static const struct wl_output_listener output_listener = {
1207  output_mode,
1208  output_done,
1209  output_scale,
1210 };
1211 
1212 static void shell_ping(void * /*data*/, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
1213 {
1214  xdg_wm_base_pong(xdg_wm_base, serial);
1215 }
1216 
1217 static const struct xdg_wm_base_listener shell_listener = {
1218  shell_ping,
1219 };
1220 
1221 static void global_add(void *data,
1222  struct wl_registry *wl_registry,
1223  uint32_t name,
1224  const char *interface,
1225  uint32_t /*version*/)
1226 {
1227  struct display_t *display = static_cast<struct display_t *>(data);
1228  if (!strcmp(interface, wl_compositor_interface.name)) {
1229  display->compositor = static_cast<wl_compositor *>(
1230  wl_registry_bind(wl_registry, name, &wl_compositor_interface, 1));
1231  }
1232  else if (!strcmp(interface, xdg_wm_base_interface.name)) {
1233  display->xdg_shell = static_cast<xdg_wm_base *>(
1234  wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
1235  xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr);
1236  }
1237  else if (!strcmp(interface, wl_output_interface.name)) {
1238  output_t *output = new output_t;
1239  output->scale = 1;
1240  output->output = static_cast<wl_output *>(
1241  wl_registry_bind(wl_registry, name, &wl_output_interface, 2));
1242  display->outputs.push_back(output);
1243  wl_output_add_listener(output->output, &output_listener, output);
1244  }
1245  else if (!strcmp(interface, wl_seat_interface.name)) {
1246  input_t *input = new input_t;
1247  input->system = display->system;
1248  input->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
1249  input->xkb_state = nullptr;
1250  input->data_offer_dnd = nullptr;
1251  input->data_offer_copy_paste = nullptr;
1252  input->data_source = new data_source_t;
1253  input->data_source->data_source = nullptr;
1254  input->data_source->buffer_out = nullptr;
1255  input->relative_pointer = nullptr;
1256  input->locked_pointer = nullptr;
1257  input->seat = static_cast<wl_seat *>(
1258  wl_registry_bind(wl_registry, name, &wl_seat_interface, 4));
1259  display->inputs.push_back(input);
1260  wl_seat_add_listener(input->seat, &seat_listener, input);
1261  }
1262  else if (!strcmp(interface, wl_shm_interface.name)) {
1263  display->shm = static_cast<wl_shm *>(
1264  wl_registry_bind(wl_registry, name, &wl_shm_interface, 1));
1265  }
1266  else if (!strcmp(interface, wl_data_device_manager_interface.name)) {
1267  display->data_device_manager = static_cast<wl_data_device_manager *>(
1268  wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 1));
1269  }
1270  else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) {
1271  display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(
1272  wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1));
1273  }
1274  else if (!strcmp(interface, zwp_pointer_constraints_v1_interface.name)) {
1275  display->pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>(
1276  wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1));
1277  }
1278 }
1279 
1289 static void global_remove(void * /*data*/, struct wl_registry * /*wl_registry*/, uint32_t /*name*/)
1290 {
1291 }
1292 
1293 static const struct wl_registry_listener registry_listener = {
1294  global_add,
1295  global_remove,
1296 };
1297 
1300 /* -------------------------------------------------------------------- */
1307 {
1308  d->system = this;
1309  /* Connect to the Wayland server. */
1310  d->display = wl_display_connect(nullptr);
1311  if (!d->display) {
1312  display_destroy(d);
1313  throw std::runtime_error("Wayland: unable to connect to display!");
1314  }
1315 
1316  /* Register interfaces. */
1317  struct wl_registry *registry = wl_display_get_registry(d->display);
1318  wl_registry_add_listener(registry, &registry_listener, d);
1319  /* Call callback for registry listener. */
1320  wl_display_roundtrip(d->display);
1321  /* Call callbacks for registered listeners. */
1322  wl_display_roundtrip(d->display);
1323  wl_registry_destroy(registry);
1324 
1325  if (!d->xdg_shell) {
1326  display_destroy(d);
1327  throw std::runtime_error("Wayland: unable to access xdg_shell!");
1328  }
1329 
1330  /* Register data device per seat for IPC between Wayland clients. */
1331  if (d->data_device_manager) {
1332  for (input_t *input : d->inputs) {
1333  input->data_device = wl_data_device_manager_get_data_device(d->data_device_manager,
1334  input->seat);
1335  wl_data_device_add_listener(input->data_device, &data_device_listener, input);
1336  }
1337  }
1338 
1339  const char *theme = std::getenv("XCURSOR_THEME");
1340  const char *size = std::getenv("XCURSOR_SIZE");
1341  const int sizei = size ? std::stoi(size) : default_cursor_size;
1342 
1343  d->cursor_theme = wl_cursor_theme_load(theme, sizei, d->shm);
1344  if (!d->cursor_theme) {
1345  display_destroy(d);
1346  throw std::runtime_error("Wayland: unable to access cursor themes!");
1347  }
1348 }
1349 
1351 {
1352  display_destroy(d);
1353 }
1354 
1355 bool GHOST_SystemWayland::processEvents(bool waitForEvent)
1356 {
1357  const bool fired = getTimerManager()->fireTimers(getMilliSeconds());
1358 
1359  if (waitForEvent) {
1360  wl_display_dispatch(d->display);
1361  }
1362  else {
1363  wl_display_roundtrip(d->display);
1364  }
1365 
1366  return fired || (getEventManager()->getNumEvents() > 0);
1367 }
1368 
1370 {
1371  return 0;
1372 }
1373 
1375 {
1376  if (!d->inputs.empty()) {
1377  static const xkb_state_component mods_all = xkb_state_component(
1378  XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED |
1379  XKB_STATE_MODS_EFFECTIVE);
1380 
1382  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) ==
1383  1);
1385  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) ==
1386  1);
1388  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LAlt", mods_all) == 1);
1390  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RAlt", mods_all) == 1);
1392  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LControl", mods_all) == 1);
1394  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RControl", mods_all) == 1);
1396  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "Super", mods_all) == 1);
1398  xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "NumLock", mods_all) == 1);
1399 
1400  return GHOST_kSuccess;
1401  }
1402  return GHOST_kFailure;
1403 }
1404 
1406 {
1407  if (!d->inputs.empty()) {
1408  buttons = d->inputs[0]->buttons;
1409  return GHOST_kSuccess;
1410  }
1411  return GHOST_kFailure;
1412 }
1413 
1415 {
1416  GHOST_TUns8 *clipboard = static_cast<GHOST_TUns8 *>(malloc((selection.size() + 1)));
1417  memcpy(clipboard, selection.data(), selection.size() + 1);
1418  return clipboard;
1419 }
1420 
1421 void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/) const
1422 {
1423  if (!d->data_device_manager || d->inputs.empty()) {
1424  return;
1425  }
1426 
1427  data_source_t *data_source = d->inputs[0]->data_source;
1428 
1429  /* Copy buffer. */
1430  data_source->buffer_out = static_cast<char *>(malloc(strlen(buffer) + 1));
1431  std::strcpy(data_source->buffer_out, buffer);
1432 
1433  data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager);
1434 
1435  wl_data_source_add_listener(
1436  data_source->data_source, &data_source_listener, data_source->buffer_out);
1437 
1438  for (const std::string &type : mime_send) {
1439  wl_data_source_offer(data_source->data_source, type.c_str());
1440  }
1441 
1442  if (!d->inputs.empty() && d->inputs[0]->data_device) {
1443  wl_data_device_set_selection(
1444  d->inputs[0]->data_device, data_source->data_source, data_source->source_serial);
1445  }
1446 }
1447 
1449 {
1450  return d ? GHOST_TUns8(d->outputs.size()) : 0;
1451 }
1452 
1454 {
1455  if (!d->inputs.empty() && (d->inputs[0]->focus_pointer != nullptr)) {
1456  x = d->inputs[0]->x;
1457  y = d->inputs[0]->y;
1458  return GHOST_kSuccess;
1459  }
1460  else {
1461  return GHOST_kFailure;
1462  }
1463 }
1464 
1466 {
1467  return GHOST_kFailure;
1468 }
1469 
1471 {
1472  if (getNumDisplays() > 0) {
1473  /* We assume first output as main. */
1474  width = uint32_t(d->outputs[0]->width);
1475  height = uint32_t(d->outputs[0]->height);
1476  }
1477 }
1478 
1480 {
1482 }
1483 
1485 {
1486  /* Create new off-screen window. */
1487  wl_surface *os_surface = wl_compositor_create_surface(compositor());
1488  wl_egl_window *os_egl_window = wl_egl_window_create(os_surface, int(1), int(1));
1489 
1490  d->os_surfaces.push_back(os_surface);
1491  d->os_egl_windows.push_back(os_egl_window);
1492 
1493  GHOST_Context *context = new GHOST_ContextEGL(false,
1494  EGLNativeWindowType(os_egl_window),
1495  EGLNativeDisplayType(d->display),
1496  EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
1497  3,
1498  3,
1501  EGL_OPENGL_API);
1502 
1503  if (context->initializeDrawingContext()) {
1504  return context;
1505  }
1506  else {
1507  delete context;
1508  }
1509 
1510  GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
1511 
1512  return nullptr;
1513 }
1514 
1516 {
1517  delete context;
1518  return GHOST_kSuccess;
1519 }
1520 
1523  GHOST_TInt32 top,
1528  GHOST_GLSettings glSettings,
1529  const bool exclusive,
1530  const bool is_dialog,
1531  const GHOST_IWindow *parentWindow)
1532 {
1534  this,
1535  title,
1536  left,
1537  top,
1538  width,
1539  height,
1540  state,
1541  parentWindow,
1542  type,
1543  is_dialog,
1544  ((glSettings.flags & GHOST_glStereoVisual) != 0),
1545  exclusive);
1546 
1547  if (window) {
1548  if (window->getValid()) {
1549  m_windowManager->addWindow(window);
1552  }
1553  else {
1554  delete window;
1555  window = nullptr;
1556  }
1557  }
1558 
1559  return window;
1560 }
1561 
1563 {
1564  return d->display;
1565 }
1566 
1568 {
1569  return d->compositor;
1570 }
1571 
1573 {
1574  return d->xdg_shell;
1575 }
1576 
1577 void GHOST_SystemWayland::setSelection(const std::string &selection)
1578 {
1579  this->selection = selection;
1580 }
1581 
1582 static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
1583 {
1584  input->cursor.visible = (buffer != nullptr);
1585 
1586  wl_surface_attach(input->cursor.surface, buffer, 0, 0);
1587  wl_surface_commit(input->cursor.surface);
1588 
1589  if (input->cursor.visible) {
1590  wl_surface_damage(input->cursor.surface,
1591  0,
1592  0,
1593  int32_t(input->cursor.image.width),
1594  int32_t(input->cursor.image.height));
1595  wl_pointer_set_cursor(input->pointer,
1596  input->pointer_serial,
1597  input->cursor.surface,
1598  int32_t(input->cursor.image.hotspot_x),
1599  int32_t(input->cursor.image.hotspot_y));
1600  }
1601 }
1602 
1604 {
1605  if (d->inputs.empty()) {
1606  return GHOST_kFailure;
1607  }
1608  const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) :
1610 
1611  wl_cursor *cursor = wl_cursor_theme_get_cursor(d->cursor_theme, cursor_name.c_str());
1612 
1613  if (!cursor) {
1614  GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
1615  return GHOST_kFailure;
1616  }
1617 
1618  struct wl_cursor_image *image = cursor->images[0];
1619  struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
1620  if (!buffer) {
1621  return GHOST_kFailure;
1622  }
1623  cursor_t *c = &d->inputs[0]->cursor;
1624  c->buffer = buffer;
1625  c->image = *image;
1626 
1628 
1629  return GHOST_kSuccess;
1630 }
1631 
1633 {
1634  return GHOST_TSuccess(cursors.count(cursorShape) && !cursors.at(cursorShape).empty());
1635 }
1636 
1638  GHOST_TUns8 *mask,
1639  int sizex,
1640  int sizey,
1641  int hotX,
1642  int hotY,
1643  bool /*canInvertColor*/)
1644 {
1645  if (d->inputs.empty()) {
1646  return GHOST_kFailure;
1647  }
1648 
1649  cursor_t *cursor = &d->inputs[0]->cursor;
1650 
1651  static const int32_t stride = sizex * 4; /* ARGB */
1652  cursor->file_buffer->size = size_t(stride * sizey);
1653 
1654  const int fd = memfd_create("blender-cursor-custom", MFD_CLOEXEC | MFD_ALLOW_SEALING);
1655  fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK);
1656  posix_fallocate(fd, 0, int32_t(cursor->file_buffer->size));
1657 
1658  cursor->file_buffer->data = mmap(
1659  nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1660 
1661  struct wl_shm_pool *pool = wl_shm_create_pool(d->shm, fd, int32_t(cursor->file_buffer->size));
1662 
1663  wl_buffer *buffer = wl_shm_pool_create_buffer(
1664  pool, 0, sizex, sizey, stride, WL_SHM_FORMAT_ARGB8888);
1665 
1666  wl_shm_pool_destroy(pool);
1667  close(fd);
1668 
1669  wl_buffer_add_listener(buffer, &cursor_buffer_listener, cursor);
1670 
1671  static constexpr uint32_t black = 0xFF000000;
1672  static constexpr uint32_t white = 0xFFFFFFFF;
1673  static constexpr uint32_t transparent = 0x00000000;
1674 
1675  uint8_t datab = 0, maskb = 0;
1676  uint32_t *pixel;
1677 
1678  for (int y = 0; y < sizey; ++y) {
1679  pixel = &static_cast<uint32_t *>(cursor->file_buffer->data)[y * sizex];
1680  for (int x = 0; x < sizex; ++x) {
1681  if ((x % 8) == 0) {
1682  datab = *bitmap++;
1683  maskb = *mask++;
1684 
1685  /* Reverse bit order. */
1686  datab = uint8_t((datab * 0x0202020202ULL & 0x010884422010ULL) % 1023);
1687  maskb = uint8_t((maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023);
1688  }
1689 
1690  if (maskb & 0x80) {
1691  *pixel++ = (datab & 0x80) ? white : black;
1692  }
1693  else {
1694  *pixel++ = (datab & 0x80) ? white : transparent;
1695  }
1696  datab <<= 1;
1697  maskb <<= 1;
1698  }
1699  }
1700 
1701  cursor->buffer = buffer;
1702  cursor->image.width = uint32_t(sizex);
1703  cursor->image.height = uint32_t(sizey);
1704  cursor->image.hotspot_x = uint32_t(hotX);
1705  cursor->image.hotspot_y = uint32_t(hotY);
1706 
1708 
1709  return GHOST_kSuccess;
1710 }
1711 
1713 {
1714  if (d->inputs.empty()) {
1715  return GHOST_kFailure;
1716  }
1717 
1718  input_t *input = d->inputs[0];
1719 
1720  cursor_t *cursor = &input->cursor;
1721  if (visible) {
1722  if (!cursor->visible) {
1723  set_cursor_buffer(input, cursor->buffer);
1724  }
1725  }
1726  else {
1727  if (cursor->visible) {
1728  set_cursor_buffer(input, nullptr);
1729  }
1730  }
1731 
1732  return GHOST_kSuccess;
1733 }
1734 
1736  wl_surface *surface)
1737 {
1738  if (d->inputs.empty()) {
1739  return GHOST_kFailure;
1740  }
1741 
1742  input_t *input = d->inputs[0];
1743 
1744  switch (mode) {
1745  case GHOST_kGrabDisable:
1746  if (input->relative_pointer) {
1747  zwp_relative_pointer_v1_destroy(input->relative_pointer);
1748  input->relative_pointer = nullptr;
1749  }
1750  if (input->locked_pointer) {
1751  zwp_locked_pointer_v1_destroy(input->locked_pointer);
1752  input->locked_pointer = nullptr;
1753  }
1754  break;
1755 
1756  case GHOST_kGrabNormal:
1757  case GHOST_kGrabWrap:
1758  input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
1759  d->relative_pointer_manager, input->pointer);
1760  zwp_relative_pointer_v1_add_listener(
1762  input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
1764  surface,
1765  input->pointer,
1766  nullptr,
1767  ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
1768  break;
1769 
1770  case GHOST_kGrabHide:
1771  setCursorVisibility(false);
1772  break;
1773  }
1774 
1775  return GHOST_kSuccess;
1776 }
1777 
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
KDTree *BLI_kdtree_nd_() new(unsigned int maxsize)
Definition: kdtree_impl.h:99
SSIZE_T ssize_t
Definition: BLI_winstuff.h:87
#define GHOST_OPENGL_EGL_CONTEXT_FLAGS
#define GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_PRINT(x)
Definition: GHOST_Debug.h:51
static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive)
static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
static void data_device_drop(void *data, struct wl_data_device *)
static const struct wl_data_source_listener data_source_listener
static void data_source_action(void *, struct wl_data_source *, uint32_t)
static void data_source_dnd_drop_performed(void *, struct wl_data_source *)
static const struct wl_output_listener output_listener
static void data_source_cancelled(void *, struct wl_data_source *wl_data_source)
static const zwp_relative_pointer_v1_listener relative_pointer_listener
static void data_offer_action(void *data, struct wl_data_offer *, uint32_t dnd_action)
static const std::unordered_map< std::string, GHOST_TDragnDropTypes > mime_dnd
static const struct xdg_wm_base_listener shell_listener
#define GXMAP(k, x, y)
static const struct wl_data_device_listener data_device_listener
static void output_done(void *, struct wl_output *)
static void dnd_events(const input_t *const input, const GHOST_TEventType event)
static void global_remove(void *, struct wl_registry *, uint32_t)
static void display_destroy(display_t *d)
static void keyboard_repeat_info(void *data, struct wl_keyboard *, int32_t rate, int32_t delay)
static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
static void data_source_send(void *data, struct wl_data_source *, const char *, int32_t fd)
static void relative_pointer_relative_motion(void *data, struct zwp_relative_pointer_v1 *, uint32_t, uint32_t, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t, wl_fixed_t)
static void data_offer_offer(void *data, struct wl_data_offer *, const char *mime_type)
const struct wl_buffer_listener cursor_buffer_listener
static void pointer_motion(void *data, struct wl_pointer *, uint32_t, wl_fixed_t surface_x, wl_fixed_t surface_y)
static const struct wl_seat_listener seat_listener
static void cursor_buffer_release(void *data, struct wl_buffer *wl_buffer)
static void keyboard_key(void *data, struct wl_keyboard *, uint32_t serial, uint32_t, uint32_t key, uint32_t state)
static const struct wl_data_offer_listener data_offer_listener
static void keyboard_modifiers(void *data, struct wl_keyboard *, uint32_t, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
static void data_device_leave(void *data, struct wl_data_device *)
static void keyboard_keymap(void *data, struct wl_keyboard *, uint32_t format, int32_t fd, uint32_t size)
static void data_offer_source_actions(void *data, struct wl_data_offer *, uint32_t source_actions)
static void pointer_button(void *data, struct wl_pointer *, uint32_t serial, uint32_t, uint32_t button, uint32_t state)
static void pointer_leave(void *data, struct wl_pointer *, uint32_t, struct wl_surface *surface)
static const std::vector< std::string > mime_preference_order
static const struct wl_registry_listener registry_listener
static constexpr const char * mime_text_utf8
static void output_mode(void *data, struct wl_output *, uint32_t, int32_t width, int32_t height, int32_t)
static const struct wl_pointer_listener pointer_listener
static void pointer_axis(void *data, struct wl_pointer *, uint32_t, uint32_t axis, wl_fixed_t value)
static void keyboard_enter(void *data, struct wl_keyboard *, uint32_t, struct wl_surface *surface, struct wl_array *)
static void global_add(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t)
static void output_geometry(void *data, struct wl_output *, int32_t, int32_t, int32_t, int32_t, int32_t, const char *make, const char *model, int32_t transform)
static void keyboard_leave(void *data, struct wl_keyboard *, uint32_t, struct wl_surface *surface)
static const std::unordered_map< GHOST_TStandardCursor, std::string > cursors
static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(struct xkb_state *xkb_state, xkb_keycode_t key)
static const struct wl_keyboard_listener keyboard_listener
static void data_device_enter(void *data, struct wl_data_device *, uint32_t serial, struct wl_surface *, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id)
static void shell_ping(void *, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
static constexpr const char * mime_text_uri
static void output_scale(void *data, struct wl_output *, int32_t factor)
static void data_device_motion(void *data, struct wl_data_device *, uint32_t, wl_fixed_t x, wl_fixed_t y)
static const int default_cursor_size
static void data_device_data_offer(void *, struct wl_data_device *, struct wl_data_offer *id)
static void data_source_dnd_finished(void *, struct wl_data_source *)
static void seat_name(void *data, struct wl_seat *, const char *name)
static const std::vector< std::string > mime_send
static void data_source_target(void *, struct wl_data_source *, const char *)
static GHOST_TKey xkb_map_gkey(const xkb_keysym_t &sym)
static void data_device_selection(void *data, struct wl_data_device *, struct wl_data_offer *id)
static constexpr const char * mime_text_plain
static void pointer_enter(void *data, struct wl_pointer *, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
GHOST_TWindowState
Definition: GHOST_Types.h:144
GHOST_TStandardCursor
Definition: GHOST_Types.h:222
@ GHOST_kStandardCursorBottomLeftCorner
Definition: GHOST_Types.h:260
@ GHOST_kStandardCursorZoomIn
Definition: GHOST_Types.h:244
@ GHOST_kStandardCursorVerticalSplit
Definition: GHOST_Types.h:239
@ GHOST_kStandardCursorHelp
Definition: GHOST_Types.h:229
@ GHOST_kStandardCursorCopy
Definition: GHOST_Types.h:261
@ GHOST_kStandardCursorWait
Definition: GHOST_Types.h:230
@ GHOST_kStandardCursorHorizontalSplit
Definition: GHOST_Types.h:240
@ GHOST_kStandardCursorTopSide
Definition: GHOST_Types.h:253
@ GHOST_kStandardCursorStop
Definition: GHOST_Types.h:250
@ GHOST_kStandardCursorCrosshair
Definition: GHOST_Types.h:232
@ GHOST_kStandardCursorNSEWScroll
Definition: GHOST_Types.h:247
@ GHOST_kStandardCursorLeftRight
Definition: GHOST_Types.h:252
@ GHOST_kStandardCursorPencil
Definition: GHOST_Types.h:236
@ GHOST_kStandardCursorNSScroll
Definition: GHOST_Types.h:248
@ GHOST_kStandardCursorCrosshairA
Definition: GHOST_Types.h:233
@ GHOST_kStandardCursorUpDown
Definition: GHOST_Types.h:251
@ GHOST_kStandardCursorUpArrow
Definition: GHOST_Types.h:237
@ GHOST_kStandardCursorBottomSide
Definition: GHOST_Types.h:254
@ GHOST_kStandardCursorInfo
Definition: GHOST_Types.h:227
@ GHOST_kStandardCursorTopLeftCorner
Definition: GHOST_Types.h:257
@ GHOST_kStandardCursorEyedropper
Definition: GHOST_Types.h:243
@ GHOST_kStandardCursorKnife
Definition: GHOST_Types.h:242
@ GHOST_kStandardCursorMove
Definition: GHOST_Types.h:246
@ GHOST_kStandardCursorCrosshairB
Definition: GHOST_Types.h:234
@ GHOST_kStandardCursorBottomRightCorner
Definition: GHOST_Types.h:259
@ GHOST_kStandardCursorDownArrow
Definition: GHOST_Types.h:238
@ GHOST_kStandardCursorEraser
Definition: GHOST_Types.h:241
@ GHOST_kStandardCursorDefault
Definition: GHOST_Types.h:224
@ GHOST_kStandardCursorEWScroll
Definition: GHOST_Types.h:249
@ GHOST_kStandardCursorRightSide
Definition: GHOST_Types.h:256
@ GHOST_kStandardCursorRightArrow
Definition: GHOST_Types.h:225
@ GHOST_kStandardCursorTopRightCorner
Definition: GHOST_Types.h:258
@ GHOST_kStandardCursorDestroy
Definition: GHOST_Types.h:228
@ GHOST_kStandardCursorCrosshairC
Definition: GHOST_Types.h:235
@ GHOST_kStandardCursorZoomOut
Definition: GHOST_Types.h:245
@ GHOST_kStandardCursorLeftSide
Definition: GHOST_Types.h:255
@ GHOST_kStandardCursorText
Definition: GHOST_Types.h:231
@ GHOST_kStandardCursorLeftArrow
Definition: GHOST_Types.h:226
unsigned int GHOST_TUns32
Definition: GHOST_Types.h:64
unsigned long long GHOST_TUns64
Definition: GHOST_Types.h:86
GHOST_TEventType
Definition: GHOST_Types.h:177
@ GHOST_kEventWindowSize
Definition: GHOST_Types.h:201
@ GHOST_kEventDraggingDropDone
Definition: GHOST_Types.h:208
@ GHOST_kEventDraggingExited
Definition: GHOST_Types.h:207
@ GHOST_kEventCursorMove
Definition: GHOST_Types.h:180
@ GHOST_kEventDraggingUpdated
Definition: GHOST_Types.h:206
@ GHOST_kEventDraggingEntered
Definition: GHOST_Types.h:205
@ GHOST_kEventButtonUp
Mouse button event.
Definition: GHOST_Types.h:182
@ GHOST_kEventButtonDown
Mouse move event.
Definition: GHOST_Types.h:181
@ GHOST_kEventKeyDown
Trackpad event.
Definition: GHOST_Types.h:191
@ GHOST_kEventUnknown
Definition: GHOST_Types.h:178
@ GHOST_kEventKeyUp
Definition: GHOST_Types.h:192
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
Definition: GHOST_Types.h:119
int GHOST_TInt32
Definition: GHOST_Types.h:63
@ GHOST_glStereoVisual
Definition: GHOST_Types.h:71
GHOST_TKey
Definition: GHOST_Types.h:267
@ GHOST_kKeyInsert
Definition: GHOST_Types.h:354
@ GHOST_kKeySemicolon
Definition: GHOST_Types.h:296
@ GHOST_kKeyMediaPlay
Definition: GHOST_Types.h:406
@ GHOST_kKeyQuote
Definition: GHOST_Types.h:277
@ GHOST_kKeyAccentGrave
Definition: GHOST_Types.h:330
@ GHOST_kKeyLeftAlt
Definition: GHOST_Types.h:336
@ GHOST_kKeyRightShift
Definition: GHOST_Types.h:333
@ GHOST_kKeyNumLock
Definition: GHOST_Types.h:343
@ GHOST_kKeyEnter
Definition: GHOST_Types.h:273
@ GHOST_kKeyNumpadSlash
Definition: GHOST_Types.h:377
@ GHOST_kKeyRightArrow
Definition: GHOST_Types.h:347
@ GHOST_kKeyPause
Definition: GHOST_Types.h:352
@ GHOST_kKeyCapsLock
Definition: GHOST_Types.h:342
@ GHOST_kKeyApp
Definition: GHOST_Types.h:340
@ GHOST_kKeyMinus
Definition: GHOST_Types.h:279
@ GHOST_kKeyMediaStop
Definition: GHOST_Types.h:407
@ GHOST_kKeyBackSpace
Definition: GHOST_Types.h:269
@ GHOST_kKeyDownPage
Definition: GHOST_Types.h:359
@ GHOST_kKeyDownArrow
Definition: GHOST_Types.h:349
@ GHOST_kKeyClear
Definition: GHOST_Types.h:272
@ GHOST_kKeyNumpadPeriod
Definition: GHOST_Types.h:372
@ GHOST_kKeyF1
Definition: GHOST_Types.h:380
@ GHOST_kKeyNumpadAsterisk
Definition: GHOST_Types.h:376
@ GHOST_kKeyPrintScreen
Definition: GHOST_Types.h:351
@ GHOST_kKeyLeftControl
Definition: GHOST_Types.h:334
@ GHOST_kKeyLeftBracket
Definition: GHOST_Types.h:327
@ GHOST_kKeyTab
Definition: GHOST_Types.h:270
@ GHOST_kKeyComma
Definition: GHOST_Types.h:278
@ GHOST_kKeyRightBracket
Definition: GHOST_Types.h:328
@ GHOST_kKeyBackslash
Definition: GHOST_Types.h:329
@ GHOST_kKeyOS
Definition: GHOST_Types.h:338
@ GHOST_kKeyLinefeed
Definition: GHOST_Types.h:271
@ GHOST_kKeyRightAlt
Definition: GHOST_Types.h:337
@ GHOST_kKeyPeriod
Definition: GHOST_Types.h:281
@ GHOST_kKeyNumpadPlus
Definition: GHOST_Types.h:374
@ GHOST_kKeyUpPage
Definition: GHOST_Types.h:358
@ GHOST_kKeyLeftArrow
Definition: GHOST_Types.h:346
@ GHOST_kKeyEqual
Definition: GHOST_Types.h:297
@ GHOST_kKeyHome
Definition: GHOST_Types.h:356
@ GHOST_kKeyEnd
Definition: GHOST_Types.h:357
@ GHOST_kKeyUpArrow
Definition: GHOST_Types.h:348
@ GHOST_kKeyDelete
Definition: GHOST_Types.h:355
@ GHOST_kKeyNumpad0
Definition: GHOST_Types.h:362
@ GHOST_kKeyMediaFirst
Definition: GHOST_Types.h:408
@ GHOST_kKeyRightControl
Definition: GHOST_Types.h:335
@ GHOST_kKeyEsc
Definition: GHOST_Types.h:275
@ GHOST_kKeyPlus
Definition: GHOST_Types.h:280
@ GHOST_kKeyUnknown
Definition: GHOST_Types.h:268
@ GHOST_kKeyScrollLock
Definition: GHOST_Types.h:344
@ GHOST_kKeySlash
Definition: GHOST_Types.h:282
@ GHOST_kKeyNumpadEnter
Definition: GHOST_Types.h:373
@ GHOST_kKeyNumpadMinus
Definition: GHOST_Types.h:375
@ GHOST_kKeyLeftShift
Definition: GHOST_Types.h:332
@ GHOST_kKeyMediaLast
Definition: GHOST_Types.h:409
@ GHOST_kKeySpace
Definition: GHOST_Types.h:276
GHOST_TDrawingContextType
Definition: GHOST_Types.h:156
GHOST_TButtonMask
Definition: GHOST_Types.h:164
@ GHOST_kButtonMaskRight
Definition: GHOST_Types.h:168
@ GHOST_kButtonMaskLeft
Definition: GHOST_Types.h:166
@ GHOST_kButtonMaskMiddle
Definition: GHOST_Types.h:167
char GHOST_TInt8
Definition: GHOST_Types.h:59
GHOST_TSuccess
Definition: GHOST_Types.h:91
@ GHOST_kFailure
Definition: GHOST_Types.h:91
@ GHOST_kSuccess
Definition: GHOST_Types.h:91
@ GHOST_kModifierKeyRightControl
Definition: GHOST_Types.h:139
@ GHOST_kModifierKeyNumMasks
Definition: GHOST_Types.h:141
@ GHOST_kModifierKeyLeftControl
Definition: GHOST_Types.h:138
@ GHOST_kModifierKeyRightAlt
Definition: GHOST_Types.h:137
@ GHOST_kModifierKeyOS
Definition: GHOST_Types.h:140
@ GHOST_kModifierKeyRightShift
Definition: GHOST_Types.h:135
@ GHOST_kModifierKeyLeftAlt
Definition: GHOST_Types.h:136
@ GHOST_kModifierKeyLeftShift
Definition: GHOST_Types.h:134
GHOST_TGrabCursorMode
Definition: GHOST_Types.h:412
@ GHOST_kGrabWrap
Definition: GHOST_Types.h:418
@ GHOST_kGrabDisable
Definition: GHOST_Types.h:414
@ GHOST_kGrabHide
Definition: GHOST_Types.h:420
@ GHOST_kGrabNormal
Definition: GHOST_Types.h:416
@ GHOST_kDragnDropTypeFilenames
Definition: GHOST_Types.h:479
@ GHOST_kDragnDropTypeString
Definition: GHOST_Types.h:480
unsigned char GHOST_TUns8
Definition: GHOST_Types.h:60
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble top
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
#define output
GHOST_TUns32 getNumEvents()
virtual GHOST_TUserDataPtr getUserData() const =0
GHOST_IWindow * createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, const GHOST_IWindow *parentWindow) override
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override
GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode, wl_surface *surface)
GHOST_TUns8 getNumDisplays() const override
void setSelection(const std::string &selection)
void putClipboard(GHOST_TInt8 *buffer, bool selection) const override
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override
GHOST_TSuccess disposeContext(GHOST_IContext *context) override
GHOST_IContext * createOffscreenContext(GHOST_GLSettings glSettings) override
wl_compositor * compositor()
GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const override
void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override
GHOST_TSuccess setCursorVisibility(bool visible)
GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape)
void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override
bool processEvents(bool waitForEvent) override
GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
int toggleConsole(int action) override
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape)
GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) override
GHOST_TUns8 * getClipboard(bool selection) const override
GHOST_EventManager * getEventManager() const
Definition: GHOST_System.h:412
GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask)
GHOST_ITimerTask * installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData=NULL)
GHOST_TimerManager * getTimerManager() const
Definition: GHOST_System.h:407
GHOST_WindowManager * m_windowManager
Definition: GHOST_System.h:383
GHOST_TSuccess pushEvent(GHOST_IEvent *event)
virtual GHOST_TUns64 getMilliSeconds() const
bool fireTimers(GHOST_TUns64 time)
GHOST_TSuccess addWindow(GHOST_IWindow *window)
GHOST_TSuccess setActiveWindow(GHOST_IWindow *window)
virtual bool getValid() const
Definition: GHOST_Window.h:92
double time
struct @203::@204 surface
uint pos
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
format
Definition: logImageCore.h:47
static char ** types
Definition: makesdna.c:164
static ulong state[N]
static int left
static int make(const char *input_file_name, const char *output_file_name)
Definition: msgfmt.c:302
static unsigned c
Definition: RandGen.cpp:97
struct blender::compositor::@172::@174 task
struct SELECTID_Context context
Definition: select_engine.c:47
unsigned int uint32_t
Definition: stdint.h:83
signed int int32_t
Definition: stdint.h:80
unsigned char uint8_t
Definition: stdint.h:81
void set(GHOST_TButtonMask mask, bool down)
void set(GHOST_TModifierKeyMask mask, bool down)
GHOST_TUns8 ** strings
Definition: GHOST_Types.h:513
struct wl_cursor_image image
struct buffer_t * file_buffer
struct wl_buffer * buffer
struct wl_surface * surface
std::atomic< bool > in_use
std::unordered_set< std::string > types
struct data_offer_t::@1231 dnd
struct wl_data_offer * id
struct wl_data_source * data_source
std::vector< struct wl_surface * > os_surfaces
std::vector< output_t * > outputs
struct wl_shm * shm
struct zwp_relative_pointer_manager_v1 * relative_pointer_manager
struct wl_cursor_theme * cursor_theme
GHOST_SystemWayland * system
struct wl_compositor * compositor
std::vector< input_t * > inputs
struct xdg_wm_base * xdg_shell
struct wl_display * display
std::vector< struct wl_egl_window * > os_egl_windows
struct zwp_pointer_constraints_v1 * pointer_constraints
struct wl_data_device_manager * data_device_manager
struct input_t::@1232 key_repeat
GHOST_SystemWayland * system
struct wl_seat * seat
struct xkb_state * xkb_state
struct xkb_context * xkb_context
std::string name
GHOST_Buttons buttons
struct zwp_relative_pointer_v1 * relative_pointer
struct wl_data_device * data_device
GHOST_ITimerTask * timer
struct data_offer_t * data_offer_copy_paste
struct zwp_locked_pointer_v1 * locked_pointer
struct wl_surface * focus_pointer
struct data_offer_t * data_offer_dnd
struct cursor_t cursor
uint32_t pointer_serial
struct wl_pointer * pointer
struct wl_keyboard * keyboard
struct wl_surface * focus_keyboard
struct data_source_t * data_source
GHOST_TEventKeyData key_data
GHOST_SystemWayland * system
struct wl_output * output
std::string model
std::string make
static const char hex[17]
Definition: thumbs.c:173
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
uint len