widget/cocoa/nsMenuGroupOwnerX.mm

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsMenuGroupOwnerX.h"
michael@0 7 #include "nsMenuBarX.h"
michael@0 8 #include "nsMenuX.h"
michael@0 9 #include "nsMenuItemX.h"
michael@0 10 #include "nsMenuUtilsX.h"
michael@0 11 #include "nsCocoaUtils.h"
michael@0 12 #include "nsCocoaWindow.h"
michael@0 13
michael@0 14 #include "nsCOMPtr.h"
michael@0 15 #include "nsString.h"
michael@0 16 #include "nsObjCExceptions.h"
michael@0 17 #include "nsThreadUtils.h"
michael@0 18
michael@0 19 #include "mozilla/dom/Element.h"
michael@0 20 #include "nsIWidget.h"
michael@0 21 #include "nsIDocument.h"
michael@0 22 #include "nsIDOMDocument.h"
michael@0 23 #include "nsIDOMElement.h"
michael@0 24
michael@0 25 #include "nsINode.h"
michael@0 26
michael@0 27 using namespace mozilla;
michael@0 28
michael@0 29 NS_IMPL_ISUPPORTS(nsMenuGroupOwnerX, nsIMutationObserver)
michael@0 30
michael@0 31
michael@0 32 nsMenuGroupOwnerX::nsMenuGroupOwnerX()
michael@0 33 : mCurrentCommandID(eCommand_ID_Last),
michael@0 34 mDocument(nullptr)
michael@0 35 {
michael@0 36 }
michael@0 37
michael@0 38
michael@0 39 nsMenuGroupOwnerX::~nsMenuGroupOwnerX()
michael@0 40 {
michael@0 41 // make sure we unregister ourselves as a document observer
michael@0 42 if (mDocument)
michael@0 43 mDocument->RemoveMutationObserver(this);
michael@0 44 }
michael@0 45
michael@0 46
michael@0 47 nsresult nsMenuGroupOwnerX::Create(nsIContent* aContent)
michael@0 48 {
michael@0 49 if (!aContent)
michael@0 50 return NS_ERROR_INVALID_ARG;
michael@0 51
michael@0 52 mContent = aContent;
michael@0 53
michael@0 54 nsIDocument* doc = aContent->OwnerDoc();
michael@0 55 if (!doc)
michael@0 56 return NS_ERROR_FAILURE;
michael@0 57 doc->AddMutationObserver(this);
michael@0 58 mDocument = doc;
michael@0 59
michael@0 60 return NS_OK;
michael@0 61 }
michael@0 62
michael@0 63
michael@0 64 //
michael@0 65 // nsIMutationObserver
michael@0 66 //
michael@0 67
michael@0 68
michael@0 69 void nsMenuGroupOwnerX::CharacterDataWillChange(nsIDocument* aDocument,
michael@0 70 nsIContent* aContent,
michael@0 71 CharacterDataChangeInfo* aInfo)
michael@0 72 {
michael@0 73 }
michael@0 74
michael@0 75
michael@0 76 void nsMenuGroupOwnerX::CharacterDataChanged(nsIDocument* aDocument,
michael@0 77 nsIContent* aContent,
michael@0 78 CharacterDataChangeInfo* aInfo)
michael@0 79 {
michael@0 80 }
michael@0 81
michael@0 82
michael@0 83 void nsMenuGroupOwnerX::ContentAppended(nsIDocument* aDocument,
michael@0 84 nsIContent* aContainer,
michael@0 85 nsIContent* aFirstNewContent,
michael@0 86 int32_t /* unused */)
michael@0 87 {
michael@0 88 for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
michael@0 89 ContentInserted(aDocument, aContainer, cur, 0);
michael@0 90 }
michael@0 91 }
michael@0 92
michael@0 93
michael@0 94 void nsMenuGroupOwnerX::NodeWillBeDestroyed(const nsINode * aNode)
michael@0 95 {
michael@0 96 // our menu bar node is being destroyed
michael@0 97 mDocument = nullptr;
michael@0 98 }
michael@0 99
michael@0 100
michael@0 101 void nsMenuGroupOwnerX::AttributeWillChange(nsIDocument* aDocument,
michael@0 102 dom::Element* aContent,
michael@0 103 int32_t aNameSpaceID,
michael@0 104 nsIAtom* aAttribute,
michael@0 105 int32_t aModType)
michael@0 106 {
michael@0 107 }
michael@0 108
michael@0 109
michael@0 110 void nsMenuGroupOwnerX::AttributeChanged(nsIDocument* aDocument,
michael@0 111 dom::Element* aElement,
michael@0 112 int32_t aNameSpaceID,
michael@0 113 nsIAtom* aAttribute,
michael@0 114 int32_t aModType)
michael@0 115 {
michael@0 116 nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
michael@0 117 nsChangeObserver* obs = LookupContentChangeObserver(aElement);
michael@0 118 if (obs)
michael@0 119 obs->ObserveAttributeChanged(aDocument, aElement, aAttribute);
michael@0 120 }
michael@0 121
michael@0 122
michael@0 123 void nsMenuGroupOwnerX::ContentRemoved(nsIDocument * aDocument,
michael@0 124 nsIContent * aContainer,
michael@0 125 nsIContent * aChild,
michael@0 126 int32_t aIndexInContainer,
michael@0 127 nsIContent * aPreviousSibling)
michael@0 128 {
michael@0 129 if (!aContainer) {
michael@0 130 return;
michael@0 131 }
michael@0 132
michael@0 133 nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
michael@0 134 nsChangeObserver* obs = LookupContentChangeObserver(aContainer);
michael@0 135 if (obs)
michael@0 136 obs->ObserveContentRemoved(aDocument, aChild, aIndexInContainer);
michael@0 137 else if (aContainer != mContent) {
michael@0 138 // We do a lookup on the parent container in case things were removed
michael@0 139 // under a "menupopup" item. That is basically a wrapper for the contents
michael@0 140 // of a "menu" node.
michael@0 141 nsCOMPtr<nsIContent> parent = aContainer->GetParent();
michael@0 142 if (parent) {
michael@0 143 obs = LookupContentChangeObserver(parent);
michael@0 144 if (obs)
michael@0 145 obs->ObserveContentRemoved(aDocument, aChild, aIndexInContainer);
michael@0 146 }
michael@0 147 }
michael@0 148 }
michael@0 149
michael@0 150
michael@0 151 void nsMenuGroupOwnerX::ContentInserted(nsIDocument * aDocument,
michael@0 152 nsIContent * aContainer,
michael@0 153 nsIContent * aChild,
michael@0 154 int32_t /* unused */)
michael@0 155 {
michael@0 156 if (!aContainer) {
michael@0 157 return;
michael@0 158 }
michael@0 159
michael@0 160 nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
michael@0 161 nsChangeObserver* obs = LookupContentChangeObserver(aContainer);
michael@0 162 if (obs)
michael@0 163 obs->ObserveContentInserted(aDocument, aContainer, aChild);
michael@0 164 else if (aContainer != mContent) {
michael@0 165 // We do a lookup on the parent container in case things were removed
michael@0 166 // under a "menupopup" item. That is basically a wrapper for the contents
michael@0 167 // of a "menu" node.
michael@0 168 nsCOMPtr<nsIContent> parent = aContainer->GetParent();
michael@0 169 if (parent) {
michael@0 170 obs = LookupContentChangeObserver(parent);
michael@0 171 if (obs)
michael@0 172 obs->ObserveContentInserted(aDocument, aContainer, aChild);
michael@0 173 }
michael@0 174 }
michael@0 175 }
michael@0 176
michael@0 177
michael@0 178 void nsMenuGroupOwnerX::ParentChainChanged(nsIContent *aContent)
michael@0 179 {
michael@0 180 }
michael@0 181
michael@0 182
michael@0 183 // For change management, we don't use a |nsSupportsHashtable| because
michael@0 184 // we know that the lifetime of all these items is bounded by the
michael@0 185 // lifetime of the menubar. No need to add any more strong refs to the
michael@0 186 // picture because the containment hierarchy already uses strong refs.
michael@0 187 void nsMenuGroupOwnerX::RegisterForContentChanges(nsIContent *aContent,
michael@0 188 nsChangeObserver *aMenuObject)
michael@0 189 {
michael@0 190 mContentToObserverTable.Put(aContent, aMenuObject);
michael@0 191 }
michael@0 192
michael@0 193
michael@0 194 void nsMenuGroupOwnerX::UnregisterForContentChanges(nsIContent *aContent)
michael@0 195 {
michael@0 196 mContentToObserverTable.Remove(aContent);
michael@0 197 }
michael@0 198
michael@0 199
michael@0 200 nsChangeObserver* nsMenuGroupOwnerX::LookupContentChangeObserver(nsIContent* aContent)
michael@0 201 {
michael@0 202 nsChangeObserver * result;
michael@0 203 if (mContentToObserverTable.Get(aContent, &result))
michael@0 204 return result;
michael@0 205 else
michael@0 206 return nullptr;
michael@0 207 }
michael@0 208
michael@0 209
michael@0 210 // Given a menu item, creates a unique 4-character command ID and
michael@0 211 // maps it to the item. Returns the id for use by the client.
michael@0 212 uint32_t nsMenuGroupOwnerX::RegisterForCommand(nsMenuItemX* inMenuItem)
michael@0 213 {
michael@0 214 // no real need to check for uniqueness. We always start afresh with each
michael@0 215 // window at 1. Even if we did get close to the reserved Apple command id's,
michael@0 216 // those don't start until at least ' ', which is integer 538976288. If
michael@0 217 // we have that many menu items in one window, I think we have other
michael@0 218 // problems.
michael@0 219
michael@0 220 // make id unique
michael@0 221 ++mCurrentCommandID;
michael@0 222
michael@0 223 mCommandToMenuObjectTable.Put(mCurrentCommandID, inMenuItem);
michael@0 224
michael@0 225 return mCurrentCommandID;
michael@0 226 }
michael@0 227
michael@0 228
michael@0 229 // Removes the mapping between the given 4-character command ID
michael@0 230 // and its associated menu item.
michael@0 231 void nsMenuGroupOwnerX::UnregisterCommand(uint32_t inCommandID)
michael@0 232 {
michael@0 233 mCommandToMenuObjectTable.Remove(inCommandID);
michael@0 234 }
michael@0 235
michael@0 236
michael@0 237 nsMenuItemX* nsMenuGroupOwnerX::GetMenuItemForCommandID(uint32_t inCommandID)
michael@0 238 {
michael@0 239 nsMenuItemX * result;
michael@0 240 if (mCommandToMenuObjectTable.Get(inCommandID, &result))
michael@0 241 return result;
michael@0 242 else
michael@0 243 return nullptr;
michael@0 244 }

mercurial