~mozillateam/thunderbird/thunderbird-beta.vivid

« back to all changes in this revision

Viewing changes to debian/globalmenu/src/uGlobalMenuBar.cpp

  • Committer: Chris Coulson
  • Date: 2013-04-02 22:59:42 UTC
  • Revision ID: chris.coulson@canonical.com-20130402225942-fdq9x5wmmhoedwc5
* New upstream release from the beta channel (THUNDERBIRD_21_0b1_BUILD1)
* Drop support for building on older than precise
  - update debian/apport/source_thunderbird.py.in
  - update debian/build/mozbuild.mk
  - update debian/config/mozconfig.in
  - update debian/control.in
  - remove debian/patches/add-syspref-dir.patch
  - update debian/patches/series.in
  - remove debian/patches/use-new-yasm-in-lucid.patch
  - update debian/rules
  - update debian/thunderbird-globalmenu.dirs.in
  - update debian/thunderbird.desktop.in
  - update debian/thunderbird.dirs.in
  - update debian/thunderbird.install.in
  - update debian/thunderbird.links.in
  - update debian/thunderbird.postinst.in
  - update debian/thunderbird.postrm.in
  - update debian/thunderbird.preinst.in
* Drop the perl script for preprocessing the quilt series file
  - remove debian/build/enable-dist-patches.pl
  - update debian/build/mozbuild.mk
  - update debian/patches/series.in
* Make sure that SHELL is set in the build environment
  - update debian/build/mozbuild.mk
* Don't set the MOZCONFIG environment variable, but just copy our config
  in to the root of the source tree
  - update debian/build/mozconfig.mk
* Drop libthai suggest - this hasn't been needed for a long time
  - update debian/control
* Replace latex-xft-fonts suggest with ttf-lyx (yes, I know this is a
  transitional package since 12.10, but it avoids suggesting a different
  package for each release)
  - update debian/control
* Use virtualenv for compare-locales
  - update debian/build/create-tarball.py
  - update debian/build/mozbuild.mk
* Refactor create-tarball.py
* Fix LP: #1093665 - 'Next' button icon points upwards. Thanks to
  Richard Marti for the patch
  - update debian/patches/theme-refresh-messenger-toolbar-icons.patch
* Move some test integration patches in to a new directory
  - rename d/p/test-overrides/xpcshell-disable-addon-select-dialog-test.patch =>
      d/p/test-integration/xpcshell-disable-addon-select-dialog-test-for-adt.patch
  - rename debian/patches/update-python-virtualenv.patch =>
      d/p/test-integration/mozmill-update-python-virtualenv.patch
  - rename debian/patches/workaround-shebang-char-limit.patch =>
      d/p/test-fixes/mozmill-workaround-shebang-char-limit.patch
  - rename d/p/test-overrides/xpcshell-disable-mailglue-distribution-test.patch =>
      d/p/test-integration/xpcshell-disable-mailglue-distribution-test.patch
* Drop debian/patches/python-virtualenv-multiarch-fix.patch - fixed upstream
* Drop the ability to automatically skip xpcshell tests on an installed system that
  require write access to the application directory, preferring to just disable
  them instead. In reality, we weren't ever going to use this feature
  - remove d/p/test-integration/xpcshell-allow-omit-tests-on-real-install.patch
  - rename d/p/test-integration/xpcshell-disable-mailglue-distribution-test.patch =>
      d/p/test-integration/xpcshell-disable-tests-which-need-appdir-write-access.patch
  - update d/p/test-integration/xpcshell-disable-tests-which-need-appdir-write-access.patch
  - remove d/p/xpcshell-disable-extension-upgrade-test-for-adt.patch (merged
    in to the last patch)
  - remove d/p/test-overrides/xpcshell-disable-isp-autoconfig-test.patch
    (merged in to the last patch)
* Disable some extra failing xpcshell tests
  - rename d/p/test-overrides/xpcshell-disable-geolocation-provider-test.patch =>
      d/p/test-overrides/xpcshell-disable-failing-tests.patch
  - update d/p/test-overrides/xpcshell-disable-failing-tests.patch
  - update debian/patches/series.in
* Disable the menubar addon
  - update debian/config/mozconfig.in
  - update debian/build/mozbuild.mk
  - update debian/thunderbird-globalmenu.dirs.in
* Drop the menubar addon
  - remove debian/globalmenu
  - update debian/build/mozbuild.mk
  - update debian/config/mozconfig.in
  - update debian/control.in
  - remove debian/thunderbird-globalmenu.dirs.in
  - remove debian/patches/unity-globalmenu-build-support.patch
  - update debian/patches/series.in
* Fix build failure with --disable-updater builds
  - add debian/patches/fix-install-manifest-for-no-updater.patch
  - update debian/patches/series
* Fix a space versus tab issue in debian/build/mozbuild.mk
* Add native support for the Unity menubar (no addon)
  - add debian/patches/unity-menubar.patch
  - update debian/patches/series.in
* Refresh patches
  - update d/p/test-overrides/xpcshell-disable-geolocation-provider-test.patch
  - update debian/patches/xpcshell-allow-omit-tests-on-real-install.patch
  - update debian/patches/dont-include-hyphenation-patterns.patch
  - update d/p/test-integration/mozmill-update-python-virtualenv.patch

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 globalmenu-extension.
16
 
 *
17
 
 * The Initial Developer of the Original Code is
18
 
 * Canonical Ltd.
19
 
 * Portions created by the Initial Developer are Copyright (C) 2010
20
 
 * the Initial Developer. All Rights Reserved.
21
 
 *
22
 
 * Contributor(s):
23
 
 * Chris Coulson <chris.coulson@canonical.com>
24
 
 *
25
 
 * Alternatively, the contents of this file may be used under the terms of
26
 
 * either the GNU General Public License Version 2 or later (the "GPL"), or
27
 
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
 
 * in which case the provisions of the GPL or the LGPL are applicable instead
29
 
 * of those above. If you wish to allow use of your version of this file only
30
 
 * under the terms of either the GPL or the LGPL, and not to allow others to
31
 
 * use your version of this file under the terms of the MPL, indicate your
32
 
 * decision by deleting the provisions above and replace them with the notice
33
 
 * and other provisions required by the GPL or the LGPL. If you do not delete
34
 
 * the provisions above, a recipient may use your version of this file under
35
 
 * the terms of any one of the MPL, the GPL or the LGPL.
36
 
 * 
37
 
 * ***** END LICENSE BLOCK ***** */
38
 
 
39
 
#include <nsDebug.h>
40
 
#include <nsIObserver.h>
41
 
#include <nsIWidget.h>
42
 
#include <nsIDOMWindow.h>
43
 
#include <nsIXULWindow.h>
44
 
#include <nsIInterfaceRequestorUtils.h>
45
 
#include <nsIDocShell.h>
46
 
#if MOZILLA_BRANCH_VERSION < 17
47
 
# include <nsIDOMNSEvent.h>
48
 
#endif
49
 
#include <nsIPrefBranch.h>
50
 
#include <nsIDOMKeyEvent.h>
51
 
#include <nsIDOMEventListener.h>
52
 
#include <nsICaseConversion.h>
53
 
#include <nsIContent.h>
54
 
#include <nsIDOMDocument.h>
55
 
#include <nsIDOMEventTarget.h>
56
 
#include <nsIDOMEvent.h>
57
 
 
58
 
#include <glib-object.h>
59
 
#include <gdk/gdkx.h>
60
 
 
61
 
#include "uGlobalMenuBar.h"
62
 
#include "uGlobalMenu.h"
63
 
#include "uGlobalMenuUtils.h"
64
 
#include "uGlobalMenuService.h"
65
 
#include "uWidgetAtoms.h"
66
 
 
67
 
#include "uDebug.h"
68
 
 
69
 
#define MODIFIER_SHIFT    1
70
 
#define MODIFIER_CONTROL  2
71
 
#define MODIFIER_ALT      4
72
 
#define MODIFIER_META     8
73
 
 
74
 
NS_IMPL_ISUPPORTS1(uGlobalMenuBar::EventListener, nsIDOMEventListener)
75
 
 
76
 
NS_IMETHODIMP
77
 
uGlobalMenuBar::EventListener::HandleEvent(nsIDOMEvent *aEvent)
78
 
{
79
 
  nsAutoString type;
80
 
  nsresult rv = aEvent->GetType(type);
81
 
  if (NS_FAILED(rv)) {
82
 
    NS_WARNING("Failed to determine type of event");
83
 
    return rv;
84
 
  }
85
 
 
86
 
  if (type.EqualsLiteral("focus")) {
87
 
    mMenuBar->Focus();
88
 
  } else if (type.EqualsLiteral("blur")) {
89
 
    mMenuBar->Blur();
90
 
  } else if (type.EqualsLiteral("keypress")) {
91
 
    rv = mMenuBar->KeyPress(aEvent);
92
 
  } else if (type.EqualsLiteral("keydown")) {
93
 
    rv = mMenuBar->KeyDown(aEvent);
94
 
  } else if (type.EqualsLiteral("keyup")) {
95
 
    rv = mMenuBar->KeyUp(aEvent);
96
 
  }
97
 
 
98
 
  return rv;
99
 
}
100
 
 
101
 
/*static*/ gboolean
102
 
uGlobalMenuBar::MapEventCallback(GtkWidget *widget,
103
 
                                 GdkEvent *event,
104
 
                                 gpointer user_data)
105
 
{
106
 
  uGlobalMenuBar *menubar = static_cast<uGlobalMenuBar *>(user_data);
107
 
  menubar->Register();
108
 
 
109
 
  return FALSE;
110
 
}
111
 
 
112
 
void
113
 
uGlobalMenuBar::Register()
114
 
{
115
 
  if (mCancellable) {
116
 
    // Registration in progress
117
 
    return;
118
 
  }
119
 
 
120
 
  mCancellable = g_cancellable_new();
121
 
 
122
 
  PRUint32 xidn = (PRUint32) GDK_WINDOW_XID(gtk_widget_get_window(mTopLevel));
123
 
  uGlobalMenuService::RegisterGlobalMenuBar(this, mCancellable, xidn, mPath);
124
 
}
125
 
 
126
 
uint32_t
127
 
uGlobalMenuBar::IndexOf(nsIContent *aContent)
128
 
{
129
 
  if (!aContent) {
130
 
    return -1;
131
 
  }
132
 
 
133
 
  for (uint32_t i = 0; i < mMenuObjects.Length(); i++) {
134
 
    if (mMenuObjects[i]->GetContent() == aContent) {
135
 
      return i;
136
 
    }
137
 
  }
138
 
 
139
 
  return -1;
140
 
}
141
 
 
142
 
bool
143
 
uGlobalMenuBar::AppendMenuObject(uGlobalMenuObject *menu)
144
 
{
145
 
  gboolean res = dbusmenu_menuitem_child_append(mDbusMenuItem,
146
 
                                                menu->GetDbusMenuItem());
147
 
  return res && mMenuObjects.AppendElement(menu);
148
 
}
149
 
 
150
 
bool
151
 
uGlobalMenuBar::InsertMenuObjectAfterContent(uGlobalMenuObject *menu,
152
 
                                             nsIContent *aPrevSibling)
153
 
{
154
 
  int32_t index = IndexOf(aPrevSibling);
155
 
  NS_ASSERTION(index >= 0 || !aPrevSibling, "Previous sibling not found");
156
 
  if (index < 0 && aPrevSibling) {
157
 
    return false;
158
 
  }
159
 
 
160
 
  index++;
161
 
 
162
 
  gboolean res = dbusmenu_menuitem_child_add_position(mDbusMenuItem,
163
 
                                                      menu->GetDbusMenuItem(),
164
 
                                                      index);
165
 
  return res && mMenuObjects.InsertElementAt(index, menu);
166
 
}
167
 
 
168
 
bool
169
 
uGlobalMenuBar::RemoveMenuObjectForContent(nsIContent *aContent)
170
 
{
171
 
  int32_t index = IndexOf(aContent);
172
 
  NS_ASSERTION(index >= 0, "Previous sibling not found");
173
 
  if (index < 0) {
174
 
    return false;
175
 
  }
176
 
 
177
 
  gboolean res = dbusmenu_menuitem_child_delete(mDbusMenuItem,
178
 
                                       mMenuObjects[index]->GetDbusMenuItem());
179
 
  mMenuObjects[index]->Destroy();
180
 
  mMenuObjects.RemoveElementAt(index);
181
 
 
182
 
  return !!res;
183
 
}
184
 
 
185
 
nsresult
186
 
uGlobalMenuBar::Build()
187
 
{
188
 
  PRUint32 count = mContent->GetChildCount();
189
 
 
190
 
  for (PRUint32 i = 0; i < count; i++) {
191
 
    nsIContent *menuContent = mContent->GetChildAt(i);
192
 
 
193
 
    bool failed = false;
194
 
    nsRefPtr<uGlobalMenuObject> newItem =
195
 
      uGlobalMenuUtils::CreateMenuObject(this, mListener, menuContent, &failed);
196
 
 
197
 
    if (newItem) {
198
 
      failed = !(AppendMenuObject(newItem));
199
 
    }
200
 
 
201
 
    NS_ASSERTION(!failed, "Failed to append item to menubar");
202
 
    if (failed) {
203
 
      // XXX: Is there anything else we should do here?
204
 
      return NS_ERROR_FAILURE;
205
 
    }
206
 
  }
207
 
 
208
 
  return NS_OK;
209
 
}
210
 
 
211
 
nsresult
212
 
uGlobalMenuBar::Init(nsIWidget *aWindow,
213
 
                     nsIContent *aMenuBar)
214
 
{
215
 
  NS_ENSURE_ARG(aWindow);
216
 
  NS_ENSURE_ARG(aMenuBar);
217
 
 
218
 
  mContent = aMenuBar;
219
 
 
220
 
  mTopLevel = uGlobalMenuUtils::WidgetToGTKWindow(aWindow);
221
 
  if (!GTK_IS_WINDOW(mTopLevel)) {
222
 
    return NS_ERROR_FAILURE;
223
 
  }
224
 
 
225
 
  g_object_ref(mTopLevel);
226
 
 
227
 
  mPath = NS_LITERAL_CSTRING("/com/canonical/menu/");
228
 
  char xid[10];
229
 
  sprintf(xid, "%X", (PRUint32) GDK_WINDOW_XID(gtk_widget_get_window(mTopLevel)));
230
 
  mPath.Append(xid);
231
 
 
232
 
  mServer = dbusmenu_server_new(mPath.get());
233
 
 
234
 
  GetDbusMenuItem();
235
 
  dbusmenu_server_set_root(mServer, mDbusMenuItem);
236
 
 
237
 
  mListener = new uGlobalMenuDocListener();
238
 
 
239
 
  nsresult rv = mListener->Init(mContent);
240
 
  if (NS_FAILED(rv)) {
241
 
    NS_ERROR("Failed to initialize doc listener");
242
 
    return rv;
243
 
  }
244
 
 
245
 
  rv = Build();
246
 
  if (NS_FAILED(rv)) {
247
 
    NS_ERROR("Failed to build menubar");
248
 
    return rv;
249
 
  }
250
 
 
251
 
  mEventListener = new EventListener(this);
252
 
 
253
 
  mDocument = mContent->OwnerDoc();
254
 
  NS_ASSERTION(mDocument, "Menubar has no owner document!");
255
 
  if (!mDocument) {
256
 
    return NS_ERROR_FAILURE;
257
 
  }
258
 
 
259
 
  nsCOMPtr<nsIDOMEventTarget> docTarget = do_QueryInterface(mDocument);
260
 
  NS_ASSERTION(docTarget, "Document failed QI to nsIDOMEventTarget");
261
 
  if (!docTarget) {
262
 
    return NS_ERROR_FAILURE;
263
 
  }
264
 
 
265
 
  docTarget->AddEventListener(NS_LITERAL_STRING("focus"),
266
 
                              mEventListener,
267
 
                              true);
268
 
  docTarget->AddEventListener(NS_LITERAL_STRING("blur"),
269
 
                              mEventListener,
270
 
                              true);
271
 
  docTarget->AddEventListener(NS_LITERAL_STRING("keypress"),
272
 
                              mEventListener,
273
 
                              false);
274
 
  docTarget->AddEventListener(NS_LITERAL_STRING("keydown"),
275
 
                              mEventListener,
276
 
                              false);
277
 
  docTarget->AddEventListener(NS_LITERAL_STRING("keyup"),
278
 
                              mEventListener,
279
 
                              false);
280
 
 
281
 
  nsIPrefBranch *prefs = uGlobalMenuService::GetPrefService();
282
 
  NS_ASSERTION(prefs, "Failed to get pref service");
283
 
  if (!prefs) {
284
 
    return NS_ERROR_FAILURE;
285
 
  }
286
 
 
287
 
  prefs->GetIntPref("ui.key.menuAccessKey", &mAccessKey);
288
 
  if (mAccessKey == nsIDOMKeyEvent::DOM_VK_SHIFT) {
289
 
    mAccessKeyMask = MODIFIER_SHIFT;
290
 
  } else if (mAccessKey == nsIDOMKeyEvent::DOM_VK_CONTROL) {
291
 
    mAccessKeyMask = MODIFIER_CONTROL;
292
 
  } else if (mAccessKey == nsIDOMKeyEvent::DOM_VK_ALT) {
293
 
    mAccessKeyMask = MODIFIER_ALT;
294
 
  } else if (mAccessKey == nsIDOMKeyEvent::DOM_VK_META) {
295
 
    mAccessKeyMask = MODIFIER_META;
296
 
  } else {
297
 
    mAccessKeyMask = MODIFIER_ALT;
298
 
  }
299
 
 
300
 
  /* Do this before registering for content changes, so that we
301
 
   * don't handle the subsequent event */
302
 
  nsCOMPtr<nsIDOMElement> self = do_QueryInterface(mContent);
303
 
  NS_ASSERTION(self, "Content failed QI to nsIDOMElement");
304
 
  if (!self) {
305
 
    return NS_ERROR_FAILURE;
306
 
  }
307
 
 
308
 
  self->SetAttribute(NS_LITERAL_STRING("openedwithkey"),
309
 
                     NS_LITERAL_STRING("false"));
310
 
 
311
 
  mListener->RegisterForContentChanges(mContent, this);
312
 
 
313
 
  // Unity forgets our window if it is unmapped by the application, which
314
 
  // happens with some extensions that add "minimize to tray" type
315
 
  // functionality. We hook on to the MapNotify event to re-register our menu
316
 
  // with Unity
317
 
  g_signal_connect(G_OBJECT(mTopLevel), "map-event",
318
 
                   G_CALLBACK(MapEventCallback), this);
319
 
 
320
 
  if (gtk_widget_get_mapped(mTopLevel)) {
321
 
    Register();
322
 
  }
323
 
 
324
 
  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
325
 
  NS_ASSERTION(domDoc, "Document failed QI to nsIDOMDocument");
326
 
  if (!domDoc) {
327
 
    return NS_ERROR_FAILURE;
328
 
  }
329
 
 
330
 
  nsCOMPtr<nsIDOMElement> windowElem;
331
 
  domDoc->GetDocumentElement(getter_AddRefs(windowElem));
332
 
  NS_ASSERTION(windowElem, "Document has no documentElement");
333
 
  if (!windowElem) {
334
 
    return NS_ERROR_FAILURE;
335
 
  }
336
 
 
337
 
  return windowElem->SetAttribute(NS_LITERAL_STRING("shellshowingmenubar"),
338
 
                                  NS_LITERAL_STRING("true"));
339
 
}
340
 
 
341
 
PRUint32
342
 
uGlobalMenuBar::GetModifiersFromEvent(nsIDOMKeyEvent *aKeyEvent)
343
 
{
344
 
  PRUint32 modifiers = 0;
345
 
  bool modifier;
346
 
 
347
 
  aKeyEvent->GetAltKey(&modifier);
348
 
  if (modifier) {
349
 
    modifiers |= MODIFIER_ALT;
350
 
  }
351
 
 
352
 
  aKeyEvent->GetShiftKey(&modifier);
353
 
  if (modifier) {
354
 
    modifiers |= MODIFIER_SHIFT;
355
 
  }
356
 
 
357
 
  aKeyEvent->GetCtrlKey(&modifier);
358
 
  if (modifier) {
359
 
    modifiers |= MODIFIER_CONTROL;
360
 
  }
361
 
 
362
 
  aKeyEvent->GetMetaKey(&modifier);
363
 
  if (modifier) {
364
 
    modifiers |= MODIFIER_META;
365
 
  }
366
 
 
367
 
  return modifiers;
368
 
}
369
 
 
370
 
uGlobalMenuBar::uGlobalMenuBar():
371
 
  uGlobalMenuObject(), mServer(nullptr), mTopLevel(nullptr),
372
 
  mCancellable(nullptr)
373
 
{
374
 
  MOZ_COUNT_CTOR(uGlobalMenuBar);
375
 
}
376
 
 
377
 
uGlobalMenuBar::~uGlobalMenuBar()
378
 
{
379
 
  TRACETM();
380
 
 
381
 
  if (!IsDestroyed()) {
382
 
    Destroy();
383
 
  }
384
 
 
385
 
  MOZ_COUNT_DTOR(uGlobalMenuBar);
386
 
}
387
 
 
388
 
/*static*/ uGlobalMenuBar*
389
 
uGlobalMenuBar::Create(nsIWidget *aWindow,
390
 
                       nsIContent *aMenuBar)
391
 
{
392
 
  TRACEC(aMenuBar);
393
 
 
394
 
  uGlobalMenuBar *menubar = new uGlobalMenuBar();
395
 
  if (!menubar) {
396
 
    return nullptr;
397
 
  }
398
 
 
399
 
  if (NS_FAILED(menubar->Init(aWindow, aMenuBar))) {
400
 
    delete menubar;
401
 
    return nullptr;
402
 
  }
403
 
 
404
 
  return menubar;
405
 
}
406
 
 
407
 
void
408
 
uGlobalMenuBar::Destroy()
409
 
{
410
 
  TRACETM();
411
 
 
412
 
  NS_ASSERTION(!IsDestroyed(), "Menubar is already destroyed");
413
 
  if (IsDestroyed()) {
414
 
    return;
415
 
  }
416
 
 
417
 
  if (mTopLevel) {
418
 
    g_signal_handlers_disconnect_by_func(mTopLevel,
419
 
                                         uGlobalMenuUtils::FuncToVoidPtr(MapEventCallback),
420
 
                                         this);
421
 
  }
422
 
 
423
 
  if (mCancellable) {
424
 
    g_cancellable_cancel(mCancellable);
425
 
    g_object_unref(mCancellable);
426
 
    mCancellable = nullptr;
427
 
  }
428
 
 
429
 
  if (mDocument) {
430
 
    nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
431
 
    if (domDoc) {
432
 
      nsCOMPtr<nsIDOMElement> windowElem;
433
 
      domDoc->GetDocumentElement(getter_AddRefs(windowElem));
434
 
      if (windowElem) {
435
 
        windowElem->SetAttribute(NS_LITERAL_STRING("shellshowingmenubar"),
436
 
                                 NS_LITERAL_STRING("false"));
437
 
      }
438
 
    }
439
 
 
440
 
    nsCOMPtr<nsIDOMEventTarget> docTarget = do_QueryInterface(mDocument);
441
 
    if (docTarget) {
442
 
      docTarget->RemoveEventListener(NS_LITERAL_STRING("focus"),
443
 
                                     mEventListener,
444
 
                                     true);
445
 
      docTarget->RemoveEventListener(NS_LITERAL_STRING("blur"),
446
 
                                     mEventListener,
447
 
                                     true);
448
 
      docTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"),
449
 
                                     mEventListener,
450
 
                                     false);
451
 
      docTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"),
452
 
                                     mEventListener,
453
 
                                     false);
454
 
      docTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"),
455
 
                                     mEventListener,
456
 
                                     false);
457
 
    }
458
 
  }
459
 
 
460
 
  if (mTopLevel) {
461
 
    g_object_unref(mTopLevel);
462
 
    mTopLevel = nullptr;
463
 
  }
464
 
 
465
 
  if (mServer) {
466
 
    g_object_unref(mServer);
467
 
    mServer = nullptr;
468
 
  }
469
 
 
470
 
  if (mListener) {
471
 
    mListener->Destroy();
472
 
  }
473
 
 
474
 
  uGlobalMenuObject::Destroy();
475
 
}
476
 
 
477
 
void
478
 
uGlobalMenuBar::Blur()
479
 
{
480
 
  dbusmenu_server_set_status(mServer, DBUSMENU_STATUS_NORMAL);
481
 
}
482
 
 
483
 
void
484
 
uGlobalMenuBar::Focus()
485
 
{
486
 
  nsCOMPtr<nsIDOMElement> self = do_QueryInterface(mContent);
487
 
#if DEBUG_GLOBALMENU >= 2
488
 
  nsAutoString old;
489
 
  self->GetAttribute(NS_LITERAL_STRING("openedwithkey"), old);
490
 
  if (old.Equals(NS_LITERAL_STRING("true"))) {
491
 
    LOG("Received focus - unsetting \"openedwithkey\"");
492
 
  }
493
 
#endif
494
 
  self->SetAttribute(NS_LITERAL_STRING("openedwithkey"),
495
 
                     NS_LITERAL_STRING("false"));
496
 
}
497
 
 
498
 
bool
499
 
uGlobalMenuBar::ShouldHandleKeyEvent(nsIDOMEvent *aKeyEvent)
500
 
{
501
 
#if MOZILLA_BRANCH_VERSION < 17
502
 
  nsCOMPtr<nsIDOMNSEvent> event = do_QueryInterface(aKeyEvent);
503
 
  if (!event) {
504
 
    return false;
505
 
  }
506
 
#else
507
 
  nsIDOMEvent *event = aKeyEvent;
508
 
#endif
509
 
 
510
 
  bool handled, trusted;
511
 
  event->GetPreventDefault(&handled);
512
 
  event->GetIsTrusted(&trusted);
513
 
 
514
 
  if (handled || !trusted) {
515
 
    return false;
516
 
  }
517
 
 
518
 
  return true;
519
 
}
520
 
 
521
 
nsresult
522
 
uGlobalMenuBar::KeyDown(nsIDOMEvent *aKeyEvent)
523
 
{
524
 
  if (!ShouldHandleKeyEvent(aKeyEvent)) {
525
 
    return NS_OK;
526
 
  }
527
 
 
528
 
  nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
529
 
  if (keyEvent) {
530
 
    PRUint32 keyCode;
531
 
    keyEvent->GetKeyCode(&keyCode);
532
 
    PRUint32 modifiers = GetModifiersFromEvent(keyEvent);
533
 
    if ((keyCode == static_cast<PRUint32>(mAccessKey)) &&
534
 
        ((modifiers & ~mAccessKeyMask) == 0)) {
535
 
      dbusmenu_server_set_status(mServer, DBUSMENU_STATUS_NOTICE);
536
 
    }
537
 
  }
538
 
 
539
 
  return NS_OK;
540
 
}
541
 
 
542
 
nsresult
543
 
uGlobalMenuBar::KeyUp(nsIDOMEvent *aKeyEvent)
544
 
{
545
 
  if (!ShouldHandleKeyEvent(aKeyEvent)) {
546
 
    return NS_OK;
547
 
  }
548
 
 
549
 
  nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
550
 
  if (keyEvent) {
551
 
    PRUint32 keyCode;
552
 
    keyEvent->GetKeyCode(&keyCode);
553
 
    if (keyCode == static_cast<PRUint32>(mAccessKey)) {
554
 
      dbusmenu_server_set_status(mServer, DBUSMENU_STATUS_NORMAL);
555
 
    }
556
 
  }
557
 
 
558
 
  return NS_OK;
559
 
}
560
 
 
561
 
nsresult
562
 
uGlobalMenuBar::KeyPress(nsIDOMEvent *aKeyEvent)
563
 
{
564
 
  if (!ShouldHandleKeyEvent(aKeyEvent)) {
565
 
    return NS_OK;
566
 
  }
567
 
 
568
 
  nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
569
 
  uGlobalMenuObject *found = nullptr;
570
 
 
571
 
  if (keyEvent) {
572
 
    PRUint32 keyCode;
573
 
    keyEvent->GetKeyCode(&keyCode);
574
 
    PRUint32 count = mMenuObjects.Length();
575
 
    PRUint32 modifiers = GetModifiersFromEvent(keyEvent);
576
 
    if ((modifiers & mAccessKeyMask) && ((modifiers & ~mAccessKeyMask) == 0)) {
577
 
      // The menu access modifier is pressed
578
 
      PRUint32 charCode;
579
 
      keyEvent->GetCharCode(&charCode);
580
 
      if (charCode != 0) {
581
 
        PRUnichar ch = PRUnichar(charCode);
582
 
 
583
 
        nsICaseConversion *converter= uGlobalMenuService::GetCaseConverter();
584
 
 
585
 
        PRUnichar chu;
586
 
        PRUnichar chl;
587
 
        if (converter) {
588
 
          converter->ToUpper(ch, &chu);
589
 
          converter->ToLower(ch, &chl);
590
 
        } else {
591
 
          NS_WARNING("No case converter");
592
 
          chu = ch;
593
 
          chl = ch;
594
 
        }
595
 
 
596
 
        for (PRUint32 i = 0; i < count; i++) {
597
 
          nsIContent *content = mMenuObjects[i]->GetContent();
598
 
          if (content) {
599
 
            nsAutoString accessKey;
600
 
            content->GetAttr(kNameSpaceID_None, uWidgetAtoms::accesskey,
601
 
                             accessKey);
602
 
            const PRUnichar *key = accessKey.BeginReading();
603
 
            if (*key == chl || *key == chu) {
604
 
              found = mMenuObjects[i];
605
 
              break;
606
 
            }
607
 
          }
608
 
        }
609
 
      }
610
 
    } else if (keyCode == nsIDOMKeyEvent::DOM_VK_F10) {
611
 
      // Go through each mMenuObject, and find the first one
612
 
      // that is both visible and sensitive, and mark it found
613
 
      // for opening.
614
 
      for (PRUint32 i = 0; i < count; i++) {
615
 
        uGlobalMenu *menu = static_cast<uGlobalMenu *>((uGlobalMenuObject *)mMenuObjects[i]);
616
 
        if (menu->CanOpen()) {
617
 
          found = mMenuObjects[i];
618
 
          break;
619
 
        }
620
 
      }
621
 
    }
622
 
  }
623
 
 
624
 
  if (found) {
625
 
    nsCOMPtr<nsIDOMElement> self = do_QueryInterface(mContent);
626
 
    self->SetAttribute(NS_LITERAL_STRING("openedwithkey"),
627
 
                       NS_LITERAL_STRING("true"));
628
 
    uGlobalMenu *menu = static_cast<uGlobalMenu *>(found);
629
 
    menu->OpenMenuDelayed();
630
 
    aKeyEvent->StopPropagation();
631
 
    aKeyEvent->PreventDefault();
632
 
  }
633
 
 
634
 
  return NS_OK;
635
 
}
636
 
 
637
 
void
638
 
uGlobalMenuBar::NotifyMenuBarRegistered()
639
 
{
640
 
  g_object_unref(mCancellable);
641
 
  mCancellable = nullptr;
642
 
 
643
 
  SetFlags(UNITY_MENUBAR_IS_REGISTERED);
644
 
}
645
 
 
646
 
void
647
 
uGlobalMenuBar::ObserveAttributeChanged(nsIContent *aContent,
648
 
                                        nsIAtom *aAttribute)
649
 
{
650
 
 
651
 
}
652
 
 
653
 
void
654
 
uGlobalMenuBar::ObserveContentRemoved(nsIContent *aContainer,
655
 
                                      nsIContent *aChild)
656
 
{
657
 
  TRACETM();
658
 
  NS_ASSERTION(aContainer == mContent,
659
 
               "Received an event that wasn't meant for us!");
660
 
 
661
 
  RemoveMenuObjectForContent(aChild);
662
 
}
663
 
 
664
 
void
665
 
uGlobalMenuBar::ObserveContentInserted(nsIContent *aContainer,
666
 
                                       nsIContent *aChild,
667
 
                                       nsIContent *aPrevSibling)
668
 
{
669
 
  TRACETM();
670
 
  NS_ASSERTION(aContainer == mContent,
671
 
               "Received an event that wasn't meant for us!");
672
 
 
673
 
  aPrevSibling = uGlobalMenuUtils::GetPreviousSupportedSibling(aPrevSibling);
674
 
 
675
 
  bool failed = false;
676
 
  nsRefPtr<uGlobalMenuObject> newItem =
677
 
    uGlobalMenuUtils::CreateMenuObject(this, mListener, aChild, &failed);
678
 
 
679
 
  if (newItem) {
680
 
    failed = !(InsertMenuObjectAfterContent(newItem, aPrevSibling));
681
 
  }
682
 
 
683
 
  NS_ASSERTION(!failed, "Failed to insert item in to menubar");
684
 
}