|
9 | 9 |
|
10 | 10 | from dataclasses import dataclass |
11 | 11 | from typing import ( |
| 12 | + Any, |
12 | 13 | List, |
13 | 14 | Optional, |
14 | 15 | ) |
|
30 | 31 | import NVDAState |
31 | 32 |
|
32 | 33 |
|
| 34 | +def __getattr__(attrName: str) -> Any: |
| 35 | + """Module level `__getattr__` used to preserve backward compatibility. |
| 36 | + """ |
| 37 | + if attrName == "post_windowMessageReceipt" and NVDAState._allowDeprecatedAPI(): |
| 38 | + from winAPI.messageWindow import pre_handleWindowMessage |
| 39 | + log.warning( |
| 40 | + "core.post_windowMessageReceipt is deprecated, " |
| 41 | + "use winAPI.messageWindow.pre_handleWindowMessage instead." |
| 42 | + ) |
| 43 | + return pre_handleWindowMessage |
| 44 | + raise AttributeError(f"module {repr(__name__)} has no attribute {repr(attrName)}") |
| 45 | + |
| 46 | + |
| 47 | + |
33 | 48 | # inform those who want to know that NVDA has finished starting up. |
34 | 49 | postNvdaStartup = extensionPoints.Action() |
35 | 50 |
|
|
38 | 53 | #: The thread identifier of the main thread. |
39 | 54 | mainThreadId = threading.get_ident() |
40 | 55 |
|
41 | | -#: Notifies when a window message has been received by NVDA. |
42 | | -#: This allows components to perform an action when several system events occur, |
43 | | -#: such as power, screen orientation and hardware changes. |
44 | | -#: Handlers are called with three arguments. |
45 | | -#: @param msg: The window message. |
46 | | -#: @type msg: int |
47 | | -#: @param wParam: Additional message information. |
48 | | -#: @type wParam: int |
49 | | -#: @param lParam: Additional message information. |
50 | | -#: @type lParam: int |
51 | | -# TODO: move to winAPI.messageWindow |
52 | | -post_windowMessageReceipt = extensionPoints.Action() |
53 | | - |
54 | 56 | _pump = None |
55 | 57 | _isPumpPending = False |
56 | 58 |
|
@@ -553,126 +555,9 @@ def onEndSession(evt): |
553 | 555 | # the GUI mainloop must be running for this to work so delay it |
554 | 556 | wx.CallAfter(audioDucking.initialize) |
555 | 557 |
|
556 | | - from winAPI.messageWindow import WindowMessage |
557 | | - from winAPI import sessionTracking |
558 | | - import winUser |
559 | | - # #3763: In wxPython 3, the class name of frame windows changed from wxWindowClassNR to wxWindowNR. |
560 | | - # NVDA uses the main frame to check for and quit another instance of NVDA. |
561 | | - # To remain compatible with older versions of NVDA, create our own wxWindowClassNR. |
562 | | - # We don't need to do anything else because wx handles WM_QUIT for all windows. |
563 | | - import windowUtils |
564 | | - # TODO: move to winAPI.messageWindow |
565 | | - class MessageWindow(windowUtils.CustomWindow): |
566 | | - className = u"wxWindowClassNR" |
567 | | - # Windows constants for power / display changes |
568 | | - # TODO: move to winAPI |
569 | | - PBT_APMPOWERSTATUSCHANGE = 0xA |
570 | | - UNKNOWN_BATTERY_STATUS = 0xFF |
571 | | - AC_ONLINE = 0X1 |
572 | | - NO_SYSTEM_BATTERY = 0X80 |
573 | | - #States for screen orientation |
574 | | - # TODO: move to winAPI, turn to Enum |
575 | | - ORIENTATION_NOT_INITIALIZED = 0 |
576 | | - ORIENTATION_PORTRAIT = 1 |
577 | | - ORIENTATION_LANDSCAPE = 2 |
578 | | - |
579 | | - def __init__(self, windowName=None): |
580 | | - super(MessageWindow, self).__init__(windowName) |
581 | | - self.oldBatteryStatus = None |
582 | | - self.orientationStateCache = self.ORIENTATION_NOT_INITIALIZED |
583 | | - self.orientationCoordsCache = (0,0) |
584 | | - self.handlePowerStatusChange() |
585 | | - |
586 | | - # Call must be paired with a call to sessionTracking.unregister |
587 | | - self._isSessionTrackingRegistered = sessionTracking.register(self.handle) |
588 | | - |
589 | | - def warnIfSessionTrackingNotRegistered(self) -> None: |
590 | | - if self._isSessionTrackingRegistered: |
591 | | - return |
592 | | - failedToRegisterMsg = _( |
593 | | - # Translators: This is a warning to users, shown if NVDA cannot determine if |
594 | | - # Windows is locked. |
595 | | - "NVDA failed to register session tracking. " |
596 | | - "While this instance of NVDA is running, " |
597 | | - "your desktop will not be secure when Windows is locked. " |
598 | | - "Restart NVDA? " |
599 | | - ) |
600 | | - if wx.YES == gui.messageBox( |
601 | | - failedToRegisterMsg, |
602 | | - # Translators: This is a warning to users, shown if NVDA cannot determine if |
603 | | - # Windows is locked. |
604 | | - caption=_("NVDA could not start securely."), |
605 | | - style=wx.ICON_ERROR | wx.YES_NO, |
606 | | - ): |
607 | | - restart() |
608 | | - |
609 | | - def destroy(self): |
610 | | - """ |
611 | | - NVDA must unregister session tracking before destroying the message window. |
612 | | - """ |
613 | | - if self._isSessionTrackingRegistered: |
614 | | - # Requires an active message window and a handle to unregister. |
615 | | - sessionTracking.unregister(self.handle) |
616 | | - super().destroy() |
617 | | - |
618 | | - def windowProc(self, hwnd, msg, wParam, lParam): |
619 | | - post_windowMessageReceipt.notify(msg=msg, wParam=wParam, lParam=lParam) |
620 | | - if msg == WindowMessage.POWER_BROADCAST and wParam == self.PBT_APMPOWERSTATUSCHANGE: |
621 | | - self.handlePowerStatusChange() |
622 | | - elif msg == winUser.WM_DISPLAYCHANGE: |
623 | | - self.handleScreenOrientationChange(lParam) |
624 | | - elif msg == WindowMessage.WTS_SESSION_CHANGE: |
625 | | - # If we are receiving WTS_SESSION_CHANGE events, _isSessionTrackingRegistered should be True |
626 | | - sessionTracking.handleSessionChange(sessionTracking.WindowsTrackedSession(wParam), lParam) |
627 | | - |
628 | | - def handleScreenOrientationChange(self, lParam): |
629 | | - # TODO: move to winAPI |
630 | | - import ui |
631 | | - # Resolution detection comes from an article found at https://msdn.microsoft.com/en-us/library/ms812142.aspx. |
632 | | - #The low word is the width and hiword is height. |
633 | | - width = winUser.LOWORD(lParam) |
634 | | - height = winUser.HIWORD(lParam) |
635 | | - self.orientationCoordsCache = (width,height) |
636 | | - if width > height: |
637 | | - # If the height and width are the same, it's actually a screen flip, and we do want to alert of those! |
638 | | - if self.orientationStateCache == self.ORIENTATION_LANDSCAPE and self.orientationCoordsCache != (width,height): |
639 | | - return |
640 | | - #Translators: The screen is oriented so that it is wider than it is tall. |
641 | | - ui.message(_("Landscape" )) |
642 | | - self.orientationStateCache = self.ORIENTATION_LANDSCAPE |
643 | | - else: |
644 | | - if self.orientationStateCache == self.ORIENTATION_PORTRAIT and self.orientationCoordsCache != (width,height): |
645 | | - return |
646 | | - #Translators: The screen is oriented in such a way that the height is taller than it is wide. |
647 | | - ui.message(_("Portrait")) |
648 | | - self.orientationStateCache = self.ORIENTATION_PORTRAIT |
649 | | - |
650 | | - def handlePowerStatusChange(self): |
651 | | - # TODO: move to winAPI |
652 | | - #Mostly taken from script_say_battery_status, but modified. |
653 | | - import ui |
654 | | - import winKernel |
655 | | - sps = winKernel.SYSTEM_POWER_STATUS() |
656 | | - if not winKernel.GetSystemPowerStatus(sps) or sps.BatteryFlag is self.UNKNOWN_BATTERY_STATUS: |
657 | | - return |
658 | | - if sps.BatteryFlag & self.NO_SYSTEM_BATTERY: |
659 | | - return |
660 | | - if self.oldBatteryStatus is None: |
661 | | - #Just initializing the cache, do not report anything. |
662 | | - self.oldBatteryStatus = sps.ACLineStatus |
663 | | - return |
664 | | - if sps.ACLineStatus == self.oldBatteryStatus: |
665 | | - #Sometimes, this double fires. This also fires when the battery level decreases by 3%. |
666 | | - return |
667 | | - self.oldBatteryStatus = sps.ACLineStatus |
668 | | - if sps.ACLineStatus & self.AC_ONLINE: |
669 | | - #Translators: Reported when the battery is plugged in, and now is charging. |
670 | | - ui.message(_("Charging battery. %d percent") % sps.BatteryLifePercent) |
671 | | - else: |
672 | | - #Translators: Reported when the battery is no longer plugged in, and now is not charging. |
673 | | - ui.message(_("Not charging battery. %d percent") %sps.BatteryLifePercent) |
| 558 | + from winAPI.messageWindow import _MessageWindow |
674 | 559 | import versionInfo |
675 | | - messageWindow = MessageWindow(versionInfo.name) |
| 560 | + messageWindow = _MessageWindow(versionInfo.name) |
676 | 561 |
|
677 | 562 | # initialize wxpython localization support |
678 | 563 | wxLocaleObj = wx.Locale() |
|
0 commit comments