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.h580
1 files changed, 580 insertions, 0 deletions
diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
new file mode 100644
index 000000000..49a8d4baf
--- /dev/null
+++ b/widget/gtk/nsWindow.h
@@ -0,0 +1,580 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* 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 "mozcontainer.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "nsIDragService.h"
+#include "nsITimer.h"
+#include "nsGkAtoms.h"
+#include "nsRefPtrHashtable.h"
+
+#include "nsBaseWidget.h"
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#ifdef MOZ_X11
+#include <gdk/gdkx.h>
+#endif /* MOZ_X11 */
+
+#include "mozilla/widget/WindowSurface.h"
+#include "mozilla/widget/WindowSurfaceProvider.h"
+
+#ifdef ACCESSIBILITY
+#include "mozilla/a11y/Accessible.h"
+#endif
+#include "mozilla/EventForwards.h"
+#include "mozilla/TouchEvents.h"
+
+#include "IMContextWrapper.h"
+
+#undef LOG
+#ifdef MOZ_LOGGING
+
+#include "mozilla/Logging.h"
+#include "nsTArray.h"
+#include "Units.h"
+
+extern PRLogModuleInfo *gWidgetLog;
+extern PRLogModuleInfo *gWidgetFocusLog;
+extern PRLogModuleInfo *gWidgetDragLog;
+extern PRLogModuleInfo *gWidgetDrawLog;
+
+#define LOG(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args)
+#define LOGFOCUS(args) MOZ_LOG(gWidgetFocusLog, mozilla::LogLevel::Debug, args)
+#define LOGDRAG(args) MOZ_LOG(gWidgetDragLog, mozilla::LogLevel::Debug, args)
+#define LOGDRAW(args) MOZ_LOG(gWidgetDrawLog, mozilla::LogLevel::Debug, args)
+
+#else
+
+#define LOG(args)
+#define LOGFOCUS(args)
+#define LOGDRAG(args)
+#define LOGDRAW(args)
+
+#endif /* MOZ_LOGGING */
+
+class gfxPattern;
+class nsPluginNativeWindowGtk;
+
+namespace mozilla {
+class TimeStamp;
+class CurrentX11TimeGetter;
+}
+
+class nsWindow : public nsBaseWidget
+{
+public:
+ typedef mozilla::gfx::DrawTarget DrawTarget;
+ typedef mozilla::WidgetEventTime WidgetEventTime;
+
+ nsWindow();
+
+ static void ReleaseGlobals();
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ void CommonCreate(nsIWidget *aParent, bool aListenForResizes);
+
+ virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
+ nsEventStatus& aStatus) override;
+
+ // called when we are destroyed
+ virtual void OnDestroy(void) 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
+ virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent,
+ nsNativeWidget aNativeParent,
+ const LayoutDeviceIntRect& aRect,
+ nsWidgetInitData* aInitData) override;
+ virtual void Destroy() override;
+ virtual nsIWidget *GetParent() override;
+ virtual float GetDPI() override;
+ virtual double GetDefaultScaleInternal() override;
+ // Under Gtk, we manage windows using device pixels so no scaling is needed:
+ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final
+ {
+ return mozilla::DesktopToLayoutDeviceScale(1.0);
+ }
+ virtual nsresult SetParent(nsIWidget* aNewParent) override;
+ virtual void SetModal(bool aModal) override;
+ virtual bool IsVisible() const override;
+ virtual void ConstrainPosition(bool aAllowSlop,
+ int32_t *aX,
+ int32_t *aY) override;
+ virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
+ NS_IMETHOD Move(double aX,
+ double aY) override;
+ NS_IMETHOD Show (bool aState) override;
+ NS_IMETHOD Resize (double aWidth,
+ double aHeight,
+ bool aRepaint) override;
+ NS_IMETHOD Resize (double aX,
+ double aY,
+ double aWidth,
+ double aHeight,
+ bool aRepaint) override;
+ virtual bool IsEnabled() const override;
+
+ void SetZIndex(int32_t aZIndex) override;
+ virtual void SetSizeMode(nsSizeMode aMode) override;
+ NS_IMETHOD Enable(bool aState) override;
+ NS_IMETHOD SetFocus(bool aRaise = false) override;
+ virtual LayoutDeviceIntRect GetScreenBounds() override;
+ virtual LayoutDeviceIntRect GetClientBounds() override;
+ virtual LayoutDeviceIntSize GetClientSize() override;
+ virtual LayoutDeviceIntPoint GetClientOffset() override;
+ NS_IMETHOD SetCursor(nsCursor aCursor) override;
+ NS_IMETHOD SetCursor(imgIContainer* aCursor,
+ uint32_t aHotspotX, uint32_t aHotspotY) override;
+ NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override;
+ virtual void* GetNativeData(uint32_t aDataType) override;
+ void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
+ NS_IMETHOD SetTitle(const nsAString& aTitle) override;
+ NS_IMETHOD SetIcon(const nsAString& aIconSpec) override;
+ virtual void SetWindowClass(const nsAString& xulWinType) override;
+ virtual LayoutDeviceIntPoint WidgetToScreenOffset() override;
+ virtual void CaptureMouse(bool aCapture) override;
+ virtual void CaptureRollupEvents(nsIRollupListener *aListener,
+ bool aDoCapture) override;
+ NS_IMETHOD GetAttention(int32_t aCycleCount) override;
+ virtual nsresult SetWindowClipRegion(const nsTArray<LayoutDeviceIntRect>& aRects,
+ bool aIntersectWithExisting) override;
+ virtual bool HasPendingInputEvent() override;
+
+ virtual bool PrepareForFullscreenTransition(nsISupports** aData) override;
+ virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage,
+ uint16_t aDuration,
+ nsISupports* aData,
+ nsIRunnable* aCallback) override;
+ virtual nsresult MakeFullScreen(bool aFullScreen,
+ nsIScreen* aTargetScreen = nullptr) override;
+ NS_IMETHOD 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);
+
+ GdkRectangle DevicePixelsToGdkRectRoundOut(LayoutDeviceIntRect aRect);
+
+ // event callbacks
+#if (MOZ_WIDGET_GTK == 2)
+ gboolean OnExposeEvent(GdkEventExpose *aEvent);
+#else
+ gboolean OnExposeEvent(cairo_t *cr);
+#endif
+ gboolean OnConfigureEvent(GtkWidget *aWidget,
+ GdkEventConfigure *aEvent);
+ void OnContainerUnrealize();
+ 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 OnVisibilityNotifyEvent(GdkEventVisibility *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);
+#if GTK_CHECK_VERSION(3,4,0)
+ gboolean OnTouchEvent(GdkEventTouch* aEvent);
+#endif
+
+ virtual already_AddRefed<mozilla::gfx::DrawTarget>
+ StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
+ mozilla::layers::BufferMode* aBufferMode) override;
+ virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget,
+ LayoutDeviceIntRegion& aInvalidRegion) override;
+
+private:
+ void UpdateAlpha(mozilla::gfx::SourceSurface* aSourceSurface, nsIntRect aBoundsRect);
+
+ void NativeMove();
+ void NativeResize();
+ void NativeMoveResize();
+
+ void NativeShow (bool aAction);
+ void SetHasMappedToplevel(bool aState);
+ LayoutDeviceIntSize GetSafeWindowSize(LayoutDeviceIntSize aSize);
+
+ void EnsureGrabs (void);
+ void GrabPointer (guint32 aTime);
+ void ReleaseGrabs (void);
+
+ void UpdateClientOffset();
+
+public:
+ enum PluginType {
+ PluginType_NONE = 0, /* do not have any plugin */
+ PluginType_XEMBED, /* the plugin support xembed */
+ PluginType_NONXEMBED /* the plugin does not support xembed */
+ };
+
+ void SetPluginType(PluginType aPluginType);
+#ifdef MOZ_X11
+ void SetNonXEmbedPluginFocus(void);
+ void LoseNonXEmbedPluginFocus(void);
+#endif /* MOZ_X11 */
+
+ void ThemeChanged(void);
+ void OnDPIChanged(void);
+ void OnCheckResize(void);
+
+#ifdef MOZ_X11
+ Window mOldFocusWindow;
+#endif /* MOZ_X11 */
+
+ static guint32 sLastButtonPressTime;
+
+ NS_IMETHOD BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent,
+ int32_t aHorizontal,
+ int32_t aVertical) override;
+ NS_IMETHOD BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent) override;
+
+ MozContainer* GetMozContainer() { return mContainer; }
+ // GetMozContainerWidget returns the MozContainer even for undestroyed
+ // descendant windows
+ GtkWidget* GetMozContainerWidget();
+ GdkWindow* GetGdkWindow() { return mGdkWindow; }
+ bool IsDestroyed() { return mIsDestroyed; }
+
+ void DispatchDragEvent(mozilla::EventMessage aMsg,
+ const LayoutDeviceIntPoint& aRefPoint,
+ guint aTime);
+ static void UpdateDragStatus (GdkDragContext *aDragContext,
+ nsIDragService *aDragService);
+ // If this dispatched the keydown event actually, this returns TRUE,
+ // otherwise, FALSE.
+ bool DispatchKeyDownEvent(GdkEventKey *aEvent,
+ bool *aIsCancelled);
+ WidgetEventTime GetWidgetEventTime(guint32 aEventTime);
+ mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime);
+ mozilla::CurrentX11TimeGetter* GetCurrentTimeGetter();
+
+ NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
+ const InputContextAction& aAction) override;
+ NS_IMETHOD_(InputContext) GetInputContext() override;
+ virtual nsIMEUpdatePreference GetIMEUpdatePreference() override;
+ NS_IMETHOD_(TextEventDispatcherListener*)
+ GetNativeTextEventDispatcherListener() override;
+ bool ExecuteNativeKeyBindingRemapped(
+ NativeKeyBindingsType aType,
+ const mozilla::WidgetKeyboardEvent& aEvent,
+ DoCommandCallback aCallback,
+ void* aCallbackData,
+ uint32_t aGeckoKeyCode,
+ uint32_t aNativeKeyCode);
+ NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
+ NativeKeyBindingsType aType,
+ const mozilla::WidgetKeyboardEvent& aEvent,
+ DoCommandCallback aCallback,
+ void* aCallbackData) override;
+
+ // These methods are for toplevel windows only.
+ void ResizeTransparencyBitmap();
+ void ApplyTransparencyBitmap();
+ void ClearTransparencyBitmap();
+
+ virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
+ virtual nsTransparencyMode GetTransparencyMode() override;
+ virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) override;
+ nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
+ uint8_t* aAlphas, int32_t aStride);
+
+#if (MOZ_WIDGET_GTK == 2)
+ static already_AddRefed<DrawTarget> GetDrawTargetForGdkDrawable(GdkDrawable* aDrawable,
+ const mozilla::gfx::IntSize& aSize);
+#endif
+ virtual void ReparentNativeWidget(nsIWidget* aNewParent) override;
+
+ virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
+ uint32_t aNativeMessage,
+ uint32_t aModifierFlags,
+ nsIObserver* aObserver) override;
+
+ virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
+ nsIObserver* aObserver) override
+ { return SynthesizeNativeMouseEvent(aPoint, GDK_MOTION_NOTIFY, 0, aObserver); }
+
+ virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint,
+ uint32_t aNativeMessage,
+ double aDeltaX,
+ double aDeltaY,
+ double aDeltaZ,
+ uint32_t aModifierFlags,
+ uint32_t aAdditionalFlags,
+ nsIObserver* aObserver) override;
+
+#if GTK_CHECK_VERSION(3,4,0)
+ virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
+ TouchPointerState aPointerState,
+ LayoutDeviceIntPoint aPoint,
+ double aPointerPressure,
+ uint32_t aPointerOrientation,
+ nsIObserver* aObserver) override;
+#endif
+
+#ifdef MOZ_X11
+ Display* XDisplay() { return mXDisplay; }
+#endif
+ virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
+
+ // HiDPI scale conversion
+ gint GdkScaleFactor();
+
+ // To GDK
+ gint DevicePixelsToGdkCoordRoundUp(int pixels);
+ gint DevicePixelsToGdkCoordRoundDown(int pixels);
+ GdkPoint DevicePixelsToGdkPointRoundDown(LayoutDeviceIntPoint point);
+ GdkRectangle DevicePixelsToGdkSizeRoundUp(LayoutDeviceIntSize pixelSize);
+
+ // From GDK
+ int GdkCoordToDevicePixels(gint coord);
+ LayoutDeviceIntPoint GdkPointToDevicePixels(GdkPoint point);
+ LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble x, gdouble y);
+ LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect);
+
+ virtual bool WidgetTypeSupportsAcceleration() override;
+protected:
+ virtual ~nsWindow();
+
+ // event handling code
+ void DispatchActivateEvent(void);
+ void DispatchDeactivateEvent(void);
+ void DispatchResized();
+ void MaybeDispatchResized();
+
+ // Helper for SetParent and ReparentNativeWidget.
+ void ReparentNativeWidgetInternal(nsIWidget* aNewParent,
+ GtkWidget* aNewContainer,
+ GdkWindow* aNewParentWindow,
+ GtkWidget* aOldContainer);
+
+ virtual void RegisterTouchWindow() override;
+
+ nsCOMPtr<nsIWidget> mParent;
+ // Is this a toplevel window?
+ bool mIsTopLevel;
+ // Has this widget been destroyed yet?
+ bool mIsDestroyed;
+
+ // Should we send resize events on all resizes?
+ bool mListenForResizes;
+ // Does WindowResized need to be called on listeners?
+ bool mNeedsDispatchResized;
+ // This flag tracks if we're hidden or shown.
+ bool mIsShown;
+ bool mNeedsShow;
+ // is this widget enabled?
+ bool mEnabled;
+ // has the native window for this been created yet?
+ bool mCreated;
+#if GTK_CHECK_VERSION(3,4,0)
+ // whether we handle touch event
+ bool mHandleTouchEvent;
+#endif
+ // true if this is a drag and drop feedback popup
+ bool mIsDragPopup;
+ // Can we access X?
+ bool mIsX11Display;
+
+private:
+ void DestroyChildWindows();
+ GtkWidget *GetToplevelWidget();
+ nsWindow *GetContainerWindow();
+ void SetUrgencyHint(GtkWidget *top_window, bool state);
+ void *SetupPluginPort(void);
+ void SetDefaultIcon(void);
+ void InitButtonEvent(mozilla::WidgetMouseEvent& aEvent,
+ GdkEventButton* aGdkEvent);
+ bool DispatchCommandEvent(nsIAtom* aCommand);
+ bool DispatchContentCommandEvent(mozilla::EventMessage aMsg);
+ 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);
+ void ClearCachedResources();
+ nsIWidgetListener* GetListener();
+
+ GtkWidget *mShell;
+ MozContainer *mContainer;
+ GdkWindow *mGdkWindow;
+
+ uint32_t mHasMappedToplevel : 1,
+ mIsFullyObscured : 1,
+ mRetryPointerGrab : 1;
+ nsSizeMode mSizeState;
+ PluginType mPluginType;
+
+ int32_t mTransparencyBitmapWidth;
+ int32_t mTransparencyBitmapHeight;
+
+ nsIntPoint mClientOffset;
+
+#if GTK_CHECK_VERSION(3,4,0)
+ // This field omits duplicate scroll events caused by GNOME bug 726878.
+ guint32 mLastScrollEventTime;
+
+ // for touch event handling
+ nsRefPtrHashtable<nsPtrHashKey<GdkEventSequence>, mozilla::dom::Touch> mTouches;
+#endif
+
+#ifdef MOZ_X11
+ Display* mXDisplay;
+ Window mXWindow;
+ Visual* mXVisual;
+ int mXDepth;
+ mozilla::widget::WindowSurfaceProvider mSurfaceProvider;
+#endif
+
+ // Upper bound on pending ConfigureNotify events to be dispatched to the
+ // window. See bug 1225044.
+ unsigned int mPendingConfigures;
+
+#ifdef ACCESSIBILITY
+ RefPtr<mozilla::a11y::Accessible> 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
+
+ // Updates the bounds of the socket widget we manage for remote plugins.
+ void ResizePluginSocketWidget();
+
+ // e10s specific - for managing the socket widget this window hosts.
+ nsPluginNativeWindowGtk* mPluginNativeWindow;
+
+ // The cursor cache
+ static GdkCursor *gsGtkCursorCache[eCursorCount];
+
+ // Transparency
+ bool mIsTransparent;
+ // 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;
+
+ // all of our DND stuff
+ void InitDragEvent(mozilla::WidgetDragEvent& aEvent);
+
+ float mLastMotionPressure;
+
+ // Remember the last sizemode so that we can restore it when
+ // leaving fullscreen
+ nsSizeMode mLastSizeMode;
+
+ static bool DragInProgress(void);
+
+ void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent);
+
+ // nsBaseWidget
+ virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
+ LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
+ LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
+
+ void CleanLayerManagerRecursive();
+
+ virtual int32_t RoundsWidgetCoordinatesTo() override;
+
+ /**
+ * |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;
+
+ mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter;
+};
+
+class nsChildWindow : public nsWindow {
+public:
+ nsChildWindow();
+ ~nsChildWindow();
+};
+
+#endif /* __nsWindow_h__ */