summaryrefslogtreecommitdiffstats
path: root/widget/windows/nsWindow.h
blob: c75c9d174d73091611d9659ce7fb039f03514489 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
/* -*- 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}};

/**
 * 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;
  nsresult SetNonClientMargins(const LayoutDeviceIntMargin&) override;
  void SetResizeMargin(mozilla::LayoutDeviceIntCoord aResizeMargin) override;
  void UpdateWindowDraggingRegion(
      const LayoutDeviceIntRegion& aRegion) 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 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();
  static const wchar_t* GetMainWindowClass();
  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(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);
  // 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);

  /**
   * 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;
  }
  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 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;
  // Whether we're an alert window. Alert windows don't have taskbar icons and
  // don't steal focus from other windows when opened. They're also expected to
  // be of type WindowType::Dialog.
  bool mIsAlert = false;
  bool mIsPerformingDwmFlushHack = false;
  bool mDraggingWindowWithMouse = 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
  mozilla::LayoutDeviceIntCoord mHorResizeMargin;
  // Height of the top and bottom portions of the resize region
  mozilla::LayoutDeviceIntCoord mVertResizeMargin;
  // Height of the caption plus border
  mozilla::LayoutDeviceIntCoord 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
  LayoutDeviceIntRect mLastPaintBounds;

  ResizeState mResizeState = NOT_RESIZING;

  // Transparency
  TransparencyMode mTransparencyMode = TransparencyMode::Opaque;
  nsIntRegion mPossiblyTransparentRegion;

  // 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 were 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;

  // 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_