summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/basicctrls_darwin.m12
-rw-r--r--redo/objc_darwin.h1
-rw-r--r--redo/textfield_darwin.go1
-rw-r--r--redo/warningpopover_darwin.m64
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];
+}