michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim:expandtab:shiftwidth=4:tabstop=4: michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef __nsWindow_h__ michael@0: #define __nsWindow_h__ michael@0: michael@0: #include "mozilla/ipc/SharedMemorySysV.h" michael@0: michael@0: #include "nsAutoPtr.h" michael@0: michael@0: #include "mozcontainer.h" michael@0: #include "nsWeakReference.h" michael@0: michael@0: #include "nsIDragService.h" michael@0: #include "nsITimer.h" michael@0: #include "nsGkAtoms.h" michael@0: michael@0: #include "nsBaseWidget.h" michael@0: #include michael@0: #include michael@0: michael@0: #ifdef MOZ_X11 michael@0: #include michael@0: #endif /* MOZ_X11 */ michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: #include "mozilla/a11y/Accessible.h" michael@0: #endif michael@0: #include "mozilla/EventForwards.h" michael@0: michael@0: #include "nsGtkIMModule.h" michael@0: michael@0: #undef LOG michael@0: #ifdef MOZ_LOGGING michael@0: michael@0: // make sure that logging is enabled before including prlog.h michael@0: #define FORCE_PR_LOG michael@0: michael@0: #include "prlog.h" michael@0: #include "nsTArray.h" michael@0: michael@0: extern PRLogModuleInfo *gWidgetLog; michael@0: extern PRLogModuleInfo *gWidgetFocusLog; michael@0: extern PRLogModuleInfo *gWidgetDragLog; michael@0: extern PRLogModuleInfo *gWidgetDrawLog; michael@0: michael@0: #define LOG(args) PR_LOG(gWidgetLog, 4, args) michael@0: #define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args) michael@0: #define LOGDRAG(args) PR_LOG(gWidgetDragLog, 4, args) michael@0: #define LOGDRAW(args) PR_LOG(gWidgetDrawLog, 4, args) michael@0: michael@0: #else michael@0: michael@0: #define LOG(args) michael@0: #define LOGFOCUS(args) michael@0: #define LOGDRAG(args) michael@0: #define LOGDRAW(args) michael@0: michael@0: #endif /* MOZ_LOGGING */ michael@0: michael@0: class gfxASurface; michael@0: class gfxPattern; michael@0: class nsDragService; michael@0: #if defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV) michael@0: # define MOZ_HAVE_SHMIMAGE michael@0: michael@0: class nsShmImage; michael@0: #endif michael@0: michael@0: class nsWindow : public nsBaseWidget, public nsSupportsWeakReference michael@0: { michael@0: public: michael@0: nsWindow(); michael@0: virtual ~nsWindow(); michael@0: michael@0: static void ReleaseGlobals(); michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: michael@0: void CommonCreate(nsIWidget *aParent, bool aListenForResizes); michael@0: michael@0: virtual nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, michael@0: nsEventStatus& aStatus); michael@0: michael@0: // called when we are destroyed michael@0: void OnDestroy(void); michael@0: michael@0: // called to check and see if a widget's dimensions are sane michael@0: bool AreBoundsSane(void); michael@0: michael@0: // nsIWidget michael@0: NS_IMETHOD Create(nsIWidget *aParent, michael@0: nsNativeWidget aNativeParent, michael@0: const nsIntRect &aRect, michael@0: nsDeviceContext *aContext, michael@0: nsWidgetInitData *aInitData); michael@0: NS_IMETHOD Destroy(void); michael@0: virtual nsIWidget *GetParent(); michael@0: virtual float GetDPI(); michael@0: virtual nsresult SetParent(nsIWidget* aNewParent); michael@0: NS_IMETHOD SetModal(bool aModal); michael@0: virtual bool IsVisible() const; michael@0: NS_IMETHOD ConstrainPosition(bool aAllowSlop, michael@0: int32_t *aX, michael@0: int32_t *aY); michael@0: virtual void SetSizeConstraints(const SizeConstraints& aConstraints); michael@0: NS_IMETHOD Move(double aX, michael@0: double aY); michael@0: NS_IMETHOD Show (bool aState); michael@0: NS_IMETHOD Resize (double aWidth, michael@0: double aHeight, michael@0: bool aRepaint); michael@0: NS_IMETHOD Resize (double aX, michael@0: double aY, michael@0: double aWidth, michael@0: double aHeight, michael@0: bool aRepaint); michael@0: virtual bool IsEnabled() const; michael@0: michael@0: michael@0: NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, michael@0: nsIWidget *aWidget, michael@0: bool aActivate); michael@0: void SetZIndex(int32_t aZIndex); michael@0: NS_IMETHOD SetSizeMode(int32_t aMode); michael@0: NS_IMETHOD Enable(bool aState); michael@0: NS_IMETHOD SetFocus(bool aRaise = false); michael@0: NS_IMETHOD GetScreenBounds(nsIntRect &aRect); michael@0: NS_IMETHOD GetClientBounds(nsIntRect &aRect); michael@0: virtual nsIntPoint GetClientOffset(); michael@0: NS_IMETHOD SetCursor(nsCursor aCursor); michael@0: NS_IMETHOD SetCursor(imgIContainer* aCursor, michael@0: uint32_t aHotspotX, uint32_t aHotspotY); michael@0: NS_IMETHOD Invalidate(const nsIntRect &aRect); michael@0: virtual void* GetNativeData(uint32_t aDataType); michael@0: NS_IMETHOD SetTitle(const nsAString& aTitle); michael@0: NS_IMETHOD SetIcon(const nsAString& aIconSpec); michael@0: NS_IMETHOD SetWindowClass(const nsAString& xulWinType); michael@0: virtual nsIntPoint WidgetToScreenOffset(); michael@0: NS_IMETHOD EnableDragDrop(bool aEnable); michael@0: NS_IMETHOD CaptureMouse(bool aCapture); michael@0: NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, michael@0: bool aDoCapture); michael@0: NS_IMETHOD GetAttention(int32_t aCycleCount); michael@0: michael@0: virtual bool HasPendingInputEvent(); michael@0: michael@0: NS_IMETHOD MakeFullScreen(bool aFullScreen); michael@0: NS_IMETHOD HideWindowChrome(bool aShouldHide); michael@0: michael@0: /** michael@0: * GetLastUserInputTime returns a timestamp for the most recent user input michael@0: * event. This is intended for pointer grab requests (including drags). michael@0: */ michael@0: static guint32 GetLastUserInputTime(); michael@0: michael@0: // utility method, -1 if no change should be made, otherwise returns a michael@0: // value that can be passed to gdk_window_set_decorations michael@0: gint ConvertBorderStyles(nsBorderStyle aStyle); michael@0: michael@0: // event callbacks michael@0: #if (MOZ_WIDGET_GTK == 2) michael@0: gboolean OnExposeEvent(GdkEventExpose *aEvent); michael@0: #else michael@0: gboolean OnExposeEvent(cairo_t *cr); michael@0: #endif michael@0: gboolean OnConfigureEvent(GtkWidget *aWidget, michael@0: GdkEventConfigure *aEvent); michael@0: void OnContainerUnrealize(); michael@0: void OnSizeAllocate(GtkAllocation *aAllocation); michael@0: void OnDeleteEvent(); michael@0: void OnEnterNotifyEvent(GdkEventCrossing *aEvent); michael@0: void OnLeaveNotifyEvent(GdkEventCrossing *aEvent); michael@0: void OnMotionNotifyEvent(GdkEventMotion *aEvent); michael@0: void OnButtonPressEvent(GdkEventButton *aEvent); michael@0: void OnButtonReleaseEvent(GdkEventButton *aEvent); michael@0: void OnContainerFocusInEvent(GdkEventFocus *aEvent); michael@0: void OnContainerFocusOutEvent(GdkEventFocus *aEvent); michael@0: gboolean OnKeyPressEvent(GdkEventKey *aEvent); michael@0: gboolean OnKeyReleaseEvent(GdkEventKey *aEvent); michael@0: void OnScrollEvent(GdkEventScroll *aEvent); michael@0: void OnVisibilityNotifyEvent(GdkEventVisibility *aEvent); michael@0: void OnWindowStateEvent(GtkWidget *aWidget, michael@0: GdkEventWindowState *aEvent); michael@0: void OnDragDataReceivedEvent(GtkWidget *aWidget, michael@0: GdkDragContext *aDragContext, michael@0: gint aX, michael@0: gint aY, michael@0: GtkSelectionData*aSelectionData, michael@0: guint aInfo, michael@0: guint aTime, michael@0: gpointer aData); michael@0: michael@0: mozilla::TemporaryRef StartRemoteDrawing() MOZ_OVERRIDE; michael@0: michael@0: private: michael@0: void UpdateAlpha(gfxPattern* aPattern, nsIntRect aBoundsRect); michael@0: michael@0: void NativeResize(int32_t aWidth, michael@0: int32_t aHeight, michael@0: bool aRepaint); michael@0: michael@0: void NativeResize(int32_t aX, michael@0: int32_t aY, michael@0: int32_t aWidth, michael@0: int32_t aHeight, michael@0: bool aRepaint); michael@0: michael@0: void NativeShow (bool aAction); michael@0: void SetHasMappedToplevel(bool aState); michael@0: nsIntSize GetSafeWindowSize(nsIntSize aSize); michael@0: michael@0: void EnsureGrabs (void); michael@0: void GrabPointer (guint32 aTime); michael@0: void ReleaseGrabs (void); michael@0: michael@0: public: michael@0: enum PluginType { michael@0: PluginType_NONE = 0, /* do not have any plugin */ michael@0: PluginType_XEMBED, /* the plugin support xembed */ michael@0: PluginType_NONXEMBED /* the plugin does not support xembed */ michael@0: }; michael@0: michael@0: void SetPluginType(PluginType aPluginType); michael@0: #ifdef MOZ_X11 michael@0: void SetNonXEmbedPluginFocus(void); michael@0: void LoseNonXEmbedPluginFocus(void); michael@0: #endif /* MOZ_X11 */ michael@0: michael@0: void ThemeChanged(void); michael@0: michael@0: #ifdef MOZ_X11 michael@0: Window mOldFocusWindow; michael@0: #endif /* MOZ_X11 */ michael@0: michael@0: static guint32 sLastButtonPressTime; michael@0: michael@0: NS_IMETHOD BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent, michael@0: int32_t aHorizontal, michael@0: int32_t aVertical); michael@0: NS_IMETHOD BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent); michael@0: michael@0: MozContainer* GetMozContainer() { return mContainer; } michael@0: // GetMozContainerWidget returns the MozContainer even for undestroyed michael@0: // descendant windows michael@0: GtkWidget* GetMozContainerWidget(); michael@0: GdkWindow* GetGdkWindow() { return mGdkWindow; } michael@0: bool IsDestroyed() { return mIsDestroyed; } michael@0: michael@0: void DispatchDragEvent(uint32_t aMsg, michael@0: const nsIntPoint& aRefPoint, michael@0: guint aTime); michael@0: static void UpdateDragStatus (GdkDragContext *aDragContext, michael@0: nsIDragService *aDragService); michael@0: // If this dispatched the keydown event actually, this returns TRUE, michael@0: // otherwise, FALSE. michael@0: bool DispatchKeyDownEvent(GdkEventKey *aEvent, michael@0: bool *aIsCancelled); michael@0: michael@0: NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE; michael@0: NS_IMETHOD_(void) SetInputContext(const InputContext& aContext, michael@0: const InputContextAction& aAction); michael@0: NS_IMETHOD_(InputContext) GetInputContext(); michael@0: NS_IMETHOD_(bool) ExecuteNativeKeyBinding( michael@0: NativeKeyBindingsType aType, michael@0: const mozilla::WidgetKeyboardEvent& aEvent, michael@0: DoCommandCallback aCallback, michael@0: void* aCallbackData) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState); michael@0: michael@0: // These methods are for toplevel windows only. michael@0: void ResizeTransparencyBitmap(); michael@0: void ApplyTransparencyBitmap(); michael@0: void ClearTransparencyBitmap(); michael@0: michael@0: virtual void SetTransparencyMode(nsTransparencyMode aMode); michael@0: virtual nsTransparencyMode GetTransparencyMode(); michael@0: virtual nsresult ConfigureChildren(const nsTArray& aConfigurations); michael@0: nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect, michael@0: uint8_t* aAlphas, int32_t aStride); michael@0: michael@0: #if (MOZ_WIDGET_GTK == 2) michael@0: gfxASurface *GetThebesSurface(); michael@0: michael@0: static already_AddRefed GetSurfaceForGdkDrawable(GdkDrawable* aDrawable, michael@0: const nsIntSize& aSize); michael@0: #else michael@0: gfxASurface *GetThebesSurface(cairo_t *cr); michael@0: #endif michael@0: NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); michael@0: michael@0: virtual nsresult SynthesizeNativeMouseEvent(nsIntPoint aPoint, michael@0: uint32_t aNativeMessage, michael@0: uint32_t aModifierFlags); michael@0: michael@0: virtual nsresult SynthesizeNativeMouseMove(nsIntPoint aPoint) michael@0: { return SynthesizeNativeMouseEvent(aPoint, GDK_MOTION_NOTIFY, 0); } michael@0: michael@0: protected: michael@0: // event handling code michael@0: void DispatchActivateEvent(void); michael@0: void DispatchDeactivateEvent(void); michael@0: void DispatchResized(int32_t aWidth, int32_t aHeight); michael@0: michael@0: // Helper for SetParent and ReparentNativeWidget. michael@0: void ReparentNativeWidgetInternal(nsIWidget* aNewParent, michael@0: GtkWidget* aNewContainer, michael@0: GdkWindow* aNewParentWindow, michael@0: GtkWidget* aOldContainer); michael@0: nsCOMPtr mParent; michael@0: // Is this a toplevel window? michael@0: bool mIsTopLevel; michael@0: // Has this widget been destroyed yet? michael@0: bool mIsDestroyed; michael@0: michael@0: // This is a flag that tracks if we need to resize a widget or michael@0: // window when we show it. michael@0: bool mNeedsResize; michael@0: // This is a flag that tracks if we need to move a widget or michael@0: // window when we show it. michael@0: bool mNeedsMove; michael@0: // Should we send resize events on all resizes? michael@0: bool mListenForResizes; michael@0: // This flag tracks if we're hidden or shown. michael@0: bool mIsShown; michael@0: bool mNeedsShow; michael@0: // is this widget enabled? michael@0: bool mEnabled; michael@0: // has the native window for this been created yet? michael@0: bool mCreated; michael@0: michael@0: private: michael@0: void DestroyChildWindows(); michael@0: GtkWidget *GetToplevelWidget(); michael@0: nsWindow *GetContainerWindow(); michael@0: void SetUrgencyHint(GtkWidget *top_window, bool state); michael@0: void *SetupPluginPort(void); michael@0: void SetDefaultIcon(void); michael@0: void InitButtonEvent(mozilla::WidgetMouseEvent& aEvent, michael@0: GdkEventButton* aGdkEvent); michael@0: bool DispatchCommandEvent(nsIAtom* aCommand); michael@0: bool DispatchContentCommandEvent(int32_t aMsg); michael@0: void SetWindowClipRegion(const nsTArray& aRects, michael@0: bool aIntersectWithExisting); michael@0: bool CheckForRollup(gdouble aMouseX, gdouble aMouseY, michael@0: bool aIsWheel, bool aAlwaysRollup); michael@0: bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent, michael@0: GdkWindow** aWindow, gint* aButton, michael@0: gint* aRootX, gint* aRootY); michael@0: void ClearCachedResources(); michael@0: michael@0: GtkWidget *mShell; michael@0: MozContainer *mContainer; michael@0: GdkWindow *mGdkWindow; michael@0: michael@0: uint32_t mHasMappedToplevel : 1, michael@0: mIsFullyObscured : 1, michael@0: mRetryPointerGrab : 1; michael@0: nsSizeMode mSizeState; michael@0: PluginType mPluginType; michael@0: michael@0: int32_t mTransparencyBitmapWidth; michael@0: int32_t mTransparencyBitmapHeight; michael@0: michael@0: #ifdef MOZ_HAVE_SHMIMAGE michael@0: // If we're using xshm rendering, mThebesSurface wraps mShmImage michael@0: nsRefPtr mShmImage; michael@0: #endif michael@0: nsRefPtr mThebesSurface; michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: nsRefPtr mRootAccessible; michael@0: michael@0: /** michael@0: * Request to create the accessible for this window if it is top level. michael@0: */ michael@0: void CreateRootAccessible(); michael@0: michael@0: /** michael@0: * Dispatch accessible event for the top level window accessible. michael@0: * michael@0: * @param aEventType [in] the accessible event type to dispatch michael@0: */ michael@0: void DispatchEventToRootAccessible(uint32_t aEventType); michael@0: michael@0: /** michael@0: * Dispatch accessible window activate event for the top level window michael@0: * accessible. michael@0: */ michael@0: void DispatchActivateEventAccessible(); michael@0: michael@0: /** michael@0: * Dispatch accessible window deactivate event for the top level window michael@0: * accessible. michael@0: */ michael@0: void DispatchDeactivateEventAccessible(); michael@0: michael@0: /** michael@0: * Dispatch accessible window maximize event for the top level window michael@0: * accessible. michael@0: */ michael@0: void DispatchMaximizeEventAccessible(); michael@0: michael@0: /** michael@0: * Dispatch accessible window minize event for the top level window michael@0: * accessible. michael@0: */ michael@0: void DispatchMinimizeEventAccessible(); michael@0: michael@0: /** michael@0: * Dispatch accessible window restore event for the top level window michael@0: * accessible. michael@0: */ michael@0: void DispatchRestoreEventAccessible(); michael@0: #endif michael@0: michael@0: // The cursor cache michael@0: static GdkCursor *gsGtkCursorCache[eCursorCount]; michael@0: michael@0: // Transparency michael@0: bool mIsTransparent; michael@0: // This bitmap tracks which pixels are transparent. We don't support michael@0: // full translucency at this time; each pixel is either fully opaque michael@0: // or fully transparent. michael@0: gchar* mTransparencyBitmap; michael@0: michael@0: // all of our DND stuff michael@0: void InitDragEvent(mozilla::WidgetDragEvent& aEvent); michael@0: michael@0: float mLastMotionPressure; michael@0: michael@0: // Remember the last sizemode so that we can restore it when michael@0: // leaving fullscreen michael@0: nsSizeMode mLastSizeMode; michael@0: michael@0: static bool DragInProgress(void); michael@0: michael@0: void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent); michael@0: michael@0: // nsBaseWidget michael@0: virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, michael@0: LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, michael@0: LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, michael@0: bool* aAllowRetaining = nullptr) MOZ_OVERRIDE; michael@0: michael@0: void CleanLayerManagerRecursive(); michael@0: michael@0: /** michael@0: * |mIMModule| takes all IME related stuff. michael@0: * michael@0: * This is owned by the top-level nsWindow or the topmost child michael@0: * nsWindow embedded in a non-Gecko widget. michael@0: * michael@0: * The instance is created when the top level widget is created. And when michael@0: * the widget is destroyed, it's released. All child windows refer its michael@0: * ancestor widget's instance. So, one set of IM contexts is created for michael@0: * all windows in a hierarchy. If the children are released after the top michael@0: * level window is released, the children still have a valid pointer, michael@0: * however, IME doesn't work at that time. michael@0: */ michael@0: nsRefPtr mIMModule; michael@0: }; michael@0: michael@0: class nsChildWindow : public nsWindow { michael@0: public: michael@0: nsChildWindow(); michael@0: ~nsChildWindow(); michael@0: }; michael@0: michael@0: #endif /* __nsWindow_h__ */