From dbb18a6ecbd8d07aa792273325821ccb1e4dddb3 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Mon, 25 Jan 2021 22:23:53 +1100 Subject: [PATCH] [client] x11/sdl: get the border dimensions from the backend --- client/displayservers/SDL/sdl.c | 15 ++++++- client/displayservers/X11/x11.c | 74 +++++++++++++++++++++++++++++---- client/include/app.h | 3 +- client/src/app.c | 13 ++---- client/src/main.h | 2 +- common/include/common/types.h | 10 +++++ 6 files changed, 98 insertions(+), 19 deletions(-) diff --git a/client/displayservers/SDL/sdl.c b/client/displayservers/SDL/sdl.c index cc1580bd..d697b473 100644 --- a/client/displayservers/SDL/sdl.c +++ b/client/displayservers/SDL/sdl.c @@ -23,6 +23,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "app.h" #include "kb.h" +#include "common/types.h" #include "common/debug.h" struct SDLDSState @@ -146,8 +147,20 @@ static bool sdlEventFilter(SDL_Event * event) case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_RESIZED: - app_handleResizeEvent(event->window.data1, event->window.data2); + { + struct Border border; + SDL_GetWindowBordersSize( + app_getWindow(), + &border.top, + &border.left, + &border.bottom, + &border.right + ); + + app_handleResizeEvent(event->window.data1, event->window.data2, + border); return true; + } case SDL_WINDOWEVENT_MOVED: app_updateWindowPos(event->window.data1, event->window.data2); diff --git a/client/displayservers/X11/x11.c b/client/displayservers/X11/x11.c index 74b595dd..aa217363 100644 --- a/client/displayservers/X11/x11.c +++ b/client/displayservers/X11/x11.c @@ -46,6 +46,11 @@ struct X11DSState bool keyboardGrabbed; bool entered; bool focused; + struct Rect rect; + struct Border border; + + Atom aNetReqFrameExtents; + Atom aNetFrameExtents; // clipboard members Atom aSelection; @@ -93,6 +98,25 @@ static bool x11Init(SDL_SysWMinfo * info) x11.display = info->info.x11.display; x11.window = info->info.x11.window; + x11.aNetReqFrameExtents = + XInternAtom(x11.display, "_NET_REQUEST_FRAME_EXTENTS", True); + x11.aNetFrameExtents = + XInternAtom(x11.display, "_NET_FRAME_EXTENTS", True); + + if (x11.aNetReqFrameExtents) + { + XEvent reqevent = + { + .type = ClientMessage, + .xclient.window = x11.window, + .xclient.format = 32, + .xclient.message_type = x11.aNetReqFrameExtents + }; + + XSendEvent(x11.display, DefaultRootWindow(x11.display), False, + SubstructureNotifyMask | SubstructureRedirectMask, &reqevent); + } + int major = 2; int minor = 3; if (XIQueryVersion(x11.display, &major, &minor) != Success) @@ -318,8 +342,13 @@ static bool x11EventFilter(SDL_Event * event) &y, &child); + x11.rect.x = x; + x11.rect.y = y; + x11.rect.w = xe.xconfigure.width; + x11.rect.h = xe.xconfigure.height; + app_updateWindowPos(x, y); - app_handleResizeEvent(xe.xconfigure.width, xe.xconfigure.height); + app_handleResizeEvent(x11.rect.w, x11.rect.h, x11.border); return true; } @@ -558,14 +587,45 @@ static bool x11EventFilter(SDL_Event * event) return true; case PropertyNotify: - if (xe.xproperty.display != x11.display || - xe.xproperty.window != x11.window || - xe.xproperty.atom != x11.aSelData || - xe.xproperty.state != PropertyNewValue || - x11.lowerBound == 0) + if (xe.xproperty.display != x11.display || + xe.xproperty.window != x11.window || + xe.xproperty.state != PropertyNewValue) return false; - x11CBSelectionIncr(xe.xproperty); + if (xe.xproperty.atom == x11.aNetFrameExtents) + { + Atom type; + int fmt; + unsigned long num, bytes; + unsigned char *data; + + if (XGetWindowProperty(x11.display, x11.window, + x11.aNetFrameExtents, 0, 4, False, AnyPropertyType, + &type, &fmt, &num, &bytes, &data) != Success) + return true; + + if (num >= 4) + { + long *cardinal = (long *)data; + x11.border.left = cardinal[0]; + x11.border.right = cardinal[1]; + x11.border.top = cardinal[2]; + x11.border.bottom = cardinal[3]; + app_handleResizeEvent(x11.rect.w, x11.rect.h, x11.border); + } + + XFree(data); + return true; + } + + if (xe.xproperty.atom == x11.aSelData) + { + if (x11.lowerBound == 0) + return false; + x11CBSelectionIncr(xe.xproperty); + return true; + } + return true; default: diff --git a/client/include/app.h b/client/include/app.h index 9d5ea1c9..9e9585dc 100644 --- a/client/include/app.h +++ b/client/include/app.h @@ -19,6 +19,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include +#include "common/types.h" #include "interface/displayserver.h" SDL_Window * app_getWindow(void); @@ -30,7 +31,7 @@ bool app_cursorWantsRaw(void); bool app_cursorInWindow(void); void app_updateCursorPos(double x, double y); void app_updateWindowPos(int x, int y); -void app_handleResizeEvent(int w, int h); +void app_handleResizeEvent(int w, int h, const struct Border border); void app_handleMouseGrabbed(double ex, double ey); void app_handleMouseNormal(double ex, double ey); void app_handleMouseBasic(void); diff --git a/client/src/app.c b/client/src/app.c index 1648a751..b3608421 100644 --- a/client/src/app.c +++ b/client/src/app.c @@ -458,8 +458,8 @@ void app_handleMouseNormal(double ex, double ey) const int ty = (local.y <= 0.0) ? floor(local.y) : ceil(local.y); if (core_isValidPointerPos( - g_state.windowPos.x + g_state.border.x + tx, - g_state.windowPos.y + g_state.border.y + ty)) + g_state.windowPos.x + g_state.border.left + tx, + g_state.windowPos.y + g_state.border.top + ty)) { core_setCursorInView(false); @@ -570,14 +570,9 @@ void app_updateWindowPos(int x, int y) g_state.windowPos.y = y; } -void app_handleResizeEvent(int w, int h) +void app_handleResizeEvent(int w, int h, const struct Border border) { - SDL_GetWindowBordersSize(g_state.window, - &g_state.border.y, - &g_state.border.x, - &g_state.border.h, - &g_state.border.w - ); + memcpy(&g_state.border, &border, sizeof(border)); /* don't do anything else if the window dimensions have not changed */ if (g_state.windowW == w && g_state.windowH == h) diff --git a/client/src/main.h b/client/src/main.h index d81b38b7..22db5844 100644 --- a/client/src/main.h +++ b/client/src/main.h @@ -58,7 +58,7 @@ struct AppState int windowCX, windowCY; LG_RendererRotate rotate; bool focused; - SDL_Rect border; + struct Border border; SDL_Point srcSize; LG_RendererRect dstRect; bool posInfoValid; diff --git a/common/include/common/types.h b/common/include/common/types.h index 02767638..253c9f2c 100644 --- a/common/include/common/types.h +++ b/common/include/common/types.h @@ -25,6 +25,16 @@ struct DoublePoint double x, y; }; +struct Rect +{ + int x, y, w, h; +}; + +struct Border +{ + int left, top, right, bottom; +}; + typedef enum FrameType { FRAME_TYPE_INVALID ,