aboutsummaryrefslogtreecommitdiffstats
path: root/src/x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/x11.c')
-rw-r--r--src/x11.c260
1 files changed, 108 insertions, 152 deletions
diff --git a/src/x11.c b/src/x11.c
index 6e9d6c0..3d2e080 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -11,7 +11,7 @@
#include "platform.h"
#include "types.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <X11/X.h>
#include <X11/Xatom.h>
@@ -70,7 +70,8 @@
#ifdef __cplusplus
# define PUGL_INIT_STRUCT \
- {}
+ { \
+ }
#else
# define PUGL_INIT_STRUCT {0}
#endif
@@ -404,14 +405,18 @@ updateSizeHints(const PuglView* const view)
XSizeHints sizeHints = PUGL_INIT_STRUCT;
if (!view->hints[PUGL_RESIZABLE]) {
- const PuglRect frame = puglGetFrame(view);
+ PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
+ if (!puglIsValidSize(size.width, size.height)) {
+ size = puglGetSizeHint(view, PUGL_DEFAULT_SIZE);
+ }
+
sizeHints.flags = PBaseSize | PMinSize | PMaxSize;
- sizeHints.base_width = (int)frame.width;
- sizeHints.base_height = (int)frame.height;
- sizeHints.min_width = (int)frame.width;
- sizeHints.min_height = (int)frame.height;
- sizeHints.max_width = (int)frame.width;
- sizeHints.max_height = (int)frame.height;
+ sizeHints.base_width = (int)size.width;
+ sizeHints.base_height = (int)size.height;
+ sizeHints.min_width = (int)size.width;
+ sizeHints.min_height = (int)size.height;
+ sizeHints.max_width = (int)size.width;
+ sizeHints.max_height = (int)size.height;
} else {
// Avoid setting PBaseSize for top level views to avoid window manager bugs
const PuglArea defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
@@ -510,48 +515,21 @@ clearX11Clipboard(PuglX11Clipboard* const board)
board->data.len = 0;
}
-static PuglRect
-getInitialFrame(PuglView* const view)
+PuglPoint
+puglGetAncestorCenter(const PuglView* const view)
{
- if (view->lastConfigure.type == PUGL_CONFIGURE) {
- // Use the last configured frame
- const PuglRect frame = {view->lastConfigure.x,
- view->lastConfigure.y,
- view->lastConfigure.width,
- view->lastConfigure.height};
- return frame;
- }
-
- const PuglSpan defaultWidth = view->sizeHints[PUGL_DEFAULT_SIZE].width;
- const PuglSpan defaultHeight = view->sizeHints[PUGL_DEFAULT_SIZE].height;
- const int x = view->defaultX;
- const int y = view->defaultY;
- if (puglIsValidPosition(x, y)) {
- // Use the default position set with puglSetPosition while unrealized
- const PuglRect frame = {
- (PuglCoord)x, (PuglCoord)y, defaultWidth, defaultHeight};
- return frame;
- }
-
- // Get the best "parentish" window to position the window in
- Display* const display = view->world->impl->display;
- const Window parent =
- (view->parent ? (Window)view->parent
- : view->transientParent ? (Window)view->transientParent
- : RootWindow(display, view->impl->screen));
+ Display* const display = view->world->impl->display;
+ const int screen = view->impl->screen;
+ XWindowAttributes ancestorAttrs = PUGL_INIT_STRUCT;
+ XGetWindowAttributes(display,
+ view->transientParent ? (Window)view->transientParent
+ : RootWindow(display, screen),
+ &ancestorAttrs);
- // Get the position/size of the parent as bounds for the new window
- XWindowAttributes parentAttrs = PUGL_INIT_STRUCT;
- XGetWindowAttributes(display, parent, &parentAttrs);
-
- // Center the frame within the parent bounds
- const int centerX = parentAttrs.x + parentAttrs.width / 2;
- const int centerY = parentAttrs.y + parentAttrs.height / 2;
- const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2)),
- (PuglCoord)(centerY - (defaultHeight / 2)),
- defaultWidth,
- defaultHeight};
- return frame;
+ const PuglPoint center = {
+ (PuglCoord)(ancestorAttrs.x + (ancestorAttrs.width / 2)),
+ (PuglCoord)(ancestorAttrs.y + (ancestorAttrs.height / 2))};
+ return center;
}
PuglStatus
@@ -606,16 +584,17 @@ puglRealize(PuglView* const view)
attr.event_mask |= StructureNotifyMask;
attr.event_mask |= VisibilityChangeMask;
- // Calculate the initial window rectangle
- const PuglRect initialFrame = getInitialFrame(view);
+ // Calculate the initial window frame
+ const PuglArea initialSize = puglGetInitialSize(view);
+ const PuglPoint initialPos = puglGetInitialPosition(view, initialSize);
// Create the window
impl->win = XCreateWindow(display,
parent,
- initialFrame.x,
- initialFrame.y,
- initialFrame.width,
- initialFrame.height,
+ initialPos.x,
+ initialPos.y,
+ initialSize.width,
+ initialSize.height,
0,
impl->vi->depth,
InputOutput,
@@ -770,7 +749,7 @@ puglShow(PuglView* const view, const PuglShowCommand command)
}
if (view->stage == PUGL_VIEW_STAGE_CONFIGURED) {
- st = puglPostRedisplay(view);
+ st = puglObscureView(view);
}
}
@@ -1026,7 +1005,7 @@ translateClientMessage(PuglView* const view, XClientMessageEvent message)
{
Display* const display = view->world->impl->display;
const PuglX11Atoms* const atoms = &view->world->impl->atoms;
- PuglEvent event = {{PUGL_NOTHING, 0}};
+ PuglEvent event = {{PUGL_NOTHING, 0U}};
if (message.message_type == atoms->WM_PROTOCOLS) {
const Atom protocol = (Atom)message.data.l[0];
@@ -1099,17 +1078,19 @@ getCurrentConfiguration(PuglView* const view)
XWindowAttributes attrs;
XGetWindowAttributes(display, view->impl->win, &attrs);
- // Get window position relative to the root window
+ // Get window position (relative to the root window if not a child)
Window ignoredChild = 0;
- int rootX = 0;
- int rootY = 0;
- XTranslateCoordinates(
- display, view->impl->win, attrs.root, 0, 0, &rootX, &rootY, &ignoredChild);
+ int x = attrs.x;
+ int y = attrs.y;
+ if (!view->parent) {
+ XTranslateCoordinates(
+ display, view->impl->win, attrs.root, 0, 0, &x, &y, &ignoredChild);
+ }
// Build a configure event based on the current window configuration
- PuglEvent configureEvent = {{PUGL_CONFIGURE, 0}};
- configureEvent.configure.x = (PuglCoord)rootX;
- configureEvent.configure.y = (PuglCoord)rootY;
+ PuglEvent configureEvent = {{PUGL_CONFIGURE, 0U}};
+ configureEvent.configure.x = (PuglCoord)x;
+ configureEvent.configure.y = (PuglCoord)y;
configureEvent.configure.width = (PuglSpan)attrs.width;
configureEvent.configure.height = (PuglSpan)attrs.height;
configureEvent.configure.style = getCurrentViewStyleFlags(view);
@@ -1138,7 +1119,7 @@ translatePropertyNotify(PuglView* const view, XPropertyEvent message)
{
const PuglInternals* const impl = view->impl;
const PuglX11Atoms* const atoms = &view->world->impl->atoms;
- PuglEvent event = {{PUGL_NOTHING, 0}};
+ PuglEvent event = {{PUGL_NOTHING, 0U}};
if (message.atom == atoms->NET_WM_STATE) {
// Get all the current states set in the window hints
@@ -1188,7 +1169,7 @@ translatePropertyNotify(PuglView* const view, XPropertyEvent message)
static PuglEvent
translateEvent(PuglView* const view, XEvent xevent)
{
- PuglEvent event = {{PUGL_NOTHING, 0}};
+ PuglEvent event = {{PUGL_NOTHING, 0U}};
event.any.flags = xevent.xany.send_event ? PUGL_IS_SEND_EVENT : 0;
switch (xevent.type) {
@@ -1209,6 +1190,9 @@ translateEvent(PuglView* const view, XEvent xevent)
view->impl->mapped = false;
event = makeConfigureEvent(view);
break;
+ case DestroyNotify:
+ view->impl->win = None;
+ break;
case ConfigureNotify:
event = makeConfigureEvent(view);
event.configure.width = (PuglSpan)xevent.xconfigure.width;
@@ -1532,21 +1516,11 @@ puglSendEvent(PuglView* const view, const PuglEvent* const event)
return PUGL_UNSUPPORTED;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglWaitForEvent(PuglView* const view)
-{
- XEvent xevent;
- XPeekEvent(view->world->impl->display, &xevent);
- return PUGL_SUCCESS;
-}
-#endif
-
static void
mergeExposeEvents(PuglExposeEvent* const dst, const PuglExposeEvent* const src)
{
if (!dst->type) {
- if (src->width > 0.0 && src->height > 0.0) {
+ if (src->width && src->height) {
*dst = *src;
}
} else {
@@ -1610,7 +1584,7 @@ handleSelectionNotify(const PuglWorld* const world,
Display* const display = view->world->impl->display;
const Atom selection = event->selection;
PuglX11Clipboard* const board = getX11SelectionClipboard(view, selection);
- PuglEvent puglEvent = {{PUGL_NOTHING, 0}};
+ PuglEvent puglEvent = {{PUGL_NOTHING, 0U}};
if (event->target == atoms->TARGETS) {
// Notification of available datatypes
@@ -1620,7 +1594,7 @@ handleSelectionNotify(const PuglWorld* const world,
view, event->requestor, event->property, &numFormats, &formats) &&
!setClipboardFormats(view, board, numFormats, formats)) {
const PuglDataOfferEvent offer = {
- PUGL_DATA_OFFER, 0, (double)event->time / 1e3};
+ PUGL_DATA_OFFER, 0U, (double)event->time / 1e3};
puglEvent.offer = offer;
board->acceptedFormatIndex = UINT32_MAX;
@@ -1697,8 +1671,7 @@ handleSelectionRequest(const PuglWorld* const world,
}
/// Flush pending configure and expose events for all views
-PUGL_WARN_UNUSED_RESULT
-static PuglStatus
+PUGL_WARN_UNUSED_RESULT static PuglStatus
flushExposures(PuglWorld* const world)
{
PuglStatus st0 = PUGL_SUCCESS;
@@ -1751,7 +1724,7 @@ handleTimerEvent(PuglWorld* const world, const XEvent xevent)
for (size_t i = 0; i < world->impl->numTimers; ++i) {
if (world->impl->timers[i].alarm == notify->alarm) {
- PuglEvent event = {{PUGL_TIMER, 0}};
+ PuglEvent event = {{PUGL_TIMER, 0U}};
event.timer.id = world->impl->timers[i].id;
puglDispatchEvent(world->impl->timers[i].view, &event);
}
@@ -1849,14 +1822,6 @@ dispatchX11Events(PuglWorld* const world)
return st;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglProcessEvents(PuglView* const view)
-{
- return puglUpdate(view->world, 0.0);
-}
-#endif
-
PuglStatus
puglUpdate(PuglWorld* const world, const double timeout)
{
@@ -1867,8 +1832,9 @@ puglUpdate(PuglWorld* const world, const double timeout)
world->impl->dispatchingEvents = true;
if (timeout < 0.0) {
- st0 = pollX11Socket(world, timeout);
- st0 = st0 ? st0 : dispatchX11Events(world);
+ if (!(st0 = pollX11Socket(world, timeout))) {
+ st0 = dispatchX11Events(world);
+ }
} else if (timeout <= 0.001) {
st0 = dispatchX11Events(world);
} else {
@@ -1894,33 +1860,45 @@ double
puglGetTime(const PuglWorld* const world)
{
struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
+ return 0.0;
+ }
+
return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) -
world->startTime;
}
PuglStatus
-puglPostRedisplay(PuglView* const view)
+puglObscureView(PuglView* const view)
{
- PuglRect rect = puglGetFrame(view);
- rect.x = 0;
- rect.y = 0;
-
- return puglPostRedisplayRect(view, rect);
+ return puglObscureRegion(
+ view, 0, 0, view->lastConfigure.width, view->lastConfigure.height);
}
PuglStatus
-puglPostRedisplayRect(PuglView* const view, const PuglRect rect)
+puglObscureRegion(PuglView* const view,
+ const int x,
+ const int y,
+ const unsigned width,
+ const unsigned height)
{
- const PuglExposeEvent event = {
- PUGL_EXPOSE, 0, rect.x, rect.y, rect.width, rect.height};
+ if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ const PuglCoord cx = MAX((PuglCoord)0, (PuglCoord)x);
+ const PuglCoord cy = MAX((PuglCoord)0, (PuglCoord)y);
+ const PuglSpan cw = MIN(view->lastConfigure.width, (PuglSpan)width);
+ const PuglSpan ch = MIN(view->lastConfigure.height, (PuglSpan)height);
+
+ const PuglExposeEvent event = {PUGL_EXPOSE, 0U, cx, cy, cw, ch};
if (view->world->impl->dispatchingEvents) {
// Currently dispatching events, add/expand expose for the loop end
mergeExposeEvents(&view->impl->pendingExpose.expose, &event);
} else if (view->impl->win) {
// Not dispatching events, send an X expose so we wake up next time
- PuglEvent exposeEvent = {{PUGL_EXPOSE, 0}};
+ PuglEvent exposeEvent = {{PUGL_EXPOSE, 0U}};
exposeEvent.expose = event;
return puglSendEvent(view, &exposeEvent);
}
@@ -1974,65 +1952,41 @@ puglGetScaleFactor(const PuglView* const view)
return view->world->impl->scaleFactor;
}
-PuglStatus
-puglSetFrame(PuglView* const view, const PuglRect frame)
-{
- if (!view->impl->win) {
- // Set defaults to be used when realized
- view->defaultX = frame.x;
- view->defaultY = frame.y;
- view->sizeHints[PUGL_DEFAULT_SIZE].width = frame.width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = frame.height;
- return PUGL_SUCCESS;
- }
-
- return puglX11Status(XMoveResizeWindow(view->world->impl->display,
- view->impl->win,
- frame.x,
- frame.y,
- frame.width,
- frame.height));
-}
-
-PuglStatus
-puglSetPosition(PuglView* const view, const int x, const int y)
+static PuglStatus
+puglSetWindowPosition(PuglView* const view, const int x, const int y)
{
- Display* const display = view->world->impl->display;
-
- if (!puglIsValidPosition(x, y)) {
- return PUGL_BAD_PARAMETER;
- }
-
- if (!view->impl->win) {
- // Set defaults to be used when realized
- view->defaultX = x;
- view->defaultY = y;
- return PUGL_SUCCESS;
- }
-
- return puglX11Status(XMoveWindow(display,
+ return puglX11Status(XMoveWindow(view->world->impl->display,
view->impl->win,
(int)(x - view->impl->frameExtentLeft),
(int)(y - view->impl->frameExtentTop)));
}
-PuglStatus
-puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
+static PuglStatus
+puglSetWindowSize(PuglView* const view,
+ const unsigned width,
+ const unsigned height)
{
- Display* const display = view->world->impl->display;
+ return !view->impl->win
+ ? PUGL_SUCCESS
+ : puglX11Status(XResizeWindow(
+ view->world->impl->display, view->impl->win, width, height));
+}
- if (!puglIsValidSize(width, height)) {
+PuglStatus
+puglSetPositionHint(PuglView* const view,
+ const PuglPositionHint hint,
+ const int x,
+ const int y)
+{
+ if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) {
return PUGL_BAD_PARAMETER;
}
- if (!view->impl->win) {
- // Set defaults to be used when realized
- view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height;
- return PUGL_SUCCESS;
- }
+ view->positionHints[hint].x = (PuglCoord)x;
+ view->positionHints[hint].y = (PuglCoord)y;
- return puglX11Status(XResizeWindow(display, view->impl->win, width, height));
+ return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y)
+ : PUGL_SUCCESS;
}
PuglStatus
@@ -2043,7 +1997,9 @@ puglSetSizeHint(PuglView* const view,
{
const PuglStatus st = puglStoreSizeHint(view, hint, width, height);
- return st ? st : updateSizeHints(view);
+ return st ? st
+ : (hint == PUGL_CURRENT_SIZE) ? puglSetWindowSize(view, width, height)
+ : updateSizeHints(view);
}
PuglStatus