~ubuntu-branches/ubuntu/precise/firefox/precise-proposed

« back to all changes in this revision

Viewing changes to debian/globalmenu/components/src/uGlobalMenuDocListener.cpp

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2012-04-02 08:30:28 UTC
  • Revision ID: package-import@ubuntu.com-20120402083028-430x8nc65vivx0ne
Tags: 11.0+build1-0ubuntu2
* Update globalmenu-extension to 3.0.1
  - Reduce our memory footprint a bit, which wasn't really a lot anyway
  - Avoid the use of the component manager for accessing commonly used
    services, where "commonly used" means "accessed when building every
    menu item". This should save some CPU cycles when building or
    refreshing menus
  - Try to recycle menuitems when they are removed from a menu by
    adding contiguous blocks of removed items to a "free list" which
    is emptied asynchronously, and reusing the items in this list when
    new items are added in place of the removed items. This means that
    refreshing the history menu contents when the menu is opened no
    longer alters the menu structure, but results in a shifting of
    properties between existing nodes instead. This has a few benefits:
    + With no layout changes, unity-panel-service doesn't request
      the entire menu structure, which significantly reduces dbus traffic
      and makes it much faster to refresh the menu contents
    + The size of the menu doesn't change when it is refreshed, which
      eliminates the flicker that used to occur when opening the history
      menu.
    + The HUD can refresh our menus now without triggering layout updates
      (assuming that menu layout really hasn't changed, eg, by adding
      a bookmark)
  - Remove all use of the global observer service for sending our own
    internal notifications around
  - Clean up the way we ensure that the correct edit commands are
    enabled by just installing our own popupshowing handler rather
    than using an additional notification to fix things up after the
    default handler runs
  - Get rid of a static initializer
  - Don't support older than Firefox 11
  - Fix some GError leaks
  - Hide the internal menu when creating a native menu, rather than
    waiting for confirmation that the native menu is registered
    successfully. We don't try to create a native menu if we don't
    find a menu service to register the menu with anyway
  - Keep menu contents updated whilst the menu is open, rather than
    just whilst it is opening

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
 
/* ***** BEGIN LICENSE BLOCK *****
3
 
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
 
 *
5
 
 * The contents of this file are subject to the Mozilla Public License Version
6
 
 * 1.1 (the "License"); you may not use this file except in compliance with
7
 
 * the License. You may obtain a copy of the License at
8
 
 * http://www.mozilla.org/MPL/
9
 
 *
10
 
 * Software distributed under the License is distributed on an "AS IS" basis,
11
 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
 
 * for the specific language governing rights and limitations under the
13
 
 * License.
14
 
 *
15
 
 * The Original Code is mozilla.org code.
16
 
 *
17
 
 * The Initial Developer of the Original Code is
18
 
 * Netscape Communications Corporation.
19
 
 * Portions created by the Initial Developer are Copyright (C) 1998
20
 
 * the Initial Developer. All Rights Reserved.
21
 
 *
22
 
 * Contributor(s):
23
 
 *   Josh Aas <josh@mozilla.com>
24
 
 *   Thomas K. Dyas <tom.dyas@gmail.com>
25
 
 *   Chris Coulson <chris.coulson@canonical.com>
26
 
 *
27
 
 * Alternatively, the contents of this file may be used under the terms of
28
 
 * either the GNU General Public License Version 2 or later (the "GPL"), or
29
 
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
 
 * in which case the provisions of the GPL or the LGPL are applicable instead
31
 
 * of those above. If you wish to allow use of your version of this file only
32
 
 * under the terms of either the GPL or the LGPL, and not to allow others to
33
 
 * use your version of this file under the terms of the MPL, indicate your
34
 
 * decision by deleting the provisions above and replace them with the notice
35
 
 * and other provisions required by the GPL or the LGPL. If you do not delete
36
 
 * the provisions above, a recipient may use your version of this file under
37
 
 * the terms of any one of the MPL, the GPL or the LGPL.
38
 
 *
39
 
 * ***** END LICENSE BLOCK ***** */
40
 
 
41
 
#include <prtypes.h>
42
 
#include <nsIDocument.h>
43
 
#include <nsIAtom.h>
44
 
#include <nsINode.h>
45
 
#include <mozilla/dom/Element.h>
46
 
#include <nsIContent.h>
47
 
#include <nsIDocument.h>
48
 
 
49
 
#include "uGlobalMenuDocListener.h"
50
 
 
51
 
#include "uDebug.h"
52
 
 
53
 
NS_IMPL_ISUPPORTS1(uGlobalMenuDocListener, nsIMutationObserver)
54
 
 
55
 
nsresult
56
 
uGlobalMenuDocListener::Init(nsIContent *rootNode)
57
 
{
58
 
  NS_ENSURE_ARG(rootNode);
59
 
 
60
 
#if MOZILLA_BRANCH_MAJOR_VERSION >= 10
61
 
  mDocument = rootNode->OwnerDoc();
62
 
#else
63
 
  mDocument = rootNode->GetOwnerDoc();
64
 
#endif
65
 
  if (!mDocument)
66
 
    return NS_ERROR_FAILURE;
67
 
  mDocument->AddMutationObserver(this);
68
 
 
69
 
  return NS_OK;
70
 
}
71
 
 
72
 
void
73
 
uGlobalMenuDocListener::Destroy()
74
 
{
75
 
  if (mDocument) {
76
 
    mDocument->RemoveMutationObserver(this);
77
 
  }
78
 
}
79
 
 
80
 
uGlobalMenuDocListener::uGlobalMenuDocListener() :
81
 
#ifdef DEBUG_chrisccoulson
82
 
  mCount(0),
83
 
#endif
84
 
  mDocument(nsnull)
85
 
{
86
 
  mContentToObserverTable.Init();
87
 
}
88
 
 
89
 
uGlobalMenuDocListener::~uGlobalMenuDocListener()
90
 
{
91
 
  NS_ASSERTION(mCount == 0, "Some nodes forgot to unregister listeners");
92
 
}
93
 
 
94
 
void
95
 
uGlobalMenuDocListener::CharacterDataWillChange(nsIDocument *aDocument,
96
 
                                                nsIContent *aContent,
97
 
                                                CharacterDataChangeInfo *aInfo)
98
 
{
99
 
 
100
 
}
101
 
 
102
 
void
103
 
uGlobalMenuDocListener::CharacterDataChanged(nsIDocument *aDocument,
104
 
                                             nsIContent *aContent,
105
 
                                             CharacterDataChangeInfo *aInfo)
106
 
{
107
 
 
108
 
}
109
 
 
110
 
void
111
 
uGlobalMenuDocListener::AttributeWillChange(nsIDocument *aDocument,
112
 
                                            mozilla::dom::Element *aElement,
113
 
                                            PRInt32 aNameSpaceID,
114
 
                                            nsIAtom *aAttribute,
115
 
                                            PRInt32 aModType)
116
 
{
117
 
 
118
 
}
119
 
 
120
 
void
121
 
uGlobalMenuDocListener::AttributeChanged(nsIDocument *aDocument,
122
 
                                         mozilla::dom::Element *aElement,
123
 
                                         PRInt32 aNameSpaceID,
124
 
                                         nsIAtom *aAttribute,
125
 
                                         PRInt32 aModType)
126
 
{
127
 
  if (!aElement)
128
 
    return;
129
 
 
130
 
  nsTArray<uMenuChangeObserver *> listeners;
131
 
  GetListeners(aElement, listeners);
132
 
 
133
 
  for (PRUint32 i = 0; i < listeners.Length(); i++) {
134
 
    listeners[i]->ObserveAttributeChanged(aDocument, aElement, aAttribute);
135
 
  }
136
 
}
137
 
 
138
 
void
139
 
uGlobalMenuDocListener::ContentAppended(nsIDocument *aDocument,
140
 
                                        nsIContent *aContainer,
141
 
                                        nsIContent *aFirstNewContent,
142
 
                                        PRInt32 aNewIndexInContainer)
143
 
{
144
 
  for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
145
 
    ContentInserted(aDocument, aContainer, cur, aNewIndexInContainer);
146
 
    aNewIndexInContainer++;
147
 
  }
148
 
}
149
 
 
150
 
void
151
 
uGlobalMenuDocListener::ContentInserted(nsIDocument *aDocument,
152
 
                                        nsIContent *aContainer,
153
 
                                        nsIContent *aChild,
154
 
                                        PRInt32 aIndexInContainer)
155
 
{
156
 
  if (!aContainer)
157
 
    return;
158
 
 
159
 
  nsTArray<uMenuChangeObserver *> listeners;
160
 
  GetListeners(aContainer, listeners);
161
 
 
162
 
  for (PRUint32 i = 0; i < listeners.Length(); i++) {
163
 
    listeners[i]->ObserveContentInserted(aDocument, aContainer, aChild,
164
 
                                         aIndexInContainer);
165
 
  }
166
 
 
167
 
  if (listeners.Length() == 0) {
168
 
    for (PRUint32 i = 0; i < mGlobalObservers.Length(); i++) {
169
 
      mGlobalObservers[i]->ObserveContentInserted(aDocument, aContainer,
170
 
                                                  aChild, aIndexInContainer);
171
 
    }
172
 
  }
173
 
}
174
 
 
175
 
void
176
 
uGlobalMenuDocListener::ContentRemoved(nsIDocument *aDocument,
177
 
                                       nsIContent *aContainer,
178
 
                                       nsIContent *aChild,
179
 
                                       PRInt32 aIndexInContainer,
180
 
                                       nsIContent *aPreviousSibling)
181
 
{
182
 
  if (!aContainer)
183
 
    return;
184
 
 
185
 
  nsTArray<uMenuChangeObserver *> listeners;
186
 
  GetListeners(aContainer, listeners);
187
 
 
188
 
  for (PRUint32 i = 0; i < listeners.Length(); i++) {
189
 
    listeners[i]->ObserveContentRemoved(aDocument, aContainer, aChild,
190
 
                                        aIndexInContainer);
191
 
  }
192
 
 
193
 
  if (listeners.Length() == 0) {
194
 
    for (PRUint32 i = 0; i < mGlobalObservers.Length(); i++) {
195
 
      mGlobalObservers[i]->ObserveContentRemoved(aDocument, aContainer, aChild,
196
 
                                                 aIndexInContainer);
197
 
    }
198
 
  }
199
 
}
200
 
 
201
 
void
202
 
uGlobalMenuDocListener::NodeWillBeDestroyed(const nsINode *aNode)
203
 
{
204
 
  mDocument = nsnull;
205
 
}
206
 
 
207
 
void
208
 
uGlobalMenuDocListener::ParentChainChanged(nsIContent *aContent)
209
 
{
210
 
 
211
 
}
212
 
 
213
 
nsresult
214
 
uGlobalMenuDocListener::RegisterForContentChanges(nsIContent *aContent,
215
 
                                                  uMenuChangeObserver *aMenuObject)
216
 
{
217
 
  NS_ENSURE_ARG(aContent);
218
 
  NS_ENSURE_ARG(aMenuObject);
219
 
 
220
 
  nsTArray<uMenuChangeObserver *> *listeners;
221
 
  if (!mContentToObserverTable.Get(aContent, &listeners)) {
222
 
    listeners = new nsTArray<uMenuChangeObserver *>();
223
 
    mContentToObserverTable.Put(aContent, listeners);
224
 
  }
225
 
 
226
 
  for (PRUint32 i = 0; i < listeners->Length(); i++) {
227
 
    if (listeners->ElementAt(i) == aMenuObject) {
228
 
      return NS_ERROR_FAILURE;
229
 
    }
230
 
  }
231
 
 
232
 
  listeners->AppendElement(aMenuObject);
233
 
#ifdef DEBUG_chrisccoulson
234
 
  mCount++;
235
 
#endif
236
 
  return NS_OK;
237
 
}
238
 
 
239
 
nsresult
240
 
uGlobalMenuDocListener::UnregisterForContentChanges(nsIContent *aContent,
241
 
                                                    uMenuChangeObserver *aMenuObject)
242
 
{
243
 
  NS_ENSURE_ARG(aContent);
244
 
  NS_ENSURE_ARG(aMenuObject);
245
 
 
246
 
  nsTArray<uMenuChangeObserver *> *listeners;
247
 
  if (!mContentToObserverTable.Get(aContent, &listeners)) {
248
 
    return NS_ERROR_FAILURE;
249
 
  }
250
 
 
251
 
  PRUint32 length = listeners->Length();
252
 
  for (PRUint32 i = 0; i < length; i++) {
253
 
    if (listeners->ElementAt(i) == aMenuObject) {
254
 
      listeners->RemoveElementAt(i);
255
 
#ifdef DEBUG_chrisccoulson
256
 
      mCount--;
257
 
#endif
258
 
    }
259
 
  }
260
 
 
261
 
  nsresult rv = listeners->Length() < length ? NS_OK : NS_ERROR_FAILURE;
262
 
 
263
 
  if (listeners->Length() == 0) {
264
 
    mContentToObserverTable.Remove(aContent);
265
 
  }
266
 
 
267
 
  return rv;
268
 
}
269
 
 
270
 
nsresult
271
 
uGlobalMenuDocListener::RegisterForAllChanges(uMenuChangeObserver *aMenuObject)
272
 
{
273
 
  NS_ENSURE_ARG(aMenuObject);
274
 
 
275
 
  PRUint32 count = mGlobalObservers.Length();
276
 
  for (PRUint32 i = 0; i < count; i ++) {
277
 
    if (mGlobalObservers[i] == aMenuObject) {
278
 
      // Don't add more than once
279
 
      return NS_ERROR_FAILURE;
280
 
    }
281
 
  }
282
 
 
283
 
  mGlobalObservers.AppendElement(aMenuObject);
284
 
  return NS_OK;
285
 
}
286
 
 
287
 
nsresult
288
 
uGlobalMenuDocListener::UnregisterForAllChanges(uMenuChangeObserver *aMenuObject)
289
 
{
290
 
  NS_ENSURE_ARG(aMenuObject);
291
 
 
292
 
  PRUint32 count = mGlobalObservers.Length();
293
 
  for (PRUint32 i = 0; i < count; i++) {
294
 
    if (mGlobalObservers[i] == aMenuObject) {
295
 
      mGlobalObservers.RemoveElementAt(i);
296
 
      return NS_OK;
297
 
    }
298
 
  }
299
 
 
300
 
  return NS_ERROR_FAILURE;
301
 
}
302
 
 
303
 
void
304
 
uGlobalMenuDocListener::GetListeners(nsIContent *aContent,
305
 
                                     nsTArray<uMenuChangeObserver *>& _result)
306
 
{
307
 
  nsTArray<uMenuChangeObserver *> *listeners;
308
 
  if (mContentToObserverTable.Get(aContent, &listeners)) {
309
 
    _result.ReplaceElementsAt(0, _result.Length(), listeners->Elements(),
310
 
                              listeners->Length());
311
 
  }
312
 
}