Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsCOMPtr.h"
7 #include "nsTitleBarFrame.h"
8 #include "nsIContent.h"
9 #include "nsIDocument.h"
10 #include "nsIDOMNodeList.h"
11 #include "nsGkAtoms.h"
12 #include "nsIWidget.h"
13 #include "nsMenuPopupFrame.h"
14 #include "nsPresContext.h"
15 #include "nsIDocShell.h"
16 #include "nsPIDOMWindow.h"
17 #include "nsDisplayList.h"
18 #include "nsContentUtils.h"
19 #include "mozilla/MouseEvents.h"
21 using namespace mozilla;
23 //
24 // NS_NewTitleBarFrame
25 //
26 // Creates a new TitleBar frame and returns it
27 //
28 nsIFrame*
29 NS_NewTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
30 {
31 return new (aPresShell) nsTitleBarFrame(aPresShell, aContext);
32 }
34 NS_IMPL_FRAMEARENA_HELPERS(nsTitleBarFrame)
36 nsTitleBarFrame::nsTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
37 :nsBoxFrame(aPresShell, aContext, false)
38 {
39 mTrackingMouseMove = false;
40 UpdateMouseThrough();
41 }
43 void
44 nsTitleBarFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
45 const nsRect& aDirtyRect,
46 const nsDisplayListSet& aLists)
47 {
48 // override, since we don't want children to get events
49 if (aBuilder->IsForEventDelivery()) {
50 if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
51 nsGkAtoms::_true, eCaseMatters))
52 return;
53 }
54 nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
55 }
57 nsresult
58 nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
59 WidgetGUIEvent* aEvent,
60 nsEventStatus* aEventStatus)
61 {
62 NS_ENSURE_ARG_POINTER(aEventStatus);
63 if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
64 return NS_OK;
65 }
67 bool doDefault = true;
69 switch (aEvent->message) {
71 case NS_MOUSE_BUTTON_DOWN: {
72 if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
73 // titlebar has no effect in non-chrome shells
74 nsCOMPtr<nsIDocShellTreeItem> dsti = aPresContext->GetDocShell();
75 if (dsti) {
76 if (dsti->ItemType() == nsIDocShellTreeItem::typeChrome) {
77 // we're tracking.
78 mTrackingMouseMove = true;
80 // start capture.
81 nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
83 // remember current mouse coordinates.
84 mLastPoint = LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint);
85 }
86 }
88 *aEventStatus = nsEventStatus_eConsumeNoDefault;
89 doDefault = false;
90 }
91 }
92 break;
95 case NS_MOUSE_BUTTON_UP: {
96 if (mTrackingMouseMove &&
97 aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
98 // we're done tracking.
99 mTrackingMouseMove = false;
101 // end capture
102 nsIPresShell::SetCapturingContent(nullptr, 0);
104 *aEventStatus = nsEventStatus_eConsumeNoDefault;
105 doDefault = false;
106 }
107 }
108 break;
110 case NS_MOUSE_MOVE: {
111 if(mTrackingMouseMove)
112 {
113 nsIntPoint nsMoveBy = LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint) - mLastPoint;
115 nsIFrame* parent = GetParent();
116 while (parent) {
117 nsMenuPopupFrame* popupFrame = do_QueryFrame(parent);
118 if (popupFrame)
119 break;
120 parent = parent->GetParent();
121 }
123 // if the titlebar is in a popup, move the popup frame, otherwise
124 // move the widget associated with the window
125 if (parent) {
126 nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame*>(parent);
127 nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
128 nsIntRect bounds;
129 widget->GetScreenBounds(bounds);
131 int32_t newx = aPresContext->DevPixelsToIntCSSPixels(bounds.x + nsMoveBy.x);
132 int32_t newy = aPresContext->DevPixelsToIntCSSPixels(bounds.y + nsMoveBy.y);
133 menuPopupFrame->MoveTo(newx, newy, false);
134 }
135 else {
136 nsIPresShell* presShell = aPresContext->PresShell();
137 nsPIDOMWindow *window = presShell->GetDocument()->GetWindow();
138 if (window) {
139 window->MoveBy(nsMoveBy.x, nsMoveBy.y);
140 }
141 }
143 *aEventStatus = nsEventStatus_eConsumeNoDefault;
145 doDefault = false;
146 }
147 }
148 break;
150 case NS_MOUSE_CLICK: {
151 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
152 if (mouseEvent->IsLeftClickEvent()) {
153 MouseClicked(aPresContext, mouseEvent);
154 }
155 break;
156 }
157 }
159 if ( doDefault )
160 return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
161 else
162 return NS_OK;
163 }
165 void
166 nsTitleBarFrame::MouseClicked(nsPresContext* aPresContext,
167 WidgetMouseEvent* aEvent)
168 {
169 // Execute the oncommand event handler.
170 nsContentUtils::DispatchXULCommand(mContent,
171 aEvent && aEvent->mFlags.mIsTrusted);
172 }