Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / ui / gfx / gtk_native_view_id_manager.cc
1 // Copyright (c) 2012 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 "ui/gfx/gtk_native_view_id_manager.h"
6
7 #include <gdk/gdkx.h>
8 #include <gtk/gtk.h>
9
10 #include "base/logging.h"
11 #include "base/memory/singleton.h"
12 #include "base/rand_util.h"
13 #include "ui/gfx/gdk_compat.h"
14 #include "ui/gfx/gtk_compat.h"
15 #include "ui/gfx/gtk_preserve_window.h"
16
17 // -----------------------------------------------------------------------------
18 // Bounce functions for GTK to callback into a C++ object...
19
20 void OnRealize(gfx::NativeView widget, void* arg) {
21   GtkNativeViewManager* manager = reinterpret_cast<GtkNativeViewManager*>(arg);
22   manager->OnRealize(widget);
23 }
24
25 void OnUnrealize(gfx::NativeView widget, void *arg) {
26   GtkNativeViewManager* manager = reinterpret_cast<GtkNativeViewManager*>(arg);
27   manager->OnUnrealize(widget);
28 }
29
30 static void OnDestroy(GtkObject* obj, void* arg) {
31   GtkNativeViewManager* manager = reinterpret_cast<GtkNativeViewManager*>(arg);
32   manager->OnDestroy(reinterpret_cast<GtkWidget*>(obj));
33 }
34
35 // -----------------------------------------------------------------------------
36
37
38 // -----------------------------------------------------------------------------
39 // Public functions...
40
41 GtkNativeViewManager::GtkNativeViewManager() {
42 }
43
44 GtkNativeViewManager::~GtkNativeViewManager() {
45 }
46
47 // static
48 GtkNativeViewManager* GtkNativeViewManager::GetInstance() {
49   return Singleton<GtkNativeViewManager>::get();
50 }
51
52 gfx::NativeViewId GtkNativeViewManager::GetIdForWidget(gfx::NativeView widget) {
53   // This is just for unit tests:
54   if (!widget)
55     return 0;
56
57   base::AutoLock locked(lock_);
58
59   std::map<gfx::NativeView, gfx::NativeViewId>::const_iterator i =
60     native_view_to_id_.find(widget);
61
62   if (i != native_view_to_id_.end())
63     return i->second;
64
65   gfx::NativeViewId new_id =
66       static_cast<gfx::NativeViewId>(base::RandUint64());
67   while (id_to_info_.find(new_id) != id_to_info_.end())
68     new_id = static_cast<gfx::NativeViewId>(base::RandUint64());
69
70   NativeViewInfo info;
71   info.widget = widget;
72   if (gtk_widget_get_realized(widget)) {
73     GdkWindow *gdk_window = gtk_widget_get_window(widget);
74     DCHECK(gdk_window);
75     info.x_window_id = GDK_WINDOW_XID(gdk_window);
76   }
77
78   native_view_to_id_[widget] = new_id;
79   id_to_info_[new_id] = info;
80
81   g_signal_connect(widget, "realize", G_CALLBACK(::OnRealize), this);
82   g_signal_connect(widget, "unrealize", G_CALLBACK(::OnUnrealize), this);
83   g_signal_connect(widget, "destroy", G_CALLBACK(::OnDestroy), this);
84
85   return new_id;
86 }
87
88 bool GtkNativeViewManager::GetXIDForId(XID* output, gfx::NativeViewId id) {
89   base::AutoLock locked(lock_);
90
91   std::map<gfx::NativeViewId, NativeViewInfo>::const_iterator i =
92       id_to_info_.find(id);
93
94   if (i == id_to_info_.end())
95     return false;
96
97   *output = i->second.x_window_id;
98   return true;
99 }
100
101 bool GtkNativeViewManager::GetNativeViewForId(gfx::NativeView* output,
102                                               gfx::NativeViewId id) {
103   base::AutoLock locked(lock_);
104
105   std::map<gfx::NativeViewId, NativeViewInfo>::const_iterator i =
106       id_to_info_.find(id);
107
108   if (i == id_to_info_.end())
109     return false;
110
111   *output = i->second.widget;
112   return true;
113 }
114
115 bool GtkNativeViewManager::GetPermanentXIDForId(XID* output,
116                                                 gfx::NativeViewId id) {
117   base::AutoLock locked(lock_);
118
119   std::map<gfx::NativeViewId, NativeViewInfo>::iterator i =
120       id_to_info_.find(id);
121
122   if (i == id_to_info_.end())
123     return false;
124
125   // We only return permanent XIDs for widgets that allow us to guarantee that
126   // the XID will not change.
127   DCHECK(GTK_IS_PRESERVE_WINDOW(i->second.widget));
128   GtkPreserveWindow* widget =
129       reinterpret_cast<GtkPreserveWindow*>(i->second.widget);
130   gtk_preserve_window_set_preserve(widget, TRUE);
131
132   *output = GDK_WINDOW_XID(gtk_widget_get_window(i->second.widget));
133
134   // Update the reference count on the permanent XID.
135   PermanentXIDInfo info;
136   info.widget = widget;
137   info.ref_count = 1;
138   std::pair<std::map<XID, PermanentXIDInfo>::iterator, bool> ret =
139     perm_xid_to_info_.insert(std::make_pair(*output, info));
140
141   if (!ret.second) {
142     DCHECK(ret.first->second.widget == widget);
143     ret.first->second.ref_count++;
144   }
145
146   return true;
147 }
148
149 bool GtkNativeViewManager::AddRefPermanentXID(XID xid) {
150   base::AutoLock locked(lock_);
151
152   std::map<XID, PermanentXIDInfo>::iterator i =
153     perm_xid_to_info_.find(xid);
154
155   if (i == perm_xid_to_info_.end())
156     return false;
157
158   i->second.ref_count++;
159
160   return true;
161 }
162
163 void GtkNativeViewManager::ReleasePermanentXID(XID xid) {
164   base::AutoLock locked(lock_);
165
166   std::map<XID, PermanentXIDInfo>::iterator i =
167     perm_xid_to_info_.find(xid);
168
169   if (i == perm_xid_to_info_.end())
170     return;
171
172   if (i->second.ref_count > 1) {
173     i->second.ref_count--;
174   } else {
175     if (i->second.widget) {
176       gtk_preserve_window_set_preserve(i->second.widget, FALSE);
177     } else {
178       GdkWindow* window = reinterpret_cast<GdkWindow*>(
179           gdk_x11_window_lookup_for_display(gdk_display_get_default(), xid));
180       DCHECK(window);
181       gdk_window_destroy(window);
182     }
183     perm_xid_to_info_.erase(i);
184   }
185 }
186
187 // -----------------------------------------------------------------------------
188
189
190 // -----------------------------------------------------------------------------
191 // Private functions...
192
193 gfx::NativeViewId GtkNativeViewManager::GetWidgetId(gfx::NativeView widget) {
194   lock_.AssertAcquired();
195
196   std::map<gfx::NativeView, gfx::NativeViewId>::const_iterator i =
197     native_view_to_id_.find(widget);
198
199   CHECK(i != native_view_to_id_.end());
200   return i->second;
201 }
202
203 void GtkNativeViewManager::OnRealize(gfx::NativeView widget) {
204   base::AutoLock locked(lock_);
205
206   const gfx::NativeViewId id = GetWidgetId(widget);
207   std::map<gfx::NativeViewId, NativeViewInfo>::iterator i =
208     id_to_info_.find(id);
209
210   CHECK(i != id_to_info_.end());
211
212   GdkWindow* gdk_window = gtk_widget_get_window(widget);
213   CHECK(gdk_window);
214   i->second.x_window_id = GDK_WINDOW_XID(gdk_window);
215 }
216
217 void GtkNativeViewManager::OnUnrealize(gfx::NativeView widget) {
218   base::AutoLock locked(lock_);
219
220   const gfx::NativeViewId id = GetWidgetId(widget);
221   std::map<gfx::NativeViewId, NativeViewInfo>::iterator i =
222     id_to_info_.find(id);
223
224   CHECK(i != id_to_info_.end());
225 }
226
227 void GtkNativeViewManager::OnDestroy(gfx::NativeView widget) {
228   base::AutoLock locked(lock_);
229
230   std::map<gfx::NativeView, gfx::NativeViewId>::iterator i =
231     native_view_to_id_.find(widget);
232   CHECK(i != native_view_to_id_.end());
233
234   std::map<gfx::NativeViewId, NativeViewInfo>::iterator j =
235     id_to_info_.find(i->second);
236   CHECK(j != id_to_info_.end());
237
238   // If the XID is supposed to outlive the widget, mark it
239   // in the lookup table.
240   if (GTK_IS_PRESERVE_WINDOW(widget) &&
241       gtk_preserve_window_get_preserve(
242           reinterpret_cast<GtkPreserveWindow*>(widget))) {
243     std::map<XID, PermanentXIDInfo>::iterator k =
244         perm_xid_to_info_.find(GDK_WINDOW_XID(gtk_widget_get_window(widget)));
245
246     if (k != perm_xid_to_info_.end())
247       k->second.widget = NULL;
248   }
249
250   native_view_to_id_.erase(i);
251   id_to_info_.erase(j);
252 }
253
254 // -----------------------------------------------------------------------------