| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" | 5 #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 #include <gdk/gdk.h> | 8 #include <gdk/gdk.h> |
| 9 #include <gdk/gdkx.h> | 9 #include <gdk/gdkx.h> |
| 10 #include <cairo/cairo.h> | 10 #include <cairo/cairo.h> |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 GtkTargetList* target_list = gtk_target_list_new(NULL, 0); | 61 GtkTargetList* target_list = gtk_target_list_new(NULL, 0); |
| 62 gtk_target_list_add_text_targets(target_list, 0); | 62 gtk_target_list_add_text_targets(target_list, 0); |
| 63 gint num_targets = 0; | 63 gint num_targets = 0; |
| 64 GtkTargetEntry* targets = gtk_target_table_new_from_list(target_list, | 64 GtkTargetEntry* targets = gtk_target_table_new_from_list(target_list, |
| 65 &num_targets); | 65 &num_targets); |
| 66 gtk_selection_clear_targets(widget, GDK_SELECTION_PRIMARY); | 66 gtk_selection_clear_targets(widget, GDK_SELECTION_PRIMARY); |
| 67 gtk_selection_add_targets(widget, GDK_SELECTION_PRIMARY, targets, | 67 gtk_selection_add_targets(widget, GDK_SELECTION_PRIMARY, targets, |
| 68 num_targets); | 68 num_targets); |
| 69 gtk_target_list_unref(target_list); | 69 gtk_target_list_unref(target_list); |
| 70 gtk_target_table_free(targets, num_targets); | 70 gtk_target_table_free(targets, num_targets); |
| 71 | |
| 72 // When X requests the contents of the clipboard, GTK will emit the | |
| 73 // selection_request_event signal. The default handler would then | |
| 74 // synchronously emit the selection_get signal. However, we want to | |
| 75 // respond to the selection_request_event asynchronously, so we intercept | |
| 76 // the signal in OnSelectionRequest, request the selection text from the | |
| 77 // render view, and return TRUE so the default handler won't be called. Then | |
| 78 // when we get the selection text back from the renderer in | |
| 79 // SetSelectionText() we will call manually the selection_request_event | |
| 80 // default handler. | |
| 81 g_signal_connect(widget, "selection_request_event", | |
| 82 G_CALLBACK(OnSelectionRequest), host_view); | |
| 83 g_signal_connect(widget, "selection_get", | |
| 84 G_CALLBACK(OnSelectionGet), host_view); | |
| 85 | |
| 86 // In OnSelectionGet, we need to access |host_view| to get the selection | |
| 87 // text. | |
| 88 g_object_set_data(G_OBJECT(widget), "render-widget-host-view-gtk", | |
| 89 host_view); | |
| 90 return widget; | 71 return widget; |
| 91 } | 72 } |
| 92 | 73 |
| 93 private: | 74 private: |
| 94 static gboolean ConfigureEvent(GtkWidget* widget, GdkEventConfigure* config, | 75 static gboolean ConfigureEvent(GtkWidget* widget, GdkEventConfigure* config, |
| 95 RenderWidgetHostViewGtk* host_view) { | 76 RenderWidgetHostViewGtk* host_view) { |
| 96 host_view->GetRenderWidgetHost()->WasResized(); | 77 host_view->GetRenderWidgetHost()->WasResized(); |
| 97 return FALSE; | 78 return FALSE; |
| 98 } | 79 } |
| 99 | 80 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 return FALSE; | 131 return FALSE; |
| 151 } | 132 } |
| 152 | 133 |
| 153 static gboolean MouseScrollEvent(GtkWidget* widget, GdkEventScroll* event, | 134 static gboolean MouseScrollEvent(GtkWidget* widget, GdkEventScroll* event, |
| 154 RenderWidgetHostViewGtk* host_view) { | 135 RenderWidgetHostViewGtk* host_view) { |
| 155 host_view->GetRenderWidgetHost()->ForwardWheelEvent( | 136 host_view->GetRenderWidgetHost()->ForwardWheelEvent( |
| 156 WebInputEventFactory::mouseWheelEvent(event)); | 137 WebInputEventFactory::mouseWheelEvent(event)); |
| 157 return FALSE; | 138 return FALSE; |
| 158 } | 139 } |
| 159 | 140 |
| 160 | |
| 161 static gboolean OnSelectionRequest(GtkWidget* widget, | |
| 162 GdkEventSelection* event) { | |
| 163 RenderWidgetHostViewGtk* host_view = | |
| 164 reinterpret_cast<RenderWidgetHostViewGtk*>( | |
| 165 g_object_get_data(G_OBJECT(widget), "render-widget-host-view-gtk")); | |
| 166 | |
| 167 // If we already know the selection text, return FALSE to let the default | |
| 168 // handler run. Also, don't try to handle two events simultaneously, | |
| 169 // because we might end up sending the wrong |event_selection_| back to GTK. | |
| 170 if (!host_view->selection_text_.empty() || | |
| 171 host_view->event_selection_active_) | |
| 172 return FALSE; | |
| 173 | |
| 174 host_view->event_selection_ = *event; | |
| 175 host_view->event_selection_active_ = true; | |
| 176 if (host_view->selection_text_.empty()) | |
| 177 host_view->RequestSelectionText(); | |
| 178 | |
| 179 return TRUE; | |
| 180 } | |
| 181 | |
| 182 static void OnSelectionGet(GtkWidget* widget, | |
| 183 GtkSelectionData* data, | |
| 184 guint info, guint time, | |
| 185 RenderWidgetHostViewGtk* host_view) { | |
| 186 DCHECK(!host_view->selection_text_.empty() || | |
| 187 host_view->event_selection_active_); | |
| 188 | |
| 189 gtk_selection_data_set(data, data->target, 8, | |
| 190 reinterpret_cast<const guchar*>(host_view->selection_text_.c_str()), | |
| 191 host_view->selection_text_.length()); | |
| 192 } | |
| 193 | |
| 194 DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWidgetHostViewGtkWidget); | 141 DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWidgetHostViewGtkWidget); |
| 195 }; | 142 }; |
| 196 | 143 |
| 197 static gboolean OnPopupParentFocusOut(GtkWidget* parent, GdkEventFocus* focus, | 144 static gboolean OnPopupParentFocusOut(GtkWidget* parent, GdkEventFocus* focus, |
| 198 RenderWidgetHost* host) { | 145 RenderWidgetHost* host) { |
| 199 host->Shutdown(); | 146 host->Shutdown(); |
| 200 return FALSE; | 147 return FALSE; |
| 201 } | 148 } |
| 202 | 149 |
| 203 // static | 150 // static |
| 204 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( | 151 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( |
| 205 RenderWidgetHost* widget) { | 152 RenderWidgetHost* widget) { |
| 206 return new RenderWidgetHostViewGtk(widget); | 153 return new RenderWidgetHostViewGtk(widget); |
| 207 } | 154 } |
| 208 | 155 |
| 209 RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) | 156 RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) |
| 210 : host_(widget_host), | 157 : host_(widget_host), |
| 211 parent_host_view_(NULL), | 158 parent_host_view_(NULL), |
| 212 parent_(NULL), | 159 parent_(NULL), |
| 213 popup_signal_id_(0), | 160 popup_signal_id_(0), |
| 214 activatable_(true), | 161 activatable_(true), |
| 215 is_loading_(false), | 162 is_loading_(false) { |
| 216 event_selection_active_(false) { | |
| 217 host_->set_view(this); | 163 host_->set_view(this); |
| 218 } | 164 } |
| 219 | 165 |
| 220 RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() { | 166 RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() { |
| 221 } | 167 } |
| 222 | 168 |
| 223 void RenderWidgetHostViewGtk::InitAsChild() { | 169 void RenderWidgetHostViewGtk::InitAsChild() { |
| 224 view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this)); | 170 view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this)); |
| 225 gtk_widget_show(view_.get()); | 171 gtk_widget_show(view_.get()); |
| 226 } | 172 } |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 } | 307 } |
| 362 | 308 |
| 363 void RenderWidgetHostViewGtk::SetTooltipText(const std::wstring& tooltip_text) { | 309 void RenderWidgetHostViewGtk::SetTooltipText(const std::wstring& tooltip_text) { |
| 364 if (tooltip_text.empty()) { | 310 if (tooltip_text.empty()) { |
| 365 gtk_widget_set_has_tooltip(view_.get(), FALSE); | 311 gtk_widget_set_has_tooltip(view_.get(), FALSE); |
| 366 } else { | 312 } else { |
| 367 gtk_widget_set_tooltip_text(view_.get(), WideToUTF8(tooltip_text).c_str()); | 313 gtk_widget_set_tooltip_text(view_.get(), WideToUTF8(tooltip_text).c_str()); |
| 368 } | 314 } |
| 369 } | 315 } |
| 370 | 316 |
| 371 void RenderWidgetHostViewGtk::SelectionChanged() { | 317 void RenderWidgetHostViewGtk::SelectionChanged(const std::string& text) { |
| 372 selection_text_.clear(); | 318 GtkClipboard* x_clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); |
| 373 | 319 gtk_clipboard_set_text(x_clipboard, text.c_str(), text.length()); |
| 374 guint32 timestamp = gdk_x11_get_server_time(view_.get()->window); | |
| 375 gtk_selection_owner_set(view_.get(), GDK_SELECTION_PRIMARY, timestamp); | |
| 376 } | |
| 377 | |
| 378 void RenderWidgetHostViewGtk::SetSelectionText(const std::string& text) { | |
| 379 selection_text_ = text; | |
| 380 DCHECK(event_selection_active_); | |
| 381 event_selection_active_ = false; | |
| 382 // Resume normal handling of the active selection_request_event. | |
| 383 GtkWidgetClass* klass = GTK_WIDGET_CLASS(gtk_type_class(GTK_TYPE_WIDGET)); | |
| 384 klass->selection_request_event(view_.get(), &event_selection_); | |
| 385 } | 320 } |
| 386 | 321 |
| 387 BackingStore* RenderWidgetHostViewGtk::AllocBackingStore( | 322 BackingStore* RenderWidgetHostViewGtk::AllocBackingStore( |
| 388 const gfx::Size& size) { | 323 const gfx::Size& size) { |
| 389 Display* display = x11_util::GetXDisplay(); | 324 Display* display = x11_util::GetXDisplay(); |
| 390 void* visual = x11_util::GetVisualFromGtkWidget(view_.get()); | 325 void* visual = x11_util::GetVisualFromGtkWidget(view_.get()); |
| 391 XID root_window = x11_util::GetX11RootWindow(); | 326 XID root_window = x11_util::GetX11RootWindow(); |
| 392 bool use_render = x11_util::QueryRenderSupport(display); | 327 bool use_render = x11_util::QueryRenderSupport(display); |
| 393 bool use_shared_memory = x11_util::QuerySharedMemorySupport(display); | 328 bool use_shared_memory = x11_util::QuerySharedMemorySupport(display); |
| 394 int depth = gtk_widget_get_visual(view_.get())->depth; | 329 int depth = gtk_widget_get_visual(view_.get())->depth; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 | 391 |
| 457 default: | 392 default: |
| 458 gdk_cursor = gdk_cursor_new(current_cursor_.GetCursorType()); | 393 gdk_cursor = gdk_cursor_new(current_cursor_.GetCursorType()); |
| 459 } | 394 } |
| 460 gdk_window_set_cursor(view_.get()->window, gdk_cursor); | 395 gdk_window_set_cursor(view_.get()->window, gdk_cursor); |
| 461 // The window now owns the cursor. | 396 // The window now owns the cursor. |
| 462 if (gdk_cursor) | 397 if (gdk_cursor) |
| 463 gdk_cursor_unref(gdk_cursor); | 398 gdk_cursor_unref(gdk_cursor); |
| 464 } | 399 } |
| 465 | 400 |
| 466 void RenderWidgetHostViewGtk::RequestSelectionText() { | |
| 467 host_->Send(new ViewMsg_RequestSelectionText(host_->routing_id())); | |
| 468 } | |
| 469 | |
| 470 void RenderWidgetHostViewGtk::ReceivedSelectionText(GtkClipboard* clipboard, | 401 void RenderWidgetHostViewGtk::ReceivedSelectionText(GtkClipboard* clipboard, |
| 471 const gchar* text, gpointer userdata) { | 402 const gchar* text, gpointer userdata) { |
| 472 // If there's nothing to paste (|text| is NULL), do nothing. | 403 // If there's nothing to paste (|text| is NULL), do nothing. |
| 473 if (!text) | 404 if (!text) |
| 474 return; | 405 return; |
| 475 RenderWidgetHostViewGtk* host_view = | 406 RenderWidgetHostViewGtk* host_view = |
| 476 reinterpret_cast<RenderWidgetHostViewGtk*>(userdata); | 407 reinterpret_cast<RenderWidgetHostViewGtk*>(userdata); |
| 477 host_view->host_->Send(new ViewMsg_InsertText(host_view->host_->routing_id(), | 408 host_view->host_->Send(new ViewMsg_InsertText(host_view->host_->routing_id(), |
| 478 UTF8ToUTF16(text))); | 409 UTF8ToUTF16(text))); |
| 479 } | 410 } |
| OLD | NEW |