diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-09-09 02:30:51 +0200 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-09-09 02:30:51 +0200 |
commit | 70e4841d311d68689724768157cc9cbfbde7a9fc (patch) | |
tree | ba9499f77d1258530a7e60aa6e1732c41d98161c /src/libui_sdl/libui/darwin/window.m | |
parent | 81747d6c34eb159481a6ca3f283d065fa3568617 (diff) |
another UI attempt, I guess.
sorry.
Diffstat (limited to 'src/libui_sdl/libui/darwin/window.m')
-rw-r--r-- | src/libui_sdl/libui/darwin/window.m | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/darwin/window.m b/src/libui_sdl/libui/darwin/window.m new file mode 100644 index 0000000..97c22e6 --- /dev/null +++ b/src/libui_sdl/libui/darwin/window.m @@ -0,0 +1,407 @@ +// 15 august 2015 +#import "uipriv_darwin.h" + +#define defaultStyleMask (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) + +struct uiWindow { + uiDarwinControl c; + NSWindow *window; + uiControl *child; + int margined; + int (*onClosing)(uiWindow *, void *); + void *onClosingData; + struct singleChildConstraints constraints; + void (*onContentSizeChanged)(uiWindow *, void *); + void *onContentSizeChangedData; + BOOL suppressSizeChanged; + int fullscreen; + int borderless; +}; + +@implementation libuiNSWindow + +- (void)libui_doMove:(NSEvent *)initialEvent +{ + doManualMove(self, initialEvent); +} + +- (void)libui_doResize:(NSEvent *)initialEvent on:(uiWindowResizeEdge)edge +{ + doManualResize(self, initialEvent, edge); +} + +@end + +@interface windowDelegateClass : NSObject<NSWindowDelegate> { + struct mapTable *windows; +} +- (BOOL)windowShouldClose:(id)sender; +- (void)windowDidResize:(NSNotification *)note; +- (void)windowDidEnterFullScreen:(NSNotification *)note; +- (void)windowDidExitFullScreen:(NSNotification *)note; +- (void)registerWindow:(uiWindow *)w; +- (void)unregisterWindow:(uiWindow *)w; +- (uiWindow *)lookupWindow:(NSWindow *)w; +@end + +@implementation windowDelegateClass + +- (id)init +{ + self = [super init]; + if (self) + self->windows = newMap(); + return self; +} + +- (void)dealloc +{ + mapDestroy(self->windows); + [super dealloc]; +} + +- (BOOL)windowShouldClose:(id)sender +{ + uiWindow *w; + + w = [self lookupWindow:((NSWindow *) sender)]; + // w should not be NULL; we are only the delegate of registered windows + if ((*(w->onClosing))(w, w->onClosingData)) + uiControlDestroy(uiControl(w)); + return NO; +} + +- (void)windowDidResize:(NSNotification *)note +{ + uiWindow *w; + + w = [self lookupWindow:((NSWindow *) [note object])]; + if (!w->suppressSizeChanged) + (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData); +} + +- (void)windowDidEnterFullScreen:(NSNotification *)note +{ + uiWindow *w; + + w = [self lookupWindow:((NSWindow *) [note object])]; + if (!w->suppressSizeChanged) + w->fullscreen = 1; +} + +- (void)windowDidExitFullScreen:(NSNotification *)note +{ + uiWindow *w; + + w = [self lookupWindow:((NSWindow *) [note object])]; + if (!w->suppressSizeChanged) + w->fullscreen = 0; +} + +- (void)registerWindow:(uiWindow *)w +{ + mapSet(self->windows, w->window, w); + [w->window setDelegate:self]; +} + +- (void)unregisterWindow:(uiWindow *)w +{ + [w->window setDelegate:nil]; + mapDelete(self->windows, w->window); +} + +- (uiWindow *)lookupWindow:(NSWindow *)w +{ + uiWindow *v; + + v = uiWindow(mapGet(self->windows, w)); + // this CAN (and IS ALLOWED TO) return NULL, just in case we're called with some OS X-provided window as the key window + return v; +} + +@end + +static windowDelegateClass *windowDelegate = nil; + +static void removeConstraints(uiWindow *w) +{ + NSView *cv; + + cv = [w->window contentView]; + singleChildConstraintsRemove(&(w->constraints), cv); +} + +static void uiWindowDestroy(uiControl *c) +{ + uiWindow *w = uiWindow(c); + + // hide the window + [w->window orderOut:w->window]; + removeConstraints(w); + if (w->child != NULL) { + uiControlSetParent(w->child, NULL); + uiDarwinControlSetSuperview(uiDarwinControl(w->child), nil); + uiControlDestroy(w->child); + } + [windowDelegate unregisterWindow:w]; + [w->window release]; + uiFreeControl(uiControl(w)); +} + +uiDarwinControlDefaultHandle(uiWindow, window) + +uiControl *uiWindowParent(uiControl *c) +{ + return NULL; +} + +void uiWindowSetParent(uiControl *c, uiControl *parent) +{ + uiUserBugCannotSetParentOnToplevel("uiWindow"); +} + +static int uiWindowToplevel(uiControl *c) +{ + return 1; +} + +static int uiWindowVisible(uiControl *c) +{ + uiWindow *w = uiWindow(c); + + return [w->window isVisible]; +} + +static void uiWindowShow(uiControl *c) +{ + uiWindow *w = (uiWindow *) c; + + [w->window makeKeyAndOrderFront:w->window]; +} + +static void uiWindowHide(uiControl *c) +{ + uiWindow *w = (uiWindow *) c; + + [w->window orderOut:w->window]; +} + +uiDarwinControlDefaultEnabled(uiWindow, window) +uiDarwinControlDefaultEnable(uiWindow, window) +uiDarwinControlDefaultDisable(uiWindow, window) + +static void uiWindowSyncEnableState(uiDarwinControl *c, int enabled) +{ + uiWindow *w = uiWindow(c); + + if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(w), enabled)) + return; + if (w->child != NULL) + uiDarwinControlSyncEnableState(uiDarwinControl(w->child), enabled); +} + +static void uiWindowSetSuperview(uiDarwinControl *c, NSView *superview) +{ + // TODO +} + +static void windowRelayout(uiWindow *w) +{ + NSView *childView; + NSView *contentView; + + removeConstraints(w); + if (w->child == NULL) + return; + childView = (NSView *) uiControlHandle(w->child); + contentView = [w->window contentView]; + singleChildConstraintsEstablish(&(w->constraints), + contentView, childView, + uiDarwinControlHugsTrailingEdge(uiDarwinControl(w->child)), + uiDarwinControlHugsBottom(uiDarwinControl(w->child)), + w->margined, + @"uiWindow"); +} + +uiDarwinControlDefaultHugsTrailingEdge(uiWindow, window) +uiDarwinControlDefaultHugsBottom(uiWindow, window) + +static void uiWindowChildEdgeHuggingChanged(uiDarwinControl *c) +{ + uiWindow *w = uiWindow(c); + + windowRelayout(w); +} + +// TODO +uiDarwinControlDefaultHuggingPriority(uiWindow, window) +uiDarwinControlDefaultSetHuggingPriority(uiWindow, window) +// end TODO + +static void uiWindowChildVisibilityChanged(uiDarwinControl *c) +{ + uiWindow *w = uiWindow(c); + + windowRelayout(w); +} + +char *uiWindowTitle(uiWindow *w) +{ + return uiDarwinNSStringToText([w->window title]); +} + +void uiWindowSetTitle(uiWindow *w, const char *title) +{ + [w->window setTitle:toNSString(title)]; +} + +void uiWindowContentSize(uiWindow *w, int *width, int *height) +{ + NSRect r; + + r = [w->window contentRectForFrameRect:[w->window frame]]; + *width = r.size.width; + *height = r.size.height; +} + +void uiWindowSetContentSize(uiWindow *w, int width, int height) +{ + w->suppressSizeChanged = YES; + [w->window setContentSize:NSMakeSize(width, height)]; + w->suppressSizeChanged = NO; +} + +int uiWindowFullscreen(uiWindow *w) +{ + return w->fullscreen; +} + +void uiWindowSetFullscreen(uiWindow *w, int fullscreen) +{ + if (w->fullscreen && fullscreen) + return; + if (!w->fullscreen && !fullscreen) + return; + w->fullscreen = fullscreen; + if (w->fullscreen && w->borderless) // borderless doesn't play nice with fullscreen; don't toggle while borderless + return; + w->suppressSizeChanged = YES; + [w->window toggleFullScreen:w->window]; + w->suppressSizeChanged = NO; + if (!w->fullscreen && w->borderless) // borderless doesn't play nice with fullscreen; restore borderless after removing + [w->window setStyleMask:NSBorderlessWindowMask]; +} + +void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) +{ + w->onContentSizeChanged = f; + w->onContentSizeChangedData = data; +} + +void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) +{ + w->onClosing = f; + w->onClosingData = data; +} + +int uiWindowBorderless(uiWindow *w) +{ + return w->borderless; +} + +void uiWindowSetBorderless(uiWindow *w, int borderless) +{ + w->borderless = borderless; + if (w->borderless) { + // borderless doesn't play nice with fullscreen; wait for later + if (!w->fullscreen) + [w->window setStyleMask:NSBorderlessWindowMask]; + } else { + [w->window setStyleMask:defaultStyleMask]; + // borderless doesn't play nice with fullscreen; restore state + if (w->fullscreen) { + w->suppressSizeChanged = YES; + [w->window toggleFullScreen:w->window]; + w->suppressSizeChanged = NO; + } + } +} + +void uiWindowSetChild(uiWindow *w, uiControl *child) +{ + NSView *childView; + + if (w->child != NULL) { + childView = (NSView *) uiControlHandle(w->child); + [childView removeFromSuperview]; + uiControlSetParent(w->child, NULL); + } + w->child = child; + if (w->child != NULL) { + uiControlSetParent(w->child, uiControl(w)); + childView = (NSView *) uiControlHandle(w->child); + uiDarwinControlSetSuperview(uiDarwinControl(w->child), [w->window contentView]); + uiDarwinControlSyncEnableState(uiDarwinControl(w->child), uiControlEnabledToUser(uiControl(w))); + } + windowRelayout(w); +} + +int uiWindowMargined(uiWindow *w) +{ + return w->margined; +} + +void uiWindowSetMargined(uiWindow *w, int margined) +{ + w->margined = margined; + singleChildConstraintsSetMargined(&(w->constraints), w->margined); +} + +static int defaultOnClosing(uiWindow *w, void *data) +{ + return 0; +} + +static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) +{ + // do nothing +} + +uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) +{ + uiWindow *w; + + finalizeMenus(); + + uiDarwinNewControl(uiWindow, w); + + w->window = [[libuiNSWindow alloc] initWithContentRect:NSMakeRect(0, 0, (CGFloat) width, (CGFloat) height) + styleMask:defaultStyleMask + backing:NSBackingStoreBuffered + defer:YES]; + [w->window setTitle:toNSString(title)]; + + // do NOT release when closed + // we manually do this in uiWindowDestroy() above + [w->window setReleasedWhenClosed:NO]; + + if (windowDelegate == nil) { + windowDelegate = [[windowDelegateClass new] autorelease]; + [delegates addObject:windowDelegate]; + } + [windowDelegate registerWindow:w]; + uiWindowOnClosing(w, defaultOnClosing, NULL); + uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); + + return w; +} + +// utility function for menus +uiWindow *windowFromNSWindow(NSWindow *w) +{ + if (w == nil) + return NULL; + if (windowDelegate == nil) // no windows were created yet; we're called with some OS X-provided window + return NULL; + return [windowDelegate lookupWindow:w]; +} |