| 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/gdkkeysyms.h> | 9 #include <gdk/gdkkeysyms.h> |
| 10 #include <gdk/gdkx.h> | 10 #include <gdk/gdkx.h> |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 if (host_view->parent_ && host_view->activatable() && | 114 if (host_view->parent_ && host_view->activatable() && |
| 115 GDK_Escape == event->keyval) { | 115 GDK_Escape == event->keyval) { |
| 116 // Force popups to close on Esc just in case the renderer is hung. This | 116 // Force popups to close on Esc just in case the renderer is hung. This |
| 117 // allows us to release our keyboard grab. | 117 // allows us to release our keyboard grab. |
| 118 host_view->host_->Shutdown(); | 118 host_view->host_->Shutdown(); |
| 119 } else { | 119 } else { |
| 120 NativeWebKeyboardEvent wke(event); | 120 NativeWebKeyboardEvent wke(event); |
| 121 host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(wke); | 121 host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(wke); |
| 122 } | 122 } |
| 123 | 123 |
| 124 // Save the current modifier-key state before dispatching this event to the |
| 125 // GtkIMContext object so its event handlers can use this state to create |
| 126 // Char events. |
| 127 host_view->im_modifier_state_ = event->state; |
| 128 |
| 124 // Dispatch this event to the GtkIMContext object. | 129 // Dispatch this event to the GtkIMContext object. |
| 125 // It sends a "commit" signal when it has a character to be inserted | 130 // It sends a "commit" signal when it has a character to be inserted |
| 126 // even when we use a US keyboard so that we can send a Char event | 131 // even when we use a US keyboard so that we can send a Char event |
| 127 // (or an IME event) to the renderer in our "commit"-signal handler. | 132 // (or an IME event) to the renderer in our "commit"-signal handler. |
| 128 // We should send a KeyDown (or a KeyUp) event before dispatching this | 133 // We should send a KeyDown (or a KeyUp) event before dispatching this |
| 129 // event to the GtkIMContext object (and send a Char event) so that WebKit | 134 // event to the GtkIMContext object (and send a Char event) so that WebKit |
| 130 // can dispatch the JavaScript events in the following order: onkeydown(), | 135 // can dispatch the JavaScript events in the following order: onkeydown(), |
| 131 // onkeypress(), and onkeyup(). (Many JavaScript pages assume this.) | 136 // onkeypress(), and onkeyup(). (Many JavaScript pages assume this.) |
| 132 // TODO(hbono): we should not dispatch a key event when the input focus | 137 // TODO(hbono): we should not dispatch a key event when the input focus |
| 133 // is in a password input? | 138 // is in a password input? |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 gdk_window_get_origin(widget->window, &x, &y); | 180 gdk_window_get_origin(widget->window, &x, &y); |
| 176 fake_event.globalX = fake_event.x + x; | 181 fake_event.globalX = fake_event.x + x; |
| 177 fake_event.globalY = fake_event.y + y; | 182 fake_event.globalY = fake_event.y + y; |
| 178 fake_event.type = WebKit::WebInputEvent::MouseMove; | 183 fake_event.type = WebKit::WebInputEvent::MouseMove; |
| 179 fake_event.button = WebKit::WebMouseEvent::ButtonNone; | 184 fake_event.button = WebKit::WebMouseEvent::ButtonNone; |
| 180 host_view->GetRenderWidgetHost()->ForwardMouseEvent(fake_event); | 185 host_view->GetRenderWidgetHost()->ForwardMouseEvent(fake_event); |
| 181 } | 186 } |
| 182 | 187 |
| 183 host_view->ShowCurrentCursor(); | 188 host_view->ShowCurrentCursor(); |
| 184 host_view->GetRenderWidgetHost()->Focus(); | 189 host_view->GetRenderWidgetHost()->Focus(); |
| 190 |
| 191 // Notify the GtkIMContext object of this focus-in event and |
| 192 // attach this GtkIMContext object to this window. |
| 193 // We should call gtk_im_context_set_client_window() only when this window |
| 194 // gain (or release) the window focus because an immodule may reset its |
| 195 // internal status when processing this function. |
| 196 gtk_im_context_focus_in(host_view->im_context_); |
| 197 gtk_im_context_set_client_window(host_view->im_context_, |
| 198 host_view->native_view()->window); |
| 185 return FALSE; | 199 return FALSE; |
| 186 } | 200 } |
| 187 | 201 |
| 188 static gboolean OnFocusOut(GtkWidget* widget, GdkEventFocus* focus, | 202 static gboolean OnFocusOut(GtkWidget* widget, GdkEventFocus* focus, |
| 189 RenderWidgetHostViewGtk* host_view) { | 203 RenderWidgetHostViewGtk* host_view) { |
| 190 // Whenever we lose focus, set the cursor back to that of our parent window, | 204 // Whenever we lose focus, set the cursor back to that of our parent window, |
| 191 // which should be the default arrow. | 205 // which should be the default arrow. |
| 192 gdk_window_set_cursor(widget->window, NULL); | 206 gdk_window_set_cursor(widget->window, NULL); |
| 193 // If we are showing a context menu, maintain the illusion that webkit has | 207 // If we are showing a context menu, maintain the illusion that webkit has |
| 194 // focus. | 208 // focus. |
| 195 if (!host_view->is_showing_context_menu_) | 209 if (!host_view->is_showing_context_menu_) |
| 196 host_view->GetRenderWidgetHost()->Blur(); | 210 host_view->GetRenderWidgetHost()->Blur(); |
| 211 |
| 212 // Notify the GtkIMContext object of this focus-in event and |
| 213 // detach this GtkIMContext object from this window. |
| 214 gtk_im_context_focus_out(host_view->im_context_); |
| 215 gtk_im_context_set_client_window(host_view->im_context_, NULL); |
| 197 return FALSE; | 216 return FALSE; |
| 198 } | 217 } |
| 199 | 218 |
| 200 static gboolean ButtonPressReleaseEvent( | 219 static gboolean ButtonPressReleaseEvent( |
| 201 GtkWidget* widget, GdkEventButton* event, | 220 GtkWidget* widget, GdkEventButton* event, |
| 202 RenderWidgetHostViewGtk* host_view) { | 221 RenderWidgetHostViewGtk* host_view) { |
| 203 // We want to translate the coordinates of events that do not originate | 222 // We want to translate the coordinates of events that do not originate |
| 204 // from this widget to be relative to the top left of the widget. | 223 // from this widget to be relative to the top left of the widget. |
| 205 GtkWidget* event_widget = gtk_get_event_widget( | 224 GtkWidget* event_widget = gtk_get_event_widget( |
| 206 reinterpret_cast<GdkEvent*>(event)); | 225 reinterpret_cast<GdkEvent*>(event)); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 UTF8ToWide(preedit_text), cursor_position, -1, -1); | 331 UTF8ToWide(preedit_text), cursor_position, -1, -1); |
| 313 g_free(preedit_text); | 332 g_free(preedit_text); |
| 314 } | 333 } |
| 315 | 334 |
| 316 static void ForwardCharEvent(RenderWidgetHostViewGtk* host_view, | 335 static void ForwardCharEvent(RenderWidgetHostViewGtk* host_view, |
| 317 wchar_t im_character) { | 336 wchar_t im_character) { |
| 318 if (!im_character) | 337 if (!im_character) |
| 319 return; | 338 return; |
| 320 | 339 |
| 321 NativeWebKeyboardEvent char_event(im_character, | 340 NativeWebKeyboardEvent char_event(im_character, |
| 341 host_view->im_modifier_state_, |
| 322 base::Time::Now().ToDoubleT()); | 342 base::Time::Now().ToDoubleT()); |
| 323 host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(char_event); | 343 host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(char_event); |
| 324 } | 344 } |
| 325 | 345 |
| 326 DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWidgetHostViewGtkWidget); | 346 DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWidgetHostViewGtkWidget); |
| 327 }; | 347 }; |
| 328 | 348 |
| 329 // static | 349 // static |
| 330 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( | 350 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( |
| 331 RenderWidgetHost* widget) { | 351 RenderWidgetHost* widget) { |
| 332 return new RenderWidgetHostViewGtk(widget); | 352 return new RenderWidgetHostViewGtk(widget); |
| 333 } | 353 } |
| 334 | 354 |
| 335 RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) | 355 RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) |
| 336 : host_(widget_host), | 356 : host_(widget_host), |
| 337 about_to_validate_and_paint_(false), | 357 about_to_validate_and_paint_(false), |
| 338 is_hidden_(false), | 358 is_hidden_(false), |
| 339 is_loading_(false), | 359 is_loading_(false), |
| 340 is_showing_context_menu_(false), | 360 is_showing_context_menu_(false), |
| 341 parent_host_view_(NULL), | 361 parent_host_view_(NULL), |
| 342 parent_(NULL), | 362 parent_(NULL), |
| 343 is_popup_first_mouse_release_(true), | 363 is_popup_first_mouse_release_(true), |
| 344 im_context_(NULL), | 364 im_context_(NULL), |
| 345 im_is_composing_cjk_text_(false) { | 365 im_is_composing_cjk_text_(false), |
| 366 im_modifier_state_(0) { |
| 346 host_->set_view(this); | 367 host_->set_view(this); |
| 347 } | 368 } |
| 348 | 369 |
| 349 RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() { | 370 RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() { |
| 350 if (im_context_) | 371 if (im_context_) |
| 351 g_object_unref(im_context_); | 372 g_object_unref(im_context_); |
| 352 view_.Destroy(); | 373 view_.Destroy(); |
| 353 } | 374 } |
| 354 | 375 |
| 355 void RenderWidgetHostViewGtk::InitAsChild() { | 376 void RenderWidgetHostViewGtk::InitAsChild() { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 } | 528 } |
| 508 | 529 |
| 509 void RenderWidgetHostViewGtk::IMEUpdateStatus(int control, | 530 void RenderWidgetHostViewGtk::IMEUpdateStatus(int control, |
| 510 const gfx::Rect& caret_rect) { | 531 const gfx::Rect& caret_rect) { |
| 511 // The renderer has updated its IME status. | 532 // The renderer has updated its IME status. |
| 512 // Control the GtkIMContext object according to this status. | 533 // Control the GtkIMContext object according to this status. |
| 513 if (!im_context_) | 534 if (!im_context_) |
| 514 return; | 535 return; |
| 515 | 536 |
| 516 if (control == IME_DISABLE) { | 537 if (control == IME_DISABLE) { |
| 517 // TODO(hbono): this code just resets the GtkIMContext object and | 538 // TODO(hbono): this code just resets the GtkIMContext object. |
| 518 // detaches it from this window. Should we prevent sending key events to | 539 // Should we prevent sending key events to the GtkIMContext object |
| 519 // the GtkIMContext object (or unref it) when we disable IMEs? | 540 // (or unref it) when we disable IMEs? |
| 520 gtk_im_context_reset(im_context_); | 541 gtk_im_context_reset(im_context_); |
| 521 gtk_im_context_set_client_window(im_context_, NULL); | |
| 522 gtk_im_context_set_cursor_location(im_context_, NULL); | 542 gtk_im_context_set_cursor_location(im_context_, NULL); |
| 523 } else { | 543 } else { |
| 524 // TODO(hbono): we should finish (not reset) an ongoing composition | 544 // TODO(hbono): we should finish (not reset) an ongoing composition |
| 525 // when |control| is IME_COMPLETE_COMPOSITION. | 545 // when |control| is IME_COMPLETE_COMPOSITION. |
| 526 | 546 |
| 527 // Attach the GtkIMContext object to this window. | |
| 528 gtk_im_context_set_client_window(im_context_, view_.get()->window); | |
| 529 | |
| 530 // Updates the position of the IME candidate window. | 547 // Updates the position of the IME candidate window. |
| 531 // The position sent from the renderer is a relative one, so we need to | 548 // The position sent from the renderer is a relative one, so we need to |
| 532 // attach the GtkIMContext object to this window before changing the | 549 // attach the GtkIMContext object to this window before changing the |
| 533 // position. | 550 // position. |
| 534 GdkRectangle cursor_rect(caret_rect.ToGdkRectangle()); | 551 GdkRectangle cursor_rect(caret_rect.ToGdkRectangle()); |
| 535 gtk_im_context_set_cursor_location(im_context_, &cursor_rect); | 552 gtk_im_context_set_cursor_location(im_context_, &cursor_rect); |
| 536 } | 553 } |
| 537 } | 554 } |
| 538 | 555 |
| 539 void RenderWidgetHostViewGtk::DidPaintRect(const gfx::Rect& rect) { | 556 void RenderWidgetHostViewGtk::DidPaintRect(const gfx::Rect& rect) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 void RenderWidgetHostViewGtk::ReceivedSelectionText(GtkClipboard* clipboard, | 700 void RenderWidgetHostViewGtk::ReceivedSelectionText(GtkClipboard* clipboard, |
| 684 const gchar* text, gpointer userdata) { | 701 const gchar* text, gpointer userdata) { |
| 685 // If there's nothing to paste (|text| is NULL), do nothing. | 702 // If there's nothing to paste (|text| is NULL), do nothing. |
| 686 if (!text) | 703 if (!text) |
| 687 return; | 704 return; |
| 688 RenderWidgetHostViewGtk* host_view = | 705 RenderWidgetHostViewGtk* host_view = |
| 689 reinterpret_cast<RenderWidgetHostViewGtk*>(userdata); | 706 reinterpret_cast<RenderWidgetHostViewGtk*>(userdata); |
| 690 host_view->host_->Send(new ViewMsg_InsertText(host_view->host_->routing_id(), | 707 host_view->host_->Send(new ViewMsg_InsertText(host_view->host_->routing_id(), |
| 691 UTF8ToUTF16(text))); | 708 UTF8ToUTF16(text))); |
| 692 } | 709 } |
| OLD | NEW |