Blender V4.5
GHOST_WindowX11.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9/* For standard X11 cursors */
10#include <X11/Xatom.h>
11#include <X11/Xmd.h>
12#include <X11/Xutil.h>
13#include <X11/cursorfont.h>
14
15#include "GHOST_Debug.hh"
16#include "GHOST_IconX11.hh"
17#include "GHOST_SystemX11.hh"
18#include "GHOST_Types.h"
19#include "GHOST_WindowX11.hh"
20#include "GHOST_utildefines.hh"
21
22#ifdef WITH_XDND
23# include "GHOST_DropTargetX11.hh"
24#endif
25
26#ifdef WITH_OPENGL_BACKEND
27# include "GHOST_ContextEGL.hh"
28# include "GHOST_ContextGLX.hh"
29#endif
30#ifdef WITH_VULKAN_BACKEND
31# include "GHOST_ContextVK.hh"
32#endif
33
34/* For #XIWarpPointer. */
35#ifdef WITH_X11_XINPUT
36# include <X11/extensions/XInput2.h>
37#endif
38
39/* For DPI value. */
40#include <X11/Xresource.h>
41
42#include <cstdio>
43#include <cstring>
44
45/* For `gethostname`. */
46#include <unistd.h>
47
48#include <algorithm>
49#include <climits>
50#include <cmath>
51#include <string>
52
53/* For obscure full screen mode stuff
54 * lifted verbatim from blut. */
55
57 long flags;
61};
62
63enum {
66};
67enum {
68 MWM_FUNCTION_ALL = (1L << 0),
70 MWM_FUNCTION_MOVE = (1L << 2),
73 MWM_FUNCTION_CLOSE = (1L << 5),
74};
75
76#ifndef HOST_NAME_MAX
77# define HOST_NAME_MAX 64
78#endif
79
80// #define GHOST_X11_GRAB
81
82/*
83 * A Client can't change the window property, that is
84 * the work of the window manager. In case, we send
85 * a ClientMessage to the RootWindow with the property
86 * and the Action (WM-spec define this):
87 */
88#define _NET_WM_STATE_REMOVE 0
89#define _NET_WM_STATE_ADD 1
90// #define _NET_WM_STATE_TOGGLE 2 // UNUSED
91
92#ifdef WITH_OPENGL_BACKEND
93static XVisualInfo *get_x11_visualinfo(Display *display)
94{
95 int num_visuals;
96 XVisualInfo vinfo_template;
97 vinfo_template.screen = DefaultScreen(display);
98 return XGetVisualInfo(display, VisualScreenMask, &vinfo_template, &num_visuals);
99}
100#endif
101
103 Display *display,
104 const char *title,
106 int32_t top,
107 uint32_t width,
108 uint32_t height,
110 GHOST_WindowX11 *parentWindow,
112 const bool is_dialog,
113 const bool stereoVisual,
114 const bool exclusive,
115 const bool is_debug,
116 const GHOST_GPUDevice &preferred_device)
117 : GHOST_Window(width, height, state, stereoVisual, exclusive),
118 m_display(display),
119 m_visualInfo(nullptr),
120 m_fbconfig(nullptr),
121 m_normal_state(GHOST_kWindowStateNormal),
122 m_system(system),
123 m_invalid_window(false),
124 m_empty_cursor(None),
125 m_custom_cursor(None),
126 m_visible_cursor(None),
127#ifdef WITH_XDND
128 m_dropTarget(nullptr),
129#endif
130 m_tabletData(GHOST_TABLET_DATA_NONE),
131#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
132 m_xic(nullptr),
133#endif
134 m_valid_setup(false),
135 m_is_debug_context(is_debug),
136 m_preferred_device(preferred_device)
137{
138#ifdef WITH_OPENGL_BACKEND
139 if (type == GHOST_kDrawingContextTypeOpenGL) {
140 m_visualInfo = get_x11_visualinfo(m_display);
141 }
142 else
143#endif
144 {
145 XVisualInfo tmp = {nullptr};
146 int n;
147 m_visualInfo = XGetVisualInfo(m_display, 0, &tmp, &n);
148 }
149
150 /* caller needs to check 'getValid()' */
151 if (m_visualInfo == nullptr) {
152 fprintf(stderr, "initial window could not find the GLX extension\n");
153 return;
154 }
155
156 uint xattributes_valuemask = 0;
157
158 XSetWindowAttributes xattributes;
159 memset(&xattributes, 0, sizeof(xattributes));
160
161 xattributes_valuemask |= CWBorderPixel;
162 xattributes.border_pixel = 0;
163
164 /* Specify which events we are interested in hearing. */
165
166 xattributes_valuemask |= CWEventMask;
167 xattributes.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask |
168 EnterWindowMask | LeaveWindowMask | ButtonPressMask |
169 ButtonReleaseMask | PointerMotionMask | FocusChangeMask |
170 PropertyChangeMask | KeymapStateMask;
171
172 if (exclusive) {
173 xattributes_valuemask |= CWOverrideRedirect;
174 xattributes.override_redirect = True;
175 }
176
177 xattributes_valuemask |= CWColormap;
178 xattributes.colormap = XCreateColormap(
179 m_display, RootWindow(m_display, m_visualInfo->screen), m_visualInfo->visual, AllocNone);
180
181 /* create the window! */
182 m_window = XCreateWindow(m_display,
183 RootWindow(m_display, m_visualInfo->screen),
184 left,
185 top,
186 width,
187 height,
188 0, /* no border. */
189 m_visualInfo->depth,
190 InputOutput,
191 m_visualInfo->visual,
192 xattributes_valuemask,
193 &xattributes);
194
195#ifdef WITH_XDND
196 /* initialize drop target for newly created window */
197 m_dropTarget = new GHOST_DropTargetX11(this, m_system);
198 GHOST_PRINT("Set drop target\n");
199#endif
200
202 Atom atoms[2];
203 int count = 0;
205 atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
206 atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
207 }
208 else {
209 atoms[count++] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
210 }
211
212 XChangeProperty(m_display,
213 m_window,
214 m_system->m_atom._NET_WM_STATE,
215 XA_ATOM,
216 32,
217 PropModeReplace,
218 (uchar *)atoms,
219 count);
220 m_post_init = False;
221 }
222 /*
223 * One of the problem with WM-spec is that can't set a property
224 * to a window that isn't mapped. That is why we can't "just
225 * call setState" here.
226 *
227 * To fix this, we first need know that the window is really
228 * map waiting for the MapNotify event.
229 *
230 * So, m_post_init indicate that we need wait for the MapNotify
231 * event and then set the Window state to the m_post_state.
232 */
234 m_post_init = True;
236 }
237 else {
238 m_post_init = False;
240 }
241
242 if (is_dialog && parentWindow) {
243 setDialogHints(parentWindow);
244 }
245
246 /* Create some hints for the window manager on how
247 * we want this window treated. */
248 {
249 XSizeHints *xsizehints = XAllocSizeHints();
250 xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
251 xsizehints->x = left;
252 xsizehints->y = top;
253 xsizehints->width = width;
254 xsizehints->height = height;
255 xsizehints->min_width = 320; /* Size hints, could be made apart of the GHOST API. */
256 xsizehints->min_height = 240; /* Limits are also arbitrary, but should not allow 1x1 window. */
257 xsizehints->max_width = 65535;
258 xsizehints->max_height = 65535;
259 XSetWMNormalHints(m_display, m_window, xsizehints);
260 XFree(xsizehints);
261 }
262
263 /* XClassHint, title */
264 {
265 XClassHint *xclasshint = XAllocClassHint();
266 const int len = strlen(title) + 1;
267 char *wmclass = (char *)malloc(sizeof(char) * len);
268 memcpy(wmclass, title, len * sizeof(char));
269 xclasshint->res_name = wmclass;
270 xclasshint->res_class = wmclass;
271 XSetClassHint(m_display, m_window, xclasshint);
272 free(wmclass);
273 XFree(xclasshint);
274 }
275
276 /* The basic for a good ICCCM "work" */
277 if (m_system->m_atom.WM_PROTOCOLS) {
278 Atom atoms[2];
279 int natom = 0;
280
281 if (m_system->m_atom.WM_DELETE_WINDOW) {
282 atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
283 natom++;
284 }
285
286 if (m_system->m_atom.WM_TAKE_FOCUS && m_system->m_windowFocus) {
287 atoms[natom] = m_system->m_atom.WM_TAKE_FOCUS;
288 natom++;
289 }
290
291 if (natom) {
292 // printf("Register atoms: %d\n", natom);
293 XSetWMProtocols(m_display, m_window, atoms, natom);
294 }
295 }
296
297 /* Set the window hints */
298 {
299 XWMHints *xwmhints = XAllocWMHints();
300 xwmhints->initial_state = NormalState;
301 xwmhints->input = (m_system->m_windowFocus) ? True : False;
302 xwmhints->flags = InputHint | StateHint;
303 XSetWMHints(display, m_window, xwmhints);
304 XFree(xwmhints);
305 }
306
307 /* set the icon */
308 {
309 Atom _NET_WM_ICON = XInternAtom(m_display, "_NET_WM_ICON", False);
310 XChangeProperty(m_display,
311 m_window,
312 _NET_WM_ICON,
313 XA_CARDINAL,
314 32,
315 PropModeReplace,
318 }
319
320 /* set the process ID (_NET_WM_PID) */
321 {
322 Atom _NET_WM_PID = XInternAtom(m_display, "_NET_WM_PID", False);
323 pid_t pid = getpid();
324 XChangeProperty(
325 m_display, m_window, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace, (uchar *)&pid, 1);
326 }
327
328 /* set the hostname (WM_CLIENT_MACHINE) */
329 {
330 char hostname[HOST_NAME_MAX];
331 char *text_array[1];
332 XTextProperty text_prop;
333
334 gethostname(hostname, sizeof(hostname));
335 hostname[sizeof(hostname) - 1] = '\0';
336 text_array[0] = hostname;
337
338 XStringListToTextProperty(text_array, 1, &text_prop);
339 XSetWMClientMachine(m_display, m_window, &text_prop);
340 XFree(text_prop.value);
341 }
342
343#ifdef WITH_X11_XINPUT
344 refreshXInputDevices();
345#endif
346
347 /* now set up the rendering context. */
349 m_valid_setup = true;
350 GHOST_PRINT("Created window\n");
351 }
352 else {
353 const char *text =
354 "A graphics card and driver with support for OpenGL 4.3 or higher is "
355 "required.\n\nInstalling the latest driver for your graphics card might resolve the "
356 "issue.";
357 const char *help = "https://www.blender.org/download/requirements/";
358 system->showMessageBox(
359 "Unsupported hardware", text, "Learn More", "Close", help, GHOST_DialogError);
360 exit(0);
361 }
362
363 setTitle(title);
364
365 if (exclusive && system->m_windowFocus) {
366 XMapRaised(m_display, m_window);
367 }
368 else {
369 XMapWindow(m_display, m_window);
370
371 if (!system->m_windowFocus) {
372 XLowerWindow(m_display, m_window);
373 }
374 }
375 GHOST_PRINT("Mapped window\n");
376
377 XFlush(m_display);
378}
379
380#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
381static Bool destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
382{
383 GHOST_PRINT("XIM input context destroyed\n");
384
385 if (ptr) {
386 *(XIC *)ptr = nullptr;
387 }
388 /* Ignored by X11. */
389 return True;
390}
391
392bool GHOST_WindowX11::createX11_XIC()
393{
394 XIM xim = m_system->getX11_XIM();
395 if (!xim) {
396 return false;
397 }
398
399 XICCallback destroy;
400 destroy.callback = (XICProc)destroyICCallback;
401 destroy.client_data = (XPointer)&m_xic;
402 m_xic = XCreateIC(xim,
403 XNClientWindow,
404 m_window,
405 XNFocusWindow,
406 m_window,
407 XNInputStyle,
408 XIMPreeditNothing | XIMStatusNothing,
409 XNResourceName,
410 GHOST_X11_RES_NAME,
411 XNResourceClass,
412 GHOST_X11_RES_CLASS,
413 XNDestroyCallback,
414 &destroy,
415 nullptr);
416 if (!m_xic) {
417 return false;
418 }
419
420 ulong fevent;
421 XGetICValues(m_xic, XNFilterEvents, &fevent, nullptr);
422 XSelectInput(m_display,
423 m_window,
424 ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask |
425 EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask |
426 PointerMotionMask | FocusChangeMask | PropertyChangeMask | KeymapStateMask |
427 fevent);
428 return true;
429}
430#endif
431
432#ifdef WITH_X11_XINPUT
433void GHOST_WindowX11::refreshXInputDevices()
434{
435 if (m_system->m_xinput_version.present) {
436 std::vector<XEventClass> xevents;
437
438 for (GHOST_SystemX11::GHOST_TabletX11 &xtablet : m_system->GetXTablets()) {
439 /* With modern XInput (XLIB 1.6.2 at least and/or EVDEV 2.9.0) and some 'no-name' tablets
440 * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
441 * otherwise we do not get any tablet motion event once pen is pressed... See #43367.
442 */
443 XEventClass ev;
444
445 DeviceMotionNotify(xtablet.Device, xtablet.MotionEvent, ev);
446 if (ev) {
447 xevents.push_back(ev);
448 }
449 DeviceButtonPress(xtablet.Device, xtablet.PressEvent, ev);
450 if (ev) {
451 xevents.push_back(ev);
452 }
453 ProximityIn(xtablet.Device, xtablet.ProxInEvent, ev);
454 if (ev) {
455 xevents.push_back(ev);
456 }
457 ProximityOut(xtablet.Device, xtablet.ProxOutEvent, ev);
458 if (ev) {
459 xevents.push_back(ev);
460 }
461 }
462
463 XSelectExtensionEvent(m_display, m_window, xevents.data(), int(xevents.size()));
464 }
465}
466
467#endif /* WITH_X11_XINPUT */
468
470{
471 return m_window;
472}
473
475{
476 return GHOST_Window::getValid() && m_valid_setup;
477}
478
479void GHOST_WindowX11::setTitle(const char *title)
480{
481 Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
482 Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
483 XChangeProperty(
484 m_display, m_window, name, utf8str, 8, PropModeReplace, (const uchar *)title, strlen(title));
485
486 /* This should convert to valid x11 string
487 * and getTitle would need matching change */
488 XStoreName(m_display, m_window, title);
489
490 XFlush(m_display);
491}
492
493std::string GHOST_WindowX11::getTitle() const
494{
495 char *name = nullptr;
496
497 XFetchName(m_display, m_window, &name);
498 std::string title = name ? name : "untitled";
499 XFree(name);
500 return title;
501}
502
504{
505 /* Getting the window bounds under X11 is not
506 * really supported (nor should it be desired). */
508}
509
511{
512 Window root_return;
513 int x_return, y_return;
514 uint w_return, h_return, border_w_return, depth_return;
515 int32_t screen_x, screen_y;
516
517 XGetGeometry(m_display,
518 m_window,
519 &root_return,
520 &x_return,
521 &y_return,
522 &w_return,
523 &h_return,
524 &border_w_return,
525 &depth_return);
526
527 clientToScreen(0, 0, screen_x, screen_y);
528
529 bounds.m_l = screen_x;
530 bounds.m_r = bounds.m_l + w_return;
531 bounds.m_t = screen_y;
532 bounds.m_b = bounds.m_t + h_return;
533}
534
536{
537 XWindowChanges values;
538 uint value_mask = CWWidth;
539 values.width = width;
540 XConfigureWindow(m_display, m_window, value_mask, &values);
541
542 return GHOST_kSuccess;
543}
544
546{
547 XWindowChanges values;
548 uint value_mask = CWHeight;
549 values.height = height;
550 XConfigureWindow(m_display, m_window, value_mask, &values);
551 return GHOST_kSuccess;
552}
553
554GHOST_TSuccess GHOST_WindowX11::setClientSize(uint32_t width, uint32_t height)
555{
556 XWindowChanges values;
557 uint value_mask = CWWidth | CWHeight;
558 values.width = width;
559 values.height = height;
560 XConfigureWindow(m_display, m_window, value_mask, &values);
561 return GHOST_kSuccess;
562}
563
565{
566 int ax, ay;
567 Window temp;
568
569 /* Use (0, 0) instead of (inX, inY) to work around overflow of signed int16 in
570 * the implementation of this function. */
571 XTranslateCoordinates(
572 m_display, RootWindow(m_display, m_visualInfo->screen), m_window, 0, 0, &ax, &ay, &temp);
573 outX = ax + inX;
574 outY = ay + inY;
575}
576
578{
579 int ax, ay;
580 Window temp;
581
582 XTranslateCoordinates(
583 m_display, m_window, RootWindow(m_display, m_visualInfo->screen), inX, inY, &ax, &ay, &temp);
584 outX = ax;
585 outY = ay;
586}
587
589{
590
591 Atom atom_window_type = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False);
592 Atom atom_dialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
593 MotifWmHints hints = {0};
594
595 XChangeProperty(m_display,
596 m_window,
597 atom_window_type,
598 XA_ATOM,
599 32,
600 PropModeReplace,
601 (uchar *)&atom_dialog,
602 1);
603 XSetTransientForHint(m_display, m_window, parentWindow->m_window);
604
605 /* Disable minimizing of the window for now.
606 * Actually, most window managers disable minimizing and maximizing for dialogs, ignoring this.
607 * Leaving it here anyway in the hope it brings back maximizing on some window managers at least,
608 * we'd preferably have it even for dialog windows (e.g. file browser). */
612 XChangeProperty(m_display,
613 m_window,
614 m_system->m_atom._MOTIF_WM_HINTS,
615 m_system->m_atom._MOTIF_WM_HINTS,
616 32,
617 PropModeReplace,
618 (uchar *)&hints,
619 4);
620
621 return GHOST_kSuccess;
622}
623
624void GHOST_WindowX11::icccmSetState(int state)
625{
626 XEvent xev;
627
628 if (state != IconicState) {
629 return;
630 }
631
632 xev.xclient.type = ClientMessage;
633 xev.xclient.serial = 0;
634 xev.xclient.send_event = True;
635 xev.xclient.display = m_display;
636 xev.xclient.window = m_window;
637 xev.xclient.format = 32;
638 xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
639 xev.xclient.data.l[0] = state;
640 XSendEvent(m_display,
641 RootWindow(m_display, m_visualInfo->screen),
642 False,
643 SubstructureNotifyMask | SubstructureRedirectMask,
644 &xev);
645}
646
647int GHOST_WindowX11::icccmGetState() const
648{
649 struct {
650 CARD32 state;
651 XID icon;
652 } *prop_ret;
653 ulong bytes_after, num_ret;
654 Atom type_ret;
655 int ret, format_ret;
656 CARD32 st;
657
658 prop_ret = nullptr;
659 ret = XGetWindowProperty(m_display,
660 m_window,
661 m_system->m_atom.WM_STATE,
662 0,
663 2,
664 False,
665 m_system->m_atom.WM_STATE,
666 &type_ret,
667 &format_ret,
668 &num_ret,
669 &bytes_after,
670 ((uchar **)&prop_ret));
671 if ((ret == Success) && (prop_ret != nullptr) && (num_ret == 2)) {
672 st = prop_ret->state;
673 }
674 else {
675 st = NormalState;
676 }
677
678 if (prop_ret) {
679 XFree(prop_ret);
680 }
681
682 return st;
683}
684
685void GHOST_WindowX11::netwmMaximized(bool set)
686{
687 XEvent xev;
688
689 xev.xclient.type = ClientMessage;
690 xev.xclient.serial = 0;
691 xev.xclient.send_event = True;
692 xev.xclient.window = m_window;
693 xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
694 xev.xclient.format = 32;
695
696 if (set == True) {
697 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
698 }
699 else {
700 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
701 }
702
703 xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
704 xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
705 xev.xclient.data.l[3] = 0;
706 xev.xclient.data.l[4] = 0;
707 XSendEvent(m_display,
708 RootWindow(m_display, m_visualInfo->screen),
709 False,
710 SubstructureRedirectMask | SubstructureNotifyMask,
711 &xev);
712}
713
714bool GHOST_WindowX11::netwmIsMaximized() const
715{
716 Atom *prop_ret;
717 ulong bytes_after, num_ret, i;
718 Atom type_ret;
719 bool st;
720 int format_ret, ret, count;
721
722 prop_ret = nullptr;
723 st = False;
724 ret = XGetWindowProperty(m_display,
725 m_window,
726 m_system->m_atom._NET_WM_STATE,
727 0,
728 INT_MAX,
729 False,
730 XA_ATOM,
731 &type_ret,
732 &format_ret,
733 &num_ret,
734 &bytes_after,
735 (uchar **)&prop_ret);
736 if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
737 count = 0;
738 for (i = 0; i < num_ret; i++) {
739 if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ) {
740 count++;
741 }
742 if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT) {
743 count++;
744 }
745 if (count == 2) {
746 st = True;
747 break;
748 }
749 }
750 }
751
752 if (prop_ret) {
753 XFree(prop_ret);
754 }
755 return st;
756}
757
758void GHOST_WindowX11::netwmFullScreen(bool set)
759{
760 XEvent xev;
761
762 xev.xclient.type = ClientMessage;
763 xev.xclient.serial = 0;
764 xev.xclient.send_event = True;
765 xev.xclient.window = m_window;
766 xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
767 xev.xclient.format = 32;
768
769 if (set == True) {
770 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
771 }
772 else {
773 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
774 }
775
776 xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
777 xev.xclient.data.l[2] = 0;
778 xev.xclient.data.l[3] = 0;
779 xev.xclient.data.l[4] = 0;
780 XSendEvent(m_display,
781 RootWindow(m_display, m_visualInfo->screen),
782 False,
783 SubstructureRedirectMask | SubstructureNotifyMask,
784 &xev);
785}
786
787bool GHOST_WindowX11::netwmIsFullScreen() const
788{
789 Atom *prop_ret;
790 ulong bytes_after, num_ret, i;
791 Atom type_ret;
792 bool st;
793 int format_ret, ret;
794
795 prop_ret = nullptr;
796 st = False;
797 ret = XGetWindowProperty(m_display,
798 m_window,
799 m_system->m_atom._NET_WM_STATE,
800 0,
801 INT_MAX,
802 False,
803 XA_ATOM,
804 &type_ret,
805 &format_ret,
806 &num_ret,
807 &bytes_after,
808 (uchar **)&prop_ret);
809 if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
810 for (i = 0; i < num_ret; i++) {
811 if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_FULLSCREEN) {
812 st = True;
813 break;
814 }
815 }
816 }
817
818 if (prop_ret) {
819 XFree(prop_ret);
820 }
821 return st;
822}
823
824void GHOST_WindowX11::motifFullScreen(bool set)
825{
826 MotifWmHints hints;
827
829 if (set == True) {
830 hints.decorations = 0;
831 }
832 else {
833 hints.decorations = 1;
834 }
835
836 XChangeProperty(m_display,
837 m_window,
838 m_system->m_atom._MOTIF_WM_HINTS,
839 m_system->m_atom._MOTIF_WM_HINTS,
840 32,
841 PropModeReplace,
842 (uchar *)&hints,
843 4);
844}
845
846bool GHOST_WindowX11::motifIsFullScreen() const
847{
848 MotifWmHints *prop_ret;
849 ulong bytes_after, num_ret;
850 Atom type_ret;
851 bool state;
852 int format_ret, st;
853
854 prop_ret = nullptr;
855 state = False;
856 st = XGetWindowProperty(m_display,
857 m_window,
858 m_system->m_atom._MOTIF_WM_HINTS,
859 0,
860 INT_MAX,
861 False,
862 m_system->m_atom._MOTIF_WM_HINTS,
863 &type_ret,
864 &format_ret,
865 &num_ret,
866 &bytes_after,
867 (uchar **)&prop_ret);
868 if ((st == Success) && prop_ret) {
869 if (prop_ret->flags & MWM_HINTS_DECORATIONS) {
870 if (!prop_ret->decorations) {
871 state = True;
872 }
873 }
874 }
875
876 if (prop_ret) {
877 XFree(prop_ret);
878 }
879 return state;
880}
881
883{
884 GHOST_TWindowState state_ret;
885 int state;
886
887 state_ret = GHOST_kWindowStateNormal;
888 state = icccmGetState();
889 /*
890 * In the Iconic and Withdrawn state, the window
891 * is unmapped, so only need return a Minimized state.
892 */
893 if (ELEM(state, IconicState, WithdrawnState)) {
894 state_ret = GHOST_kWindowStateMinimized;
895 }
896 else if (netwmIsFullScreen() == True) {
898 }
899 else if (motifIsFullScreen() == True) {
901 }
902 else if (netwmIsMaximized() == True) {
903 state_ret = GHOST_kWindowStateMaximized;
904 }
905 return state_ret;
906}
907
909{
910 GHOST_TWindowState cur_state;
911 bool is_max, is_full, is_motif_full;
912
913 cur_state = getState();
914 if (state == int(cur_state)) {
915 return GHOST_kSuccess;
916 }
917
918 if (cur_state != GHOST_kWindowStateMinimized) {
919 /*
920 * The window don't have this property's
921 * if it's not mapped.
922 */
923 is_max = netwmIsMaximized();
924 is_full = netwmIsFullScreen();
925 }
926 else {
927 is_max = False;
928 is_full = False;
929 }
930
931 is_motif_full = motifIsFullScreen();
932
934 state = m_normal_state;
935 }
936
938 if (is_max == True) {
939 netwmMaximized(False);
940 }
941 if (is_full == True) {
942 netwmFullScreen(False);
943 }
944 if (is_motif_full == True) {
945 motifFullScreen(False);
946 }
947 icccmSetState(NormalState);
948 return GHOST_kSuccess;
949 }
950
952 /*
953 * We can't change to full screen if the window
954 * isn't mapped.
955 */
956 if (cur_state == GHOST_kWindowStateMinimized) {
957 return GHOST_kFailure;
958 }
959
960 m_normal_state = cur_state;
961
962 if (is_max == True) {
963 netwmMaximized(False);
964 }
965 if (is_full == False) {
966 netwmFullScreen(True);
967 }
968 if (is_motif_full == False) {
969 motifFullScreen(True);
970 }
971 return GHOST_kSuccess;
972 }
973
975 /*
976 * We can't change to Maximized if the window
977 * isn't mapped.
978 */
979 if (cur_state == GHOST_kWindowStateMinimized) {
980 return GHOST_kFailure;
981 }
982
983 if (is_full == True) {
984 netwmFullScreen(False);
985 }
986 if (is_motif_full == True) {
987 motifFullScreen(False);
988 }
989 if (is_max == False) {
990 netwmMaximized(True);
991 }
992 return GHOST_kSuccess;
993 }
994
996 /*
997 * The window manager need save the current state of
998 * the window (maximized, full screen, etc).
999 */
1000 icccmSetState(IconicState);
1001 return GHOST_kSuccess;
1002 }
1003
1004 return GHOST_kFailure;
1005}
1006
1008{
1009 if (order == GHOST_kWindowOrderTop) {
1010 XWindowAttributes attr;
1011 Atom atom;
1012
1013 /* We use both #XRaiseWindow and #_NET_ACTIVE_WINDOW, since some
1014 * window managers ignore the former (e.g. KWIN from KDE) and others
1015 * don't implement the latter (e.g. FLUXBOX before 0.9.9). */
1016
1017 XRaiseWindow(m_display, m_window);
1018
1019 atom = XInternAtom(m_display, "_NET_ACTIVE_WINDOW", True);
1020
1021 if (atom != None) {
1022 Window root;
1023 XEvent xev;
1024 long eventmask;
1025
1026 xev.xclient.type = ClientMessage;
1027 xev.xclient.serial = 0;
1028 xev.xclient.send_event = True;
1029 xev.xclient.window = m_window;
1030 xev.xclient.message_type = atom;
1031
1032 xev.xclient.format = 32;
1033 xev.xclient.data.l[0] = 1;
1034 xev.xclient.data.l[1] = CurrentTime;
1035 xev.xclient.data.l[2] = m_window;
1036 xev.xclient.data.l[3] = 0;
1037 xev.xclient.data.l[4] = 0;
1038
1039 root = RootWindow(m_display, m_visualInfo->screen);
1040 eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
1041
1042 XSendEvent(m_display, root, False, eventmask, &xev);
1043 }
1044
1045 XGetWindowAttributes(m_display, m_window, &attr);
1046
1047 /* Minimized windows give bad match error. */
1048 if (attr.map_state == IsViewable) {
1049 XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime);
1050 }
1051 XFlush(m_display);
1052 }
1053 else if (order == GHOST_kWindowOrderBottom) {
1054 XLowerWindow(m_display, m_window);
1055 XFlush(m_display);
1056 }
1057 else {
1058 return GHOST_kFailure;
1059 }
1060
1061 return GHOST_kSuccess;
1062}
1063
1065{
1066 Atom atom_window_type = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False);
1067 Atom atom_dialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
1068
1069 Atom *prop_ret;
1070 ulong bytes_after, num_ret;
1071 Atom type_ret;
1072 bool st;
1073 int format_ret, ret;
1074
1075 prop_ret = nullptr;
1076 st = False;
1077 ret = XGetWindowProperty(m_display,
1078 m_window,
1079 atom_window_type,
1080 0,
1081 INT_MAX,
1082 False,
1083 XA_ATOM,
1084 &type_ret,
1085 &format_ret,
1086 &num_ret,
1087 &bytes_after,
1088 (uchar **)&prop_ret);
1089 if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
1090 if (prop_ret[0] == atom_dialog) {
1091 st = True;
1092 }
1093 }
1094
1095 if (prop_ret) {
1096 XFree(prop_ret);
1097 }
1098
1099 return st;
1100}
1101
1103{
1104 /* So the idea of this function is to generate an expose event
1105 * for the window.
1106 * Unfortunately X does not handle expose events for you and
1107 * it is the client's job to refresh the dirty part of the window.
1108 * We need to queue up invalidate calls and generate GHOST events
1109 * for them in the system.
1110 *
1111 * We implement this by setting a boolean in this class to concatenate
1112 * all such calls into a single event for this window.
1113 *
1114 * At the same time we queue the dirty windows in the system class
1115 * and generate events for them at the next processEvents call. */
1116
1117 if (m_invalid_window == false) {
1118 m_system->addDirtyWindow(this);
1119 m_invalid_window = true;
1120 }
1121
1122 return GHOST_kSuccess;
1123}
1124
1129
1131{
1132 m_invalid_window = false;
1133}
1134
1136{
1137 std::map<uint, Cursor>::iterator it = m_standard_cursors.begin();
1138 for (; it != m_standard_cursors.end(); ++it) {
1139 XFreeCursor(m_display, it->second);
1140 }
1141
1142 if (m_empty_cursor) {
1143 XFreeCursor(m_display, m_empty_cursor);
1144 }
1145 if (m_custom_cursor) {
1146 XFreeCursor(m_display, m_custom_cursor);
1147 }
1148
1149 if (m_valid_setup) {
1150 static Atom Primary_atom, Clipboard_atom;
1151 Window p_owner, c_owner;
1152 /* Change the owner of the Atoms to None if we are the owner. */
1153 Primary_atom = XInternAtom(m_display, "PRIMARY", False);
1154 Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
1155
1156 p_owner = XGetSelectionOwner(m_display, Primary_atom);
1157 c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
1158
1159 if (p_owner == m_window) {
1160 XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
1161 }
1162 if (c_owner == m_window) {
1163 XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
1164 }
1165 }
1166
1167 if (m_visualInfo) {
1168 XFree(m_visualInfo);
1169 }
1170
1171#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1172 if (m_xic) {
1173 XDestroyIC(m_xic);
1174 }
1175#endif
1176
1177#ifdef WITH_XDND
1178 delete m_dropTarget;
1179#endif
1180
1182
1183 if (m_valid_setup) {
1184 XDestroyWindow(m_display, m_window);
1185 }
1186}
1187
1189{
1190 switch (type) {
1191#ifdef WITH_VULKAN_BACKEND
1192 case GHOST_kDrawingContextTypeVulkan: {
1194 GHOST_kVulkanPlatformX11,
1195 m_window,
1196 m_display,
1197 nullptr,
1198 nullptr,
1199 nullptr,
1200 1,
1201 2,
1202 m_is_debug_context,
1203 m_preferred_device);
1204 if (context->initializeDrawingContext()) {
1205 return context;
1206 }
1207 delete context;
1208 return nullptr;
1209 }
1210#endif
1211
1212#ifdef WITH_OPENGL_BACKEND
1213 case GHOST_kDrawingContextTypeOpenGL: {
1214# ifdef USE_EGL
1215 /* Try to initialize an EGL context. */
1216 for (int minor = 6; minor >= 3; --minor) {
1218 this->m_system,
1220 EGLNativeWindowType(m_window),
1221 EGLNativeDisplayType(m_display),
1222 EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
1223 4,
1224 minor,
1226 (m_is_debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
1228 EGL_OPENGL_API);
1229 if (context->initializeDrawingContext()) {
1230 return context;
1231 }
1232 delete context;
1233 }
1234 /* EGL initialization failed, try to fall back to a GLX context. */
1235# endif
1236
1237 for (int minor = 6; minor >= 3; --minor) {
1238 GHOST_Context *context = new GHOST_ContextGLX(
1240 m_window,
1241 m_display,
1242 (GLXFBConfig)m_fbconfig,
1243 GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
1244 4,
1245 minor,
1246 GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1248 if (context->initializeDrawingContext()) {
1249 return context;
1250 }
1251 delete context;
1252 }
1253 return nullptr;
1254 }
1255#endif
1256
1257 default:
1258 /* Unsupported backend. */
1259 return nullptr;
1260 }
1261}
1262
1263GHOST_TSuccess GHOST_WindowX11::getStandardCursor(GHOST_TStandardCursor g_cursor, Cursor &xcursor)
1264{
1265 uint xcursor_id;
1266
1267 switch (g_cursor) {
1269 xcursor_id = XC_question_arrow;
1270 break;
1272 xcursor_id = XC_watch;
1273 break;
1275 xcursor_id = XC_xterm;
1276 break;
1278 xcursor_id = XC_crosshair;
1279 break;
1281 xcursor_id = XC_sb_v_double_arrow;
1282 break;
1284 xcursor_id = XC_sb_h_double_arrow;
1285 break;
1287 xcursor_id = XC_top_side;
1288 break;
1290 xcursor_id = XC_bottom_side;
1291 break;
1293 xcursor_id = XC_left_side;
1294 break;
1296 xcursor_id = XC_right_side;
1297 break;
1299 xcursor_id = XC_top_left_corner;
1300 break;
1302 xcursor_id = XC_top_right_corner;
1303 break;
1305 xcursor_id = XC_bottom_right_corner;
1306 break;
1308 xcursor_id = XC_bottom_left_corner;
1309 break;
1311 xcursor = None;
1312 return GHOST_kSuccess;
1313 default:
1314 xcursor = None;
1315 return GHOST_kFailure;
1316 }
1317
1318 xcursor = m_standard_cursors[xcursor_id];
1319
1320 if (!xcursor) {
1321 xcursor = XCreateFontCursor(m_display, xcursor_id);
1322
1323 m_standard_cursors[xcursor_id] = xcursor;
1324 }
1325
1326 return GHOST_kSuccess;
1327}
1328
1329Cursor GHOST_WindowX11::getEmptyCursor()
1330{
1331 if (!m_empty_cursor) {
1332 Pixmap blank;
1333 XColor dummy = {0};
1334 char data[1] = {0};
1335
1336 /* make a blank cursor */
1337 blank = XCreateBitmapFromData(
1338 m_display, RootWindow(m_display, m_visualInfo->screen), data, 1, 1);
1339
1340 m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
1341 XFreePixmap(m_display, blank);
1342 }
1343
1344 return m_empty_cursor;
1345}
1346
1348{
1349 Cursor xcursor;
1350
1351 if (visible) {
1352 if (m_visible_cursor) {
1353 xcursor = m_visible_cursor;
1354 }
1355 else if (getStandardCursor(getCursorShape(), xcursor) == GHOST_kFailure) {
1356 getStandardCursor(getCursorShape(), xcursor);
1357 }
1358 }
1359 else {
1360 xcursor = getEmptyCursor();
1361 }
1362
1363 XDefineCursor(m_display, m_window, xcursor);
1364 XFlush(m_display);
1365
1366 return GHOST_kSuccess;
1367}
1368
1370{
1371 if (mode != GHOST_kGrabDisable) {
1372 if (mode != GHOST_kGrabNormal) {
1373 m_system->getCursorPosition(UNPACK2(m_cursorGrabInitPos));
1374 setCursorGrabAccum(0, 0);
1375
1376 if (mode == GHOST_kGrabHide) {
1378 }
1379 }
1380#ifdef GHOST_X11_GRAB
1381 XGrabPointer(m_display,
1382 m_window,
1383 False,
1384 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1385 GrabModeAsync,
1386 GrabModeAsync,
1387 None,
1388 None,
1389 CurrentTime);
1390#endif
1391 }
1392 else {
1394 m_system->setCursorPosition(UNPACK2(m_cursorGrabInitPos));
1395 }
1396
1398 /* use to generate a mouse move event, otherwise the last event
1399 * blender gets can be outside the screen causing menus not to show
1400 * properly unless the user moves the mouse */
1401
1402#if defined(WITH_X11_XINPUT) && defined(USE_X11_XINPUT_WARP)
1403 if ((m_system->m_xinput_version.present) && (m_system->m_xinput_version.major_version >= 2))
1404 {
1405 int device_id;
1406 if (XIGetClientPointer(m_display, None, &device_id) != False) {
1407 XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, 0, 0);
1408 }
1409 }
1410 else
1411#endif
1412 {
1413 XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
1414 }
1415 }
1416
1417 /* Perform this last so to workaround XWayland bug, see: #53004. */
1420 }
1421
1422 /* Almost works without but important
1423 * otherwise the mouse GHOST location can be incorrect on exit. */
1424 setCursorGrabAccum(0, 0);
1425 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1426#ifdef GHOST_X11_GRAB
1427 XUngrabPointer(m_display, CurrentTime);
1428#endif
1429 }
1430
1431 XFlush(m_display);
1432
1433 return GHOST_kSuccess;
1434}
1435
1437{
1438 Cursor xcursor;
1439 if (getStandardCursor(shape, xcursor) == GHOST_kFailure) {
1440 getStandardCursor(GHOST_kStandardCursorDefault, xcursor);
1441 }
1442
1443 m_visible_cursor = xcursor;
1444
1445 XDefineCursor(m_display, m_window, xcursor);
1446 XFlush(m_display);
1447
1448 return GHOST_kSuccess;
1449}
1450
1452{
1453 Cursor xcursor;
1454 return getStandardCursor(shape, xcursor);
1455}
1456
1458 uint8_t *mask,
1459 int sizex,
1460 int sizey,
1461 int hotX,
1462 int hotY,
1463 bool /*canInvertColor*/)
1464{
1465 Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
1466 Pixmap bitmap_pix, mask_pix;
1467 XColor fg, bg;
1468
1469 if (XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) {
1470 return GHOST_kFailure;
1471 }
1472 if (XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) {
1473 return GHOST_kFailure;
1474 }
1475
1476 if (m_custom_cursor) {
1477 XFreeCursor(m_display, m_custom_cursor);
1478 }
1479
1480 bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char *)bitmap, sizex, sizey);
1481 mask_pix = XCreateBitmapFromData(m_display, m_window, (char *)mask, sizex, sizey);
1482
1483 m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
1484 XDefineCursor(m_display, m_window, m_custom_cursor);
1485 XFlush(m_display);
1486
1487 m_visible_cursor = m_custom_cursor;
1488
1489 XFreePixmap(m_display, bitmap_pix);
1490 XFreePixmap(m_display, mask_pix);
1491
1492 XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
1493 XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
1494
1495 return GHOST_kSuccess;
1496}
1497
1499{
1500 /* Try to read DPI setting set using xrdb */
1501 char *resMan = XResourceManagerString(m_display);
1502 if (resMan) {
1503 XrmDatabase xrdb = XrmGetStringDatabase(resMan);
1504 if (xrdb) {
1505 int dpi = -1;
1506 char *type = nullptr;
1507 XrmValue val;
1508
1509 int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val);
1510 if (success && type) {
1511 if (STREQ(type, "String")) {
1512 dpi = atoi((const char *)val.addr);
1513 }
1514 }
1515 XrmDestroyDatabase(xrdb);
1516
1517 if (dpi != -1) {
1518 return dpi;
1519 }
1520 }
1521 }
1522
1523 /* Fall back to calculating DPI using X reported DPI, set using `xrandr --dpi`. */
1524 XWindowAttributes attr;
1525 if (!XGetWindowAttributes(m_display, m_window, &attr)) {
1526 /* Failed to get window attributes, return X11 default DPI */
1527 return 96;
1528 }
1529
1530 Screen *screen = attr.screen;
1531 int pixelWidth = WidthOfScreen(screen);
1532 int pixelHeight = HeightOfScreen(screen);
1533 int mmWidth = WidthMMOfScreen(screen);
1534 int mmHeight = HeightMMOfScreen(screen);
1535
1536 double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight));
1537 double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight));
1538 float inchDiagonal = mmDiagonal * 0.039f;
1539 int dpi = pixelDiagonal / inchDiagonal;
1540 return dpi;
1541}
1542
1544{
1545 return GHOST_kFailure;
1546}
1547
void BLI_kdtree_nd_ free(KDTree *tree)
unsigned char uchar
unsigned long ulong
unsigned int uint
#define UNPACK2(a)
#define ARRAY_SIZE(arr)
#define ELEM(...)
#define STREQ(a, b)
#define GHOST_OPENGL_EGL_CONTEXT_FLAGS
#define GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY
#define GHOST_OPENGL_GLX_CONTEXT_FLAGS
#define Window
#define Display
#define GHOST_PRINT(x)
static const unsigned long BLENDER_ICONS_WM_X11[]
GHOST_TWindowState
@ GHOST_kWindowStateMinimized
@ GHOST_kWindowStateMaximized
@ GHOST_kWindowStateNormal
@ GHOST_kWindowStateFullScreen
GHOST_TStandardCursor
@ GHOST_kStandardCursorBottomLeftCorner
@ GHOST_kStandardCursorHelp
@ GHOST_kStandardCursorWait
@ GHOST_kStandardCursorTopSide
@ GHOST_kStandardCursorCrosshair
@ GHOST_kStandardCursorLeftRight
@ GHOST_kStandardCursorUpDown
@ GHOST_kStandardCursorBottomSide
@ GHOST_kStandardCursorTopLeftCorner
@ GHOST_kStandardCursorBottomRightCorner
@ GHOST_kStandardCursorDefault
@ GHOST_kStandardCursorRightSide
@ GHOST_kStandardCursorTopRightCorner
@ GHOST_kStandardCursorLeftSide
@ GHOST_kStandardCursorText
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
GHOST_TDrawingContextType
GHOST_TWindowOrder
@ GHOST_kWindowOrderTop
@ GHOST_kWindowOrderBottom
GHOST_TSuccess
Definition GHOST_Types.h:80
@ GHOST_kFailure
Definition GHOST_Types.h:80
@ GHOST_kSuccess
Definition GHOST_Types.h:80
GHOST_TGrabCursorMode
@ GHOST_kGrabDisable
@ GHOST_kGrabHide
@ GHOST_kGrabNormal
@ GHOST_DialogError
Definition GHOST_Types.h:75
#define _NET_WM_STATE_REMOVE
@ MWM_FUNCTION_MINIMIZE
@ MWM_FUNCTION_RESIZE
@ MWM_FUNCTION_MAXIMIZE
@ MWM_FUNCTION_ALL
@ MWM_FUNCTION_MOVE
@ MWM_FUNCTION_CLOSE
@ MWM_HINTS_DECORATIONS
@ MWM_HINTS_FUNCTIONS
#define HOST_NAME_MAX
#define _NET_WM_STATE_ADD
BMesh const char void * data
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
GHOST_TSuccess showMessageBox(const char *title, const char *message, const char *help_label, const char *continue_label, const char *link, GHOST_DialogOptions dialog_options) const override
GHOST_TSuccess setDialogHints(GHOST_WindowX11 *parentWindow)
GHOST_Context * newDrawingContext(GHOST_TDrawingContextType type) override
bool getValid() const override
void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
GHOST_TSuccess setClientHeight(uint32_t height) override
void getWindowBounds(GHOST_Rect &bounds) const override
~GHOST_WindowX11() override
GHOST_TWindowState m_post_state
GHOST_TSuccess setState(GHOST_TWindowState state) override
GHOST_TSuccess endProgressBar() override
void getClientBounds(GHOST_Rect &bounds) const override
GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_WindowX11 *parentWindow, GHOST_TDrawingContextType type, const bool is_dialog, const bool stereoVisual, const bool exclusive, const bool is_debug, const GHOST_GPUDevice &preferred_device)
void setTitle(const char *title) override
std::string getTitle() const override
GHOST_TSuccess setClientWidth(uint32_t width) override
GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override
GHOST_TSuccess setProgressBar(float progress) override
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor shape) override
GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) override
GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) override
GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override
GHOST_TSuccess setWindowCursorVisibility(bool visible) override
void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
bool isDialog() const override
uint16_t getDPIHint() override
GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override
GHOST_TSuccess invalidate() override
GHOST_TWindowState getState() const override
GHOST_Rect m_cursorGrabBounds
void setCursorGrabAccum(int32_t x, int32_t y)
GHOST_TGrabCursorMode m_cursorGrab
bool m_wantStereoVisual
int32_t m_cursorGrabInitPos[2]
GHOST_TStandardCursor getCursorShape() const override
GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) override
GHOST_TSuccess releaseNativeHandles()
bool getValid() const override
GHOST_Window(uint32_t width, uint32_t height, GHOST_TWindowState state, const bool wantStereoVisual=false, const bool exclusive=false)
uint top
#define sqrt
int count
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static ulong state[N]
static int left
#define L
return ret
i
Definition text_draw.cc:230
uint len
PointerRNA * ptr
Definition wm_files.cc:4226