OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/logging.h" |
| 9 #include "chrome/browser/ui/views/frame/global_menu_bar_x11.h" |
| 10 #include "content/public/browser/browser_thread.h" |
| 11 |
| 12 using content::BrowserThread; |
| 13 |
| 14 namespace { |
| 15 |
| 16 const char kAppMenuRegistrarName[] = "com.canonical.AppMenu.Registrar"; |
| 17 const char kAppMenuRegistrarPath[] = "/com/canonical/AppMenu/Registrar"; |
| 18 |
| 19 } // namespace |
| 20 |
| 21 // static |
| 22 GlobalMenuBarRegistrarX11* GlobalMenuBarRegistrarX11::GetInstance() { |
| 23 return Singleton<GlobalMenuBarRegistrarX11>::get(); |
| 24 } |
| 25 |
| 26 void GlobalMenuBarRegistrarX11::OnWindowMapped(unsigned long xid) { |
| 27 live_xids_.insert(xid); |
| 28 |
| 29 if (registrar_proxy_) |
| 30 RegisterXID(xid); |
| 31 } |
| 32 |
| 33 void GlobalMenuBarRegistrarX11::OnWindowUnmapped(unsigned long xid) { |
| 34 if (registrar_proxy_) |
| 35 UnregisterXID(xid); |
| 36 |
| 37 live_xids_.erase(xid); |
| 38 } |
| 39 |
| 40 GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11() |
| 41 : registrar_proxy_(NULL) { |
| 42 // libdbusmenu uses the gio version of dbus; I tried using the code in dbus/, |
| 43 // but it looks like that's isn't sharing the bus name with the gio version, |
| 44 // even when |connection_type| is set to SHARED. |
| 45 g_dbus_proxy_new_for_bus( |
| 46 G_BUS_TYPE_SESSION, |
| 47 static_cast<GDBusProxyFlags>( |
| 48 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | |
| 49 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | |
| 50 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START), |
| 51 NULL, |
| 52 kAppMenuRegistrarName, |
| 53 kAppMenuRegistrarPath, |
| 54 kAppMenuRegistrarName, |
| 55 NULL, // TODO: Probalby want a real cancelable. |
| 56 static_cast<GAsyncReadyCallback>(OnProxyCreatedThunk), |
| 57 this); |
| 58 } |
| 59 |
| 60 GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() { |
| 61 if (registrar_proxy_) { |
| 62 g_signal_handlers_disconnect_by_func( |
| 63 registrar_proxy_, |
| 64 reinterpret_cast<void*>(OnNameOwnerChangedThunk), |
| 65 this); |
| 66 g_object_unref(registrar_proxy_); |
| 67 } |
| 68 } |
| 69 |
| 70 void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) { |
| 71 DCHECK(registrar_proxy_); |
| 72 std::string path = GlobalMenuBarX11::GetPathForWindow(xid); |
| 73 |
| 74 // TODO(erg): The mozilla implementation goes to a lot of callback trouble |
| 75 // just to make sure that they react to make sure there's some sort of |
| 76 // cancelable object; including making a whole callback just to handle the |
| 77 // cancelable. |
| 78 // |
| 79 // I don't see any reason why we should care if "RegisterWindow" completes or |
| 80 // not. |
| 81 g_dbus_proxy_call(registrar_proxy_, |
| 82 "RegisterWindow", |
| 83 g_variant_new("(uo)", xid, path.c_str()), |
| 84 G_DBUS_CALL_FLAGS_NONE, -1, |
| 85 NULL, |
| 86 NULL, |
| 87 NULL); |
| 88 } |
| 89 |
| 90 void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid) { |
| 91 DCHECK(registrar_proxy_); |
| 92 std::string path = GlobalMenuBarX11::GetPathForWindow(xid); |
| 93 |
| 94 // TODO(erg): The mozilla implementation goes to a lot of callback trouble |
| 95 // just to make sure that they react to make sure there's some sort of |
| 96 // cancelable object; including making a whole callback just to handle the |
| 97 // cancelable. |
| 98 // |
| 99 // I don't see any reason why we should care if "UnregisterWindow" completes |
| 100 // or not. |
| 101 g_dbus_proxy_call(registrar_proxy_, |
| 102 "UnregisterWindow", |
| 103 g_variant_new("(u)", xid), |
| 104 G_DBUS_CALL_FLAGS_NONE, -1, |
| 105 NULL, |
| 106 NULL, |
| 107 NULL); |
| 108 } |
| 109 |
| 110 void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject* source, |
| 111 GAsyncResult* result) { |
| 112 GError* error = NULL; |
| 113 GDBusProxy* proxy = g_dbus_proxy_new_for_bus_finish(result, &error); |
| 114 if (error) { |
| 115 g_error_free(error); |
| 116 return; |
| 117 } |
| 118 |
| 119 // TODO(erg): Mozilla's implementation has a workaround for GDBus |
| 120 // cancellation here. However, it's marked as fixed. If there's weird |
| 121 // problems with cancelation, look at how they fixed their issues. |
| 122 |
| 123 registrar_proxy_ = proxy; |
| 124 |
| 125 g_signal_connect(registrar_proxy_, "notify::g-name-owner", |
| 126 G_CALLBACK(OnNameOwnerChangedThunk), this); |
| 127 |
| 128 OnNameOwnerChanged(NULL, NULL); |
| 129 } |
| 130 |
| 131 void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject* /* ignored */, |
| 132 GParamSpec* /* ignored */) { |
| 133 // If the name owner changed, we need to reregister all the live xids with |
| 134 // the system. |
| 135 for (std::set<unsigned long>::const_iterator it = live_xids_.begin(); |
| 136 it != live_xids_.end(); ++it) { |
| 137 RegisterXID(*it); |
| 138 } |
| 139 } |
OLD | NEW |