aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pugl/detail/implementation.c22
-rw-r--r--pugl/detail/mac.h2
-rw-r--r--pugl/detail/mac.m98
-rw-r--r--pugl/detail/mac_cairo.m6
-rw-r--r--pugl/detail/mac_gl.m14
-rw-r--r--pugl/detail/types.h3
-rw-r--r--pugl/detail/win.c46
-rw-r--r--pugl/detail/win.h3
-rw-r--r--pugl/detail/win_cairo.c13
-rw-r--r--pugl/detail/x11.c46
-rw-r--r--pugl/detail/x11_cairo.c4
-rw-r--r--pugl/pugl.h31
-rw-r--r--test/pugl_cairo_test.c13
-rw-r--r--test/pugl_test.c4
14 files changed, 230 insertions, 75 deletions
diff --git a/pugl/detail/implementation.c b/pugl/detail/implementation.c
index 6ec19c2..53af30b 100644
--- a/pugl/detail/implementation.c
+++ b/pugl/detail/implementation.c
@@ -89,9 +89,9 @@ puglNewView(PuglWorld* const world)
return NULL;
}
- view->world = world;
- view->width = 640;
- view->height = 480;
+ view->world = world;
+ view->frame.width = 640;
+ view->frame.height = 480;
puglSetDefaultHints(view->hints);
@@ -138,8 +138,8 @@ puglInitWindowHint(PuglView* view, PuglWindowHint hint, int value)
void
puglInitWindowSize(PuglView* view, int width, int height)
{
- view->width = width;
- view->height = height;
+ view->frame.width = width;
+ view->frame.height = height;
}
void
@@ -218,8 +218,14 @@ puglGetVisible(PuglView* view)
void
puglGetSize(PuglView* view, int* width, int* height)
{
- *width = view->width;
- *height = view->height;
+ *width = (int)view->frame.width;
+ *height = (int)view->frame.height;
+}
+
+PuglRect
+puglGetFrame(const PuglView* view)
+{
+ return view->frame;
}
void*
@@ -293,8 +299,6 @@ puglDispatchEvent(PuglView* view, const PuglEvent* event)
case PUGL_NOTHING:
break;
case PUGL_CONFIGURE:
- view->width = (int)event->configure.width;
- view->height = (int)event->configure.height;
puglEnterContext(view, false);
view->eventFunc(view, event);
puglLeaveContext(view, false);
diff --git a/pugl/detail/mac.h b/pugl/detail/mac.h
index 1bd2bbc..0652733 100644
--- a/pugl/detail/mac.h
+++ b/pugl/detail/mac.h
@@ -33,10 +33,12 @@
NSMutableAttributedString* markedText;
NSTimer* timer;
NSTimer* urgentTimer;
+ bool reshaped;
}
- (void) dispatchConfigure:(NSRect)bounds;
- (void) dispatchExpose:(NSRect)rect;
+- (void) setReshaped;
@end
diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m
index 3fa700e..b7495f4 100644
--- a/pugl/detail/mac.m
+++ b/pugl/detail/mac.m
@@ -31,6 +31,31 @@
#include <stdlib.h>
+static NSRect
+rectToScreen(NSRect rect)
+{
+ const double screenHeight = [[NSScreen mainScreen] frame].size.height;
+
+ rect.origin.y = screenHeight - rect.origin.y - rect.size.height;
+ return rect;
+}
+
+static void
+updateViewRect(PuglView* view)
+{
+ NSWindow* const window = view->impl->window;
+ if (window) {
+ const double screenHeight = [[NSScreen mainScreen] frame].size.height;
+ const NSRect frame = [window frame];
+ const NSRect content = [window contentRectForFrameRect:frame];
+
+ view->frame.x = content.origin.x;
+ view->frame.y = screenHeight - content.origin.y - content.size.height;
+ view->frame.width = content.size.width;
+ view->frame.height = content.size.height;
+ }
+}
+
@implementation PuglWindow
- (id) initWithContentRect:(NSRect)contentRect
@@ -52,7 +77,7 @@
- (void)setPuglview:(PuglView*)view
{
puglview = view;
- [self setContentSize:NSMakeSize(view->width, view->height)];
+ [self setContentSize:NSMakeSize(view->frame.width, view->frame.height)];
}
- (BOOL) canBecomeKeyWindow
@@ -79,6 +104,22 @@
- (void) dispatchExpose:(NSRect)rect
{
+ if (reshaped) {
+ updateViewRect(puglview);
+
+ const PuglEventConfigure ev = {
+ PUGL_CONFIGURE,
+ 0,
+ puglview->frame.x,
+ puglview->frame.y,
+ puglview->frame.width,
+ puglview->frame.height,
+ };
+
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ reshaped = false;
+ }
+
const PuglEventExpose ev = {
PUGL_EXPOSE,
0,
@@ -102,18 +143,9 @@
return YES;
}
-- (void) dispatchConfigure:(NSRect)bounds
+- (void) setReshaped
{
- const PuglEventConfigure ev = {
- PUGL_CONFIGURE,
- 0,
- bounds.origin.x,
- bounds.origin.y,
- bounds.size.width,
- bounds.size.height,
- };
-
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ reshaped = true;
}
static uint32_t
@@ -608,6 +640,13 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
return YES;
}
+- (void) windowDidMove:(NSNotification*)notification
+{
+ (void)notification;
+
+ updateViewRect(window->puglview);
+}
+
- (void) windowDidBecomeKey:(NSNotification*)notification
{
(void)notification;
@@ -684,7 +723,8 @@ puglCreateWindow(PuglView* view, const char* title)
impl->wrapperView->puglview = view;
impl->wrapperView->markedText = [[NSMutableAttributedString alloc] init];
[impl->wrapperView setAutoresizesSubviews:YES];
- [impl->wrapperView initWithFrame:NSMakeRect(0, 0, view->width, view->height)];
+ [impl->wrapperView initWithFrame:
+ NSMakeRect(0, 0, view->frame.width, view->frame.height)];
[impl->wrapperView addConstraint:
puglConstraint(impl->wrapperView, NSLayoutAttributeWidth, view->min_width)];
[impl->wrapperView addConstraint:
@@ -712,7 +752,11 @@ puglCreateWindow(PuglView* view, const char* title)
initWithBytes:title
length:strlen(title)
encoding:NSUTF8StringEncoding];
- NSRect frame = NSMakeRect(0, 0, view->min_width, view->min_height);
+
+ const NSRect frame = rectToScreen(
+ NSMakeRect(view->frame.x, view->frame.y,
+ view->min_width, view->min_height));
+
unsigned style = (NSClosableWindowMask |
NSTitledWindowMask |
NSMiniaturizableWindowMask );
@@ -757,6 +801,7 @@ void
puglShowWindow(PuglView* view)
{
[view->impl->window setIsVisible:YES];
+ updateViewRect(view);
view->visible = true;
}
@@ -896,3 +941,28 @@ puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->wrapperView;
}
+
+PuglStatus
+puglSetFrame(PuglView* view, const PuglRect frame)
+{
+ PuglInternals* const impl = view->impl;
+
+ // Update view frame to exactly the requested frame in Pugl coordinates
+ view->frame = frame;
+
+ const NSRect rect = NSMakeRect(frame.x, frame.y, frame.width, frame.height);
+ if (impl->window) {
+ // Resize window to fit new content rect
+ const NSRect windowFrame = [
+ impl->window frameRectForContentRect:rectToScreen(rect)];
+
+ [impl->window setFrame:windowFrame display:NO];
+ }
+
+ // Resize views
+ const NSRect drawRect = NSMakeRect(0, 0, frame.width, frame.height);
+ [impl->wrapperView setFrame:(impl->window ? drawRect : rect)];
+ [impl->drawView setFrame:drawRect];
+
+ return PUGL_SUCCESS;
+}
diff --git a/pugl/detail/mac_cairo.m b/pugl/detail/mac_cairo.m
index ce03486..fcb4f07 100644
--- a/pugl/detail/mac_cairo.m
+++ b/pugl/detail/mac_cairo.m
@@ -50,7 +50,7 @@
PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
[super resizeWithOldSuperviewSize:oldSize];
- [wrapper dispatchConfigure:[self bounds]];
+ [wrapper setReshaped];
}
- (void) drawRect:(NSRect)rect
@@ -74,7 +74,7 @@ puglMacCairoCreate(PuglView* view)
PuglCairoView* drawView = [PuglCairoView alloc];
drawView->puglview = view;
- [drawView initWithFrame:NSMakeRect(0, 0, view->width, view->height)];
+ [drawView initWithFrame:NSMakeRect(0, 0, view->frame.width, view->frame.height)];
if (view->hints[PUGL_RESIZABLE]) {
[drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
} else {
@@ -111,7 +111,7 @@ puglMacCairoEnter(PuglView* view, bool drawing)
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
drawView->surface = cairo_quartz_surface_create_for_cg_context(
- context, view->width, view->height);
+ context, view->frame.width, view->frame.height);
drawView->cr = cairo_create(drawView->surface);
diff --git a/pugl/detail/mac_gl.m b/pugl/detail/mac_gl.m
index 1392989..58d815d 100644
--- a/pugl/detail/mac_gl.m
+++ b/pugl/detail/mac_gl.m
@@ -82,15 +82,7 @@ typedef NSUInteger NSWindowStyleMask;
PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
[super reshape];
- [wrapper dispatchConfigure:[self bounds]];
-}
-
-- (void) update
-{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
-
- [super update];
- [wrapper dispatchConfigure:[self bounds]];
+ [wrapper setReshaped];
}
- (void) drawRect:(NSRect)rect
@@ -112,9 +104,11 @@ puglMacGlCreate(PuglView* view)
{
PuglInternals* impl = view->impl;
PuglOpenGLView* drawView = [PuglOpenGLView alloc];
+ const NSRect rect = NSMakeRect(
+ 0, 0, view->frame.width, view->frame.height);
drawView->puglview = view;
- [drawView initWithFrame:NSMakeRect(0, 0, view->width, view->height)];
+ [drawView initWithFrame:rect];
if (view->hints[PUGL_RESIZABLE]) {
[drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
} else {
diff --git a/pugl/detail/types.h b/pugl/detail/types.h
index e279833..5254f01 100644
--- a/pugl/detail/types.h
+++ b/pugl/detail/types.h
@@ -56,8 +56,7 @@ struct PuglViewImpl {
PuglNativeWindow parent;
uintptr_t transient_parent;
PuglHints hints;
- int width;
- int height;
+ PuglRect frame;
int min_width;
int min_height;
int min_aspect_x;
diff --git a/pugl/detail/win.c b/pugl/detail/win.c
index 6cd34e3..65ae4ae 100644
--- a/pugl/detail/win.c
+++ b/pugl/detail/win.c
@@ -406,16 +406,20 @@ handleConfigure(PuglView* view, PuglEvent* event)
{
RECT rect;
GetClientRect(view->impl->hwnd, &rect);
- view->width = rect.right - rect.left;
- view->height = rect.bottom - rect.top;
+ view->frame.x = rect.left;
+ view->frame.y = rect.top;
+ view->frame.width = rect.right - rect.left;
+ view->frame.height = rect.bottom - rect.top;
event->configure.type = PUGL_CONFIGURE;
- event->configure.x = rect.left;
- event->configure.y = rect.top;
- event->configure.width = view->width;
- event->configure.height = view->height;
-
- view->backend->resize(view, view->width, view->height);
+ event->configure.x = view->frame.x;
+ event->configure.y = view->frame.y;
+ event->configure.width = view->frame.width;
+ event->configure.height = view->frame.height;
+
+ view->backend->resize(view,
+ rect.right - rect.left,
+ rect.bottom - rect.top);
return rect;
}
@@ -745,3 +749,29 @@ puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->hwnd;
}
+
+PuglStatus
+puglSetFrame(PuglView* view, const PuglRect frame)
+{
+ view->frame = frame;
+
+ if (view->impl->hwnd) {
+ RECT rect = { (long)frame.x,
+ (long)frame.y,
+ (long)frame.x + (long)frame.width,
+ (long)frame.y + (long)frame.height };
+
+ AdjustWindowRectEx(&rect, puglWinGetWindowFlags(view),
+ FALSE,
+ puglWinGetWindowExFlags(view));
+
+ if (!SetWindowPos(view->impl->hwnd, HWND_TOP,
+ rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ (SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER))) {
+ return PUGL_ERR_UNKNOWN;
+ }
+ }
+
+ return PUGL_SUCCESS;
+}
diff --git a/pugl/detail/win.h b/pugl/detail/win.h
index c051eb1..8d6ce12 100644
--- a/pugl/detail/win.h
+++ b/pugl/detail/win.h
@@ -95,7 +95,8 @@ puglWinCreateWindow(const PuglView* const view,
const unsigned winExFlags = puglWinGetWindowExFlags(view);
// Calculate total window size to accommodate requested view size
- RECT wr = { 0, 0, view->width, view->height };
+ RECT wr = { (long)view->frame.x, (long)view->frame.y,
+ (long)view->frame.width, (long)view->frame.height };
AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags);
// Create window and get drawing context
diff --git a/pugl/detail/win_cairo.c b/pugl/detail/win_cairo.c
index 49175c1..cbca7e8 100644
--- a/pugl/detail/win_cairo.c
+++ b/pugl/detail/win_cairo.c
@@ -42,7 +42,7 @@ puglWinCairoCreateDrawContext(PuglView* view)
surface->drawDc = CreateCompatibleDC(impl->hdc);
surface->drawBitmap = CreateCompatibleBitmap(
- impl->hdc, view->width, view->height);
+ impl->hdc, (int)view->frame.width, (int)view->frame.height);
DeleteObject(SelectObject(surface->drawDc, surface->drawBitmap));
@@ -87,7 +87,7 @@ puglWinCairoConfigure(PuglView* view)
return st;
}
- impl->pfd = puglWinGetPixelFormatDescriptor(&view->hints);
+ impl->pfd = puglWinGetPixelFormatDescriptor(view->hints);
impl->pfId = ChoosePixelFormat(impl->hdc, &impl->pfd);
if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) {
@@ -150,7 +150,8 @@ puglWinCairoLeave(PuglView* view, bool drawing)
cairo_restore(surface->cr);
cairo_surface_flush(surface->surface);
- BitBlt(impl->hdc, 0, 0, view->width, view->height,
+ BitBlt(impl->hdc,
+ 0, 0, (int)view->frame.width, (int)view->frame.height,
surface->drawDc, 0, 0, SRCCOPY);
PAINTSTRUCT ps;
@@ -162,11 +163,9 @@ puglWinCairoLeave(PuglView* view, bool drawing)
static int
puglWinCairoResize(PuglView* view,
- int width,
- int height)
+ int PUGL_UNUSED(width),
+ int PUGL_UNUSED(height))
{
- view->width = width;
- view->height = height;
int st = 0;
if ((st = puglWinCairoDestroyDrawContext(view)) ||
(st = puglWinCairoCreateDrawContext(view))) {
diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c
index b564225..e7b39f8 100644
--- a/pugl/detail/x11.c
+++ b/pugl/detail/x11.c
@@ -146,6 +146,8 @@ puglCreateWindow(PuglView* view, const char* title)
PuglWorld* const world = view->world;
PuglX11Atoms* const atoms = &view->world->impl->atoms;
Display* const display = world->impl->display;
+ const int width = (int)view->frame.width;
+ const int height = (int)view->frame.height;
impl->display = display;
impl->screen = DefaultScreen(display);
@@ -169,7 +171,8 @@ puglCreateWindow(PuglView* view, const char* title)
const Window win = impl->win = XCreateWindow(
display, xParent,
- 0, 0, view->width, view->height, 0, impl->vi->depth, InputOutput,
+ (int)view->frame.x, (int)view->frame.y, width, height,
+ 0, impl->vi->depth, InputOutput,
impl->vi->visual, CWColormap | CWEventMask, &attr);
if (view->backend->create(view)) {
@@ -179,10 +182,10 @@ puglCreateWindow(PuglView* view, const char* title)
XSizeHints sizeHints = {0};
if (!view->hints[PUGL_RESIZABLE]) {
sizeHints.flags = PMinSize|PMaxSize;
- sizeHints.min_width = view->width;
- sizeHints.min_height = view->height;
- sizeHints.max_width = view->width;
- sizeHints.max_height = view->height;
+ sizeHints.min_width = width;
+ sizeHints.min_height = height;
+ sizeHints.max_width = width;
+ sizeHints.max_height = height;
} else {
if (view->min_width || view->min_height) {
sizeHints.flags = PMinSize;
@@ -201,8 +204,9 @@ puglCreateWindow(PuglView* view, const char* title)
if (title) {
XStoreName(display, win, title);
- XChangeProperty(display, win, atoms->NET_WM_NAME, atoms->UTF8_STRING, 8,
- PropModeReplace, (const uint8_t*)title, strlen(title));
+ XChangeProperty(display, win, atoms->NET_WM_NAME,
+ atoms->UTF8_STRING, 8, PropModeReplace,
+ (const uint8_t*)title, (int)strlen(title));
}
if (!view->parent) {
@@ -628,9 +632,14 @@ puglDispatchEvents(PuglWorld* world)
puglEnterContext(view, mustExpose);
if (configure->type) {
- view->width = (int)configure->configure.width;
- view->height = (int)configure->configure.height;
- view->backend->resize(view, view->width, view->height);
+ view->frame.x = configure->configure.x;
+ view->frame.y = configure->configure.y;
+ view->frame.width = configure->configure.width;
+ view->frame.height = configure->configure.height;
+
+ view->backend->resize(view,
+ (int)view->frame.width,
+ (int)view->frame.height);
view->eventFunc(view, &view->impl->pendingConfigure);
}
@@ -667,7 +676,7 @@ puglPostRedisplay(PuglView* view)
XExposeEvent ev = {Expose, 0, True,
view->impl->display, view->impl->win,
0, 0,
- view->width, view->height,
+ view->frame.width, view->frame.height,
0};
XSendEvent(view->impl->display, view->impl->win, False, 0, (XEvent*)&ev);
@@ -678,3 +687,18 @@ puglGetNativeWindow(PuglView* view)
{
return (PuglNativeWindow)view->impl->win;
}
+
+PuglStatus
+puglSetFrame(PuglView* view, const PuglRect frame)
+{
+ view->frame = frame;
+
+ if (view->impl->win &&
+ XMoveResizeWindow(view->world->impl->display, view->impl->win,
+ (int)frame.x, (int)frame.y,
+ (int)frame.width, (int)frame.height)) {
+ return PUGL_ERR_UNKNOWN;
+ }
+
+ return PUGL_SUCCESS;
+}
diff --git a/pugl/detail/x11_cairo.c b/pugl/detail/x11_cairo.c
index d5e2ed7..550144a 100644
--- a/pugl/detail/x11_cairo.c
+++ b/pugl/detail/x11_cairo.c
@@ -55,8 +55,8 @@ static int
puglX11CairoCreate(PuglView* view)
{
PuglInternals* const impl = view->impl;
- const int width = view->width;
- const int height = view->height;
+ const int width = (int)view->frame.width;
+ const int height = (int)view->frame.height;
PuglX11CairoSurface surface = { 0 };
surface.back = cairo_xlib_surface_create(
diff --git a/pugl/pugl.h b/pugl/pugl.h
index 3639a96..1bd49bb 100644
--- a/pugl/pugl.h
+++ b/pugl/pugl.h
@@ -126,6 +126,19 @@ typedef enum {
} PuglWindowHintValue;
/**
+ A rectangle.
+
+ This is used to describe things like view position and size. Pugl generally
+ uses coordinates where the top left corner is 0,0.
+*/
+typedef struct {
+ double x;
+ double y;
+ double width;
+ double height;
+} PuglRect;
+
+/**
Keyboard modifier flags.
*/
typedef enum {
@@ -539,8 +552,10 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent);
/**
Set the window size before creating a window.
+
+ @deprecated Use puglSetFrame().
*/
-PUGL_API void
+PUGL_API PUGL_DEPRECATED_BY("puglSetFrame") void
puglInitWindowSize(PuglView* view, int width, int height);
/**
@@ -655,10 +670,22 @@ puglGetVisible(PuglView* view);
/**
Get the current size of the view.
*/
-PUGL_API void
+PUGL_API PUGL_DEPRECATED_BY("puglGetFrame") void
puglGetSize(PuglView* view, int* width, int* height);
/**
+ Get the current position and size of the view.
+*/
+PUGL_API PuglRect
+puglGetFrame(const PuglView* view);
+
+/**
+ Set the current position and size of the view.
+*/
+PUGL_API PuglStatus
+puglSetFrame(PuglView* view, PuglRect frame);
+
+/**
@name Context
Functions for accessing the drawing context.
@{
diff --git a/test/pugl_cairo_test.c b/test/pugl_cairo_test.c
index 3ac2054..20a96e7 100644
--- a/test/pugl_cairo_test.c
+++ b/test/pugl_cairo_test.c
@@ -115,8 +115,9 @@ onDisplay(PuglView* view)
cairo_t* cr = (cairo_t*)puglGetContext(view);
// Draw background
- int width, height;
- puglGetSize(view, &width, &height);
+ const PuglRect frame = puglGetFrame(view);
+ const double width = frame.width;
+ const double height = frame.height;
if (entered) {
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
} else {
@@ -126,8 +127,8 @@ onDisplay(PuglView* view)
cairo_fill(cr);
// Scale to view size
- const double scaleX = (width - (512 / (double)width)) / 512.0;
- const double scaleY = (height - (512 / (double)height)) / 512.0;
+ const double scaleX = (width - (512 / width)) / 512.0;
+ const double scaleY = (height - (512 / height)) / 512.0;
cairo_scale(cr, scaleX, scaleY);
// Draw button
@@ -206,9 +207,11 @@ main(int argc, char** argv)
world = puglNewWorld();
+ const PuglRect frame = { 0, 0, 512, 512 };
+
PuglView* view = puglNewView(world);
puglInitWindowClass(view, "PuglCairoTest");
- puglInitWindowSize(view, 512, 512);
+ puglSetFrame(view, frame);
puglInitWindowMinSize(view, 256, 256);
puglInitWindowHint(view, PUGL_RESIZABLE, resizable);
puglInitBackend(view, puglCairoBackend());
diff --git a/test/pugl_test.c b/test/pugl_test.c
index d6207fe..ea849a6 100644
--- a/test/pugl_test.c
+++ b/test/pugl_test.c
@@ -181,9 +181,11 @@ main(int argc, char** argv)
app.world = puglNewWorld();
+ const PuglRect frame = { 0, 0, 512, 512 };
+
PuglView* view = puglNewView(app.world);
puglInitWindowClass(view, "PuglTest");
- puglInitWindowSize(view, 512, 512);
+ puglSetFrame(view, frame);
puglInitWindowMinSize(view, 256, 256);
puglInitWindowAspectRatio(view, 1, 1, 16, 9);
puglInitBackend(view, puglGlBackend());