Blocking/Locking a background window

Mac OSX specific forum
Lebostein
Addict
Addict
Posts: 807
Joined: Fri Jun 11, 2004 7:07 am

Blocking/Locking a background window

Post by Lebostein »

How I block a window with another popup window on Mac OS? If I disable the background window (DisableWindow) and I click on this disabled background window, the background window gets active and the popup looses the focus. It is even possible to activate gadgets in this disabled window (SetActiveGadget). So I can scroll through a list (with trackpad), switch the active gadgets by TAB and press buttons with SPACE inside a disabled window!! It seems only some mouse interaction are blocked. This is not the behaviour I see on Windows. With Windows the disabled window is untouchable. It is impossible to activate a disabled window and it is impossible to activate and trigger gadgets inside a disabled window. Is DisableWindow() the wrong way to lock a window?
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Blocking/Locking a background window

Post by Danilo »

Could you use a modal window?

Code: Select all

Macro RunModal(_window_)
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"runModalForWindow:",WindowID(_window_))
EndMacro

Macro AbortModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"abortModal")
EndMacro

Macro StopModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"stopModal")
EndMacro

Procedure OnButton_0()
    HideWindow(1,#False) ; without this line, hidden windows are always displayed automatically, and always centered
    RunModal( 1 )
EndProcedure

Procedure OnButton_1()
    AbortModal() ; StopModal()
    SetActiveWindow(0)
    HideWindow(1,#True)
EndProcedure

If OpenWindow(0,0,0,800,600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(0,10,10,150,25,"Open Modal Window")
    BindGadgetEvent(0,@OnButton_0())
    ListViewGadget(2,10,45,300,300)
    For i = 1 To 200 : AddGadgetItem(2,-1,"Item "+i) : Next
    
    OpenWindow(1,200,300,300,200,"Tool",#PB_Window_Tool|#PB_Window_Invisible,WindowID(0))
    ButtonGadget(1,10,10,150,25,"Close Modal Window")
    BindGadgetEvent(1,@OnButton_1())
    
    Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
User avatar
fsw
Addict
Addict
Posts: 1572
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: Blocking/Locking a background window

Post by fsw »

You could probably also use sheets; that's what I do.
Sheets can be any size, even bigger as the main window.
On how to implement sheets: Use a window as a sheet for another window

I am to provide the public with beneficial shocks.
Alfred Hitshock
Wolfram
Enthusiast
Enthusiast
Posts: 568
Joined: Thu May 30, 2013 4:39 pm

Re: Blocking/Locking a background window

Post by Wolfram »

Hi Danilo,

nice example. Is it possible to add a Keyboard shortcut to the Modal Window?
For example to have copy and past.

Thanks
Wolfram
macOS Catalina 10.15.7
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Blocking/Locking a background window

Post by Danilo »

Wolfram wrote:Is it possible to add a Keyboard shortcut to the Modal Window?
Another RunModal() method is required for this, so we can use PB's WaitWindowEvent() to run all of the internal event processing:

Code: Select all

Enumeration Commands 1000
    #Command_Copy
    #Command_Paste
EndEnumeration

;Macro RunModal(_window_)
;    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"runModalForWindow:",WindowID(_window_))
;EndMacro


Procedure RunModal(_window_)
    #NSModalResponseContinue = -1002
    ; begin a modal session
    Protected session = CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"beginModalSessionForWindow:",WindowID(_window_))
    ; loop while modal session is still running
    While CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"runModalSession:",session) = #NSModalResponseContinue
        WaitWindowEvent() ; PB's event processing
    Wend
    ; end modal session
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"endModalSession:",session)
EndProcedure

Macro AbortModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"abortModal")
EndMacro

Macro StopModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"stopModal")
EndMacro


Procedure OnCopy()
    Debug "Copy!"
EndProcedure

Procedure OnPaste()
    Debug "Paste!"
EndProcedure

Procedure OnButton_0()
    ;HideWindow(1,#False) ; without this line, hidden windows are always displayed automatically, and always centered
    RunModal( 1 )
EndProcedure

Procedure OnButton_1()
    AbortModal() ; StopModal()
    SetActiveWindow(0)
    HideWindow(1,#True)
EndProcedure

If OpenWindow(0,0,0,800,600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(0,10,10,150,25,"Open Modal Window")
    BindGadgetEvent(0,@OnButton_0())
    ListViewGadget(2,10,45,300,300)
    For i = 1 To 200 : AddGadgetItem(2,-1,"Item "+i) : Next
    
    OpenWindow(1,200,300,300,200,"Tool",#PB_Window_Tool|#PB_Window_Invisible,WindowID(0))
    ButtonGadget(1,10,10,150,25,"Close Modal Window")
    BindGadgetEvent(1,@OnButton_1())
    
    AddKeyboardShortcut(1,#PB_Key_1, #Command_Copy)
    AddKeyboardShortcut(1,#PB_Key_2, #Command_Paste)
    BindEvent(#PB_Event_Menu, @OnCopy() , 1, #Command_Copy)
    BindEvent(#PB_Event_Menu, @OnPaste(), 1, #Command_Paste)
        
    Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
Wolfram
Enthusiast
Enthusiast
Posts: 568
Joined: Thu May 30, 2013 4:39 pm

Re: Blocking/Locking a background window

Post by Wolfram »

Why are Windows which are open by the Modal Window (like this MessageRequester) not in center?

Code: Select all

Enumeration Commands 1000
    #Command_Copy
    #Command_Paste
EndEnumeration


Procedure RunModal(_window_)
    #NSModalResponseContinue = -1002
    ; begin a modal session
    Protected session = CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"beginModalSessionForWindow:",WindowID(_window_))
    ; loop while modal session is still running
    While CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"runModalSession:",session) = #NSModalResponseContinue
        WaitWindowEvent() ; PB's event processing
    Wend
    ; end modal session
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"endModalSession:",session)
EndProcedure

Macro AbortModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"abortModal")
EndMacro

Macro StopModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"stopModal")
EndMacro


Procedure OnCopy()
  Debug "Copy!"
  MessageRequester("ERROR!", "I'm not centered")
EndProcedure

Procedure OnPaste()
    Debug "Paste!"
EndProcedure

Procedure OnButton_0()
    ;HideWindow(1,#False) ; without this line, hidden windows are always displayed automatically, and always centered
    RunModal( 1 )
EndProcedure

Procedure OnButton_1()
    AbortModal() ; StopModal()
    SetActiveWindow(0)
    HideWindow(1,#True)
EndProcedure

If OpenWindow(0,0,0,800,600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(0,10,10,150,25,"Open Modal Window")
    BindGadgetEvent(0,@OnButton_0())
    ListViewGadget(2,10,45,300,300)
    For i = 1 To 200 : AddGadgetItem(2,-1,"Item "+i) : Next
    
    OpenWindow(1,200,300,300,200,"Tool",#PB_Window_Tool|#PB_Window_Invisible,WindowID(0))
    ButtonGadget(1,10,10,150,25,"Close Modal Window")
    BindGadgetEvent(1,@OnButton_1())
    
    AddKeyboardShortcut(1,#PB_Key_1, #Command_Copy)
    AddKeyboardShortcut(1,#PB_Key_2, #Command_Paste)
    BindEvent(#PB_Event_Menu, @OnCopy() , 1, #Command_Copy)
    BindEvent(#PB_Event_Menu, @OnPaste(), 1, #Command_Paste)
        
    Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
macOS Catalina 10.15.7
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Blocking/Locking a background window

Post by Danilo »

Wolfram wrote:Why are Windows which are open by the Modal Window (like this MessageRequester) not in center?
Looks like default behavior of NSAlert dialogs. If the alert (a modal dialog) is opened when another modal window is active, it is
positioned relative to the modal window (which makes sense somehow).

If you don't want that behavior, you can change it by centering and displaying the alert before running it in modal mode:

Code: Select all

Enumeration Commands 1000
    #Command_Copy
    #Command_Paste
EndEnumeration


Procedure RunModal(_window_)
    #NSModalResponseContinue = -1002
    ; begin a modal session
    Protected session = CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"beginModalSessionForWindow:",WindowID(_window_))
    ; loop while modal session is still running
    While CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"runModalSession:",session) = #NSModalResponseContinue
        WaitWindowEvent() ; PB's event processing
    Wend
    ; end modal session
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"endModalSession:",session)
EndProcedure

Macro AbortModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"abortModal")
EndMacro

Macro StopModal()
    CocoaMessage(0,CocoaMessage(0,0,"NSApplication sharedApplication"),"stopModal")
EndMacro


Procedure OnCopy()
  Debug "Copy!"
  
  ;MessageRequester("ERROR!", "I'm not centered")
  
  alert = CocoaMessage(0,CocoaMessage(0,0,"NSAlert alloc"),"init")
  CocoaMessage(0,alert,"setMessageText:$",@"Message text.")
  CocoaMessage(0,alert,"setInformativeText:$",@"Informative text.")
  CocoaMessage(0,alert,"addButtonWithTitle:$",@"OK")
  ;CocoaMessage(0,alert,"addButtonWithTitle:$",@"Cancel")
  ;CocoaMessage(0,alert,"addButtonWithTitle:$",@"Abort")
  CocoaMessage(0,alert,"layout")
  
  ; START FIX
  alertWindow = CocoaMessage(0,alert,"window")
  If alertWindow
      CocoaMessage(0,alertWindow,"center")                  ; center the window
      CocoaMessage(0,alertWindow,"makeKeyAndOrderFront:",0) ; display the window (without this line, it is displayed relative to the modal window)
  EndIf
  ; END FIX
  
  CocoaMessage(0,alert,"runModal")
  CocoaMessage(0,alert,"release")
  
EndProcedure

Procedure OnPaste()
    Debug "Paste!"
EndProcedure

Procedure OnButton_0()
    ;HideWindow(1,#False) ; without this line, hidden windows are always displayed automatically, and always centered
    RunModal( 1 )
EndProcedure

Procedure OnButton_1()
    AbortModal() ; StopModal()
    SetActiveWindow(0)
    HideWindow(1,#True)
EndProcedure

If OpenWindow(0,0,0,800,600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(0,10,10,150,25,"Open Modal Window")
    BindGadgetEvent(0,@OnButton_0())
    ListViewGadget(2,10,45,300,300)
    For i = 1 To 200 : AddGadgetItem(2,-1,"Item "+i) : Next
    
    AddKeyboardShortcut(0,#PB_Key_1, #Command_Copy)
    AddKeyboardShortcut(0,#PB_Key_2, #Command_Paste)
    BindEvent(#PB_Event_Menu, @OnCopy() , 0, #Command_Copy)
    BindEvent(#PB_Event_Menu, @OnPaste(), 0, #Command_Paste)

    OpenWindow(1,200,300,900,600,"Tool",#PB_Window_Tool|#PB_Window_Invisible,WindowID(0))
    ButtonGadget(1,10,10,150,25,"Close Modal Window")
    BindGadgetEvent(1,@OnButton_1())
    
    AddKeyboardShortcut(1,#PB_Key_1, #Command_Copy)
    AddKeyboardShortcut(1,#PB_Key_2, #Command_Paste)
    BindEvent(#PB_Event_Menu, @OnCopy() , 1, #Command_Copy)
    BindEvent(#PB_Event_Menu, @OnPaste(), 1, #Command_Paste)
        
    Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
Lebostein
Addict
Addict
Posts: 807
Joined: Fri Jun 11, 2004 7:07 am

Re: Blocking/Locking a background window

Post by Lebostein »

DisableWindow() on Mac OS X is very, very slow! If you have a ListIconGadget with > 10000 Items, then DisableWindow() needs more than a second to disable the window. With Windows DisableWindow() works immediately....
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Blocking/Locking a background window

Post by Rinzwind »

Examples above won't compile in recent PB... Did it ever work?
WindowEvent() and WaitWindowEvent() can not be called from a 'binded' event callback.

or any WaitWindowEvent in callback...

Can be solved in the above by not using BindEvent on the first button, but not always possible.
Post Reply