Borderless “fake window” using Engine3D does not behave like a normal Windows window

Advanced game related topics
User avatar
skinkairewalker
Addict
Addict
Posts: 827
Joined: Fri Dec 04, 2015 9:26 pm

Borderless “fake window” using Engine3D does not behave like a normal Windows window

Post by skinkairewalker »

Hello everyone,

I’m experimenting with creating a custom borderless window using PureBasic Engine3D, simulating a normal Windows window with:
  • a fake title bar drawn with sprites
  • a close button
  • manual window dragging using ResizeWindow()
  • continuous 3D rendering via OpenWindowedScreen()
The main goal is to avoid the Windows freeze that happens when resizing or moving normal bordered windows, and to have full control over the UI.

Visually, the code works, but the window does not behave like a normal Windows window, and I’m not sure whether this is a limitation of the Engine3D or if I’m missing a better architectural approach.

Issues observed
  • The window does not respond exactly like a standard Windows window
    (focus behavior, dragging feel, system interaction)
  • WindowEvent() handling feels limited or inconsistent when combined with
    OpenWindowedScreen()
  • During some interactions (losing focus, clicking outside, fast dragging),
    the behavior is not consistent
  • I’m unsure if this kind of “fake window” is:
    • inherently limited by Engine3D
    • or if there is a recommended pattern to implement this more correctly in PureBasic

    Code :

    Code: Select all

    #WIN_W = 800
    #WIN_H = 600
    #TITLE_H = 32
    #BTN_SIZE = 24
    
    InitEngine3D()
    InitSprite()
    InitKeyboard()
    InitMouse()
    
    OpenWindow(0, 200, 200, #WIN_W, #WIN_H, "",
      #PB_Window_BorderLess)
    
    OpenWindowedScreen(WindowID(0), 0, 0, #WIN_W, #WIN_H, 0, 0, 0)
    
    CreateSprite(1, #WIN_W, #TITLE_H)
    StartDrawing(SpriteOutput(1))
      Box(0, 0, #WIN_W, #TITLE_H, RGB(40,40,40))
    StopDrawing()
    
    CreateSprite(2, #BTN_SIZE, #BTN_SIZE)
    StartDrawing(SpriteOutput(2))
      Box(0, 0, #BTN_SIZE, #BTN_SIZE, RGB(120,40,40))
    StopDrawing()
    
    Global dragging = #False
    Global dragOffX, dragOffY
    
    Repeat
      ExamineMouse()
      While WindowEvent() : Wend
    
      mx = MouseX()
      my = MouseY()
    
      If MouseButton(#PB_MouseButton_Left)
        If my < #TITLE_H And dragging = #False
          dragging = #True
          dragOffX = DesktopMouseX() - WindowX(0)
          dragOffY = DesktopMouseY() - WindowY(0)
        EndIf
      Else
        dragging = #False
      EndIf
    
      If dragging
        ResizeWindow(0,
          DesktopMouseX() - dragOffX,
          DesktopMouseY() - dragOffY,
          #PB_Ignore, #PB_Ignore)
      EndIf
    
      RenderWorld()
      DisplaySprite(1, 0, 0)
      DisplaySprite(2, #WIN_W - #BTN_SIZE - 6, 4)
    
      FlipBuffers()
      Delay(1)
    Until KeyboardPushed(#PB_Key_Escape)
    
    End
    
    

    The final goal is to avoid my game freezing when moving a native Windows window, and also to gain more control over the window behavior. Does anyone know how this code could be improved to work more reliably?
miso
Enthusiast
Enthusiast
Posts: 673
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Borderless “fake window” using Engine3D does not behave like a normal Windows window

Post by miso »

Hello SkinkaireWalker!

First, you will need a camera, it is not presented in the example.

Regarding mouse. There are two kind of mouse with pb, one is OS mouse, the other is some kind of raw mouse.
When you call examinemouse() you lose desktopmouse. Use only one of the two.
( with desktopmouse, you don't call examinemouse )

If you use fullscreen borderless, you can check focuslost, and switch back to desktopmouse using the releasemouse(#true/#false) command.
Calling examinemouse() automatically switch to rawmouse.

I hope that helped.

miso
miso
Enthusiast
Enthusiast
Posts: 673
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Borderless “fake window” using Engine3D does not behave like a normal Windows window

Post by miso »

I use a procedure something like this for alt tabbing from windowed fullscreen.

Code: Select all

#MAINLOOP_DELAY = 0

;=====================================================
; Processes windows events
; Delays(0), and examines the keyboard and mouse
; Handles proper Alt+Tabbing, program sleeps while not 
; active
;=====================================================
  Procedure SweepEvents()
    Protected w_event.i
    Delay(#MAINLOOP_DELAY)
    Repeat 
      w_event = WindowEvent() : If w_event = #PB_Event_CloseWindow : End : EndIf
      If w_event = #PB_Event_DeactivateWindow
        ReleaseMouse(#True)
        Repeat
          w_event = WaitWindowEvent(1) :If w_event = #PB_Event_CloseWindow : End : EndIf
        Until w_event = #PB_Event_ActivateWindow
        ReleaseMouse(#False)
      EndIf
    Until Not w_event
    ExamineKeyboard()
    ExamineMouse()
  EndProcedure


#WIN_W = 800
#WIN_H = 600
#TITLE_H = 32
#BTN_SIZE = 24

InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()

OpenWindow(0, 200, 200, #WIN_W, #WIN_H, "",
  #PB_Window_BorderLess)

OpenWindowedScreen(WindowID(0), 0, 0, #WIN_W, #WIN_H, 0, 0, 0)

CreateSprite(1, #WIN_W, #TITLE_H)
StartDrawing(SpriteOutput(1))
  Box(0, 0, #WIN_W, #TITLE_H, RGB(40,40,40))
StopDrawing()

CreateSprite(2, #BTN_SIZE, #BTN_SIZE)
StartDrawing(SpriteOutput(2))
  Box(0, 0, #BTN_SIZE, #BTN_SIZE, RGB(120,40,40))
StopDrawing()

Global dragging = #False
Global dragOffX, dragOffY
CreateCamera(1,0,0,100,100)
Repeat
  ;ExamineMouse():ExamineKeyboard()
  SweepEvents()
  
  While WindowEvent() : Wend

  mx = MouseX()
  my = MouseY()

  If MouseButton(#PB_MouseButton_Left)
    If my < #TITLE_H And dragging = #False
      dragging = #True
      dragOffX = DesktopMouseX() - WindowX(0)
      dragOffY = DesktopMouseY() - WindowY(0)
    EndIf
  Else
    dragging = #False
  EndIf

  If dragging
    ResizeWindow(0,
      DesktopMouseX() - dragOffX,
      DesktopMouseY() - dragOffY,
      #PB_Ignore, #PB_Ignore)
  EndIf

  RenderWorld()
  DisplaySprite(1, 0, 0)
  DisplaySprite(2, #WIN_W - #BTN_SIZE - 6, 4)

  FlipBuffers()
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape)

End

User avatar
minimy
Addict
Addict
Posts: 845
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Borderless “fake window” using Engine3D does not behave like a normal Windows window

Post by minimy »

Hello friends, may be this can help you a little.

As miso say, you are mixing two concepts, 1 is the OS API, the other is the 3D engine.
To work with OS API you need use ReleaseMouse(#true), after this you have the real mouse.
In my opinion, if you are working in a window, for your project i thiink is bad idea work with sprites, better if use canvas and control it direct from the API OS. Canvas is very friendly to handle special gadgets.
Process your canvas here: 'Repeat: ev=WindowEvent(): Until ev=0'. Then you use real desktop coords to move the window.
I hope this can help you.

Code: Select all

#WIN_W = 800: #WIN_H = 600
#TITLE_H = 32: #BTN_SIZE = 24
Global dragging = #False
Global dragOffX, dragOffY

;sys
InitEngine3D():InitSprite():InitKeyboard():InitMouse()
OpenWindow(0, 200, 200, #WIN_W, #WIN_H, "", #PB_Window_BorderLess): OpenWindowedScreen(WindowID(0), 0, 0, #WIN_W, #WIN_H, 0, 0, 0,#PB_Screen_SmartSynchronization)

;3D
CreateCamera(0,0,0,100,100): CameraBackColor(0,$444444):MoveCamera(0,0,30,-100): CameraLookAt(0,0,0,0)
CreateLight(0,$ffffff,10,100,30,#PB_Light_Point)
e=CreateEntity(#PB_Any,MeshID(CreatePlane(#PB_Any,100,100,1,1,1,1)),MaterialID(CreateMaterial(#PB_Any,#Null,$ff007700)))

;sprites
CreateSprite(1, #WIN_W, #TITLE_H): StartDrawing(SpriteOutput(1)): Box(0, 0, #WIN_W, #TITLE_H, RGB(40,40,40)): StopDrawing()
CreateSprite(2, #BTN_SIZE, #BTN_SIZE): StartDrawing(SpriteOutput(2)): Box(0, 0, #BTN_SIZE, #BTN_SIZE, RGB(120,40,40)): StopDrawing()

ReleaseMouse(#True); show the real mouse

Repeat
  Repeat: ev=WindowEvent(): Until ev=0

  ExamineMouse():ExamineKeyboard()
  mx = MouseX(): my = MouseY()

  If MouseButton(#PB_MouseButton_Left)
    If my < #TITLE_H And dragging = #False
      dragging = #True: dragOffX = DesktopMouseX() - WindowX(0): dragOffY = DesktopMouseY() - WindowY(0)
    EndIf
  Else
    dragging = #False
  EndIf

  If dragging
    ResizeWindow(0, DesktopMouseX() - dragOffX, DesktopMouseY() - dragOffY, #PB_Ignore, #PB_Ignore)
  EndIf

  RenderWorld()
  DisplaySprite(1, 0, 0)
  DisplaySprite(2, #WIN_W - #BTN_SIZE - 6, 4)

  FlipBuffers()
  Delay(1)
  If KeyboardPushed(#PB_Key_Escape):quit=1:EndIf
Until quit=1

End

If translation=Error: reply="Sorry, Im Spanish": Endif
Post Reply