Source code for spacr.qt.widgets.cursor_policy
"""Keep the operating system's standard arrow in every interactive context."""
from __future__ import annotations
from PySide6.QtCore import QEvent, QObject, Qt
from PySide6.QtGui import QCursor
from PySide6.QtWidgets import QApplication, QWidget
from ..gil_priority import _watch_application_events
[docs]
def arrow_cursor(active=False):
"""Return the native OS arrow without customizing its artwork or size.
:param active: retained for compatibility; both states use the OS arrow.
:returns: a native arrow that follows the user's OS pointer preferences.
"""
return QCursor(Qt.ArrowCursor)
_POINTER_EVENTS = frozenset({
QEvent.CursorChange, QEvent.Enter, QEvent.Show, QEvent.MouseMove})
class _CursorPolicy(QObject):
"""Preserve gestures while suppressing application cursor substitutions."""
def __init__(self, application):
"""Bind the native-arrow policy to its application and guard recursive cursor events."""
super().__init__(application)
self._changing = False
def eventFilter(self, watched, event):
"""Restore the native arrow on pointer events without consuming the original gesture.
A ``Show`` of a widget that never had a cursor set on it is passed
over: such a widget shows its parent's cursor, which this policy has
already answered for, and a module screen's first show delivers one
``Show`` per child -- several thousand -- that used to read and
compare a cursor each (7 % of a slow module's first open).
"""
if self._changing:
return False
kind = event.type()
if kind not in _POINTER_EVENTS:
return False
if not isinstance(watched, QWidget):
return False
if (kind == QEvent.Show
and not watched.testAttribute(Qt.WA_SetCursor)
and QApplication.overrideCursor() is None):
return False
self._changing = True
try:
if watched.cursor().shape() != Qt.ArrowCursor:
watched.setCursor(arrow_cursor())
override = QApplication.overrideCursor()
if override is not None and override.shape() != Qt.ArrowCursor:
QApplication.changeOverrideCursor(arrow_cursor())
except RuntimeError:
pass
finally:
self._changing = False
return False
[docs]
def install_cursor_policy(application=None):
"""Install the native-arrow policy once; leave all gestures unchanged."""
app = application or QApplication.instance()
if app is None or getattr(app, '_spacr_cursor_policy', None) is not None:
return False
policy = _CursorPolicy(app)
app._spacr_cursor_policy = policy
_watch_application_events(app, policy, _POINTER_EVENTS)
for widget in QApplication.allWidgets():
policy.eventFilter(widget, QEvent(QEvent.CursorChange))
return True