Ticket #16865: mouse.py

File mouse.py, 3.3 KB (added by Tom Goddard, 4 months ago)

Python script to create a backing window on Acer 3d display that handles mouse events.

Line 
1# Allow mouse modes to work with mouse on Acer or Sony 3D displays.
2# Both these displays create a fullscreen window. This mouse mode support
3# works by creating a backing full-screen Qt window which receives the
4# mouse events.
5
6def enable_xr_mouse_modes(session):
7 screen = find_xr_screen(session)
8 from Qt.QtWidgets import QWidget
9 w = QWidget()
10 session._xr_mouse_backing_window = w
11 w.move(screen.geometry().topLeft())
12 w.showFullScreen()
13 w.mousePressEvent = lambda e: dispatch_mouse_event(e, "mouse_down", session)
14 w.mouseMoveEvent = lambda e: dispatch_mouse_event(e, "mouse_drag", session)
15 w.mouseReleaseEvent = lambda e: dispatch_mouse_event(e, "mouse_up", session)
16 w.mouseDoubleClickEvent = lambda e: dispatch_mouse_event(e, "mouse_double_click", session)
17 w.wheelEvent = lambda e: dispatch_wheel_event(e, session)
18
19def dispatch_mouse_event(event, action, session):
20 '''
21 Convert a mouse event from 3D screen coordinates to
22 graphics pane coordinates and dispatch it.
23 '''
24 p = event.position()
25 gx, gy = map_event_coordinates(p.x(), p.y(), session)
26 e = repositioned_event(event, gx, gy)
27 session.ui.mouse_modes._dispatch_mouse_event(e, action)
28
29def dispatch_wheel_event(event, session):
30 '''
31 Convert a wheel event from 3D screen coordinates to
32 graphics pane coordinates and dispatch it.
33 '''
34 p = event.position()
35 gx, gy = map_event_coordinates(p.x(), p.y(), session)
36 e = repositioned_event(event, gx, gy)
37 session.ui.mouse_modes._wheel_event(e)
38
39def map_event_coordinates(x, y, session):
40 '''
41 Handle different aspect ratio of 3D screen window and
42 graphics window. Graphics window has cropped version
43 of 3D window image.
44 '''
45 w3d = session._xr_mouse_backing_window
46 w, h = w3d.width(), w3d.height()
47 gw, gh = session.main_view.window_size
48 if w == 0 or h == 0 or gw == 0 or gh == 0:
49 return x, y
50 fx,fy = x/w, y/h
51 af = w*gh/(h*gw)
52 if af > 1:
53 afx = 0.5 + af * (fx - 0.5)
54 afy = fy
55 else:
56 afx = fx
57 afy = 0.5 + (1/af) * (fy - 0.5)
58 gx, gy = afx * gw, afy * gh
59 return gx, gy
60
61def repositioned_event(event, x, y):
62 from Qt.QtGui import QMouseEvent, QWheelEvent
63 from Qt.QtCore import QPointF
64 pos = QPointF(x, y)
65 if isinstance(event, QMouseEvent):
66 e = QMouseEvent(event.type(), pos, event.globalPosition(), event.button(), event.buttons(), event.modifiers(), event.device())
67 elif isinstance(event, QWheelEvent):
68 e = QWheelEvent(pos, event.globalPosition(), event.pixelDelta(), event.angleDelta(), event.buttons(), event.modifiers(), event.phase(), event.inverted(), device = event.device())
69 else:
70 raise RuntimeError(f'Event type is not mouse or wheel event {event}')
71 return e
72
73def find_xr_screen(session):
74 known_screen_models = ['ASV27-2P']
75 screens = session.ui.screens()
76 for screen in screens:
77 if screen.model() in known_screen_models:
78 return screen
79 mnames = [screen.model() for screen in screens]
80 msg = f'Could not find Acer 3D screen model {", ".join(known_screen_models)} , only found {", ".join(mnames)}'
81 raise RuntimeError(msg)
82
83enable_xr_mouse_modes(session)
84
85# When OpenXR turned off delete the backing window with
86# session._xr_mouse_backing_window.deleteLater()
87# session._xr_mouse_backing_window = None