Page 1 of 1

Window resize events

Posted: Fri Jul 24, 2020 6:10 pm
by WilliamL
...it seems that I brought this up once before but I can't find the post.

When I resize a window I get a lot of #PB_Event_SizeWindow events. This is not usually a problem but I had a case where the data being re-loaded to the gadgets was large and having many #PB_Event_SizeWindow events was slowing things down with the repeated re-loads. Is there a way to get just one #PB_Event_SizeWindow event when the window is resized?

Code: Select all

#wndid=1 : #gadget1=1
Procedure UpdateGadgetInfo()
    ;ClearGadgetItems(#gadget1) ; taken out to show the repeated loading
    AddGadgetItem(#gadget1,-1,"Added line")
EndProcedure

If OpenWindow(#wndid, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
    ListViewGadget(#gadget1,10,10,175,240)
    UpdateGadgetInfo()
EndIf

Repeat
    Event = WaitWindowEvent()
    Select event
    Case #PB_Event_CloseWindow
        End
    Case #PB_Event_SizeWindow
        Debug "Window resized"
        ResizeGadget(#gadget1,#PB_Ignore,#PB_Ignore,WindowWidth(#wndid)-20,WindowHeight(#wndid)-20)
        UpdateGadgetInfo()
    EndSelect
ForEver

Re: Window resize events

Posted: Fri Jul 24, 2020 10:05 pm
by mk-soft
At macOS and the events of PB are very strange.

After hours of searching finally found.

NSWindowDidEndLiveResizeNotification

Base of Wilbert - Link: viewtopic.php?p=393576#p393576

Code: Select all

;-TOP

; *** import the required functions ***

ImportC ""
  sel_registerName(str.p-ascii)
  class_addMethod(class, selector, imp, types.p-ascii)
EndImport

; *** required variables ***

Global notificationCenter = CocoaMessage(0, 0, "NSNotificationCenter defaultCenter")
Global appDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Global delegateClass = CocoaMessage(0, appDelegate, "class")

Define selector

; ---

#wndid=1 : #gadget1=1

Procedure UpdateGadgetInfo()
  Static cnt
  cnt + 1
  AddGadgetItem(#gadget1,-1,"Added line " + cnt)
EndProcedure

; *** Window0 resize callback ***

ProcedureC Window0_Resize(obj, sel, notification)
  ResizeGadget(#gadget1, 10, 10, WindowWidth(#wndid) - 20, WindowHeight(#wndid) - 20)
EndProcedure

ProcedureC Window0_ResizeDone(obj, sel, notification)
  UpdateGadgetInfo()
EndProcedure

; ----

If OpenWindow(#wndid, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
  ListViewGadget(#gadget1,10,10,175,240)
  UpdateGadgetInfo()
  
  selector = sel_registerName("Window0_Resize:")
  class_addMethod(delegateClass, selector, @Window0_Resize(), "v@:@")
  CocoaMessage(0, notificationCenter, "addObserver:", appDelegate, "selector:", selector, "name:$", @"NSWindowDidResizeNotification", "object:", WindowID(#wndid))
  
  selector = sel_registerName("Window0_ResizeDone:")
  class_addMethod(delegateClass, selector, @Window0_ResizeDone(), "v@:@")
  CocoaMessage(0, notificationCenter, "addObserver:", appDelegate, "selector:", selector, "name:$", @"NSWindowDidEndLiveResizeNotification", "object:", WindowID(#wndid))
  
EndIf

Repeat
  Event = WaitWindowEvent()
  Select event
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_SizeWindow
      ;
  EndSelect
ForEver

CocoaMessage(0, notificationCenter, "removeObserver:", appDelegate, "name:$", @"NSWindowDidResizeNotification", "object:", #nil)
CocoaMessage(0, notificationCenter, "removeObserver:", appDelegate, "name:$", @"NSWindowDidEndLiveResizeNotification", "object:", #nil)

Re: Window resize events

Posted: Fri Jul 24, 2020 10:35 pm
by WilliamL
mk-soft,

I saw wilberts example also and I've been studying both of them. I see what you have done and it works fine. I wonder if it works this way on Windows?

I tried using a flag to set the first time thru the event but I couldn't figure out how to know when the drag was done. Your second method (?) was the key (Window0_ResizeDone() ).

I don't know how you (both) figure this stuff out :!:

Thanks again.

Re: Window resize events

Posted: Sat Jul 25, 2020 7:41 am
by Shardik
I have found out something really weird: WilliamL's first example is running like a charm when setting #wndid=0 instead of #wndid=1 or any other number or when using #PB_Any...:oops:

I have observed this on MacOS 10.13.6 'High Sierra' and MacOS 10.14.6 'Mojave' with PB 5.46 x86 and x64 and PB 5.72 x86 and x64. #wndid=0 doesn't defer from other IDs in PB 5.31 x86 and x64, i.e. in PB 5.31 #PB_Event_SizeWindow produces several events also with #wndid=0.

Re: Window resize events

Posted: Sat Jul 25, 2020 10:52 am
by Wolfram
May be this helps you.
But depends on how slow you update procedure is you need a trigger if you left the mouse button.

Code: Select all

#wndid=1 : #gadget1=1
Procedure UpdateGadgetInfo()
    ;ClearGadgetItems(#gadget1) ; taken out to show the repeated loading
    AddGadgetItem(#gadget1,-1,"Added line")
EndProcedure

Procedure rsCallback()
          Debug "Window resized"
        ResizeGadget(#gadget1,#PB_Ignore,#PB_Ignore,WindowWidth(#wndid)-20,WindowHeight(#wndid)-20)
        UpdateGadgetInfo()
EndProcedure


If OpenWindow(#wndid, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
    ListViewGadget(#gadget1,10,10,175,240)
    UpdateGadgetInfo()
    
    BindEvent(#PB_Event_SizeWindow, @rsCallback(), #wndid)
    
EndIf



Repeat
  Event = WaitWindowEvent()
    Select event
    Case #PB_Event_CloseWindow
        End
;     Case #PB_Event_SizeWindow
;         Debug "Window resized"
;         ResizeGadget(#gadget1,#PB_Ignore,#PB_Ignore,WindowWidth(#wndid)-20,WindowHeight(#wndid)-20)
;         UpdateGadgetInfo()
    EndSelect
  ForEver
  

Re: Window resize events

Posted: Sat Jul 25, 2020 11:33 am
by mk-soft
May be this helps you.
But depends on how slow you update procedure is you need a trigger if you left the mouse button.
I've tested that too.
Unfortunately I did not save the code with currentEvent.

But every time after a Resize Event there is also NSLeftMouseUp.

Somehow there must be a bug in the event management of PB.

Re: Window resize events

Posted: Sat Jul 25, 2020 6:18 pm
by Shardik
@mk-soft,

your example is too complicated. You don't need two callbacks. One callback for NSWindowDidEndLiveResizeNotification would be sufficient.
mk-soft wrote:After hours of searching finally found.
I had posted this cross-platform solution already in 2014 in the German forum... :wink:

I have taken my old cross-platform example from 2014, stripped off the Linux and Windows parts and adapted it to WilliamL's example:

Code: Select all

EnableExplicit

#WinID = 0

#PB_Event_WindowResizeComplete = #PB_Event_FirstCustomValue

ProcedureC WindowCallback(Object.I, Selector.I, Notification.I)
  ResizeGadget(0, 10, 10, WindowWidth(#WinID) - 20,
    WindowHeight(#WinID) - 20)
  PostEvent(#PB_Event_WindowResizeComplete, #WinID, 0)
EndProcedure

Procedure UpdateGadgetInfo()
  Static LineCount.I
  LineCount + 1
  AddGadgetItem(0, -1, "Added line " + LineCount)
EndProcedure

Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Define NotificationCenter.I = CocoaMessage(0, 0,
  "NSNotificationCenter defaultCenter")
Define Selector.I = sel_registerName_("WindowResizeDidEnd:")

If OpenWindow(#WinID, 100, 200, 195, 260, "Resizing test",
  #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  ListViewGadget(0, 10, 10, 175, 240)

  class_addMethod_(DelegateClass, Selector, @WindowCallback(), "v@:@")
  CocoaMessage(0, NotificationCenter,
    "addObserver:", AppDelegate,
    "selector:", Selector,
    "name:$", @"NSWindowDidEndLiveResizeNotification",
    "object:", WindowID(#WinID))

  UpdateGadgetInfo()
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #PB_Event_WindowResizeComplete
        UpdateGadgetInfo()
    EndSelect
  ForEver
EndIf

CocoaMessage(0, NotificationCenter, "removeObserver:", AppDelegate,
  "name:$", @"NSWindowDidEndLiveResizeNotification",
  "object:", WindowID(#WinID))
I have just posted this bug report in the forum "Bugs - Mac OSX"

Re: Window resize events

Posted: Sat Jul 25, 2020 7:14 pm
by mk-soft
Damn it.

I didn't look in the German forums.

But it's a bug in the PB ?!
If the Window ID is zero, there is only one event like in Windows.
With Linux every event arrives in the MainScope ?!

Code: Select all

;-TOP

Enumeration Windows 0 ; Set here to 1 
  #Main
EndEnumeration

Enumeration Gadgets 1
  #Gadget
EndEnumeration

Enumeration Status
  #MainStatusBar
EndEnumeration

Procedure DoEventSizeWindow()
  Static cnt
  cnt + 1
  Debug "BindEvent SizeWindow Count " + cnt
  ResizeGadget(#Gadget, 5, 5, WindowWidth(#Main) - 10, WindowHeight(#Main) - 10)
EndProcedure

BindEvent(#PB_Event_SizeWindow, @DoEventSizeWindow(), #Main)

Procedure Main()
  Protected cnt
  
  #MainStyle = #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 600, 400, "Window" , #MainStyle)
    ListViewGadget(#Gadget, 5, 5, 590, 390)
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_SizeWindow
          If EventWindow() = #Main
            cnt + 1
            Debug "MainScope SizeWindow Count " + cnt
            AddGadgetItem(#Gadget,-1,"MainScope Added line " + cnt)
          EndIf
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()

Re: Window resize events

Posted: Sun Jul 26, 2020 6:50 pm
by Shardik
@mk-soft,

I have tested your last example on all 3 operating systems running on real hardware:
  • Linux Mint 19.3 'Tricia' x64 with Cinnamon and PB 5.72 x64:
    Each window resize event generates multiple messages.
    For each BindEvent message 1 MainScope message is displayed.
    BindEvent count and MainScope count are synchronized.
  • MacOS 10.14.6 'Mojave' and PB 5.72 x64:
    • #Window=0
      Each window resize event generates 1 message.
      Multiple BindEvent messages are displayed for 1 MainScope message.
    • #Window<>0
      Each window resize event generates multiple messages.
      Multiple BindEvent and multiple MainScope messages are displayed.
  • Windows 10 x64 v1909 with PB 5.72 x86:
    Each window resize event generates 1 message.
    Multiple BindEvent messages are displayed for 1 MainScope message.
By the way, you should add #PB_Window_SizeGadget to your constant #MainStyle because otherwise the window resizing won't work on Windows!
mk-soft wrote:But it's a bug in the PB ?!
It's clearly a bug in PB for MacOS and it's a total mess for cross-platform programming when trying to catch window resize events!

Re: Window resize events

Posted: Fri Aug 14, 2020 3:38 am
by WilliamL
Maybe this thread should be moved to 'Bugs - Mac OSX'...

Re: Window resize events

Posted: Fri Sep 25, 2020 5:41 am
by collectordave
I maybe looking at this a little simply.

On my mac I just throw the events I do not want away.

I have added the sizewindowhandler() from the help

Code: Select all

#wndid=23 : #gadget1=1
Procedure UpdateGadgetInfo()
    ClearGadgetItems(#gadget1) ; taken out to show the repeated loading
    AddGadgetItem(#gadget1,-1,"Added line")
EndProcedure

 Procedure SizeWindowHandler()
   
    Debug "Size event on window #" + EventWindow()
    ResizeGadget(#gadget1,#PB_Ignore,#PB_Ignore,WindowWidth(#wndid)-20,WindowHeight(#wndid)-20)
    
  EndProcedure



If OpenWindow(#wndid, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
    ListViewGadget(#gadget1,10,10,175,240)
    UpdateGadgetInfo()
EndIf



  BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())

Repeat
    Event = WaitWindowEvent()
    Select event
    Case #PB_Event_CloseWindow
        End
      Case #PB_Event_SizeWindow
        Debug "Main Loop Resize"
        UpdateGadgetInfo()
        While WindowEvent():Wend
    EndSelect
ForEver
I get multiple calls to the size handler and just one to the main loop resize bit?

PB 5.72 on mac book pro high sierra

CD