aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-01-11 02:48:39 -0500
committerDavid Robillard <d@drobilla.net>2023-01-11 03:28:10 -0500
commitab2a8b226f341c38a6a1cd459addbf4e9af83cfc (patch)
tree9a56737bd96d2eed1a83384d3906ca7ddd289dfd /src
parenta02dd604ff43264757460ca4d87a2dde6ed7bbf0 (diff)
downloadpugl-ab2a8b226f341c38a6a1cd459addbf4e9af83cfc.tar.gz
pugl-ab2a8b226f341c38a6a1cd459addbf4e9af83cfc.tar.bz2
pugl-ab2a8b226f341c38a6a1cd459addbf4e9af83cfc.zip
X11: Fix positioning of top-level windows with decorations
Diffstat (limited to 'src')
-rw-r--r--src/x11.c73
-rw-r--r--src/x11.h3
2 files changed, 68 insertions, 8 deletions
diff --git a/src/x11.c b/src/x11.c
index 2b9b0f6..6fe5b8b 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -166,6 +166,7 @@ puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags)
impl->atoms.WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", 0);
impl->atoms.PUGL_CLIENT_MSG = XInternAtom(display, "_PUGL_CLIENT_MSG", 0);
impl->atoms.NET_CLOSE_WINDOW = XInternAtom(display, "_NET_CLOSE_WINDOW", 0);
+ impl->atoms.NET_FRAME_EXTENTS = XInternAtom(display, "_NET_FRAME_EXTENTS", 0);
impl->atoms.NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", 0);
impl->atoms.NET_WM_PID = XInternAtom(display, "_NET_WM_PID", 0);
impl->atoms.NET_WM_PING = XInternAtom(display, "_NET_WM_PING", 0);
@@ -1048,14 +1049,24 @@ getCurrentViewStyleFlags(PuglView* const view)
static PuglEvent
getCurrentConfiguration(PuglView* const view)
{
- // Get initial window position and size
+ Display* const display = view->world->impl->display;
+
+ // Get window size from attributes
XWindowAttributes attrs;
- XGetWindowAttributes(view->world->impl->display, view->impl->win, &attrs);
+ XGetWindowAttributes(display, view->impl->win, &attrs);
+
+ // Get window position relative to the root window
+ const Window root = RootWindow(display, view->impl->screen);
+ Window ignoredChild = 0;
+ int rootX = 0;
+ int rootY = 0;
+ XTranslateCoordinates(
+ display, view->impl->win, root, 0, 0, &rootX, &rootY, &ignoredChild);
// Build a configure event based on the current window configuration
PuglEvent configureEvent = {{PUGL_CONFIGURE, 0}};
- configureEvent.configure.x = (PuglCoord)attrs.x;
- configureEvent.configure.y = (PuglCoord)attrs.y;
+ configureEvent.configure.x = (PuglCoord)rootX;
+ configureEvent.configure.y = (PuglCoord)rootY;
configureEvent.configure.width = (PuglSpan)attrs.width;
configureEvent.configure.height = (PuglSpan)attrs.height;
configureEvent.configure.style = getCurrentViewStyleFlags(view);
@@ -1099,6 +1110,33 @@ translatePropertyNotify(PuglView* const view, XPropertyEvent message)
event.configure.style = getCurrentViewStyleFlags(view); // FIXME: necessary?
XFree(hints);
+ } else if (message.atom == atoms->NET_FRAME_EXTENTS) {
+ Atom actualType = 0;
+ int actualFormat = 0;
+ unsigned long actualNumItems = 0U;
+ unsigned long bytesAfter = 0;
+ long* extents = NULL;
+ XGetWindowProperty(view->world->impl->display,
+ impl->win,
+ message.atom,
+ 0,
+ LONG_MAX,
+ False,
+ XA_CARDINAL,
+ &actualType,
+ &actualFormat,
+ &actualNumItems,
+ &bytesAfter,
+ (uint8_t**)&extents);
+
+ if (actualNumItems == 4) {
+ view->impl->frameExtentLeft = extents[0];
+ view->impl->frameExtentTop = extents[2];
+ }
+
+ if (extents) {
+ XFree(extents);
+ }
}
return event;
@@ -1130,10 +1168,25 @@ translateEvent(PuglView* const view, XEvent xevent)
break;
case ConfigureNotify:
event = makeConfigureEvent(view);
- event.configure.x = (PuglCoord)xevent.xconfigure.x;
- event.configure.y = (PuglCoord)xevent.xconfigure.y;
event.configure.width = (PuglSpan)xevent.xconfigure.width;
event.configure.height = (PuglSpan)xevent.xconfigure.height;
+ if (view->parent) {
+ // Use window position relative to parent
+ event.configure.x = (PuglCoord)xevent.xconfigure.x;
+ event.configure.y = (PuglCoord)xevent.xconfigure.y;
+ } else {
+ // Get window position relative to the root
+ Display* const display = view->world->impl->display;
+ const Window win = view->impl->win;
+ const Window root = RootWindow(display, view->impl->screen);
+ int x = 0;
+ int y = 0;
+ Window ignored = 0;
+ if (XTranslateCoordinates(display, win, root, 0, 0, &x, &y, &ignored)) {
+ event.configure.x = (PuglCoord)x;
+ event.configure.y = (PuglCoord)y;
+ }
+ }
break;
case Expose:
event.type = PUGL_EXPOSE;
@@ -1900,8 +1953,12 @@ puglSetPosition(PuglView* const view, const int x, const int y)
return PUGL_SUCCESS;
}
- return XMoveWindow(display, view->impl->win, x, y) ? PUGL_SUCCESS
- : PUGL_UNKNOWN_ERROR;
+ return XMoveWindow(display,
+ view->impl->win,
+ (int)(x - view->impl->frameExtentLeft),
+ (int)(y - view->impl->frameExtentTop))
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
}
PuglStatus
diff --git a/src/x11.h b/src/x11.h
index b2c0e54..bc93630 100644
--- a/src/x11.h
+++ b/src/x11.h
@@ -26,6 +26,7 @@ typedef struct {
Atom WM_DELETE_WINDOW;
Atom PUGL_CLIENT_MSG;
Atom NET_CLOSE_WINDOW;
+ Atom NET_FRAME_EXTENTS;
Atom NET_WM_NAME;
Atom NET_WM_PID;
Atom NET_WM_PING;
@@ -85,6 +86,8 @@ struct PuglInternalsImpl {
PuglEvent pendingConfigure;
PuglEvent pendingExpose;
PuglX11Clipboard clipboard;
+ long frameExtentLeft;
+ long frameExtentTop;
int screen;
const char* cursorName;
bool mapped;