This had bothered me for a long time and so I wrote a patch for Linux.
With full screen, RestoreMouse must be called at the end, otherwise the mouse cursor for the desktop is destroyed.
Also runs on Linux host system (Tested on Raspberry PI)
Features:
- Auto scrolling for mouse delta at the edge of the screen
- Changing the mouse cursor on the screen
- Changing the mouse cursor for mouse release mode
Update v1.02.2
- Added: FrameDelay for save cpu usage (Needs only with OpenWindowedScreen)
Update v1.03.1
- Bugfix mouse delta direction and menu height
Update v1.03.2
- Limit windowed screen mouse position to screen size (auto scroll area now inside screen)
Screen3DMousePatch.pb
Code: Select all
;-TOP
; Comment : Linux Screen3DMousePatch
; Author : mk-soft
; Version : v1.03.2
; Create : 02.09.2022
; Update : 10.09.2022
; Link : https://www.purebasic.fr/english/viewtopic.php?t=79766
; Info:
;
; - Call InitWindowMouse after OpenScreen or OpenWindowedScreen
; - Call RestoreMouse at end of program to restore desktop mouse cursor (Needs only with OpenScreen)
; - Call FrameDelay for save cpu usage (Needs only with OpenWindowedScreen)
; - Enumeration of cursor type:
; * Link: "https://docs.gtk.org/gdk3/enum.CursorType.html"
; * Blank: -2
;
; - ScrollRange:
; * Auto scrolling range for mouse delta
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
ImportC ""
gtk_widget_get_window(widget)
gdk_get_default_root_window()
gdk_window_get_cursor(window)
EndImport
Structure udtMouseData
IsWindow.i
Window.i
WindowID.i
WindowGDK.i
IsMenu.i
CursorDefault.i
CursorScreen.i
CursorState.i
x.l
y.l
lastX.l
lastY.l
deltaX.l
deltaY.l
menuHeight.l
scrollRange.l
screenWidth.l
screenHeight.l
EndStructure
Global MyMouseData.udtMouseData
Procedure InitWindowMouse(Window = 0, CursorDefault = 0, CursorScreen = 130, ScrollRange = 25)
Protected PosX.l, PosY.l
With MyMouseData
; Get Window Data
If IsWindow(Window)
\IsWindow = #True
\Window = Window
\WindowID = WindowID(Window)
\WindowGDK = gtk_widget_get_window(\WindowID)
If IsMenu(0)
\IsMenu = #True
\menuHeight = MenuHeight()
EndIf
Else
\WindowGDK = gdk_get_default_root_window()
EndIf
; Define Cursor Data
If CursorDefault
\CursorDefault = gdk_cursor_new_(CursorDefault)
Else
\CursorDefault = gdk_window_get_cursor(\WindowGDK)
EndIf
\CursorScreen = gdk_cursor_new_(CursorScreen); Blank = -2
gdk_window_set_cursor_(\WindowGDK, \CursorScreen)
; Scroll Range
\scrollRange = ScrollRange
\screenWidth = ScreenWidth()
\screenHeight = ScreenHeight()
; Get Positions
If IsWindow(Window)
gtk_widget_get_pointer_(\WindowID, @PosX, @PosY)
\lastX = PosX
\lastY = PosY
Else
\x = DesktopMouseX()
\y = DesktopMouseY()
\lastX = \x
\lastY = \y
EndIf
EndWith
ProcedureReturn #True
EndProcedure
Procedure RestoreMouse()
Protected window, cursor
If OpenWindow(0, 0, 0, 0, 0, "Restore Mouse Cursor", #PB_Window_Invisible)
window = gdk_get_default_root_window()
cursor = gdk_cursor_new_(68)
If window
gdk_window_set_cursor_(window, cursor)
EndIf
EndIf
EndProcedure
; ----
Procedure.f MyMouseX()
ProcedureReturn MyMouseData\x
EndProcedure
Procedure.f MyMouseY()
ProcedureReturn MyMouseData\y
EndProcedure
Procedure.f MyMouseDeltaX()
ProcedureReturn MyMouseData\deltaX
EndProcedure
Procedure.f MyMouseDeltaY()
ProcedureReturn MyMouseData\deltaY
EndProcedure
Procedure MyReleaseMouse(State)
With MyMouseData
\CursorState = State
If \WindowGDK
If State
gdk_window_set_cursor_(\WindowGDK, \CursorDefault)
Else
gdk_window_set_cursor_(\WindowGDK, \CursorScreen)
EndIf
EndIf
EndWith
EndProcedure
Procedure MyExamineMouse()
Protected PosX.l, PosY.l
With MyMouseData
If \IsWindow
gtk_widget_get_pointer_(\WindowID, @PosX, @PosY)
If \IsMenu
PosY - \menuHeight
EndIf
If PosX < 0
PosX = 0
ElseIf PosX >= \screenWidth
PosX = \screenWidth - 1
EndIf
If PosY < 0
PosY = 0
ElseIf PosY >= \screenHeight
PosY = \screenHeight - 1
EndIf
Else
PosX = DesktopMouseX()
PosY = DesktopMouseY()
EndIf
\x = PosX
\y = PosY
If \CursorState
\deltaX = 0
\deltaY = 0
Else
\deltaX = PosX - \lastX
\deltaY = PosY - \lastY
EndIf
\lastX = PosX
\lastY = PosY
If PosX < \scrollRange
\lastX = \scrollRange
If \deltaX > \scrollRange
\deltaX = \scrollRange
EndIf
ElseIf PosX > \screenWidth - \scrollRange
\lastX = \screenWidth - \scrollRange
If \deltaX < -\scrollRange
\deltaX = -\scrollRange
EndIf
Else
\lastX = PosX
EndIf
If PosY < \scrollRange
\lastY = \scrollRange
If \deltaY > \scrollRange
\deltaY = \scrollRange
EndIf
ElseIf PosY > \screenHeight - \scrollRange
\lastY = \screenHeight - \scrollRange
If \deltaY < -\scrollRange
\deltaY = -\scrollRange
EndIf
Else
\lastY = PosY
EndIf
EndWith
ProcedureReturn #True
EndProcedure
;-- Macros
Macro MouseX()
MyMouseX()
EndMacro
Macro MouseY()
MyMouseY()
EndMacro
Macro MouseDeltaX()
MyMouseDeltaX()
EndMacro
Macro MouseDeltaY()
MyMouseDeltaY()
EndMacro
Macro ReleaseMouse(State)
MyReleaseMouse(State)
EndMacro
Macro ExamineMouse()
MyExamineMouse()
EndMacro
CompilerElse
Procedure InitWindowMouse(Window = 0, CursorDefault = 0, CursorScreen = 130, ScrollRange = 25)
; do nothing
EndProcedure
Procedure RestoreMouse()
; do nothing
EndProcedure
CompilerEndIf
Procedure FrameDelay(Frames = 30)
Static time
Protected diff_time, delay_time
If time
diff_time = ElapsedMilliseconds() - time
delay_time = (1000 / Frames) - diff_time
If delay_time > 0
Delay(delay_time)
EndIf
EndIf
time = ElapsedMilliseconds()
EndProcedure
;-- End