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/. */
5 #include "nsCOMPtr.h"
6 #include "nsButtonBoxFrame.h"
7 #include "nsIContent.h"
8 #include "nsIDOMNodeList.h"
9 #include "nsIDOMXULButtonElement.h"
10 #include "nsGkAtoms.h"
11 #include "nsNameSpaceManager.h"
12 #include "nsPresContext.h"
13 #include "nsIPresShell.h"
14 #include "nsIDOMElement.h"
15 #include "nsDisplayList.h"
16 #include "nsContentUtils.h"
17 #include "mozilla/dom/Element.h"
18 #include "mozilla/EventStateManager.h"
19 #include "mozilla/EventStates.h"
20 #include "mozilla/MouseEvents.h"
21 #include "mozilla/TextEvents.h"
23 using namespace mozilla;
25 //
26 // NS_NewXULButtonFrame
27 //
28 // Creates a new Button frame and returns it
29 //
30 nsIFrame*
31 NS_NewButtonBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
32 {
33 return new (aPresShell) nsButtonBoxFrame(aPresShell, aContext);
34 }
36 NS_IMPL_FRAMEARENA_HELPERS(nsButtonBoxFrame)
38 void
39 nsButtonBoxFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
40 const nsRect& aDirtyRect,
41 const nsDisplayListSet& aLists)
42 {
43 // override, since we don't want children to get events
44 if (aBuilder->IsForEventDelivery())
45 return;
46 nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
47 }
49 nsresult
50 nsButtonBoxFrame::HandleEvent(nsPresContext* aPresContext,
51 WidgetGUIEvent* aEvent,
52 nsEventStatus* aEventStatus)
53 {
54 NS_ENSURE_ARG_POINTER(aEventStatus);
55 if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
56 return NS_OK;
57 }
59 switch (aEvent->message) {
60 case NS_KEY_DOWN: {
61 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
62 if (!keyEvent) {
63 break;
64 }
65 if (NS_VK_SPACE == keyEvent->keyCode) {
66 EventStateManager* esm = aPresContext->EventStateManager();
67 // :hover:active state
68 esm->SetContentState(mContent, NS_EVENT_STATE_HOVER);
69 esm->SetContentState(mContent, NS_EVENT_STATE_ACTIVE);
70 }
71 break;
72 }
74 // On mac, Return fires the default button, not the focused one.
75 #ifndef XP_MACOSX
76 case NS_KEY_PRESS: {
77 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
78 if (!keyEvent) {
79 break;
80 }
81 if (NS_VK_RETURN == keyEvent->keyCode) {
82 nsCOMPtr<nsIDOMXULButtonElement> buttonEl(do_QueryInterface(mContent));
83 if (buttonEl) {
84 MouseClicked(aPresContext, aEvent);
85 *aEventStatus = nsEventStatus_eConsumeNoDefault;
86 }
87 }
88 break;
89 }
90 #endif
92 case NS_KEY_UP: {
93 WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
94 if (!keyEvent) {
95 break;
96 }
97 if (NS_VK_SPACE == keyEvent->keyCode) {
98 // only activate on keyup if we're already in the :hover:active state
99 NS_ASSERTION(mContent->IsElement(), "How do we have a non-element?");
100 EventStates buttonState = mContent->AsElement()->State();
101 if (buttonState.HasAllStates(NS_EVENT_STATE_ACTIVE |
102 NS_EVENT_STATE_HOVER)) {
103 // return to normal state
104 EventStateManager* esm = aPresContext->EventStateManager();
105 esm->SetContentState(nullptr, NS_EVENT_STATE_ACTIVE);
106 esm->SetContentState(nullptr, NS_EVENT_STATE_HOVER);
107 MouseClicked(aPresContext, aEvent);
108 }
109 }
110 break;
111 }
113 case NS_MOUSE_CLICK: {
114 WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
115 if (mouseEvent->IsLeftClickEvent()) {
116 MouseClicked(aPresContext, mouseEvent);
117 }
118 break;
119 }
120 }
122 return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
123 }
125 void
126 nsButtonBoxFrame::DoMouseClick(WidgetGUIEvent* aEvent, bool aTrustEvent)
127 {
128 // Don't execute if we're disabled.
129 if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
130 nsGkAtoms::_true, eCaseMatters))
131 return;
133 // Execute the oncommand event handler.
134 bool isShift = false;
135 bool isControl = false;
136 bool isAlt = false;
137 bool isMeta = false;
138 if(aEvent) {
139 WidgetInputEvent* inputEvent = aEvent->AsInputEvent();
140 isShift = inputEvent->IsShift();
141 isControl = inputEvent->IsControl();
142 isAlt = inputEvent->IsAlt();
143 isMeta = inputEvent->IsMeta();
144 }
146 // Have the content handle the event, propagating it according to normal DOM rules.
147 nsCOMPtr<nsIPresShell> shell = PresContext()->GetPresShell();
148 if (shell) {
149 nsContentUtils::DispatchXULCommand(mContent,
150 aEvent ?
151 aEvent->mFlags.mIsTrusted : aTrustEvent,
152 nullptr, shell,
153 isControl, isAlt, isShift, isMeta);
154 }
155 }