23#include <winpr/platform.h>
24#include "sdl_utils.hpp"
28#if defined(WITH_SDL_X11_NATIVE)
33bool sdl_x11_has_compositor()
35 if (!sdl::utils::isX11Driver())
38 Display* dpy = XOpenDisplay(
nullptr);
42 (void)snprintf(sel,
sizeof(sel),
"_NET_WM_CM_S%d", DefaultScreen(dpy));
43 const Atom atom = XInternAtom(dpy, sel, False);
44 const bool composited = (XGetSelectionOwner(dpy, atom) != None);
50static std::pair<Display*, Window> sdl_x11_handles(SDL_Window* window)
52 if (!window || !sdl::utils::isX11Driver())
53 return {
nullptr, 0 };
54 auto props = SDL_GetWindowProperties(window);
55 auto dpy =
static_cast<Display*
>(
56 SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER,
nullptr));
58 static_cast<Window
>(SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0));
62bool sdl_x11_begin_move_size(SDL_Window* window,
int netDirection)
64 const auto [dpy, xwin] = sdl_x11_handles(window);
65 if (!dpy || (xwin == 0))
69 static Atom s_moveResize = None;
70 if (s_moveResize == None)
71 s_moveResize = XInternAtom(dpy,
"_NET_WM_MOVERESIZE", False);
75 SDL_GetGlobalMouseState(&gx, &gy);
77 XClientMessageEvent xev = {};
78 xev.type = ClientMessage;
80 xev.message_type = s_moveResize;
83 xev.data.l[0] =
static_cast<long>(gx);
84 xev.data.l[1] =
static_cast<long>(gy);
85 xev.data.l[2] = netDirection;
86 xev.data.l[3] = Button1;
91 XUngrabPointer(dpy, CurrentTime);
92 XSendEvent(dpy, DefaultRootWindow(dpy), False,
93 SubstructureRedirectMask | SubstructureNotifyMask,
reinterpret_cast<XEvent*
>(&xev));
98bool sdl_x11_set_frame_extents(SDL_Window* window,
int left,
int right,
int top,
int bottom)
100 const auto [dpy, xwin] = sdl_x11_handles(window);
101 if (!dpy || (xwin == 0))
104 static Atom s_extents = None;
105 if (s_extents == None)
106 s_extents = XInternAtom(dpy,
"_GTK_FRAME_EXTENTS", False);
109 const long data[4] = { left, right, top, bottom };
110 XChangeProperty(dpy, xwin, s_extents, XA_CARDINAL, 32, PropModeReplace,
111 reinterpret_cast<const unsigned char*
>(data), 4);
116bool sdl_x11_set_bit_gravity(SDL_Window* window,
int gravity)
118 const auto [dpy, xwin] = sdl_x11_handles(window);
119 if (!dpy || (xwin == 0))
123 XSetWindowAttributes attrs{};
124 attrs.bit_gravity = gravity;
125 XChangeWindowAttributes(dpy, xwin, CWBitGravity, &attrs);
130bool sdl_x11_send_left_button_release(SDL_Window* window)
132 const auto [dpy, xwin] = sdl_x11_handles(window);
133 if (!dpy || (xwin == 0))
137 XButtonEvent ev = {};
138 ev.type = ButtonRelease;
141 ev.root = DefaultRootWindow(dpy);
142 ev.time = CurrentTime;
144 ev.same_screen = True;
145 if (!XSendEvent(dpy, xwin, False, NoEventMask,
reinterpret_cast<XEvent*
>(&ev)))
151bool sdl_x11_raise_window(SDL_Window* window)
153 const auto [dpy, xwin] = sdl_x11_handles(window);
154 if (!dpy || (xwin == 0))
156 XRaiseWindow(dpy, xwin);
161static Window sdl_x11_xwindow(SDL_Window* window)
163 return sdl_x11_handles(window).second;
166bool sdl_x11_restack_windows(
const std::vector<SDL_Window*>& topToBottom)
168 if (!sdl::utils::isX11Driver() || (topToBottom.size() < 2))
171 auto props = SDL_GetWindowProperties(topToBottom.front());
172 auto dpy =
static_cast<Display*
>(
173 SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER,
nullptr));
177 static Atom s_restack = None;
178 if (s_restack == None)
179 s_restack = XInternAtom(dpy,
"_NET_RESTACK_WINDOW", False);
181 const Window root = DefaultRootWindow(dpy);
183 for (
size_t i = 1; i < topToBottom.size(); i++)
185 const Window win = sdl_x11_xwindow(topToBottom.at(i));
186 const Window sibling = sdl_x11_xwindow(topToBottom.at(i - 1));
187 if ((win == 0) || (sibling == 0))
190 XClientMessageEvent xev = {};
191 xev.type = ClientMessage;
193 xev.message_type = s_restack;
197 xev.data.l[1] =
static_cast<long>(sibling);
198 xev.data.l[2] = Below;
200 XSendEvent(dpy, root, False, SubstructureRedirectMask | SubstructureNotifyMask,
201 reinterpret_cast<XEvent*
>(&xev));
209bool sdl_x11_has_compositor()
214bool sdl_x11_begin_move_size(WINPR_ATTR_UNUSED SDL_Window* window,
215 WINPR_ATTR_UNUSED
int netDirection)
220bool sdl_x11_set_frame_extents(WINPR_ATTR_UNUSED SDL_Window* window, WINPR_ATTR_UNUSED
int left,
221 WINPR_ATTR_UNUSED
int right, WINPR_ATTR_UNUSED
int top,
222 WINPR_ATTR_UNUSED
int bottom)
227bool sdl_x11_set_bit_gravity(WINPR_ATTR_UNUSED SDL_Window* window, WINPR_ATTR_UNUSED
int gravity)
232bool sdl_x11_restack_windows(WINPR_ATTR_UNUSED
const std::vector<SDL_Window*>& topToBottom)
237bool sdl_x11_send_left_button_release(WINPR_ATTR_UNUSED SDL_Window* window)
242bool sdl_x11_raise_window(WINPR_ATTR_UNUSED SDL_Window* window)