1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
14 #include "CompositorWidget.h"
15 #include "MozContainer.h"
16 #include "VsyncSource.h"
17 #include "mozilla/EventForwards.h"
18 #include "mozilla/Maybe.h"
19 #include "mozilla/RefPtr.h"
20 #include "mozilla/TouchEvents.h"
21 #include "mozilla/UniquePtr.h"
22 #include "mozilla/widget/WindowSurface.h"
23 #include "mozilla/widget/WindowSurfaceProvider.h"
24 #include "nsBaseWidget.h"
25 #include "nsGkAtoms.h"
26 #include "nsIDragService.h"
27 #include "nsRefPtrHashtable.h"
28 #include "IMContextWrapper.h"
31 # include "mozilla/a11y/LocalAccessible.h"
35 # include <gdk/gdkx.h>
36 # include "X11UndefineNone.h"
39 # include <gdk/gdkwayland.h>
40 # include "base/thread.h"
41 # include "WaylandVsyncSource.h"
42 # include "nsClipboardWayland.h"
47 # include "mozilla/Logging.h"
48 # include "nsTArray.h"
51 extern mozilla::LazyLogModule gWidgetLog
;
52 extern mozilla::LazyLogModule gWidgetDragLog
;
53 extern mozilla::LazyLogModule gWidgetPopupLog
;
54 extern mozilla::LazyLogModule gWidgetVsync
;
56 # define LOG(str, ...) \
57 MOZ_LOG(IsPopup() ? gWidgetPopupLog : gWidgetLog, \
58 mozilla::LogLevel::Debug, \
59 ("%s: " str, GetDebugTag().get(), ##__VA_ARGS__))
60 # define LOGW(...) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
61 # define LOGDRAG(...) \
62 MOZ_LOG(gWidgetDragLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
63 # define LOG_POPUP(...) \
64 MOZ_LOG(gWidgetPopupLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
65 # define LOG_VSYNC(...) \
66 MOZ_LOG(gWidgetVsync, mozilla::LogLevel::Debug, (__VA_ARGS__))
67 # define LOG_ENABLED() \
68 (MOZ_LOG_TEST(gWidgetPopupLog, mozilla::LogLevel::Debug) || \
69 MOZ_LOG_TEST(gWidgetLog, mozilla::LogLevel::Debug))
76 # define LOG_POPUP(...)
77 # define LOG_ENABLED() false
79 #endif /* MOZ_LOGGING */
81 #if defined(MOZ_WAYLAND) && !defined(MOZ_X11)
82 typedef uintptr_t Window
;
87 #if !GTK_CHECK_VERSION(3, 18, 0)
88 struct _GdkEventTouchpadPinch
;
89 typedef struct _GdkEventTouchpadPinch GdkEventTouchpadPinch
;
92 #if !GTK_CHECK_VERSION(3, 22, 0)
94 GDK_ANCHOR_FLIP_X
= 1 << 0,
95 GDK_ANCHOR_FLIP_Y
= 1 << 1,
96 GDK_ANCHOR_SLIDE_X
= 1 << 2,
97 GDK_ANCHOR_SLIDE_Y
= 1 << 3,
98 GDK_ANCHOR_RESIZE_X
= 1 << 4,
99 GDK_ANCHOR_RESIZE_Y
= 1 << 5,
100 GDK_ANCHOR_FLIP
= GDK_ANCHOR_FLIP_X
| GDK_ANCHOR_FLIP_Y
,
101 GDK_ANCHOR_SLIDE
= GDK_ANCHOR_SLIDE_X
| GDK_ANCHOR_SLIDE_Y
,
102 GDK_ANCHOR_RESIZE
= GDK_ANCHOR_RESIZE_X
| GDK_ANCHOR_RESIZE_Y
107 enum class NativeKeyBindingsType
: uint8_t;
111 class CurrentX11TimeGetter
;
116 } // namespace widget
117 } // namespace mozilla
119 class nsWindow final
: public nsBaseWidget
{
121 typedef mozilla::gfx::DrawTarget DrawTarget
;
122 typedef mozilla::WidgetEventTime WidgetEventTime
;
123 typedef mozilla::WidgetKeyboardEvent WidgetKeyboardEvent
;
124 typedef mozilla::widget::PlatformCompositorWidgetDelegate
125 PlatformCompositorWidgetDelegate
;
129 static void ReleaseGlobals();
131 NS_INLINE_DECL_REFCOUNTING_INHERITED(nsWindow
, nsBaseWidget
)
133 nsresult
DispatchEvent(mozilla::WidgetGUIEvent
* aEvent
,
134 nsEventStatus
& aStatus
) override
;
136 // called when we are destroyed
137 void OnDestroy() override
;
139 // called to check and see if a widget's dimensions are sane
140 bool AreBoundsSane(void);
143 using nsBaseWidget::Create
; // for Create signature not overridden here
144 [[nodiscard
]] nsresult
Create(nsIWidget
* aParent
,
145 nsNativeWidget aNativeParent
,
146 const LayoutDeviceIntRect
& aRect
,
147 InitData
* aInitData
) override
;
148 void Destroy() override
;
149 nsIWidget
* GetParent() override
;
150 float GetDPI() override
;
151 double GetDefaultScaleInternal() override
;
152 mozilla::DesktopToLayoutDeviceScale
GetDesktopToDeviceScale() override
;
153 mozilla::DesktopToLayoutDeviceScale
GetDesktopToDeviceScaleByScreen()
155 void SetParent(nsIWidget
* aNewParent
) override
;
156 void SetModal(bool aModal
) override
;
157 bool IsVisible() const override
;
158 bool IsMapped() const override
;
159 void ConstrainPosition(DesktopIntPoint
&) override
;
160 void SetSizeConstraints(const SizeConstraints
& aConstraints
) override
;
161 void LockAspectRatio(bool aShouldLock
) override
;
162 void Move(double aX
, double aY
) override
;
163 void Show(bool aState
) override
;
164 void Resize(double aWidth
, double aHeight
, bool aRepaint
) override
;
165 void Resize(double aX
, double aY
, double aWidth
, double aHeight
,
166 bool aRepaint
) override
;
167 bool IsEnabled() const override
;
169 void SetZIndex(int32_t aZIndex
) override
;
170 nsSizeMode
SizeMode() override
{ return mSizeMode
; }
171 void SetSizeMode(nsSizeMode aMode
) override
;
172 void GetWorkspaceID(nsAString
& workspaceID
) override
;
173 void MoveToWorkspace(const nsAString
& workspaceID
) override
;
174 void Enable(bool aState
) override
;
175 void SetFocus(Raise
, mozilla::dom::CallerType aCallerType
) override
;
176 LayoutDeviceIntRect
GetScreenBounds() override
;
177 LayoutDeviceIntRect
GetClientBounds() override
;
178 LayoutDeviceIntSize
GetClientSize() override
;
179 LayoutDeviceIntPoint
GetClientOffset() override
{ return mClientOffset
; }
180 LayoutDeviceIntPoint
GetScreenEdgeSlop() override
;
182 // Recomputes the client offset according to our current window position.
183 // If aNotify is true, NotifyWindowMoved will be called on client offset
186 // NOTE(emilio): It seems that as long any change here update either the size
187 // or the position of the window, we should be doing fine without notifying,
188 // but this is done to preserve existing behavior.
189 void RecomputeClientOffset(bool aNotify
);
191 void SetCursor(const Cursor
&) override
;
192 void Invalidate(const LayoutDeviceIntRect
& aRect
) override
;
193 void* GetNativeData(uint32_t aDataType
) override
;
194 nsresult
SetTitle(const nsAString
& aTitle
) override
;
195 void SetIcon(const nsAString
& aIconSpec
) override
;
196 void SetWindowClass(const nsAString
& xulWinType
, const nsAString
& xulWinClass
,
197 const nsAString
& xulWinName
) override
;
198 LayoutDeviceIntPoint
WidgetToScreenOffset() override
;
199 void CaptureRollupEvents(bool aDoCapture
) override
;
200 [[nodiscard
]] nsresult
GetAttention(int32_t aCycleCount
) override
;
201 bool HasPendingInputEvent() override
;
203 bool PrepareForFullscreenTransition(nsISupports
** aData
) override
;
204 void PerformFullscreenTransition(FullscreenTransitionStage aStage
,
205 uint16_t aDuration
, nsISupports
* aData
,
206 nsIRunnable
* aCallback
) override
;
207 already_AddRefed
<Screen
> GetWidgetScreen() override
;
208 nsresult
MakeFullScreen(bool aFullScreen
) override
;
209 void HideWindowChrome(bool aShouldHide
) override
;
212 * GetLastUserInputTime returns a timestamp for the most recent user input
213 * event. This is intended for pointer grab requests (including drags).
215 static guint32
GetLastUserInputTime();
217 // utility method, -1 if no change should be made, otherwise returns a
218 // value that can be passed to gdk_window_set_decorations
219 gint
ConvertBorderStyles(BorderStyle aStyle
);
221 mozilla::widget::IMContextWrapper
* GetIMContext() const { return mIMContext
; }
223 bool DispatchCommandEvent(nsAtom
* aCommand
);
224 bool DispatchContentCommandEvent(mozilla::EventMessage aMsg
);
227 gboolean
OnExposeEvent(cairo_t
* cr
);
228 gboolean
OnConfigureEvent(GtkWidget
* aWidget
, GdkEventConfigure
* aEvent
);
232 void OnSizeAllocate(GtkAllocation
* aAllocation
);
233 void OnDeleteEvent();
234 void OnEnterNotifyEvent(GdkEventCrossing
* aEvent
);
235 void OnLeaveNotifyEvent(GdkEventCrossing
* aEvent
);
236 void OnMotionNotifyEvent(GdkEventMotion
* aEvent
);
237 void OnButtonPressEvent(GdkEventButton
* aEvent
);
238 void OnButtonReleaseEvent(GdkEventButton
* aEvent
);
239 void OnContainerFocusInEvent(GdkEventFocus
* aEvent
);
240 void OnContainerFocusOutEvent(GdkEventFocus
* aEvent
);
241 gboolean
OnKeyPressEvent(GdkEventKey
* aEvent
);
242 gboolean
OnKeyReleaseEvent(GdkEventKey
* aEvent
);
244 void OnScrollEvent(GdkEventScroll
* aEvent
);
246 void OnWindowStateEvent(GtkWidget
* aWidget
, GdkEventWindowState
* aEvent
);
247 void OnDragDataReceivedEvent(GtkWidget
* aWidget
, GdkDragContext
* aDragContext
,
249 GtkSelectionData
* aSelectionData
, guint aInfo
,
250 guint aTime
, gpointer aData
);
251 gboolean
OnPropertyNotifyEvent(GtkWidget
* aWidget
, GdkEventProperty
* aEvent
);
252 gboolean
OnTouchEvent(GdkEventTouch
* aEvent
);
253 gboolean
OnTouchpadPinchEvent(GdkEventTouchpadPinch
* aEvent
);
255 gint
GetInputRegionMarginInGdkCoords();
257 void UpdateTopLevelOpaqueRegion();
259 already_AddRefed
<mozilla::gfx::DrawTarget
> StartRemoteDrawingInRegion(
260 const LayoutDeviceIntRegion
& aInvalidRegion
,
261 mozilla::layers::BufferMode
* aBufferMode
) override
;
262 void EndRemoteDrawingInRegion(
263 mozilla::gfx::DrawTarget
* aDrawTarget
,
264 const LayoutDeviceIntRegion
& aInvalidRegion
) override
;
266 void SetProgress(unsigned long progressPercent
);
268 RefPtr
<mozilla::VsyncDispatcher
> GetVsyncDispatcher() override
;
269 bool SynchronouslyRepaintOnResize() override
;
272 void OnCheckResize();
273 void OnCompositedChanged();
274 void OnScaleChanged(bool aNotify
);
275 void DispatchResized();
277 static guint32 sLastButtonPressTime
;
279 MozContainer
* GetMozContainer() { return mContainer
; }
280 GdkWindow
* GetGdkWindow() const { return mGdkWindow
; };
281 GdkWindow
* GetToplevelGdkWindow() const;
282 GtkWidget
* GetGtkWidget() const { return mShell
; }
283 nsIFrame
* GetFrame() const;
284 nsWindow
* GetEffectiveParent();
285 bool IsDestroyed() const { return mIsDestroyed
; }
286 bool IsPopup() const;
287 bool IsWaylandPopup() const;
288 bool IsPIPWindow() const { return mIsPIPWindow
; };
289 bool IsDragPopup() { return mIsDragPopup
; };
291 nsAutoCString
GetDebugTag() const;
293 void DispatchDragEvent(mozilla::EventMessage aMsg
,
294 const LayoutDeviceIntPoint
& aRefPoint
, guint aTime
);
295 static void UpdateDragStatus(GdkDragContext
* aDragContext
,
296 nsIDragService
* aDragService
);
297 void SetDragSource(GdkDragContext
* aSourceDragContext
);
299 WidgetEventTime
GetWidgetEventTime(guint32 aEventTime
);
300 mozilla::TimeStamp
GetEventTimeStamp(guint32 aEventTime
);
302 mozilla::CurrentX11TimeGetter
* GetCurrentTimeGetter();
305 void SetInputContext(const InputContext
& aContext
,
306 const InputContextAction
& aAction
) override
;
307 InputContext
GetInputContext() override
;
308 TextEventDispatcherListener
* GetNativeTextEventDispatcherListener() override
;
309 MOZ_CAN_RUN_SCRIPT
bool GetEditCommands(
310 mozilla::NativeKeyBindingsType aType
,
311 const mozilla::WidgetKeyboardEvent
& aEvent
,
312 nsTArray
<mozilla::CommandInt
>& aCommands
) override
;
314 // These methods are for toplevel windows only.
315 void ResizeTransparencyBitmap();
316 void ApplyTransparencyBitmap();
317 void ClearTransparencyBitmap();
319 void SetTransparencyMode(TransparencyMode aMode
) override
;
320 TransparencyMode
GetTransparencyMode() override
;
321 void SetInputRegion(const InputRegion
&) override
;
322 nsresult
UpdateTranslucentWindowAlphaInternal(const nsIntRect
& aRect
,
325 void ReparentNativeWidget(nsIWidget
* aNewParent
) override
;
327 void UpdateTitlebarTransparencyBitmap();
329 nsresult
SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint
,
330 NativeMouseMessage aNativeMessage
,
331 mozilla::MouseButton aButton
,
332 nsIWidget::Modifiers aModifierFlags
,
333 nsIObserver
* aObserver
) override
;
335 nsresult
SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint
,
336 nsIObserver
* aObserver
) override
{
337 return SynthesizeNativeMouseEvent(
338 aPoint
, NativeMouseMessage::Move
, mozilla::MouseButton::eNotPressed
,
339 nsIWidget::Modifiers::NO_MODIFIERS
, aObserver
);
342 nsresult
SynthesizeNativeMouseScrollEvent(
343 LayoutDeviceIntPoint aPoint
, uint32_t aNativeMessage
, double aDeltaX
,
344 double aDeltaY
, double aDeltaZ
, uint32_t aModifierFlags
,
345 uint32_t aAdditionalFlags
, nsIObserver
* aObserver
) override
;
347 nsresult
SynthesizeNativeTouchPoint(uint32_t aPointerId
,
348 TouchPointerState aPointerState
,
349 LayoutDeviceIntPoint aPoint
,
350 double aPointerPressure
,
351 uint32_t aPointerOrientation
,
352 nsIObserver
* aObserver
) override
;
354 nsresult
SynthesizeNativeTouchPadPinch(TouchpadGesturePhase aEventPhase
,
356 LayoutDeviceIntPoint aPoint
,
357 int32_t aModifierFlags
) override
;
359 nsresult
SynthesizeNativeTouchpadPan(TouchpadGesturePhase aEventPhase
,
360 LayoutDeviceIntPoint aPoint
,
361 double aDeltaX
, double aDeltaY
,
362 int32_t aModifierFlags
,
363 nsIObserver
* aObserver
) override
;
365 void GetCompositorWidgetInitData(
366 mozilla::widget::CompositorWidgetInitData
* aInitData
) override
;
368 nsresult
SetNonClientMargins(const LayoutDeviceIntMargin
&) override
;
369 void SetDrawsInTitlebar(bool aState
);
370 mozilla::LayoutDeviceIntCoord
GetTitlebarRadius();
371 LayoutDeviceIntRect
GetTitlebarRect();
372 void UpdateWindowDraggingRegion(
373 const LayoutDeviceIntRegion
& aRegion
) override
;
375 // HiDPI scale conversion
376 gint
GdkCeiledScaleFactor();
377 double FractionalScaleFactor();
380 gint
DevicePixelsToGdkCoordRoundUp(int);
381 gint
DevicePixelsToGdkCoordRoundDown(int);
382 GdkPoint
DevicePixelsToGdkPointRoundDown(const LayoutDeviceIntPoint
&);
383 GdkRectangle
DevicePixelsToGdkSizeRoundUp(const LayoutDeviceIntSize
&);
384 GdkRectangle
DevicePixelsToGdkRectRoundOut(const LayoutDeviceIntRect
&);
387 int GdkCoordToDevicePixels(gint
);
388 LayoutDeviceIntPoint
GdkPointToDevicePixels(const GdkPoint
&);
389 LayoutDeviceIntPoint
GdkEventCoordsToDevicePixels(gdouble aX
, gdouble aY
);
390 LayoutDeviceIntRect
GdkRectToDevicePixels(const GdkRectangle
&);
392 bool WidgetTypeSupportsAcceleration() override
;
394 nsresult
SetSystemFont(const nsCString
& aFontName
) override
;
395 nsresult
GetSystemFont(nsCString
& aFontName
) override
;
398 GTK_DECORATION_SYSTEM
, // CSD including shadows
399 GTK_DECORATION_CLIENT
, // CSD without shadows
400 GTK_DECORATION_NONE
, // WM does not support CSD at all
401 } GtkWindowDecoration
;
403 * Get the support of Client Side Decoration by checking the desktop
406 static GtkWindowDecoration
GetSystemGtkWindowDecoration();
408 static bool GetTopLevelWindowActiveState(nsIFrame
* aFrame
);
409 static bool TitlebarUseShapeMask();
410 bool IsRemoteContent() { return HasRemoteContent(); }
411 void NativeMoveResizeWaylandPopupCallback(const GdkRectangle
* aFinalSize
,
412 bool aFlippedX
, bool aFlippedY
);
413 static bool IsToplevelWindowTransparent();
415 static nsWindow
* GetFocusedWindow();
418 // Use xdg-activation protocol to transfer focus from gFocusWindow to aWindow.
419 static void TransferFocusToWaylandWindow(nsWindow
* aWindow
);
420 void FocusWaylandWindow(const char* aTokenID
);
422 bool GetCSDDecorationOffset(int* aDx
, int* aDy
);
423 bool SetEGLNativeWindowSize(const LayoutDeviceIntSize
& aEGLWindowSize
);
424 void WaylandDragWorkaround(GdkEventButton
* aEvent
);
426 void CreateCompositorVsyncDispatcher() override
;
427 LayoutDeviceIntPoint
GetNativePointerLockCenter() {
428 return mNativePointerLockCenter
;
430 void SetNativePointerLockCenter(
431 const LayoutDeviceIntPoint
& aLockCenter
) override
;
432 void LockNativePointer() override
;
433 void UnlockNativePointer() override
;
434 LayoutDeviceIntSize
GetMoveToRectPopupSize() const override
{
435 return mMoveToRectPopupSize
;
440 // WebRender compositor is enabled
442 // WebRender compositor is paused as we're repainting whole window and
443 // we're waiting for content process to update page content.
444 COMPOSITOR_PAUSED_FLICKERING
445 } WindowCompositorState
;
447 // Pause compositor to avoid rendering artifacts from content process.
448 void ResumeCompositorImpl();
449 void ResumeCompositorFlickering();
450 void ResumeCompositorFromCompositorThread();
451 void PauseCompositorFlickering();
452 bool IsWaitingForCompositorResume();
454 // Force hide this window, remove compositor etc. to avoid
455 // rendering queue blocking (see Bug 1782948).
456 void ClearRenderingQueue();
458 bool ApplyEnterLeaveMutterWorkaround();
460 void NotifyOcclusionState(mozilla::widget::OcclusionState aState
) override
;
462 static nsWindow
* GetWindow(GdkWindow
* window
);
467 // event handling code
468 void DispatchActivateEvent(void);
469 void DispatchDeactivateEvent(void);
470 void MaybeDispatchResized();
471 void DispatchPanGesture(mozilla::PanGestureInput
& aPanInput
);
473 void RegisterTouchWindow() override
;
475 nsCOMPtr
<nsIWidget
> mParent
;
476 PopupType mPopupHint
{};
477 mozilla::Atomic
<int, mozilla::Relaxed
> mCeiledScaleFactor
{1};
478 double mFractionalScaleFactor
= 0.0;
480 void UpdateAlpha(mozilla::gfx::SourceSurface
* aSourceSurface
,
481 nsIntRect aBoundsRect
);
483 void NativeMoveResize(bool aMoved
, bool aResized
);
485 void NativeShow(bool aAction
);
486 void SetHasMappedToplevel(bool aState
);
487 LayoutDeviceIntSize
GetSafeWindowSize(LayoutDeviceIntSize aSize
);
489 void DispatchContextMenuEventFromMouseEvent(
490 uint16_t domButton
, GdkEventButton
* aEvent
,
491 const mozilla::LayoutDeviceIntPoint
& aRefPoint
);
493 void TryToShowNativeWindowMenu(GdkEventButton
* aEvent
);
495 void WaylandStartVsync();
496 void WaylandStopVsync();
497 void DestroyChildWindows();
498 GtkWidget
* GetToplevelWidget() const;
499 nsWindow
* GetContainerWindow() const;
500 Window
GetX11Window();
501 bool GetShapedState();
502 void EnsureGdkWindow();
503 void SetUrgencyHint(GtkWidget
* top_window
, bool state
);
504 void SetDefaultIcon(void);
505 void SetWindowDecoration(BorderStyle aStyle
);
506 void InitButtonEvent(mozilla::WidgetMouseEvent
& aEvent
,
507 GdkEventButton
* aGdkEvent
,
508 const mozilla::LayoutDeviceIntPoint
& aRefPoint
);
509 bool CheckForRollup(gdouble aMouseX
, gdouble aMouseY
, bool aIsWheel
,
511 void RollupAllMenus() { CheckForRollup(0, 0, false, true); }
512 void CheckForRollupDuringGrab() { RollupAllMenus(); }
514 bool GetDragInfo(mozilla::WidgetMouseEvent
* aMouseEvent
, GdkWindow
** aWindow
,
515 gint
* aButton
, gint
* aRootX
, gint
* aRootY
);
516 nsIWidgetListener
* GetListener();
518 nsWindow
* GetTransientForWindowIfPopup();
519 bool IsHandlingTouchSequence(GdkEventSequence
* aSequence
);
521 void ResizeInt(const mozilla::Maybe
<LayoutDeviceIntPoint
>& aMove
,
522 LayoutDeviceIntSize aSize
);
523 void NativeMoveResizeWaylandPopup(bool aMove
, bool aResize
);
525 // Returns a window edge if the given point (in device pixels) is within a
526 // resizer region of the window.
527 // Only used when drawing decorations client side.
528 mozilla::Maybe
<GdkWindowEdge
> CheckResizerEdge(const LayoutDeviceIntPoint
&);
530 GtkTextDirection
GetTextDirection();
532 bool DrawsToCSDTitlebar() const;
533 void AddCSDDecorationSize(int* aWidth
, int* aHeight
);
535 void CreateAndPutGdkScrollEvent(mozilla::LayoutDeviceIntPoint aPoint
,
536 double aDeltaX
, double aDeltaY
);
538 nsCString mGtkWindowAppClass
;
539 nsCString mGtkWindowAppName
;
540 nsCString mGtkWindowRoleName
;
541 void RefreshWindowClass();
543 GtkWidget
* mShell
= nullptr;
544 MozContainer
* mContainer
= nullptr;
545 GdkWindow
* mGdkWindow
= nullptr;
546 PlatformCompositorWidgetDelegate
* mCompositorWidgetDelegate
= nullptr;
547 mozilla::Atomic
<WindowCompositorState
, mozilla::Relaxed
> mCompositorState
{
549 // This is used in COMPOSITOR_PAUSED_FLICKERING mode only to resume compositor
550 // in some reasonable time when page content is not updated.
551 guint mCompositorPauseTimeoutID
= 0;
553 // The actual size mode that's in effect.
554 nsSizeMode mSizeMode
= nsSizeMode_Normal
;
555 // The last size mode we've requested. This might not match mSizeMode if
556 // there's a request to change the size mode in progress.
557 nsSizeMode mLastSizeModeRequest
= nsSizeMode_Normal
;
558 nsSizeMode mLastSizeModeBeforeFullscreen
= nsSizeMode_Normal
;
560 float mAspectRatio
= 0.0f
;
561 float mAspectRatioSaved
= 0.0f
;
562 mozilla::Maybe
<GtkOrientation
> mAspectResizer
;
563 LayoutDeviceIntPoint mLastResizePoint
;
565 // The size requested, which might not be reflected in mBounds. Used in
566 // WaylandPopupSetDirectPosition() to remember intended size for popup
567 // positioning, in LockAspect() to remember the intended aspect ratio, and
568 // to remember a size requested while waiting for moved-to-rect when
569 // OnSizeAllocate() might change mBounds.Size().
570 LayoutDeviceIntSize mLastSizeRequest
;
571 LayoutDeviceIntPoint mClientOffset
;
572 // Indicates a new size that still needs to be dispatched.
573 LayoutDeviceIntSize mNeedsDispatchSize
= LayoutDeviceIntSize(-1, -1);
575 // This field omits duplicate scroll events caused by GNOME bug 726878.
576 guint32 mLastScrollEventTime
= GDK_CURRENT_TIME
;
577 mozilla::ScreenCoord mLastPinchEventSpan
;
579 struct TouchpadPinchGestureState
{
580 // Focus point of the PHASE_BEGIN event
581 ScreenPoint mBeginFocus
;
583 // Focus point of the most recent PHASE_UPDATE event
584 ScreenPoint mCurrentFocus
;
587 // Used for handling touchpad pinch gestures
588 ScreenPoint mCurrentTouchpadFocus
;
590 // Used for synthesizing touchpad pinch gestures
591 TouchpadPinchGestureState mCurrentSynthesizedTouchpadPinch
;
593 // Used for synthesizing touchpad pan gestures
594 struct TouchpadPanGestureState
{
595 mozilla::Maybe
<TouchpadGesturePhase
> mTouchpadGesturePhase
;
596 uint64_t mSavedObserver
= 0;
599 // Used for synthesizing touchpad pan gestures
600 TouchpadPanGestureState mCurrentSynthesizedTouchpadPan
;
602 // for touch event handling
603 nsRefPtrHashtable
<nsPtrHashKey
<GdkEventSequence
>, mozilla::dom::Touch
>
606 // Upper bound on pending ConfigureNotify events to be dispatched to the
607 // window. See bug 1225044.
608 unsigned int mPendingConfigures
= 0;
610 // Window titlebar rendering mode, GTK_DECORATION_NONE if it's disabled
612 GtkWindowDecoration mGtkWindowDecoration
= GTK_DECORATION_NONE
;
614 // Draggable titlebar region maintained by UpdateWindowDraggingRegion
615 LayoutDeviceIntRegion mDraggableRegion
;
618 static GdkCursor
* gsGtkCursorCache
[eCursorCount
];
620 // If true, draw our own window titlebar.
622 // Needs to be atomic because GetTitlebarRect() gets called from non-main
625 // FIXME(emilio): GetTitlebarRect() reads other things that TSAN doesn't
626 // catch because mDrawInTitlebar is false on automation ~always. We should
627 // probably make GetTitlebarRect() simpler / properly thread-safe.
628 mozilla::Atomic
<bool, mozilla::Relaxed
> mDrawInTitlebar
{false};
630 mozilla::Mutex mDestroyMutex
;
632 // Has this widget been destroyed yet?
633 bool mIsDestroyed
: 1;
634 // mIsShown tracks requested visible status from browser perspective, i.e.
635 // if the window should be visible or now.
637 // mNeedsShow is set when browser requested to show this window but we failed
638 // to do so for some reason (wrong window size for instance).
639 // In such case we set mIsShown = true and mNeedsShow = true to indicate
640 // that the window is not actually visible but we report to browser that
641 // it is visible (mIsShown == true).
643 // This track real window visibility from OS perspective.
644 // It's set by OnMap/OnUnrealize which is based on Gtk events.
646 // is this widget enabled?
648 // has the native window for this been created yet?
650 // whether we handle touch event
651 bool mHandleTouchEvent
: 1;
652 // true if this is a drag and drop feedback popup
653 bool mIsDragPopup
: 1;
654 bool mCompositedScreen
: 1;
655 bool mIsAccelerated
: 1;
656 bool mWindowShouldStartDragging
: 1;
657 bool mHasMappedToplevel
: 1;
658 bool mRetryPointerGrab
: 1;
659 bool mPanInProgress
: 1;
660 // Draw titlebar with :backdrop css state (inactive/unfocused).
661 bool mTitlebarBackdropState
: 1;
662 // It's undecorated popup utility window, without resizers/titlebar,
663 // movable by mouse. Used on Wayland for popups without
664 // parent (for instance WebRTC sharing indicator, notifications).
665 bool mIsWaylandPanelWindow
: 1;
666 // It's child window, i.e. window which is nested in parent window.
667 // This is obsoleted and should not be used.
668 // We use GdkWindow hierarchy for such windows.
669 bool mIsChildWindow
: 1;
670 bool mAlwaysOnTop
: 1;
671 bool mNoAutoHide
: 1;
672 bool mIsTransparent
: 1;
673 // We can expect at least one size-allocate event after early resizes.
674 bool mHasReceivedSizeAllocate
: 1;
675 bool mWidgetCursorLocked
: 1;
676 bool mUndecorated
: 1;
678 /* Gkt creates popup in two incarnations - wl_subsurface and xdg_popup.
679 * Kind of popup is choosen before GdkWindow is mapped so we can change
680 * it only when GdkWindow is hidden.
682 * Relevant Gtk code is at gdkwindow-wayland.c
683 * in should_map_as_popup() and should_map_as_subsurface()
686 * - can't be positioned by move-to-rect
687 * - can stand outside popup widget hierarchy (has toplevel as parent)
688 * - don't have child popup widgets
691 * - can be positioned by move-to-rect
692 * - aligned in popup widget hierarchy, first one is attached to toplevel
693 * - has child (popup) widgets
695 * Thus we need to map Firefox popup type to desired Gtk one:
702 * - autohide popups (hamburger menu)
706 * We set mPopupTrackInHierarchy = false for pernament panels which
707 * are always mapped to toplevel and painted as wl_surfaces.
709 bool mPopupTrackInHierarchy
: 1;
710 bool mPopupTrackInHierarchyConfigured
: 1;
712 /* On X11 Gtk tends to ignore window position requests when gtk_window
713 * is hidden. Save the position requests at mPopupPosition and apply
714 * when the widget is shown.
716 bool mHiddenPopupPositioned
: 1;
718 // The transparency bitmap is used instead of ARGB visual for toplevel
719 // window to draw titlebar.
720 bool mTransparencyBitmapForTitlebar
: 1;
722 // True when we're on compositing window manager and this
723 // window is using visual with alpha channel.
724 bool mHasAlphaVisual
: 1;
726 // When popup is anchored, mPopupPosition is relative to its parent popup.
727 bool mPopupAnchored
: 1;
729 // When popup is context menu.
730 bool mPopupContextMenu
: 1;
732 // Indicates that this popup matches layout setup so we can use parent popup
733 // coordinates reliably.
734 bool mPopupMatchesLayout
: 1;
736 /* Indicates that popup setup was changed and
737 * we need to recalculate popup coordinates.
739 bool mPopupChanged
: 1;
741 // Popup is hidden only as a part of hierarchy tree update.
742 bool mPopupTemporaryHidden
: 1;
744 // Popup is going to be closed and removed.
745 bool mPopupClosed
: 1;
747 // Popup is positioned by gdk_window_move_to_rect()
748 bool mPopupUseMoveToRect
: 1;
750 /* mWaitingForMoveToRectCallback is set when move-to-rect is called
751 * and we're waiting for move-to-rect callback.
753 * If another position/resize request comes between move-to-rect call and
754 * move-to-rect callback we set mMovedAfterMoveToRect/mResizedAfterMoveToRect.
756 bool mWaitingForMoveToRectCallback
: 1;
757 bool mMovedAfterMoveToRect
: 1;
758 bool mResizedAfterMoveToRect
: 1;
760 // Params used for popup placemend by GdkWindowMoveToRect.
761 // When popup is only resized and not positioned,
762 // we need to reuse last GdkWindowMoveToRect params to avoid
764 struct WaylandPopupMoveToRectParams
{
765 LayoutDeviceIntRect mAnchorRect
= {0, 0, 0, 0};
766 GdkGravity mAnchorRectType
= GDK_GRAVITY_NORTH_WEST
;
767 GdkGravity mPopupAnchorType
= GDK_GRAVITY_NORTH_WEST
;
768 GdkAnchorHints mHints
= GDK_ANCHOR_SLIDE
;
769 GdkPoint mOffset
= {0, 0};
770 bool mAnchorSet
= false;
773 WaylandPopupMoveToRectParams mPopupMoveToRectParams
;
775 // Whether we've configured default clear color already.
776 bool mConfiguredClearColor
: 1;
777 // Whether we've received a non-blank paint in which case we can reset the
778 // clear color to transparent.
779 bool mGotNonBlankPaint
: 1;
781 // Whether we need to retry capturing the mouse because we' re not mapped yet.
782 bool mNeedsToRetryCapturingMouse
: 1;
784 // This bitmap tracks which pixels are transparent. We don't support
785 // full translucency at this time; each pixel is either fully opaque
786 // or fully transparent.
787 gchar
* mTransparencyBitmap
= nullptr;
788 int32_t mTransparencyBitmapWidth
= 0;
789 int32_t mTransparencyBitmapHeight
= 0;
791 // all of our DND stuff
792 void InitDragEvent(mozilla::WidgetDragEvent
& aEvent
);
794 float mLastMotionPressure
= 0.0f
;
796 InputRegion mInputRegion
;
798 static bool DragInProgress(void);
800 void DispatchMissedButtonReleases(GdkEventCrossing
* aGdkEvent
);
802 // When window widget gets mapped/unmapped we need to configure
803 // underlying GdkWindow properly. Otherwise we'll end up with
804 // rendering to released window.
805 void ConfigureGdkWindow();
806 void ReleaseGdkWindow();
807 void ConfigureCompositor();
809 bool IsAlwaysUndecoratedWindow() const;
812 WindowRenderer
* GetWindowRenderer() override
;
813 void DidGetNonBlankPaint() override
;
815 void SetCompositorWidgetDelegate(CompositorWidgetDelegate
* delegate
) override
;
817 int32_t RoundsWidgetCoordinatesTo() override
;
819 void UpdateMozWindowActive();
821 void ForceTitlebarRedraw();
822 bool DoDrawTilebarCorners();
823 bool IsChromeWindowTitlebar();
825 void SetPopupWindowDecoration(bool aShowOnTaskbar
);
827 void ApplySizeConstraints();
829 // Wayland Popup section
830 GdkPoint
WaylandGetParentPosition();
831 bool WaylandPopupConfigure();
832 bool WaylandPopupIsAnchored();
833 bool WaylandPopupIsMenu();
834 bool WaylandPopupIsContextMenu();
835 bool WaylandPopupIsPermanent();
836 // First popup means it's attached directly to toplevel window
837 bool WaylandPopupIsFirst();
838 bool IsWidgetOverflowWindow();
839 void RemovePopupFromHierarchyList();
840 void ShowWaylandPopupWindow();
841 void HideWaylandPopupWindow(bool aTemporaryHidden
, bool aRemoveFromPopupList
);
842 void ShowWaylandToplevelWindow();
843 void HideWaylandToplevelWindow();
844 void WaylandPopupHideTooltips();
845 void WaylandPopupCloseOrphanedPopups();
846 void AppendPopupToHierarchyList(nsWindow
* aToplevelWindow
);
847 void WaylandPopupHierarchyHideTemporary();
848 void WaylandPopupHierarchyShowTemporaryHidden();
849 void WaylandPopupHierarchyCalculatePositions();
850 bool IsInPopupHierarchy();
851 void AddWindowToPopupHierarchy();
852 void UpdateWaylandPopupHierarchy();
853 void WaylandPopupHierarchyHideByLayout(
854 nsTArray
<nsIWidget
*>* aLayoutWidgetHierarchy
);
855 void WaylandPopupHierarchyValidateByLayout(
856 nsTArray
<nsIWidget
*>* aLayoutWidgetHierarchy
);
857 void CloseAllPopupsBeforeRemotePopup();
858 void WaylandPopupHideClosedPopups();
859 void WaylandPopupPrepareForMove();
860 void WaylandPopupMoveImpl();
861 void WaylandPopupMovePlain(int aX
, int aY
);
862 bool WaylandPopupRemoveNegativePosition(int* aX
= nullptr, int* aY
= nullptr);
863 bool WaylandPopupCheckAndGetAnchor(GdkRectangle
* aPopupAnchor
,
865 bool WaylandPopupAnchorAdjustForParentPopup(GdkRectangle
* aPopupAnchor
,
867 nsWindow
* GetTopmostWindow();
868 bool IsPopupInLayoutPopupChain(nsTArray
<nsIWidget
*>* aLayoutWidgetHierarchy
,
869 bool aMustMatchParent
);
870 void WaylandPopupMarkAsClosed();
871 void WaylandPopupRemoveClosedPopups();
872 void WaylandPopupSetDirectPosition();
873 bool WaylandPopupFitsToplevelWindow(bool aMove
);
874 const WaylandPopupMoveToRectParams
WaylandPopupGetPositionFromLayout();
875 void WaylandPopupPropagateChangesToLayout(bool aMove
, bool aResize
);
876 nsWindow
* WaylandPopupFindLast(nsWindow
* aPopup
);
877 GtkWindow
* GetCurrentTopmostWindow() const;
878 nsAutoCString
GetFrameTag() const;
879 nsCString
GetPopupTypeName();
880 bool IsPopupDirectionRTL();
883 void LogPopupHierarchy();
884 void LogPopupAnchorHints(int aHints
);
885 void LogPopupGravity(GdkGravity aGravity
);
888 bool IsTopLevelWindowType() const {
889 return mWindowType
== WindowType::TopLevel
||
890 mWindowType
== WindowType::Dialog
;
893 // mPopupPosition is the original popup position/size from layout, set by
894 // nsWindow::Move() or nsWindow::Resize().
895 // Popup position is relative to main (toplevel) window.
896 GdkPoint mPopupPosition
{};
898 // mRelativePopupPosition is popup position calculated against
899 // recent popup parent window.
900 GdkPoint mRelativePopupPosition
{};
902 // Toplevel window (first element) of linked list of Wayland popups. It's null
903 // if we're the toplevel.
904 RefPtr
<nsWindow
> mWaylandToplevel
;
906 // Next/Previous popups in Wayland popup hierarchy.
907 RefPtr
<nsWindow
> mWaylandPopupNext
;
908 RefPtr
<nsWindow
> mWaylandPopupPrev
;
910 // When popup is resized by Gtk by move-to-rect callback,
911 // we store final popup size here. Then we use mMoveToRectPopupSize size
912 // in following popup operations unless mLayoutPopupSizeCleared is set.
913 LayoutDeviceIntSize mMoveToRectPopupSize
;
916 * |mIMContext| takes all IME related stuff.
918 * This is owned by the top-level nsWindow or the topmost child
919 * nsWindow embedded in a non-Gecko widget.
921 * The instance is created when the top level widget is created. And when
922 * the widget is destroyed, it's released. All child windows refer its
923 * ancestor widget's instance. So, one set of IM contexts is created for
924 * all windows in a hierarchy. If the children are released after the top
925 * level window is released, the children still have a valid pointer,
926 * however, IME doesn't work at that time.
928 RefPtr
<mozilla::widget::IMContextWrapper
> mIMContext
;
931 mozilla::UniquePtr
<mozilla::CurrentX11TimeGetter
> mCurrentTimeGetter
;
933 static GtkWindowDecoration sGtkWindowDecoration
;
935 static bool sTransparentMainWindow
;
938 RefPtr
<mozilla::a11y::LocalAccessible
> mRootAccessible
;
941 * Request to create the accessible for this window if it is top level.
943 void CreateRootAccessible();
946 * Dispatch accessible event for the top level window accessible.
948 * @param aEventType [in] the accessible event type to dispatch
950 void DispatchEventToRootAccessible(uint32_t aEventType
);
953 * Dispatch accessible window activate event for the top level window
956 void DispatchActivateEventAccessible();
959 * Dispatch accessible window deactivate event for the top level window
962 void DispatchDeactivateEventAccessible();
965 * Dispatch accessible window maximize event for the top level window
968 void DispatchMaximizeEventAccessible();
971 * Dispatch accessible window minize event for the top level window
974 void DispatchMinimizeEventAccessible();
977 * Dispatch accessible window restore event for the top level window
980 void DispatchRestoreEventAccessible();
983 void SetUserTimeAndStartupTokenForActivatedWindow();
985 void KioskLockOnMonitor();
987 void EmulateResizeDrag(GdkEventMotion
* aEvent
);
990 typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT
= 0,
991 GTK_WIDGET_COMPOSIDED_DISABLED
= 1,
992 GTK_WIDGET_COMPOSIDED_ENABLED
= 2} WindowComposeRequest
;
993 void SetCompositorHint(WindowComposeRequest aState
);
994 bool ConfigureX11GLVisual();
997 RefPtr
<mozilla::WaylandVsyncSource
> mWaylandVsyncSource
;
998 RefPtr
<mozilla::VsyncDispatcher
> mWaylandVsyncDispatcher
;
999 LayoutDeviceIntPoint mNativePointerLockCenter
;
1000 zwp_locked_pointer_v1
* mLockedPointer
= nullptr;
1001 zwp_relative_pointer_v1
* mRelativePointer
= nullptr;
1003 // An activation token from our environment (see handling of the
1004 // XDG_ACTIVATION_TOKEN/DESKTOP_STARTUP_ID) env vars.
1005 nsCString mWindowActivationTokenFromEnv
;
1006 mozilla::widget::WindowSurfaceProvider mSurfaceProvider
;
1007 GdkDragContext
* mSourceDragContext
= nullptr;
1009 LayoutDeviceIntRect mLastLoggedBoundSize
;
1010 int mLastLoggedScale
= -1;
1012 // Running in kiosk mode and requested to stay on specified monitor.
1013 // If monitor is removed minimize the window.
1014 mozilla::Maybe
<int> mKioskMonitor
;
1017 #endif /* __nsWindow_h__ */