1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:expandtab:shiftwidth=4:tabstop=4: 3 */ 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/. */ 7 8 #ifndef __nsWindow_h__ 9 #define __nsWindow_h__ 10 11 #include <gdk/gdk.h> 12 #include <gtk/gtk.h> 13 14 #include "CompositorWidget.h" 15 #include "MozContainer.h" 16 #include "mozilla/EventForwards.h" 17 #include "mozilla/Maybe.h" 18 #include "mozilla/RefPtr.h" 19 #include "mozilla/TouchEvents.h" 20 #include "mozilla/UniquePtr.h" 21 #include "mozilla/widget/WindowSurface.h" 22 #include "mozilla/widget/WindowSurfaceProvider.h" 23 #include "nsBaseWidget.h" 24 #include "nsGkAtoms.h" 25 #include "nsIDragService.h" 26 #include "nsRefPtrHashtable.h" 27 #include "IMContextWrapper.h" 28 29 #ifdef ACCESSIBILITY 30 # include "mozilla/a11y/LocalAccessible.h" 31 #endif 32 33 #ifdef MOZ_X11 34 # include <gdk/gdkx.h> 35 # include "X11UndefineNone.h" 36 #endif 37 #ifdef MOZ_WAYLAND 38 # include <gdk/gdkwayland.h> 39 # include "base/thread.h" 40 # include "WaylandVsyncSource.h" 41 # include "nsClipboardWayland.h" 42 #endif 43 44 #ifdef MOZ_LOGGING 45 46 # include "mozilla/Logging.h" 47 # include "nsTArray.h" 48 # include "Units.h" 49 50 extern mozilla::LazyLogModule gWidgetLog; 51 extern mozilla::LazyLogModule gWidgetDragLog; 52 extern mozilla::LazyLogModule gWidgetPopupLog; 53 extern mozilla::LazyLogModule gWidgetVsync; 54 55 # define LOG(str, ...) \ 56 MOZ_LOG(IsPopup() ? gWidgetPopupLog : gWidgetLog, \ 57 mozilla::LogLevel::Debug, \ 58 ("%s: " str, GetDebugTag().get(), ##__VA_ARGS__)) 59 # define LOGW(...) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) 60 # define LOGDRAG(...) \ 61 MOZ_LOG(gWidgetDragLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) 62 # define LOG_POPUP(...) \ 63 MOZ_LOG(gWidgetPopupLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) 64 # define LOG_VSYNC(...) \ 65 MOZ_LOG(gWidgetVsync, mozilla::LogLevel::Debug, (__VA_ARGS__)) 66 # define LOG_ENABLED() \ 67 (MOZ_LOG_TEST(gWidgetPopupLog, mozilla::LogLevel::Debug) || \ 68 MOZ_LOG_TEST(gWidgetLog, mozilla::LogLevel::Debug)) 69 70 #else 71 72 # define LOG(...) 73 # define LOGW(...) 74 # define LOGDRAG(...) 75 # define LOG_POPUP(...) 76 # define LOG_ENABLED() false 77 78 #endif /* MOZ_LOGGING */ 79 80 class gfxPattern; 81 class nsIFrame; 82 #if !GTK_CHECK_VERSION(3, 18, 0) 83 struct _GdkEventTouchpadPinch; 84 typedef struct _GdkEventTouchpadPinch GdkEventTouchpadPinch; 85 86 #endif 87 88 namespace mozilla { 89 enum class NativeKeyBindingsType : uint8_t; 90 91 class TimeStamp; 92 class CurrentX11TimeGetter; 93 } // namespace mozilla 94 95 class nsWindow final : public nsBaseWidget { 96 public: 97 typedef mozilla::gfx::DrawTarget DrawTarget; 98 typedef mozilla::WidgetEventTime WidgetEventTime; 99 typedef mozilla::WidgetKeyboardEvent WidgetKeyboardEvent; 100 typedef mozilla::widget::PlatformCompositorWidgetDelegate 101 PlatformCompositorWidgetDelegate; 102 103 nsWindow(); 104 105 static void ReleaseGlobals(); 106 107 NS_INLINE_DECL_REFCOUNTING_INHERITED(nsWindow, nsBaseWidget) 108 109 nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, 110 nsEventStatus& aStatus) override; 111 112 // called when we are destroyed 113 void OnDestroy() override; 114 115 // called to check and see if a widget's dimensions are sane 116 bool AreBoundsSane(void); 117 118 // nsIWidget 119 using nsBaseWidget::Create; // for Create signature not overridden here 120 [[nodiscard]] nsresult Create(nsIWidget* aParent, 121 nsNativeWidget aNativeParent, 122 const LayoutDeviceIntRect& aRect, 123 nsWidgetInitData* aInitData) override; 124 void Destroy() override; 125 nsIWidget* GetParent() override; 126 float GetDPI() override; 127 double GetDefaultScaleInternal() override; 128 mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override; 129 mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScaleByScreen() 130 override; 131 void SetParent(nsIWidget* aNewParent) override; 132 void SetModal(bool aModal) override; 133 bool IsVisible() const override; 134 void ConstrainPosition(bool aAllowSlop, int32_t* aX, int32_t* aY) override; 135 void SetSizeConstraints(const SizeConstraints& aConstraints) override; 136 void LockAspectRatio(bool aShouldLock) override; 137 void Move(double aX, double aY) override; 138 void Show(bool aState) override; 139 void Resize(double aWidth, double aHeight, bool aRepaint) override; 140 void Resize(double aX, double aY, double aWidth, double aHeight, 141 bool aRepaint) override; 142 bool IsEnabled() const override; 143 144 void SetZIndex(int32_t aZIndex) override; 145 void SetSizeMode(nsSizeMode aMode) override; 146 void GetWorkspaceID(nsAString& workspaceID) override; 147 void MoveToWorkspace(const nsAString& workspaceID) override; 148 void Enable(bool aState) override; 149 void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; 150 LayoutDeviceIntRect GetScreenBounds() override; 151 LayoutDeviceIntRect GetClientBounds() override; 152 LayoutDeviceIntSize GetClientSize() override; 153 LayoutDeviceIntPoint GetClientOffset() override; 154 void SetCursor(const Cursor&) override; 155 void Invalidate(const LayoutDeviceIntRect& aRect) override; 156 void* GetNativeData(uint32_t aDataType) override; 157 nsresult SetTitle(const nsAString& aTitle) override; 158 void SetIcon(const nsAString& aIconSpec) override; 159 void SetWindowClass(const nsAString& xulWinType) override; 160 LayoutDeviceIntPoint WidgetToScreenOffset() override; 161 void CaptureMouse(bool aCapture) override; 162 void CaptureRollupEvents(nsIRollupListener* aListener, 163 bool aDoCapture) override; 164 [[nodiscard]] nsresult GetAttention(int32_t aCycleCount) override; 165 bool HasPendingInputEvent() override; 166 167 bool PrepareForFullscreenTransition(nsISupports** aData) override; 168 void PerformFullscreenTransition(FullscreenTransitionStage aStage, 169 uint16_t aDuration, nsISupports* aData, 170 nsIRunnable* aCallback) override; 171 already_AddRefed<nsIScreen> GetWidgetScreen() override; 172 nsresult MakeFullScreen(bool aFullScreen) override; 173 void HideWindowChrome(bool aShouldHide) override; 174 175 /** 176 * GetLastUserInputTime returns a timestamp for the most recent user input 177 * event. This is intended for pointer grab requests (including drags). 178 */ 179 static guint32 GetLastUserInputTime(); 180 181 // utility method, -1 if no change should be made, otherwise returns a 182 // value that can be passed to gdk_window_set_decorations 183 gint ConvertBorderStyles(nsBorderStyle aStyle); 184 185 GdkRectangle DevicePixelsToGdkRectRoundOut(LayoutDeviceIntRect aRect); 186 GetIMContext()187 mozilla::widget::IMContextWrapper* GetIMContext() const { return mIMContext; } 188 189 bool DispatchCommandEvent(nsAtom* aCommand); 190 bool DispatchContentCommandEvent(mozilla::EventMessage aMsg); 191 192 // event callbacks 193 gboolean OnExposeEvent(cairo_t* cr); 194 gboolean OnConfigureEvent(GtkWidget* aWidget, GdkEventConfigure* aEvent); 195 void OnMap(); 196 void OnUnrealize(); 197 void OnSizeAllocate(GtkAllocation* aAllocation); 198 void OnDeleteEvent(); 199 void OnEnterNotifyEvent(GdkEventCrossing* aEvent); 200 void OnLeaveNotifyEvent(GdkEventCrossing* aEvent); 201 void OnMotionNotifyEvent(GdkEventMotion* aEvent); 202 void OnButtonPressEvent(GdkEventButton* aEvent); 203 void OnButtonReleaseEvent(GdkEventButton* aEvent); 204 void OnContainerFocusInEvent(GdkEventFocus* aEvent); 205 void OnContainerFocusOutEvent(GdkEventFocus* aEvent); 206 gboolean OnKeyPressEvent(GdkEventKey* aEvent); 207 gboolean OnKeyReleaseEvent(GdkEventKey* aEvent); 208 209 void OnScrollEvent(GdkEventScroll* aEvent); 210 211 void OnWindowStateEvent(GtkWidget* aWidget, GdkEventWindowState* aEvent); 212 void OnDragDataReceivedEvent(GtkWidget* aWidget, GdkDragContext* aDragContext, 213 gint aX, gint aY, 214 GtkSelectionData* aSelectionData, guint aInfo, 215 guint aTime, gpointer aData); 216 gboolean OnPropertyNotifyEvent(GtkWidget* aWidget, GdkEventProperty* aEvent); 217 gboolean OnTouchEvent(GdkEventTouch* aEvent); 218 gboolean OnTouchpadPinchEvent(GdkEventTouchpadPinch* aEvent); 219 220 void UpdateTopLevelOpaqueRegion(); 221 222 already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawingInRegion( 223 const LayoutDeviceIntRegion& aInvalidRegion, 224 mozilla::layers::BufferMode* aBufferMode) override; 225 void EndRemoteDrawingInRegion( 226 mozilla::gfx::DrawTarget* aDrawTarget, 227 const LayoutDeviceIntRegion& aInvalidRegion) override; 228 229 void SetProgress(unsigned long progressPercent); 230 231 RefPtr<mozilla::gfx::VsyncSource> GetVsyncSource() override; 232 bool SynchronouslyRepaintOnResize() override; 233 234 void OnDPIChanged(void); 235 void OnCheckResize(void); 236 void OnCompositedChanged(void); 237 void OnScaleChanged(); 238 void DispatchResized(); 239 240 static guint32 sLastButtonPressTime; 241 242 [[nodiscard]] nsresult BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent, 243 int32_t aHorizontal, 244 int32_t aVertical) override; 245 GetMozContainer()246 MozContainer* GetMozContainer() { return mContainer; } 247 LayoutDeviceIntSize GetMozContainerSize(); 248 // GetMozContainerWidget returns the MozContainer even for undestroyed 249 // descendant windows 250 GtkWidget* GetMozContainerWidget(); GetGdkWindow()251 GdkWindow* GetGdkWindow() { return mGdkWindow; }; 252 GdkWindow* GetToplevelGdkWindow(); GetGtkWidget()253 GtkWidget* GetGtkWidget() { return mShell; } 254 nsIFrame* GetFrame() const; IsDestroyed()255 bool IsDestroyed() const { return mIsDestroyed; } 256 bool IsPopup() const; 257 bool IsWaylandPopup() const; IsPIPWindow()258 bool IsPIPWindow() const { return mIsPIPWindow; }; IsDragPopup()259 bool IsDragPopup() { return mIsDragPopup; }; 260 261 nsAutoCString GetDebugTag() const; 262 263 void DispatchDragEvent(mozilla::EventMessage aMsg, 264 const LayoutDeviceIntPoint& aRefPoint, guint aTime); 265 static void UpdateDragStatus(GdkDragContext* aDragContext, 266 nsIDragService* aDragService); 267 268 WidgetEventTime GetWidgetEventTime(guint32 aEventTime); 269 mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime); 270 mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter(); 271 272 void SetInputContext(const InputContext& aContext, 273 const InputContextAction& aAction) override; 274 InputContext GetInputContext() override; 275 TextEventDispatcherListener* GetNativeTextEventDispatcherListener() override; 276 MOZ_CAN_RUN_SCRIPT bool GetEditCommands( 277 mozilla::NativeKeyBindingsType aType, 278 const mozilla::WidgetKeyboardEvent& aEvent, 279 nsTArray<mozilla::CommandInt>& aCommands) override; 280 281 // These methods are for toplevel windows only. 282 void ResizeTransparencyBitmap(); 283 void ApplyTransparencyBitmap(); 284 void ClearTransparencyBitmap(); 285 286 void SetTransparencyMode(nsTransparencyMode aMode) override; 287 nsTransparencyMode GetTransparencyMode() override; 288 void SetWindowMouseTransparent(bool aIsTransparent) override; 289 nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect, 290 uint8_t* aAlphas, 291 int32_t aStride); 292 void ReparentNativeWidget(nsIWidget* aNewParent) override; 293 294 void UpdateTitlebarTransparencyBitmap(); 295 296 nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, 297 NativeMouseMessage aNativeMessage, 298 mozilla::MouseButton aButton, 299 nsIWidget::Modifiers aModifierFlags, 300 nsIObserver* aObserver) override; 301 SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,nsIObserver * aObserver)302 nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, 303 nsIObserver* aObserver) override { 304 return SynthesizeNativeMouseEvent( 305 aPoint, NativeMouseMessage::Move, mozilla::MouseButton::eNotPressed, 306 nsIWidget::Modifiers::NO_MODIFIERS, aObserver); 307 } 308 309 nsresult SynthesizeNativeMouseScrollEvent( 310 LayoutDeviceIntPoint aPoint, uint32_t aNativeMessage, double aDeltaX, 311 double aDeltaY, double aDeltaZ, uint32_t aModifierFlags, 312 uint32_t aAdditionalFlags, nsIObserver* aObserver) override; 313 314 nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, 315 TouchPointerState aPointerState, 316 LayoutDeviceIntPoint aPoint, 317 double aPointerPressure, 318 uint32_t aPointerOrientation, 319 nsIObserver* aObserver) override; 320 321 nsresult SynthesizeNativeTouchPadPinch(TouchpadGesturePhase aEventPhase, 322 float aScale, 323 LayoutDeviceIntPoint aPoint, 324 int32_t aModifierFlags) override; 325 326 void GetCompositorWidgetInitData( 327 mozilla::widget::CompositorWidgetInitData* aInitData) override; 328 329 nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override; 330 void SetDrawsInTitlebar(bool aState) override; 331 mozilla::LayoutDeviceIntCoord GetTitlebarRadius(); 332 LayoutDeviceIntRect GetTitlebarRect(); 333 void UpdateWindowDraggingRegion( 334 const LayoutDeviceIntRegion& aRegion) override; 335 336 // HiDPI scale conversion 337 gint GdkCeiledScaleFactor(); 338 bool UseFractionalScale(); 339 double FractionalScaleFactor(); 340 341 // To GDK 342 gint DevicePixelsToGdkCoordRoundUp(int pixels); 343 gint DevicePixelsToGdkCoordRoundDown(int pixels); 344 GdkPoint DevicePixelsToGdkPointRoundDown(LayoutDeviceIntPoint point); 345 GdkRectangle DevicePixelsToGdkSizeRoundUp(LayoutDeviceIntSize pixelSize); 346 347 // From GDK 348 int GdkCoordToDevicePixels(gint coord); 349 LayoutDeviceIntPoint GdkPointToDevicePixels(GdkPoint point); 350 LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble x, gdouble y); 351 LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect); 352 353 bool WidgetTypeSupportsAcceleration() override; 354 355 nsresult SetSystemFont(const nsCString& aFontName) override; 356 nsresult GetSystemFont(nsCString& aFontName) override; 357 358 typedef enum { 359 GTK_DECORATION_SYSTEM, // CSD including shadows 360 GTK_DECORATION_CLIENT, // CSD without shadows 361 GTK_DECORATION_NONE, // WM does not support CSD at all 362 } GtkWindowDecoration; 363 /** 364 * Get the support of Client Side Decoration by checking 365 * the XDG_CURRENT_DESKTOP environment variable. 366 */ 367 static GtkWindowDecoration GetSystemGtkWindowDecoration(); 368 369 static bool GetTopLevelWindowActiveState(nsIFrame* aFrame); 370 static bool TitlebarUseShapeMask(); IsRemoteContent()371 bool IsRemoteContent() { return HasRemoteContent(); } 372 void NativeMoveResizeWaylandPopupCallback(const GdkRectangle* aFinalSize, 373 bool aFlippedX, bool aFlippedY); 374 static bool IsToplevelWindowTransparent(); 375 376 static nsWindow* GetFocusedWindow(); 377 378 #ifdef MOZ_WAYLAND 379 // Use xdg-activation protocol to transfer focus from gFocusWindow to aWindow. 380 static void RequestFocusWaylandWindow(RefPtr<nsWindow> aWindow); 381 void FocusWaylandWindow(const char* aTokenID); 382 383 bool GetCSDDecorationOffset(int* aDx, int* aDy); 384 void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize); 385 void WaylandDragWorkaround(GdkEventButton* aEvent); 386 387 wl_display* GetWaylandDisplay(); 388 void CreateCompositorVsyncDispatcher() override; GetNativePointerLockCenter()389 LayoutDeviceIntPoint GetNativePointerLockCenter() { 390 return mNativePointerLockCenter; 391 } 392 void SetNativePointerLockCenter( 393 const LayoutDeviceIntPoint& aLockCenter) override; 394 void LockNativePointer() override; 395 void UnlockNativePointer() override; GetPreferredPopupRect()396 LayoutDeviceIntRect GetPreferredPopupRect() const override { 397 return mPreferredPopupRect; 398 }; FlushPreferredPopupRect()399 void FlushPreferredPopupRect() override { 400 mPreferredPopupRect = LayoutDeviceIntRect(); 401 mPreferredPopupRectFlushed = true; 402 }; 403 #endif 404 405 typedef enum { 406 // WebRender compositor is enabled 407 COMPOSITOR_ENABLED, 408 // WebRender compositor is paused after window creation. 409 COMPOSITOR_PAUSED_INITIALLY, 410 // WebRender compositor is paused because GtkWindow is hidden, 411 // we can't draw into GL context. 412 COMPOSITOR_PAUSED_MISSING_WINDOW, 413 // WebRender compositor is paused as we're repainting whole window and 414 // we're waiting for content process to update page content. 415 COMPOSITOR_PAUSED_FLICKERING 416 } WindowCompositorState; 417 418 // Pause compositor to avoid rendering artifacts from content process. 419 void ResumeCompositor(); 420 void ResumeCompositorFromCompositorThread(); 421 void PauseCompositor(); 422 bool IsWaitingForCompositorResume(); 423 424 protected: 425 virtual ~nsWindow(); 426 427 // event handling code 428 void DispatchActivateEvent(void); 429 void DispatchDeactivateEvent(void); 430 void MaybeDispatchResized(); 431 432 void RegisterTouchWindow() override; CompositorInitiallyPaused()433 bool CompositorInitiallyPaused() override { 434 return mCompositorState == COMPOSITOR_PAUSED_INITIALLY; 435 } 436 nsCOMPtr<nsIWidget> mParent; 437 nsPopupType mPopupHint{}; 438 int mWindowScaleFactor = 1; 439 440 void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, 441 nsIntRect aBoundsRect); 442 443 void NativeMoveResize(bool aMoved, bool aResized); 444 445 void NativeShow(bool aAction); 446 void SetHasMappedToplevel(bool aState); 447 LayoutDeviceIntSize GetSafeWindowSize(LayoutDeviceIntSize aSize); 448 449 void EnsureGrabs(void); 450 void GrabPointer(guint32 aTime); 451 void ReleaseGrabs(void); 452 453 void UpdateClientOffsetFromFrameExtents(); 454 void UpdateClientOffsetFromCSDWindow(); 455 456 void DispatchContextMenuEventFromMouseEvent(uint16_t domButton, 457 GdkEventButton* aEvent); 458 459 void EnableRenderingToWindow(); 460 void DisableRenderingToWindow(); 461 void ResumeCompositorHiddenWindow(); 462 void PauseCompositorHiddenWindow(); 463 void WaylandStartVsync(); 464 void WaylandStopVsync(); 465 void DestroyChildWindows(); 466 GtkWidget* GetToplevelWidget(); 467 nsWindow* GetContainerWindow(); 468 Window GetX11Window(); 469 bool GetShapedState(); 470 void EnsureGdkWindow(); 471 void SetUrgencyHint(GtkWidget* top_window, bool state); 472 void SetDefaultIcon(void); 473 void SetWindowDecoration(nsBorderStyle aStyle); 474 void InitButtonEvent(mozilla::WidgetMouseEvent& aEvent, 475 GdkEventButton* aGdkEvent); 476 bool CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel, 477 bool aAlwaysRollup); CheckForRollupDuringGrab()478 void CheckForRollupDuringGrab() { CheckForRollup(0, 0, false, true); } 479 480 bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent, GdkWindow** aWindow, 481 gint* aButton, gint* aRootX, gint* aRootY); 482 nsIWidgetListener* GetListener(); 483 484 nsWindow* GetTransientForWindowIfPopup(); 485 bool IsHandlingTouchSequence(GdkEventSequence* aSequence); 486 487 void ResizeInt(int aX, int aY, int aWidth, int aHeight, bool aMove, 488 bool aRepaint); 489 void NativeMoveResizeWaylandPopup(bool aMove, bool aResize); 490 491 // Returns true if the given point (in device pixels) is within a resizer 492 // region of the window. Only used when drawing decorations client side. 493 bool CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge); 494 495 GtkTextDirection GetTextDirection(); 496 497 void AddCSDDecorationSize(int* aWidth, int* aHeight); 498 499 nsCString mGtkWindowAppName; 500 nsCString mGtkWindowRoleName; 501 void RefreshWindowClass(); 502 503 GtkWidget* mShell = nullptr; 504 MozContainer* mContainer = nullptr; 505 GdkWindow* mGdkWindow = nullptr; 506 PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate = nullptr; 507 mozilla::Atomic<WindowCompositorState, mozilla::Relaxed> mCompositorState{ 508 COMPOSITOR_ENABLED}; 509 // This is used in COMPOSITOR_PAUSED_FLICKERING mode only to resume compositor 510 // in some reasonable time when page content is not updated. 511 int mCompositorPauseTimeoutID = 0; 512 513 nsSizeMode mSizeState = nsSizeMode_Normal; 514 float mAspectRatio = 0.0f; 515 float mAspectRatioSaved = 0.0f; 516 nsIntPoint mClientOffset; 517 518 // This field omits duplicate scroll events caused by GNOME bug 726878. 519 guint32 mLastScrollEventTime = GDK_CURRENT_TIME; 520 mozilla::ScreenCoord mLastPinchEventSpan; 521 522 // for touch event handling 523 nsRefPtrHashtable<nsPtrHashKey<GdkEventSequence>, mozilla::dom::Touch> 524 mTouches; 525 526 // Upper bound on pending ConfigureNotify events to be dispatched to the 527 // window. See bug 1225044. 528 unsigned int mPendingConfigures = 0; 529 530 // Window titlebar rendering mode, GTK_DECORATION_NONE if it's disabled 531 // for this window. 532 GtkWindowDecoration mGtkWindowDecoration = GTK_DECORATION_NONE; 533 534 // Draggable titlebar region maintained by UpdateWindowDraggingRegion 535 LayoutDeviceIntRegion mDraggableRegion; 536 537 // The cursor cache 538 static GdkCursor* gsGtkCursorCache[eCursorCount]; 539 540 // If true, draw our own window titlebar. 541 // 542 // Needs to be atomic because GetTitlebarRect() gets called from non-main 543 // threads. 544 // 545 // FIXME(emilio): GetTitlebarRect() reads other things that TSAN doesn't 546 // catch because mDrawInTitlebar is false on automation ~always. We should 547 // probably make GetTitlebarRect() simpler / properly thread-safe. 548 mozilla::Atomic<bool, mozilla::Relaxed> mDrawInTitlebar{false}; 549 550 // Has this widget been destroyed yet? 551 bool mIsDestroyed : 1; 552 // Does WindowResized need to be called on listeners? 553 bool mNeedsDispatchResized : 1; 554 // mIsShown tracks requested visible status from browser perspective, i.e. 555 // if the window should be visible or now. 556 bool mIsShown : 1; 557 // mNeedsShow is set when browser requested to show this window but we failed 558 // to do so for some reason (wrong window size for instance). 559 // In such case we set mIsShown = true and mNeedsShow = true to indicate 560 // that the window is not actually visible but we report to browser that 561 // it is visible (mIsShown == true). 562 bool mNeedsShow : 1; 563 // This track real window visibility from OS perspective. 564 // It's set by OnMap/OnUnrealize which is based on Gtk events. 565 bool mIsMapped : 1; 566 // is this widget enabled? 567 bool mEnabled : 1; 568 // has the native window for this been created yet? 569 bool mCreated : 1; 570 // whether we handle touch event 571 bool mHandleTouchEvent : 1; 572 // true if this is a drag and drop feedback popup 573 bool mIsDragPopup : 1; 574 bool mWindowScaleFactorChanged : 1; 575 bool mCompositedScreen : 1; 576 bool mIsAccelerated : 1; 577 bool mWindowShouldStartDragging : 1; 578 bool mHasMappedToplevel : 1; 579 bool mRetryPointerGrab : 1; 580 bool mPanInProgress : 1; 581 // Use dedicated GdkWindow for mContainer 582 bool mDrawToContainer : 1; 583 // Draw titlebar with :backdrop css state (inactive/unfocused). 584 bool mTitlebarBackdropState : 1; 585 // It's PictureInPicture window. 586 bool mIsPIPWindow : 1; 587 // It's undecorated popup utility window, without resizers/titlebar, 588 // movable by mouse. Used on Wayland for popups without 589 // parent (for instance WebRTC sharing indicator, notifications). 590 bool mIsWaylandPanelWindow : 1; 591 // It's child window, i.e. window which is nested in parent window. 592 // This is obsoleted and should not be used. 593 // We use GdkWindow hierarchy for such windows. 594 bool mIsChildWindow : 1; 595 bool mAlwaysOnTop : 1; 596 bool mNoAutoHide : 1; 597 bool mMouseTransparent : 1; 598 bool mIsTransparent : 1; 599 // We can't detect size state changes correctly so set this flag 600 // to force update mBounds after a size state change from a configure 601 // event. 602 bool mBoundsAreValid : 1; 603 604 /* Gkt creates popup in two incarnations - wl_subsurface and xdg_popup. 605 * Kind of popup is choosen before GdkWindow is mapped so we can change 606 * it only when GdkWindow is hidden. 607 * 608 * Relevant Gtk code is at gdkwindow-wayland.c 609 * in should_map_as_popup() and should_map_as_subsurface() 610 * 611 * wl_subsurface: 612 * - can't be positioned by move-to-rect 613 * - can stand outside popup widget hierarchy (has toplevel as parent) 614 * - don't have child popup widgets 615 * 616 * xdg_popup: 617 * - can be positioned by move-to-rect 618 * - aligned in popup widget hierarchy, first one is attached to toplevel 619 * - has child (popup) widgets 620 * 621 * Thus we need to map Firefox popup type to desired Gtk one: 622 * 623 * wl_subsurface: 624 * - pernament panels 625 * 626 * xdg_popup: 627 * - menus 628 * - autohide popups (hamburger menu) 629 * - extension popups 630 * - tooltips 631 * 632 * We set mPopupTrackInHierarchy = false for pernament panels which 633 * are always mapped to toplevel and painted as wl_surfaces. 634 */ 635 bool mPopupTrackInHierarchy : 1; 636 bool mPopupTrackInHierarchyConfigured : 1; 637 638 /* On X11 Gtk tends to ignore window position requests when gtk_window 639 * is hidden. Save the position requests at mPopupPosition and apply 640 * when the widget is shown. 641 */ 642 bool mHiddenPopupPositioned : 1; 643 644 // The transparency bitmap is used instead of ARGB visual for toplevel 645 // window to draw titlebar. 646 bool mTransparencyBitmapForTitlebar : 1; 647 648 // True when we're on compositing window manager and this 649 // window is using visual with alpha channel. 650 bool mHasAlphaVisual : 1; 651 652 // When popup is anchored, mPopupPosition is relative to its parent popup. 653 bool mPopupAnchored : 1; 654 655 // When popup is context menu. 656 bool mPopupContextMenu : 1; 657 658 // Indicates that this popup matches layout setup so we can use parent popup 659 // coordinates reliably. 660 bool mPopupMatchesLayout : 1; 661 662 /* Indicates that popup setup was changed and 663 * we need to recalculate popup coordinates. 664 */ 665 bool mPopupChanged : 1; 666 667 // Popup is hidden only as a part of hierarchy tree update. 668 bool mPopupTemporaryHidden : 1; 669 670 // Popup is going to be closed and removed. 671 bool mPopupClosed : 1; 672 673 // Popup is positioned by gdk_window_move_to_rect() 674 bool mPopupUseMoveToRect : 1; 675 676 bool mPreferredPopupRectFlushed : 1; 677 /* mWaitingForMoveToRectCallback is set when move-to-rect is called 678 * and we're waiting for move-to-rect callback. 679 * 680 * If another position/resize request comes between move-to-rect call and 681 * move-to-rect callback we set mNewBoundsAfterMoveToRect. 682 */ 683 bool mWaitingForMoveToRectCallback : 1; 684 685 // Set when move/resize action is initiated by move-to-rect operation. 686 // Don't use move-to-rect again in such case. 687 bool mUpdatedByMoveToRectCallback : 1; 688 689 // Whether we've configured default clear color already. 690 bool mConfiguredClearColor : 1; 691 // Whether we've received a non-blank paint in which case we can reset the 692 // clear color to transparent. 693 bool mGotNonBlankPaint : 1; 694 695 // This bitmap tracks which pixels are transparent. We don't support 696 // full translucency at this time; each pixel is either fully opaque 697 // or fully transparent. 698 gchar* mTransparencyBitmap = nullptr; 699 int32_t mTransparencyBitmapWidth = 0; 700 int32_t mTransparencyBitmapHeight = 0; 701 702 // all of our DND stuff 703 void InitDragEvent(mozilla::WidgetDragEvent& aEvent); 704 705 float mLastMotionPressure = 0.0f; 706 707 // Remember the last sizemode so that we can restore it when 708 // leaving fullscreen 709 nsSizeMode mLastSizeMode = nsSizeMode_Normal; 710 711 static bool DragInProgress(void); 712 713 void DispatchMissedButtonReleases(GdkEventCrossing* aGdkEvent); 714 715 // When window widget gets mapped/unmapped we need to configure 716 // underlying GdkWindow properly. Otherwise we'll end up with 717 // rendering to released window. 718 void ConfigureGdkWindow(); 719 void ReleaseGdkWindow(); 720 721 // nsBaseWidget 722 WindowRenderer* GetWindowRenderer() override; 723 void DidGetNonBlankPaint() override; 724 725 void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override; 726 727 void CleanLayerManagerRecursive(); 728 729 int32_t RoundsWidgetCoordinatesTo() override; 730 731 void UpdateMozWindowActive(); 732 733 void ForceTitlebarRedraw(); 734 bool DoDrawTilebarCorners(); 735 bool IsChromeWindowTitlebar(); 736 737 void SetPopupWindowDecoration(bool aShowOnTaskbar); 738 739 void ApplySizeConstraints(void); 740 741 // Wayland Popup section 742 GdkPoint WaylandGetParentPosition(); 743 bool WaylandPopupNeedsTrackInHierarchy(); 744 bool WaylandPopupIsAnchored(); 745 bool WaylandPopupIsMenu(); 746 bool WaylandPopupIsContextMenu(); 747 bool WaylandPopupIsPermanent(); 748 bool IsWidgetOverflowWindow(); 749 void RemovePopupFromHierarchyList(); 750 void ShowWaylandWindow(); 751 void HideWaylandWindow(); 752 void HideWaylandPopupWindow(bool aTemporaryHidden, bool aRemoveFromPopupList); 753 void HideWaylandToplevelWindow(); 754 void WaylandPopupHideTooltips(); 755 void AppendPopupToHierarchyList(nsWindow* aToplevelWindow); 756 void WaylandPopupHierarchyHideTemporary(); 757 void WaylandPopupHierarchyShowTemporaryHidden(); 758 void WaylandPopupHierarchyCalculatePositions(); 759 bool IsInPopupHierarchy(); 760 void AddWindowToPopupHierarchy(); 761 void UpdateWaylandPopupHierarchy(); 762 void WaylandPopupHierarchyHideByLayout( 763 nsTArray<nsIWidget*>* aLayoutWidgetHierarchy); 764 void WaylandPopupHierarchyValidateByLayout( 765 nsTArray<nsIWidget*>* aLayoutWidgetHierarchy); 766 void CloseAllPopupsBeforeRemotePopup(); 767 void WaylandPopupHideClosedPopups(); 768 void WaylandPopupMove(); 769 bool WaylandPopupRemoveNegativePosition(int* aX = nullptr, int* aY = nullptr); 770 nsWindow* WaylandPopupGetTopmostWindow(); 771 bool IsPopupInLayoutPopupChain(nsTArray<nsIWidget*>* aLayoutWidgetHierarchy, 772 bool aMustMatchParent); 773 void WaylandPopupMarkAsClosed(); 774 void WaylandPopupRemoveClosedPopups(); 775 void WaylandPopupSetDirectPosition(); 776 bool WaylandPopupFitsParentWindow(const GdkRectangle& aSize); 777 nsWindow* WaylandPopupFindLast(nsWindow* aPopup); 778 GtkWindow* GetCurrentTopmostWindow(); 779 nsAutoCString GetFrameTag() const; 780 nsCString GetPopupTypeName(); 781 bool IsPopupDirectionRTL(); 782 783 #ifdef MOZ_LOGGING 784 void LogPopupHierarchy(); 785 #endif 786 787 // mPopupPosition is the original popup position from layout, set by 788 // nsWindow::Move() or nsWindow::Resize(). 789 GdkPoint mPopupPosition{}; 790 791 // mRelativePopupPosition is popup position calculated against parent window. 792 GdkPoint mRelativePopupPosition{}; 793 794 // Toplevel window (first element) of linked list of Wayland popups. It's null 795 // if we're the toplevel. 796 RefPtr<nsWindow> mWaylandToplevel; 797 798 // Next/Previous popups in Wayland popup hierarchy. 799 RefPtr<nsWindow> mWaylandPopupNext; 800 RefPtr<nsWindow> mWaylandPopupPrev; 801 802 // Used by WaylandPopupMove() to track popup movement. 803 LayoutDeviceIntRect mPreferredPopupRect; 804 805 LayoutDeviceIntRect mNewBoundsAfterMoveToRect; 806 807 /** 808 * |mIMContext| takes all IME related stuff. 809 * 810 * This is owned by the top-level nsWindow or the topmost child 811 * nsWindow embedded in a non-Gecko widget. 812 * 813 * The instance is created when the top level widget is created. And when 814 * the widget is destroyed, it's released. All child windows refer its 815 * ancestor widget's instance. So, one set of IM contexts is created for 816 * all windows in a hierarchy. If the children are released after the top 817 * level window is released, the children still have a valid pointer, 818 * however, IME doesn't work at that time. 819 */ 820 RefPtr<mozilla::widget::IMContextWrapper> mIMContext; 821 822 mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter; 823 static GtkWindowDecoration sGtkWindowDecoration; 824 825 static bool sTransparentMainWindow; 826 827 #ifdef ACCESSIBILITY 828 RefPtr<mozilla::a11y::LocalAccessible> mRootAccessible; 829 830 /** 831 * Request to create the accessible for this window if it is top level. 832 */ 833 void CreateRootAccessible(); 834 835 /** 836 * Dispatch accessible event for the top level window accessible. 837 * 838 * @param aEventType [in] the accessible event type to dispatch 839 */ 840 void DispatchEventToRootAccessible(uint32_t aEventType); 841 842 /** 843 * Dispatch accessible window activate event for the top level window 844 * accessible. 845 */ 846 void DispatchActivateEventAccessible(); 847 848 /** 849 * Dispatch accessible window deactivate event for the top level window 850 * accessible. 851 */ 852 void DispatchDeactivateEventAccessible(); 853 854 /** 855 * Dispatch accessible window maximize event for the top level window 856 * accessible. 857 */ 858 void DispatchMaximizeEventAccessible(); 859 860 /** 861 * Dispatch accessible window minize event for the top level window 862 * accessible. 863 */ 864 void DispatchMinimizeEventAccessible(); 865 866 /** 867 * Dispatch accessible window restore event for the top level window 868 * accessible. 869 */ 870 void DispatchRestoreEventAccessible(); 871 #endif 872 873 #ifdef MOZ_X11 874 typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT = 0, 875 GTK_WIDGET_COMPOSIDED_DISABLED = 1, 876 GTK_WIDGET_COMPOSIDED_ENABLED = 2} WindowComposeRequest; 877 void SetCompositorHint(WindowComposeRequest aState); 878 bool ConfigureX11GLVisual(); 879 #endif 880 #ifdef MOZ_WAYLAND 881 RefPtr<mozilla::gfx::VsyncSource> mWaylandVsyncSource; 882 LayoutDeviceIntPoint mNativePointerLockCenter; 883 zwp_locked_pointer_v1* mLockedPointer = nullptr; 884 zwp_relative_pointer_v1* mRelativePointer = nullptr; 885 xdg_activation_token_v1* mXdgToken = nullptr; 886 #endif 887 mozilla::widget::WindowSurfaceProvider mSurfaceProvider; 888 }; 889 890 #endif /* __nsWindow_h__ */ 891