Bug 513162 - Widget additions for recycling top level widgets as content containers. r=vlad.

This commit is contained in:
Jim Mathies 2010-06-24 21:01:06 -05:00
Родитель e66cbb615d
Коммит b6fd12e643
5 изменённых файлов: 205 добавлений и 10 удалений

Просмотреть файл

@ -66,6 +66,7 @@ class nsGUIEvent;
class imgIContainer;
class gfxASurface;
class nsIContent;
class ViewWrapper;
namespace mozilla {
namespace layers {
@ -110,8 +111,9 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#endif
#define NS_IWIDGET_IID \
{ 0xf286438a, 0x6ec6, 0x4766, \
{ 0xa4, 0x76, 0x4a, 0x44, 0x80, 0x95, 0xd3, 0x1f } }
{ 0x271ac413, 0xa202, 0x46dc, \
{ 0xbc, 0xd5, 0x67, 0xa1, 0xfb, 0x58, 0x89, 0x7f } }
/*
* Window shadow styles
* Also used for the -moz-window-shadow CSS property
@ -235,6 +237,28 @@ class nsIWidget : public nsISupports {
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull) = 0;
/**
* Attach to a top level widget.
*
* In cases where a top level chrome widget is being used as a content
* container, attach a secondary event callback and update the device
* context. The primary event callback will continue to be called, so the
* owning base window will continue to function.
*
* aViewEventFunction Event callback that will receive mirrored
* events.
* aContext The new device context for the view
*/
NS_IMETHOD AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction,
nsIDeviceContext *aContext) = 0;
/**
* Accessor functions to get and set secondary client data. Used by
* nsIView in connection with AttachViewToTopLevel above.
*/
NS_IMETHOD SetAttachedViewPtr(ViewWrapper* aViewWrapper) = 0;
virtual ViewWrapper* GetAttachedViewPtr() = 0;
/**
* Accessor functions to get and set the client data associated with the
* widget.
@ -408,6 +432,22 @@ class nsIWidget : public nsISupports {
PRInt32 aHeight,
PRBool aRepaint) = 0;
/**
* Resize and reposition the inner client area of the widget.
*
* @param aX the new x offset expressed in the parent's coordinate system
* @param aY the new y offset expressed in the parent's coordinate system
* @param aWidth the new width of the client area.
* @param aHeight the new height of the client area.
* @param aRepaint whether the widget should be repainted
*
*/
NS_IMETHOD ResizeClient(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint) = 0;
/**
* Sets the widget's z-index.
*/
@ -502,6 +542,14 @@ class nsIWidget : public nsISupports {
*/
NS_IMETHOD GetClientBounds(nsIntRect &aRect) = 0;
/**
* Get the client offset from the window origin.
*
* @param aPt on return it holds the width and height of the offset.
*
*/
NS_IMETHOD GetClientOffset(nsIntPoint &aPt) = 0;
/**
* Get the foreground color for this widget
*

Просмотреть файл

@ -582,8 +582,10 @@ nsWindow::Create(nsIWidget *aParent,
nsToolkit::mDllInstance,
NULL);
if (!mWnd)
if (!mWnd) {
NS_WARNING("nsWindow CreateWindowEx failed.");
return NS_ERROR_FAILURE;
}
if (nsWindow::sTrackPointHack &&
mWindowType != eWindowType_plugin &&
@ -1337,6 +1339,10 @@ NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
NS_ASSERTION((aWidth >=0 ) , "Negative width passed to nsWindow::Resize");
NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
// Avoid unnecessary resizing calls
if (mBounds.width == aWidth && mBounds.height == aHeight)
return NS_OK;
#ifdef MOZ_XUL
if (eTransparencyTransparent == mTransparencyMode)
ResizeTranslucentWindow(aWidth, aHeight);
@ -1372,6 +1378,11 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeig
NS_ASSERTION((aWidth >=0 ), "Negative width passed to nsWindow::Resize");
NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
// Avoid unnecessary resizing calls
if (mBounds.x == aX && mBounds.y == aY &&
mBounds.width == aWidth && mBounds.height == aHeight)
return NS_OK;
#ifdef MOZ_XUL
if (eTransparencyTransparent == mTransparencyMode)
ResizeTranslucentWindow(aWidth, aHeight);
@ -1402,6 +1413,30 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeig
return NS_OK;
}
// Resize the client area and position the widget within it's parent
NS_METHOD nsWindow::ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
// Adjust our existing window bounds, based on the new client dims.
RECT client;
GetClientRect(mWnd, &client);
nsIntPoint dims(client.right - client.left, client.bottom - client.top);
aWidth = mBounds.width + (aWidth - dims.x);
aHeight = mBounds.height + (aHeight - dims.y);
if (aX || aY) {
// offsets
nsIntRect bounds;
GetScreenBounds(bounds);
aX += bounds.x;
aY += bounds.y;
return Resize(aX, aY, aWidth, aHeight, aRepaint);
}
return Resize(aWidth, aHeight, aRepaint);
}
#if !defined(WINCE)
NS_IMETHODIMP
nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
@ -1691,7 +1726,9 @@ NS_METHOD nsWindow::SetFocus(PRBool aRaise)
*
**************************************************************/
// Get this component dimension
// Return the window's full dimensions in screen coordinates.
// If the window has a parent, converts the origin to an offset
// of the parent's screen origin.
NS_METHOD nsWindow::GetBounds(nsIntRect &aRect)
{
if (mWnd) {
@ -1702,6 +1739,32 @@ NS_METHOD nsWindow::GetBounds(nsIntRect &aRect)
aRect.width = r.right - r.left;
aRect.height = r.bottom - r.top;
// chrome on parent:
// ___ 5,5 (chrome start)
// | ____ 10,10 (client start)
// | | ____ 20,20 (child start)
// | | |
// 20,20 - 5,5 = 15,15 (??)
// minus GetClientOffset:
// 15,15 - 5,5 = 10,10
//
// no chrome on parent:
// ______ 10,10 (win start)
// | ____ 20,20 (child start)
// | |
// 20,20 - 10,10 = 10,10
//
// walking the chain:
// ___ 5,5 (chrome start)
// | ___ 10,10 (client start)
// | | ___ 20,20 (child start)
// | | | __ 30,30 (child start)
// | | | |
// 30,30 - 20,20 = 10,10 (offset from second child to first)
// 20,20 - 5,5 = 15,15 + 10,10 = 25,25 (??)
// minus GetClientOffset:
// 25,25 - 5,5 = 20,20 (offset from second child to parent client)
// convert coordinates if parent exists
HWND parent = ::GetParent(mWnd);
if (parent) {
@ -1709,6 +1772,14 @@ NS_METHOD nsWindow::GetBounds(nsIntRect &aRect)
VERIFY(::GetWindowRect(parent, &pr));
r.left -= pr.left;
r.top -= pr.top;
// adjust for chrome
nsWindow* pWidget = static_cast<nsWindow*>(GetParent());
if (pWidget && pWidget->IsTopLevelWidget()) {
nsIntPoint clientOffset;
pWidget->GetClientOffset(clientOffset);
r.left -= clientOffset.x;
r.top -= clientOffset.y;
}
}
aRect.x = r.left;
aRect.y = r.top;
@ -1755,6 +1826,23 @@ NS_METHOD nsWindow::GetScreenBounds(nsIntRect &aRect)
return NS_OK;
}
// return the x,y offset of the client area from the origin
// of the window. If the window is borderless returns (0,0).
NS_METHOD nsWindow::GetClientOffset(nsIntPoint &aPt)
{
if (!mWnd) {
aPt.x = aPt.y = 0;
return NS_OK;
}
RECT r1;
GetWindowRect(mWnd, &r1);
nsIntPoint pt = WidgetToScreenOffset();
aPt.x = pt.x - r1.left;
aPt.y = pt.y - r1.top;
return NS_OK;
}
/**************************************************************
*
* SECTION: nsIWidget::SetBackgroundColor
@ -6332,6 +6420,13 @@ PRBool nsWindow::OnResize(nsIntRect &aWindowRect)
event.mWinWidth = 0;
event.mWinHeight = 0;
}
#if 0
printf("[%X] OnResize: client:(%d x %d x %d x %d) window:(%d x %d)\n", this,
aWindowRect.x, aWindowRect.y, aWindowRect.width, aWindowRect.height,
event.mWinWidth, event.mWinHeight);
#endif
return DispatchWindowEvent(&event);
}

Просмотреть файл

@ -129,6 +129,7 @@ public:
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
#if !defined(WINCE)
NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
#endif
@ -140,6 +141,7 @@ public:
NS_IMETHOD GetBounds(nsIntRect &aRect);
NS_IMETHOD GetScreenBounds(nsIntRect &aRect);
NS_IMETHOD GetClientBounds(nsIntRect &aRect);
NS_IMETHOD GetClientOffset(nsIntPoint &aPt);
NS_IMETHOD SetBackgroundColor(const nscolor &aColor);
NS_IMETHOD SetCursor(imgIContainer* aCursor,
PRUint32 aHotspotX, PRUint32 aHotspotY);
@ -243,6 +245,7 @@ public:
PRBool GetIMEEnabled() { return mIMEEnabled; }
// needed in nsIMM32Handler.cpp
PRBool PluginHasFocus() { return mIMEEnabled == nsIWidget::IME_STATUS_PLUGIN; }
PRBool IsTopLevelWidget() { return mIsTopWidgetWindow; }
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
PRBool HasTaskbarIconBeenCreated() { return mHasTaskbarIconBeenCreated; }

Просмотреть файл

@ -95,7 +95,9 @@ nsAutoRollup::~nsAutoRollup()
nsBaseWidget::nsBaseWidget()
: mClientData(nsnull)
, mViewWrapperPtr(nsnull)
, mEventCallback(nsnull)
, mViewCallback(nsnull)
, mContext(nsnull)
, mToolkit(nsnull)
, mCursor(eCursor_standard)
@ -237,6 +239,46 @@ NS_IMETHODIMP nsBaseWidget::SetClientData(void* aClientData)
return NS_OK;
}
// Attach a view to our widget which we'll send events to.
NS_IMETHODIMP
nsBaseWidget::AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction,
nsIDeviceContext *aContext)
{
NS_ASSERTION((mWindowType == eWindowType_toplevel), "Can't attach to child?");
mViewCallback = aViewEventFunction;
if (aContext) {
if (mContext) {
NS_IF_RELEASE(mContext);
}
mContext = aContext;
NS_ADDREF(mContext);
}
return NS_OK;
}
ViewWrapper* nsBaseWidget::GetAttachedViewPtr()
{
return mViewWrapperPtr;
}
NS_IMETHODIMP nsBaseWidget::SetAttachedViewPtr(ViewWrapper* aViewWrapper)
{
mViewWrapperPtr = aViewWrapper;
return NS_OK;
}
NS_METHOD nsBaseWidget::ResizeClient(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint)
{
return Resize(aX, aY, aWidth, aHeight, aRepaint);
}
//-------------------------------------------------------------------------
//
// Close this nsBaseWidget
@ -770,18 +812,18 @@ NS_METHOD nsBaseWidget::GetScreenBounds(nsIntRect &aRect)
return GetBounds(aRect);
}
/**
*
*
**/
NS_METHOD nsBaseWidget::GetClientOffset(nsIntPoint &aPt)
{
aPt.x = aPt.y = 0;
return NS_OK;
}
NS_METHOD nsBaseWidget::SetBounds(const nsIntRect &aRect)
{
mBounds = aRect;
return NS_OK;
}
NS_METHOD nsBaseWidget::EnableDragDrop(PRBool aEnable)
{

Просмотреть файл

@ -116,6 +116,7 @@ public:
NS_IMETHOD GetBounds(nsIntRect &aRect);
NS_IMETHOD GetClientBounds(nsIntRect &aRect);
NS_IMETHOD GetScreenBounds(nsIntRect &aRect);
NS_IMETHOD GetClientOffset(nsIntPoint &aPt);
NS_IMETHOD EnableDragDrop(PRBool aEnable);
NS_IMETHOD GetAttention(PRInt32 aCycleCount);
virtual PRBool HasPendingInputEvent();
@ -143,6 +144,10 @@ public:
NS_IMETHOD OnIMESelectionChange(void) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD OnDefaultButtonLoaded(const nsIntRect &aButtonRect) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta, PRBool aIsHorizontal, PRInt32 &aOverriddenDelta);
NS_IMETHOD AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction, nsIDeviceContext *aContext);
virtual ViewWrapper* GetAttachedViewPtr();
NS_IMETHOD SetAttachedViewPtr(ViewWrapper* aViewWrapper);
NS_IMETHOD ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
/**
* Use this when GetLayerManager() returns a BasicLayerManager
@ -195,7 +200,9 @@ protected:
protected:
void* mClientData;
ViewWrapper* mViewWrapperPtr;
EVENT_CALLBACK mEventCallback;
EVENT_CALLBACK mViewCallback;
nsIDeviceContext* mContext;
nsIToolkit* mToolkit;
nsRefPtr<LayerManager> mLayerManager;