Page 1 of 2

WindowResizing flicker issue - can damage the running OS

Posted: Mon Oct 05, 2020 8:20 pm
by Saki

Latest info for you about it !
Fred and his team have clarified the matter, it is not a PB bug but a behavior of the Windows OS.
But read it anyway, because it can important to know that.


There is a problem with ResizeWindow which has existed for a long time.
I use ResizeWindow with BindEvent to resize the window proportionally.
After running ResizeWindow several times it seems that there is a buffer overflow which causes the windows to flicker extremely when resizing.
This can only be stopped by restarting the OS.
Please look, the window with the several small gadgets does not use ResizeWindow.
(This are two separatelly running exe !)
I run it first and it works fine to resize.
Now I resize the window with the big gadget that calls ResizeWindow multiple.
After a few seconds there is an internal crash and the gadget starts flickering.
Now the window with the small gadget flickers too.
Every window that has gadgets and resizes them will flicker from now on.
It seems that a buffer is no longer available in Windows OS.
This is very bad, because from now on everything flickers miserably.
Usually the programmer or user can't see the reason why everything suddenly flickers.
When programming, this can also be very bad, because you want to eliminate a flickering that you did not cause yourself.

You have to see if you can create a small demo code,
to be able to fix it better, but it is very special,
but unfortunately also very bad.

But I want to post it here, because it is really important to know about it and what causes this effect.

Image

Re: WindowResizing flicker Bug - damage the running OS

Posted: Tue Oct 06, 2020 1:29 pm
by Fred
Might be a driver problem. Could you post a small sample showing the issue ?

Re: WindowResizing flicker Bug - damage the running OS

Posted: Tue Oct 06, 2020 1:45 pm
by BarryG
Does it flicker with SmartWindowRefresh() enabled?

And what happens if you try PureLust's DeFlicker module -> viewtopic.php?f=12&t=65364

Re: WindowResizing flicker Bug - damage the running OS

Posted: Tue Oct 06, 2020 2:54 pm
by Saki
Hi Fred, thanks for the answer.
This is really a strange thing, it's nothing new either, but I could never locate what caused this behavior.
Only these new high computationally intensive Wizzard routines made it possible to recognize cause and effect.

Please see if this little reduced demo codes works for you.
The first is wizzard dependent and must be copied into the demo code archive of the wizzard.
It corresponds to the GIF in the thread above.
The error is triggered after seconds with this code.

With the very small stand alone code further down you don't see it well,
but with this stand alone code you can see exactly what happens at the bottom from the window.
The stand alone code also triggers the effect immediately and change the running OS.
To remove the effekt you must reboot the OS.

Hi Barry, no, that won't work, this one sits much deeper and is something completely different.

Best Regards Saki

Wizzard enhanced

Code: Select all

; ************** Dynamic Window / GUI creating module ***************
XIncludeFile("./GFX_Wizzard_BF.pbi")

EnableExplicit

DeclareModule CreateGUI_1
  EnableExplicit
  UseModule GFX_Wizzard_BF
  Declare CreateGUI_1(window_x, window_y, window_width_output, window_height_output)
EndDeclareModule

Module CreateGUI_1
  
  Global window_width_developing=920 ; Developing size
  Global window_height_developing=400
  
  Global window_min_width=200 ; Minimum window size
  Global window_min_height=150
  
  Global window_x, window_y, window_width_output, window_height_output
  Global window_flags=#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_Invisible 
  Global window_ID=OpenWindow(#PB_Any, 0, 0, window_width_developing, window_height_developing,
                              "Dynamic Window and GUI creating", Window_flags)
  WindowBounds(window_ID, window_min_width, window_min_height, #PB_Ignore, #PB_Ignore)
  Global get_all_window_events ; Auxiliary variable for callback procedure WindowEvent handling
  
  Define Image_ID=LoadImage(#PB_Any, "./Image_Set/Sunset.jpg")
  Global Image_1_ID=LoadImage(#PB_Any, "./Image_Set/Foxy.png")
  ; Global Image_2_ID=LoadImage(#PB_Any, "./Image_Set/Cat_01.jpg")
  
  ; Create ButtonImageGadget _1 for using ==========================================
  Global ButtonImageGadget_1_width=600
  Global ButtonImageGadget_1_height=150
  Global ButtonImageGadget_1_x=WindowWidth(window_ID)/2-ButtonImageGadget_1_width/2
  Global ButtonImageGadget_1_y=WindowHeight(window_ID)/2-ButtonImageGadget_1_height/2
  
  Define text_1$="Hello World"

  Global Gadget_1_ID=MagicTextGadget_BF(0,                          ; 0 = ButtonImageGadget - 1 = CanvasGadget
                                        text_1$,                    ; Text
                                        ButtonImageGadget_1_x,      ; Gadget output x pos
                                        ButtonImageGadget_1_y,      ; Gadget output y pos
                                        ButtonImageGadget_1_width,  ; Gadget width
                                        ButtonImageGadget_1_height, ; Gadget height
                                        ButtonImageGadget_1_width,  ; Text width
                                        ButtonImageGadget_1_height, ; Text height
                                        1,                          ; Text stretching x - Headline mode
                                        1,                          ; Text stretching y - Headline mode
                                        1,                          ; padding_x
                                        1,                          ; Padding y
                                        #Black,                     ; Text color - Alpha channel supported
                                        -1,                         ; Background color - Alpha channel supported - For invisible background set to -1
                                        1,                          ; Text flag - Text center=1 - Text right=2 - Text vertical=3
                                        "Georgia",                  ; Font type - more is not needed - accept also ""
                                        #PB_Font_Bold,              ; Font style
                                        0)                          ; #PB_Canvas_Border ; Border flag)
  
  ; ############## Resize procedure for callback ##############################
  Procedure WindowResizing_BindEvent_CreateGUI_1()
    
    ; ============= Init the scaling variables ==============
    Global set_x.d=100/window_width_developing*WindowWidth(window_ID)/100
    Global set_y.d=100/window_height_developing*WindowHeight(window_ID)/100

    Define button_width.d=600  ; Text width
    Define button_height.d=200 ; Text height
    
    Define fitted_text_width.d=ButtonImageGadget_1_width*set_x   ; Fitted text width  - Negative values available
    Define fitted_text_height.d=ButtonImageGadget_1_height*set_y ; Fitted text height - Negative values available
    
    ResizeWindow(window_ID, #PB_Ignore, #PB_Ignore, WindowWidth(window_ID), WindowWidth(window_ID)/1.5)

    SetMagicTextGadget_BF(gadget_1_ID,                      ; Gadget_ID - look the demo code for using
                          ButtonImageGadget_1_width*set_x,  ; Button width
                          ButtonImageGadget_1_height*set_y, ; Button height
                          ButtonImageGadget_1_width*1.3,    ; Text width
                          ButtonImageGadget_1_height*1.8,   ; Text height
                          ButtonImageGadget_1_x*set_x,      ; Gadget output x pos
                          ButtonImageGadget_1_y*set_y,      ; Gadget output y pos
                          "",                               ; Text
                          -1,                               ; Text stretching x - Headline mode
                          -1,                               ; Text stretching y - Headline mode
                          -1,                               ; Padding x
                          -1,                               ; Padding_y
                          -1,                               ; Text color
                          -1)                               ; Background color  
  EndProcedure
  
  ; ===========================================================================
  Procedure CreateGUI_1(window_x, window_y, window_width_output, window_height_output)
    
    ; =============== Calculate the output position and size =================
    Deactivate_DPI_ResizeFactor_BF(1) ; We use here the DPI aware compiler option
    window_width_output*DPI_ResizeFactor_BF() : window_height_output*DPI_ResizeFactor_BF()
    If window_x=-1 : window_x=WindowX(window_ID)-(window_width_output-WindowWidth(window_ID))/2
      Else : window_x*DPI_ResizeFactor_BF() : EndIf
    If window_y=-1 : window_y=WindowY(window_ID)-(window_height_output-WindowHeight(window_ID))/2
      Else : window_y*DPI_ResizeFactor_BF() : EndIf
    ResizeWindow(window_ID, window_x, window_y, window_width_output, window_height_output)
    
    ; ================= Init the resize procedure callback ======================
    BindEvent(#PB_Event_SizeWindow, @WindowResizing_BindEvent_CreateGUI_1())
    
    ; ====== Init all gadgets - Call simple the resize callback procedure =======
    Macro Refresh_all_Gadgets ; Refresh the gadgets
      Get_all_Window_Events_BF(1) ; Activate for fixing output problems with complex text and textboxes on MacOS 
                                  ; For using inside a callback procedure deactivate 
      WindowResizing_BindEvent_CreateGUI_1()
      Get_all_Window_Events_BF(0) ; Activate for fixing output problems with complex text and textboxes on MacOS 
                                  ; For using inside a callback procedure deactivate 
    EndMacro
    
    ; ============================= Show the result =============================
    Deactivate_DPI_ResizeFactor_BF(0)
    Refresh_all_Gadgets    
    HideWindow(window_ID, 0)
    
    Repeat
      Define win_event=WaitWindowEvent()
    Until win_event=#PB_Event_CloseWindow
    
  EndProcedure
  
EndModule
UseModule CreateGUI_1

CompilerIf #PB_Compiler_IsMainFile 
  ; ========================== Run the module, ====================================
  ; Debug DPI_ResizeFactor_BF() ; Get the actual DPI resize factor  
  ; Deactivate_DPI_ResizeFactor_BF(1) ; This function deactivate the DPI aware feature 
  CreateGUI_1(-1, -1, 900, 550) ; x, y, width, height - x=-1 center the output x - y=-1 center the output y
  
CompilerEndIf
Stand alone

Code: Select all

EnableExplicit

DeclareModule CreateGUI_1
  EnableExplicit
  Declare CreateGUI_1(window_x, window_y, window_width_output, window_height_output)
EndDeclareModule

Module CreateGUI_1
  
  Global window_width_developing=620 ; Developing size
  Global window_height_developing=400
  
  Global window_min_width=200 ; Minimum window size
  Global window_min_height=150
  
  Global window_x, window_y, window_width_output, window_height_output
  Global window_flags=#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_Invisible
  Global window_ID=OpenWindow(#PB_Any, 0, 0, window_width_developing, window_height_developing,
                              "Dynamic Window and GUI creating", Window_flags)
  WindowBounds(window_ID, window_min_width, window_min_height, #PB_Ignore, #PB_Ignore)
  Global get_all_window_events ; Auxiliary variable for callback procedure WindowEvent handling
  
  ; Create ButtonImageGadget _1 for using ==========================================
  Global ButtonImageGadget_1_width=300
  Global ButtonImageGadget_1_height=350
  Global ButtonImageGadget_1_x=WindowWidth(window_ID)/2-ButtonImageGadget_1_width/2
  Global ButtonImageGadget_1_y=WindowHeight(window_ID)/2-ButtonImageGadget_1_height/2
  
  Global image_ID=CreateImage(#PB_Any, 120, 120, 24, #Red)
  
  Global Gadget_1_ID=ButtonImageGadget(#PB_Any,
                                       ButtonImageGadget_1_x,      ; Gadget output x pos
                                       ButtonImageGadget_1_y,      ; Gadget output y pos
                                       ButtonImageGadget_1_width,  ; Gadget width
                                       ButtonImageGadget_1_height, ImageID(image_ID)) ; Gadget height
                                                                                      ; ############## Resize procedure for callback ##############################
  Procedure WindowResizing_BindEvent_CreateGUI_1()
    
    ; ============= Init the scaling variables ==============
    Global set_x.d=100/window_width_developing*WindowWidth(window_ID)/100
    Global set_y.d=100/window_height_developing*WindowHeight(window_ID)/100
    
    Define button_width.d=600  ; Text width
    Define button_height.d=200 ; Text height
    
    Define fitted_text_width.d=ButtonImageGadget_1_width*set_x   ; Fitted text width  - Negative values available
    Define fitted_text_height.d=ButtonImageGadget_1_height*set_y ; Fitted text height - Negative values available
    
    ResizeWindow(window_ID, #PB_Ignore, #PB_Ignore, WindowWidth(window_ID), WindowWidth(window_ID)/1.5)
    
    ResizeGadget(gadget_1_ID,
                 ButtonImageGadget_1_x*set_x,
                 ButtonImageGadget_1_y*set_y,
                 ButtonImageGadget_1_width*set_x,  
                 ButtonImageGadget_1_height*set_y)
  EndProcedure
  
  ; ===========================================================================
  Procedure CreateGUI_1(window_x, window_y, window_width_output, window_height_output)
    
    ; ================= Init the resize procedure callback ======================
    BindEvent(#PB_Event_SizeWindow, @WindowResizing_BindEvent_CreateGUI_1())
    
    ; ====== Init all gadgets - Call simple the resize callback procedure =======
    Macro Refresh_all_Gadgets ; Refresh the gadgets
      WindowResizing_BindEvent_CreateGUI_1()
    EndMacro
    
    ; ============================= Show the result =============================
    Refresh_all_Gadgets   
    HideWindow(window_ID, 0)
    
    Repeat
      Define win_event=WaitWindowEvent()
    Until win_event=#PB_Event_CloseWindow
    
  EndProcedure
  
EndModule
UseModule CreateGUI_1

CompilerIf #PB_Compiler_IsMainFile
  ; ========================== Run the module, ====================================
  ; Debug DPI_ResizeFactor_BF() ; Get the actual DPI resize factor 
  ; Deactivate_DPI_ResizeFactor_BF(1) ; This function deactivate the DPI aware feature
  CreateGUI_1(-1, -1, 900, 550) ; x, y, width, height - x=-1 center the output x - y=-1 center the output y
  
CompilerEndIf

Re: WindowResizing flicker Bug - damage the running OS

Posted: Wed Oct 07, 2020 9:32 pm
by Saki
Hi, I'm doing another post here to register another malfunction caused by ResizeWindow.
If you call the small demo code above and maximize the window,
it is not possible to shrink it with the Maximize Gadget at the top of the window again.
I could not find the exact cause yet, but, the window is probably of the opinion that it is not yet maximized.
Remove you ResizeWindow it works again.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Mon Oct 19, 2020 3:11 pm
by Blue
CONFIRMED : Malfunctions described above on Windows 10 x64
Resizing the window causes strong flicker, and the Maximize button stops working once the window has been maximized.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Mon Oct 19, 2020 4:24 pm
by Mijikai
Can you test this callback?

Code: Select all

Procedure.i ResizeAndKeepAspect(hWnd.i,uMsg.i,wParam.i,lParam)
  Static aspect.f
  Protected *wr.RECT
  Protected wnd_w.i
  Protected wnd_h.i
  Select uMsg
    Case #WM_SIZING
      *wr = lParam
      wnd_w = (*wr\right - *wr\left)
      wnd_h = (*wr\bottom - *wr\top)
      If Not aspect
        aspect = wnd_h / wnd_w
      EndIf
      If (wnd_h / wnd_w) > aspect
        wnd_w = (wnd_h / aspect)
      Else
        wnd_h = (wnd_w * aspect)
      EndIf
      If wParam = #WMSZ_TOP|#WMSZ_TOPLEFT|#WMSZ_TOPRIGHT
        *wr\top = *wr\bottom - wnd_h
      Else
        *wr\bottom = *wr\top + wnd_h  
      EndIf
      If wParam = #WMSZ_LEFT|#WMSZ_TOPLEFT|#WMSZ_BOTTOMLEFT
        *wr\left = *wr\right - wnd_w
      Else
        *wr\right = *wr\left + wnd_w
      EndIf
    Case #WM_NCLBUTTONDOWN
      ;SystemParametersInfo_(#SPI_SETDRAGFULLWINDOWS,#Null,#Null,#SPIF_SENDWININICHANGE);optional - only show frame on resize
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Re: WindowResizing flicker Bug - damage the running OS

Posted: Mon Oct 19, 2020 6:09 pm
by Saki
Hi Mijikai

Running ResizeWindow() alone is enough to trigger the error irreversibly on the OS.
The wizzard code above just shows it very nicely, because he is extremely computationally
intensive and therefore everything runs relatively slow.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Mon Oct 19, 2020 7:42 pm
by JHPJHP
Windows 10
PureBasic 5.73 beta 2 (x86)
Saki/walbus wrote:...it is not possible to shrink it with the Maximize Gadget at the top of the window again.
The problem is having the ResizeWindow Function located in the binded event (#PB_Event_SizeWindow) Procedure: WindowResizing_BindEvent_CreateGUI_1

In addition, I'm not seeing any Gadget flicker after removing the ResizeWindow Function from the event triggered by resizing the window.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Mon Oct 19, 2020 8:32 pm
by Saki
The CallBack function is correct implemented, it should work.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Fri Oct 30, 2020 2:52 pm
by Fred
The standalone code works here. Unfortunately we need a smaller code showing the issue. We won't investigate the whole Gfx package.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Fri Oct 30, 2020 3:17 pm
by Saki
Hi Fred, yes, of course, its clear.
It is difficult, I can try if I can make a little code that shows the bug.
I couldn't do it so far, so I made the reference to the wizzard code, because you can see it there extremely well.
Look, when you run the stand alone code you don't notice anything, everything seems to be OK.
But when you run this Wizzard code afterwards, for example, it will flicker miserably, just like all other such codes.
"GFX_Wizzard_BF\Dynamic_Gadgets_with_MagicTextGadget_1_BF.pb"
It will only disappear when you restart the OS.
It seems, This problem is caused by all code that runs ResizeWindow in a CallBack.
It was very difficult to find cause and effect here.
I use a 4k monitor, the effect is much more pronounced here, probably because of the much larger amount of data.
If I go to 1920x1080 it is much weaker.

A difficult thing.
Thanks for looking at it, though.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Fri Oct 30, 2020 4:42 pm
by cas
JHPJHP wrote:The problem is having the ResizeWindow Function located in the binded event (#PB_Event_SizeWindow)
Exactly, this is bad coding practice.
Blue wrote:Maximize button stops working once the window has been maximized.
OS waits to see what will callback return before updating new dimensions and if you call WindowWidth/Height before that callback is done (as is case here because you call it inside that callback) then it returns old values and window is basically locked in always maximized state.

There is also a problem when you resize only with top or bottom border.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Fri Oct 30, 2020 4:57 pm
by Saki
Hi, cas,
yes, but that is not the point at all.
That the shrink doesn't work anymore is no problem and the cause is clearly visible.
I only brought it up because I noticed it, but I was not surprised.
How do you want to change a window with its contents on demand proportionally without a callback ?
There is no bad or good programming style, because this is the only way, there is no other way.
But you don't have to have it, it's a gimmick.
The only problem is that if you do it, something in the running OS gets damaged.

There are just certain things that you cannot solve elegantly, even if you want to.

It's also nothing very bad, if you know it, don't use it, the bug won't be triggered.

Re: WindowResizing flicker Bug - damage the running OS

Posted: Fri Oct 30, 2020 6:45 pm
by #NULL
I just tried one of your above codes on linux and just get a window that doesn't draw/update properly and becomes unresponsive. A quick inquiry shows me dozens of uses of [Wait]WindowEvent() in various different places including swallowing events without processing them, which tells me... I don't even know where to start. Probably not a PB bug.