/* -*- 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"mozilla/ipc/SharedMemorySysV.h"#include"nsAutoPtr.h"#include"mozcontainer.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 */#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"externPRLogModuleInfo*gWidgetLog;externPRLogModuleInfo*gWidgetFocusLog;externPRLogModuleInfo*gWidgetDragLog;externPRLogModuleInfo*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 */classgfxASurface;classgfxPattern;classnsPluginNativeWindowGtk;#if defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV)# define MOZ_HAVE_SHMIMAGEclassnsShmImage;#endifnamespacemozilla{classTimeStamp;classCurrentX11TimeGetter;}classnsWindow:publicnsBaseWidget{public:nsWindow();staticvoidReleaseGlobals();NS_DECL_ISUPPORTS_INHERITEDvoidCommonCreate(nsIWidget*aParent,boolaListenForResizes);virtualnsresultDispatchEvent(mozilla::WidgetGUIEvent*aEvent,nsEventStatus&aStatus)override;// called when we are destroyedvirtualvoidOnDestroy(void)override;// called to check and see if a widget's dimensions are saneboolAreBoundsSane(void);// nsIWidgetNS_IMETHODCreate(nsIWidget*aParent,nsNativeWidgetaNativeParent,constLayoutDeviceIntRect&aRect,nsWidgetInitData*aInitData)override;NS_IMETHODDestroy(void)override;virtualnsIWidget*GetParent()override;virtualfloatGetDPI()override;virtualdoubleGetDefaultScaleInternal()override;virtualnsresultSetParent(nsIWidget*aNewParent)override;NS_IMETHODSetModal(boolaModal)override;virtualboolIsVisible()constoverride;NS_IMETHODConstrainPosition(boolaAllowSlop,int32_t*aX,int32_t*aY)override;virtualvoidSetSizeConstraints(constSizeConstraints&aConstraints)override;NS_IMETHODMove(doubleaX,doubleaY)override;NS_IMETHODShow(boolaState)override;NS_IMETHODResize(doubleaWidth,doubleaHeight,boolaRepaint)override;NS_IMETHODResize(doubleaX,doubleaY,doubleaWidth,doubleaHeight,boolaRepaint)override;virtualboolIsEnabled()constoverride;NS_IMETHODPlaceBehind(nsTopLevelWidgetZPlacementaPlacement,nsIWidget*aWidget,boolaActivate)override;voidSetZIndex(int32_taZIndex)override;NS_IMETHODSetSizeMode(nsSizeModeaMode)override;NS_IMETHODEnable(boolaState)override;NS_IMETHODSetFocus(boolaRaise=false)override;NS_IMETHODGetScreenBounds(LayoutDeviceIntRect&aRect)override;NS_IMETHODGetClientBounds(LayoutDeviceIntRect&aRect)override;virtualLayoutDeviceIntSizeGetClientSize()override;virtualLayoutDeviceIntPointGetClientOffset()override;NS_IMETHODSetCursor(nsCursoraCursor)override;NS_IMETHODSetCursor(imgIContainer*aCursor,uint32_taHotspotX,uint32_taHotspotY)override;NS_IMETHODInvalidate(constLayoutDeviceIntRect&aRect)override;virtualvoid*GetNativeData(uint32_taDataType)override;voidSetNativeData(uint32_taDataType,uintptr_taVal)override;NS_IMETHODSetTitle(constnsAString&aTitle)override;NS_IMETHODSetIcon(constnsAString&aIconSpec)override;NS_IMETHODSetWindowClass(constnsAString&xulWinType)override;virtualLayoutDeviceIntPointWidgetToScreenOffset()override;NS_IMETHODEnableDragDrop(boolaEnable)override;NS_IMETHODCaptureMouse(boolaCapture)override;NS_IMETHODCaptureRollupEvents(nsIRollupListener*aListener,boolaDoCapture)override;NS_IMETHODGetAttention(int32_taCycleCount)override;virtualnsresultSetWindowClipRegion(constnsTArray<nsIntRect>&aRects,boolaIntersectWithExisting)override;virtualboolHasPendingInputEvent()override;virtualboolPrepareForFullscreenTransition(nsISupports**aData)override;virtualvoidPerformFullscreenTransition(FullscreenTransitionStageaStage,uint16_taDuration,nsISupports*aData,nsIRunnable*aCallback)override;NS_IMETHODMakeFullScreen(boolaFullScreen,nsIScreen*aTargetScreen=nullptr)override;NS_IMETHODHideWindowChrome(boolaShouldHide)override;/** * GetLastUserInputTime returns a timestamp for the most recent user input * event. This is intended for pointer grab requests (including drags). */staticguint32GetLastUserInputTime();// utility method, -1 if no change should be made, otherwise returns a// value that can be passed to gdk_window_set_decorationsgintConvertBorderStyles(nsBorderStyleaStyle);GdkRectangleDevicePixelsToGdkRectRoundOut(LayoutDeviceIntRectaRect);// event callbacks#if (MOZ_WIDGET_GTK == 2)gbooleanOnExposeEvent(GdkEventExpose*aEvent);#elsegbooleanOnExposeEvent(cairo_t*cr);#endifgbooleanOnConfigureEvent(GtkWidget*aWidget,GdkEventConfigure*aEvent);voidOnContainerUnrealize();voidOnSizeAllocate(GtkAllocation*aAllocation);voidOnDeleteEvent();voidOnEnterNotifyEvent(GdkEventCrossing*aEvent);voidOnLeaveNotifyEvent(GdkEventCrossing*aEvent);voidOnMotionNotifyEvent(GdkEventMotion*aEvent);voidOnButtonPressEvent(GdkEventButton*aEvent);voidOnButtonReleaseEvent(GdkEventButton*aEvent);voidOnContainerFocusInEvent(GdkEventFocus*aEvent);voidOnContainerFocusOutEvent(GdkEventFocus*aEvent);gbooleanOnKeyPressEvent(GdkEventKey*aEvent);gbooleanOnKeyReleaseEvent(GdkEventKey*aEvent);voidOnScrollEvent(GdkEventScroll*aEvent);voidOnVisibilityNotifyEvent(GdkEventVisibility*aEvent);voidOnWindowStateEvent(GtkWidget*aWidget,GdkEventWindowState*aEvent);voidOnDragDataReceivedEvent(GtkWidget*aWidget,GdkDragContext*aDragContext,gintaX,gintaY,GtkSelectionData*aSelectionData,guintaInfo,guintaTime,gpointeraData);gbooleanOnPropertyNotifyEvent(GtkWidget*aWidget,GdkEventProperty*aEvent);#if GTK_CHECK_VERSION(3,4,0)gbooleanOnTouchEvent(GdkEventTouch*aEvent);#endifvirtualalready_AddRefed<mozilla::gfx::DrawTarget>StartRemoteDrawingInRegion(nsIntRegion&aInvalidRegion)override;virtualvoidEndRemoteDrawingInRegion(mozilla::gfx::DrawTarget*aDrawTarget,nsIntRegion&aInvalidRegion)override;private:voidUpdateAlpha(mozilla::gfx::SourceSurface*aSourceSurface,nsIntRectaBoundsRect);voidNativeMove();voidNativeResize();voidNativeMoveResize();voidNativeShow(boolaAction);voidSetHasMappedToplevel(boolaState);LayoutDeviceIntSizeGetSafeWindowSize(LayoutDeviceIntSizeaSize);voidEnsureGrabs(void);voidGrabPointer(guint32aTime);voidReleaseGrabs(void);voidUpdateClientOffset();public:enumPluginType{PluginType_NONE=0,/* do not have any plugin */PluginType_XEMBED,/* the plugin support xembed */PluginType_NONXEMBED/* the plugin does not support xembed */};voidSetPluginType(PluginTypeaPluginType);#ifdef MOZ_X11voidSetNonXEmbedPluginFocus(void);voidLoseNonXEmbedPluginFocus(void);#endif /* MOZ_X11 */voidThemeChanged(void);#ifdef MOZ_X11WindowmOldFocusWindow;#endif /* MOZ_X11 */staticguint32sLastButtonPressTime;NS_IMETHODBeginResizeDrag(mozilla::WidgetGUIEvent*aEvent,int32_taHorizontal,int32_taVertical)override;NS_IMETHODBeginMoveDrag(mozilla::WidgetMouseEvent*aEvent)override;MozContainer*GetMozContainer(){returnmContainer;}// GetMozContainerWidget returns the MozContainer even for undestroyed// descendant windowsGtkWidget*GetMozContainerWidget();GdkWindow*GetGdkWindow(){returnmGdkWindow;}boolIsDestroyed(){returnmIsDestroyed;}voidDispatchDragEvent(mozilla::EventMessageaMsg,constLayoutDeviceIntPoint&aRefPoint,guintaTime);staticvoidUpdateDragStatus(GdkDragContext*aDragContext,nsIDragService*aDragService);// If this dispatched the keydown event actually, this returns TRUE,// otherwise, FALSE.boolDispatchKeyDownEvent(GdkEventKey*aEvent,bool*aIsCancelled);mozilla::TimeStampGetEventTimeStamp(guint32aEventTime);mozilla::CurrentX11TimeGetter*GetCurrentTimeGetter();NS_IMETHOD_(void)SetInputContext(constInputContext&aContext,constInputContextAction&aAction)override;NS_IMETHOD_(InputContext)GetInputContext()override;virtualnsIMEUpdatePreferenceGetIMEUpdatePreference()override;boolExecuteNativeKeyBindingRemapped(NativeKeyBindingsTypeaType,constmozilla::WidgetKeyboardEvent&aEvent,DoCommandCallbackaCallback,void*aCallbackData,uint32_taGeckoKeyCode,uint32_taNativeKeyCode);NS_IMETHOD_(bool)ExecuteNativeKeyBinding(NativeKeyBindingsTypeaType,constmozilla::WidgetKeyboardEvent&aEvent,DoCommandCallbackaCallback,void*aCallbackData)override;// These methods are for toplevel windows only.voidResizeTransparencyBitmap();voidApplyTransparencyBitmap();voidClearTransparencyBitmap();virtualvoidSetTransparencyMode(nsTransparencyModeaMode)override;virtualnsTransparencyModeGetTransparencyMode()override;virtualnsresultConfigureChildren(constnsTArray<Configuration>&aConfigurations)override;nsresultUpdateTranslucentWindowAlphaInternal(constnsIntRect&aRect,uint8_t*aAlphas,int32_taStride);virtualalready_AddRefed<mozilla::gfx::DrawTarget>GetDrawTarget(constnsIntRegion&aRegion);#if (MOZ_WIDGET_GTK == 2)staticalready_AddRefed<gfxASurface>GetSurfaceForGdkDrawable(GdkDrawable*aDrawable,constnsIntSize&aSize);#endifNS_IMETHODReparentNativeWidget(nsIWidget*aNewParent)override;virtualnsresultSynthesizeNativeMouseEvent(LayoutDeviceIntPointaPoint,uint32_taNativeMessage,uint32_taModifierFlags,nsIObserver*aObserver)override;virtualnsresultSynthesizeNativeMouseMove(LayoutDeviceIntPointaPoint,nsIObserver*aObserver)override{returnSynthesizeNativeMouseEvent(aPoint,GDK_MOTION_NOTIFY,0,aObserver);}virtualnsresultSynthesizeNativeMouseScrollEvent(LayoutDeviceIntPointaPoint,uint32_taNativeMessage,doubleaDeltaX,doubleaDeltaY,doubleaDeltaZ,uint32_taModifierFlags,uint32_taAdditionalFlags,nsIObserver*aObserver)override;// HiDPI scale conversiongintGdkScaleFactor();// To GDKgintDevicePixelsToGdkCoordRoundUp(intpixels);gintDevicePixelsToGdkCoordRoundDown(intpixels);GdkPointDevicePixelsToGdkPointRoundDown(nsIntPointpoint);GdkRectangleDevicePixelsToGdkSizeRoundUp(nsIntSizepixelSize);// From GDKintGdkCoordToDevicePixels(gintcoord);LayoutDeviceIntPointGdkPointToDevicePixels(GdkPointpoint);LayoutDeviceIntPointGdkEventCoordsToDevicePixels(gdoublex,gdoubley);nsIntRectGdkRectToDevicePixels(GdkRectanglerect);protected:virtual~nsWindow();// event handling codevoidDispatchActivateEvent(void);voidDispatchDeactivateEvent(void);voidDispatchResized();voidMaybeDispatchResized();// Helper for SetParent and ReparentNativeWidget.voidReparentNativeWidgetInternal(nsIWidget*aNewParent,GtkWidget*aNewContainer,GdkWindow*aNewParentWindow,GtkWidget*aOldContainer);virtualnsresultNotifyIMEInternal(constIMENotification&aIMENotification)override;virtualvoidRegisterTouchWindow()override;nsCOMPtr<nsIWidget>mParent;// Is this a toplevel window?boolmIsTopLevel;// Has this widget been destroyed yet?boolmIsDestroyed;// Should we send resize events on all resizes?boolmListenForResizes;// Does WindowResized need to be called on listeners?boolmNeedsDispatchResized;// This flag tracks if we're hidden or shown.boolmIsShown;boolmNeedsShow;// is this widget enabled?boolmEnabled;// has the native window for this been created yet?boolmCreated;#if GTK_CHECK_VERSION(3,4,0)// whether we handle touch eventboolmHandleTouchEvent;#endif// true if this is a drag and drop feedback popupboolmIsDragPopup;private:voidDestroyChildWindows();GtkWidget*GetToplevelWidget();nsWindow*GetContainerWindow();voidSetUrgencyHint(GtkWidget*top_window,boolstate);void*SetupPluginPort(void);voidSetDefaultIcon(void);voidInitButtonEvent(mozilla::WidgetMouseEvent&aEvent,GdkEventButton*aGdkEvent);boolDispatchCommandEvent(nsIAtom*aCommand);boolDispatchContentCommandEvent(mozilla::EventMessageaMsg);boolCheckForRollup(gdoubleaMouseX,gdoubleaMouseY,boolaIsWheel,boolaAlwaysRollup);boolGetDragInfo(mozilla::WidgetMouseEvent*aMouseEvent,GdkWindow**aWindow,gint*aButton,gint*aRootX,gint*aRootY);voidClearCachedResources();GtkWidget*mShell;MozContainer*mContainer;GdkWindow*mGdkWindow;uint32_tmHasMappedToplevel:1,mIsFullyObscured:1,mRetryPointerGrab:1;nsSizeModemSizeState;PluginTypemPluginType;int32_tmTransparencyBitmapWidth;int32_tmTransparencyBitmapHeight;nsIntPointmClientOffset;#if GTK_CHECK_VERSION(3,4,0)// This field omits duplicate scroll events caused by GNOME bug 726878.guint32mLastScrollEventTime;// for touch event handlingnsRefPtrHashtable<nsPtrHashKey<GdkEventSequence>,mozilla::dom::Touch>mTouches;#endif#ifdef MOZ_X11Display*mXDisplay;DrawablemXWindow;Visual*mXVisual;intmXDepth;#endif#ifdef MOZ_HAVE_SHMIMAGE// If we're using xshm renderingRefPtr<nsShmImage>mShmImage;#endif#ifdef ACCESSIBILITYRefPtr<mozilla::a11y::Accessible>mRootAccessible;/** * Request to create the accessible for this window if it is top level. */voidCreateRootAccessible();/** * Dispatch accessible event for the top level window accessible. * * @param aEventType [in] the accessible event type to dispatch */voidDispatchEventToRootAccessible(uint32_taEventType);/** * Dispatch accessible window activate event for the top level window * accessible. */voidDispatchActivateEventAccessible();/** * Dispatch accessible window deactivate event for the top level window * accessible. */voidDispatchDeactivateEventAccessible();/** * Dispatch accessible window maximize event for the top level window * accessible. */voidDispatchMaximizeEventAccessible();/** * Dispatch accessible window minize event for the top level window * accessible. */voidDispatchMinimizeEventAccessible();/** * Dispatch accessible window restore event for the top level window * accessible. */voidDispatchRestoreEventAccessible();#endif// Updates the bounds of the socket widget we manage for remote plugins.voidResizePluginSocketWidget();// e10s specific - for managing the socket widget this window hosts.nsPluginNativeWindowGtk*mPluginNativeWindow;// The cursor cachestaticGdkCursor*gsGtkCursorCache[eCursorCount];// TransparencyboolmIsTransparent;// 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 stuffvoidInitDragEvent(mozilla::WidgetDragEvent&aEvent);floatmLastMotionPressure;// Remember the last sizemode so that we can restore it when// leaving fullscreennsSizeModemLastSizeMode;staticboolDragInProgress(void);voidDispatchMissedButtonReleases(GdkEventCrossing*aGdkEvent);// nsBaseWidgetvirtualLayerManager*GetLayerManager(PLayerTransactionChild*aShadowManager=nullptr,LayersBackendaBackendHint=mozilla::layers::LayersBackend::LAYERS_NONE,LayerManagerPersistenceaPersistence=LAYER_MANAGER_CURRENT,bool*aAllowRetaining=nullptr)override;voidCleanLayerManagerRecursive();virtualint32_tRoundsWidgetCoordinatesTo()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;nsAutoPtr<mozilla::CurrentX11TimeGetter>mCurrentTimeGetter;};classnsChildWindow:publicnsWindow{public:nsChildWindow();~nsChildWindow();};#endif /* __nsWindow_h__ */