And implemented moves on OS X.

This commit is contained in:
Pietro Gagliardi 2016-11-02 09:29:44 -04:00
parent 81b95a59b1
commit 17dc5f407e
4 changed files with 75 additions and 13 deletions

View File

@ -7,6 +7,9 @@ This README is being written.<br>
## Announcements ## Announcements
* **2 November 2016**
* Added two new functions to replace the deleted `uiWindowPosition()` and friends: `uiAreaBeginUserWindowMove()` and `uiAreaBeginUserWindowResize()`. When used in a `uiAreaHandler.Mouse()` event handler, these let you initiate a user-driven mouse move or mouse resize of the window at any point in a uiArea.
* **31 October 2016** * **31 October 2016**
* @krakjoe noticed that I accidentally used thread-unsafe code in uiQueueMain() on Unix. Fixed. * @krakjoe noticed that I accidentally used thread-unsafe code in uiQueueMain() on Unix. Fixed.

View File

@ -140,4 +140,5 @@ extern NSTextField *newLabel(NSString *str);
extern NSImage *imageImage(uiImage *); extern NSImage *imageImage(uiImage *);
// winmoveresize.m // winmoveresize.m
extern void doManualMove(NSWindow *w, NSEvent *initialEvent);
extern void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge); extern void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge);

View File

@ -22,7 +22,7 @@ struct uiWindow {
- (void)libui_doMove:(NSEvent *)initialEvent - (void)libui_doMove:(NSEvent *)initialEvent
{ {
// TODO doManualMove(self, initialEvent);
} }
- (void)libui_doResize:(NSEvent *)initialEvent on:(uiWindowResizeEdge)edge - (void)libui_doResize:(NSEvent *)initialEvent on:(uiWindowResizeEdge)edge

View File

@ -1,6 +1,76 @@
// 1 november 2016 // 1 november 2016
#import "uipriv_darwin.h" #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];
}
// LONGTERM FUTURE -[NSWindow performWindowDragWithEvent:] would be better but that's 10.11-only
void doManualMove(NSWindow *w, NSEvent *initialEvent)
{
__block struct onMoveDragParams mdp;
struct nextEventArgs nea;
BOOL (^handleEvent)(NSEvent *e);
__block BOOL done;
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 // see http://stackoverflow.com/a/40352996/3408572
static void minMaxAutoLayoutSizes(NSWindow *w, NSSize *min, NSSize *max) static void minMaxAutoLayoutSizes(NSWindow *w, NSSize *min, NSSize *max)
{ {
@ -93,18 +163,6 @@ struct onResizeDragParams {
NSSize max; NSSize max;
}; };
// 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;
}
static void onResizeDrag(struct onResizeDragParams *p, NSEvent *e) static void onResizeDrag(struct onResizeDragParams *p, NSEvent *e)
{ {
NSPoint new; NSPoint new;