diff options
| -rw-r--r-- | redo/basicctrls_darwin.m | 12 | ||||
| -rw-r--r-- | redo/objc_darwin.h | 1 | ||||
| -rw-r--r-- | redo/textfield_darwin.go | 1 | ||||
| -rw-r--r-- | redo/warningpopover_darwin.m | 64 |
4 files changed, 65 insertions, 13 deletions
diff --git a/redo/basicctrls_darwin.m b/redo/basicctrls_darwin.m index 8110fb8..57d6b68 100644 --- a/redo/basicctrls_darwin.m +++ b/redo/basicctrls_darwin.m @@ -7,7 +7,7 @@ #define toNSButton(x) ((NSButton *) (x)) #define toNSTextField(x) ((NSTextField *) (x)) #define toNSView(x) ((NSView *) (x)) -#define toNSPopover(x) ((NSPopover *) (x)) +#define toNSWindow(x) ((NSWindow *) (x)) #define toNSBox(x) ((NSBox *) (x)) @interface goControlDelegate : NSObject <NSTextFieldDelegate> { @@ -168,18 +168,18 @@ void textFieldSetText(id t, char *text) id textfieldOpenInvalidPopover(id textfield, char *reason) { - NSPopover *popover; + id popover; - popover = (NSPopover *) newWarningPopover(reason); - [popover showRelativeToRect:NSZeroRect ofView:toNSView(textfield) preferredEdge:NSMaxYEdge]; + popover = newWarningPopover(reason); + warningPopoverShow(popover, textfield); NSBeep(); return (id) popover; } void textfieldCloseInvalidPopover(id popover) { - [toNSPopover(popover) close]; - [toNSPopover(popover) release]; + [toNSWindow(popover) orderOut:toNSWindow(popover)]; + [toNSWindow(popover) release]; } id newLabel(void) diff --git a/redo/objc_darwin.h b/redo/objc_darwin.h index 411b0cb..a961a0e 100644 --- a/redo/objc_darwin.h +++ b/redo/objc_darwin.h @@ -145,5 +145,6 @@ extern void openFile(id, void *); /* warningpopover_darwin.m */ extern id newWarningPopover(char *); +extern void warningPopoverShow(id, id); #endif diff --git a/redo/textfield_darwin.go b/redo/textfield_darwin.go index 89711d4..8539f8b 100644 --- a/redo/textfield_darwin.go +++ b/redo/textfield_darwin.go @@ -48,7 +48,6 @@ func (t *textfield) OnChanged(f func()) { func (t *textfield) Invalid(reason string) { // TODO disable animations if reason is still valid - // TODO don't steal focus if t.invalid != nil { C.textfieldCloseInvalidPopover(t.invalid) t.invalid = nil diff --git a/redo/warningpopover_darwin.m b/redo/warningpopover_darwin.m index 09be14b..40b62f0 100644 --- a/redo/warningpopover_darwin.m +++ b/redo/warningpopover_darwin.m @@ -3,6 +3,48 @@ #include "objc_darwin.h" #include <Cocoa/Cocoa.h> +// We would be able to just use plain old NSPopover here, but alas that steals focus. +// NSPopovers are intended for interactive content, and Apple seems to be diligent in enforcing this rule, as the known techniques for preventing a NSPopover from stealing focus no longer work in 10.9. +// Let's just fake it with a window. + +// TODO +// - doesn't get hidden properly when asked to order out +// - doesn't get hidden when changing first responders +// - doesn't get hidden when switching between programs/shown again +// - doesn't animate or have a transparent background; probably should + +@interface goWarningPopover : NSWindow +@end + +@implementation goWarningPopover + +- (id)init +{ + self = [super initWithContentRect:NSZeroRect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + [self setOpaque:NO]; +// [self setAlphaValue:0.1]; + [self setHasShadow:YES]; + [self setExcludedFromWindowsMenu:YES]; + [self setMovableByWindowBackground:NO]; + [self setLevel:NSPopUpMenuWindowLevel]; + return self; +} + +- (BOOL)canBecomeKeyWindow +{ + return NO; +} + +- (BOOL)canBecomeMainWindow +{ + return NO; +} + +@end + @interface goWarningView : NSView { @public NSImageView *icon; @@ -65,14 +107,24 @@ id newWarningPopover(char *text) [wv addSubview:wv->label]; [wv sizeToFitAndArrange]; - NSPopover *popover; - NSViewController *vc; + goWarningPopover *popover; - vc = [NSViewController new]; - [vc setView:wv]; - popover = [NSPopover new]; - [popover setContentViewController:vc]; + popover = [[goWarningPopover alloc] init]; // explicitly use our initializer + [[popover contentView] addSubview:wv]; [popover setContentSize:[wv frame].size]; return (id) popover; } + +void warningPopoverShow(id popover, id control) +{ + goWarningPopover *p = (goWarningPopover *) popover; + NSView *v = (NSView *) control; + NSRect vr; + NSPoint vo; + + vr = [v convertRect:[v frame] toView:nil]; + vo = [[v window] convertRectToScreen:vr].origin; + [p setFrameOrigin:NSMakePoint(vo.x, vo.y - [p frame].size.height)]; + [p orderFront:p]; +} |
