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)))
151static Window sdl_x11_xwindow(SDL_Window* window)
153 return sdl_x11_handles(window).second;
156bool sdl_x11_restack_windows(
const std::vector<SDL_Window*>& topToBottom)
158 if (!sdl::utils::isX11Driver() || (topToBottom.size() < 2))
161 auto props = SDL_GetWindowProperties(topToBottom.front());
162 auto dpy =
static_cast<Display*
>(
163 SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER,
nullptr));
167 static Atom s_restack = None;
168 if (s_restack == None)
169 s_restack = XInternAtom(dpy,
"_NET_RESTACK_WINDOW", False);
171 const Window root = DefaultRootWindow(dpy);
173 for (
size_t i = 1; i < topToBottom.size(); i++)
175 const Window win = sdl_x11_xwindow(topToBottom.at(i));
176 const Window sibling = sdl_x11_xwindow(topToBottom.at(i - 1));
177 if ((win == 0) || (sibling == 0))
180 XClientMessageEvent xev = {};
181 xev.type = ClientMessage;
183 xev.message_type = s_restack;
187 xev.data.l[1] =
static_cast<long>(sibling);
188 xev.data.l[2] = Below;
190 XSendEvent(dpy, root, False, SubstructureRedirectMask | SubstructureNotifyMask,
191 reinterpret_cast<XEvent*
>(&xev));
199bool sdl_x11_has_compositor()
204bool sdl_x11_begin_move_size(WINPR_ATTR_UNUSED SDL_Window* window,
205 WINPR_ATTR_UNUSED
int netDirection)
210bool sdl_x11_set_frame_extents(WINPR_ATTR_UNUSED SDL_Window* window, WINPR_ATTR_UNUSED
int left,
211 WINPR_ATTR_UNUSED
int right, WINPR_ATTR_UNUSED
int top,
212 WINPR_ATTR_UNUSED
int bottom)
217bool sdl_x11_set_bit_gravity(WINPR_ATTR_UNUSED SDL_Window* window, WINPR_ATTR_UNUSED
int gravity)
222bool sdl_x11_restack_windows(WINPR_ATTR_UNUSED
const std::vector<SDL_Window*>& topToBottom)
227bool sdl_x11_send_left_button_release(WINPR_ATTR_UNUSED SDL_Window* window)