Atlas - SDL_x11xfixes.c

Home / ext / SDL / src / video / x11 Lines: 1 | Size: 8295 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21 22#include "SDL_internal.h" 23 24#if defined(SDL_VIDEO_DRIVER_X11) && defined(SDL_VIDEO_DRIVER_X11_XFIXES) 25 26#include "SDL_x11video.h" 27#include "SDL_x11xfixes.h" 28#include "../../events/SDL_mouse_c.h" 29#include "../../events/SDL_touch_c.h" 30 31static bool xfixes_initialized = true; 32static int xfixes_selection_notify_event = 0; 33 34static int query_xfixes_version(Display *display, int major, int minor) 35{ 36 // We don't care if this fails, so long as it sets major/minor on it's way out the door. 37 X11_XFixesQueryVersion(display, &major, &minor); 38 return (major * 1000) + minor; 39} 40 41static bool xfixes_version_atleast(const int version, const int wantmajor, const int wantminor) 42{ 43 return version >= ((wantmajor * 1000) + wantminor); 44} 45 46void X11_InitXfixes(SDL_VideoDevice *_this) 47{ 48 SDL_VideoData *data = _this->internal; 49 50 int version = 0; 51 int event, error; 52 int fixes_opcode; 53 54 Atom XA_CLIPBOARD = data->atoms.CLIPBOARD; 55 56 if (!SDL_X11_HAVE_XFIXES || 57 !X11_XQueryExtension(data->display, "XFIXES", &fixes_opcode, &event, &error)) { 58 return; 59 } 60 61 // Selection tracking is available in all versions of XFixes 62 xfixes_selection_notify_event = event + XFixesSelectionNotify; 63 X11_XFixesSelectSelectionInput(data->display, DefaultRootWindow(data->display), 64 XA_CLIPBOARD, XFixesSetSelectionOwnerNotifyMask); 65 X11_XFixesSelectSelectionInput(data->display, DefaultRootWindow(data->display), 66 XA_PRIMARY, XFixesSetSelectionOwnerNotifyMask); 67 68 // We need at least 5.0 for barriers. 69 version = query_xfixes_version(data->display, 5, 0); 70 if (!xfixes_version_atleast(version, 5, 0)) { 71 return; // X server does not support the version we want at all. 72 } 73 74 xfixes_initialized = 1; 75} 76 77bool X11_XfixesIsInitialized(void) 78{ 79 return xfixes_initialized; 80} 81 82int X11_GetXFixesSelectionNotifyEvent(void) 83{ 84 return xfixes_selection_notify_event; 85} 86 87bool X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window) 88{ 89 if (SDL_RectEmpty(&window->mouse_rect)) { 90 X11_ConfineCursorWithFlags(_this, window, NULL, 0); 91 } else { 92 if (window->flags & SDL_WINDOW_INPUT_FOCUS) { 93 X11_ConfineCursorWithFlags(_this, window, &window->mouse_rect, 0); 94 } else { 95 // Save the state for when we get focus again 96 SDL_WindowData *wdata = window->internal; 97 98 SDL_memcpy(&wdata->barrier_rect, &window->mouse_rect, sizeof(wdata->barrier_rect)); 99 100 wdata->pointer_barrier_active = true; 101 } 102 } 103 104 return true; 105} 106 107bool X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rect, int flags) 108{ 109 /* Yaakuro: For some reason Xfixes when confining inside a rect where the 110 * edges exactly match, a rectangle the cursor 'slips' out of the barrier. 111 * To prevent that the lines for the barriers will span the whole screen. 112 */ 113 SDL_VideoData *data = _this->internal; 114 SDL_WindowData *wdata; 115 116 if (!X11_XfixesIsInitialized()) { 117 return SDL_Unsupported(); 118 } 119 120 // If there is already a set of barriers active, disable them. 121 if (data->active_cursor_confined_window) { 122 X11_DestroyPointerBarrier(_this, data->active_cursor_confined_window); 123 } 124 125 SDL_assert(window != NULL); 126 wdata = window->internal; 127 128 /* If user did not specify an area to confine, destroy the barrier that was/is assigned to 129 * this window it was assigned */ 130 if (rect) { 131 int x1, y1, x2, y2; 132 SDL_Rect bounds; 133 SDL_GetWindowPosition(window, &bounds.x, &bounds.y); 134 SDL_GetWindowSize(window, &bounds.w, &bounds.h); 135 136 /** Negative values are not allowed. Clip values relative to the specified window. */ 137 x1 = bounds.x + SDL_max(rect->x, 0); 138 y1 = bounds.y + SDL_max(rect->y, 0); 139 x2 = SDL_min(bounds.x + rect->x + rect->w, bounds.x + bounds.w); 140 y2 = SDL_min(bounds.y + rect->y + rect->h, bounds.y + bounds.h); 141 142 if ((wdata->barrier_rect.x != rect->x) || 143 (wdata->barrier_rect.y != rect->y) || 144 (wdata->barrier_rect.w != rect->w) || 145 (wdata->barrier_rect.h != rect->h)) { 146 wdata->barrier_rect = *rect; 147 } 148 149 // Use the display bounds to ensure the barriers don't have corner gaps 150 SDL_GetDisplayBounds(SDL_GetDisplayForWindow(window), &bounds); 151 152 /** Create the left barrier */ 153 wdata->barrier[0] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, 154 x1, bounds.y, 155 x1, bounds.y + bounds.h, 156 BarrierPositiveX, 157 0, NULL); 158 /** Create the right barrier */ 159 wdata->barrier[1] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, 160 x2, bounds.y, 161 x2, bounds.y + bounds.h, 162 BarrierNegativeX, 163 0, NULL); 164 /** Create the top barrier */ 165 wdata->barrier[2] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, 166 bounds.x, y1, 167 bounds.x + bounds.w, y1, 168 BarrierPositiveY, 169 0, NULL); 170 /** Create the bottom barrier */ 171 wdata->barrier[3] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, 172 bounds.x, y2, 173 bounds.x + bounds.w, y2, 174 BarrierNegativeY, 175 0, NULL); 176 177 X11_XFlush(data->display); 178 179 // Lets remember current active confined window. 180 data->active_cursor_confined_window = window; 181 182 /* User activated the confinement for this window. We use this later to reactivate 183 * the confinement if it got deactivated by FocusOut or UnmapNotify */ 184 wdata->pointer_barrier_active = true; 185 } else { 186 X11_DestroyPointerBarrier(_this, window); 187 188 // Only set barrier inactive when user specified NULL and not handled by focus out. 189 if (flags != X11_BARRIER_HANDLED_BY_EVENT) { 190 wdata->pointer_barrier_active = false; 191 } 192 } 193 return true; 194} 195 196void X11_DestroyPointerBarrier(SDL_VideoDevice *_this, SDL_Window *window) 197{ 198 int i; 199 SDL_VideoData *data = _this->internal; 200 if (window) { 201 SDL_WindowData *wdata = window->internal; 202 203 for (i = 0; i < 4; i++) { 204 if (wdata->barrier[i] > 0) { 205 X11_XFixesDestroyPointerBarrier(data->display, wdata->barrier[i]); 206 wdata->barrier[i] = 0; 207 } 208 } 209 X11_XFlush(data->display); 210 } 211 data->active_cursor_confined_window = NULL; 212} 213 214#endif // SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_DRIVER_X11_XFIXES 215
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.