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