Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/SDL3/SDL_video.h
Original file line number Diff line number Diff line change
Expand Up @@ -2703,6 +2703,18 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowOpacity(SDL_Window *window, float
*/
extern SDL_DECLSPEC float SDLCALL SDL_GetWindowOpacity(SDL_Window *window);

/**
* Enable or disable mouse passthrough for a window.
*
* \param window the window to set mouse passthrough for.
* \param passthrough true to make the window transparent to mouse input, false to capture mouse input.
*
* \threadsafety This function should only be called on the main thread.
*
* \since This function is available since SDL 3.6.0.
*/
extern SDL_DECLSPEC void SDLCALL SDL_SetWindowMousePassthrough(SDL_Window *window, bool passthrough);

/**
* Set the window as a child of a parent window.
*
Expand Down
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,7 @@ SDL3_0.0.0 {
SDL_RotateSurface;
SDL_LoadSurface_IO;
SDL_LoadSurface;
SDL_SetWindowMousePassthrough;
# extra symbols go here (don't modify this line)
local: *;
};
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1296,3 +1296,4 @@
#define SDL_RotateSurface SDL_RotateSurface_REAL
#define SDL_LoadSurface_IO SDL_LoadSurface_IO_REAL
#define SDL_LoadSurface SDL_LoadSurface_REAL
#define SDL_SetWindowMousePassthrough SDL_SetWindowMousePassthrough_REAL
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1304,3 +1304,4 @@ SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateAnimatedCursor,(SDL_CursorFrameInfo *a,int
SDL_DYNAPI_PROC(SDL_Surface*,SDL_RotateSurface,(SDL_Surface *a,float b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface_IO,(SDL_IOStream *a,bool b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface,(const char *a),(a),return)
SDL_DYNAPI_PROC(void,SDL_SetWindowMousePassthrough,(SDL_Window *a,bool b),(a,b),)
1 change: 1 addition & 0 deletions src/video/SDL_sysvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ struct SDL_VideoDevice
float (*GetWindowContentScale)(SDL_VideoDevice *_this, SDL_Window *window);
void (*GetWindowSizeInPixels)(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h);
bool (*SetWindowOpacity)(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
void (*SetWindowMousePassthrough)(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough);
bool (*SetWindowParent)(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent);
bool (*SetWindowModal)(SDL_VideoDevice *_this, SDL_Window *window, bool modal);
void (*ShowWindow)(SDL_VideoDevice *_this, SDL_Window *window);
Expand Down
10 changes: 10 additions & 0 deletions src/video/SDL_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -3793,6 +3793,16 @@ float SDL_GetWindowOpacity(SDL_Window *window)
return window->opacity;
}

void SDL_SetWindowMousePassthrough(SDL_Window *window, bool passthrough)
{
if (!_this->SetWindowMousePassthrough) {
SDL_Unsupported();
return;
}

_this->SetWindowMousePassthrough(_this, window, passthrough);
}

bool SDL_SetWindowParent(SDL_Window *window, SDL_Window *parent)
{
CHECK_WINDOW_MAGIC(window, false);
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoavideo.m
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ static void Cocoa_DeleteDevice(SDL_VideoDevice *device)
device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
device->SetWindowAspectRatio = Cocoa_SetWindowAspectRatio;
device->SetWindowOpacity = Cocoa_SetWindowOpacity;
device->SetWindowMousePassthrough = Cocoa_SetWindowMousePassthrough;
device->GetWindowSizeInPixels = Cocoa_GetWindowSizeInPixels;
device->ShowWindow = Cocoa_ShowWindow;
device->HideWindow = Cocoa_HideWindow;
Expand Down
1 change: 1 addition & 0 deletions src/video/cocoa/SDL_cocoawindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ extern void Cocoa_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *windo
extern void Cocoa_SetWindowAspectRatio(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h);
extern bool Cocoa_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
extern void Cocoa_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough);
extern void Cocoa_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_HideWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window);
Expand Down
7 changes: 7 additions & 0 deletions src/video/cocoa/SDL_cocoawindow.m
Original file line number Diff line number Diff line change
Expand Up @@ -3416,6 +3416,13 @@ bool Cocoa_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float op
}
}

void Cocoa_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough) {
@autoreleasepool {
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
[data.nswindow setIgnoresMouseEvents:passthrough];
}
}

bool Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
bool result = false;
Expand Down
1 change: 1 addition & 0 deletions src/video/wayland/SDL_waylandvideo.c
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
device->SetWindowParent = Wayland_SetWindowParent;
device->SetWindowModal = Wayland_SetWindowModal;
device->SetWindowOpacity = Wayland_SetWindowOpacity;
device->SetWindowMousePassthrough = Wayland_SetWindowMousePassthrough;
device->SetWindowTitle = Wayland_SetWindowTitle;
device->SetWindowIcon = Wayland_SetWindowIcon;
device->GetWindowSizeInPixels = Wayland_GetWindowSizeInPixels;
Expand Down
14 changes: 14 additions & 0 deletions src/video/wayland/SDL_waylandwindow.c
Original file line number Diff line number Diff line change
Expand Up @@ -2961,6 +2961,20 @@ bool Wayland_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float
return SDL_SetError("wayland: set window opacity failed; compositor lacks support for the required wp_alpha_modifier_v1 protocol");
}

void Wayland_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough)
{
SDL_VideoData *viddata = _this->internal;
SDL_WindowData *data = window->internal;

if (passthrough) {
struct wl_region *region = wl_compositor_create_region(viddata->compositor);
wl_surface_set_input_region(data->surface, region);
wl_region_destroy(region);
} else {
wl_surface_set_input_region(data->surface, NULL);
}
}

void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *wind = window->internal;
Expand Down
1 change: 1 addition & 0 deletions src/video/wayland/SDL_waylandwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ extern SDL_DisplayID Wayland_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Win
extern bool Wayland_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent_window);
extern bool Wayland_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, bool modal);
extern bool Wayland_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
extern void Wayland_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough);
extern void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
extern void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y);
extern void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
Expand Down
1 change: 1 addition & 0 deletions src/video/windows/SDL_windowsvideo.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
device->GetWindowBordersSize = WIN_GetWindowBordersSize;
device->GetWindowSizeInPixels = WIN_GetWindowSizeInPixels;
device->SetWindowOpacity = WIN_SetWindowOpacity;
device->SetWindowMousePassthrough = WIN_SetWindowMousePassthrough;
device->ShowWindow = WIN_ShowWindow;
device->HideWindow = WIN_HideWindow;
device->RaiseWindow = WIN_RaiseWindow;
Expand Down
29 changes: 29 additions & 0 deletions src/video/windows/SDL_windowswindow.c
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,35 @@ bool WIN_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opac
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
}

void WIN_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough)
{
#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
#else
SDL_WindowData *data = window->internal;
HWND hwnd = data->hwnd;
LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);

if (passthrough) {
COLORREF key = 0;
BYTE alpha = 0;
DWORD flags = 0;
if (style & WS_EX_LAYERED) {
GetLayeredWindowAttributes(hwnd, &key, &alpha, &flags);
}
style |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
SetWindowLong(hwnd, GWL_EXSTYLE, style);
SetLayeredWindowAttributes(hwnd, key, alpha, flags);
} else {
style &= ~WS_EX_TRANSPARENT;

if ((style & (WS_EX_LAYERED | LWA_ALPHA)) == WS_EX_LAYERED) {
style &= ~WS_EX_LAYERED;
}
SetWindowLong(hwnd, GWL_EXSTYLE, style);
}
#endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
}

#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)

static const char *SDLGetClipboardFormatName(UINT cf, char *text, int len)
Expand Down
1 change: 1 addition & 0 deletions src/video/windows/SDL_windowswindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ extern void WIN_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window);
extern bool WIN_GetWindowBordersSize(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right);
extern void WIN_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *width, int *height);
extern bool WIN_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
extern void WIN_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough);
extern void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void WIN_HideWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void WIN_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window);
Expand Down
1 change: 1 addition & 0 deletions src/video/x11/SDL_x11video.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static SDL_VideoDevice *X11_CreateDevice(void)
device->SetWindowAspectRatio = X11_SetWindowAspectRatio;
device->GetWindowBordersSize = X11_GetWindowBordersSize;
device->SetWindowOpacity = X11_SetWindowOpacity;
device->SetWindowMousePassthrough = X11_SetWindowMousePassthrough;
device->SetWindowParent = X11_SetWindowParent;
device->SetWindowModal = X11_SetWindowModal;
device->ShowWindow = X11_ShowWindow;
Expand Down
14 changes: 14 additions & 0 deletions src/video/x11/SDL_x11window.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,20 @@ bool X11_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opac
return true;
}

void X11_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough)
{
SDL_WindowData *data = window->internal;
Display *display = data->videodata->display;

if (passthrough) {
Region region = X11_XCreateRegion();
X11_XShapeCombineRegion(display, data->xwindow, ShapeInput, 0, 0, region, ShapeSet);
X11_XDestroyRegion(region);
} else {
X11_XShapeCombineMask(display, data->xwindow, ShapeInput, 0, 0, None, ShapeSet);
}
}

bool X11_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent)
{
SDL_WindowData *data = window->internal;
Expand Down
1 change: 1 addition & 0 deletions src/video/x11/SDL_x11window.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ extern void X11_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window)
extern void X11_SetWindowAspectRatio(SDL_VideoDevice *_this, SDL_Window *window);
extern bool X11_GetWindowBordersSize(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right);
extern bool X11_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
extern void X11_SetWindowMousePassthrough(SDL_VideoDevice *_this, SDL_Window *window, bool passthrough);
extern bool X11_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent);
extern bool X11_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, bool modal);
extern void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window);
Expand Down
Loading