aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/darwin/winmoveresize.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl/libui/darwin/winmoveresize.m')
-rw-r--r--src/libui_sdl/libui/darwin/winmoveresize.m253
1 files changed, 0 insertions, 253 deletions
diff --git a/src/libui_sdl/libui/darwin/winmoveresize.m b/src/libui_sdl/libui/darwin/winmoveresize.m
deleted file mode 100644
index 9145b7b..0000000
--- a/src/libui_sdl/libui/darwin/winmoveresize.m
+++ /dev/null
@@ -1,253 +0,0 @@
-// 1 november 2016
-#import "uipriv_darwin.h"
-
-// because we are changing the window frame each time the mouse moves, the successive -[NSEvent locationInWindow]s cannot be meaningfully used together
-// make sure they are all following some sort of standard to avoid this problem; the screen is the most obvious possibility since it requires only one conversion (the only one that a NSWindow provides)
-static NSPoint makeIndependent(NSPoint p, NSWindow *w)
-{
- NSRect r;
-
- r.origin = p;
- // mikeash in irc.freenode.net/#macdev confirms both that any size will do and that we can safely ignore the resultant size
- r.size = NSZeroSize;
- return [w convertRectToScreen:r].origin;
-}
-
-struct onMoveDragParams {
- NSWindow *w;
- // using the previous point causes weird issues like the mouse seeming to fall behind the window edge... so do this instead
- // TODO will this make things like the menubar and dock easier too?
- NSRect initialFrame;
- NSPoint initialPoint;
-};
-
-void onMoveDrag(struct onMoveDragParams *p, NSEvent *e)
-{
- NSPoint new;
- NSRect frame;
- CGFloat offx, offy;
-
- new = makeIndependent([e locationInWindow], p->w);
- frame = p->initialFrame;
-
- offx = new.x - p->initialPoint.x;
- offy = new.y - p->initialPoint.y;
- frame.origin.x += offx;
- frame.origin.y += offy;
-
- // TODO handle the menubar
- // TODO wait the system does this for us already?!
-
- [p->w setFrameOrigin:frame.origin];
-}
-
-void doManualMove(NSWindow *w, NSEvent *initialEvent)
-{
- __block struct onMoveDragParams mdp;
- struct nextEventArgs nea;
- BOOL (^handleEvent)(NSEvent *e);
- __block BOOL done;
-
- // this is only available on 10.11 and newer (LONGTERM FUTURE)
- // but use it if available; this lets us use the real OS dragging code, which means we can take advantage of OS features like Spaces
- if ([w respondsToSelector:@selector(performWindowDragWithEvent:)]) {
- [((id) w) performWindowDragWithEvent:initialEvent];
- return;
- }
-
- mdp.w = w;
- mdp.initialFrame = [mdp.w frame];
- mdp.initialPoint = makeIndependent([initialEvent locationInWindow], mdp.w);
-
- nea.mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask;
- nea.duration = [NSDate distantFuture];
- nea.mode = NSEventTrackingRunLoopMode; // nextEventMatchingMask: docs suggest using this for manual mouse tracking
- nea.dequeue = YES;
- handleEvent = ^(NSEvent *e) {
- if ([e type] == NSLeftMouseUp) {
- done = YES;
- return YES; // do not send
- }
- onMoveDrag(&mdp, e);
- return YES; // do not send
- };
- done = NO;
- while (mainStep(&nea, handleEvent))
- if (done)
- break;
-}
-
-// see http://stackoverflow.com/a/40352996/3408572
-static void minMaxAutoLayoutSizes(NSWindow *w, NSSize *min, NSSize *max)
-{
- NSLayoutConstraint *cw, *ch;
- NSView *contentView;
- NSRect prevFrame;
-
- // if adding these constraints causes the window to change size somehow, don't show it to the user and change it back afterwards
- NSDisableScreenUpdates();
- prevFrame = [w frame];
-
- // minimum: encourage the window to be as small as possible
- contentView = [w contentView];
- cw = mkConstraint(contentView, NSLayoutAttributeWidth,
- NSLayoutRelationEqual,
- nil, NSLayoutAttributeNotAnAttribute,
- 0, 0,
- @"window minimum width finding constraint");
- [cw setPriority:NSLayoutPriorityDragThatCanResizeWindow];
- [contentView addConstraint:cw];
- ch = mkConstraint(contentView, NSLayoutAttributeHeight,
- NSLayoutRelationEqual,
- nil, NSLayoutAttributeNotAnAttribute,
- 0, 0,
- @"window minimum height finding constraint");
- [ch setPriority:NSLayoutPriorityDragThatCanResizeWindow];
- [contentView addConstraint:ch];
- *min = [contentView fittingSize];
- [contentView removeConstraint:cw];
- [contentView removeConstraint:ch];
-
- // maximum: encourage the window to be as large as possible
- contentView = [w contentView];
- cw = mkConstraint(contentView, NSLayoutAttributeWidth,
- NSLayoutRelationEqual,
- nil, NSLayoutAttributeNotAnAttribute,
- 0, CGFLOAT_MAX,
- @"window maximum width finding constraint");
- [cw setPriority:NSLayoutPriorityDragThatCanResizeWindow];
- [contentView addConstraint:cw];
- ch = mkConstraint(contentView, NSLayoutAttributeHeight,
- NSLayoutRelationEqual,
- nil, NSLayoutAttributeNotAnAttribute,
- 0, CGFLOAT_MAX,
- @"window maximum height finding constraint");
- [ch setPriority:NSLayoutPriorityDragThatCanResizeWindow];
- [contentView addConstraint:ch];
- *max = [contentView fittingSize];
- [contentView removeConstraint:cw];
- [contentView removeConstraint:ch];
-
- [w setFrame:prevFrame display:YES]; // TODO really YES?
- NSEnableScreenUpdates();
-}
-
-static void handleResizeLeft(NSRect *frame, NSPoint old, NSPoint new)
-{
- frame->origin.x += new.x - old.x;
- frame->size.width -= new.x - old.x;
-}
-
-// TODO properly handle the menubar
-// TODO wait, OS X does it for us?!
-static void handleResizeTop(NSRect *frame, NSPoint old, NSPoint new)
-{
- frame->size.height += new.y - old.y;
-}
-
-static void handleResizeRight(NSRect *frame, NSPoint old, NSPoint new)
-{
- frame->size.width += new.x - old.x;
-}
-
-
-// TODO properly handle the menubar
-static void handleResizeBottom(NSRect *frame, NSPoint old, NSPoint new)
-{
- frame->origin.y += new.y - old.y;
- frame->size.height -= new.y - old.y;
-}
-
-struct onResizeDragParams {
- NSWindow *w;
- // using the previous point causes weird issues like the mouse seeming to fall behind the window edge... so do this instead
- // TODO will this make things like the menubar and dock easier too?
- NSRect initialFrame;
- NSPoint initialPoint;
- uiWindowResizeEdge edge;
- NSSize min;
- NSSize max;
-};
-
-static void onResizeDrag(struct onResizeDragParams *p, NSEvent *e)
-{
- NSPoint new;
- NSRect frame;
-
- new = makeIndependent([e locationInWindow], p->w);
- frame = p->initialFrame;
-
- // horizontal
- switch (p->edge) {
- case uiWindowResizeEdgeLeft:
- case uiWindowResizeEdgeTopLeft:
- case uiWindowResizeEdgeBottomLeft:
- handleResizeLeft(&frame, p->initialPoint, new);
- break;
- case uiWindowResizeEdgeRight:
- case uiWindowResizeEdgeTopRight:
- case uiWindowResizeEdgeBottomRight:
- handleResizeRight(&frame, p->initialPoint, new);
- break;
- }
- // vertical
- switch (p->edge) {
- case uiWindowResizeEdgeTop:
- case uiWindowResizeEdgeTopLeft:
- case uiWindowResizeEdgeTopRight:
- handleResizeTop(&frame, p->initialPoint, new);
- break;
- case uiWindowResizeEdgeBottom:
- case uiWindowResizeEdgeBottomLeft:
- case uiWindowResizeEdgeBottomRight:
- handleResizeBottom(&frame, p->initialPoint, new);
- break;
- }
-
- // constrain
- // TODO should we constrain against anything else as well? minMaxAutoLayoutSizes() already gives us nonnegative sizes, but...
- if (frame.size.width < p->min.width)
- frame.size.width = p->min.width;
- if (frame.size.height < p->min.height)
- frame.size.height = p->min.height;
- // TODO > or >= ?
- if (frame.size.width > p->max.width)
- frame.size.width = p->max.width;
- if (frame.size.height > p->max.height)
- frame.size.height = p->max.height;
-
- [p->w setFrame:frame display:YES]; // and do reflect the new frame immediately
-}
-
-// TODO do our events get fired with this? *should* they?
-void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge)
-{
- __block struct onResizeDragParams rdp;
- struct nextEventArgs nea;
- BOOL (^handleEvent)(NSEvent *e);
- __block BOOL done;
-
- rdp.w = w;
- rdp.initialFrame = [rdp.w frame];
- rdp.initialPoint = makeIndependent([initialEvent locationInWindow], rdp.w);
- rdp.edge = edge;
- // TODO what happens if these change during the loop?
- minMaxAutoLayoutSizes(rdp.w, &(rdp.min), &(rdp.max));
-
- nea.mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask;
- nea.duration = [NSDate distantFuture];
- nea.mode = NSEventTrackingRunLoopMode; // nextEventMatchingMask: docs suggest using this for manual mouse tracking
- nea.dequeue = YES;
- handleEvent = ^(NSEvent *e) {
- if ([e type] == NSLeftMouseUp) {
- done = YES;
- return YES; // do not send
- }
- onResizeDrag(&rdp, e);
- return YES; // do not send
- };
- done = NO;
- while (mainStep(&nea, handleEvent))
- if (done)
- break;
-}