michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsTitleBarFrame.h" michael@0: #include "nsIContent.h" michael@0: #include "nsIDocument.h" michael@0: #include "nsIDOMNodeList.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsIWidget.h" michael@0: #include "nsMenuPopupFrame.h" michael@0: #include "nsPresContext.h" michael@0: #include "nsIDocShell.h" michael@0: #include "nsPIDOMWindow.h" michael@0: #include "nsDisplayList.h" michael@0: #include "nsContentUtils.h" michael@0: #include "mozilla/MouseEvents.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: // michael@0: // NS_NewTitleBarFrame michael@0: // michael@0: // Creates a new TitleBar frame and returns it michael@0: // michael@0: nsIFrame* michael@0: NS_NewTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) michael@0: { michael@0: return new (aPresShell) nsTitleBarFrame(aPresShell, aContext); michael@0: } michael@0: michael@0: NS_IMPL_FRAMEARENA_HELPERS(nsTitleBarFrame) michael@0: michael@0: nsTitleBarFrame::nsTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) michael@0: :nsBoxFrame(aPresShell, aContext, false) michael@0: { michael@0: mTrackingMouseMove = false; michael@0: UpdateMouseThrough(); michael@0: } michael@0: michael@0: void michael@0: nsTitleBarFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) michael@0: { michael@0: // override, since we don't want children to get events michael@0: if (aBuilder->IsForEventDelivery()) { michael@0: if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents, michael@0: nsGkAtoms::_true, eCaseMatters)) michael@0: return; michael@0: } michael@0: nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists); michael@0: } michael@0: michael@0: nsresult michael@0: nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aEventStatus); michael@0: if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: bool doDefault = true; michael@0: michael@0: switch (aEvent->message) { michael@0: michael@0: case NS_MOUSE_BUTTON_DOWN: { michael@0: if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) { michael@0: // titlebar has no effect in non-chrome shells michael@0: nsCOMPtr dsti = aPresContext->GetDocShell(); michael@0: if (dsti) { michael@0: if (dsti->ItemType() == nsIDocShellTreeItem::typeChrome) { michael@0: // we're tracking. michael@0: mTrackingMouseMove = true; michael@0: michael@0: // start capture. michael@0: nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED); michael@0: michael@0: // remember current mouse coordinates. michael@0: mLastPoint = LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint); michael@0: } michael@0: } michael@0: michael@0: *aEventStatus = nsEventStatus_eConsumeNoDefault; michael@0: doDefault = false; michael@0: } michael@0: } michael@0: break; michael@0: michael@0: michael@0: case NS_MOUSE_BUTTON_UP: { michael@0: if (mTrackingMouseMove && michael@0: aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) { michael@0: // we're done tracking. michael@0: mTrackingMouseMove = false; michael@0: michael@0: // end capture michael@0: nsIPresShell::SetCapturingContent(nullptr, 0); michael@0: michael@0: *aEventStatus = nsEventStatus_eConsumeNoDefault; michael@0: doDefault = false; michael@0: } michael@0: } michael@0: break; michael@0: michael@0: case NS_MOUSE_MOVE: { michael@0: if(mTrackingMouseMove) michael@0: { michael@0: nsIntPoint nsMoveBy = LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint) - mLastPoint; michael@0: michael@0: nsIFrame* parent = GetParent(); michael@0: while (parent) { michael@0: nsMenuPopupFrame* popupFrame = do_QueryFrame(parent); michael@0: if (popupFrame) michael@0: break; michael@0: parent = parent->GetParent(); michael@0: } michael@0: michael@0: // if the titlebar is in a popup, move the popup frame, otherwise michael@0: // move the widget associated with the window michael@0: if (parent) { michael@0: nsMenuPopupFrame* menuPopupFrame = static_cast(parent); michael@0: nsCOMPtr widget = menuPopupFrame->GetWidget(); michael@0: nsIntRect bounds; michael@0: widget->GetScreenBounds(bounds); michael@0: michael@0: int32_t newx = aPresContext->DevPixelsToIntCSSPixels(bounds.x + nsMoveBy.x); michael@0: int32_t newy = aPresContext->DevPixelsToIntCSSPixels(bounds.y + nsMoveBy.y); michael@0: menuPopupFrame->MoveTo(newx, newy, false); michael@0: } michael@0: else { michael@0: nsIPresShell* presShell = aPresContext->PresShell(); michael@0: nsPIDOMWindow *window = presShell->GetDocument()->GetWindow(); michael@0: if (window) { michael@0: window->MoveBy(nsMoveBy.x, nsMoveBy.y); michael@0: } michael@0: } michael@0: michael@0: *aEventStatus = nsEventStatus_eConsumeNoDefault; michael@0: michael@0: doDefault = false; michael@0: } michael@0: } michael@0: break; michael@0: michael@0: case NS_MOUSE_CLICK: { michael@0: WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent(); michael@0: if (mouseEvent->IsLeftClickEvent()) { michael@0: MouseClicked(aPresContext, mouseEvent); michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: michael@0: if ( doDefault ) michael@0: return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus); michael@0: else michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsTitleBarFrame::MouseClicked(nsPresContext* aPresContext, michael@0: WidgetMouseEvent* aEvent) michael@0: { michael@0: // Execute the oncommand event handler. michael@0: nsContentUtils::DispatchXULCommand(mContent, michael@0: aEvent && aEvent->mFlags.mIsTrusted); michael@0: }