Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(701)

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_gtk.cc

Issue 63145: Copy text selection from renderer to browser every time it changes. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698