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 "views/controls/native_view_host_gtk.h" | |
6 | |
7 #include <gtk/gtk.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "views/widget/widget_gtk.h" | |
11 | |
12 namespace views { | |
13 | |
14 NativeViewHostGtk::NativeViewHostGtk() | |
15 : NativeViewHost(), | |
16 destroy_signal_id_(0) { | |
17 } | |
18 | |
19 NativeViewHostGtk::~NativeViewHostGtk() { | |
20 } | |
21 | |
22 // static | |
23 View* NativeViewHostGtk::GetViewForNative(GtkWidget* widget) { | |
24 gpointer user_data = g_object_get_data(G_OBJECT(widget), "chrome-view"); | |
25 return static_cast<View*>(user_data); | |
26 } | |
27 | |
28 // static | |
29 void NativeViewHostGtk::SetViewForNative(GtkWidget* widget, View* view) { | |
30 g_object_set_data(G_OBJECT(widget), "chrome-view", view); | |
31 } | |
32 | |
33 void NativeViewHostGtk::Attach(GtkWidget* widget) { | |
34 DCHECK(native_view() == NULL); | |
35 DCHECK(widget); | |
36 | |
37 // Adds a mapping between the GtkWidget and us. | |
38 SetViewForNative(widget, this); | |
39 | |
40 destroy_signal_id_ = g_signal_connect(G_OBJECT(widget), "destroy", | |
41 G_CALLBACK(CallDestroy), NULL); | |
42 | |
43 set_native_view(widget); | |
44 | |
45 // First hide the new window. We don't want anything to draw (like sub-hwnd | |
46 // borders), when we change the parent below. | |
47 gtk_widget_hide(widget); | |
48 | |
49 // Set the parent. | |
50 static_cast<WidgetGtk*>(GetWidget())->AddChild(widget); | |
51 Layout(); | |
52 | |
53 // TODO: figure out focus. | |
54 // FocusManager::InstallFocusSubclass( | |
55 // hwnd, associated_focus_view()_ ? associated_focus_view() : this); | |
56 } | |
57 | |
58 void NativeViewHostGtk::Detach() { | |
59 DCHECK(native_view()); | |
60 | |
61 g_signal_handler_disconnect(G_OBJECT(native_view()), destroy_signal_id_); | |
62 destroy_signal_id_ = 0; | |
63 | |
64 // TODO: focus. | |
65 // FocusManager::UninstallFocusSubclass(native_view()); | |
66 set_native_view(NULL); | |
67 set_installed_clip(false); | |
68 } | |
69 | |
70 void NativeViewHostGtk::ViewHierarchyChanged(bool is_add, View* parent, | |
71 View* child) { | |
72 if (!native_view()) | |
73 return; | |
74 | |
75 WidgetGtk* parent_widget = static_cast<WidgetGtk*>(GetWidget()); | |
76 if (is_add && parent_widget) { | |
77 GtkWidget* widget_parent = gtk_widget_get_parent(native_view()); | |
78 GtkWidget* parent_widget_widget = parent_widget->child_widget_parent(); | |
79 if (widget_parent != parent_widget_widget) { | |
80 g_object_ref(native_view()); | |
81 if (widget_parent) | |
82 gtk_container_remove(GTK_CONTAINER(widget_parent), native_view()); | |
83 gtk_container_add(GTK_CONTAINER(parent_widget_widget), native_view()); | |
84 g_object_unref(native_view()); | |
85 } | |
86 if (IsVisibleInRootView()) | |
87 gtk_widget_show(native_view()); | |
88 else | |
89 gtk_widget_hide(native_view()); | |
90 Layout(); | |
91 } else if (!is_add) { | |
92 gtk_widget_hide(native_view()); | |
93 if (parent_widget) { | |
94 gtk_container_remove(GTK_CONTAINER(parent_widget->child_widget_parent()), | |
95 native_view()); | |
96 } | |
97 } | |
98 } | |
99 | |
100 void NativeViewHostGtk::Focus() { | |
101 NOTIMPLEMENTED(); | |
102 } | |
103 | |
104 void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) { | |
105 DCHECK(w > 0 && h > 0); | |
106 | |
107 bool has_window = (GTK_WIDGET_FLAGS(native_view()) & GTK_NO_WINDOW) == 0; | |
108 if (!has_window) { | |
109 // Clip is only supported on GtkWidgets that have windows. If this becomes | |
110 // an issue (as it may be in the options dialog) we'll need to wrap the | |
111 // widget in a GtkFixed with a window. We have to do this as not all widgets | |
112 // support turning on GTK_NO_WINDOW (for example, buttons don't appear to | |
113 // draw anything when they have a window). | |
114 NOTREACHED(); | |
115 return; | |
116 } | |
117 DCHECK(has_window); | |
118 // Unset the current region. | |
119 gdk_window_shape_combine_region(native_view()->window, NULL, 0, 0); | |
120 | |
121 // Set a new region. | |
122 // TODO: using shapes is a bit expensive. Should investigated if there is | |
123 // another more efficient way to accomplish this. | |
124 GdkRectangle clip_rect = { x, y, w, h }; | |
125 GdkRegion* clip_region = gdk_region_rectangle(&clip_rect); | |
126 gdk_window_shape_combine_region(native_view()->window, clip_region, x, y); | |
127 gdk_region_destroy(clip_region); | |
128 } | |
129 | |
130 void NativeViewHostGtk::UninstallClip() { | |
131 gtk_widget_shape_combine_mask(native_view(), NULL, 0, 0); | |
132 } | |
133 | |
134 void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) { | |
135 WidgetGtk* parent = static_cast<WidgetGtk*>(GetWidget()); | |
136 parent->PositionChild(native_view(), x, y, w, h); | |
137 gtk_widget_show(native_view()); | |
138 } | |
139 | |
140 void NativeViewHostGtk::HideWidget() { | |
141 gtk_widget_hide(native_view()); | |
142 } | |
143 | |
144 void NativeViewHostGtk::OnDestroy() { | |
145 set_native_view(NULL); | |
146 } | |
147 | |
148 // static | |
149 void NativeViewHostGtk::CallDestroy(GtkObject* object) { | |
150 View* view = GetViewForNative(GTK_WIDGET(object)); | |
151 if (!view) | |
152 return; | |
153 | |
154 return static_cast<NativeViewHostGtk*>(view)->OnDestroy(); | |
155 } | |
156 | |
157 } // namespace views | |
OLD | NEW |