1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 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 "mozcontainer.h" 12 #include "mozilla/RefPtr.h" 13 #include "mozilla/UniquePtr.h" 14 #include "nsIDragService.h" 15 #include "nsITimer.h" 16 #include "nsGkAtoms.h" 17 #include "nsRefPtrHashtable.h" 18 19 #include "nsBaseWidget.h" 20 #include <gdk/gdk.h> 21 #include <gtk/gtk.h> 22 23 #ifdef MOZ_X11 24 #include <gdk/gdkx.h> 25 #endif /* MOZ_X11 */ 26 27 #include "mozilla/widget/WindowSurface.h" 28 #include "mozilla/widget/WindowSurfaceProvider.h" 29 30 #ifdef ACCESSIBILITY 31 #include "mozilla/a11y/Accessible.h" 32 #endif 33 #include "mozilla/EventForwards.h" 34 #include "mozilla/TouchEvents.h" 35 36 #include "IMContextWrapper.h" 37 38 #undef LOG 39 #ifdef MOZ_LOGGING 40 41 #include "mozilla/Logging.h" 42 #include "nsTArray.h" 43 #include "Units.h" 44 45 extern PRLogModuleInfo *gWidgetLog; 46 extern PRLogModuleInfo *gWidgetFocusLog; 47 extern PRLogModuleInfo *gWidgetDragLog; 48 extern PRLogModuleInfo *gWidgetDrawLog; 49 50 #define LOG(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args) 51 #define LOGFOCUS(args) MOZ_LOG(gWidgetFocusLog, mozilla::LogLevel::Debug, args) 52 #define LOGDRAG(args) MOZ_LOG(gWidgetDragLog, mozilla::LogLevel::Debug, args) 53 #define LOGDRAW(args) MOZ_LOG(gWidgetDrawLog, mozilla::LogLevel::Debug, args) 54 55 #else 56 57 #define LOG(args) 58 #define LOGFOCUS(args) 59 #define LOGDRAG(args) 60 #define LOGDRAW(args) 61 62 #endif /* MOZ_LOGGING */ 63 64 class gfxPattern; 65 class nsPluginNativeWindowGtk; 66 67 namespace mozilla { 68 class TimeStamp; 69 class CurrentX11TimeGetter; 70 } 71 72 class nsWindow : public nsBaseWidget 73 { 74 public: 75 typedef mozilla::gfx::DrawTarget DrawTarget; 76 typedef mozilla::WidgetEventTime WidgetEventTime; 77 78 nsWindow(); 79 80 static void ReleaseGlobals(); 81 82 NS_DECL_ISUPPORTS_INHERITED 83 84 void CommonCreate(nsIWidget *aParent, bool aListenForResizes); 85 86 virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, 87 nsEventStatus& aStatus) override; 88 89 // called when we are destroyed 90 virtual void OnDestroy(void) override; 91 92 // called to check and see if a widget's dimensions are sane 93 bool AreBoundsSane(void); 94 95 // nsIWidget 96 using nsBaseWidget::Create; // for Create signature not overridden here 97 virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent, 98 nsNativeWidget aNativeParent, 99 const LayoutDeviceIntRect& aRect, 100 nsWidgetInitData* aInitData) override; 101 virtual void Destroy() override; 102 virtual nsIWidget *GetParent() override; 103 virtual float GetDPI() override; 104 virtual double GetDefaultScaleInternal() override; 105 // Under Gtk, we manage windows using device pixels so no scaling is needed: GetDesktopToDeviceScale()106 mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final 107 { 108 return mozilla::DesktopToLayoutDeviceScale(1.0); 109 } 110 virtual nsresult SetParent(nsIWidget* aNewParent) override; 111 virtual void SetModal(bool aModal) override; 112 virtual bool IsVisible() const override; 113 virtual void ConstrainPosition(bool aAllowSlop, 114 int32_t *aX, 115 int32_t *aY) override; 116 virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override; 117 NS_IMETHOD Move(double aX, 118 double aY) override; 119 NS_IMETHOD Show (bool aState) override; 120 NS_IMETHOD Resize (double aWidth, 121 double aHeight, 122 bool aRepaint) override; 123 NS_IMETHOD Resize (double aX, 124 double aY, 125 double aWidth, 126 double aHeight, 127 bool aRepaint) override; 128 virtual bool IsEnabled() const override; 129 130 void SetZIndex(int32_t aZIndex) override; 131 virtual void SetSizeMode(nsSizeMode aMode) override; 132 NS_IMETHOD Enable(bool aState) override; 133 NS_IMETHOD SetFocus(bool aRaise = false) override; 134 virtual LayoutDeviceIntRect GetScreenBounds() override; 135 virtual LayoutDeviceIntRect GetClientBounds() override; 136 virtual LayoutDeviceIntSize GetClientSize() override; 137 virtual LayoutDeviceIntPoint GetClientOffset() override; 138 NS_IMETHOD SetCursor(nsCursor aCursor) override; 139 NS_IMETHOD SetCursor(imgIContainer* aCursor, 140 uint32_t aHotspotX, uint32_t aHotspotY) override; 141 NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override; 142 virtual void* GetNativeData(uint32_t aDataType) override; 143 void SetNativeData(uint32_t aDataType, uintptr_t aVal) override; 144 NS_IMETHOD SetTitle(const nsAString& aTitle) override; 145 NS_IMETHOD SetIcon(const nsAString& aIconSpec) override; 146 virtual void SetWindowClass(const nsAString& xulWinType) override; 147 virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; 148 virtual void CaptureMouse(bool aCapture) override; 149 virtual void CaptureRollupEvents(nsIRollupListener *aListener, 150 bool aDoCapture) override; 151 NS_IMETHOD GetAttention(int32_t aCycleCount) override; 152 virtual nsresult SetWindowClipRegion(const nsTArray<LayoutDeviceIntRect>& aRects, 153 bool aIntersectWithExisting) override; 154 virtual bool HasPendingInputEvent() override; 155 156 virtual bool PrepareForFullscreenTransition(nsISupports** aData) override; 157 virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, 158 uint16_t aDuration, 159 nsISupports* aData, 160 nsIRunnable* aCallback) override; 161 virtual nsresult MakeFullScreen(bool aFullScreen, 162 nsIScreen* aTargetScreen = nullptr) override; 163 NS_IMETHOD HideWindowChrome(bool aShouldHide) override; 164 165 /** 166 * GetLastUserInputTime returns a timestamp for the most recent user input 167 * event. This is intended for pointer grab requests (including drags). 168 */ 169 static guint32 GetLastUserInputTime(); 170 171 // utility method, -1 if no change should be made, otherwise returns a 172 // value that can be passed to gdk_window_set_decorations 173 gint ConvertBorderStyles(nsBorderStyle aStyle); 174 175 GdkRectangle DevicePixelsToGdkRectRoundOut(LayoutDeviceIntRect aRect); 176 177 // event callbacks 178 #if (MOZ_WIDGET_GTK == 2) 179 gboolean OnExposeEvent(GdkEventExpose *aEvent); 180 #else 181 gboolean OnExposeEvent(cairo_t *cr); 182 #endif 183 gboolean OnConfigureEvent(GtkWidget *aWidget, 184 GdkEventConfigure *aEvent); 185 void OnContainerUnrealize(); 186 void OnSizeAllocate(GtkAllocation *aAllocation); 187 void OnDeleteEvent(); 188 void OnEnterNotifyEvent(GdkEventCrossing *aEvent); 189 void OnLeaveNotifyEvent(GdkEventCrossing *aEvent); 190 void OnMotionNotifyEvent(GdkEventMotion *aEvent); 191 void OnButtonPressEvent(GdkEventButton *aEvent); 192 void OnButtonReleaseEvent(GdkEventButton *aEvent); 193 void OnContainerFocusInEvent(GdkEventFocus *aEvent); 194 void OnContainerFocusOutEvent(GdkEventFocus *aEvent); 195 gboolean OnKeyPressEvent(GdkEventKey *aEvent); 196 gboolean OnKeyReleaseEvent(GdkEventKey *aEvent); 197 void OnScrollEvent(GdkEventScroll *aEvent); 198 void OnVisibilityNotifyEvent(GdkEventVisibility *aEvent); 199 void OnWindowStateEvent(GtkWidget *aWidget, 200 GdkEventWindowState *aEvent); 201 void OnDragDataReceivedEvent(GtkWidget *aWidget, 202 GdkDragContext *aDragContext, 203 gint aX, 204 gint aY, 205 GtkSelectionData*aSelectionData, 206 guint aInfo, 207 guint aTime, 208 gpointer aData); 209 gboolean OnPropertyNotifyEvent(GtkWidget *aWidget, 210 GdkEventProperty *aEvent); 211 #if GTK_CHECK_VERSION(3,4,0) 212 gboolean OnTouchEvent(GdkEventTouch* aEvent); 213 #endif 214 215 virtual already_AddRefed<mozilla::gfx::DrawTarget> 216 StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, 217 mozilla::layers::BufferMode* aBufferMode) override; 218 virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget, 219 LayoutDeviceIntRegion& aInvalidRegion) override; 220 221 private: 222 void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, nsIntRect aBoundsRect); 223 224 void NativeMove(); 225 void NativeResize(); 226 void NativeMoveResize(); 227 228 void NativeShow (bool aAction); 229 void SetHasMappedToplevel(bool aState); 230 LayoutDeviceIntSize GetSafeWindowSize(LayoutDeviceIntSize aSize); 231 232 void EnsureGrabs (void); 233 void GrabPointer (guint32 aTime); 234 void ReleaseGrabs (void); 235 236 void UpdateClientOffset(); 237 238 public: 239 enum PluginType { 240 PluginType_NONE = 0, /* do not have any plugin */ 241 PluginType_XEMBED, /* the plugin support xembed */ 242 PluginType_NONXEMBED /* the plugin does not support xembed */ 243 }; 244 245 void SetPluginType(PluginType aPluginType); 246 #ifdef MOZ_X11 247 void SetNonXEmbedPluginFocus(void); 248 void LoseNonXEmbedPluginFocus(void); 249 #endif /* MOZ_X11 */ 250 251 void ThemeChanged(void); 252 void OnDPIChanged(void); 253 void OnCheckResize(void); 254 255 #ifdef MOZ_X11 256 Window mOldFocusWindow; 257 #endif /* MOZ_X11 */ 258 259 static guint32 sLastButtonPressTime; 260 261 NS_IMETHOD BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent, 262 int32_t aHorizontal, 263 int32_t aVertical) override; 264 NS_IMETHOD BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent) override; 265 GetMozContainer()266 MozContainer* GetMozContainer() { return mContainer; } 267 // GetMozContainerWidget returns the MozContainer even for undestroyed 268 // descendant windows 269 GtkWidget* GetMozContainerWidget(); GetGdkWindow()270 GdkWindow* GetGdkWindow() { return mGdkWindow; } IsDestroyed()271 bool IsDestroyed() { return mIsDestroyed; } 272 273 void DispatchDragEvent(mozilla::EventMessage aMsg, 274 const LayoutDeviceIntPoint& aRefPoint, 275 guint aTime); 276 static void UpdateDragStatus (GdkDragContext *aDragContext, 277 nsIDragService *aDragService); 278 // If this dispatched the keydown event actually, this returns TRUE, 279 // otherwise, FALSE. 280 bool DispatchKeyDownEvent(GdkEventKey *aEvent, 281 bool *aIsCancelled); 282 WidgetEventTime GetWidgetEventTime(guint32 aEventTime); 283 mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime); 284 mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter(); 285 286 NS_IMETHOD_(void) SetInputContext(const InputContext& aContext, 287 const InputContextAction& aAction) override; 288 NS_IMETHOD_(InputContext) GetInputContext() override; 289 virtual nsIMEUpdatePreference GetIMEUpdatePreference() override; 290 NS_IMETHOD_(TextEventDispatcherListener*) 291 GetNativeTextEventDispatcherListener() override; 292 bool ExecuteNativeKeyBindingRemapped( 293 NativeKeyBindingsType aType, 294 const mozilla::WidgetKeyboardEvent& aEvent, 295 DoCommandCallback aCallback, 296 void* aCallbackData, 297 uint32_t aGeckoKeyCode, 298 uint32_t aNativeKeyCode); 299 NS_IMETHOD_(bool) ExecuteNativeKeyBinding( 300 NativeKeyBindingsType aType, 301 const mozilla::WidgetKeyboardEvent& aEvent, 302 DoCommandCallback aCallback, 303 void* aCallbackData) override; 304 305 // These methods are for toplevel windows only. 306 void ResizeTransparencyBitmap(); 307 void ApplyTransparencyBitmap(); 308 void ClearTransparencyBitmap(); 309 310 virtual void SetTransparencyMode(nsTransparencyMode aMode) override; 311 virtual nsTransparencyMode GetTransparencyMode() override; 312 virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override; 313 nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect, 314 uint8_t* aAlphas, int32_t aStride); 315 316 #if (MOZ_WIDGET_GTK == 2) 317 static already_AddRefed<DrawTarget> GetDrawTargetForGdkDrawable(GdkDrawable* aDrawable, 318 const mozilla::gfx::IntSize& aSize); 319 #endif 320 virtual void ReparentNativeWidget(nsIWidget* aNewParent) override; 321 322 virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, 323 uint32_t aNativeMessage, 324 uint32_t aModifierFlags, 325 nsIObserver* aObserver) override; 326 SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,nsIObserver * aObserver)327 virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, 328 nsIObserver* aObserver) override 329 { return SynthesizeNativeMouseEvent(aPoint, GDK_MOTION_NOTIFY, 0, aObserver); } 330 331 virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint, 332 uint32_t aNativeMessage, 333 double aDeltaX, 334 double aDeltaY, 335 double aDeltaZ, 336 uint32_t aModifierFlags, 337 uint32_t aAdditionalFlags, 338 nsIObserver* aObserver) override; 339 340 #if GTK_CHECK_VERSION(3,4,0) 341 virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, 342 TouchPointerState aPointerState, 343 LayoutDeviceIntPoint aPoint, 344 double aPointerPressure, 345 uint32_t aPointerOrientation, 346 nsIObserver* aObserver) override; 347 #endif 348 349 #ifdef MOZ_X11 XDisplay()350 Display* XDisplay() { return mXDisplay; } 351 #endif 352 virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override; 353 354 // HiDPI scale conversion 355 gint GdkScaleFactor(); 356 357 // To GDK 358 gint DevicePixelsToGdkCoordRoundUp(int pixels); 359 gint DevicePixelsToGdkCoordRoundDown(int pixels); 360 GdkPoint DevicePixelsToGdkPointRoundDown(LayoutDeviceIntPoint point); 361 GdkRectangle DevicePixelsToGdkSizeRoundUp(LayoutDeviceIntSize pixelSize); 362 363 // From GDK 364 int GdkCoordToDevicePixels(gint coord); 365 LayoutDeviceIntPoint GdkPointToDevicePixels(GdkPoint point); 366 LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble x, gdouble y); 367 LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect); 368 369 virtual bool WidgetTypeSupportsAcceleration() override; 370 protected: 371 virtual ~nsWindow(); 372 373 // event handling code 374 void DispatchActivateEvent(void); 375 void DispatchDeactivateEvent(void); 376 void DispatchResized(); 377 void MaybeDispatchResized(); 378 379 // Helper for SetParent and ReparentNativeWidget. 380 void ReparentNativeWidgetInternal(nsIWidget* aNewParent, 381 GtkWidget* aNewContainer, 382 GdkWindow* aNewParentWindow, 383 GtkWidget* aOldContainer); 384 385 virtual void RegisterTouchWindow() override; 386 387 nsCOMPtr<nsIWidget> mParent; 388 // Is this a toplevel window? 389 bool mIsTopLevel; 390 // Has this widget been destroyed yet? 391 bool mIsDestroyed; 392 393 // Should we send resize events on all resizes? 394 bool mListenForResizes; 395 // Does WindowResized need to be called on listeners? 396 bool mNeedsDispatchResized; 397 // This flag tracks if we're hidden or shown. 398 bool mIsShown; 399 bool mNeedsShow; 400 // is this widget enabled? 401 bool mEnabled; 402 // has the native window for this been created yet? 403 bool mCreated; 404 #if GTK_CHECK_VERSION(3,4,0) 405 // whether we handle touch event 406 bool mHandleTouchEvent; 407 #endif 408 // true if this is a drag and drop feedback popup 409 bool mIsDragPopup; 410 // Can we access X? 411 bool mIsX11Display; 412 413 private: 414 void DestroyChildWindows(); 415 GtkWidget *GetToplevelWidget(); 416 nsWindow *GetContainerWindow(); 417 void SetUrgencyHint(GtkWidget *top_window, bool state); 418 void *SetupPluginPort(void); 419 void SetDefaultIcon(void); 420 void InitButtonEvent(mozilla::WidgetMouseEvent& aEvent, 421 GdkEventButton* aGdkEvent); 422 bool DispatchCommandEvent(nsIAtom* aCommand); 423 bool DispatchContentCommandEvent(mozilla::EventMessage aMsg); 424 bool CheckForRollup(gdouble aMouseX, gdouble aMouseY, 425 bool aIsWheel, bool aAlwaysRollup); CheckForRollupDuringGrab()426 void CheckForRollupDuringGrab() 427 { 428 CheckForRollup(0, 0, false, true); 429 } 430 431 bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent, 432 GdkWindow** aWindow, gint* aButton, 433 gint* aRootX, gint* aRootY); 434 void ClearCachedResources(); 435 nsIWidgetListener* GetListener(); 436 437 GtkWidget *mShell; 438 MozContainer *mContainer; 439 GdkWindow *mGdkWindow; 440 441 uint32_t mHasMappedToplevel : 1, 442 mIsFullyObscured : 1, 443 mRetryPointerGrab : 1; 444 nsSizeMode mSizeState; 445 PluginType mPluginType; 446 447 int32_t mTransparencyBitmapWidth; 448 int32_t mTransparencyBitmapHeight; 449 450 nsIntPoint mClientOffset; 451 452 #if GTK_CHECK_VERSION(3,4,0) 453 // This field omits duplicate scroll events caused by GNOME bug 726878. 454 guint32 mLastScrollEventTime; 455 456 // for touch event handling 457 nsRefPtrHashtable<nsPtrHashKey<GdkEventSequence>, mozilla::dom::Touch> mTouches; 458 #endif 459 460 #ifdef MOZ_X11 461 Display* mXDisplay; 462 Window mXWindow; 463 Visual* mXVisual; 464 int mXDepth; 465 mozilla::widget::WindowSurfaceProvider mSurfaceProvider; 466 #endif 467 468 // Upper bound on pending ConfigureNotify events to be dispatched to the 469 // window. See bug 1225044. 470 unsigned int mPendingConfigures; 471 472 #ifdef ACCESSIBILITY 473 RefPtr<mozilla::a11y::Accessible> mRootAccessible; 474 475 /** 476 * Request to create the accessible for this window if it is top level. 477 */ 478 void CreateRootAccessible(); 479 480 /** 481 * Dispatch accessible event for the top level window accessible. 482 * 483 * @param aEventType [in] the accessible event type to dispatch 484 */ 485 void DispatchEventToRootAccessible(uint32_t aEventType); 486 487 /** 488 * Dispatch accessible window activate event for the top level window 489 * accessible. 490 */ 491 void DispatchActivateEventAccessible(); 492 493 /** 494 * Dispatch accessible window deactivate event for the top level window 495 * accessible. 496 */ 497 void DispatchDeactivateEventAccessible(); 498 499 /** 500 * Dispatch accessible window maximize event for the top level window 501 * accessible. 502 */ 503 void DispatchMaximizeEventAccessible(); 504 505 /** 506 * Dispatch accessible window minize event for the top level window 507 * accessible. 508 */ 509 void DispatchMinimizeEventAccessible(); 510 511 /** 512 * Dispatch accessible window restore event for the top level window 513 * accessible. 514 */ 515 void DispatchRestoreEventAccessible(); 516 #endif 517 518 // Updates the bounds of the socket widget we manage for remote plugins. 519 void ResizePluginSocketWidget(); 520 521 // e10s specific - for managing the socket widget this window hosts. 522 nsPluginNativeWindowGtk* mPluginNativeWindow; 523 524 // The cursor cache 525 static GdkCursor *gsGtkCursorCache[eCursorCount]; 526 527 // Transparency 528 bool mIsTransparent; 529 // This bitmap tracks which pixels are transparent. We don't support 530 // full translucency at this time; each pixel is either fully opaque 531 // or fully transparent. 532 gchar* mTransparencyBitmap; 533 534 // all of our DND stuff 535 void InitDragEvent(mozilla::WidgetDragEvent& aEvent); 536 537 float mLastMotionPressure; 538 539 // Remember the last sizemode so that we can restore it when 540 // leaving fullscreen 541 nsSizeMode mLastSizeMode; 542 543 static bool DragInProgress(void); 544 545 void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent); 546 547 // nsBaseWidget 548 virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, 549 LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, 550 LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override; 551 552 void CleanLayerManagerRecursive(); 553 554 virtual int32_t RoundsWidgetCoordinatesTo() override; 555 556 /** 557 * |mIMContext| takes all IME related stuff. 558 * 559 * This is owned by the top-level nsWindow or the topmost child 560 * nsWindow embedded in a non-Gecko widget. 561 * 562 * The instance is created when the top level widget is created. And when 563 * the widget is destroyed, it's released. All child windows refer its 564 * ancestor widget's instance. So, one set of IM contexts is created for 565 * all windows in a hierarchy. If the children are released after the top 566 * level window is released, the children still have a valid pointer, 567 * however, IME doesn't work at that time. 568 */ 569 RefPtr<mozilla::widget::IMContextWrapper> mIMContext; 570 571 mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter; 572 }; 573 574 class nsChildWindow : public nsWindow { 575 public: 576 nsChildWindow(); 577 ~nsChildWindow(); 578 }; 579 580 #endif /* __nsWindow_h__ */ 581