|
13 | 13 | import subprocess |
14 | 14 | import winreg |
15 | 15 |
|
16 | | -from .base import Window as _Window, MonitorEventsListener as _MonitorEventsListener |
| 16 | +from . import base |
17 | 17 | from ...constants import APP_EXECUTABLE, PACKAGE_IDENTIFIER |
18 | 18 | from ...types import Rect, RectList |
19 | 19 | from ...version import VERSION |
|
49 | 49 |
|
50 | 50 | PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 |
51 | 51 |
|
| 52 | +DBT_DEVNODES_CHANGED = 0x0007 |
| 53 | + |
52 | 54 | BOOL = ctypes.wintypes.BOOL |
53 | 55 |
|
54 | 56 | DWORD = ctypes.wintypes.DWORD |
@@ -415,7 +417,7 @@ def relaunch_as_elevated() -> None: |
415 | 417 | sys.exit() |
416 | 418 |
|
417 | 419 |
|
418 | | -class Window(_Window): |
| 420 | +class Window(base.Window): |
419 | 421 | def __init__(self, hwnd: int) -> None: |
420 | 422 | self._hwnd = hwnd |
421 | 423 | self._handle = WindowHandle(self._hwnd) |
@@ -454,24 +456,31 @@ def size(self) -> tuple[int, int]: |
454 | 456 | return self._pid.size |
455 | 457 |
|
456 | 458 |
|
457 | | -class MonitorEventsListener(_MonitorEventsListener): |
458 | | - """Listen for monitor change events.""" |
| 459 | +class EventListener(base.EventListener): |
| 460 | + """Base Windows event listener. |
| 461 | +
|
| 462 | + Override the `check` method to implement this. |
| 463 | + """ |
459 | 464 |
|
460 | 465 | def __init__(self) -> None: |
461 | 466 | super().__init__() |
462 | 467 | self._hwnd = None # type: int | None |
463 | 468 |
|
| 469 | + def check(self, hwnd: int, msg: int, wparam: int, lparam: int) -> bool: |
| 470 | + """Determine if a specific event has been fired.""" |
| 471 | + return False |
| 472 | + |
464 | 473 | def run(self) -> None: |
465 | 474 | """Create and start the message listener.""" |
466 | 475 | def wndproc(hwnd: int, msg: int, wparam: int, lparam: int) -> int: |
467 | | - if msg in (WM_DISPLAYCHANGE, WM_DEVICECHANGE): |
| 476 | + if self.check(hwnd, msg, wparam, lparam): |
468 | 477 | self.trigger() |
469 | 478 | return user32.DefWindowProcW(hwnd, msg, wparam, lparam) |
470 | 479 |
|
471 | 480 | hinst = kernel32.GetModuleHandleW(None) |
472 | 481 | wndproc_c = WNDPROCTYPE(wndproc) |
473 | 482 |
|
474 | | - class_name = 'MouseTracksHiddenWindowClass' |
| 483 | + class_name = type(self).__name__ |
475 | 484 | wc = WNDCLASS() |
476 | 485 | wc.lpfnWndProc = wndproc_c |
477 | 486 | wc.lpszClassName = class_name |
@@ -501,6 +510,20 @@ def stop(self) -> None: |
501 | 510 | user32.PostMessageW(self._hwnd, WM_QUIT, 0, 0) |
502 | 511 |
|
503 | 512 |
|
| 513 | +class MonitorEventListener(EventListener): |
| 514 | + """Listen for monitor change events.""" |
| 515 | + |
| 516 | + def check(self, hwnd: int, msg: int, wparam: int, lparam: int) -> bool: |
| 517 | + return msg == WM_DISPLAYCHANGE |
| 518 | + |
| 519 | + |
| 520 | +class ControllerEventListener(EventListener): |
| 521 | + """Listen for controller change events.""" |
| 522 | + |
| 523 | + def check(self, hwnd: int, msg: int, wparam: int, lparam: int) -> bool: |
| 524 | + return msg == WM_DEVICECHANGE and wparam == DBT_DEVNODES_CHANGED |
| 525 | + |
| 526 | + |
504 | 527 | def prepare_application_icon(icon_path: Path | str) -> None: |
505 | 528 | """Register app so that setting an icon is possible.""" |
506 | 529 | ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(PACKAGE_IDENTIFIER) |
|
0 commit comments