1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "XULMenuBarElement.h"
8 #include "MenuBarListener.h"
9 #include "XULButtonElement.h"
10 #include "nsXULPopupManager.h"
11 #include "mozilla/Assertions.h"
12 #include "mozilla/dom/BindContext.h"
13 #include "mozilla/AsyncEventDispatcher.h"
15 namespace mozilla::dom
{
17 NS_IMPL_CYCLE_COLLECTION_CLASS(XULMenuBarElement
)
18 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULMenuBarElement
,
21 tmp
->mListener
->Detach();
22 tmp
->mListener
= nullptr;
24 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULMenuBarElement
,
27 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListener
)
28 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
29 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(XULMenuBarElement
,
32 XULMenuBarElement::XULMenuBarElement(
33 already_AddRefed
<class NodeInfo
>&& aNodeInfo
)
34 : XULMenuParentElement(std::move(aNodeInfo
)) {}
36 XULMenuBarElement::~XULMenuBarElement() { MOZ_DIAGNOSTIC_ASSERT(!mListener
); }
38 void XULMenuBarElement::SetActive(bool aActiveFlag
) {
39 // If the activity is not changed, there is nothing to do.
40 if (mIsActive
== aActiveFlag
) {
44 // We can't activate a menubar outside of the document.
45 if (!IsInComposedDoc()) {
46 MOZ_ASSERT(!mIsActive
, "How?");
51 // If there is a request to deactivate the menu bar, check to see whether
52 // there is a menu popup open for the menu bar. In this case, don't
53 // deactivate the menu bar.
54 if (auto* activeChild
= GetActiveMenuChild()) {
55 if (activeChild
->IsMenuPopupOpen()) {
61 mIsActive
= aActiveFlag
;
62 if (nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance()) {
63 pm
->SetActiveMenuBar(this, aActiveFlag
);
66 mActiveByKeyboard
= false;
67 SetActiveMenuChild(nullptr);
70 RefPtr dispatcher
= new AsyncEventDispatcher(
71 this, aActiveFlag
? u
"DOMMenuBarActive"_ns
: u
"DOMMenuBarInactive"_ns
,
72 CanBubble::eYes
, ChromeOnlyDispatch::eNo
);
73 DebugOnly
<nsresult
> rv
= dispatcher
->PostDOMEvent();
74 NS_ASSERTION(NS_SUCCEEDED(rv
), "AsyncEventDispatcher failed to dispatch");
77 nsresult
XULMenuBarElement::BindToTree(BindContext
& aContext
,
79 MOZ_TRY(XULMenuParentElement::BindToTree(aContext
, aParent
));
80 MOZ_DIAGNOSTIC_ASSERT(!mListener
);
81 if (aContext
.InComposedDoc()) {
82 mListener
= new MenuBarListener(*this);
87 void XULMenuBarElement::UnbindFromTree(bool aNullParent
) {
92 if (NS_WARN_IF(mIsActive
)) {
93 // Clean up silently when getting removed from the document while active.
95 if (nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance()) {
96 pm
->SetActiveMenuBar(this, false);
99 return XULMenuParentElement::UnbindFromTree(aNullParent
);
102 } // namespace mozilla::dom