Page 1 of 2
EventClose on Dock
Posted: Fri Aug 29, 2014 9:50 pm
by spacebuddy
If I minimize my application, then right click on the icon on the dock, the one with the little light under it, then select quit no event is fired?
How do I detect this event, I don't want anyone clicking on the dock icon and just closing my application without a warning
Re: EventClose on Dock
Posted: Fri Aug 29, 2014 10:32 pm
by Polo
This event is #pb_menu_quit (or something like that).
Re: EventClose on Dock
Posted: Fri Aug 29, 2014 10:50 pm
by spacebuddy
Polo wrote:This event is #pb_menu_quit (or something like that).
No, that is not the one. That is when you click on the top menu and select "Quit". I am talking about your application being minimized
on the dock, then right clicking the icon and selecting "Quit".
Re: EventClose on Dock
Posted: Sat Aug 30, 2014 2:28 am
by Polo
From what I remember it's the same event, did you try?
Re: EventClose on Dock
Posted: Thu Sep 04, 2014 9:12 pm
by Shardik
Unfortunately #PB_Menu_Quit doesn't work in detecting the selection of "Quit" after a right click onto the application's minimized dock icon. It's a little bit more complicated: you have to define a callback for the NSApplicationDelegate method applicationShouldTerminate: and then you are even able to ask the user for a confirmation to terminate the application. Without this workaround your program will terminate with a debugger error message. Therefore I have already posted this
bug report.
I have tested the following code with MacOS X 10.6.8 (Snow Leopard) with PB 5.30 x86 and x64 in both ASCII and Unicode mode:
Code: Select all
EnableExplicit
ImportC ""
sel_registerName(MethodName.S)
class_addMethod(Class.I, Selector.I, Implementation.I, Types.S)
EndImport
ProcedureC AppShouldTerminate(Object.I, Selector.I, Sender.I)
If MessageRequester("Confirmation", "Do you want to terminate the application?",
#PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
End
Else
ProcedureReturn #NO
EndIf
EndProcedure
Procedure.S ConvertToUTF8(String.S)
Protected UTF8String.S = Space(StringByteLength(String))
PokeS(@UTF8String, String, -1, #PB_UTF8)
ProcedureReturn UTF8String
EndProcedure
Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
"NSApplication sharedApplication"), "delegate")
OpenWindow(0, 270, 100, 200, 170, "Test", #PB_Window_MinimizeGadget)
class_addMethod(CocoaMessage(0, AppDelegate, "class"),
sel_registerName(ConvertToUTF8("applicationShouldTerminate:")),
@AppShouldTerminate(), "v@:@")
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Re: EventClose on Dock
Posted: Tue Sep 23, 2014 3:52 am
by kenmo
THANK YOU SHARDIK
I have not tested your code yet, but this looks like exactly what I need.
(My program isn't catching the "Quit" dock event, so it doesn't exit properly, which later causes problems the next time it runs!)
Re: EventClose on Dock
Posted: Fri Aug 30, 2019 10:03 am
by Rinzwind
The code of Shardik doesn't seem to work anymore?
Just interested in getting the applicationShouldTerminate and applicationWillTerminate notificatoin.
Re: EventClose on Dock
Posted: Fri Aug 30, 2019 11:53 am
by wilbert
class_addMethod only adds a method if it doesn't exist.
It appears PureBasic itself started using applicationShouldTerminate: which wasn't the case at the time this code was posted.
One way would be to use class_replaceMethod and call the previous implementation of applicationShouldTerminate: from within the callback.
Something like this.
Code: Select all
EnableExplicit
Prototype Proto_AppShouldTerminate(Object, Selector, Sender)
DeclareC AppShouldTerminate(Object, Selector, Sender)
Global AppDelegate, AppShouldTerminate_.Proto_AppShouldTerminate
AppDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
AppShouldTerminate_ = class_replaceMethod_(CocoaMessage(0, AppDelegate, "class"),
sel_registerName_("applicationShouldTerminate:"),
@AppShouldTerminate(), "v@:@")
ProcedureC AppShouldTerminate(Object, Selector, Sender)
If AppShouldTerminate_
AppShouldTerminate_(Object, Selector, Sender)
EndIf
If MessageRequester("Confirmation", "Do you want to terminate the application?",
#PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
End
Else
ProcedureReturn #NO
EndIf
EndProcedure
OpenWindow(0, 270, 100, 200, 170, "Test", #PB_Window_MinimizeGadget)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
If you only need a notification, you could probably also use NSNotificationCenter and observe for NSApplicationWillTerminateNotification .
Re: EventClose on Dock
Posted: Fri Aug 30, 2019 12:19 pm
by Rinzwind
And thanks again mr iGuru. Is there anything you can't figure out irt macPB?
Re: EventClose on Dock
Posted: Fri Aug 30, 2019 12:31 pm
by wilbert
Rinzwind wrote:Is there anything you can't figure out irt macPB?
Of course
But I like macOS and do know a bit about it.
I'm sure Shardik would also have been able to figure this out since he posted the original code and knows a lot about macOS.
Re: EventClose on Dock
Posted: Wed Sep 04, 2019 12:28 pm
by Rinzwind
Hmm additional unclarity...
"For Cocoa applications, termination is partly handled by the Application Kit, which calls the applicationShouldTerminate: delegate method. To abort the termination sequence, implement this method and return NSTerminateCancel; otherwise, termination of your application continues normally."
"NSTerminateLater = 2
It may be OK to proceed with termination later. Returning this value causes Cocoa to run the run loop in the NSModalPanelRunLoopMode until your app subsequently calls replyToApplicationShouldTerminate: with the value YES or NO. This return value is for delegates that need to provide document modal alerts (sheets) in order to decide whether to quit.
"
If I return NSTerminateLater the main event loop is indeed not called anymore... a new event loop is started it seems. I have no clue how to handle that bit NSModalPanelRunLoopMode. I want to just continue with the main loop and call replyToApplicationShouldTerminate whenever convenient...
Re: EventClose on Dock
Posted: Wed Sep 04, 2019 1:55 pm
by wilbert
Rinzwind wrote:f I return NSTerminateLater the main event loop is indeed not called anymore... a new event loop is started it seems. I have no clue how to handle that bit NSModalPanelRunLoopMode. I want to just continue with the main loop and call replyToApplicationShouldTerminate whenever convenient...
I doubt if what you want is possible this way.
Like what you quoted already mentions, this is intended for something like the PureBasic MessageRequester to get confirmation if you want the app to quit or not.
If you want to continue with the main loop, just cancel the quit. You can set a flag or post an event and act on that from the main loop.
Re: EventClose on Dock
Posted: Wed Sep 04, 2019 2:14 pm
by Rinzwind
If I return #NSTerminateNow the application is instantly killed. If I return #NSTerminateCancel (0) the OS dialog app prevents shutdown is shown and shutdown is cancelled. With #NSTerminateLater the app becomes unresponsive. Hmm
Re: EventClose on Dock
Posted: Wed Sep 04, 2019 2:48 pm
by Rinzwind
Any way to at least show some moving gui like progressbar in that “sheet” runmode?
Re: EventClose on Dock
Posted: Wed Sep 04, 2019 3:07 pm
by wilbert
Is the event method I suggested not working for you ?
Code: Select all
Enumeration #PB_Event_FirstCustomValue
#Event_TerminateRequested
EndEnumeration
Prototype Proto_AppShouldTerminate(Object, Selector, Sender)
DeclareC AppShouldTerminate(Object, Selector, Sender)
Global AppDelegate, AppShouldTerminate_.Proto_AppShouldTerminate
AppDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
AppShouldTerminate_ = class_replaceMethod_(CocoaMessage(0, AppDelegate, "class"),
sel_registerName_("applicationShouldTerminate:"),
@AppShouldTerminate(), "v@:@")
ProcedureC AppShouldTerminate(Object, Selector, Sender)
PostEvent(#Event_TerminateRequested)
If AppShouldTerminate_
ProcedureReturn AppShouldTerminate_(Object, Selector, Sender)
EndIf
ProcedureReturn #NO
EndProcedure
OpenWindow(0, 0, 0, 420, 320, "Terminate request example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EditorGadget(0, 10, 10, 400, 300)
Repeat
Event = WaitWindowEvent()
If Event = #Event_TerminateRequested
AddGadgetItem(0, -1, "Terminate requested at:" + FormatDate("%hh:%ii:%ss", Date()))
EndIf
Until Event = #PB_Event_CloseWindow