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 OnVisibilityNotifyEvent(GdkVisibilityState aState
);
247 void OnWindowStateEvent(GtkWidget
* aWidget
, GdkEventWindowState
* aEvent
);
248 void OnDragDataReceivedEvent(GtkWidget
* aWidget
, GdkDragContext
* aDragContext
,
250 GtkSelectionData
* aSelectionData
, guint aInfo
,
251 guint aTime
, gpointer aData
);
252 gboolean
OnPropertyNotifyEvent(GtkWidget
* aWidget
, GdkEventProperty
* aEvent
);
253 gboolean
OnTouchEvent(GdkEventTouch
* aEvent
);
254 gboolean
OnTouchpadPinchEvent(GdkEventTouchpadPinch
* aEvent
);
256 gint
GetInputRegionMarginInGdkCoords();
258 void UpdateTopLevelOpaqueRegion();
260 already_AddRefed
<mozilla::gfx::DrawTarget
> StartRemoteDrawingInRegion(
261 const LayoutDeviceIntRegion
& aInvalidRegion
,
262 mozilla::layers::BufferMode
* aBufferMode
) override
;
263 void EndRemoteDrawingInRegion(
264 mozilla::gfx::DrawTarget
* aDrawTarget
,
265 const LayoutDeviceIntRegion
& aInvalidRegion
) override
;
267 void SetProgress(unsigned long progressPercent
);
269 RefPtr
<mozilla::VsyncDispatcher
> GetVsyncDispatcher() override
;
270 bool SynchronouslyRepaintOnResize() override
;
273 void OnCheckResize();
274 void OnCompositedChanged();
275 void OnScaleChanged(bool aNotify
);
276 void DispatchResized();
278 static guint32 sLastButtonPressTime
;
280 MozContainer
* GetMozContainer() { return mContainer
; }
281 GdkWindow
* GetGdkWindow() const { return mGdkWindow
; };
282 GdkWindow
* GetToplevelGdkWindow() const;
283 GtkWidget
* GetGtkWidget() const { return mShell
; }
284 nsIFrame
* GetFrame() const;
285 nsWindow
* GetEffectiveParent();
286 bool IsDestroyed() const { return mIsDestroyed
; }
287 bool IsPopup() const;
288 bool IsWaylandPopup() const;
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 mozilla::Atomic
<int, mozilla::Relaxed
> mCeiledScaleFactor
{1};
477 double mFractionalScaleFactor
= 0.0;
479 void UpdateAlpha(mozilla::gfx::SourceSurface
* aSourceSurface
,
480 nsIntRect aBoundsRect
);
482 void NativeMoveResize(bool aMoved
, bool aResized
);
484 void NativeShow(bool aAction
);
485 void SetHasMappedToplevel(bool aState
);
486 LayoutDeviceIntSize
GetSafeWindowSize(LayoutDeviceIntSize aSize
);
488 void DispatchContextMenuEventFromMouseEvent(
489 uint16_t domButton
, GdkEventButton
* aEvent
,
490 const mozilla::LayoutDeviceIntPoint
& aRefPoint
);
492 void TryToShowNativeWindowMenu(GdkEventButton
* aEvent
);
494 void WaylandStartVsync();
495 void WaylandStopVsync();
496 void DestroyChildWindows();
497 GtkWidget
* GetToplevelWidget() const;
498 nsWindow
* GetContainerWindow() const;
499 Window
GetX11Window();
500 bool GetShapedState();
501 void EnsureGdkWindow();
502 void SetUrgencyHint(GtkWidget
* top_window
, bool state
);
503 void SetDefaultIcon(void);
504 void SetWindowDecoration(BorderStyle aStyle
);
505 void InitButtonEvent(mozilla::WidgetMouseEvent
& aEvent
,
506 GdkEventButton
* aGdkEvent
,
507 const mozilla::LayoutDeviceIntPoint
& aRefPoint
);
508 bool CheckForRollup(gdouble aMouseX
, gdouble aMouseY
, bool aIsWheel
,
510 void RollupAllMenus() { CheckForRollup(0, 0, false, true); }
511 void CheckForRollupDuringGrab() { RollupAllMenus(); }
513 bool GetDragInfo(mozilla::WidgetMouseEvent
* aMouseEvent
, GdkWindow
** aWindow
,
514 gint
* aButton
, gint
* aRootX
, gint
* aRootY
);
515 nsIWidgetListener
* GetListener();
517 nsWindow
* GetTransientForWindowIfPopup();
518 bool IsHandlingTouchSequence(GdkEventSequence
* aSequence
);
520 void ResizeInt(const mozilla::Maybe
<LayoutDeviceIntPoint
>& aMove
,
521 LayoutDeviceIntSize aSize
);
522 void NativeMoveResizeWaylandPopup(bool aMove
, bool aResize
);
524 // Returns a window edge if the given point (in device pixels) is within a
525 // resizer region of the window.
526 // Only used when drawing decorations client side.
527 mozilla::Maybe
<GdkWindowEdge
> CheckResizerEdge(const LayoutDeviceIntPoint
&);
529 GtkTextDirection
GetTextDirection();
531 bool DrawsToCSDTitlebar() const;
532 void AddCSDDecorationSize(int* aWidth
, int* aHeight
);
534 void CreateAndPutGdkScrollEvent(mozilla::LayoutDeviceIntPoint aPoint
,
535 double aDeltaX
, double aDeltaY
);
537 nsCString mGtkWindowAppClass
;
538 nsCString mGtkWindowAppName
;
539 nsCString mGtkWindowRoleName
;
540 void RefreshWindowClass();
542 GtkWidget
* mShell
= nullptr;
543 MozContainer
* mContainer
= nullptr;
544 GdkWindow
* mGdkWindow
= nullptr;
545 PlatformCompositorWidgetDelegate
* mCompositorWidgetDelegate
= nullptr;
546 mozilla::Atomic
<WindowCompositorState
, mozilla::Relaxed
> mCompositorState
{
548 // This is used in COMPOSITOR_PAUSED_FLICKERING mode only to resume compositor
549 // in some reasonable time when page content is not updated.
550 guint mCompositorPauseTimeoutID
= 0;
552 // The actual size mode that's in effect.
553 nsSizeMode mSizeMode
= nsSizeMode_Normal
;
554 // The last size mode we've requested. This might not match mSizeMode if
555 // there's a request to change the size mode in progress.
556 nsSizeMode mLastSizeModeRequest
= nsSizeMode_Normal
;
557 nsSizeMode mLastSizeModeBeforeFullscreen
= nsSizeMode_Normal
;
559 float mAspectRatio
= 0.0f
;
560 float mAspectRatioSaved
= 0.0f
;
561 mozilla::Maybe
<GtkOrientation
> mAspectResizer
;
562 LayoutDeviceIntPoint mLastResizePoint
;
564 // The size requested, which might not be reflected in mBounds. Used in
565 // WaylandPopupSetDirectPosition() to remember intended size for popup
566 // positioning, in LockAspect() to remember the intended aspect ratio, and
567 // to remember a size requested while waiting for moved-to-rect when
568 // OnSizeAllocate() might change mBounds.Size().
569 LayoutDeviceIntSize mLastSizeRequest
;
570 LayoutDeviceIntPoint mClientOffset
;
571 // Indicates a new size that still needs to be dispatched.
572 LayoutDeviceIntSize mNeedsDispatchSize
= LayoutDeviceIntSize(-1, -1);
574 // This field omits duplicate scroll events caused by GNOME bug 726878.
575 guint32 mLastScrollEventTime
= GDK_CURRENT_TIME
;
576 mozilla::ScreenCoord mLastPinchEventSpan
;
578 struct TouchpadPinchGestureState
{
579 // Focus point of the PHASE_BEGIN event
580 ScreenPoint mBeginFocus
;
582 // Focus point of the most recent PHASE_UPDATE event
583 ScreenPoint mCurrentFocus
;
586 // Used for handling touchpad pinch gestures
587 ScreenPoint mCurrentTouchpadFocus
;
589 // Used for synthesizing touchpad pinch gestures
590 TouchpadPinchGestureState mCurrentSynthesizedTouchpadPinch
;
592 // Used for synthesizing touchpad pan gestures
593 struct TouchpadPanGestureState
{
594 mozilla::Maybe
<TouchpadGesturePhase
> mTouchpadGesturePhase
;
595 uint64_t mSavedObserver
= 0;
598 // Used for synthesizing touchpad pan gestures
599 TouchpadPanGestureState mCurrentSynthesizedTouchpadPan
;
601 // for touch event handling
602 nsRefPtrHashtable
<nsPtrHashKey
<GdkEventSequence
>, mozilla::dom::Touch
>
605 // Upper bound on pending ConfigureNotify events to be dispatched to the
606 // window. See bug 1225044.
607 unsigned int mPendingConfigures
= 0;
609 // Window titlebar rendering mode, GTK_DECORATION_NONE if it's disabled
611 GtkWindowDecoration mGtkWindowDecoration
= GTK_DECORATION_NONE
;
613 // Draggable titlebar region maintained by UpdateWindowDraggingRegion
614 LayoutDeviceIntRegion mDraggableRegion
;
617 static GdkCursor
* gsGtkCursorCache
[eCursorCount
];
619 // If true, draw our own window titlebar.
621 // Needs to be atomic because GetTitlebarRect() gets called from non-main
624 // FIXME(emilio): GetTitlebarRect() reads other things that TSAN doesn't
625 // catch because mDrawInTitlebar is false on automation ~always. We should
626 // probably make GetTitlebarRect() simpler / properly thread-safe.
627 mozilla::Atomic
<bool, mozilla::Relaxed
> mDrawInTitlebar
{false};
629 mozilla::Mutex mDestroyMutex
;
631 // Has this widget been destroyed yet?
632 bool mIsDestroyed
: 1;
633 // mIsShown tracks requested visible status from browser perspective, i.e.
634 // if the window should be visible or now.
636 // mNeedsShow is set when browser requested to show this window but we failed
637 // to do so for some reason (wrong window size for instance).
638 // In such case we set mIsShown = true and mNeedsShow = true to indicate
639 // that the window is not actually visible but we report to browser that
640 // it is visible (mIsShown == true).
642 // This track real window visibility from OS perspective.
643 // It's set by OnMap/OnUnrealize which is based on Gtk events.
645 // is this widget enabled?
647 // has the native window for this been created yet?
649 // whether we handle touch event
650 bool mHandleTouchEvent
: 1;
651 // true if this is a drag and drop feedback popup
652 bool mIsDragPopup
: 1;
653 bool mCompositedScreen
: 1;
654 bool mIsAccelerated
: 1;
655 bool mWindowShouldStartDragging
: 1;
656 bool mHasMappedToplevel
: 1;
657 bool mRetryPointerGrab
: 1;
658 bool mPanInProgress
: 1;
659 // Draw titlebar with :backdrop css state (inactive/unfocused).
660 bool mTitlebarBackdropState
: 1;
661 // It's child window, i.e. window which is nested in parent window.
662 // This is obsoleted and should not be used.
663 // We use GdkWindow hierarchy for such windows.
664 bool mIsChildWindow
: 1;
665 bool mAlwaysOnTop
: 1;
666 bool mNoAutoHide
: 1;
667 bool mIsTransparent
: 1;
668 // We can expect at least one size-allocate event after early resizes.
669 bool mHasReceivedSizeAllocate
: 1;
670 bool mWidgetCursorLocked
: 1;
671 bool mUndecorated
: 1;
673 /* Gkt creates popup in two incarnations - wl_subsurface and xdg_popup.
674 * Kind of popup is choosen before GdkWindow is mapped so we can change
675 * it only when GdkWindow is hidden.
677 * Relevant Gtk code is at gdkwindow-wayland.c
678 * in should_map_as_popup() and should_map_as_subsurface()
681 * - can't be positioned by move-to-rect
682 * - can stand outside popup widget hierarchy (has toplevel as parent)
683 * - don't have child popup widgets
686 * - can be positioned by move-to-rect
687 * - aligned in popup widget hierarchy, first one is attached to toplevel
688 * - has child (popup) widgets
690 * Thus we need to map Firefox popup type to desired Gtk one:
697 * - autohide popups (hamburger menu)
701 * We set mPopupTrackInHierarchy = false for pernament panels which
702 * are always mapped to toplevel and painted as wl_surfaces.
704 bool mPopupTrackInHierarchy
: 1;
705 bool mPopupTrackInHierarchyConfigured
: 1;
707 /* On X11 Gtk tends to ignore window position requests when gtk_window
708 * is hidden. Save the position requests at mPopupPosition and apply
709 * when the widget is shown.
711 bool mHiddenPopupPositioned
: 1;
713 // The transparency bitmap is used instead of ARGB visual for toplevel
714 // window to draw titlebar.
715 bool mTransparencyBitmapForTitlebar
: 1;
717 // True when we're on compositing window manager and this
718 // window is using visual with alpha channel.
719 bool mHasAlphaVisual
: 1;
721 // When popup is anchored, mPopupPosition is relative to its parent popup.
722 bool mPopupAnchored
: 1;
724 // When popup is context menu.
725 bool mPopupContextMenu
: 1;
727 // Indicates that this popup matches layout setup so we can use parent popup
728 // coordinates reliably.
729 bool mPopupMatchesLayout
: 1;
731 /* Indicates that popup setup was changed and
732 * we need to recalculate popup coordinates.
734 bool mPopupChanged
: 1;
736 // Popup is hidden only as a part of hierarchy tree update.
737 bool mPopupTemporaryHidden
: 1;
739 // Popup is going to be closed and removed.
740 bool mPopupClosed
: 1;
742 // Popup is positioned by gdk_window_move_to_rect()
743 bool mPopupUseMoveToRect
: 1;
745 /* mWaitingForMoveToRectCallback is set when move-to-rect is called
746 * and we're waiting for move-to-rect callback.
748 * If another position/resize request comes between move-to-rect call and
749 * move-to-rect callback we set mMovedAfterMoveToRect/mResizedAfterMoveToRect.
751 bool mWaitingForMoveToRectCallback
: 1;
752 bool mMovedAfterMoveToRect
: 1;
753 bool mResizedAfterMoveToRect
: 1;
755 // Params used for popup placemend by GdkWindowMoveToRect.
756 // When popup is only resized and not positioned,
757 // we need to reuse last GdkWindowMoveToRect params to avoid
759 struct WaylandPopupMoveToRectParams
{
760 LayoutDeviceIntRect mAnchorRect
= {0, 0, 0, 0};
761 GdkGravity mAnchorRectType
= GDK_GRAVITY_NORTH_WEST
;
762 GdkGravity mPopupAnchorType
= GDK_GRAVITY_NORTH_WEST
;
763 GdkAnchorHints mHints
= GDK_ANCHOR_SLIDE
;
764 GdkPoint mOffset
= {0, 0};
765 bool mAnchorSet
= false;
768 WaylandPopupMoveToRectParams mPopupMoveToRectParams
;
770 // Whether we've configured default clear color already.
771 bool mConfiguredClearColor
: 1;
772 // Whether we've received a non-blank paint in which case we can reset the
773 // clear color to transparent.
774 bool mGotNonBlankPaint
: 1;
776 // Whether we need to retry capturing the mouse because we' re not mapped yet.
777 bool mNeedsToRetryCapturingMouse
: 1;
779 // This bitmap tracks which pixels are transparent. We don't support
780 // full translucency at this time; each pixel is either fully opaque
781 // or fully transparent.
782 gchar
* mTransparencyBitmap
= nullptr;
783 int32_t mTransparencyBitmapWidth
= 0;
784 int32_t mTransparencyBitmapHeight
= 0;
786 // all of our DND stuff
787 void InitDragEvent(mozilla::WidgetDragEvent
& aEvent
);
789 float mLastMotionPressure
= 0.0f
;
791 InputRegion mInputRegion
;
793 static bool DragInProgress(void);
795 void DispatchMissedButtonReleases(GdkEventCrossing
* aGdkEvent
);
797 // When window widget gets mapped/unmapped we need to configure
798 // underlying GdkWindow properly. Otherwise we'll end up with
799 // rendering to released window.
800 void ConfigureGdkWindow();
801 void ReleaseGdkWindow();
802 void ConfigureCompositor();
804 bool IsAlwaysUndecoratedWindow() const;
807 WindowRenderer
* GetWindowRenderer() override
;
808 void DidGetNonBlankPaint() override
;
810 void SetCompositorWidgetDelegate(CompositorWidgetDelegate
* delegate
) override
;
812 int32_t RoundsWidgetCoordinatesTo() override
;
814 void UpdateMozWindowActive();
816 void ForceTitlebarRedraw();
817 bool DoDrawTilebarCorners();
818 bool IsChromeWindowTitlebar();
820 void SetPopupWindowDecoration(bool aShowOnTaskbar
);
822 void ApplySizeConstraints();
824 // Wayland Popup section
825 GdkPoint
WaylandGetParentPosition();
826 bool WaylandPopupConfigure();
827 bool WaylandPopupIsAnchored();
828 bool WaylandPopupIsMenu();
829 bool WaylandPopupIsContextMenu();
830 bool WaylandPopupIsPermanent();
831 // First popup means it's attached directly to toplevel window
832 bool WaylandPopupIsFirst();
833 bool IsWidgetOverflowWindow();
834 void RemovePopupFromHierarchyList();
835 void ShowWaylandPopupWindow();
836 void HideWaylandPopupWindow(bool aTemporaryHidden
, bool aRemoveFromPopupList
);
837 void ShowWaylandToplevelWindow();
838 void HideWaylandToplevelWindow();
839 void WaylandPopupHideTooltips();
840 void WaylandPopupCloseOrphanedPopups();
841 void AppendPopupToHierarchyList(nsWindow
* aToplevelWindow
);
842 void WaylandPopupHierarchyHideTemporary();
843 void WaylandPopupHierarchyShowTemporaryHidden();
844 void WaylandPopupHierarchyCalculatePositions();
845 bool IsInPopupHierarchy();
846 void AddWindowToPopupHierarchy();
847 void UpdateWaylandPopupHierarchy();
848 void WaylandPopupHierarchyHideByLayout(
849 nsTArray
<nsIWidget
*>* aLayoutWidgetHierarchy
);
850 void WaylandPopupHierarchyValidateByLayout(
851 nsTArray
<nsIWidget
*>* aLayoutWidgetHierarchy
);
852 void CloseAllPopupsBeforeRemotePopup();
853 void WaylandPopupHideClosedPopups();
854 void WaylandPopupPrepareForMove();
855 void WaylandPopupMoveImpl();
856 void WaylandPopupMovePlain(int aX
, int aY
);
857 bool WaylandPopupRemoveNegativePosition(int* aX
= nullptr, int* aY
= nullptr);
858 bool WaylandPopupCheckAndGetAnchor(GdkRectangle
* aPopupAnchor
,
860 bool WaylandPopupAnchorAdjustForParentPopup(GdkRectangle
* aPopupAnchor
,
862 nsWindow
* GetTopmostWindow();
863 bool IsPopupInLayoutPopupChain(nsTArray
<nsIWidget
*>* aLayoutWidgetHierarchy
,
864 bool aMustMatchParent
);
865 void WaylandPopupMarkAsClosed();
866 void WaylandPopupRemoveClosedPopups();
867 void WaylandPopupSetDirectPosition();
868 bool WaylandPopupFitsToplevelWindow(bool aMove
);
869 const WaylandPopupMoveToRectParams
WaylandPopupGetPositionFromLayout();
870 void WaylandPopupPropagateChangesToLayout(bool aMove
, bool aResize
);
871 nsWindow
* WaylandPopupFindLast(nsWindow
* aPopup
);
872 GtkWindow
* GetCurrentTopmostWindow() const;
873 nsAutoCString
GetFrameTag() const;
874 nsCString
GetPopupTypeName();
875 bool IsPopupDirectionRTL();
878 void LogPopupHierarchy();
879 void LogPopupAnchorHints(int aHints
);
880 void LogPopupGravity(GdkGravity aGravity
);
883 bool IsTopLevelWindowType() const {
884 return mWindowType
== WindowType::TopLevel
||
885 mWindowType
== WindowType::Dialog
;
888 // mPopupPosition is the original popup position/size from layout, set by
889 // nsWindow::Move() or nsWindow::Resize().
890 // Popup position is relative to main (toplevel) window.
891 GdkPoint mPopupPosition
{};
893 // mRelativePopupPosition is popup position calculated against
894 // recent popup parent window.
895 GdkPoint mRelativePopupPosition
{};
897 // Toplevel window (first element) of linked list of Wayland popups. It's null
898 // if we're the toplevel.
899 RefPtr
<nsWindow
> mWaylandToplevel
;
901 // Next/Previous popups in Wayland popup hierarchy.
902 RefPtr
<nsWindow
> mWaylandPopupNext
;
903 RefPtr
<nsWindow
> mWaylandPopupPrev
;
905 // When popup is resized by Gtk by move-to-rect callback,
906 // we store final popup size here. Then we use mMoveToRectPopupSize size
907 // in following popup operations unless mLayoutPopupSizeCleared is set.
908 LayoutDeviceIntSize mMoveToRectPopupSize
;
911 * |mIMContext| takes all IME related stuff.
913 * This is owned by the top-level nsWindow or the topmost child
914 * nsWindow embedded in a non-Gecko widget.
916 * The instance is created when the top level widget is created. And when
917 * the widget is destroyed, it's released. All child windows refer its
918 * ancestor widget's instance. So, one set of IM contexts is created for
919 * all windows in a hierarchy. If the children are released after the top
920 * level window is released, the children still have a valid pointer,
921 * however, IME doesn't work at that time.
923 RefPtr
<mozilla::widget::IMContextWrapper
> mIMContext
;
926 mozilla::UniquePtr
<mozilla::CurrentX11TimeGetter
> mCurrentTimeGetter
;
928 static GtkWindowDecoration sGtkWindowDecoration
;
930 static bool sTransparentMainWindow
;
933 RefPtr
<mozilla::a11y::LocalAccessible
> mRootAccessible
;
936 * Request to create the accessible for this window if it is top level.
938 void CreateRootAccessible();
941 * Dispatch accessible event for the top level window accessible.
943 * @param aEventType [in] the accessible event type to dispatch
945 void DispatchEventToRootAccessible(uint32_t aEventType
);
948 * Dispatch accessible window activate event for the top level window
951 void DispatchActivateEventAccessible();
954 * Dispatch accessible window deactivate event for the top level window
957 void DispatchDeactivateEventAccessible();
960 * Dispatch accessible window maximize event for the top level window
963 void DispatchMaximizeEventAccessible();
966 * Dispatch accessible window minize event for the top level window
969 void DispatchMinimizeEventAccessible();
972 * Dispatch accessible window restore event for the top level window
975 void DispatchRestoreEventAccessible();
978 void SetUserTimeAndStartupTokenForActivatedWindow();
980 void KioskLockOnMonitor();
982 void EmulateResizeDrag(GdkEventMotion
* aEvent
);
985 typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT
= 0,
986 GTK_WIDGET_COMPOSIDED_DISABLED
= 1,
987 GTK_WIDGET_COMPOSIDED_ENABLED
= 2} WindowComposeRequest
;
988 void SetCompositorHint(WindowComposeRequest aState
);
989 bool ConfigureX11GLVisual();
992 RefPtr
<mozilla::WaylandVsyncSource
> mWaylandVsyncSource
;
993 RefPtr
<mozilla::VsyncDispatcher
> mWaylandVsyncDispatcher
;
994 LayoutDeviceIntPoint mNativePointerLockCenter
;
995 zwp_locked_pointer_v1
* mLockedPointer
= nullptr;
996 zwp_relative_pointer_v1
* mRelativePointer
= nullptr;
998 // An activation token from our environment (see handling of the
999 // XDG_ACTIVATION_TOKEN/DESKTOP_STARTUP_ID) env vars.
1000 nsCString mWindowActivationTokenFromEnv
;
1001 mozilla::widget::WindowSurfaceProvider mSurfaceProvider
;
1002 GdkDragContext
* mSourceDragContext
= nullptr;
1004 LayoutDeviceIntRect mLastLoggedBoundSize
;
1005 int mLastLoggedScale
= -1;
1007 // Running in kiosk mode and requested to stay on specified monitor.
1008 // If monitor is removed minimize the window.
1009 mozilla::Maybe
<int> mKioskMonitor
;
1012 #endif /* __nsWindow_h__ */