/* 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 "WaylandSurfaceLock.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/RWLock.h"
#include "mozilla/gfx/BaseMargin.h"
#include "mozilla/widget/WindowSurface.h"
#include "mozilla/widget/WindowSurfaceProvider.h"
#include "nsIWidget.h"
#include "nsIDragService.h"
#include "nsRefPtrHashtable.h"
#include "IMContextWrapper.h"
#include "LookAndFeel.h"
#ifdef ACCESSIBILITY
# include
"mozilla/a11y/LocalAccessible.h"
#endif
#ifdef MOZ_X11
# include <gdk/gdkx.h>
# include
"X11UndefineNone.h"
#endif
#ifdef MOZ_LOGGING
# undef LOG
# undef LOGVERBOSE
# 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;
extern mozilla::LazyLogModule gWidgetWaylandLog;
# define LOG_WIN(win, str, ...) \
MOZ_LOG(win->IsPopup() ? gWidgetPopupLog : gWidgetLog, \
mozilla::LogLevel::Debug, \
(
"%s: " str, win->GetDebugTag().get(),
##__VA_ARGS__))
# define LOG(...) LOG_WIN(
this, __VA_ARGS__)
# define LOGVERBOSE(str, ...) \
MOZ_LOG(IsPopup() ? gWidgetPopupLog : gWidgetLog, \
mozilla::LogLevel::Verbose, \
(
"%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(str, ...) \
MOZ_LOG(gWidgetVsync, mozilla::LogLevel::Debug, \
(
"%s: " str, GetDebugTag().get(),
##__VA_ARGS__))
# define LOG_ENABLED() \
(MOZ_LOG_TEST(gWidgetPopupLog, mozilla::LogLevel::Debug) || \
MOZ_LOG_TEST(gWidgetLog, mozilla::LogLevel::Debug))
# define LOG_ENABLED_VERBOSE() \
(MOZ_LOG_TEST(gWidgetPopupLog, mozilla::LogLevel::Verbose) || \
MOZ_LOG_TEST(gWidgetLog, mozilla::LogLevel::Verbose))
# define LOG_WAYLAND(...) \
MOZ_LOG(gWidgetWaylandLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
#else
# define LOG(...)
# define LOG_WIN(...)
# define LOGVERBOSE(...)
# 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;
class nsMenuPopupFrame;
#if !GTK_CHECK_VERSION(
3,
18,
0)
struct _GdkEventTouchpadPinch;
typedef struct _GdkEventTouchpadPinch GdkEventTouchpadPinch;
#endif
// 'Stable' Wayland subsurface rounding algorithm is used by all compositors
// except KDE.
// See
// https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/143#note_1343171
// for details.
// We want to replace it by wp-fractional-scale-v2 when it's available.
extern bool gUseStableRounding;
#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
#if !GTK_CHECK_VERSION(
3,
18,
0)
typedef enum {
GDK_TOUCHPAD_GESTURE_PHASE_BEGIN,
GDK_TOUCHPAD_GESTURE_PHASE_UPDATE,
GDK_TOUCHPAD_GESTURE_PHASE_END,
GDK_TOUCHPAD_GESTURE_PHASE_CANCEL
} GdkTouchpadGesturePhase;
#endif
struct zwp_locked_pointer_v1;
struct zwp_relative_pointer_v1;
namespace mozilla {
enum class NativeKeyBindingsType : uint8_t;
class TimeStamp;
class WaylandVsyncSource;
#ifdef MOZ_X11
class CurrentX11TimeGetter;
#endif
namespace widget {
class DBusMenuBar;
class Screen;
class WaylandSurface;
class WaylandSurfaceLock;
class nsWindowX11;
class nsWindowWayland;
}
// namespace widget
}
// namespace mozilla
class gfxImageSurface;
class nsWindow :
public nsIWidget {
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, nsIWidget)
virtual mozilla::widget::nsWindowWayland* AsWayland() {
return nullptr; }
virtual mozilla::widget::nsWindowX11* AsX11() {
return nullptr; }
// called when we are destroyed
void OnDestroy() override;
// called to check and see if a widget's dimensions are sane
bool AreBoundsSane();
// nsIWidget
using nsIWidget::Create;
// for Create signature not overridden here
[[nodiscard]] nsresult Create(nsIWidget* aParent,
const LayoutDeviceIntRect& aRect,
const InitData&) override;
void Destroy() override;
float GetDPI() override;
double GetDefaultScaleInternal() override;
uint32_t GetMaxTouchPoints()
const override;
mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale()
const override;
void SetModal(
bool aModal) override;
bool IsVisible()
const override;
void ConstrainPosition(DesktopIntPoint&) override;
void SetSizeConstraints(
const SizeConstraints&) override;
void LockAspectRatio(
bool aShouldLock) override;
void Move(
const DesktopPoint&) override;
void Show(
bool aState) override;
void Resize(
const DesktopSize&,
bool aRepaint) override;
void Resize(
const DesktopRect&,
bool aRepaint) override;
bool IsEnabled()
const override;
nsSizeMode GetSizeMode()
const {
return mSizeMode; }
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 GetBounds() override;
LayoutDeviceIntRect GetScreenBounds() override;
DesktopIntRect GetScreenBoundsUnscaled();
LayoutDeviceIntRect GetClientBounds() override;
LayoutDeviceIntSize GetClientSize() override;
LayoutDeviceIntPoint GetClientOffset() override;
LayoutDeviceIntPoint GetScreenEdgeSlop() override;
nsresult GetRestoredBounds(LayoutDeviceIntRect&) override;
bool PersistClientBounds()
const override {
return true; }
LayoutDeviceIntMargin NormalSizeModeClientToWindowMargin() override;
bool WorkspaceManagementDisabled();
bool ConstrainSizeWithScale(
int* aWidth,
int* aHeight,
double aScale);
// Recomputes the bounds according to our current window position. Dispatches
// move / resizes as needed.
void RecomputeBounds(
bool aScaleChange =
false);
// Window bounds (as in GetBounds()) are composed as
// mClientArea.Inflate(mClientMargin)*scale, i.e.:
//
// mBounds.x = (mClientArea.x - mClientMargin.left) * scale;
// mBounds.y = (mClientArea.y - mClientMargin.top) * scale;
// mBounds.width = (mClientArea.width +
// (mClientMargin.right + mClientMargin.left)) * scale;
// mBounds.height = (mClientArea.height +
// (mClientMargin.top + mClientMargin.bottom)) * scale;
//
// We use mClientMargin and mClientArea in Gdk (logical, widget) coordinates
// instead of device pixel coordinates to avoid rounding errors.
struct Bounds {
// mClientArea is window rendering area in global coordinates.
DesktopIntRect mClientArea;
// mClientMargin contains CSD decorations size on Wayland and
// CSD decorations and system titlebar size on X11.
DesktopIntMargin mClientMargin;
static Bounds Compute(
const nsWindow*);
#ifdef MOZ_X11
static Bounds ComputeX11(
const nsWindow*);
#endif
#ifdef MOZ_WAYLAND
static Bounds ComputeWayland(
const nsWindow*);
#endif
};
void SchedulePendingBounds();
void MaybeRecomputeBounds();
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,
const nsAString& xulWinClass,
const nsAString& xulWinName) override;
LayoutDeviceIntPoint WidgetToScreenOffset() override;
DesktopIntPoint WidgetToScreenOffsetUnscaled();
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<mozilla::widget::Screen> 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(BorderStyle 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 OnShellConfigureEvent(GdkEventConfigure* aEvent);
void OnContainerSizeAllocate(GtkAllocation* aAllocation);
void OnMap();
void OnUnmap();
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 OnSmoothScrollEvent(uint32_t aTime,
float aDeltaX,
float aDeltaY);
void OnVisibilityNotifyEvent(GdkVisibilityState aState);
void OnWindowStateEvent(GtkWidget* aWidget, GdkEventWindowState* aEvent);
gboolean OnPropertyNotifyEvent(GtkWidget* aWidget, GdkEventProperty* aEvent);
gboolean OnTouchEvent(GdkEventTouch* aEvent);
gboolean OnTouchpadPinchEvent(GdkEventTouchpadPinch* aEvent);
void OnTouchpadHoldEvent(GdkTouchpadGesturePhase aPhase, guint aTime,
uint32_t aFingers);
gint GetInputRegionMarginInGdkCoords();
void UpdateOpaqueRegionInternal();
void UpdateOpaqueRegion(
const LayoutDeviceIntRegion&) override;
LayoutDeviceIntRegion GetOpaqueRegionForTesting()
const override {
return GetOpaqueRegion();
}
LayoutDeviceIntRegion GetOpaqueRegion()
const;
// Exports a handle to the window, see `gdk_wayland_window_export_handle`.
using ExportHandlePromise =
mozilla::MozPromise<nsCString,
bool,
/*IsExclusive = */ true>;
RefPtr<ExportHandlePromise> ExportHandle();
void UnexportHandle();
already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawingInRegion(
const LayoutDeviceIntRegion& aInvalidRegion) override;
void EndRemoteDrawingInRegion(
mozilla::gfx::DrawTarget* aDrawTarget,
const LayoutDeviceIntRegion& aInvalidRegion) override;
virtual void SetProgress(
unsigned long progressPercent) {};
bool SynchronouslyRepaintOnResize() override;
void OnDPIChanged();
void OnCheckResize();
void OnCompositedChanged();
void DispatchResized();
void OnScaleEvent();
// Load new scale from system.
// aRefreshScreen means notify layout that scale was changed and
// it should load correct values.
// Set aRefreshScreen to false if we operate on hidden window
// or if we're going to repaint.
// aForceRefresh is used when fractional scale is changed but
// ceiled scale is kept.
void RefreshScale(
bool aRefreshScreen,
bool aForceRefresh =
false);
static guint32 sLastButtonPressTime;
MozContainer* GetMozContainer() {
return mContainer; }
GdkWindow* GetGdkWindow()
const {
return mGdkWindow; }
void SetGdkWindow(GdkWindow* aGdkWindow);
GdkWindow* GetToplevelGdkWindow()
const;
GtkWidget* GetGtkWidget()
const {
return mShell; }
#ifdef MOZ_WAYLAND
RefPtr<mozilla::widget::WaylandSurface> GetWaylandSurface() {
return mSurface;
}
#endif
bool IsDestroyed()
const {
return mIsDestroyed; }
bool IsPopup()
const;
bool IsWaylandPopup()
const;
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;
void SetTransparencyMode(TransparencyMode aMode) override;
TransparencyMode GetTransparencyMode() override;
void SetInputRegion(
const InputRegion&) override;
nsresult SynthesizeNativeMouseEvent(
LayoutDeviceIntPoint aPoint, NativeMouseMessage aNativeMessage,
mozilla::MouseButton aButton, nsIWidget::NativeModifiers aModifierFlags,
nsISynthesizedEventCallback* aCallback) override;
nsresult SynthesizeNativeMouseMove(
LayoutDeviceIntPoint aPoint,
nsISynthesizedEventCallback* aCallback) override {
return SynthesizeNativeMouseEvent(
aPoint, NativeMouseMessage::Move, mozilla::MouseButton::eNotPressed,
nsIWidget::NativeModifiers::NO_MODIFIERS, aCallback);
}
nsresult SynthesizeNativeMouseScrollEvent(
LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage,
double aDeltaX,
double aDeltaY,
double aDeltaZ, nsIWidget::NativeModifiers aModifierFlags,
uint32_t aAdditionalFlags,
nsISynthesizedEventCallback* aCallback) override;
nsresult SynthesizeNativeTouchPoint(
uint32_t aPointerId, TouchPointerState aPointerState,
LayoutDeviceIntPoint aPoint,
double aPointerPressure,
uint32_t aPointerOrientation,
nsISynthesizedEventCallback* aCallback) 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,
nsISynthesizedEventCallback* aCallback) override;
void GetCompositorWidgetInitData(
mozilla::widget::CompositorWidgetInitData* aInitData) override;
void SetCustomTitlebar(
bool) override;
void UpdateWindowDraggingRegion(
const LayoutDeviceIntRegion& aRegion) override;
#ifdef MOZ_ENABLE_DBUS
void SetDBusMenuBar(RefPtr<mozilla::widget::DBusMenuBar> aDbusMenuBar);
#endif
// HiDPI scale conversion
gint GdkCeiledScaleFactor();
double FractionalScaleFactor()
const;
LayoutDeviceIntPoint ToLayoutDevicePixels(
const DesktopIntPoint&);
LayoutDeviceIntSize ToLayoutDevicePixels(
const DesktopIntSize&);
LayoutDeviceIntRect ToLayoutDevicePixels(
const DesktopIntRect&);
LayoutDeviceIntMargin ToLayoutDevicePixels(
const DesktopIntMargin&);
DesktopIntSize ToDesktopPixels(
const LayoutDeviceIntSize&);
DesktopIntRect ToDesktopPixels(
const LayoutDeviceIntRect&);
DesktopIntPoint ToDesktopPixels(
const LayoutDeviceIntPoint&);
// To GDK
gint DevicePixelsToGdkCoordRound(
int);
gint DevicePixelsToGdkCoordRoundDown(
int);
GdkPoint DevicePixelsToGdkPointRoundDown(
const LayoutDeviceIntPoint&);
GdkRectangle DevicePixelsToGdkRectRoundOut(
const LayoutDeviceIntRect&);
GdkRectangle DevicePixelsToGdkRectRoundIn(
const LayoutDeviceIntRect&);
// From GDK
LayoutDeviceIntPoint GdkPointToDevicePixels(
const GdkPoint&);
LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble aX, gdouble aY);
bool WidgetTypeSupportsAcceleration() override;
bool WidgetTypeSupportsNativeCompositing() 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();
bool IsRemoteContent()
const {
return HasRemoteContent(); }
static bool IsToplevelWindowTransparent();
static nsWindow* GetFocusedWindow();
mozilla::UniquePtr<mozilla::widget::WaylandSurfaceLock> LockSurface();
bool ApplyEnterLeaveMutterWorkaround();
void NotifyOcclusionState(mozilla::widget::OcclusionState aState) override;
static nsWindow* GetWindow(GdkWindow* window);
/**
* Dispatch accessible window activate event for the top level window
* accessible.
*/
void DispatchActivateEventAccessible();
void GtkWidgetDestroyHandler(GtkWidget* aWidget);
void SetDragPopupSurface(RefPtr<gfxImageSurface> aDragPopupSurface,
const LayoutDeviceIntRegion& aInvalidRegion);
static nsWindow* FromGtkWidget(GtkWidget* widget);
static nsWindow* FromGdkWindow(GdkWindow* window);
static nsWindow* FromWidget(nsIWidget* aWidget) {
if (aWidget && aWidget->IsNativeWidget()) {
return static_cast<nsWindow*>(aWidget);
}
return nullptr;
}
static nsWindow* FromWidget(nsWindow*) =
delete;
void SetTextInputArea(LayoutDeviceIntRect aCursorArea);
DesktopIntRect GetTextInputArea() {
return mIMContextInputArea; };
void UnlockCursor() { mWidgetCursorLocked =
false; };
void InsertEmoji(RefPtr<nsWindow> aToplevelWindow = nullptr);
static void SessionRestoreFinished();
protected:
virtual ~nsWindow();
virtual void CreateNative() =
0;
virtual void DestroyNative() =
0;
void ConfigureToplevelWindow();
virtual void ConfigureToplevelWindowNative() {};
virtual void EnableVSyncSource() {};
virtual void DisableVSyncSource() {};
// event handling code
void DispatchActivateEvent(
void);
void DispatchDeactivateEvent(
void);
void DispatchPanGesture(mozilla::PanGestureInput& aPanInput);
void RegisterTouchWindow() override;
void NativeMoveResize(
bool aMoved,
bool aResized);
virtual void NativeShow(
bool aAction) =
0;
void SetHasMappedToplevel(
bool aState);
bool SetSafeWindowSize(LayoutDeviceIntSize& aSize);
bool SetSafeWindowSize(DesktopIntSize& aSize);
void DispatchContextMenuEventFromMouseEvent(
uint16_t domButton, GdkEventButton* aEvent,
const mozilla::LayoutDeviceIntPoint& aRefPoint);
void TryToShowNativeWindowMenu(GdkEventButton* aEvent);
bool DoTitlebarAction(mozilla::LookAndFeel::TitlebarEvent aEvent,
GdkEventButton* aButtonEvent);
void DestroyChildWindows();
nsWindow* GetContainerWindow()
const;
Window GetX11Window();
void SetUrgencyHint(GtkWidget* top_window,
bool state);
void SetDefaultIcon(
void);
void SetWindowDecoration(BorderStyle aStyle);
void InitButtonEvent(mozilla::WidgetMouseEvent& aEvent,
GdkEventButton* aGdkEvent,
const mozilla::LayoutDeviceIntPoint& aRefPoint,
bool isEraser =
false);
bool CheckForRollup(gdouble aMouseX, gdouble aMouseY,
bool aIsWheel,
bool aAlwaysRollup);
void RollupAllMenus() { CheckForRollup(
0,
0,
false,
true); }
void CheckForRollupDuringGrab() { RollupAllMenus(); }
bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent, GdkWindow** aWindow,
gint* aButton, gint* aRootX, gint* aRootY);
nsWindow* GetTransientForWindowIfPopup();
bool IsHandlingTouchSequence(GdkEventSequence* aSequence);
void ResizeInt(
const mozilla::Maybe<DesktopIntPoint>& aMove,
DesktopIntSize aSize);
// Returns a window edge if the given point (in device pixels) is within a
// resizer region of the window.
// Only used when drawing decorations client side.
mozilla::Maybe<GdkWindowEdge> CheckResizerEdge(
const LayoutDeviceIntPoint&);
GtkTextDirection GetTextDirection();
bool DrawsToCSDTitlebar()
const;
bool ToplevelUsesCSD()
const;
void CreateAndPutGdkScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
double aDeltaX,
double aDeltaY);
nsCString mGtkWindowAppClass;
nsCString mGtkWindowAppName;
nsCString mGtkWindowRoleName;
void RefreshWindowClass();
GtkWidget* mShell = nullptr;
MozContainer* mContainer = nullptr;
GdkWindow* mGdkWindow = nullptr;
// mEGLWindow is owned by WaylandSurface or it's X11 ID.
void* mEGLWindow = nullptr;
#ifdef MOZ_WAYLAND
RefPtr<mozilla::widget::WaylandSurface> mSurface;
#endif
RefPtr<gfxImageSurface> mDragPopupSurface;
LayoutDeviceIntRegion mDragPopupSurfaceRegion;
PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate = nullptr;
// 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;
mozilla::Maybe<GtkOrientation> mAspectResizer;
GdkPoint mLastResizePoint{
0,
0};
// Keep in sync with WaylandSurface::sNoScale
constexpr
static const int sNoScale = -
1;
int mCeiledScaleFactor = sNoScale;
// The size requested, which might not be reflected in mClientArea. 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 mClientArea.Size().
// All these values are in unscaled (Gdk) coordinates.
DesktopIntSize mLastSizeRequest;
// Same but for positioning. Used to track move requests.
DesktopIntPoint mLastMoveRequest;
// See Bounds for these members.
DesktopIntRect mClientArea;
DesktopIntMargin mClientMargin;
// 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;
mozilla::Maybe<uint64_t> mSavedCallbackId;
};
// 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.
bool mDrawInTitlebar =
false;
// This track real window visibility from OS perspective.
// It's set by OnMap/OnUnmap which is based on Gtk events.
bool mIsMapped;
// Has this widget been destroyed yet?
mozilla::Atomic<
bool, mozilla::Relaxed> 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;
// 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 mCompositedScreen :
1;
bool mIsAccelerated :
1;
bool mIsAlert :
1;
bool mWindowShouldStartDragging :
1;
bool mHasMappedToplevel :
1;
bool mPanInProgress :
1;
bool mPendingBoundsChange :
1;
// Draw titlebar with :backdrop css state (inactive/unfocused).
bool mTitlebarBackdropState :
1;
bool mAlwaysOnTop :
1;
bool mIsTransparent :
1;
// We can expect at least one size-allocate event after early resizes.
bool mHasReceivedSizeAllocate :
1;
bool mWidgetCursorLocked :
1;
bool mUndecorated :
1;
// True when we're on compositing window manager and this
// window is using visual with alpha channel.
bool mHasAlphaVisual :
1;
// 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;
/* 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 mX11HiddenPopupPositioned :
1;
// Popup is hidden only as a part of hierarchy tree update.
bool mPopupTemporaryHidden :
1;
// If we're waiting for session restore, don't fiddle with window
// size/focus etc.
bool mWaitingToSessionRestore :
1;
// all of our DND stuff
void InitDragEvent(mozilla::WidgetDragEvent& aEvent);
float mLastMotionPressure =
0.
0f;
InputRegion mInputRegion;
bool DragInProgress(
void);
void DispatchMissedButtonReleases(GdkEventCrossing* aGdkEvent);
bool IsAlwaysUndecoratedWindow()
const;
// nsIWidget
WindowRenderer* GetWindowRenderer() override;
void DidGetNonBlankPaint() override;
void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override;
void UpdateMozWindowActive();
void ForceTitlebarRedraw();
bool DoDrawTilebarCorners();
bool IsChromeWindowTitlebar();
void SetPopupWindowDecoration(
bool aShowOnTaskbar);
void ApplySizeConstraints();
GtkWindow* GetCurrentTopmostWindow()
const;
nsAutoCString GetFrameTag()
const;
nsCString GetPopupTypeName();
bool IsPopupDirectionRTL();
#ifdef MOZ_LOGGING
void LogPopupHierarchy();
void LogPopupAnchorHints(
int aHints);
void LogPopupGravity(GdkGravity aGravity);
#endif
// 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.
DesktopIntSize mMoveToRectPopupSize;
#ifdef MOZ_ENABLE_DBUS
RefPtr<mozilla::widget::DBusMenuBar> mDBusMenuBar;
#endif
struct LastMouseCoordinates {
template <
typename Event>
void Set(Event* aEvent) {
mX = aEvent->x;
mY = aEvent->y;
mRootX = aEvent->x_root;
mRootY = aEvent->y_root;
}
float mX =
0.
0f, mY =
0.
0f;
float mRootX =
0.
0f, mRootY =
0.
0f;
} mLastMouseCoordinates;
// We don't want to fire scroll event with the same timestamp as
// smooth scroll event.
guint32 mLastSmoothScrollEventTime = GDK_CURRENT_TIME;
/**
* |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;
DesktopIntRect mIMContextInputArea;
int mEmojiHidenSignal =
0;
#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 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();
void KioskLockOnMonitor();
void EmulateResizeDrag(GdkEventMotion* aEvent);
void RequestRepaint(LayoutDeviceIntRegion& aRepaintRegion);
bool DrawDragPopupSurface(cairo_t* cr);
bool ExtractExposeRegion(LayoutDeviceIntRegion& aRegion, cairo_t* cr);
// 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;
bool mSourceDragContextActive =
false;
mozilla::Sides mResizableEdges{mozilla::SideBits::eAll};
// Running in kiosk mode and requested to stay on specified monitor.
// If monitor is removed minimize the window.
mozilla::Maybe<
int> mKioskMonitor;
LayoutDeviceIntRegion mOpaqueRegion MOZ_GUARDED_BY(mOpaqueRegionLock);
mutable mozilla::RWLock mOpaqueRegionLock{
"nsWindow::mOpaqueRegion"};
};
nsWindow* get_window_for_gtk_widget(GtkWidget* widget);
nsWindow* get_window_for_gdk_window(GdkWindow* window);
void GtkWindowSetTransientFor(GtkWindow* aWindow, GtkWindow* aParent);
#endif /* _nsWindow_h_ */