mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
468 lines
19 KiB
C++
468 lines
19 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* 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 nsBaseWidget_h__
|
|
#define nsBaseWidget_h__
|
|
|
|
#include "mozilla/EventForwards.h"
|
|
#include "mozilla/WidgetUtils.h"
|
|
#include "nsRect.h"
|
|
#include "nsIWidget.h"
|
|
#include "nsWidgetsCID.h"
|
|
#include "nsIFile.h"
|
|
#include "nsString.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsIRollupListener.h"
|
|
#include "nsIObserver.h"
|
|
#include "nsIWidgetListener.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include <algorithm>
|
|
class nsIContent;
|
|
class nsAutoRollup;
|
|
class gfxContext;
|
|
|
|
namespace mozilla {
|
|
#ifdef ACCESSIBILITY
|
|
namespace a11y {
|
|
class Accessible;
|
|
}
|
|
#endif
|
|
|
|
namespace layers {
|
|
class BasicLayerManager;
|
|
class CompositorChild;
|
|
class CompositorParent;
|
|
}
|
|
}
|
|
|
|
namespace base {
|
|
class Thread;
|
|
}
|
|
|
|
class nsBaseWidget;
|
|
|
|
class WidgetShutdownObserver MOZ_FINAL : public nsIObserver
|
|
{
|
|
public:
|
|
WidgetShutdownObserver(nsBaseWidget* aWidget)
|
|
: mWidget(aWidget)
|
|
{ }
|
|
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
nsBaseWidget *mWidget;
|
|
};
|
|
|
|
/**
|
|
* Common widget implementation used as base class for native
|
|
* or crossplatform implementations of Widgets.
|
|
* All cross-platform behavior that all widgets need to implement
|
|
* should be placed in this class.
|
|
* (Note: widget implementations are not required to use this
|
|
* class, but it gives them a head start.)
|
|
*/
|
|
|
|
class nsBaseWidget : public nsIWidget
|
|
{
|
|
friend class nsAutoRollup;
|
|
|
|
protected:
|
|
typedef base::Thread Thread;
|
|
typedef mozilla::layers::BasicLayerManager BasicLayerManager;
|
|
typedef mozilla::layers::BufferMode BufferMode;
|
|
typedef mozilla::layers::CompositorChild CompositorChild;
|
|
typedef mozilla::layers::CompositorParent CompositorParent;
|
|
typedef mozilla::ScreenRotation ScreenRotation;
|
|
|
|
public:
|
|
nsBaseWidget();
|
|
virtual ~nsBaseWidget();
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
// nsIWidget interface
|
|
NS_IMETHOD CaptureMouse(bool aCapture);
|
|
virtual nsIWidgetListener* GetWidgetListener();
|
|
virtual void SetWidgetListener(nsIWidgetListener* alistener);
|
|
NS_IMETHOD Destroy();
|
|
NS_IMETHOD SetParent(nsIWidget* aNewParent);
|
|
virtual nsIWidget* GetParent(void);
|
|
virtual nsIWidget* GetTopLevelWidget();
|
|
virtual nsIWidget* GetSheetWindowParent(void);
|
|
virtual float GetDPI();
|
|
virtual void AddChild(nsIWidget* aChild);
|
|
virtual void RemoveChild(nsIWidget* aChild);
|
|
|
|
NS_IMETHOD SetZIndex(int32_t aZIndex);
|
|
NS_IMETHOD GetZIndex(int32_t* aZIndex);
|
|
NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
|
|
nsIWidget *aWidget, bool aActivate);
|
|
|
|
NS_IMETHOD SetSizeMode(int32_t aMode);
|
|
virtual int32_t SizeMode() MOZ_OVERRIDE
|
|
{
|
|
return mSizeMode;
|
|
}
|
|
|
|
virtual nscolor GetForegroundColor(void);
|
|
NS_IMETHOD SetForegroundColor(const nscolor &aColor);
|
|
virtual nscolor GetBackgroundColor(void);
|
|
NS_IMETHOD SetBackgroundColor(const nscolor &aColor);
|
|
virtual nsCursor GetCursor();
|
|
NS_IMETHOD SetCursor(nsCursor aCursor);
|
|
NS_IMETHOD SetCursor(imgIContainer* aCursor,
|
|
uint32_t aHotspotX, uint32_t aHotspotY);
|
|
NS_IMETHOD GetWindowType(nsWindowType& aWindowType);
|
|
virtual void SetTransparencyMode(nsTransparencyMode aMode);
|
|
virtual nsTransparencyMode GetTransparencyMode();
|
|
virtual void GetWindowClipRegion(nsTArray<nsIntRect>* aRects);
|
|
NS_IMETHOD SetWindowShadowStyle(int32_t aStyle);
|
|
virtual void SetShowsToolbarButton(bool aShow) {}
|
|
virtual void SetShowsFullScreenButton(bool aShow) {}
|
|
virtual void SetWindowAnimationType(WindowAnimationType aType) {}
|
|
NS_IMETHOD HideWindowChrome(bool aShouldHide);
|
|
NS_IMETHOD MakeFullScreen(bool aFullScreen);
|
|
virtual nsDeviceContext* GetDeviceContext();
|
|
virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
|
|
LayersBackend aBackendHint = mozilla::layers::LAYERS_NONE,
|
|
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
|
|
bool* aAllowRetaining = nullptr);
|
|
|
|
virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight);
|
|
virtual void CreateCompositor();
|
|
virtual void CreateCompositor(int aWidth, int aHeight);
|
|
virtual void PrepareWindowEffects() {}
|
|
virtual void CleanupWindowEffects() {}
|
|
virtual bool PreRender(LayerManager* aManager) { return true; }
|
|
virtual void PostRender(LayerManager* aManager) {}
|
|
virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {}
|
|
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {}
|
|
virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing();
|
|
virtual void EndRemoteDrawing() { };
|
|
virtual void CleanupRemoteDrawing() { };
|
|
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
|
|
virtual gfxASurface* GetThebesSurface();
|
|
NS_IMETHOD SetModal(bool aModal);
|
|
NS_IMETHOD SetWindowClass(const nsAString& xulWinType);
|
|
// Return whether this widget interprets parameters to Move and Resize APIs
|
|
// as "global display pixels" rather than "device pixels", and therefore
|
|
// applies its GetDefaultScale() value to them before using them as mBounds
|
|
// etc (which are always stored in device pixels).
|
|
// Note that APIs that -get- the widget's position/size/bounds, rather than
|
|
// -setting- them (i.e. moving or resizing the widget) will always return
|
|
// values in the widget's device pixels.
|
|
bool BoundsUseDisplayPixels() const {
|
|
return mWindowType <= eWindowType_popup;
|
|
}
|
|
NS_IMETHOD MoveClient(double aX, double aY);
|
|
NS_IMETHOD ResizeClient(double aWidth, double aHeight, bool aRepaint);
|
|
NS_IMETHOD ResizeClient(double aX, double aY, double aWidth, double aHeight, bool aRepaint);
|
|
NS_IMETHOD GetBounds(nsIntRect &aRect);
|
|
NS_IMETHOD GetClientBounds(nsIntRect &aRect);
|
|
NS_IMETHOD GetScreenBounds(nsIntRect &aRect);
|
|
NS_IMETHOD GetNonClientMargins(nsIntMargin &margins);
|
|
NS_IMETHOD SetNonClientMargins(nsIntMargin &margins);
|
|
virtual nsIntPoint GetClientOffset();
|
|
NS_IMETHOD EnableDragDrop(bool aEnable);
|
|
NS_IMETHOD GetAttention(int32_t aCycleCount);
|
|
virtual bool HasPendingInputEvent();
|
|
NS_IMETHOD SetIcon(const nsAString &anIconSpec);
|
|
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor, bool aActive);
|
|
virtual void SetDrawsInTitlebar(bool aState) {}
|
|
virtual bool ShowsResizeIndicator(nsIntRect* aResizerRect);
|
|
virtual void FreeNativeData(void * data, uint32_t aDataType) {}
|
|
NS_IMETHOD BeginResizeDrag(mozilla::WidgetGUIEvent* aEvent,
|
|
int32_t aHorizontal,
|
|
int32_t aVertical);
|
|
NS_IMETHOD BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent);
|
|
virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
|
|
virtual nsresult ForceUpdateNativeMenuAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
|
|
NS_IMETHOD NotifyIME(NotificationToIME aNotification) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
|
|
NS_IMETHOD SetLayersAcceleration(bool aEnabled);
|
|
virtual bool GetLayersAcceleration() { return mUseLayersAcceleration; }
|
|
virtual bool ComputeShouldAccelerate(bool aDefault);
|
|
NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState) { return NS_ERROR_NOT_IMPLEMENTED; }
|
|
NS_IMETHOD NotifyIMEOfTextChange(uint32_t aStart, uint32_t aOldEnd, uint32_t aNewEnd) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
|
|
virtual nsIMEUpdatePreference GetIMEUpdatePreference() MOZ_OVERRIDE { return nsIMEUpdatePreference(); }
|
|
NS_IMETHOD OnDefaultButtonLoaded(const nsIntRect &aButtonRect) { return NS_ERROR_NOT_IMPLEMENTED; }
|
|
NS_IMETHOD OverrideSystemMouseScrollSpeed(double aOriginalDeltaX,
|
|
double aOriginalDeltaY,
|
|
double& aOverriddenDeltaX,
|
|
double& aOverriddenDeltaY);
|
|
virtual already_AddRefed<nsIWidget>
|
|
CreateChild(const nsIntRect &aRect,
|
|
nsDeviceContext *aContext,
|
|
nsWidgetInitData *aInitData = nullptr,
|
|
bool aForceUseIWidgetParent = false);
|
|
NS_IMETHOD AttachViewToTopLevel(bool aUseAttachedEvents, nsDeviceContext *aContext);
|
|
virtual nsIWidgetListener* GetAttachedWidgetListener();
|
|
virtual void SetAttachedWidgetListener(nsIWidgetListener* aListener);
|
|
NS_IMETHOD RegisterTouchWindow();
|
|
NS_IMETHOD UnregisterTouchWindow();
|
|
|
|
void NotifyWindowDestroyed();
|
|
void NotifySizeMoveDone();
|
|
|
|
// Should be called by derived implementations to notify on system color and
|
|
// theme changes.
|
|
void NotifySysColorChanged();
|
|
void NotifyThemeChanged();
|
|
void NotifyUIStateChanged(UIStateChangeType aShowAccelerators,
|
|
UIStateChangeType aShowFocusRings);
|
|
|
|
#ifdef ACCESSIBILITY
|
|
// Get the accessible for the window.
|
|
mozilla::a11y::Accessible* GetRootAccessible();
|
|
#endif
|
|
|
|
nsPopupLevel PopupLevel() { return mPopupLevel; }
|
|
|
|
virtual nsIntSize ClientToWindowSize(const nsIntSize& aClientSize)
|
|
{
|
|
return aClientSize;
|
|
}
|
|
|
|
// return true if this is a popup widget with a native titlebar
|
|
bool IsPopupWithTitleBar() const
|
|
{
|
|
return (mWindowType == eWindowType_popup &&
|
|
mBorderStyle != eBorderStyle_default &&
|
|
mBorderStyle & eBorderStyle_title);
|
|
}
|
|
|
|
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) = 0;
|
|
|
|
virtual uint32_t GetGLFrameBufferFormat() MOZ_OVERRIDE;
|
|
|
|
virtual const SizeConstraints& GetSizeConstraints() const;
|
|
virtual void SetSizeConstraints(const SizeConstraints& aConstraints);
|
|
|
|
/**
|
|
* Use this when GetLayerManager() returns a BasicLayerManager
|
|
* (nsBaseWidget::GetLayerManager() does). This sets up the widget's
|
|
* layer manager to temporarily render into aTarget.
|
|
*
|
|
* |aNaturalWidgetBounds| is the un-rotated bounds of |aWidget|.
|
|
* |aRotation| is the "virtual rotation" to apply when rendering to
|
|
* the target. When |aRotation| is ROTATION_0,
|
|
* |aNaturalWidgetBounds| is not used.
|
|
*/
|
|
class AutoLayerManagerSetup {
|
|
public:
|
|
AutoLayerManagerSetup(nsBaseWidget* aWidget, gfxContext* aTarget,
|
|
BufferMode aDoubleBuffering,
|
|
ScreenRotation aRotation = mozilla::ROTATION_0);
|
|
~AutoLayerManagerSetup();
|
|
private:
|
|
nsBaseWidget* mWidget;
|
|
nsRefPtr<BasicLayerManager> mLayerManager;
|
|
};
|
|
friend class AutoLayerManagerSetup;
|
|
|
|
class AutoUseBasicLayerManager {
|
|
public:
|
|
AutoUseBasicLayerManager(nsBaseWidget* aWidget);
|
|
~AutoUseBasicLayerManager();
|
|
private:
|
|
nsBaseWidget* mWidget;
|
|
bool mPreviousTemporarilyUseBasicLayerManager;
|
|
};
|
|
friend class AutoUseBasicLayerManager;
|
|
|
|
nsWindowType GetWindowType() { return mWindowType; }
|
|
|
|
virtual bool ShouldUseOffMainThreadCompositing();
|
|
|
|
static nsIRollupListener* GetActiveRollupListener();
|
|
|
|
void Shutdown();
|
|
|
|
protected:
|
|
|
|
virtual void ResolveIconName(const nsAString &aIconName,
|
|
const nsAString &aIconSuffix,
|
|
nsIFile **aResult);
|
|
virtual void OnDestroy();
|
|
virtual void BaseCreate(nsIWidget *aParent,
|
|
const nsIntRect &aRect,
|
|
nsDeviceContext *aContext,
|
|
nsWidgetInitData *aInitData);
|
|
|
|
virtual nsIContent* GetLastRollup()
|
|
{
|
|
return mLastRollup;
|
|
}
|
|
|
|
virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
|
|
int32_t aNativeKeyCode,
|
|
uint32_t aModifierFlags,
|
|
const nsAString& aCharacters,
|
|
const nsAString& aUnmodifiedCharacters)
|
|
{ return NS_ERROR_UNEXPECTED; }
|
|
|
|
virtual nsresult SynthesizeNativeMouseEvent(nsIntPoint aPoint,
|
|
uint32_t aNativeMessage,
|
|
uint32_t aModifierFlags)
|
|
{ return NS_ERROR_UNEXPECTED; }
|
|
|
|
virtual nsresult SynthesizeNativeMouseMove(nsIntPoint aPoint)
|
|
{ return NS_ERROR_UNEXPECTED; }
|
|
|
|
virtual nsresult SynthesizeNativeMouseScrollEvent(nsIntPoint aPoint,
|
|
uint32_t aNativeMessage,
|
|
double aDeltaX,
|
|
double aDeltaY,
|
|
double aDeltaZ,
|
|
uint32_t aModifierFlags,
|
|
uint32_t aAdditionalFlags)
|
|
{ return NS_ERROR_UNEXPECTED; }
|
|
|
|
// Stores the clip rectangles in aRects into mClipRects. Returns true
|
|
// if the new rectangles are different from the old rectangles.
|
|
bool StoreWindowClipRegion(const nsTArray<nsIntRect>& aRects);
|
|
|
|
virtual already_AddRefed<nsIWidget>
|
|
AllocateChildPopupWidget()
|
|
{
|
|
static NS_DEFINE_IID(kCPopUpCID, NS_CHILD_CID);
|
|
nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
|
|
return widget.forget();
|
|
}
|
|
|
|
LayerManager* CreateBasicLayerManager();
|
|
|
|
nsPopupType PopupType() const { return mPopupType; }
|
|
|
|
void NotifyRollupGeometryChange()
|
|
{
|
|
// XULPopupManager isn't interested in this notification, so only
|
|
// send it if gRollupListener is set.
|
|
if (gRollupListener) {
|
|
gRollupListener->NotifyGeometryChange();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Apply the current size constraints to the given size.
|
|
*
|
|
* @param aWidth width to constrain
|
|
* @param aHeight height to constrain
|
|
*/
|
|
void ConstrainSize(int32_t* aWidth, int32_t* aHeight) const
|
|
{
|
|
*aWidth = std::max(mSizeConstraints.mMinSize.width,
|
|
std::min(mSizeConstraints.mMaxSize.width, *aWidth));
|
|
*aHeight = std::max(mSizeConstraints.mMinSize.height,
|
|
std::min(mSizeConstraints.mMaxSize.height, *aHeight));
|
|
}
|
|
|
|
virtual CompositorChild* GetRemoteRenderer() MOZ_OVERRIDE;
|
|
|
|
virtual void GetPreferredCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aHints);
|
|
|
|
/**
|
|
* Notify the widget that this window is being used with OMTC.
|
|
*/
|
|
virtual void WindowUsesOMTC() {}
|
|
|
|
protected:
|
|
/**
|
|
* Starts the OMTC compositor destruction sequence.
|
|
*
|
|
* When this function returns, the compositor should not be
|
|
* able to access the opengl context anymore.
|
|
* It is safe to call it several times if platform implementations
|
|
* require the compositor to be destroyed before ~nsBaseWidget is
|
|
* reached (This is the case with gtk2 for instance).
|
|
*/
|
|
void DestroyCompositor();
|
|
|
|
nsIWidgetListener* mWidgetListener;
|
|
nsIWidgetListener* mAttachedWidgetListener;
|
|
nsDeviceContext* mContext;
|
|
nsRefPtr<LayerManager> mLayerManager;
|
|
nsRefPtr<LayerManager> mBasicLayerManager;
|
|
nsRefPtr<CompositorChild> mCompositorChild;
|
|
nsRefPtr<CompositorParent> mCompositorParent;
|
|
nsCOMPtr<WidgetShutdownObserver> mShutdownObserver;
|
|
nscolor mBackground;
|
|
nscolor mForeground;
|
|
nsCursor mCursor;
|
|
nsWindowType mWindowType;
|
|
nsBorderStyle mBorderStyle;
|
|
bool mUseLayersAcceleration;
|
|
bool mForceLayersAcceleration;
|
|
bool mTemporarilyUseBasicLayerManager;
|
|
bool mUseAttachedEvents;
|
|
bool mContextInitialized;
|
|
nsIntRect mBounds;
|
|
nsIntRect* mOriginalBounds;
|
|
// When this pointer is null, the widget is not clipped
|
|
nsAutoArrayPtr<nsIntRect> mClipRects;
|
|
uint32_t mClipRectCount;
|
|
int32_t mZIndex;
|
|
nsSizeMode mSizeMode;
|
|
nsPopupLevel mPopupLevel;
|
|
nsPopupType mPopupType;
|
|
SizeConstraints mSizeConstraints;
|
|
|
|
static nsIRollupListener* gRollupListener;
|
|
|
|
// the last rolled up popup. Only set this when an nsAutoRollup is in scope,
|
|
// so it can be cleared automatically.
|
|
static nsIContent* mLastRollup;
|
|
|
|
#ifdef DEBUG
|
|
protected:
|
|
static nsAutoString debug_GuiEventToString(mozilla::WidgetGUIEvent* aGuiEvent);
|
|
static bool debug_WantPaintFlashing();
|
|
|
|
static void debug_DumpInvalidate(FILE * aFileOut,
|
|
nsIWidget * aWidget,
|
|
const nsIntRect * aRect,
|
|
const nsAutoCString & aWidgetName,
|
|
int32_t aWindowID);
|
|
|
|
static void debug_DumpEvent(FILE* aFileOut,
|
|
nsIWidget* aWidget,
|
|
mozilla::WidgetGUIEvent* aGuiEvent,
|
|
const nsAutoCString& aWidgetName,
|
|
int32_t aWindowID);
|
|
|
|
static void debug_DumpPaintEvent(FILE * aFileOut,
|
|
nsIWidget * aWidget,
|
|
const nsIntRegion & aPaintEvent,
|
|
const nsAutoCString & aWidgetName,
|
|
int32_t aWindowID);
|
|
|
|
static bool debug_GetCachedBoolPref(const char* aPrefName);
|
|
#endif
|
|
};
|
|
|
|
// A situation can occur when a mouse event occurs over a menu label while the
|
|
// menu popup is already open. The expected behaviour is to close the popup.
|
|
// This happens by calling nsIRollupListener::Rollup before the mouse event is
|
|
// processed. However, in cases where the mouse event is not consumed, this
|
|
// event will then get targeted at the menu label causing the menu to open
|
|
// again. To prevent this, we store in mLastRollup a reference to the popup
|
|
// that was closed during the Rollup call, and prevent this popup from
|
|
// reopening while processing the mouse event.
|
|
// mLastRollup should only be set while an nsAutoRollup is in scope;
|
|
// when it goes out of scope mLastRollup is cleared automatically.
|
|
// As mLastRollup is static, it can be retrieved by calling
|
|
// nsIWidget::GetLastRollup on any widget.
|
|
class nsAutoRollup
|
|
{
|
|
bool wasClear;
|
|
|
|
public:
|
|
|
|
nsAutoRollup();
|
|
~nsAutoRollup();
|
|
};
|
|
|
|
#endif // nsBaseWidget_h__
|