summaryrefslogtreecommitdiffstats
path: root/widget/gtk/nsWindow.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gtk/nsWindow.h')
-rw-r--r--widget/gtk/nsWindow.h994
1 files changed, 994 insertions, 0 deletions
diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
new file mode 100644
index 0000000000..e394ced73b
--- /dev/null
+++ b/widget/gtk/nsWindow.h
@@ -0,0 +1,994 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=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 __nsWindow_h__
+#define __nsWindow_h__
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "CompositorWidget.h"
+#include "MozContainer.h"
+#include "VsyncSource.h"
+#include "mozilla/EventForwards.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/TouchEvents.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/widget/WindowSurface.h"
+#include "mozilla/widget/WindowSurfaceProvider.h"
+#include "nsBaseWidget.h"
+#include "nsGkAtoms.h"
+#include "nsIDragService.h"
+#include "nsRefPtrHashtable.h"
+#include "IMContextWrapper.h"
+
+#ifdef ACCESSIBILITY
+# include "mozilla/a11y/LocalAccessible.h"
+#endif
+
+#ifdef MOZ_X11
+# include <gdk/gdkx.h>
+# include "X11UndefineNone.h"
+#endif
+#ifdef MOZ_WAYLAND
+# include <gdk/gdkwayland.h>
+# include "base/thread.h"
+# include "WaylandVsyncSource.h"
+# include "nsClipboardWayland.h"
+#endif
+
+#ifdef MOZ_LOGGING
+
+# include "mozilla/Logging.h"
+# include "nsTArray.h"
+# include "Units.h"
+
+extern mozilla::LazyLogModule gWidgetLog;
+extern mozilla::LazyLogModule gWidgetDragLog;
+extern mozilla::LazyLogModule gWidgetPopupLog;
+extern mozilla::LazyLogModule gWidgetVsync;
+
+# define LOG(str, ...) \
+ MOZ_LOG(IsPopup() ? gWidgetPopupLog : gWidgetLog, \
+ mozilla::LogLevel::Debug, \
+ ("%s: " str, GetDebugTag().get(), ##__VA_ARGS__))
+# define LOGW(...) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+# define LOGDRAG(...) \
+ MOZ_LOG(gWidgetDragLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+# define LOG_POPUP(...) \
+ MOZ_LOG(gWidgetPopupLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+# define LOG_VSYNC(...) \
+ MOZ_LOG(gWidgetVsync, mozilla::LogLevel::Debug, (__VA_ARGS__))
+# define LOG_ENABLED() \
+ (MOZ_LOG_TEST(gWidgetPopupLog, mozilla::LogLevel::Debug) || \
+ MOZ_LOG_TEST(gWidgetLog, mozilla::LogLevel::Debug))
+
+#else
+
+# define LOG(...)
+# define LOGW(...)
+# define LOGDRAG(...)
+# define LOG_POPUP(...)
+# define LOG_ENABLED() false
+
+#endif /* MOZ_LOGGING */
+
+#if defined(MOZ_WAYLAND) && !defined(MOZ_X11)
+typedef uintptr_t Window;
+#endif
+
+class gfxPattern;
+class nsIFrame;
+#if !GTK_CHECK_VERSION(3, 18, 0)
+struct _GdkEventTouchpadPinch;
+typedef struct _GdkEventTouchpadPinch GdkEventTouchpadPinch;
+#endif
+
+#if !GTK_CHECK_VERSION(3, 22, 0)
+typedef enum {
+ GDK_ANCHOR_FLIP_X = 1 << 0,
+ GDK_ANCHOR_FLIP_Y = 1 << 1,
+ GDK_ANCHOR_SLIDE_X = 1 << 2,
+ GDK_ANCHOR_SLIDE_Y = 1 << 3,
+ GDK_ANCHOR_RESIZE_X = 1 << 4,
+ GDK_ANCHOR_RESIZE_Y = 1 << 5,
+ GDK_ANCHOR_FLIP = GDK_ANCHOR_FLIP_X | GDK_ANCHOR_FLIP_Y,
+ GDK_ANCHOR_SLIDE = GDK_ANCHOR_SLIDE_X | GDK_ANCHOR_SLIDE_Y,
+ GDK_ANCHOR_RESIZE = GDK_ANCHOR_RESIZE_X | GDK_ANCHOR_RESIZE_Y
+} GdkAnchorHints;
+#endif
+
+namespace mozilla {
+enum class NativeKeyBindingsType : uint8_t;
+
+class TimeStamp;
+#ifdef MOZ_X11
+class CurrentX11TimeGetter;
+#endif
+} // namespace mozilla
+
+class nsWindow final : public nsBaseWidget {
+ public:
+ typedef mozilla::gfx::DrawTarget DrawTarget;
+ typedef mozilla::WidgetEventTime WidgetEventTime;
+ typedef mozilla::WidgetKeyboardEvent WidgetKeyboardEvent;
+ typedef mozilla::widget::PlatformCompositorWidgetDelegate
+ PlatformCompositorWidgetDelegate;
+
+ nsWindow();
+
+ static void ReleaseGlobals();
+
+ NS_INLINE_DECL_REFCOUNTING_INHERITED(nsWindow, nsBaseWidget)
+
+ nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
+ nsEventStatus& aStatus) override;
+
+ // called when we are destroyed
+ void OnDestroy() override;
+
+ // called to check and see if a widget's dimensions are sane
+ bool AreBoundsSane(void);
+
+ // nsIWidget
+ using nsBaseWidget::Create; // for Create signature not overridden here
+ [[nodiscard]] nsresult Create(nsIWidget* aParent,
+ nsNativeWidget aNativeParent,
+ const LayoutDeviceIntRect& aRect,
+ nsWidgetInitData* aInitData) override;
+ void Destroy() override;
+ nsIWidget* GetParent() override;
+ float GetDPI() override;
+ double GetDefaultScaleInternal() override;
+ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override;
+ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScaleByScreen()
+ override;
+ void SetParent(nsIWidget* aNewParent) override;
+ void SetModal(bool aModal) override;
+ bool IsVisible() const override;
+ void ConstrainPosition(bool aAllowSlop, int32_t* aX, int32_t* aY) override;
+ void SetSizeConstraints(const SizeConstraints& aConstraints) override;
+ void LockAspectRatio(bool aShouldLock) override;
+ void Move(double aX, double aY) override;
+ void Show(bool aState) override;
+ void Resize(double aWidth, double aHeight, bool aRepaint) override;
+ void Resize(double aX, double aY, double aWidth, double aHeight,
+ bool aRepaint) override;
+ bool IsEnabled() const override;
+
+ void SetZIndex(int32_t aZIndex) override;
+ nsSizeMode SizeMode() override { return mSizeMode; }
+ void SetSizeMode(nsSizeMode aMode) override;
+ void GetWorkspaceID(nsAString& workspaceID) override;
+ void MoveToWorkspace(const nsAString& workspaceID) override;
+ void Enable(bool aState) override;
+ void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override;
+ LayoutDeviceIntRect GetScreenBounds() override;
+ LayoutDeviceIntRect GetClientBounds() override;
+ LayoutDeviceIntSize GetClientSize() override;
+ LayoutDeviceIntPoint GetClientOffset() override { return mClientOffset; }
+
+ // Recomputes the client offset according to our current window position.
+ // If aNotify is true, NotifyWindowMoved will be called on client offset
+ // changes.
+ //
+ // NOTE(emilio): It seems that as long any change here update either the size
+ // or the position of the window, we should be doing fine without notifying,
+ // but this is done to preserve existing behavior.
+ void RecomputeClientOffset(bool aNotify);
+
+ void SetCursor(const Cursor&) override;
+ void Invalidate(const LayoutDeviceIntRect& aRect) override;
+ void* GetNativeData(uint32_t aDataType) override;
+ nsresult SetTitle(const nsAString& aTitle) override;
+ void SetIcon(const nsAString& aIconSpec) override;
+ void SetWindowClass(const nsAString& xulWinType) override;
+ LayoutDeviceIntPoint WidgetToScreenOffset() override;
+ void CaptureRollupEvents(bool aDoCapture) override;
+ [[nodiscard]] nsresult GetAttention(int32_t aCycleCount) override;
+ bool HasPendingInputEvent() override;
+
+ bool PrepareForFullscreenTransition(nsISupports** aData) override;
+ void PerformFullscreenTransition(FullscreenTransitionStage aStage,
+ uint16_t aDuration, nsISupports* aData,
+ nsIRunnable* aCallback) override;
+ already_AddRefed<nsIScreen> GetWidgetScreen() override;
+ nsresult MakeFullScreen(bool aFullScreen) override;
+ void HideWindowChrome(bool aShouldHide) override;
+
+ /**
+ * GetLastUserInputTime returns a timestamp for the most recent user input
+ * event. This is intended for pointer grab requests (including drags).
+ */
+ static guint32 GetLastUserInputTime();
+
+ // utility method, -1 if no change should be made, otherwise returns a
+ // value that can be passed to gdk_window_set_decorations
+ gint ConvertBorderStyles(nsBorderStyle aStyle);
+
+ mozilla::widget::IMContextWrapper* GetIMContext() const { return mIMContext; }
+
+ bool DispatchCommandEvent(nsAtom* aCommand);
+ bool DispatchContentCommandEvent(mozilla::EventMessage aMsg);
+
+ // event callbacks
+ gboolean OnExposeEvent(cairo_t* cr);
+ gboolean OnConfigureEvent(GtkWidget* aWidget, GdkEventConfigure* aEvent);
+ void OnMap();
+ void OnUnmap();
+ void OnUnrealize();
+ void OnSizeAllocate(GtkAllocation* aAllocation);
+ void OnDeleteEvent();
+ void OnEnterNotifyEvent(GdkEventCrossing* aEvent);
+ void OnLeaveNotifyEvent(GdkEventCrossing* aEvent);
+ void OnMotionNotifyEvent(GdkEventMotion* aEvent);
+ void OnButtonPressEvent(GdkEventButton* aEvent);
+ void OnButtonReleaseEvent(GdkEventButton* aEvent);
+ void OnContainerFocusInEvent(GdkEventFocus* aEvent);
+ void OnContainerFocusOutEvent(GdkEventFocus* aEvent);
+ gboolean OnKeyPressEvent(GdkEventKey* aEvent);
+ gboolean OnKeyReleaseEvent(GdkEventKey* aEvent);
+
+ void OnScrollEvent(GdkEventScroll* aEvent);
+
+ void OnWindowStateEvent(GtkWidget* aWidget, GdkEventWindowState* aEvent);
+ void OnDragDataReceivedEvent(GtkWidget* aWidget, GdkDragContext* aDragContext,
+ gint aX, gint aY,
+ GtkSelectionData* aSelectionData, guint aInfo,
+ guint aTime, gpointer aData);
+ gboolean OnPropertyNotifyEvent(GtkWidget* aWidget, GdkEventProperty* aEvent);
+ gboolean OnTouchEvent(GdkEventTouch* aEvent);
+ gboolean OnTouchpadPinchEvent(GdkEventTouchpadPinch* aEvent);
+
+ gint GetInputRegionMarginInGdkCoords();
+
+ void UpdateTopLevelOpaqueRegion();
+
+ already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawingInRegion(
+ const LayoutDeviceIntRegion& aInvalidRegion,
+ mozilla::layers::BufferMode* aBufferMode) override;
+ void EndRemoteDrawingInRegion(
+ mozilla::gfx::DrawTarget* aDrawTarget,
+ const LayoutDeviceIntRegion& aInvalidRegion) override;
+
+ void SetProgress(unsigned long progressPercent);
+
+ RefPtr<mozilla::VsyncDispatcher> GetVsyncDispatcher() override;
+ bool SynchronouslyRepaintOnResize() override;
+
+ void OnDPIChanged(void);
+ void OnCheckResize(void);
+ void OnCompositedChanged(void);
+ void OnScaleChanged();
+ void DispatchResized();
+
+ static guint32 sLastButtonPressTime;
+
+ MozContainer* GetMozContainer() { return mContainer; }
+ LayoutDeviceIntSize GetMozContainerSize();
+ GdkWindow* GetGdkWindow() const { return mGdkWindow; };
+ GdkWindow* GetToplevelGdkWindow() const;
+ GtkWidget* GetGtkWidget() const { return mShell; }
+ nsIFrame* GetFrame() const;
+ nsWindow* GetEffectiveParent();
+ bool IsDestroyed() const { return mIsDestroyed; }
+ bool IsMapped() const { return mIsMapped; }
+ bool IsPopup() const;
+ bool IsWaylandPopup() const;
+ bool IsPIPWindow() const { return mIsPIPWindow; };
+ bool IsDragPopup() { return mIsDragPopup; };
+
+ nsAutoCString GetDebugTag() const;
+
+ void DispatchDragEvent(mozilla::EventMessage aMsg,
+ const LayoutDeviceIntPoint& aRefPoint, guint aTime);
+ static void UpdateDragStatus(GdkDragContext* aDragContext,
+ nsIDragService* aDragService);
+ void SetDragSource(GdkDragContext* aSourceDragContext);
+
+ WidgetEventTime GetWidgetEventTime(guint32 aEventTime);
+ mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime);
+#ifdef MOZ_X11
+ mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter();
+#endif
+
+ void SetInputContext(const InputContext& aContext,
+ const InputContextAction& aAction) override;
+ InputContext GetInputContext() override;
+ TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override;
+ MOZ_CAN_RUN_SCRIPT bool GetEditCommands(
+ mozilla::NativeKeyBindingsType aType,
+ const mozilla::WidgetKeyboardEvent& aEvent,
+ nsTArray<mozilla::CommandInt>& aCommands) override;
+
+ // These methods are for toplevel windows only.
+ void ResizeTransparencyBitmap();
+ void ApplyTransparencyBitmap();
+ void ClearTransparencyBitmap();
+
+ void SetTransparencyMode(nsTransparencyMode aMode) override;
+ nsTransparencyMode GetTransparencyMode() override;
+ void SetInputRegion(const InputRegion&) override;
+ nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
+ uint8_t* aAlphas,
+ int32_t aStride);
+ void ReparentNativeWidget(nsIWidget* aNewParent) override;
+
+ void UpdateTitlebarTransparencyBitmap();
+
+ 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 SynthesizeNativeTouchPoint(uint32_t aPointerId,
+ TouchPointerState aPointerState,
+ LayoutDeviceIntPoint aPoint,
+ double aPointerPressure,
+ uint32_t aPointerOrientation,
+ nsIObserver* aObserver) override;
+
+ nsresult SynthesizeNativeTouchPadPinch(TouchpadGesturePhase aEventPhase,
+ float aScale,
+ LayoutDeviceIntPoint aPoint,
+ int32_t aModifierFlags) override;
+
+ nsresult SynthesizeNativeTouchpadPan(TouchpadGesturePhase aEventPhase,
+ LayoutDeviceIntPoint aPoint,
+ double aDeltaX, double aDeltaY,
+ int32_t aModifierFlags,
+ nsIObserver* aObserver) override;
+
+ void GetCompositorWidgetInitData(
+ mozilla::widget::CompositorWidgetInitData* aInitData) override;
+
+ nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
+ void SetDrawsInTitlebar(bool aState) override;
+ mozilla::LayoutDeviceIntCoord GetTitlebarRadius();
+ LayoutDeviceIntRect GetTitlebarRect();
+ void UpdateWindowDraggingRegion(
+ const LayoutDeviceIntRegion& aRegion) override;
+
+ // HiDPI scale conversion
+ gint GdkCeiledScaleFactor();
+ bool UseFractionalScale() const;
+ double FractionalScaleFactor();
+
+ // To GDK
+ gint DevicePixelsToGdkCoordRoundUp(int);
+ gint DevicePixelsToGdkCoordRoundDown(int);
+ GdkPoint DevicePixelsToGdkPointRoundDown(const LayoutDeviceIntPoint&);
+ GdkRectangle DevicePixelsToGdkSizeRoundUp(const LayoutDeviceIntSize&);
+ GdkRectangle DevicePixelsToGdkRectRoundOut(const LayoutDeviceIntRect&);
+
+ // From GDK
+ int GdkCoordToDevicePixels(gint);
+ LayoutDeviceIntPoint GdkPointToDevicePixels(const GdkPoint&);
+ LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble aX, gdouble aY);
+ LayoutDeviceIntRect GdkRectToDevicePixels(const GdkRectangle&);
+
+ bool WidgetTypeSupportsAcceleration() override;
+
+ nsresult SetSystemFont(const nsCString& aFontName) override;
+ nsresult GetSystemFont(nsCString& aFontName) override;
+
+ typedef enum {
+ GTK_DECORATION_SYSTEM, // CSD including shadows
+ GTK_DECORATION_CLIENT, // CSD without shadows
+ GTK_DECORATION_NONE, // WM does not support CSD at all
+ } GtkWindowDecoration;
+ /**
+ * Get the support of Client Side Decoration by checking the desktop
+ * environment.
+ */
+ static GtkWindowDecoration GetSystemGtkWindowDecoration();
+
+ static bool GetTopLevelWindowActiveState(nsIFrame* aFrame);
+ static bool TitlebarUseShapeMask();
+ bool IsRemoteContent() { return HasRemoteContent(); }
+ void NativeMoveResizeWaylandPopupCallback(const GdkRectangle* aFinalSize,
+ bool aFlippedX, bool aFlippedY);
+ static bool IsToplevelWindowTransparent();
+
+ static nsWindow* GetFocusedWindow();
+
+#ifdef MOZ_WAYLAND
+ // Use xdg-activation protocol to transfer focus from gFocusWindow to aWindow.
+ static void TransferFocusToWaylandWindow(nsWindow* aWindow);
+ void FocusWaylandWindow(const char* aTokenID);
+
+ bool GetCSDDecorationOffset(int* aDx, int* aDy);
+ void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize);
+ void WaylandDragWorkaround(GdkEventButton* aEvent);
+
+ wl_display* GetWaylandDisplay();
+ void CreateCompositorVsyncDispatcher() override;
+ LayoutDeviceIntPoint GetNativePointerLockCenter() {
+ return mNativePointerLockCenter;
+ }
+ void SetNativePointerLockCenter(
+ const LayoutDeviceIntPoint& aLockCenter) override;
+ void LockNativePointer() override;
+ void UnlockNativePointer() override;
+ LayoutDeviceIntSize GetMoveToRectPopupSize() const override {
+ return mMoveToRectPopupSize;
+ };
+#endif
+
+ typedef enum {
+ // WebRender compositor is enabled
+ COMPOSITOR_ENABLED,
+ // WebRender compositor is paused as we're repainting whole window and
+ // we're waiting for content process to update page content.
+ COMPOSITOR_PAUSED_FLICKERING
+ } WindowCompositorState;
+
+ // Pause compositor to avoid rendering artifacts from content process.
+ void ResumeCompositorImpl();
+ void ResumeCompositorFlickering();
+ void ResumeCompositorFromCompositorThread();
+ void PauseCompositorFlickering();
+ bool IsWaitingForCompositorResume();
+
+ // Force hide this window, remove compositor etc. to avoid
+ // rendering queue blocking (see Bug 1782948).
+ void ClearRenderingQueue();
+
+ bool ApplyEnterLeaveMutterWorkaround();
+
+ void NotifyOcclusionState(mozilla::widget::OcclusionState aState) override;
+
+ static nsWindow* GetWindow(GdkWindow* window);
+
+ protected:
+ virtual ~nsWindow();
+
+ // event handling code
+ void DispatchActivateEvent(void);
+ void DispatchDeactivateEvent(void);
+ void MaybeDispatchResized();
+ void DispatchPanGesture(mozilla::PanGestureInput& aPanInput);
+
+ void RegisterTouchWindow() override;
+
+ nsCOMPtr<nsIWidget> mParent;
+ nsPopupType mPopupHint{};
+ int mWindowScaleFactor = 1;
+
+ void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface,
+ nsIntRect aBoundsRect);
+
+ void NativeMoveResize(bool aMoved, bool aResized);
+
+ void NativeShow(bool aAction);
+ void SetHasMappedToplevel(bool aState);
+ LayoutDeviceIntSize GetSafeWindowSize(LayoutDeviceIntSize aSize);
+
+ void DispatchContextMenuEventFromMouseEvent(
+ uint16_t domButton, GdkEventButton* aEvent,
+ const mozilla::LayoutDeviceIntPoint& aRefPoint);
+
+ void TryToShowNativeWindowMenu(GdkEventButton* aEvent);
+
+ void WaylandStartVsync();
+ void WaylandStopVsync();
+ void DestroyChildWindows();
+ GtkWidget* GetToplevelWidget() const;
+ nsWindow* GetContainerWindow() const;
+ Window GetX11Window();
+ bool GetShapedState();
+ void EnsureGdkWindow();
+ void SetUrgencyHint(GtkWidget* top_window, bool state);
+ void SetDefaultIcon(void);
+ void SetWindowDecoration(nsBorderStyle aStyle);
+ void InitButtonEvent(mozilla::WidgetMouseEvent& aEvent,
+ GdkEventButton* aGdkEvent,
+ const mozilla::LayoutDeviceIntPoint& aRefPoint);
+ bool CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel,
+ bool aAlwaysRollup);
+ void CheckForRollupDuringGrab() { CheckForRollup(0, 0, false, true); }
+
+ bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent, GdkWindow** aWindow,
+ gint* aButton, gint* aRootX, gint* aRootY);
+ nsIWidgetListener* GetListener();
+
+ nsWindow* GetTransientForWindowIfPopup();
+ bool IsHandlingTouchSequence(GdkEventSequence* aSequence);
+
+ void ResizeInt(const mozilla::Maybe<LayoutDeviceIntPoint>& aMove,
+ LayoutDeviceIntSize aSize);
+ void NativeMoveResizeWaylandPopup(bool aMove, bool aResize);
+
+ // Returns true if the given point (in device pixels) is within a resizer
+ // region of the window. Only used when drawing decorations client side.
+ bool CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge);
+
+ GtkTextDirection GetTextDirection();
+
+ void AddCSDDecorationSize(int* aWidth, int* aHeight);
+
+ void CreateAndPutGdkScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
+ double aDeltaX, double aDeltaY);
+
+ nsCString mGtkWindowAppName;
+ nsCString mGtkWindowRoleName;
+ void RefreshWindowClass();
+
+ GtkWidget* mShell = nullptr;
+ MozContainer* mContainer = nullptr;
+ GdkWindow* mGdkWindow = nullptr;
+ PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate = nullptr;
+ mozilla::Atomic<WindowCompositorState, mozilla::Relaxed> mCompositorState{
+ COMPOSITOR_ENABLED};
+ // This is used in COMPOSITOR_PAUSED_FLICKERING mode only to resume compositor
+ // in some reasonable time when page content is not updated.
+ guint mCompositorPauseTimeoutID = 0;
+
+ // The actual size mode that's in effect.
+ nsSizeMode mSizeMode = nsSizeMode_Normal;
+ // The last size mode we've requested. This might not match mSizeMode if
+ // there's a request to change the size mode in progress.
+ nsSizeMode mLastSizeModeRequest = nsSizeMode_Normal;
+ nsSizeMode mLastSizeModeBeforeFullscreen = nsSizeMode_Normal;
+
+ float mAspectRatio = 0.0f;
+ float mAspectRatioSaved = 0.0f;
+
+ // The size requested, which might not be reflected in mBounds. Used in
+ // WaylandPopupSetDirectPosition() to remember intended size for popup
+ // positioning, in LockAspect() to remember the intended aspect ratio, and
+ // to remember a size requested while waiting for moved-to-rect when
+ // OnSizeAllocate() might change mBounds.Size().
+ LayoutDeviceIntSize mLastSizeRequest;
+ LayoutDeviceIntPoint mClientOffset;
+ // Indicates a new size that still needs to be dispatched.
+ LayoutDeviceIntSize mNeedsDispatchSize = LayoutDeviceIntSize(-1, -1);
+
+ // This field omits duplicate scroll events caused by GNOME bug 726878.
+ guint32 mLastScrollEventTime = GDK_CURRENT_TIME;
+ mozilla::ScreenCoord mLastPinchEventSpan;
+
+ struct TouchpadPinchGestureState {
+ // Focus point of the PHASE_BEGIN event
+ ScreenPoint mBeginFocus;
+
+ // Focus point of the most recent PHASE_UPDATE event
+ ScreenPoint mCurrentFocus;
+ };
+
+ // Used for handling touchpad pinch gestures
+ ScreenPoint mCurrentTouchpadFocus;
+
+ // Used for synthesizing touchpad pinch gestures
+ TouchpadPinchGestureState mCurrentSynthesizedTouchpadPinch;
+
+ // Used for synthesizing touchpad pan gestures
+ struct TouchpadPanGestureState {
+ mozilla::Maybe<TouchpadGesturePhase> mTouchpadGesturePhase;
+ uint64_t mSavedObserver = 0;
+ };
+
+ // Used for synthesizing touchpad pan gestures
+ TouchpadPanGestureState mCurrentSynthesizedTouchpadPan;
+
+ // for touch event handling
+ nsRefPtrHashtable<nsPtrHashKey<GdkEventSequence>, mozilla::dom::Touch>
+ mTouches;
+
+ // Upper bound on pending ConfigureNotify events to be dispatched to the
+ // window. See bug 1225044.
+ unsigned int mPendingConfigures = 0;
+
+ // Window titlebar rendering mode, GTK_DECORATION_NONE if it's disabled
+ // for this window.
+ GtkWindowDecoration mGtkWindowDecoration = GTK_DECORATION_NONE;
+
+ // Draggable titlebar region maintained by UpdateWindowDraggingRegion
+ LayoutDeviceIntRegion mDraggableRegion;
+
+ // The cursor cache
+ static GdkCursor* gsGtkCursorCache[eCursorCount];
+
+ // If true, draw our own window titlebar.
+ //
+ // Needs to be atomic because GetTitlebarRect() gets called from non-main
+ // threads.
+ //
+ // FIXME(emilio): GetTitlebarRect() reads other things that TSAN doesn't
+ // catch because mDrawInTitlebar is false on automation ~always. We should
+ // probably make GetTitlebarRect() simpler / properly thread-safe.
+ mozilla::Atomic<bool, mozilla::Relaxed> mDrawInTitlebar{false};
+
+ // Has this widget been destroyed yet?
+ bool mIsDestroyed;
+ // mIsShown tracks requested visible status from browser perspective, i.e.
+ // if the window should be visible or now.
+ bool mIsShown : 1;
+ // mNeedsShow is set when browser requested to show this window but we failed
+ // to do so for some reason (wrong window size for instance).
+ // In such case we set mIsShown = true and mNeedsShow = true to indicate
+ // that the window is not actually visible but we report to browser that
+ // it is visible (mIsShown == true).
+ bool mNeedsShow : 1;
+ // This track real window visibility from OS perspective.
+ // It's set by OnMap/OnUnrealize which is based on Gtk events.
+ bool mIsMapped : 1;
+ // is this widget enabled?
+ bool mEnabled : 1;
+ // has the native window for this been created yet?
+ bool mCreated : 1;
+ // whether we handle touch event
+ bool mHandleTouchEvent : 1;
+ // true if this is a drag and drop feedback popup
+ bool mIsDragPopup : 1;
+ bool mWindowScaleFactorChanged : 1;
+ bool mCompositedScreen : 1;
+ bool mIsAccelerated : 1;
+ bool mWindowShouldStartDragging : 1;
+ bool mHasMappedToplevel : 1;
+ bool mRetryPointerGrab : 1;
+ bool mPanInProgress : 1;
+ // Use dedicated GdkWindow for mContainer
+ bool mDrawToContainer : 1;
+ // Draw titlebar with :backdrop css state (inactive/unfocused).
+ bool mTitlebarBackdropState : 1;
+ // It's PictureInPicture window.
+ bool mIsPIPWindow : 1;
+ // It's undecorated popup utility window, without resizers/titlebar,
+ // movable by mouse. Used on Wayland for popups without
+ // parent (for instance WebRTC sharing indicator, notifications).
+ bool mIsWaylandPanelWindow : 1;
+ // It's child window, i.e. window which is nested in parent window.
+ // This is obsoleted and should not be used.
+ // We use GdkWindow hierarchy for such windows.
+ bool mIsChildWindow : 1;
+ bool mAlwaysOnTop : 1;
+ bool mNoAutoHide : 1;
+ bool mIsTransparent : 1;
+ // We can expect at least one size-allocate event after early resizes.
+ bool mHasReceivedSizeAllocate : 1;
+
+ /* Gkt creates popup in two incarnations - wl_subsurface and xdg_popup.
+ * Kind of popup is choosen before GdkWindow is mapped so we can change
+ * it only when GdkWindow is hidden.
+ *
+ * Relevant Gtk code is at gdkwindow-wayland.c
+ * in should_map_as_popup() and should_map_as_subsurface()
+ *
+ * wl_subsurface:
+ * - can't be positioned by move-to-rect
+ * - can stand outside popup widget hierarchy (has toplevel as parent)
+ * - don't have child popup widgets
+ *
+ * xdg_popup:
+ * - can be positioned by move-to-rect
+ * - aligned in popup widget hierarchy, first one is attached to toplevel
+ * - has child (popup) widgets
+ *
+ * Thus we need to map Firefox popup type to desired Gtk one:
+ *
+ * wl_subsurface:
+ * - pernament panels
+ *
+ * xdg_popup:
+ * - menus
+ * - autohide popups (hamburger menu)
+ * - extension popups
+ * - tooltips
+ *
+ * We set mPopupTrackInHierarchy = false for pernament panels which
+ * are always mapped to toplevel and painted as wl_surfaces.
+ */
+ bool mPopupTrackInHierarchy : 1;
+ bool mPopupTrackInHierarchyConfigured : 1;
+
+ /* On X11 Gtk tends to ignore window position requests when gtk_window
+ * is hidden. Save the position requests at mPopupPosition and apply
+ * when the widget is shown.
+ */
+ bool mHiddenPopupPositioned : 1;
+
+ // The transparency bitmap is used instead of ARGB visual for toplevel
+ // window to draw titlebar.
+ bool mTransparencyBitmapForTitlebar : 1;
+
+ // True when we're on compositing window manager and this
+ // window is using visual with alpha channel.
+ bool mHasAlphaVisual : 1;
+
+ // When popup is anchored, mPopupPosition is relative to its parent popup.
+ bool mPopupAnchored : 1;
+
+ // When popup is context menu.
+ bool mPopupContextMenu : 1;
+
+ // Indicates that this popup matches layout setup so we can use parent popup
+ // coordinates reliably.
+ bool mPopupMatchesLayout : 1;
+
+ /* Indicates that popup setup was changed and
+ * we need to recalculate popup coordinates.
+ */
+ bool mPopupChanged : 1;
+
+ // Popup is hidden only as a part of hierarchy tree update.
+ bool mPopupTemporaryHidden : 1;
+
+ // Popup is going to be closed and removed.
+ bool mPopupClosed : 1;
+
+ // Popup is positioned by gdk_window_move_to_rect()
+ bool mPopupUseMoveToRect : 1;
+
+ /* mWaitingForMoveToRectCallback is set when move-to-rect is called
+ * and we're waiting for move-to-rect callback.
+ *
+ * If another position/resize request comes between move-to-rect call and
+ * move-to-rect callback we set mMovedAfterMoveToRect/mResizedAfterMoveToRect.
+ */
+ bool mWaitingForMoveToRectCallback : 1;
+ bool mMovedAfterMoveToRect : 1;
+ bool mResizedAfterMoveToRect : 1;
+
+ // Params used for popup placemend by GdkWindowMoveToRect.
+ // When popup is only resized and not positioned,
+ // we need to reuse last GdkWindowMoveToRect params to avoid
+ // popup movement.
+ struct WaylandPopupMoveToRectParams {
+ LayoutDeviceIntRect mAnchorRect = {0, 0, 0, 0};
+ GdkGravity mAnchorRectType = GDK_GRAVITY_NORTH_WEST;
+ GdkGravity mPopupAnchorType = GDK_GRAVITY_NORTH_WEST;
+ GdkAnchorHints mHints = GDK_ANCHOR_SLIDE;
+ GdkPoint mOffset = {0, 0};
+ bool mAnchorSet = false;
+ };
+
+ WaylandPopupMoveToRectParams mPopupMoveToRectParams;
+
+ // Whether we've configured default clear color already.
+ bool mConfiguredClearColor : 1;
+ // Whether we've received a non-blank paint in which case we can reset the
+ // clear color to transparent.
+ bool mGotNonBlankPaint : 1;
+
+ // Whether we need to retry capturing the mouse because we' re not mapped yet.
+ bool mNeedsToRetryCapturingMouse : 1;
+
+ // This bitmap tracks which pixels are transparent. We don't support
+ // full translucency at this time; each pixel is either fully opaque
+ // or fully transparent.
+ gchar* mTransparencyBitmap = nullptr;
+ int32_t mTransparencyBitmapWidth = 0;
+ int32_t mTransparencyBitmapHeight = 0;
+
+ // all of our DND stuff
+ void InitDragEvent(mozilla::WidgetDragEvent& aEvent);
+
+ float mLastMotionPressure = 0.0f;
+
+ InputRegion mInputRegion;
+
+ static bool DragInProgress(void);
+
+ void DispatchMissedButtonReleases(GdkEventCrossing* aGdkEvent);
+
+ // When window widget gets mapped/unmapped we need to configure
+ // underlying GdkWindow properly. Otherwise we'll end up with
+ // rendering to released window.
+ void ConfigureGdkWindow();
+ void ReleaseGdkWindow();
+ void ConfigureCompositor();
+
+ // nsBaseWidget
+ WindowRenderer* GetWindowRenderer() override;
+ void DidGetNonBlankPaint() override;
+
+ void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override;
+
+ int32_t RoundsWidgetCoordinatesTo() override;
+
+ void UpdateMozWindowActive();
+
+ void ForceTitlebarRedraw();
+ bool DoDrawTilebarCorners();
+ bool IsChromeWindowTitlebar();
+
+ void SetPopupWindowDecoration(bool aShowOnTaskbar);
+
+ void ApplySizeConstraints();
+
+ // Wayland Popup section
+ GdkPoint WaylandGetParentPosition();
+ bool WaylandPopupConfigure();
+ bool WaylandPopupIsAnchored();
+ bool WaylandPopupIsMenu();
+ bool WaylandPopupIsContextMenu();
+ bool WaylandPopupIsPermanent();
+ // First popup means it's attached directly to toplevel window
+ bool WaylandPopupIsFirst();
+ bool IsWidgetOverflowWindow();
+ void RemovePopupFromHierarchyList();
+ void ShowWaylandPopupWindow();
+ void HideWaylandPopupWindow(bool aTemporaryHidden, bool aRemoveFromPopupList);
+ void ShowWaylandToplevelWindow();
+ void HideWaylandToplevelWindow();
+ void WaylandPopupHideTooltips();
+ void WaylandPopupCloseOrphanedPopups();
+ void AppendPopupToHierarchyList(nsWindow* aToplevelWindow);
+ void WaylandPopupHierarchyHideTemporary();
+ void WaylandPopupHierarchyShowTemporaryHidden();
+ void WaylandPopupHierarchyCalculatePositions();
+ bool IsInPopupHierarchy();
+ void AddWindowToPopupHierarchy();
+ void UpdateWaylandPopupHierarchy();
+ void WaylandPopupHierarchyHideByLayout(
+ nsTArray<nsIWidget*>* aLayoutWidgetHierarchy);
+ void WaylandPopupHierarchyValidateByLayout(
+ nsTArray<nsIWidget*>* aLayoutWidgetHierarchy);
+ void CloseAllPopupsBeforeRemotePopup();
+ void WaylandPopupHideClosedPopups();
+ void WaylandPopupPrepareForMove();
+ void WaylandPopupMoveImpl();
+ void WaylandPopupMovePlain(int aX, int aY);
+ bool WaylandPopupRemoveNegativePosition(int* aX = nullptr, int* aY = nullptr);
+ bool WaylandPopupCheckAndGetAnchor(GdkRectangle* aPopupAnchor,
+ GdkPoint* aOffset);
+ bool WaylandPopupAnchorAdjustForParentPopup(GdkRectangle* aPopupAnchor,
+ GdkPoint* aOffset);
+ nsWindow* WaylandPopupGetTopmostWindow();
+ bool IsPopupInLayoutPopupChain(nsTArray<nsIWidget*>* aLayoutWidgetHierarchy,
+ bool aMustMatchParent);
+ void WaylandPopupMarkAsClosed();
+ void WaylandPopupRemoveClosedPopups();
+ void WaylandPopupSetDirectPosition();
+ bool WaylandPopupFitsToplevelWindow(bool aMove);
+ const WaylandPopupMoveToRectParams WaylandPopupGetPositionFromLayout();
+ void WaylandPopupPropagateChangesToLayout(bool aMove, bool aResize);
+ nsWindow* WaylandPopupFindLast(nsWindow* aPopup);
+ GtkWindow* GetCurrentTopmostWindow() const;
+ nsAutoCString GetFrameTag() const;
+ nsCString GetPopupTypeName();
+ bool IsPopupDirectionRTL();
+
+#ifdef MOZ_LOGGING
+ void LogPopupHierarchy();
+ void LogPopupAnchorHints(int aHints);
+ void LogPopupGravity(GdkGravity aGravity);
+#endif
+
+ // mPopupPosition is the original popup position/size from layout, set by
+ // nsWindow::Move() or nsWindow::Resize().
+ // Popup position is relative to main (toplevel) window.
+ GdkPoint mPopupPosition{};
+
+ // mRelativePopupPosition is popup position calculated against
+ // recent popup parent window.
+ GdkPoint mRelativePopupPosition{};
+
+ // Toplevel window (first element) of linked list of Wayland popups. It's null
+ // if we're the toplevel.
+ RefPtr<nsWindow> mWaylandToplevel;
+
+ // Next/Previous popups in Wayland popup hierarchy.
+ RefPtr<nsWindow> mWaylandPopupNext;
+ RefPtr<nsWindow> mWaylandPopupPrev;
+
+ // When popup is resized by Gtk by move-to-rect callback,
+ // we store final popup size here. Then we use mMoveToRectPopupSize size
+ // in following popup operations unless mLayoutPopupSizeCleared is set.
+ LayoutDeviceIntSize mMoveToRectPopupSize;
+
+ /**
+ * |mIMContext| takes all IME related stuff.
+ *
+ * This is owned by the top-level nsWindow or the topmost child
+ * nsWindow embedded in a non-Gecko widget.
+ *
+ * The instance is created when the top level widget is created. And when
+ * the widget is destroyed, it's released. All child windows refer its
+ * ancestor widget's instance. So, one set of IM contexts is created for
+ * all windows in a hierarchy. If the children are released after the top
+ * level window is released, the children still have a valid pointer,
+ * however, IME doesn't work at that time.
+ */
+ RefPtr<mozilla::widget::IMContextWrapper> mIMContext;
+
+#ifdef MOZ_X11
+ mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter;
+#endif
+ static GtkWindowDecoration sGtkWindowDecoration;
+
+ static bool sTransparentMainWindow;
+
+#ifdef ACCESSIBILITY
+ RefPtr<mozilla::a11y::LocalAccessible> mRootAccessible;
+
+ /**
+ * Request to create the accessible for this window if it is top level.
+ */
+ void CreateRootAccessible();
+
+ /**
+ * Dispatch accessible event for the top level window accessible.
+ *
+ * @param aEventType [in] the accessible event type to dispatch
+ */
+ void DispatchEventToRootAccessible(uint32_t aEventType);
+
+ /**
+ * Dispatch accessible window activate event for the top level window
+ * accessible.
+ */
+ void DispatchActivateEventAccessible();
+
+ /**
+ * Dispatch accessible window deactivate event for the top level window
+ * accessible.
+ */
+ void DispatchDeactivateEventAccessible();
+
+ /**
+ * Dispatch accessible window maximize event for the top level window
+ * accessible.
+ */
+ void DispatchMaximizeEventAccessible();
+
+ /**
+ * Dispatch accessible window minize event for the top level window
+ * accessible.
+ */
+ void DispatchMinimizeEventAccessible();
+
+ /**
+ * Dispatch accessible window restore event for the top level window
+ * accessible.
+ */
+ void DispatchRestoreEventAccessible();
+#endif
+
+ void SetUserTimeAndStartupTokenForActivatedWindow();
+
+#ifdef MOZ_X11
+ typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
+ GTK_WIDGET_COMPOSIDED_DISABLED = 1,
+ GTK_WIDGET_COMPOSIDED_ENABLED = 2} WindowComposeRequest;
+ void SetCompositorHint(WindowComposeRequest aState);
+ bool ConfigureX11GLVisual();
+#endif
+#ifdef MOZ_WAYLAND
+ RefPtr<mozilla::WaylandVsyncSource> mWaylandVsyncSource;
+ RefPtr<mozilla::VsyncDispatcher> mWaylandVsyncDispatcher;
+ LayoutDeviceIntPoint mNativePointerLockCenter;
+ zwp_locked_pointer_v1* mLockedPointer = nullptr;
+ zwp_relative_pointer_v1* mRelativePointer = nullptr;
+#endif
+ // An activation token from our environment (see handling of the
+ // XDG_ACTIVATION_TOKEN/DESKTOP_STARTUP_ID) env vars.
+ nsCString mWindowActivationTokenFromEnv;
+ mozilla::widget::WindowSurfaceProvider mSurfaceProvider;
+ GdkDragContext* mSourceDragContext = nullptr;
+#if MOZ_LOGGING
+ LayoutDeviceIntRect mLastLoggedBoundSize;
+ int mLastLoggedScale = -1;
+#endif
+};
+
+#endif /* __nsWindow_h__ */