зеркало из https://github.com/mozilla/pjs.git
Bug 297080 - "Mouse cursor stays in pointer form, moving from content area to other window" [p=kinetik@flim.org (Matthew Gregan) r+sr=roc a1.9=damons]
This commit is contained in:
Родитель
75b740fd49
Коммит
e17d7baefa
|
@ -827,24 +827,12 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
break;
|
||||
case NS_MOUSE_EXIT:
|
||||
// If the event coordinate is within the bounds of the view,
|
||||
// and this is not the top-level window, then it's not really
|
||||
// an exit --- we may have traversed widget boundaries but
|
||||
// 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.
|
||||
// On the other hand, if we exit a toplevel window, then
|
||||
// it's really an exit even if the mouse is still in the
|
||||
// window bounds --- the mouse probably moved into some
|
||||
// "on top" window.
|
||||
{
|
||||
nsMouseEvent* mouseEvent = static_cast<nsMouseEvent*>(aEvent);
|
||||
nsIWidget* parentWidget = mouseEvent->widget->GetParent();
|
||||
nsPoint eventPoint;
|
||||
eventPoint = nsLayoutUtils::TranslateWidgetToView(aPresContext,
|
||||
mouseEvent->widget,
|
||||
mouseEvent->refPoint,
|
||||
aView);
|
||||
if (parentWidget &&
|
||||
(aView->GetBounds() - aView->GetPosition()).Contains(eventPoint)) {
|
||||
if (mouseEvent->exit != nsMouseEvent::eTopLevel) {
|
||||
// treat it as a move so we don't generate spurious "exit"
|
||||
// events Any necessary exit events will be generated by
|
||||
// GenerateMouseEnterExit
|
||||
|
|
|
@ -649,12 +649,13 @@ public:
|
|||
enum buttonType { eLeftButton = 0, eMiddleButton = 1, eRightButton = 2 };
|
||||
enum reasonType { eReal, eSynthesized };
|
||||
enum contextType { eNormal, eContextMenuKey };
|
||||
enum exitType { eChild, eTopLevel };
|
||||
|
||||
nsMouseEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w,
|
||||
reasonType aReason, contextType aContext = eNormal)
|
||||
: nsMouseEvent_base(isTrusted, msg, w, NS_MOUSE_EVENT),
|
||||
acceptActivation(PR_FALSE), reason(aReason), context(aContext),
|
||||
clickCount(0)
|
||||
exit(eChild), clickCount(0)
|
||||
{
|
||||
if (msg == NS_MOUSE_MOVE) {
|
||||
flags |= NS_EVENT_FLAG_CANT_CANCEL;
|
||||
|
@ -676,6 +677,7 @@ public:
|
|||
PRPackedBool acceptActivation;
|
||||
reasonType reason : 4;
|
||||
contextType context : 4;
|
||||
exitType exit;
|
||||
|
||||
/// The number of mouse clicks
|
||||
PRUint32 clickCount;
|
||||
|
|
|
@ -1524,6 +1524,10 @@ NS_IMETHODIMP nsChildView::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
|
|||
// Invokes callback and ProcessEvent methods on Event Listener object
|
||||
NS_IMETHODIMP nsChildView::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug_DumpEvent(stdout, event->widget, event, nsCAutoString("something"), 0);
|
||||
#endif
|
||||
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip(mParentWidget ? mParentWidget : this);
|
||||
|
@ -2884,7 +2888,8 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
PRUint32 msg,
|
||||
nsIWidget *widget,
|
||||
nsMouseEvent::reasonType aReason,
|
||||
NSPoint* localEventLocation)
|
||||
NSPoint* localEventLocation,
|
||||
nsMouseEvent::exitType type)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
|
@ -2903,6 +2908,8 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
macEvent.modifiers = ::GetCurrentEventKeyModifiers();
|
||||
event.nativeMsg = &macEvent;
|
||||
|
||||
event.exit = type;
|
||||
|
||||
nsEventStatus status;
|
||||
widget->DispatchEvent(&event, status);
|
||||
return status;
|
||||
|
@ -2944,7 +2951,8 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
if (sLastViewEntered) {
|
||||
nsIWidget* lastViewEnteredWidget = [(NSView<mozView>*)sLastViewEntered widget];
|
||||
NSPoint exitEventLocation = [sLastViewEntered convertPoint:windowEventLocation fromView:nil];
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal, &exitEventLocation);
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal,
|
||||
&exitEventLocation, nsMouseEvent::eChild);
|
||||
sLastViewEntered = nil;
|
||||
}
|
||||
return;
|
||||
|
@ -2968,7 +2976,8 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
NSPoint exitEventLocation = [sLastViewEntered convertPoint:windowEventLocation fromView:nil];
|
||||
// NSLog(@"sending NS_MOUSE_EXIT event with point %f,%f\n", exitEventLocation.x, exitEventLocation.y);
|
||||
nsIWidget* lastViewEnteredWidget = [(NSView<mozView>*)sLastViewEntered widget];
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal, &exitEventLocation);
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal,
|
||||
&exitEventLocation, nsMouseEvent::eTopLevel);
|
||||
sLastViewEntered = nil;
|
||||
}
|
||||
return;
|
||||
|
@ -2985,7 +2994,8 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
NSPoint exitEventLocation = [sLastViewEntered convertPoint:windowEventLocation fromView:nil];
|
||||
// NSLog(@"sending NS_MOUSE_EXIT event with point %f,%f\n", exitEventLocation.x, exitEventLocation.y);
|
||||
nsIWidget* lastViewEnteredWidget = [(NSView<mozView>*)sLastViewEntered widget];
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal, &exitEventLocation);
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal,
|
||||
&exitEventLocation, nsMouseEvent::eChild);
|
||||
|
||||
// The mouse exit event we just sent may have destroyed this widget, bail if that happened.
|
||||
if (!mGeckoChild)
|
||||
|
@ -2993,7 +3003,8 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
|
|||
}
|
||||
|
||||
// NSLog(@"sending NS_MOUSE_ENTER event with point %f,%f\n", viewEventLocation.x, viewEventLocation.y);
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_ENTER, mGeckoChild, nsMouseEvent::eReal, &viewEventLocation);
|
||||
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_ENTER, mGeckoChild, nsMouseEvent::eReal,
|
||||
&viewEventLocation, nsMouseEvent::eChild);
|
||||
|
||||
// The mouse enter event we just sent may have destroyed this widget, bail if that happened.
|
||||
if (!mGeckoChild)
|
||||
|
|
|
@ -146,6 +146,11 @@ NS_IMETHODIMP
|
|||
nsCommonWidget::DispatchEvent(nsGUIEvent *aEvent,
|
||||
nsEventStatus &aStatus)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug_DumpEvent(stdout, aEvent->widget, aEvent,
|
||||
nsCAutoString("something"), 0);
|
||||
#endif
|
||||
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
// send it to the standard callback
|
||||
|
|
|
@ -1920,6 +1920,20 @@ nsWindow::OnEnterNotifyEvent(GtkWidget *aWidget, GdkEventCrossing *aEvent)
|
|||
DispatchEvent(&event, status);
|
||||
}
|
||||
|
||||
static PRBool
|
||||
is_top_level_mouse_exit(GdkWindow* aWindow, GdkEventCrossing *aEvent)
|
||||
{
|
||||
gint x = gint(aEvent->x_root);
|
||||
gint y = gint(aEvent->y_root);
|
||||
GdkDisplay* display = gdk_drawable_get_display(aWindow);
|
||||
GdkWindow* winAtPt = gdk_display_get_window_at_pointer(display, &x, &y);
|
||||
if (!winAtPt)
|
||||
return PR_TRUE;
|
||||
GdkWindow* topLevelAtPt = gdk_window_get_toplevel(winAtPt);
|
||||
GdkWindow* topLevelWidget = gdk_window_get_toplevel(aWindow);
|
||||
return topLevelAtPt != topLevelWidget;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::OnLeaveNotifyEvent(GtkWidget *aWidget, GdkEventCrossing *aEvent)
|
||||
{
|
||||
|
@ -1934,6 +1948,9 @@ nsWindow::OnLeaveNotifyEvent(GtkWidget *aWidget, GdkEventCrossing *aEvent)
|
|||
|
||||
event.time = aEvent->time;
|
||||
|
||||
event.exit = is_top_level_mouse_exit(mDrawingarea->inner_window, aEvent)
|
||||
? nsMouseEvent::eTopLevel : nsMouseEvent::eChild;
|
||||
|
||||
LOG(("OnLeaveNotify: %p\n", (void *)this));
|
||||
|
||||
nsEventStatus status;
|
||||
|
|
|
@ -4346,16 +4346,15 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
|||
#ifndef WINCE
|
||||
case WM_MOUSELEAVE:
|
||||
{
|
||||
// We use MINLONG | MINSHORT as the mouse position to make sure
|
||||
// EventStateManager doesn't convert this EXIT message to
|
||||
// a MOVE message (besides, WM_MOUSELEAVE doesn't have the position
|
||||
// in lParam).
|
||||
// We also need to check mouse button states and put them in for
|
||||
// We need to check mouse button states and put them in for
|
||||
// wParam.
|
||||
WPARAM mouseState = (GetKeyState(VK_LBUTTON) ? MK_LBUTTON : 0)
|
||||
| (GetKeyState(VK_MBUTTON) ? MK_MBUTTON : 0)
|
||||
| (GetKeyState(VK_RBUTTON) ? MK_RBUTTON : 0);
|
||||
DispatchMouseEvent(NS_MOUSE_EXIT, mouseState, MINLONG | MINSHORT);
|
||||
// Synthesize an event position because we don't get one from
|
||||
// WM_MOUSELEAVE.
|
||||
LPARAM pos = lParamToClient(::GetMessagePos());
|
||||
DispatchMouseEvent(NS_MOUSE_EXIT, mouseState, pos);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -5658,6 +5657,16 @@ PRBool nsWindow::OnResize(nsRect &aWindowRect)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool IsTopLevelMouseExit(HWND aWnd)
|
||||
{
|
||||
DWORD pos = ::GetMessagePos();
|
||||
POINT mp;
|
||||
mp.x = GET_X_LPARAM(pos);
|
||||
mp.y = GET_Y_LPARAM(pos);
|
||||
HWND mouseTopLevel = nsWindow::GetTopLevelHWND(::WindowFromPoint(mp));
|
||||
return nsWindow::GetTopLevelHWND(aWnd) != mouseTopLevel;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Deal with all sort of mouse event
|
||||
|
@ -5763,6 +5772,9 @@ PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam,
|
|||
else if (aEventType == NS_MOUSE_MOVE && !insideMovementThreshold) {
|
||||
gLastClickCount = 0;
|
||||
}
|
||||
else if (aEventType == NS_MOUSE_EXIT) {
|
||||
event.exit = IsTopLevelMouseExit(mWnd) ? nsMouseEvent::eTopLevel : nsMouseEvent::eChild;
|
||||
}
|
||||
event.clickCount = gLastClickCount;
|
||||
|
||||
#ifdef NS_DEBUG_XX
|
||||
|
|
Загрузка…
Ссылка в новой задаче