author | Josh Aas <joshmoz@gmail.com> |
Thu, 01 Nov 2012 09:19:24 -0400 | |
changeset 112043 | d1b1ca54cb421b9566d683ec7a381a07a601b4ec |
parent 112042 | 5326fc45fe46258527d4af488bccfca2852acff0 |
child 112044 | 4d8717e04a99c2d003164517e2c00c235dffe8a9 |
push id | 23790 |
push user | ryanvm@gmail.com |
push date | Fri, 02 Nov 2012 01:26:40 +0000 |
treeherder | mozilla-central@556b9cfb269f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 647216, 806244 |
milestone | 19.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
|
--- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -506,39 +506,38 @@ NS_IMETHODIMP nsDOMWindowUtils::SendMouseEvent(const nsAString& aType, float aX, float aY, int32_t aButton, int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, - unsigned short aInputSourceArg, - bool *aPreventDefault) + unsigned short aInputSourceArg) { return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame, aPressure, - aInputSourceArg, false, aPreventDefault); + aInputSourceArg, false); } NS_IMETHODIMP nsDOMWindowUtils::SendMouseEventToWindow(const nsAString& aType, float aX, float aY, int32_t aButton, int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg) { SAMPLE_LABEL("nsDOMWindowUtils", "SendMouseEventToWindow"); return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame, aPressure, - aInputSourceArg, true, nullptr); + aInputSourceArg, true); } static nsIntPoint ToWidgetPoint(float aX, float aY, const nsPoint& aOffset, nsPresContext* aPresContext) { double appPerDev = aPresContext->AppUnitsPerDevPixel(); nscoord appPerCSS = nsPresContext::AppUnitsPerCSSPixel(); @@ -551,18 +550,17 @@ nsDOMWindowUtils::SendMouseEventCommon(c float aX, float aY, int32_t aButton, int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, - bool aToWindow, - bool *aPreventDefault) + bool aToWindow) { if (!nsContentUtils::IsCallerChrome()) { return NS_ERROR_DOM_SECURITY_ERR; } // get the widget to send the event to nsPoint offset; nsCOMPtr<nsIWidget> widget = GetWidget(&offset); @@ -579,19 +577,17 @@ nsDOMWindowUtils::SendMouseEventCommon(c msg = NS_MOUSE_MOVE; else if (aType.EqualsLiteral("mouseover")) msg = NS_MOUSE_ENTER; else if (aType.EqualsLiteral("mouseout")) msg = NS_MOUSE_EXIT; else if (aType.EqualsLiteral("contextmenu")) { msg = NS_CONTEXTMENU; contextMenuKey = (aButton == 0); - } else if (aType.EqualsLiteral("MozMouseHittest")) - msg = NS_MOUSE_MOZHITTEST; - else + } else return NS_ERROR_FAILURE; if (aInputSourceArg == nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN) { aInputSourceArg = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE; } nsMouseEvent event(true, msg, widget, nsMouseEvent::eReal, contextMenuKey ? @@ -622,20 +618,17 @@ nsDOMWindowUtils::SendMouseEventCommon(c return NS_ERROR_FAILURE; nsIView* view = viewManager->GetRootView(); if (!view) return NS_ERROR_FAILURE; status = nsEventStatus_eIgnore; return presShell->HandleEvent(view->GetFrame(), &event, false, &status); } - nsresult rv = widget->DispatchEvent(&event, status); - *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault); - - return rv; + return widget->DispatchEvent(&event, status); } NS_IMETHODIMP nsDOMWindowUtils::SendWheelEvent(float aX, float aY, double aDeltaX, double aDeltaY, double aDeltaZ,
--- a/dom/base/nsDOMWindowUtils.h +++ b/dom/base/nsDOMWindowUtils.h @@ -39,13 +39,12 @@ protected: float aX, float aY, int32_t aButton, int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, - bool aToWindow, - bool *aPreventDefault); + bool aToWindow); static mozilla::widget::Modifiers GetWidgetModifiers(int32_t aModifiers); };
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -35,17 +35,17 @@ interface nsIQueryContentEventResult; interface nsIDOMWindow; interface nsIDOMBlob; interface nsIDOMFile; interface nsIFile; interface nsIDOMTouch; interface nsIDOMClientRect; interface nsIURI; -[scriptable, uuid(b3a3589d-cc9d-4123-9b21-51c66e88b436)] +[scriptable, uuid(C98B7275-93C4-4EAD-B7CF-573D872C1071)] interface nsIDOMWindowUtils : nsISupports { /** * Image animation mode of the window. When this attribute's value * is changed, the implementation should set all images in the window * to the given value. That is, when set to kDontAnimMode, all images * will stop animating. The attribute's value must be one of the * animationMode values from imgIContainer. @@ -199,18 +199,17 @@ interface nsIDOMWindowUtils : nsISupport const long MODIFIER_CAPSLOCK = 0x0020; const long MODIFIER_FN = 0x0040; const long MODIFIER_NUMLOCK = 0x0080; const long MODIFIER_SCROLLLOCK = 0x0100; const long MODIFIER_SYMBOLLOCK = 0x0200; const long MODIFIER_OS = 0x0400; /** Synthesize a mouse event. The event types supported are: - * mousedown, mouseup, mousemove, mouseover, mouseout, contextmenu, - * MozMouseHitTest + * mousedown, mouseup, mousemove, mouseover, mouseout, contextmenu * * Events are sent in coordinates offset by aX and aY from the window. * * Note that additional events may be fired as a result of this call. For * instance, typically a click event will be fired as a result of a * mousedown and mouseup in sequence. * * Normally at this level of events, the mouseover and mouseout events are @@ -232,28 +231,26 @@ interface nsIDOMWindowUtils : nsISupport * @param aButton button to synthesize * @param aClickCount number of clicks that have been performed * @param aModifiers modifiers pressed, using constants defined as MODIFIER_* * @param aIgnoreRootScrollFrame whether the event should ignore viewport bounds * during dispatch * @param aPressure touch input pressure: 0.0 -> 1.0 * @param aInputSourceArg input source, see nsIDOMMouseEvent for values, * defaults to mouse input. - * - * returns true if the page called prevent default on this event */ - boolean sendMouseEvent(in AString aType, - in float aX, - in float aY, - in long aButton, - in long aClickCount, - in long aModifiers, - [optional] in boolean aIgnoreRootScrollFrame, - [optional] in float aPressure, - [optional] in unsigned short aInputSourceArg); + void sendMouseEvent(in AString aType, + in float aX, + in float aY, + in long aButton, + in long aClickCount, + in long aModifiers, + [optional] in boolean aIgnoreRootScrollFrame, + [optional] in float aPressure, + [optional] in unsigned short aInputSourceArg); /** Synthesize a touch event. The event types supported are: * touchstart, touchend, touchmove, and touchcancel * * Events are sent in coordinates offset by aX and aY from the window. * * Cannot be accessed from unprivileged context (not content-accessible) * Will throw a DOM security error if called without UniversalXPConnect
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1271,19 +1271,18 @@ TabChild::RecvMouseEvent(const nsString& const float& aY, const int32_t& aButton, const int32_t& aClickCount, const int32_t& aModifiers, const bool& aIgnoreRootScrollFrame) { nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils()); NS_ENSURE_TRUE(utils, true); - bool ignored = false; utils->SendMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers, - aIgnoreRootScrollFrame, 0, 0, &ignored); + aIgnoreRootScrollFrame, 0, 0); return true; } bool TabChild::RecvRealMouseEvent(const nsMouseEvent& event) { nsMouseEvent localEvent(event); DispatchWidgetEvent(localEvent);
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -201,23 +201,21 @@ function _parseModifiers(aEvent) * * aEvent is an object which may contain the properties: * shiftKey, ctrlKey, altKey, metaKey, accessKey, clickCount, button, type * * If the type is specified, an mouse event of that type is fired. Otherwise, * a mousedown followed by a mouse up is performed. * * aWindow is optional, and defaults to the current window object. - * - * Returns whether the event had preventDefault() called on it. */ function synthesizeMouse(aTarget, aOffsetX, aOffsetY, aEvent, aWindow) { var rect = aTarget.getBoundingClientRect(); - return synthesizeMouseAtPoint(rect.left + aOffsetX, rect.top + aOffsetY, + synthesizeMouseAtPoint(rect.left + aOffsetX, rect.top + aOffsetY, aEvent, aWindow); } function synthesizeTouch(aTarget, aOffsetX, aOffsetY, aEvent, aWindow) { var rect = aTarget.getBoundingClientRect(); synthesizeTouchAtPoint(rect.left + aOffsetX, rect.top + aOffsetY, aEvent, aWindow); } @@ -231,33 +229,30 @@ function synthesizeTouch(aTarget, aOffse * If the type is specified, an mouse event of that type is fired. Otherwise, * a mousedown followed by a mouse up is performed. * * aWindow is optional, and defaults to the current window object. */ function synthesizeMouseAtPoint(left, top, aEvent, aWindow) { var utils = _getDOMWindowUtils(aWindow); - var defaultPrevented = false; if (utils) { var button = aEvent.button || 0; var clickCount = aEvent.clickCount || 1; var modifiers = _parseModifiers(aEvent); if (("type" in aEvent) && aEvent.type) { - defaultPrevented = utils.sendMouseEvent(aEvent.type, left, top, button, clickCount, modifiers); + utils.sendMouseEvent(aEvent.type, left, top, button, clickCount, modifiers); } else { utils.sendMouseEvent("mousedown", left, top, button, clickCount, modifiers); utils.sendMouseEvent("mouseup", left, top, button, clickCount, modifiers); } } - - return defaultPrevented; } function synthesizeTouchAtPoint(left, top, aEvent, aWindow) { var utils = _getDOMWindowUtils(aWindow); if (utils) { var id = aEvent.id || 0; var rx = aEvent.rx || 1;
--- a/toolkit/content/WindowDraggingUtils.jsm +++ b/toolkit/content/WindowDraggingUtils.jsm @@ -1,24 +1,18 @@ /* 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/. */ -#ifdef XP_WIN -#define USE_HITTEST -#elifdef MOZ_WIDGET_COCOA -#define USE_HITTEST -#endif - this.EXPORTED_SYMBOLS = [ "WindowDraggingElement" ]; this.WindowDraggingElement = function WindowDraggingElement(elem) { this._elem = elem; this._window = elem.ownerDocument.defaultView; -#ifdef USE_HITTEST +#ifdef XP_WIN if (!this.isPanel()) this._elem.addEventListener("MozMouseHittest", this, false); else #endif this._elem.addEventListener("mousedown", this, false); }; WindowDraggingElement.prototype = { @@ -55,17 +49,17 @@ WindowDraggingElement.prototype = { return true; }, isPanel : function() { return this._elem instanceof Components.interfaces.nsIDOMXULElement && this._elem.localName == "panel"; }, handleEvent: function(aEvent) { let isPanel = this.isPanel(); -#ifdef USE_HITTEST +#ifdef XP_WIN if (!isPanel) { if (this.shouldDrag(aEvent)) aEvent.preventDefault(); return; } #endif switch (aEvent.type) {
--- a/toolkit/content/tests/chrome/window_titlebar.xul +++ b/toolkit/content/tests/chrome/window_titlebar.xul @@ -47,16 +47,17 @@ <label id="panellabelfloating" value="Titlebar"/> </titlebar> </panel> <button id="button" label="OK"/> <statusbar id="statusbar"> <statusbarpanel> <label id="statuslabel" value="Status"/> + <label id="statuslabelnodrag" value="No Drag" onmousedown="event.preventDefault()"/> </statusbarpanel> </statusbar> <script> <![CDATA[ var SimpleTest = window.opener.wrappedJSObject.SimpleTest; @@ -100,28 +101,36 @@ function waitForWindowMove(element, x, y } } function test_titlebar() { var titlebar = document.getElementById("titlebar"); var label = document.getElementById("label"); - // On Mac, the window can also be moved with the statusbar, but this works - // via the MozMouseHittest event, not via mouse events. + // on Mac, the window can also be moved with the statusbar if (navigator.platform.indexOf("Mac") >= 0) { - var preventDefaulted; - var statuslabel = document.getElementById("statuslabel"); - preventDefaulted = synthesizeMouse(statuslabel, 2, 2, { type: "MozMouseHittest" }); - SimpleTest.ok(preventDefaulted, "MozMouseHittest should have been defaultPrevented over statusbar"); + var statuslabelnodrag = document.getElementById("statuslabelnodrag"); + + origoldx = window.screenX; + origoldy = window.screenY; - var button = document.getElementById("button"); - preventDefaulted = synthesizeMouse(button, 2, 2, { type: "MozMouseHittest" }); - SimpleTest.ok(!preventDefaulted, "MozMouseHittest should NOT have been defaultPrevented over button"); + synthesizeMouse(statuslabel, 2, 2, { type: "mousedown" }); + synthesizeMouse(statuslabel, 22, 22, { type: "mousemove" }); + SimpleTest.is(window.screenX, origoldx + 20, "move window with statusbar horizontal"); + SimpleTest.is(window.screenY, origoldy + 20, "move window with statusbar vertical"); + synthesizeMouse(statuslabel, 22, 22, { type: "mouseup" }); + + // event was cancelled so the drag should not have occurred + synthesizeMouse(statuslabelnodrag, 2, 2, { type: "mousedown" }); + synthesizeMouse(statuslabelnodrag, 22, 22, { type: "mousemove" }); + SimpleTest.is(window.screenX, origoldx + 20, "move window with statusbar cancelled mousedown horizontal"); + SimpleTest.is(window.screenY, origoldy + 20, "move window with statusbar cancelled mousedown vertical"); + synthesizeMouse(statuslabelnodrag, 22, 22, { type: "mouseup" }); } origoldx = window.screenX; origoldy = window.screenY; var mousedownListener = function (event) mouseDownTarget = event.originalTarget; window.addEventListener("mousedown", mousedownListener, false); synthesizeMouse(label, 2, 2, { type: "mousedown" });
--- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -178,20 +178,16 @@ typedef NSInteger NSEventGestureAxis; // automatically firing momentum scroll events. @interface NSEvent (ScrollPhase) // Leopard and SnowLeopard - (long long)_scrollPhase; // Lion and above - (NSEventPhase)momentumPhase; @end -@protocol EventRedirection - - (NSView*)targetView; -@end - @interface ChildView : NSView< #ifdef ACCESSIBILITY mozAccessible, #endif mozView, NSTextInput> { @private // the nsChildView that created the view. It retains this NSView, so @@ -266,29 +262,25 @@ typedef NSInteger NSEventGestureAxis; // Whether this uses off-main-thread compositing. BOOL mUsingOMTCompositor; } // class initialization + (void)initialize; -+ (void)registerViewForDraggedTypes:(NSView*)aView; - // these are sent to the first responder when the window key status changes - (void)viewsWindowDidBecomeKey; - (void)viewsWindowDidResignKey; // Stop NSView hierarchy being changed during [ChildView drawRect:] - (void)delayedTearDown; - (void)sendFocusEvent:(uint32_t)eventType; -- (void)updateWindowDraggableStateOnMouseMove:(NSEvent*)theEvent; - - (void)handleMouseMoved:(NSEvent*)aEvent; - (void)drawRect:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext; - (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent enter:(BOOL)aEnter type:(nsMouseEvent::exitType)aType;
--- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1907,30 +1907,16 @@ NSEvent* gLastDragMouseDownEvent = nil; [sendTypes release]; [returnTypes release]; initialized = YES; } } -+ (void)registerViewForDraggedTypes:(NSView*)aView -{ - [aView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, - NSStringPboardType, - NSHTMLPboardType, - NSURLPboardType, - NSFilesPromisePboardType, - kWildcardPboardType, - kCorePboardType_url, - kCorePboardType_urld, - kCorePboardType_urln, - nil]]; -} - // initWithFrame:geckoChild: - (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; if ((self = [super initWithFrame:inFrame])) { mGeckoChild = inChild; mIsPluginView = NO; @@ -1968,18 +1954,27 @@ NSEvent* gLastDragMouseDownEvent = nil; [self setFocusRingType:NSFocusRingTypeNone]; #ifdef __LP64__ mSwipeAnimationCancelled = nil; #endif } // register for things we'll take from other applications - [ChildView registerViewForDraggedTypes:self]; - + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView initWithFrame: registering drag types\n")); + [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, + NSStringPboardType, + NSHTMLPboardType, + NSURLPboardType, + NSFilesPromisePboardType, + kWildcardPboardType, + kCorePboardType_url, + kCorePboardType_urld, + kCorePboardType_urln, + nil]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowBecameMain:) name:NSWindowDidBecomeMainNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowResignedMain:) name:NSWindowDidResignMainNotification object:nil]; @@ -2339,17 +2334,17 @@ NSEvent* gLastDragMouseDownEvent = nil; } [super scrollRect:aRect by:offset]; NS_OBJC_END_TRY_ABORT_BLOCK; } - (BOOL)mouseDownCanMoveWindow { - return [[self window] isMovableByWindowBackground]; + return NO; } - (void)lockFocus { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; [super lockFocus]; @@ -3285,35 +3280,16 @@ NSEvent* gLastDragMouseDownEvent = nil; } event.exit = aType; nsEventStatus status; // ignored mGeckoChild->DispatchEvent(&event, status); } -- (void)updateWindowDraggableStateOnMouseMove:(NSEvent*)theEvent -{ - if (!theEvent || !mGeckoChild) { - return; - } - - nsCocoaWindow* windowWidget = mGeckoChild->GetXULWindowWidget(); - if (!windowWidget) { - return; - } - - // We assume later on that sending a hit test event won't cause widget destruction. - nsMouseEvent hitTestEvent(true, NS_MOUSE_MOZHITTEST, mGeckoChild, nsMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&hitTestEvent]; - bool result = mGeckoChild->DispatchWindowEvent(hitTestEvent); - - [windowWidget->GetCocoaWindow() setMovableByWindowBackground:result]; -} - - (void)handleMouseMoved:(NSEvent*)theEvent { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; if (!mGeckoChild) return; nsMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGeckoChild, nsMouseEvent::eReal); @@ -4828,21 +4804,16 @@ ChildView* ChildViewMouseTracker::ViewForEvent(NSEvent* aEvent) { NSWindow* window = sWindowUnderMouse; if (!window) return nil; NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, window); NSView* view = [[[window contentView] superview] hitTest:windowEventLocation]; - - while([view conformsToProtocol:@protocol(EventRedirection)]) { - view = [(id<EventRedirection>)view targetView]; - } - if (![view isKindOfClass:[ChildView class]]) return nil; ChildView* childView = (ChildView*)view; // If childView is being destroyed return nil. if (![childView widget]) return nil; return WindowAcceptsEvent(window, aEvent, childView) ? childView : nil; @@ -4931,17 +4902,17 @@ ChildViewMouseTracker::WindowAcceptsEven // triggers bmo bugs 431902 and 476393. So here we make sure that a // ToolbarWindow's contentView always returns NO from the // mouseDownCanMoveWindow method. - (BOOL)nsChildView_NSView_mouseDownCanMoveWindow { NSWindow *ourWindow = [self window]; NSView *contentView = [ourWindow contentView]; if ([ourWindow isKindOfClass:[ToolbarWindow class]] && (self == contentView)) - return [ourWindow isMovableByWindowBackground]; + return NO; return [self nsChildView_NSView_mouseDownCanMoveWindow]; } @end #ifdef __LP64__ // When using blocks, at least on OS X 10.7, the OS sometimes calls // +[NSEvent removeMonitor:] more than once on a single event monitor, which
--- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -13,17 +13,16 @@ #include "nsBaseWidget.h" #include "nsPIWidgetCocoa.h" #include "nsAutoPtr.h" #include "nsCocoaUtils.h" class nsCocoaWindow; class nsChildView; class nsMenuBarX; -@class ChildView; // Value copied from BITMAP_MAX_AREA, used in nsNativeThemeCocoa.mm #define CUIDRAW_MAX_AREA 500000 // If we are using an SDK older than 10.7, define bits we need that are missing // from it. #if !defined(MAC_OS_X_VERSION_10_7) || \ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 @@ -172,28 +171,26 @@ typedef struct _nsCocoaWindowList { @end // NSWindow subclass for handling windows with toolbars. @interface ToolbarWindow : BaseWindow { TitlebarAndBackgroundColor *mColor; float mUnifiedToolbarHeight; NSColor *mBackgroundColor; - NSView *mTitlebarView; // strong } // Pass nil here to get the default appearance. - (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive; - (void)setUnifiedToolbarHeight:(float)aHeight; - (float)unifiedToolbarHeight; - (float)titlebarHeight; - (NSRect)titlebarRect; - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync; - (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect; - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; -- (ChildView*)mainChildView; @end class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa { private: typedef nsBaseWidget Inherited;
--- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -442,20 +442,16 @@ nsresult nsCocoaWindow::CreateNativeWind [mWindow setHasShadow:YES]; } [mWindow setBackgroundColor:[NSColor clearColor]]; [mWindow setOpaque:NO]; [mWindow setContentMinSize:NSMakeSize(60, 60)]; [mWindow disableCursorRects]; - // Make sure the window starts out not draggable by the background. - // We will turn it on as necessary. - [mWindow setMovableByWindowBackground:NO]; - [[WindowDataMap sharedWindowDataMap] ensureDataForWindow:mWindow]; mWindowMadeHere = true; return NS_OK; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } @@ -2582,104 +2578,17 @@ static const NSString* kStateShowsToolba retval = [NSArray arrayWithArray:holder]; } return retval; } @end -@interface TitlebarMouseHandlingView : NSView<EventRedirection> -{ - ToolbarWindow* mWindow; // weak - BOOL mProcessingRightMouseDown; -} - -- (id)initWithWindow:(ToolbarWindow*)aWindow; -@end - -@implementation TitlebarMouseHandlingView - -- (id)initWithWindow:(ToolbarWindow*)aWindow -{ - if ((self = [super initWithFrame:[aWindow titlebarRect]])) { - mWindow = aWindow; - [self setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; - [ChildView registerViewForDraggedTypes:self]; - mProcessingRightMouseDown = NO; - } - return self; -} - -- (NSView*)targetView -{ - return [mWindow mainChildView]; -} - -- (BOOL)mouseDownCanMoveWindow -{ - return [mWindow isMovableByWindowBackground]; -} - -// We redirect many types of events to the window's mainChildView simply by -// passing the event object to the respective handler method. We don't need any -// coordinate transformations because event coordinates are relative to the -// window. -// We only need to handle event types whose target NSView is determined by the -// event's position. We don't need to handle key events and NSMouseMoved events -// because those are only sent to the window's first responder. This view -// doesn't override acceptsFirstResponder, so it will never receive those kinds -// of events. - -- (void)mouseMoved:(NSEvent*)aEvent { [[self targetView] mouseMoved:aEvent]; } -- (void)mouseDown:(NSEvent*)aEvent { [[self targetView] mouseDown:aEvent]; } -- (void)mouseUp:(NSEvent*)aEvent { [[self targetView] mouseUp:aEvent]; } -- (void)mouseDragged:(NSEvent*)aEvent { [[self targetView] mouseDragged:aEvent]; } -- (void)rightMouseDown:(NSEvent*)aEvent -{ - // To avoid recursion... - if (mProcessingRightMouseDown) - return; - mProcessingRightMouseDown = YES; - [[self targetView] rightMouseDown:aEvent]; - mProcessingRightMouseDown = NO; -} -- (void)rightMouseUp:(NSEvent*)aEvent { [[self targetView] rightMouseUp:aEvent]; } -- (void)rightMouseDragged:(NSEvent*)aEvent { [[self targetView] rightMouseDragged:aEvent]; } -- (void)otherMouseDown:(NSEvent*)aEvent { [[self targetView] otherMouseDown:aEvent]; } -- (void)otherMouseUp:(NSEvent*)aEvent { [[self targetView] otherMouseUp:aEvent]; } -- (void)otherMouseDragged:(NSEvent*)aEvent { [[self targetView] otherMouseDragged:aEvent]; } -- (void)scrollWheel:(NSEvent*)aEvent { [[self targetView] scrollWheel:aEvent]; } -- (void)swipeWithEvent:(NSEvent*)aEvent { [[self targetView] swipeWithEvent:aEvent]; } -- (void)beginGestureWithEvent:(NSEvent*)aEvent { [[self targetView] beginGestureWithEvent:aEvent]; } -- (void)magnifyWithEvent:(NSEvent*)aEvent { [[self targetView] magnifyWithEvent:aEvent]; } -- (void)rotateWithEvent:(NSEvent*)aEvent { [[self targetView] rotateWithEvent:aEvent]; } -- (void)endGestureWithEvent:(NSEvent*)aEvent { [[self targetView] endGestureWithEvent:aEvent]; } -- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender - { return [[self targetView] draggingEntered:sender]; } -- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender - { return [[self targetView] draggingUpdated:sender]; } -- (void)draggingExited:(id <NSDraggingInfo>)sender - { [[self targetView] draggingExited:sender]; } -- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender - { return [[self targetView] performDragOperation:sender]; } -- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation - { [[self targetView] draggedImage:anImage endedAt:aPoint operation:operation]; } -- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal - { return [[self targetView] draggingSourceOperationMaskForLocal:isLocal]; } -- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDestination - { return [[self targetView] namesOfPromisedFilesDroppedAtDestination:dropDestination]; } -- (NSMenu*)menuForEvent:(NSEvent*)aEvent - { return [[self targetView] menuForEvent:aEvent]; } - -@end - -// This class allows us to exercise control over the window's title bar. This -// allows for a "unified toolbar" look, and for extending the content area into -// the title bar. It works like this: +// This class allows us to have a "unified toolbar" style window. It works like this: // 1) We set the window's style to textured. // 2) Because of this, the background color applies to the entire window, including // the titlebar area. For normal textured windows, the default pattern is a // "brushed metal" image on Tiger and a unified gradient on Leopard. // 3) We set the background color to a custom NSColor subclass that knows how tall the window is. // When -set is called on it, it sets a pattern (with a draw callback) as the fill. In that callback, // it paints the the titlebar and background colors in the correct areas of the context it's given, // which will fill the entire window (CG will tile it horizontally for us). @@ -2703,21 +2612,16 @@ static const NSString* kStateShowsToolba // // Whenever the unified gradient is drawn in the titlebar or the toolbar, both // titlebar height and toolbar height must be known in order to construct the // correct gradient (which is a linear gradient with the length // titlebarHeight + toolbarHeight - 1). But you can only get from the toolbar frame // to the containing window - the other direction doesn't work. That's why the // toolbar height is cached in the ToolbarWindow but nsNativeThemeCocoa can simply // query the window for its titlebar height when drawing the toolbar. -@interface ToolbarWindow(Private) -- (void)installTitlebarMouseHandlingView; -- (void)uninstallTitlebarMouseHandlingView; -@end; - @implementation ToolbarWindow - (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; aStyle = aStyle | NSTexturedBackgroundWindowMask; if ((self = [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag])) { @@ -2742,17 +2646,16 @@ static const NSString* kStateShowsToolba } - (void)dealloc { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; [mColor release]; [mBackgroundColor release]; - [mTitlebarView release]; [super dealloc]; NS_OBJC_END_TRY_ABORT_BLOCK; } - (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive { [super setTitlebarColor:aColor forActiveWindow:aActive]; @@ -2822,101 +2725,39 @@ static const NSString* kStateShowsToolba [self setContentBorderThickness:mUnifiedToolbarHeight forEdge:NSMaxYEdge]; // Redraw the title bar. If we're inside painting, we'll do it right now, // otherwise we'll just invalidate it. BOOL needSyncRedraw = ([NSView focusView] != nil); [self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:needSyncRedraw]; } -// Extending the content area into the title bar works by redirection of both -// drawing and mouse events. -// The window's NSView hierarchy looks like this: -// - border view ([[window contentView] superview]) -// - transparent title bar event redirection view -// - window controls (traffic light buttons) -// - content view ([window contentView], default NSView provided by the window) -// - our main Gecko ChildView ([window mainChildView]), which has an -// OpenGL context attached to it when accelerated -// - possibly more ChildViews for plugins -// -// When the window is in title bar extension mode, the mainChildView covers the -// whole window but is only visible in the content area of the window, because -// it's a subview of the window's contentView and thus clipped to its dimensions. -// This clipping is a good thing because it avoids a few problems. For example, -// if the mainChildView weren't clipped and thus visible in the titlebar, we'd -// have have to do the rounded corner masking and the drawing of the highlight -// line ourselves. -// This would be especially hard in combination with OpenGL acceleration since -// rounded corners would require making the OpenGL context transparent, which -// would bring another set of challenges with it. Having the window controls -// draw on top of an OpenGL context could be hard, too. -// -// So title bar drawing happens in the border view. The border view's drawRect -// method is not under our control, but we can get it to call into our code -// using some tricks, see the TitlebarAndBackgroundColor class below. -// Specifically, we have it call the TitlebarDrawCallback function, which -// draws the contents of mainChildView into the provided CGContext. -// (Even if the ChildView uses OpenGL for rendering, drawing in the title bar -// will happen non-accelerated in that CGContext.) -// -// Mouse event redirection happens via a TitlebarMouseHandlingView which we -// install below. - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState { BOOL stateChanged = ([self drawsContentsIntoWindowFrame] != aState); [super setDrawsContentsIntoWindowFrame:aState]; if (stateChanged && [[self delegate] isKindOfClass:[WindowDelegate class]]) { - // Here we extend / shrink our mainChildView. We do that by firing a resize - // event which will cause the ChildView to be resized to the rect returned - // by nsCocoaWindow::GetClientBounds. GetClientBounds bases its return - // value on what we return from drawsContentsIntoWindowFrame. 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(); - if (aState) { - [self installTitlebarMouseHandlingView]; - } else { - [self uninstallTitlebarMouseHandlingView]; - } + [self setTitlebarNeedsDisplayInRect:[self titlebarRect]]; } } -- (void)installTitlebarMouseHandlingView -{ - mTitlebarView = [[TitlebarMouseHandlingView alloc] initWithWindow:self]; - [[[self contentView] superview] addSubview:mTitlebarView positioned:NSWindowBelow relativeTo:nil]; -} - -- (void)uninstallTitlebarMouseHandlingView -{ - [mTitlebarView removeFromSuperview]; - [mTitlebarView release]; - mTitlebarView = nil; -} - -- (ChildView*)mainChildView -{ - NSView* view = [[[self contentView] subviews] lastObject]; - if (view && [view isKindOfClass:[ChildView class]]) - return (ChildView*)view; - return nil; -} - // Returning YES here makes the setShowsToolbarButton method work even though // the window doesn't contain an NSToolbar. - (BOOL)_hasToolbar { return YES; } // Dispatch a toolbar pill button clicked message to Gecko. @@ -2975,19 +2816,16 @@ static const NSString* kStateShowsToolba { // Drop all mouse events if a modal window has appeared above us. // This helps make us behave as if the OS were running a "real" modal // event loop. id delegate = [self delegate]; if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) { nsCocoaWindow *widget = [(WindowDelegate *)delegate geckoWidget]; if (widget) { - if (type == NSMouseMoved) { - [[self mainChildView] updateWindowDraggableStateOnMouseMove:anEvent]; - } if (gGeckoAppModalWindowList && (widget != gGeckoAppModalWindowList->window)) return; if (widget->HasModalDescendents()) return; } } break; } @@ -3043,29 +2881,29 @@ DrawNativeTitlebar(CGContextRef aContext // Pattern draw callback for standard titlebar gradients and solid titlebar colors static void TitlebarDrawCallback(void* aInfo, CGContextRef aContext) { ToolbarWindow *window = (ToolbarWindow*)aInfo; NSRect titlebarRect = [window titlebarRect]; if ([window drawsContentsIntoWindowFrame]) { - ChildView* view = [window mainChildView]; - if (!view) + NSView* view = [[[window contentView] subviews] lastObject]; + if (!view || ![view isKindOfClass:[ChildView class]]) return; // Gecko drawing assumes flippedness, but the current context isn't flipped // (because we're painting into the window's border view, which is not a // ChildView, so it isn't flipped). // So we need to set a flip transform. CGContextScaleCTM(aContext, 1.0f, -1.0f); CGContextTranslateCTM(aContext, 0.0f, -[window frame].size.height); NSRect flippedTitlebarRect = { NSZeroPoint, titlebarRect.size }; - [view drawRect:flippedTitlebarRect inTitlebarContext:aContext]; + [(ChildView*)view drawRect:flippedTitlebarRect inTitlebarContext:aContext]; } else { BOOL isMain = [window isMainWindow]; NSColor *titlebarColor = [window titlebarColorForActiveWindow:isMain]; if (!titlebarColor) { // If the titlebar color is nil, draw the default titlebar shading. DrawNativeTitlebar(aContext, NSRectToCGRect(titlebarRect), [window unifiedToolbarHeight], isMain); } else {