Line data Source code
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/. */
5 :
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"
20 :
21 : using namespace mozilla;
22 :
23 : //
24 : // NS_NewTitleBarFrame
25 : //
26 : // Creates a new TitleBar frame and returns it
27 : //
28 : nsIFrame*
29 0 : NS_NewTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
30 : {
31 0 : return new (aPresShell) nsTitleBarFrame(aContext);
32 : }
33 :
34 0 : NS_IMPL_FRAMEARENA_HELPERS(nsTitleBarFrame)
35 :
36 0 : nsTitleBarFrame::nsTitleBarFrame(nsStyleContext* aContext, ClassID aID)
37 0 : : nsBoxFrame(aContext, aID, false)
38 : {
39 0 : mTrackingMouseMove = false;
40 0 : UpdateMouseThrough();
41 0 : }
42 :
43 : void
44 0 : 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 0 : if (aBuilder->IsForEventDelivery()) {
50 0 : if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
51 : nsGkAtoms::_true, eCaseMatters))
52 0 : return;
53 : }
54 0 : nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
55 : }
56 :
57 : nsresult
58 0 : nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
59 : WidgetGUIEvent* aEvent,
60 : nsEventStatus* aEventStatus)
61 : {
62 0 : NS_ENSURE_ARG_POINTER(aEventStatus);
63 0 : if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
64 0 : return NS_OK;
65 : }
66 :
67 0 : bool doDefault = true;
68 :
69 0 : switch (aEvent->mMessage) {
70 :
71 : case eMouseDown: {
72 0 : if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
73 : // titlebar has no effect in non-chrome shells
74 0 : nsCOMPtr<nsIDocShellTreeItem> dsti = aPresContext->GetDocShell();
75 0 : if (dsti) {
76 0 : if (dsti->ItemType() == nsIDocShellTreeItem::typeChrome) {
77 : // we're tracking.
78 0 : mTrackingMouseMove = true;
79 :
80 : // start capture.
81 0 : nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
82 :
83 : // remember current mouse coordinates.
84 0 : mLastPoint = aEvent->mRefPoint;
85 : }
86 : }
87 :
88 0 : *aEventStatus = nsEventStatus_eConsumeNoDefault;
89 0 : doDefault = false;
90 : }
91 : }
92 0 : break;
93 :
94 :
95 : case eMouseUp: {
96 0 : if (mTrackingMouseMove &&
97 0 : aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
98 : // we're done tracking.
99 0 : mTrackingMouseMove = false;
100 :
101 : // end capture
102 0 : nsIPresShell::SetCapturingContent(nullptr, 0);
103 :
104 0 : *aEventStatus = nsEventStatus_eConsumeNoDefault;
105 0 : doDefault = false;
106 : }
107 : }
108 0 : break;
109 :
110 : case eMouseMove: {
111 0 : if(mTrackingMouseMove)
112 : {
113 0 : LayoutDeviceIntPoint nsMoveBy = aEvent->mRefPoint - mLastPoint;
114 :
115 0 : nsIFrame* parent = GetParent();
116 0 : while (parent) {
117 0 : nsMenuPopupFrame* popupFrame = do_QueryFrame(parent);
118 0 : if (popupFrame)
119 0 : break;
120 0 : parent = parent->GetParent();
121 : }
122 :
123 : // if the titlebar is in a popup, move the popup frame, otherwise
124 : // move the widget associated with the window
125 0 : if (parent) {
126 0 : nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame*>(parent);
127 0 : nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
128 0 : LayoutDeviceIntRect bounds = widget->GetScreenBounds();
129 :
130 0 : CSSPoint cssPos = (bounds.TopLeft() + nsMoveBy)
131 0 : / aPresContext->CSSToDevPixelScale();
132 0 : menuPopupFrame->MoveTo(RoundedToInt(cssPos), false);
133 : }
134 : else {
135 0 : nsIPresShell* presShell = aPresContext->PresShell();
136 0 : nsPIDOMWindowOuter *window = presShell->GetDocument()->GetWindow();
137 0 : if (window) {
138 0 : window->MoveBy(nsMoveBy.x, nsMoveBy.y);
139 : }
140 : }
141 :
142 0 : *aEventStatus = nsEventStatus_eConsumeNoDefault;
143 :
144 0 : doDefault = false;
145 : }
146 : }
147 0 : break;
148 :
149 : case eMouseClick: {
150 0 : WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
151 0 : if (mouseEvent->IsLeftClickEvent()) {
152 0 : MouseClicked(mouseEvent);
153 : }
154 0 : break;
155 : }
156 :
157 : default:
158 0 : break;
159 : }
160 :
161 0 : if ( doDefault )
162 0 : return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
163 : else
164 0 : return NS_OK;
165 : }
166 :
167 : void
168 0 : nsTitleBarFrame::MouseClicked(WidgetMouseEvent* aEvent)
169 : {
170 : // Execute the oncommand event handler.
171 0 : nsContentUtils::DispatchXULCommand(mContent, aEvent && aEvent->IsTrusted());
172 0 : }
|