Bug 678481 - Send a mouse move event after switiching into or out of drawintitlebar mode so that Gecko knows about the changed mouse position relative to the Gecko content area. r=josh
authorMarkus Stange <mstange@themasta.com>
Sat, 13 Aug 2011 16:25:39 +0200
changeset 74370 e99b737739888ad18dfd8be8b862bc97737f5704
parent 74369 bcab3415d9ee64c259aa6666c479ad6de7e18be6
child 74371 a3adb8c01a197a958e045a4a91ea7fef5deabab8
push id1195
push usermstange@themasta.com
push dateSat, 13 Aug 2011 14:27:25 +0000
treeherdermozilla-inbound@e99b73773988 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjosh
bugs678481
milestone8.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 678481 - Send a mouse move event after switiching into or out of drawintitlebar mode so that Gecko knows about the changed mouse position relative to the Gecko content area. r=josh
widget/src/cocoa/nsChildView.h
widget/src/cocoa/nsChildView.mm
widget/src/cocoa/nsCocoaWindow.mm
--- a/widget/src/cocoa/nsChildView.h
+++ b/widget/src/cocoa/nsChildView.h
@@ -359,19 +359,21 @@ public:
   static void MouseMoved(NSEvent* aEvent);
   static void OnDestroyView(ChildView* aView);
   static void OnDestroyWindow(NSWindow* aWindow);
   static BOOL WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent,
                                  ChildView* aView, BOOL isClickThrough = NO);
   static void MouseExitedWindow(NSEvent* aEvent);
   static void MouseEnteredWindow(NSEvent* aEvent);
   static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil);
+  static void ResendLastMouseMoveEvent();
   static ChildView* ViewForEvent(NSEvent* aEvent);
 
   static ChildView* sLastMouseEventView;
+  static NSEvent* sLastMouseMoveEvent;
   static NSWindow* sWindowUnderMouse;
 };
 
 //-------------------------------------------------------------------------
 //
 // nsChildView
 //
 //-------------------------------------------------------------------------
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -121,16 +121,17 @@ extern NSMenu* sApplicationMenu; // Appl
 // these are defined in nsCocoaWindow.mm
 extern PRBool gConsumeRollupEvent;
 
 PRBool gChildViewMethodsSwizzled = PR_FALSE;
 
 extern nsISupportsArray *gDraggedTransferables;
 
 ChildView* ChildViewMouseTracker::sLastMouseEventView = nil;
+NSEvent* ChildViewMouseTracker::sLastMouseMoveEvent = nil;
 NSWindow* ChildViewMouseTracker::sWindowUnderMouse = nil;
 
 #ifdef INVALIDATE_DEBUGGING
 static void blinkRect(Rect* r);
 static void blinkRgn(RgnHandle rgn);
 #endif
 
 nsIRollupListener * gRollupListener = nsnull;
@@ -4895,16 +4896,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
 
 #pragma mark -
 
 void
 ChildViewMouseTracker::OnDestroyView(ChildView* aView)
 {
   if (sLastMouseEventView == aView) {
     sLastMouseEventView = nil;
+    [sLastMouseMoveEvent release];
+    sLastMouseMoveEvent = nil;
   }
 }
 
 void
 ChildViewMouseTracker::OnDestroyWindow(NSWindow* aWindow)
 {
   if (sWindowUnderMouse == aWindow) {
     sWindowUnderMouse = nil;
@@ -4941,20 +4944,32 @@ ChildViewMouseTracker::ReEvaluateMouseEn
     if (type == nsMouseEvent::eTopLevel) {
       [[nsCursorManager sharedInstance] setCursor:eCursor_standard];
     }
     [sLastMouseEventView sendMouseEnterOrExitEvent:aEvent enter:YES type:type];
   }
 }
 
 void
+ChildViewMouseTracker::ResendLastMouseMoveEvent()
+{
+  if (sLastMouseMoveEvent) {
+    MouseMoved(sLastMouseMoveEvent);
+  }
+}
+
+void
 ChildViewMouseTracker::MouseMoved(NSEvent* aEvent)
 {
   MouseEnteredWindow(aEvent);
   [sLastMouseEventView handleMouseMoved:aEvent];
+  if (sLastMouseMoveEvent != aEvent) {
+    [sLastMouseMoveEvent release];
+    sLastMouseMoveEvent = [aEvent retain];
+  }
 }
 
 ChildView*
 ChildViewMouseTracker::ViewForEvent(NSEvent* aEvent)
 {
   NSWindow* window = sWindowUnderMouse;
   if (!window)
     return nil;
--- a/widget/src/cocoa/nsCocoaWindow.mm
+++ b/widget/src/cocoa/nsCocoaWindow.mm
@@ -2296,16 +2296,24 @@ static const NSString* kStateShowsToolba
   [super setDrawsContentsIntoWindowFrame:aState];
   if (stateChanged && [[self delegate] isKindOfClass:[WindowDelegate class]]) {
     WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate];
     nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget];
     if (geckoWindow) {
       // Re-layout our contents.
       geckoWindow->ReportSizeEvent();
     }
+
+    // Resizing the content area causes a reflow which would send a synthesized
+    // mousemove event to the old mouse position relative to the top left
+    // corner of the content area. But the mouse has shifted relative to the
+    // content area, so that event would have wrong position information. So
+    // we'll send a mouse move event with the correct new position.
+    ChildViewMouseTracker::ResendLastMouseMoveEvent();
+
     [self setTitlebarNeedsDisplayInRect:[self titlebarRect]];
   }
 }
 
 // Returning YES here makes the setShowsToolbarButton method work even though
 // the window doesn't contain an NSToolbar.
 - (BOOL)_hasToolbar
 {