123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- /* -*- 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 "nsNameSpaceManager.h"
- #include "nsPresContext.h"
- #include "nsIPresShell.h"
- #include "nsIDOMElement.h"
- #include "nsIDOMEvent.h"
- #include "nsDisplayList.h"
- #include "nsContentUtils.h"
- #include "mozilla/dom/Element.h"
- #include "mozilla/EventStateManager.h"
- #include "mozilla/EventStates.h"
- #include "mozilla/MouseEvents.h"
- #include "mozilla/TextEvents.h"
- using namespace mozilla;
- NS_IMPL_ISUPPORTS(nsButtonBoxFrame::nsButtonBoxListener, nsIDOMEventListener)
- nsresult
- nsButtonBoxFrame::nsButtonBoxListener::HandleEvent(nsIDOMEvent* aEvent)
- {
- if (!mButtonBoxFrame) {
- return NS_OK;
- }
- nsAutoString eventType;
- aEvent->GetType(eventType);
- if (eventType.EqualsLiteral("blur")) {
- mButtonBoxFrame->Blurred();
- return NS_OK;
- }
- NS_ABORT();
- return NS_OK;
- }
- //
- // NS_NewXULButtonFrame
- //
- // Creates a new Button frame and returns it
- //
- nsIFrame*
- NS_NewButtonBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
- {
- return new (aPresShell) nsButtonBoxFrame(aContext);
- }
- NS_IMPL_FRAMEARENA_HELPERS(nsButtonBoxFrame)
- nsButtonBoxFrame::nsButtonBoxFrame(nsStyleContext* aContext) :
- nsBoxFrame(aContext, false),
- mButtonBoxListener(nullptr),
- mIsHandlingKeyEvent(false)
- {
- UpdateMouseThrough();
- }
- void
- nsButtonBoxFrame::Init(nsIContent* aContent,
- nsContainerFrame* aParent,
- nsIFrame* aPrevInFlow)
- {
- nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
- mButtonBoxListener = new nsButtonBoxListener(this);
- mContent->AddSystemEventListener(NS_LITERAL_STRING("blur"), mButtonBoxListener, false);
- }
- void
- nsButtonBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
- {
- mContent->RemoveSystemEventListener(NS_LITERAL_STRING("blur"), mButtonBoxListener, false);
- mButtonBoxListener->mButtonBoxFrame = nullptr;
- mButtonBoxListener = nullptr;
- nsBoxFrame::DestroyFrom(aDestructRoot);
- }
- void
- nsButtonBoxFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists)
- {
- // override, since we don't want children to get events
- if (aBuilder->IsForEventDelivery())
- return;
- nsBoxFrame::BuildDisplayListForChildren(aBuilder, aLists);
- }
- nsresult
- nsButtonBoxFrame::HandleEvent(nsPresContext* aPresContext,
- WidgetGUIEvent* aEvent,
- nsEventStatus* aEventStatus)
- {
- NS_ENSURE_ARG_POINTER(aEventStatus);
- if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
- return NS_OK;
- }
- switch (aEvent->mMessage) {
- case eKeyDown: {
- WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
- if (!keyEvent) {
- break;
- }
- if (NS_VK_SPACE == keyEvent->mKeyCode) {
- EventStateManager* esm = aPresContext->EventStateManager();
- // :hover:active state
- esm->SetContentState(mContent, NS_EVENT_STATE_HOVER);
- esm->SetContentState(mContent, NS_EVENT_STATE_ACTIVE);
- mIsHandlingKeyEvent = true;
- }
- break;
- }
- case eKeyPress: {
- WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
- if (!keyEvent) {
- break;
- }
- if (NS_VK_RETURN == keyEvent->mKeyCode) {
- nsCOMPtr<nsIDOMXULButtonElement> buttonEl(do_QueryInterface(mContent));
- if (buttonEl) {
- MouseClicked(aEvent);
- *aEventStatus = nsEventStatus_eConsumeNoDefault;
- }
- }
- break;
- }
- case eKeyUp: {
- WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
- if (!keyEvent) {
- break;
- }
- if (NS_VK_SPACE == keyEvent->mKeyCode) {
- mIsHandlingKeyEvent = false;
- // only activate on keyup if we're already in the :hover:active state
- NS_ASSERTION(mContent->IsElement(), "How do we have a non-element?");
- EventStates buttonState = mContent->AsElement()->State();
- if (buttonState.HasAllStates(NS_EVENT_STATE_ACTIVE |
- NS_EVENT_STATE_HOVER)) {
- // return to normal state
- EventStateManager* esm = aPresContext->EventStateManager();
- esm->SetContentState(nullptr, NS_EVENT_STATE_ACTIVE);
- esm->SetContentState(nullptr, NS_EVENT_STATE_HOVER);
- MouseClicked(aEvent);
- }
- }
- break;
- }
- case eMouseClick: {
- WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
- if (mouseEvent->IsLeftClickEvent()) {
- MouseClicked(mouseEvent);
- }
- break;
- }
- default:
- break;
- }
- return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
- }
- void
- nsButtonBoxFrame::Blurred()
- {
- NS_ASSERTION(mContent->IsElement(), "How do we have a non-element?");
- EventStates buttonState = mContent->AsElement()->State();
- if (mIsHandlingKeyEvent &&
- buttonState.HasAllStates(NS_EVENT_STATE_ACTIVE |
- NS_EVENT_STATE_HOVER)) {
- // return to normal state
- EventStateManager* esm = PresContext()->EventStateManager();
- esm->SetContentState(nullptr, NS_EVENT_STATE_ACTIVE);
- esm->SetContentState(nullptr, NS_EVENT_STATE_HOVER);
- }
- mIsHandlingKeyEvent = false;
- }
- void
- nsButtonBoxFrame::DoMouseClick(WidgetGUIEvent* 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) {
- WidgetInputEvent* inputEvent = aEvent->AsInputEvent();
- isShift = inputEvent->IsShift();
- isControl = inputEvent->IsControl();
- isAlt = inputEvent->IsAlt();
- isMeta = inputEvent->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->IsTrusted() : aTrustEvent,
- nullptr, shell,
- isControl, isAlt, isShift, isMeta);
- }
- }
|