EventClose on Dock

Mac OSX specific forum
spacebuddy
Enthusiast
Enthusiast
Posts: 346
Joined: Thu Jul 02, 2009 5:42 am

EventClose on Dock

Post 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? :shock:

How do I detect this event, I don't want anyone clicking on the dock icon and just closing my application without a warning :D
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: EventClose on Dock

Post by Polo »

This event is #pb_menu_quit (or something like that).
spacebuddy
Enthusiast
Enthusiast
Posts: 346
Joined: Thu Jul 02, 2009 5:42 am

Re: EventClose on Dock

Post 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". :D
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: EventClose on Dock

Post by Polo »

From what I remember it's the same event, did you try?
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: EventClose on Dock

Post 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
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Re: EventClose on Dock

Post 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!)
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: EventClose on Dock

Post by Rinzwind »

The code of Shardik doesn't seem to work anymore?

Just interested in getting the applicationShouldTerminate and applicationWillTerminate notificatoin.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: EventClose on Dock

Post 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 .
Windows (x64)
Raspberry Pi OS (Arm64)
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: EventClose on Dock

Post by Rinzwind »

And thanks again mr iGuru. Is there anything you can't figure out irt macPB? 8)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: EventClose on Dock

Post by wilbert »

Rinzwind wrote:Is there anything you can't figure out irt macPB? 8)
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.
Windows (x64)
Raspberry Pi OS (Arm64)
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: EventClose on Dock

Post 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...
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: EventClose on Dock

Post 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.
Windows (x64)
Raspberry Pi OS (Arm64)
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: EventClose on Dock

Post 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
Rinzwind
Enthusiast
Enthusiast
Posts: 636
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: EventClose on Dock

Post by Rinzwind »

Any way to at least show some moving gui like progressbar in that “sheet” runmode?
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: EventClose on Dock

Post 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
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply