Bug 1003943 - Properly update widget cursors when the mouse passes between remote frames. r=smaug

This commit is contained in:
Jim Mathies 2014-05-27 20:12:29 -05:00
Родитель 2ee59969dc
Коммит e88a91f7f4
11 изменённых файлов: 68 добавлений и 10 удалений

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

@ -558,6 +558,17 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
break;
}
case NS_MOUSE_EXIT:
// If this is a remote frame, we receive NS_MOUSE_EXIT from the parent
// the mouse exits our content. Since the parent may update the cursor
// while the mouse is outside our frame, and since PuppetWidget caches the
// current cursor internally, re-entering our content (say from over a
// window edge) wont update the cursor if the cached value and the current
// cursor match. So when the mouse exits a remote frame, clear the cached
// widget cursor so a proper update will occur when the mouse re-enters.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
ClearCachedWidgetCursor(mCurrentTarget);
}
// If the event is not a top-level window exit, then it's not
// really an exit --- we may have traversed widget boundaries but
// we're still in our toplevel window.
@ -3329,6 +3340,19 @@ EventStateManager::UpdateCursor(nsPresContext* aPresContext,
}
}
void
EventStateManager::ClearCachedWidgetCursor(nsIFrame* aTargetFrame)
{
if (!aTargetFrame) {
return;
}
nsIWidget* aWidget = aTargetFrame->GetNearestWidget();
if (!aWidget) {
return;
}
aWidget->ClearCachedCursor();
}
nsresult
EventStateManager::SetCursor(int32_t aCursor, imgIContainer* aContainer,
bool aHaveHotspot,

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

@ -271,6 +271,15 @@ protected:
*/
static int32_t GetAccessModifierMaskFor(nsISupports* aDocShell);
/*
* If aTargetFrame's widget has a cached cursor value, resets the cursor
* such that the next call to SetCursor on the widget will force an update
* of the native cursor. For use in getting puppet widget to update its
* cursor between mouse exit / enter transitions. This call basically wraps
* nsIWidget ClearCachedCursor.
*/
void ClearCachedWidgetCursor(nsIFrame* aTargetFrame);
void UpdateCursor(nsPresContext* aPresContext,
WidgetEvent* aEvent,
nsIFrame* aTargetFrame,

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

@ -226,7 +226,16 @@ parent:
*/
sync GetWidgetNativeData() returns (WindowsHandle value);
SetCursor(uint32_t value);
/**
* Set the native cursor.
* @param value
* The widget cursor to set.
* @param force
* Invalidate any locally cached cursor settings and force an
* update.
*/
SetCursor(uint32_t value, bool force);
SetBackgroundColor(nscolor color);
/**

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

@ -1017,10 +1017,13 @@ TabParent::RecvAsyncMessage(const nsString& aMessage,
}
bool
TabParent::RecvSetCursor(const uint32_t& aCursor)
TabParent::RecvSetCursor(const uint32_t& aCursor, const bool& aForce)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
if (aForce) {
widget->ClearCachedCursor();
}
widget->SetCursor((nsCursor) aCursor);
}
return true;

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

@ -168,7 +168,7 @@ public:
const int32_t& aCause,
const int32_t& aFocusChange) MOZ_OVERRIDE;
virtual bool RecvRequestFocus(const bool& aCanRaise) MOZ_OVERRIDE;
virtual bool RecvSetCursor(const uint32_t& aValue) MOZ_OVERRIDE;
virtual bool RecvSetCursor(const uint32_t& aValue, const bool& aForce) MOZ_OVERRIDE;
virtual bool RecvSetBackgroundColor(const nscolor& aValue) MOZ_OVERRIDE;
virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus) MOZ_OVERRIDE;
virtual bool RecvIsParentWindowMainWidgetVisible(bool* aIsVisible);

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

@ -1507,8 +1507,9 @@ nsWindow::SetCursor(nsCursor aCursor)
}
// Only change cursor if it's actually been changed
if (aCursor != mCursor) {
if (aCursor != mCursor || mUpdateCursor) {
GdkCursor *newCursor = nullptr;
mUpdateCursor = false;
newCursor = get_gtk_cursor(aCursor);

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

@ -100,8 +100,8 @@ typedef void* nsNativeWidget;
#endif
#define NS_IWIDGET_IID \
{ 0x91944a4b, 0xbc29, 0x44aa, \
{ 0x99, 0x21, 0x42, 0xeb, 0x1f, 0xbb, 0xa6, 0x89 } }
{ 0x5b27abd6, 0x9e53, 0x4a0a, \
{ 0x86, 0xf, 0x77, 0x5c, 0xc5, 0x69, 0x35, 0xf } };
/*
* Window shadow styles
@ -1165,6 +1165,13 @@ class nsIWidget : public nsISupports {
NS_IMETHOD SetCursor(nsCursor aCursor) = 0;
/**
* If a cursor type is currently cached locally for this widget, clear the
* cached cursor to force an update on the next SetCursor call.
*/
virtual void ClearCachedCursor() = 0;
/**
* Sets an image as the cursor for this widget.
*

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

@ -809,10 +809,10 @@ nsWindow::GetGLFrameBufferFormat()
NS_IMETHODIMP
nsWindow::SetCursor(nsCursor aCursor)
{
if (mCursor == aCursor) {
if (mCursor == aCursor && !mUpdateCursor) {
return NS_OK;
}
mUpdateCursor = false;
mCursor = aCursor;
if (mWidget) {
mWidget->SetCursor(mCursor);

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

@ -649,15 +649,17 @@ PuppetWidget::NotifyIMEOfSelectionChange(
NS_IMETHODIMP
PuppetWidget::SetCursor(nsCursor aCursor)
{
if (mCursor == aCursor) {
if (mCursor == aCursor && !mUpdateCursor) {
return NS_OK;
}
if (mTabChild && !mTabChild->SendSetCursor(aCursor)) {
if (mTabChild &&
!mTabChild->SendSetCursor(aCursor, mUpdateCursor)) {
return NS_ERROR_FAILURE;
}
mCursor = aCursor;
mUpdateCursor = false;
return NS_OK;
}

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

@ -111,6 +111,7 @@ nsBaseWidget::nsBaseWidget()
, mAttachedWidgetListener(nullptr)
, mContext(nullptr)
, mCursor(eCursor_standard)
, mUpdateCursor(true)
, mBorderStyle(eBorderStyle_none)
, mUseLayersAcceleration(false)
, mForceLayersAcceleration(false)

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

@ -115,6 +115,7 @@ public:
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetCursor(imgIContainer* aCursor,
uint32_t aHotspotX, uint32_t aHotspotY);
virtual void ClearCachedCursor() { mUpdateCursor = true; }
virtual void SetTransparencyMode(nsTransparencyMode aMode);
virtual nsTransparencyMode GetTransparencyMode();
virtual void GetWindowClipRegion(nsTArray<nsIntRect>* aRects);
@ -402,6 +403,7 @@ protected:
nsRefPtr<CompositorParent> mCompositorParent;
nsRefPtr<WidgetShutdownObserver> mShutdownObserver;
nsCursor mCursor;
bool mUpdateCursor;
nsBorderStyle mBorderStyle;
bool mUseLayersAcceleration;
bool mForceLayersAcceleration;