diff options
Diffstat (limited to 'widget/windows/nsWindow.h')
-rw-r--r-- | widget/windows/nsWindow.h | 947 |
1 files changed, 947 insertions, 0 deletions
diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h new file mode 100644 index 0000000000..ecf041979e --- /dev/null +++ b/widget/windows/nsWindow.h @@ -0,0 +1,947 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef WIDGET_WINDOWS_NSWINDOW_H_ +#define WIDGET_WINDOWS_NSWINDOW_H_ + +/* + * nsWindow - Native window management and event handling. + */ + +#include "mozilla/RefPtr.h" +#include "nsBaseWidget.h" +#include "CompositorWidget.h" +#include "mozilla/EventForwards.h" +#include "nsClassHashtable.h" +#include <windows.h> +#include "touchinjection_sdk80.h" +#include "nsdefs.h" +#include "nsUserIdleService.h" +#include "nsToolkit.h" +#include "nsString.h" +#include "nsTArray.h" +#include "gfxWindowsPlatform.h" +#include "gfxWindowsSurface.h" +#include "nsWindowDbg.h" +#include "cairo.h" +#include "nsRegion.h" +#include "mozilla/EnumeratedArray.h" +#include "mozilla/Maybe.h" +#include "mozilla/MouseEvents.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/webrender/WebRenderTypes.h" +#include "mozilla/dom/MouseEventBinding.h" +#include "mozilla/DataMutex.h" +#include "mozilla/UniquePtr.h" +#include "nsMargin.h" +#include "nsRegionFwd.h" + +#include "nsWinGesture.h" +#include "WinPointerEvents.h" +#include "WinUtils.h" +#include "WindowHook.h" +#include "TaskbarWindowPreview.h" + +#ifdef ACCESSIBILITY +# include "oleacc.h" +# include "mozilla/a11y/LocalAccessible.h" +#endif + +#include "nsUXThemeData.h" +#include "nsIUserIdleServiceInternal.h" + +#include "IMMHandler.h" +#include "CheckInvariantWrapper.h" + +/** + * Forward class definitions + */ + +class nsNativeDragTarget; +class nsIRollupListener; +class imgIContainer; + +namespace mozilla { +class WidgetMouseEvent; +namespace widget { +class NativeKey; +class InProcessWinCompositorWidget; +struct MSGResult; +class DirectManipulationOwner; +} // namespace widget +} // namespace mozilla + +/** + * Forward Windows-internal definitions of otherwise incomplete ones provided by + * the SDK. + */ +const CLSID CLSID_ImmersiveShell = { + 0xC2F03A33, + 0x21F5, + 0x47FA, + {0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39}}; + +// Virtual Desktop. + +EXTERN_C const IID IID_IVirtualDesktopManager; +MIDL_INTERFACE("a5cd92ff-29be-454c-8d04-d82879fb3f1b") +IVirtualDesktopManager : public IUnknown { + public: + virtual HRESULT STDMETHODCALLTYPE IsWindowOnCurrentVirtualDesktop( + __RPC__in HWND topLevelWindow, __RPC__out BOOL * onCurrentDesktop) = 0; + virtual HRESULT STDMETHODCALLTYPE GetWindowDesktopId( + __RPC__in HWND topLevelWindow, __RPC__out GUID * desktopId) = 0; + virtual HRESULT STDMETHODCALLTYPE MoveWindowToDesktop( + __RPC__in HWND topLevelWindow, __RPC__in REFGUID desktopId) = 0; +}; + +#ifdef __MINGW32__ +__CRT_UUID_DECL(IVirtualDesktopManager, 0xa5cd92ff, 0x29be, 0x454c, 0x8d, 0x04, + 0xd8, 0x28, 0x79, 0xfb, 0x3f, 0x1b) +#endif + +/** + * Native WIN32 window wrapper. + */ + +class nsWindow final : public nsBaseWidget { + public: + using WindowHook = mozilla::widget::WindowHook; + using IMEContext = mozilla::widget::IMEContext; + using WidgetEventTime = mozilla::WidgetEventTime; + + NS_INLINE_DECL_REFCOUNTING_INHERITED(nsWindow, nsBaseWidget) + + explicit nsWindow(bool aIsChildWindow = false); + + void SendAnAPZEvent(mozilla::InputData& aEvent); + + /* + * Init a standard gecko event for this widget. + * @param aEvent the event to initialize. + * @param aPoint message position in physical coordinates. + */ + void InitEvent(mozilla::WidgetGUIEvent& aEvent, + LayoutDeviceIntPoint* aPoint = nullptr); + + /* + * Returns WidgetEventTime instance which is initialized with current message + * time. + */ + WidgetEventTime CurrentMessageWidgetEventTime() const; + + /* + * Dispatch a gecko keyboard event for this widget. This + * is called by KeyboardLayout to dispatch gecko events. + * Returns true if it's consumed. Otherwise, false. + */ + bool DispatchKeyboardEvent(mozilla::WidgetKeyboardEvent* aEvent); + + /* + * Dispatch a gecko wheel event for this widget. This + * is called by ScrollHandler to dispatch gecko events. + * Returns true if it's consumed. Otherwise, false. + */ + bool DispatchWheelEvent(mozilla::WidgetWheelEvent* aEvent); + + /* + * Dispatch a gecko content command event for this widget. This + * is called by ScrollHandler to dispatch gecko events. + * Returns true if it's consumed. Otherwise, false. + */ + bool DispatchContentCommandEvent(mozilla::WidgetContentCommandEvent* aEvent); + + /* + * Return the parent window, if it exists. + */ + nsWindow* GetParentWindowBase(bool aIncludeOwner); + + /* + * Return true if this is a top level widget. + */ + bool IsTopLevelWidget() { return mIsTopWidgetWindow; } + + // nsIWidget interface + using nsBaseWidget::Create; // for Create signature not overridden here + [[nodiscard]] nsresult Create(nsIWidget* aParent, + nsNativeWidget aNativeParent, + const LayoutDeviceIntRect& aRect, + InitData* aInitData = nullptr) override; + void Destroy() override; + void SetParent(nsIWidget* aNewParent) override; + nsIWidget* GetParent(void) override; + float GetDPI() override; + double GetDefaultScaleInternal() override; + int32_t LogToPhys(double aValue); + mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override { + if (mozilla::widget::WinUtils::IsPerMonitorDPIAware()) { + return mozilla::DesktopToLayoutDeviceScale(1.0); + } else { + return mozilla::DesktopToLayoutDeviceScale(GetDefaultScaleInternal()); + } + } + + void Show(bool aState) override; + bool IsVisible() const override; + void ConstrainPosition(DesktopIntPoint&) override; + void SetSizeConstraints(const SizeConstraints& aConstraints) override; + void LockAspectRatio(bool aShouldLock) override; + const SizeConstraints GetSizeConstraints() override; + void SetInputRegion(const InputRegion&) override; + void Move(double aX, double aY) override; + void Resize(double aWidth, double aHeight, bool aRepaint) override; + void Resize(double aX, double aY, double aWidth, double aHeight, + bool aRepaint) override; + mozilla::Maybe<bool> IsResizingNativeWidget() override; + void PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, nsIWidget* aWidget, + bool aActivate) override; + void SetSizeMode(nsSizeMode aMode) override; + nsSizeMode SizeMode() override; + void GetWorkspaceID(nsAString& workspaceID) override; + void MoveToWorkspace(const nsAString& workspaceID) override; + void SuppressAnimation(bool aSuppress) override; + void Enable(bool aState) override; + bool IsEnabled() const override; + void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; + LayoutDeviceIntRect GetBounds() override; + LayoutDeviceIntRect GetScreenBounds() override; + [[nodiscard]] nsresult GetRestoredBounds(LayoutDeviceIntRect& aRect) override; + LayoutDeviceIntRect GetClientBounds() override; + LayoutDeviceIntPoint GetClientOffset() override; + void SetBackgroundColor(const nscolor& aColor) override; + void SetCursor(const Cursor&) override; + bool PrepareForFullscreenTransition(nsISupports** aData) override; + void PerformFullscreenTransition(FullscreenTransitionStage aStage, + uint16_t aDuration, nsISupports* aData, + nsIRunnable* aCallback) override; + void CleanupFullscreenTransition() override; + nsresult MakeFullScreen(bool aFullScreen) override; + void HideWindowChrome(bool aShouldHide) override; + void Invalidate(bool aEraseBackground = false, bool aUpdateNCArea = false, + bool aIncludeChildren = false); + void Invalidate(const LayoutDeviceIntRect& aRect) override; + void* GetNativeData(uint32_t aDataType) override; + void FreeNativeData(void* data, uint32_t aDataType) override; + nsresult SetTitle(const nsAString& aTitle) override; + void SetIcon(const nsAString& aIconSpec) override; + LayoutDeviceIntPoint WidgetToScreenOffset() override; + LayoutDeviceIntMargin ClientToWindowMargin() override; + nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, + nsEventStatus& aStatus) override; + void EnableDragDrop(bool aEnable) override; + void CaptureMouse(bool aCapture); + void CaptureRollupEvents(bool aDoCapture) override; + [[nodiscard]] nsresult GetAttention(int32_t aCycleCount) override; + bool HasPendingInputEvent() override; + WindowRenderer* GetWindowRenderer() override; + void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override; + [[nodiscard]] nsresult OnDefaultButtonLoaded( + const LayoutDeviceIntRect& aButtonRect) override; + nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, + int32_t aNativeKeyCode, + uint32_t aModifierFlags, + const nsAString& aCharacters, + const nsAString& aUnmodifiedCharacters, + nsIObserver* aObserver) override; + nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, + NativeMouseMessage aNativeMessage, + mozilla::MouseButton aButton, + nsIWidget::Modifiers aModifierFlags, + nsIObserver* aObserver) override; + + nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, + nsIObserver* aObserver) override { + return SynthesizeNativeMouseEvent( + aPoint, NativeMouseMessage::Move, mozilla::MouseButton::eNotPressed, + nsIWidget::Modifiers::NO_MODIFIERS, aObserver); + } + + nsresult SynthesizeNativeMouseScrollEvent( + LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, double aDeltaX, + double aDeltaY, double aDeltaZ, uint32_t aModifierFlags, + uint32_t aAdditionalFlags, nsIObserver* aObserver) override; + + nsresult SynthesizeNativeTouchpadPan(TouchpadGesturePhase aEventPhase, + LayoutDeviceIntPoint aPoint, + double aDeltaX, double aDeltaY, + int32_t aModifierFlagsn, + nsIObserver* aObserver) override; + + void SetInputContext(const InputContext& aContext, + const InputContextAction& aAction) override; + InputContext GetInputContext() override; + TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override; + void SetTransparencyMode(TransparencyMode aMode) override; + TransparencyMode GetTransparencyMode() override; + void UpdateOpaqueRegion(const LayoutDeviceIntRegion& aOpaqueRegion) override; + nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override; + void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) override; + void SetDrawsInTitlebar(bool aState) override; + void UpdateWindowDraggingRegion( + const LayoutDeviceIntRegion& aRegion) override; + + void UpdateThemeGeometries( + const nsTArray<ThemeGeometry>& aThemeGeometries) override; + uint32_t GetMaxTouchPoints() const override; + void SetWindowClass(const nsAString& xulWinType, const nsAString& xulWinClass, + const nsAString& xulWinName) override; + + /** + * Event helpers + */ + bool DispatchMouseEvent(mozilla::EventMessage aEventMessage, WPARAM wParam, + LPARAM lParam, bool aIsContextMenuKey, + int16_t aButton, uint16_t aInputSource, + WinPointerInfo* aPointerInfo = nullptr, + bool aIgnoreAPZ = false); + void DispatchPendingEvents(); + void DispatchCustomEvent(const nsString& eventName); + +#ifdef ACCESSIBILITY + /** + * Return an accessible associated with the window. + */ + mozilla::a11y::LocalAccessible* GetAccessible(); +#endif // ACCESSIBILITY + + /** + * Window utilities + */ + nsWindow* GetTopLevelWindow(bool aStopOnDialogOrPopup); + WNDPROC GetPrevWindowProc() { return mPrevWndProc.valueOr(nullptr); } + WindowHook& GetWindowHook() { return mWindowHook; } + nsWindow* GetParentWindow(bool aIncludeOwner); + + /** + * Misc. + */ + bool WidgetTypeSupportsAcceleration() override; + + void ForcePresent(); + bool TouchEventShouldStartDrag(mozilla::EventMessage aEventMessage, + LayoutDeviceIntPoint aEventPoint); + + void SetSmallIcon(HICON aIcon); + void SetBigIcon(HICON aIcon); + void SetSmallIconNoData(); + void SetBigIconNoData(); + + static void SetIsRestoringSession(const bool aIsRestoringSession) { + sIsRestoringSession = aIsRestoringSession; + } + + bool IsRTL() const { return mIsRTL; } + + /** + * AssociateDefaultIMC() associates or disassociates the default IMC for + * the window. + * + * @param aAssociate TRUE, associates the default IMC with the window. + * Otherwise, disassociates the default IMC from the + * window. + * @return TRUE if this method associated the default IMC with + * disassociated window or disassociated the default IMC + * from associated window. + * Otherwise, i.e., if this method did nothing actually, + * FALSE. + */ + bool AssociateDefaultIMC(bool aAssociate); + + bool HasTaskbarIconBeenCreated() { return mHasTaskbarIconBeenCreated; } + // Called when either the nsWindow or an nsITaskbarTabPreview receives the + // noticiation that this window has its icon placed on the taskbar. + void SetHasTaskbarIconBeenCreated(bool created = true) { + mHasTaskbarIconBeenCreated = created; + } + + // Getter/setter for the nsITaskbarWindowPreview for this nsWindow + already_AddRefed<nsITaskbarWindowPreview> GetTaskbarPreview() { + nsCOMPtr<nsITaskbarWindowPreview> preview( + do_QueryReferent(mTaskbarPreview)); + return preview.forget(); + } + void SetTaskbarPreview(nsITaskbarWindowPreview* preview) { + mTaskbarPreview = do_GetWeakReference(preview); + } + + void ReparentNativeWidget(nsIWidget* aNewParent) override; + + // Open file picker tracking + void PickerOpen(); + void PickerClosed(); + + bool DestroyCalled() { return mDestroyCalled; } + + bool IsPopup(); + bool ShouldUseOffMainThreadCompositing() override; + + const IMEContext& DefaultIMC() const { return mDefaultIMC; } + + void GetCompositorWidgetInitData( + mozilla::widget::CompositorWidgetInitData* aInitData) override; + bool IsTouchWindow() const { return mTouchWindow; } + bool SynchronouslyRepaintOnResize() override; + void MaybeDispatchInitialFocusEvent() override; + + void LocalesChanged() override; + + void NotifyOcclusionState(mozilla::widget::OcclusionState aState) override; + void MaybeEnableWindowOcclusion(bool aEnable); + + /* + * Return the HWND or null for this widget. + */ + HWND GetWindowHandle() { + return static_cast<HWND>(GetNativeData(NS_NATIVE_WINDOW)); + } + + /* + * Touch input injection apis + */ + nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, + TouchPointerState aPointerState, + LayoutDeviceIntPoint aPoint, + double aPointerPressure, + uint32_t aPointerOrientation, + nsIObserver* aObserver) override; + nsresult ClearNativeTouchSequence(nsIObserver* aObserver) override; + + nsresult SynthesizeNativePenInput(uint32_t aPointerId, + TouchPointerState aPointerState, + LayoutDeviceIntPoint aPoint, + double aPressure, uint32_t aRotation, + int32_t aTiltX, int32_t aTiltY, + int32_t aButton, + nsIObserver* aObserver) override; + + /* + * WM_APPCOMMAND common handler. + * Sends events via NativeKey::HandleAppCommandMessage(). + */ + bool HandleAppCommandMsg(const MSG& aAppCommandMsg, LRESULT* aRetValue); + + const InputContext& InputContextRef() const { return mInputContext; } + + private: + using TimeStamp = mozilla::TimeStamp; + using TimeDuration = mozilla::TimeDuration; + using TaskbarWindowPreview = mozilla::widget::TaskbarWindowPreview; + using NativeKey = mozilla::widget::NativeKey; + using MSGResult = mozilla::widget::MSGResult; + using PlatformCompositorWidgetDelegate = + mozilla::widget::PlatformCompositorWidgetDelegate; + + struct Desktop { + // Cached GUID of the virtual desktop this window should be on. + // This value may be stale. + nsString mID; + bool mUpdateIsQueued = false; + }; + + class PointerInfo { + public: + enum class PointerType : uint8_t { + TOUCH, + PEN, + }; + + PointerInfo(int32_t aPointerId, LayoutDeviceIntPoint& aPoint, + PointerType aType) + : mPointerId(aPointerId), mPosition(aPoint), mType(aType) {} + + int32_t mPointerId; + LayoutDeviceIntPoint mPosition; + PointerType mType; + }; + + class FrameState { + public: + explicit FrameState(nsWindow* aWindow); + + void ConsumePreXULSkeletonState(bool aWasMaximized); + + // Whether we should call ShowWindow with the relevant size mode if needed. + // We want to avoid that when Windows is already performing the change for + // us (via the SWP_FRAMECHANGED messages). + enum class DoShowWindow : bool { No, Yes }; + + void EnsureSizeMode(nsSizeMode, DoShowWindow = DoShowWindow::Yes); + void EnsureFullscreenMode(bool, DoShowWindow = DoShowWindow::Yes); + void OnFrameChanging(); + void OnFrameChanged(); + + nsSizeMode GetSizeMode() const; + + void CheckInvariant() const; + + private: + void SetSizeModeInternal(nsSizeMode, DoShowWindow); + + nsSizeMode mSizeMode = nsSizeMode_Normal; + // XXX mLastSizeMode is rather bizarre and needs some documentation. + nsSizeMode mLastSizeMode = nsSizeMode_Normal; + // The old size mode before going into fullscreen mode. This should never + // be nsSizeMode_Fullscreen. + nsSizeMode mPreFullscreenSizeMode = nsSizeMode_Normal; + // Whether we're in fullscreen. We need to keep this state out of band, + // rather than just using mSizeMode, because a window can be minimized + // while fullscreen, and we don't store the fullscreen state anywhere else. + bool mFullscreenMode = false; + nsWindow* mWindow; + }; + + // Manager for taskbar-hiding. No persistent state. + class TaskbarConcealer; + + // A magic number to identify the FAKETRACKPOINTSCROLLABLE window created + // when the trackpoint hack is enabled. + enum { eFakeTrackPointScrollableID = 0x46545053 }; + + // Used for displayport suppression during window resize + enum ResizeState { NOT_RESIZING, IN_SIZEMOVE, RESIZING, MOVING }; + + ~nsWindow() override; + + void WindowUsesOMTC() override; + void RegisterTouchWindow() override; + + /** + * Callbacks + */ + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam); + static LRESULT CALLBACK WindowProcInternal(HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam); + + static BOOL CALLBACK BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg); + static BOOL CALLBACK BroadcastMsg(HWND aTopWindow, LPARAM aMsg); + static BOOL CALLBACK DispatchStarvedPaints(HWND aTopWindow, LPARAM aMsg); + static BOOL CALLBACK RegisterTouchForDescendants(HWND aTopWindow, + LPARAM aMsg); + static BOOL CALLBACK UnregisterTouchForDescendants(HWND aTopWindow, + LPARAM aMsg); + static LRESULT CALLBACK MozSpecialMsgFilter(int code, WPARAM wParam, + LPARAM lParam); + static LRESULT CALLBACK MozSpecialWndProc(int code, WPARAM wParam, + LPARAM lParam); + static LRESULT CALLBACK MozSpecialMouseProc(int code, WPARAM wParam, + LPARAM lParam); + static VOID CALLBACK HookTimerForPopups(HWND hwnd, UINT uMsg, UINT idEvent, + DWORD dwTime); + + /** + * Window utilities + */ + LPARAM lParamToScreen(LPARAM lParam); + LPARAM lParamToClient(LPARAM lParam); + + WPARAM wParamFromGlobalMouseState(); + + bool AssociateWithNativeWindow(); + void DissociateFromNativeWindow(); + bool CanTakeFocus(); + bool UpdateNonClientMargins(bool aReflowWindow = true); + void UpdateDarkModeToolbar(); + void UpdateGetWindowInfoCaptionStatus(bool aActiveCaption); + void ResetLayout(); + void InvalidateNonClientRegion(); + HRGN ExcludeNonClientFromPaintRegion(HRGN aRegion); + static const wchar_t* GetMainWindowClass(); + bool HasGlass() const { + return mTransparencyMode == TransparencyMode::BorderlessGlass; + } + HWND GetOwnerWnd() const { return ::GetWindow(mWnd, GW_OWNER); } + bool IsOwnerForegroundWindow() const { + HWND owner = GetOwnerWnd(); + return owner && owner == ::GetForegroundWindow(); + } + bool IsForegroundWindow() const { return mWnd == ::GetForegroundWindow(); } + bool IsPopup() const { return mWindowType == WindowType::Popup; } + bool IsCloaked() const { return mIsCloaked; } + + /** + * Event processing helpers + */ + HWND GetTopLevelForFocus(HWND aCurWnd); + void DispatchFocusToTopLevelWindow(bool aIsActivate); + bool DispatchStandardEvent(mozilla::EventMessage aMsg); + void RelayMouseEvent(UINT aMsg, WPARAM wParam, LPARAM lParam); + bool ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam, + LRESULT* aRetValue); + // We wrap this in ProcessMessage so we can log the return value + bool ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam, + LRESULT* aRetValue); + bool ExternalHandlerProcessMessage(UINT aMessage, WPARAM& aWParam, + LPARAM& aLParam, MSGResult& aResult); + LRESULT ProcessCharMessage(const MSG& aMsg, bool* aEventDispatched); + LRESULT ProcessKeyUpMessage(const MSG& aMsg, bool* aEventDispatched); + LRESULT ProcessKeyDownMessage(const MSG& aMsg, bool* aEventDispatched); + static bool EventIsInsideWindow( + nsWindow* aWindow, + mozilla::Maybe<POINT> aEventPoint = mozilla::Nothing()); + static void PostSleepWakeNotification(const bool aIsSleepMode); + int32_t ClientMarginHitTestPoint(int32_t mx, int32_t my); + void SetWindowButtonRect(WindowButtonType aButtonType, + const LayoutDeviceIntRect& aClientRect) override { + mWindowBtnRect[aButtonType] = aClientRect; + } + TimeStamp GetMessageTimeStamp(LONG aEventTime) const; + static void UpdateFirstEventTime(DWORD aEventTime); + void FinishLiveResizing(ResizeState aNewState); + mozilla::Maybe<mozilla::PanGestureInput> ConvertTouchToPanGesture( + const mozilla::MultiTouchInput& aTouchInput, PTOUCHINPUT aOriginalEvent); + void DispatchTouchOrPanGestureInput(mozilla::MultiTouchInput& aTouchInput, + PTOUCHINPUT aOSEvent); + + /** + * Event handlers + */ + void OnDestroy() override; + bool OnResize(const LayoutDeviceIntSize& aSize); + void OnSizeModeChange(); + bool OnGesture(WPARAM wParam, LPARAM lParam); + bool OnTouch(WPARAM wParam, LPARAM lParam); + bool OnHotKey(WPARAM wParam, LPARAM lParam); + bool OnPaint(HDC aDC, uint32_t aNestingLevel); + void OnWindowPosChanging(WINDOWPOS* info); + void OnWindowPosChanged(WINDOWPOS* wp); + void OnSysColorChanged(); + void OnDPIChanged(int32_t x, int32_t y, int32_t width, int32_t height); + bool OnPointerEvents(UINT msg, WPARAM wParam, LPARAM lParam); + + /** + * Function that registers when the user has been active (used for detecting + * when the user is idle). + */ + void UserActivity(); + + int32_t GetHeight(int32_t aProposedHeight); + + DWORD WindowStyle(); + DWORD WindowExStyle(); + + static const wchar_t* ChooseWindowClass(WindowType, bool aForMenupopupFrame); + // This method registers the given window class, and returns the class name. + static const wchar_t* RegisterWindowClass(const wchar_t* aClassName, + UINT aExtraStyle, LPWSTR aIconID); + + /** + * XP and Vista theming support for windows with rounded edges + */ + void ClearThemeRegion(); + + /** + * Popup hooks + */ + static void ScheduleHookTimer(HWND aWnd, UINT aMsgId); + static void RegisterSpecialDropdownHooks(); + static void UnregisterSpecialDropdownHooks(); + static bool GetPopupsToRollup( + nsIRollupListener* aRollupListener, uint32_t* aPopupsToRollup, + mozilla::Maybe<POINT> aEventPoint = mozilla::Nothing()); + static bool NeedsToHandleNCActivateDelayed(HWND aWnd); + static bool DealWithPopups(HWND inWnd, UINT inMsg, WPARAM inWParam, + LPARAM inLParam, LRESULT* outResult); + + /** + * Window transparency helpers + */ + void SetWindowTranslucencyInner(TransparencyMode aMode); + TransparencyMode GetWindowTranslucencyInner() const { + return mTransparencyMode; + } + void UpdateGlass(); + bool IsSimulatedClientArea(int32_t clientX, int32_t clientY); + bool IsWindowButton(int32_t hitTestResult); + + bool DispatchTouchEventFromWMPointer(UINT msg, LPARAM aLParam, + const WinPointerInfo& aPointerInfo, + mozilla::MouseButton aButton); + + static bool IsAsyncResponseEvent(UINT aMsg, LRESULT& aResult); + void IPCWindowProcHandler(UINT& msg, WPARAM& wParam, LPARAM& lParam); + + /** + * Misc. + */ + void StopFlashing(); + static HWND WindowAtMouse(); + static bool IsTopLevelMouseExit(HWND aWnd); + LayoutDeviceIntRegion GetRegionToPaint(bool aForceFullRepaint, PAINTSTRUCT ps, + HDC aDC); + nsIWidgetListener* GetPaintListener(); + + void AddWindowOverlayWebRenderCommands( + mozilla::layers::WebRenderBridgeChild* aWrBridge, + mozilla::wr::DisplayListBuilder& aBuilder, + mozilla::wr::IpcResourceUpdateQueue& aResourceUpdates) override; + + void CreateCompositor() override; + void DestroyCompositor() override; + void RequestFxrOutput() override; + + void RecreateDirectManipulationIfNeeded(); + void ResizeDirectManipulationViewport(); + void DestroyDirectManipulation(); + + bool NeedsToTrackWindowOcclusionState(); + + void AsyncUpdateWorkspaceID(Desktop& aDesktop); + + // See bug 603793 + static bool HasBogusPopupsDropShadowOnMultiMonitor(); + + static void InitMouseWheelScrollData(); + + void ChangedDPI(); + + static bool InitTouchInjection(); + + bool InjectTouchPoint(uint32_t aId, LayoutDeviceIntPoint& aPoint, + POINTER_FLAGS aFlags, uint32_t aPressure = 1024, + uint32_t aOrientation = 90); + + void OnFullscreenChanged(nsSizeMode aOldSizeMode, bool aFullScreen); + void TryDwmResizeHack(); + + static void OnCloakEvent(HWND aWnd, bool aCloaked); + void OnCloakChanged(bool aCloaked); + +#ifdef DEBUG + virtual nsresult SetHiDPIMode(bool aHiDPI) override; + virtual nsresult RestoreHiDPIMode() override; +#endif + + // Get the orientation of the hidden taskbar, on the screen that this window + // is on, or Nothing if taskbar isn't hidden. + mozilla::Maybe<UINT> GetHiddenTaskbarEdge(); + + static bool sTouchInjectInitialized; + static InjectTouchInputPtr sInjectTouchFuncPtr; + static uint32_t sInstanceCount; + static nsWindow* sCurrentWindow; + static bool sIsOleInitialized; + static Cursor sCurrentCursor; + static bool sJustGotDeactivate; + static bool sJustGotActivate; + static bool sIsInMouseCapture; + static bool sIsRestoringSession; + + // Message postponement hack. See the definition-site of + // WndProcUrgentInvocation::sDepth for details. + struct MOZ_STACK_CLASS WndProcUrgentInvocation { + struct Marker { + Marker() { ++sDepth; } + ~Marker() { --sDepth; } + }; + inline static bool IsActive() { return sDepth > 0; } + static size_t sDepth; + }; + + // Hook Data Members for Dropdowns. sProcessHook Tells the + // hook methods whether they should be processing the hook + // messages. + static HHOOK sMsgFilterHook; + static HHOOK sCallProcHook; + static HHOOK sCallMouseHook; + static bool sProcessHook; + static UINT sRollupMsgId; + static HWND sRollupMsgWnd; + static UINT sHookTimerId; + + // Used to prevent dispatching mouse events that do not originate from user + // input. + static POINT sLastMouseMovePoint; + + nsClassHashtable<nsUint32HashKey, PointerInfo> mActivePointers; + + // This is used by SynthesizeNativeTouchPoint to maintain state between + // multiple synthesized points, in the case where we can't call InjectTouch + // directly. + mozilla::UniquePtr<mozilla::MultiTouchInput> mSynthesizedTouchInput; + + InputContext mInputContext; + + nsCOMPtr<nsIWidget> mParent; + nsIntSize mLastSize = nsIntSize(0, 0); + nsIntPoint mLastPoint; + HWND mWnd = nullptr; + HWND mTransitionWnd = nullptr; + mozilla::Maybe<WNDPROC> mPrevWndProc; + HBRUSH mBrush; + IMEContext mDefaultIMC; + HDEVNOTIFY mDeviceNotifyHandle = nullptr; + bool mIsTopWidgetWindow = false; + bool mInDtor = false; + bool mIsVisible = false; + bool mIsCloaked = false; + bool mTouchWindow = false; + bool mDisplayPanFeedback = false; + bool mHideChrome = false; + bool mIsRTL; + bool mMousePresent = false; + bool mSimulatedClientArea = false; + bool mDestroyCalled = false; + bool mOpeningAnimationSuppressed; + bool mAlwaysOnTop; + bool mIsEarlyBlankWindow = false; + bool mIsShowingPreXULSkeletonUI = false; + bool mResizable = false; + bool mForMenupopupFrame = false; + bool mIsPerformingDwmFlushHack = false; + DWORD_PTR mOldStyle = 0; + DWORD_PTR mOldExStyle = 0; + nsNativeDragTarget* mNativeDragTarget = nullptr; + HKL mLastKeyboardLayout = 0; + mozilla::CheckInvariantWrapper<FrameState> mFrameState; + WindowHook mWindowHook; + uint32_t mPickerDisplayCount = 0; + HICON mIconSmall = nullptr; + HICON mIconBig = nullptr; + HWND mLastKillFocusWindow = nullptr; + PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate = nullptr; + + LayoutDeviceIntMargin NonClientSizeMargin() const { + return NonClientSizeMargin(mNonClientOffset); + } + LayoutDeviceIntMargin NonClientSizeMargin( + const LayoutDeviceIntMargin& aNonClientOffset) const; + LayoutDeviceIntMargin NormalWindowNonClientOffset() const; + + // Non-client margin settings + // Pre-calculated outward offset applied to default frames + LayoutDeviceIntMargin mNonClientOffset; + // Margins set by the owner + LayoutDeviceIntMargin mNonClientMargins; + // Margins we'd like to set once chrome is reshown: + LayoutDeviceIntMargin mFutureMarginsOnceChromeShows; + // Indicates we need to apply margins once toggling chrome into showing: + bool mFutureMarginsToUse = false; + + // Indicates custom frames are enabled + bool mCustomNonClient = false; + // Indicates custom resize margins are in effect + bool mUseResizeMarginOverrides = false; + // Width of the left and right portions of the resize region + int32_t mHorResizeMargin; + // Height of the top and bottom portions of the resize region + int32_t mVertResizeMargin; + // Height of the caption plus border + int32_t mCaptionHeight; + + // not yet set, will be calculated on first use + double mDefaultScale = -1.0; + + // not yet set, will be calculated on first use + float mAspectRatio = 0.0; + + nsCOMPtr<nsIUserIdleServiceInternal> mIdleService; + + // Draggable titlebar region maintained by UpdateWindowDraggingRegion + LayoutDeviceIntRegion mDraggableRegion; + + // Graphics + HDC mPaintDC = nullptr; // only set during painting + + LayoutDeviceIntRect mLastPaintBounds; + + ResizeState mResizeState = NOT_RESIZING; + + // Transparency + TransparencyMode mTransparencyMode = TransparencyMode::Opaque; + nsIntRegion mPossiblyTransparentRegion; + MARGINS mGlassMargins = {0, 0, 0, 0}; + + // Win7 Gesture processing and management + nsWinGesture mGesture; + + // Weak ref to the nsITaskbarWindowPreview associated with this window + nsWeakPtr mTaskbarPreview = nullptr; + + // The input region that determines whether mouse events should be ignored + // and pass through to the window below. This is currently only used for + // popups. + InputRegion mInputRegion; + + // True if the taskbar (possibly through the tab preview) tells us that the + // icon has been created on the taskbar. + bool mHasTaskbarIconBeenCreated = false; + + // Whether we're in the process of sending a WM_SETTEXT ourselves + bool mSendingSetText = false; + + // Whether we we're created as a child window (aka ChildWindow) or not. + bool mIsChildWindow : 1; + + int32_t mCachedHitTestResult = 0; + + // The point in time at which the last paint completed. We use this to avoid + // painting too rapidly in response to frequent input events. + TimeStamp mLastPaintEndTime; + + // The location of the window buttons in the window. + mozilla::Maybe<LayoutDeviceIntRect> mWindowButtonsRect; + + // Caching for hit test results (in client coordinates) + LayoutDeviceIntPoint mCachedHitTestPoint; + TimeStamp mCachedHitTestTime; + + RefPtr<mozilla::widget::InProcessWinCompositorWidget> mBasicLayersSurface; + + double mSizeConstraintsScale; // scale in effect when setting constraints + + // Will be calculated when layer manager is created. + int32_t mMaxTextureSize = -1; + + // Pointer events processing and management + WinPointerEvents mPointerEvents; + + ScreenPoint mLastPanGestureFocus; + + // When true, used to indicate an async call to RequestFxrOutput to the GPU + // process after the Compositor is created + bool mRequestFxrOutputPending = false; + + // A stack based class used in DispatchMouseEvent() to tell whether we should + // NOT open context menu when we receives WM_CONTEXTMENU after the + // DispatchMouseEvent calls. + // This class now works only in the case where a mouse up event happened in + // the overscroll gutter. + class MOZ_STACK_CLASS ContextMenuPreventer final { + public: + explicit ContextMenuPreventer(nsWindow* aWindow) + : mWindow(aWindow), mNeedsToPreventContextMenu(false){}; + ~ContextMenuPreventer() { + mWindow->mNeedsToPreventContextMenu = mNeedsToPreventContextMenu; + } + void Update(const mozilla::WidgetMouseEvent& aEvent, + const nsIWidget::ContentAndAPZEventStatus& aEventStatus); + + private: + nsWindow* mWindow; + bool mNeedsToPreventContextMenu = false; + }; + friend class ContextMenuPreventer; + bool mNeedsToPreventContextMenu = false; + + mozilla::UniquePtr<mozilla::widget::DirectManipulationOwner> mDmOwner; + + // Client rect for minimize, maximize and close buttons. + mozilla::EnumeratedArray<WindowButtonType, WindowButtonType::Count, + LayoutDeviceIntRect> + mWindowBtnRect; + + mozilla::DataMutex<Desktop> mDesktopId; + + // If set, indicates the edge of the NC region we should clear to black + // on next paint. One of: ABE_TOP, ABE_BOTTOM, ABE_LEFT or ABE_RIGHT. + mozilla::Maybe<UINT> mClearNCEdge; + + friend class nsWindowGfx; + + static constexpr int kHiddenTaskbarSize = 2; +}; + +#endif // WIDGET_WINDOWS_NSWINDOW_H_ |