Added (untested; VM issues) code to handle Mac OS X Quit Dock menu items and other related stuff that may happen in the future. Will drop the TODO after I can test it.
This commit is contained in:
parent
af770340c9
commit
f7817f6987
|
@ -20,6 +20,7 @@ though this is not always the case.
|
||||||
#include <AppKit/NSGraphics.h>
|
#include <AppKit/NSGraphics.h>
|
||||||
#include <AppKit/NSBitmapImageRep.h>
|
#include <AppKit/NSBitmapImageRep.h>
|
||||||
#include <AppKit/NSCell.h>
|
#include <AppKit/NSCell.h>
|
||||||
|
#include <AppKit/NSApplication.h>
|
||||||
|
|
||||||
/* used by listbox_darwin.go; requires NSString */
|
/* used by listbox_darwin.go; requires NSString */
|
||||||
id *_NSObservedObjectKey = (id *) (&NSObservedObjectKey);
|
id *_NSObservedObjectKey = (id *) (&NSObservedObjectKey);
|
||||||
|
@ -241,7 +242,8 @@ static void __areaView_drawRect(id self, SEL sel, NSRect r)
|
||||||
|
|
||||||
void *_areaView_drawRect = (void *) __areaView_drawRect;
|
void *_areaView_drawRect = (void *) __areaView_drawRect;
|
||||||
|
|
||||||
/* the only objective-c feature you'll see here
|
/*
|
||||||
|
this and one below it are the only objective-c feature you'll see here
|
||||||
|
|
||||||
unfortunately NSRect both varies across architectures and is passed as just a structure, so its encoding has to be computed at compile time
|
unfortunately NSRect both varies across architectures and is passed as just a structure, so its encoding has to be computed at compile time
|
||||||
because @encode() is NOT A LITERAL, we're going to just stick it all the way back in objc_darwin.go
|
because @encode() is NOT A LITERAL, we're going to just stick it all the way back in objc_darwin.go
|
||||||
|
@ -327,3 +329,19 @@ void objc_setFont(id what, unsigned int csize)
|
||||||
objc_msgSend(what, s_setFont,
|
objc_msgSend(what, s_setFont,
|
||||||
objc_msgSend(c_NSFont, s_systemFontOfSize, size));
|
objc_msgSend(c_NSFont, s_systemFontOfSize, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
-[NSApplicationDelegate applicationShouldTerminate] used to return a BOOL, but now returns a NSApplicationTerminateReply, which is a NSUInteger; hence, here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern void appDelegate_applicationShouldTerminate();
|
||||||
|
|
||||||
|
static NSApplicationTerminateReply __appDelegate_applicationShouldTerminate(id self, SEL sel)
|
||||||
|
{
|
||||||
|
appDelegate_applicationShouldTerminate();
|
||||||
|
return NSTerminateCancel; // don't quit
|
||||||
|
}
|
||||||
|
|
||||||
|
void *_appDelegate_applicationShouldTerminate = (void *) __appDelegate_applicationShouldTerminate;
|
||||||
|
|
||||||
|
char *encodedTerminateReply = @encode(NSApplicationTerminateReply);
|
||||||
|
|
|
@ -12,6 +12,7 @@ This creates a class goAppDelegate that will be used as the delegate for /everyt
|
||||||
- handles window close events (windowShouldClose:)
|
- handles window close events (windowShouldClose:)
|
||||||
- handles window resize events (windowDidResize:)
|
- handles window resize events (windowDidResize:)
|
||||||
- handles button click events (buttonClicked:)
|
- handles button click events (buttonClicked:)
|
||||||
|
- handles the application-global Quit event (such as from the Dock) (applicationShouldTerminate)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
|
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
|
||||||
|
@ -45,6 +46,8 @@ var appDelegateSels = []selector{
|
||||||
"handling window resize events"},
|
"handling window resize events"},
|
||||||
selector{"buttonClicked:", uintptr(C.appDelegate_buttonClicked), sel_bool_id,
|
selector{"buttonClicked:", uintptr(C.appDelegate_buttonClicked), sel_bool_id,
|
||||||
"handling button clicks"},
|
"handling button clicks"},
|
||||||
|
selector{"applicationShouldTerminate", uintptr(C._appDelegate_applicationShouldTerminate), sel_terminatereply,
|
||||||
|
"handling Quit menu items (such as from the Dock)/the AppQuit channel"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func mkAppDelegate() error {
|
func mkAppDelegate() error {
|
||||||
|
@ -94,3 +97,12 @@ func appDelegate_buttonClicked(self C.id, sel C.SEL, button C.id) {
|
||||||
sysData := getSysData(button)
|
sysData := getSysData(button)
|
||||||
sysData.signal()
|
sysData.signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export appDelegate_applicationShouldTerminate
|
||||||
|
func appDelegate_applicationShouldTerminate() {
|
||||||
|
// asynchronous so as to return control to the event loop
|
||||||
|
go func() {
|
||||||
|
AppQuit <- struct{}{}
|
||||||
|
}()
|
||||||
|
// xxx in bleh_darwin.m tells Cocoa not to quit
|
||||||
|
}
|
||||||
|
|
3
doc.go
3
doc.go
|
@ -20,6 +20,7 @@ Here is a simple, complete program that asks the user for their name and greets
|
||||||
|
|
||||||
func myMain() {
|
func myMain() {
|
||||||
w := ui.NewWindow("Hello", 400, 100)
|
w := ui.NewWindow("Hello", 400, 100)
|
||||||
|
ui.AppQuit = w.Closing // treat quitting the application like closing the main window
|
||||||
nameField := ui.NewLineEdit("Enter Your Name Here")
|
nameField := ui.NewLineEdit("Enter Your Name Here")
|
||||||
button := ui.NewButton("Click Here For a Greeting")
|
button := ui.NewButton("Click Here For a Greeting")
|
||||||
err := w.Open(ui.NewVerticalStack(nameField, button))
|
err := w.Open(ui.NewVerticalStack(nameField, button))
|
||||||
|
@ -29,7 +30,7 @@ Here is a simple, complete program that asks the user for their name and greets
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-w.Closing: // user tries to close the window
|
case <-w.Closing: // user tries to close the window or quit the program
|
||||||
return
|
return
|
||||||
case <-button.Clicked: // user clicked the button
|
case <-button.Clicked: // user clicked the button
|
||||||
ui.MsgBox("Hello, " + nameField.Text() + "!", "")
|
ui.MsgBox("Hello, " + nameField.Text() + "!", "")
|
||||||
|
|
11
init.go
11
init.go
|
@ -14,3 +14,14 @@ package ui
|
||||||
func Go(main func()) error {
|
func Go(main func()) error {
|
||||||
return ui(main)
|
return ui(main)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppQuit is pulsed when the user decides to quit the program if their operating system provides a facility for quitting an entire application, rather than merely close all windows (for instance, Mac OS X via the Dock icon).
|
||||||
|
// You should assign one of your Windows's Closing to this variable so the user choosing to quit the application is treated the same as closing that window.
|
||||||
|
// If you do not respond to this signal, nothing will happen.
|
||||||
|
// Do not merely check this channel alone; it is not guaranteed to be pulsed on all systems or in all conditions.
|
||||||
|
var AppQuit chan struct{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// don't expose this in the documentation
|
||||||
|
AppQuit = newEvent()
|
||||||
|
}
|
||||||
|
|
|
@ -71,14 +71,16 @@ const (
|
||||||
sel_bool_id
|
sel_bool_id
|
||||||
sel_bool
|
sel_bool
|
||||||
sel_void_rect
|
sel_void_rect
|
||||||
|
sel_terminatereply
|
||||||
nitypes
|
nitypes
|
||||||
)
|
)
|
||||||
|
|
||||||
var itypes = [nitypes][]C.char{
|
var itypes = [nitypes][]C.char{
|
||||||
sel_void_id: []C.char{'v', '@', ':', '@', 0},
|
sel_void_id: []C.char{'v', '@', ':', '@', 0},
|
||||||
sel_bool_id: []C.char{'c', '@', ':', '@', 0},
|
sel_bool_id: []C.char{'c', '@', ':', '@', 0},
|
||||||
sel_bool: []C.char{'c', '@', ':', 0},
|
sel_bool: []C.char{'c', '@', ':', 0},
|
||||||
sel_void_rect: nil, // see init() below
|
sel_void_rect: nil, // see init() below
|
||||||
|
sel_terminatereply: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -91,6 +93,14 @@ func init() {
|
||||||
}
|
}
|
||||||
x = append(x, 0)
|
x = append(x, 0)
|
||||||
itypes[sel_void_rect] = x
|
itypes[sel_void_rect] = x
|
||||||
|
|
||||||
|
x = make([]C.char, 0, 256) // more than enough
|
||||||
|
y = C.GoString(C.encodedTerminateReply)
|
||||||
|
for _, b := range y {
|
||||||
|
x = append(x, C.char(b))
|
||||||
|
}
|
||||||
|
x = append(x, '@', ':', 0)
|
||||||
|
itypes[sel_terminatereply] = x
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeClass(name string, super C.id, sels []selector, desc string) (id C.id, err error) {
|
func makeClass(name string, super C.id, sels []selector, desc string) (id C.id, err error) {
|
||||||
|
|
|
@ -117,8 +117,12 @@ extern struct xpoint getTranslatedEventPoint(id, id);
|
||||||
|
|
||||||
/* for objc_darwin.go */
|
/* for objc_darwin.go */
|
||||||
extern char *encodedNSRect;
|
extern char *encodedNSRect;
|
||||||
|
extern char *encodedTerminateReply;
|
||||||
|
|
||||||
/* for sysdata_darwin.go */
|
/* for sysdata_darwin.go */
|
||||||
extern void objc_setFont(id, unsigned int);
|
extern void objc_setFont(id, unsigned int);
|
||||||
|
|
||||||
|
/* for delegate_darwin.go */
|
||||||
|
extern void *_appDelegate_applicationShouldTerminate;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -282,6 +282,9 @@ _=curtime
|
||||||
case <-w.Closing:
|
case <-w.Closing:
|
||||||
println("window closed event received")
|
println("window closed event received")
|
||||||
break mainloop
|
break mainloop
|
||||||
|
case <-AppQuit:
|
||||||
|
println("application quit event received")
|
||||||
|
break mainloop
|
||||||
case <-b.Clicked:
|
case <-b.Clicked:
|
||||||
w.SetTitle(fmt.Sprintf("%v | %s | %s | %s | %s",
|
w.SetTitle(fmt.Sprintf("%v | %s | %s | %s | %s",
|
||||||
c.Checked(),
|
c.Checked(),
|
||||||
|
|
Loading…
Reference in New Issue