forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 2
/
nsButtonBoxFrame.cpp
143 lines (130 loc) · 4.78 KB
/
nsButtonBoxFrame.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsCOMPtr.h"
#include "nsButtonBoxFrame.h"
#include "nsIContent.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULButtonElement.h"
#include "nsGkAtoms.h"
#include "nsINameSpaceManager.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
#include "nsGUIEvent.h"
#include "nsEventStateManager.h"
#include "nsIDOMElement.h"
#include "nsDisplayList.h"
#include "nsContentUtils.h"
#include "mozilla/dom/Element.h"
//
// NS_NewXULButtonFrame
//
// Creates a new Button frame and returns it
//
nsIFrame*
NS_NewButtonBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsButtonBoxFrame(aPresShell, aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsButtonBoxFrame)
void
nsButtonBoxFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// override, since we don't want children to get events
if (aBuilder->IsForEventDelivery())
return;
nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
}
NS_IMETHODIMP
nsButtonBoxFrame::HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
return NS_OK;
}
switch (aEvent->message) {
case NS_KEY_DOWN:
if (NS_KEY_EVENT == aEvent->eventStructType) {
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
if (NS_VK_SPACE == keyEvent->keyCode) {
nsEventStateManager *esm = aPresContext->EventStateManager();
// :hover:active state
esm->SetContentState(mContent, NS_EVENT_STATE_HOVER);
esm->SetContentState(mContent, NS_EVENT_STATE_ACTIVE);
}
}
break;
// On mac, Return fires the defualt button, not the focused one.
#ifndef XP_MACOSX
case NS_KEY_PRESS:
if (NS_KEY_EVENT == aEvent->eventStructType) {
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
if (NS_VK_RETURN == keyEvent->keyCode) {
nsCOMPtr<nsIDOMXULButtonElement> buttonEl(do_QueryInterface(mContent));
if (buttonEl) {
MouseClicked(aPresContext, aEvent);
*aEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
break;
#endif
case NS_KEY_UP:
if (NS_KEY_EVENT == aEvent->eventStructType) {
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
if (NS_VK_SPACE == keyEvent->keyCode) {
// only activate on keyup if we're already in the :hover:active state
NS_ASSERTION(mContent->IsElement(), "How do we have a non-element?");
nsEventStates buttonState = mContent->AsElement()->State();
if (buttonState.HasAllStates(NS_EVENT_STATE_ACTIVE |
NS_EVENT_STATE_HOVER)) {
// return to normal state
nsEventStateManager *esm = aPresContext->EventStateManager();
esm->SetContentState(nullptr, NS_EVENT_STATE_ACTIVE);
esm->SetContentState(nullptr, NS_EVENT_STATE_HOVER);
MouseClicked(aPresContext, aEvent);
}
}
}
break;
case NS_MOUSE_CLICK:
if (NS_IS_MOUSE_LEFT_CLICK(aEvent)) {
MouseClicked(aPresContext, aEvent);
}
break;
}
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
void
nsButtonBoxFrame::DoMouseClick(nsGUIEvent* aEvent, bool aTrustEvent)
{
// Don't execute if we're disabled.
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
nsGkAtoms::_true, eCaseMatters))
return;
// Execute the oncommand event handler.
bool isShift = false;
bool isControl = false;
bool isAlt = false;
bool isMeta = false;
if(aEvent) {
isShift = ((nsInputEvent*)(aEvent))->IsShift();
isControl = ((nsInputEvent*)(aEvent))->IsControl();
isAlt = ((nsInputEvent*)(aEvent))->IsAlt();
isMeta = ((nsInputEvent*)(aEvent))->IsMeta();
}
// Have the content handle the event, propagating it according to normal DOM rules.
nsCOMPtr<nsIPresShell> shell = PresContext()->GetPresShell();
if (shell) {
nsContentUtils::DispatchXULCommand(mContent,
aEvent ?
aEvent->mFlags.mIsTrusted : aTrustEvent,
nullptr, shell,
isControl, isAlt, isShift, isMeta);
}
}