libui/darwin/window.m

408 lines
9.3 KiB
Mathematica
Raw Normal View History

// 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;
uiprivSingleChildConstraints constraints;
void (*onContentSizeChanged)(uiWindow *, void *);
void *onContentSizeChangedData;
BOOL suppressSizeChanged;
2016-06-16 08:29:28 -05:00
int fullscreen;
int borderless;
};
2018-05-05 18:38:16 -05:00
@implementation uiprivNSWindow
2018-05-05 18:38:16 -05:00
- (void)uiprivDoMove:(NSEvent *)initialEvent
{
uiprivDoManualMove(self, initialEvent);
}
2018-05-05 18:38:16 -05:00
- (void)uiprivDoResize:(NSEvent *)initialEvent on:(uiWindowResizeEdge)edge
{
uiprivDoManualResize(self, initialEvent, edge);
}
@end
@interface windowDelegateClass : NSObject<NSWindowDelegate> {
uiprivMap *windows;
}
- (BOOL)windowShouldClose:(id)sender;
- (void)windowDidResize:(NSNotification *)note;
2016-06-16 08:29:28 -05:00
- (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 = uiprivNewMap();
return self;
}
- (void)dealloc
{
uiprivMapDestroy(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);
}
2016-06-16 08:29:28 -05:00
- (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
{
uiprivMapSet(self->windows, w->window, w);
[w->window setDelegate:self];
}
- (void)unregisterWindow:(uiWindow *)w
{
[w->window setDelegate:nil];
uiprivMapDelete(self->windows, w->window);
}
- (uiWindow *)lookupWindow:(NSWindow *)w
{
uiWindow *v;
v = uiWindow(uiprivMapGet(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];
uiprivSingleChildConstraintsRemove(&(w->constraints), cv);
}
2016-04-25 11:28:36 -05:00
static void uiWindowDestroy(uiControl *c)
{
2016-04-25 11:28:36 -05:00
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];
2016-04-25 11:35:01 -05:00
[w->window release];
uiFreeControl(uiControl(w));
}
2016-04-25 11:28:36 -05:00
uiDarwinControlDefaultHandle(uiWindow, window)
uiControl *uiWindowParent(uiControl *c)
{
return NULL;
}
void uiWindowSetParent(uiControl *c, uiControl *parent)
{
uiUserBugCannotSetParentOnToplevel("uiWindow");
}
2016-04-25 11:28:36 -05:00
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];
}
2016-04-25 11:28:36 -05:00
static void uiWindowHide(uiControl *c)
{
uiWindow *w = (uiWindow *) c;
[w->window orderOut:w->window];
}
2016-04-25 11:28:36 -05:00
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);
2016-04-25 11:28:36 -05:00
}
static void uiWindowSetSuperview(uiDarwinControl *c, NSView *superview)
{
// TODO
}
2016-04-25 12:38:17 -05:00
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];
uiprivSingleChildConstraintsEstablish(&(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:uiprivToNSString(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;
}
2016-06-16 08:29:28 -05:00
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;
2016-06-16 08:29:28 -05:00
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];
2016-06-16 08:29:28 -05:00
}
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);
2016-04-25 12:38:17 -05:00
uiDarwinControlSetSuperview(uiDarwinControl(w->child), [w->window contentView]);
uiDarwinControlSyncEnableState(uiDarwinControl(w->child), uiControlEnabledToUser(uiControl(w)));
}
2016-04-25 11:28:36 -05:00
windowRelayout(w);
}
int uiWindowMargined(uiWindow *w)
{
return w->margined;
}
void uiWindowSetMargined(uiWindow *w, int margined)
{
w->margined = margined;
uiprivSingleChildConstraintsSetMargined(&(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;
uiprivFinalizeMenus();
2016-04-25 11:28:36 -05:00
uiDarwinNewControl(uiWindow, w);
2018-05-05 18:38:16 -05:00
w->window = [[uiprivNSWindow alloc] initWithContentRect:NSMakeRect(0, 0, (CGFloat) width, (CGFloat) height)
styleMask:defaultStyleMask
backing:NSBackingStoreBuffered
defer:YES];
[w->window setTitle:uiprivToNSString(title)];
// do NOT release when closed
// we manually do this in uiWindowDestroy() above
[w->window setReleasedWhenClosed:NO];
2015-08-17 11:57:45 -05:00
if (windowDelegate == nil) {
windowDelegate = [[windowDelegateClass new] autorelease];
2018-05-05 18:46:57 -05:00
[uiprivDelegates addObject:windowDelegate];
2015-08-17 11:57:45 -05:00
}
[windowDelegate registerWindow:w];
uiWindowOnClosing(w, defaultOnClosing, NULL);
uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL);
return w;
}
// utility function for menus
2018-05-05 18:38:16 -05:00
uiWindow *uiprivWindowFromNSWindow(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];
}