OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // If this gets included after the gtk headers, then a bunch of compiler | 7 // If this gets included after the gtk headers, then a bunch of compiler |
8 // errors happen because of a "#define Status int" in Xlib.h, which interacts | 8 // errors happen because of a "#define Status int" in Xlib.h, which interacts |
9 // badly with net::URLRequestStatus::Status. | 9 // badly with net::URLRequestStatus::Status. |
10 #include "chrome/common/render_messages.h" | 10 #include "chrome/common/render_messages.h" |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
142 static gboolean ExposeEvent(GtkWidget* widget, GdkEventExpose* expose, | 142 static gboolean ExposeEvent(GtkWidget* widget, GdkEventExpose* expose, |
143 RenderWidgetHostViewGtk* host_view) { | 143 RenderWidgetHostViewGtk* host_view) { |
144 const gfx::Rect damage_rect(expose->area); | 144 const gfx::Rect damage_rect(expose->area); |
145 host_view->Paint(damage_rect); | 145 host_view->Paint(damage_rect); |
146 return FALSE; | 146 return FALSE; |
147 } | 147 } |
148 | 148 |
149 static gboolean KeyPressReleaseEvent(GtkWidget* widget, GdkEventKey* event, | 149 static gboolean KeyPressReleaseEvent(GtkWidget* widget, GdkEventKey* event, |
150 RenderWidgetHostViewGtk* host_view) { | 150 RenderWidgetHostViewGtk* host_view) { |
151 if (host_view->IsPopup() && host_view->NeedsInputGrab() && | 151 if (host_view->IsPopup() && host_view->NeedsInputGrab() && |
152 GDK_Escape == event->keyval) { | 152 GDK_Escape == event->keyval) { |
piman
2011/02/10 02:28:45
Does "Esc" still close the fullscreen window ? I w
Daniel Erat
2011/02/10 04:45:19
Yes, it does. I'd assumed that Flash was handling
| |
153 // Force popups to close on Esc just in case the renderer is hung. This | 153 // Force popups to close on Esc just in case the renderer is hung. This |
154 // allows us to release our keyboard grab. | 154 // allows us to release our keyboard grab. |
155 host_view->host_->Shutdown(); | 155 host_view->host_->Shutdown(); |
156 } else { | 156 } else { |
157 // Send key event to input method. | 157 // Send key event to input method. |
158 host_view->im_context_->ProcessKeyEvent(event); | 158 host_view->im_context_->ProcessKeyEvent(event); |
159 } | 159 } |
160 | 160 |
161 // We return TRUE because we did handle the event. If it turns out webkit | 161 // We return TRUE because we did handle the event. If it turns out webkit |
162 // can't handle the event, we'll deal with it in | 162 // can't handle the event, we'll deal with it in |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
482 } | 482 } |
483 | 483 |
484 RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) | 484 RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) |
485 : host_(widget_host), | 485 : host_(widget_host), |
486 about_to_validate_and_paint_(false), | 486 about_to_validate_and_paint_(false), |
487 is_hidden_(false), | 487 is_hidden_(false), |
488 is_loading_(false), | 488 is_loading_(false), |
489 is_showing_context_menu_(false), | 489 is_showing_context_menu_(false), |
490 overlay_color_(0), | 490 overlay_color_(0), |
491 overlay_animation_(this), | 491 overlay_animation_(this), |
492 parent_host_view_(NULL), | |
493 parent_(NULL), | 492 parent_(NULL), |
494 is_popup_first_mouse_release_(true), | 493 is_popup_first_mouse_release_(true), |
495 was_focused_before_grab_(false), | 494 was_focused_before_grab_(false), |
496 do_x_grab_(false), | 495 do_x_grab_(false), |
496 is_fullscreen_(false), | |
497 dragged_at_horizontal_edge_(0), | 497 dragged_at_horizontal_edge_(0), |
498 dragged_at_vertical_edge_(0) { | 498 dragged_at_vertical_edge_(0) { |
499 host_->set_view(this); | 499 host_->set_view(this); |
500 } | 500 } |
501 | 501 |
502 RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() { | 502 RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() { |
503 view_.Destroy(); | 503 view_.Destroy(); |
504 } | 504 } |
505 | 505 |
506 void RenderWidgetHostViewGtk::InitAsChild() { | 506 void RenderWidgetHostViewGtk::InitAsChild() { |
507 view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this)); | 507 DoSharedInit(); |
508 // |im_context_| must be created after creating |view_| widget. | |
509 im_context_.reset(new GtkIMContextWrapper(this)); | |
510 // |key_bindings_handler_| must be created after creating |view_| widget. | |
511 key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get())); | |
512 plugin_container_manager_.set_host_widget(view_.get()); | |
513 | |
514 #if defined(OS_CHROMEOS) | |
515 tooltip_window_.reset(new views::TooltipWindowGtk(view_.get())); | |
516 #endif // defined(OS_CHROMEOS) | |
517 | |
518 overlay_animation_.SetDuration(kFadeEffectDuration); | 508 overlay_animation_.SetDuration(kFadeEffectDuration); |
519 overlay_animation_.SetSlideDuration(kFadeEffectDuration); | 509 overlay_animation_.SetSlideDuration(kFadeEffectDuration); |
520 | |
521 gtk_widget_show(view_.get()); | 510 gtk_widget_show(view_.get()); |
522 } | 511 } |
523 | 512 |
524 void RenderWidgetHostViewGtk::InitAsPopup( | 513 void RenderWidgetHostViewGtk::InitAsPopup( |
525 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { | 514 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { |
526 DoInitAsPopup(parent_host_view, GTK_WINDOW_POPUP, pos, false); | 515 // If we aren't a popup, then |window| will be leaked. |
516 DCHECK(IsPopup()); | |
517 | |
518 DoSharedInit(); | |
519 parent_ = parent_host_view->GetNativeView(); | |
520 GtkWindow* window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_POPUP)); | |
521 gtk_container_add(GTK_CONTAINER(window), view_.get()); | |
522 DoPopupOrFullscreenInit(window, pos); | |
523 | |
524 // The underlying X window needs to be created and mapped by the above code | |
525 // before we can grab the input devices. | |
526 if (NeedsInputGrab()) { | |
527 // Grab all input for the app. If a click lands outside the bounds of the | |
528 // popup, WebKit will notice and destroy us. Before doing this we need | |
529 // to ensure that the the popup is added to the browser's window group, | |
530 // to allow for the grabs to work correctly. | |
531 gtk_window_group_add_window(gtk_window_get_group( | |
532 GTK_WINDOW(gtk_widget_get_toplevel(parent_))), window); | |
533 gtk_grab_add(view_.get()); | |
534 | |
535 // We need for the application to do an X grab as well. However if the app | |
536 // already has an X grab (as in the case of extension popup), an app grab | |
537 // will suffice. | |
538 do_x_grab_ = !gdk_pointer_is_grabbed(); | |
539 | |
540 // Now grab all of X's input. | |
541 if (do_x_grab_) { | |
542 gdk_pointer_grab( | |
543 parent_->window, | |
544 TRUE, // Only events outside of the window are reported with respect | |
545 // to |parent_->window|. | |
546 static_cast<GdkEventMask>(GDK_BUTTON_PRESS_MASK | | |
547 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK), | |
548 NULL, | |
549 NULL, | |
550 GDK_CURRENT_TIME); | |
551 // We grab keyboard events too so things like alt+tab are eaten. | |
552 gdk_keyboard_grab(parent_->window, TRUE, GDK_CURRENT_TIME); | |
553 } | |
554 } | |
527 } | 555 } |
528 | 556 |
529 void RenderWidgetHostViewGtk::InitAsFullscreen( | 557 void RenderWidgetHostViewGtk::InitAsFullscreen() { |
530 RenderWidgetHostView* parent_host_view) { | 558 DoSharedInit(); |
531 DoInitAsPopup(parent_host_view, GTK_WINDOW_TOPLEVEL, gfx::Rect(), true); | 559 |
560 is_fullscreen_ = true; | |
561 GtkWindow* window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); | |
562 gtk_window_set_decorated(window, FALSE); | |
563 gtk_window_fullscreen(window); | |
564 gtk_container_add(GTK_CONTAINER(window), view_.get()); | |
565 | |
566 // Try to move and resize the window to cover the screen in case the window | |
567 // manager doesn't support _NET_WM_STATE_FULLSCREEN. | |
568 GdkScreen* screen = gtk_window_get_screen(window); | |
569 gfx::Rect bounds( | |
570 0, 0, gdk_screen_get_width(screen), gdk_screen_get_height(screen)); | |
571 DoPopupOrFullscreenInit(window, bounds); | |
532 } | 572 } |
533 | 573 |
534 RenderWidgetHost* RenderWidgetHostViewGtk::GetRenderWidgetHost() const { | 574 RenderWidgetHost* RenderWidgetHostViewGtk::GetRenderWidgetHost() const { |
535 return host_; | 575 return host_; |
536 } | 576 } |
537 | 577 |
538 void RenderWidgetHostViewGtk::DidBecomeSelected() { | 578 void RenderWidgetHostViewGtk::DidBecomeSelected() { |
539 if (!is_hidden_) | 579 if (!is_hidden_) |
540 return; | 580 return; |
541 | 581 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 } | 725 } |
686 } | 726 } |
687 | 727 |
688 void RenderWidgetHostViewGtk::RenderViewGone(base::TerminationStatus status, | 728 void RenderWidgetHostViewGtk::RenderViewGone(base::TerminationStatus status, |
689 int error_code) { | 729 int error_code) { |
690 Destroy(); | 730 Destroy(); |
691 plugin_container_manager_.set_host_widget(NULL); | 731 plugin_container_manager_.set_host_widget(NULL); |
692 } | 732 } |
693 | 733 |
694 void RenderWidgetHostViewGtk::Destroy() { | 734 void RenderWidgetHostViewGtk::Destroy() { |
695 if (IsPopup()) { | 735 if (do_x_grab_) { |
696 if (do_x_grab_) { | 736 // Undo the X grab. |
697 // Undo the X grab. | 737 GdkDisplay* display = gtk_widget_get_display(parent_); |
698 GdkDisplay* display = gtk_widget_get_display(parent_); | 738 gdk_display_pointer_ungrab(display, GDK_CURRENT_TIME); |
699 gdk_display_pointer_ungrab(display, GDK_CURRENT_TIME); | 739 gdk_display_keyboard_ungrab(display, GDK_CURRENT_TIME); |
700 gdk_display_keyboard_ungrab(display, GDK_CURRENT_TIME); | 740 } |
701 } | 741 |
742 // If this is a popup or fullscreen widget, then we need to destroy the window | |
743 // that we created to hold it. | |
744 if (IsPopup() || is_fullscreen_) | |
702 gtk_widget_destroy(gtk_widget_get_parent(view_.get())); | 745 gtk_widget_destroy(gtk_widget_get_parent(view_.get())); |
703 } | |
704 | 746 |
705 // Remove |view_| from all containers now, so nothing else can hold a | 747 // Remove |view_| from all containers now, so nothing else can hold a |
706 // reference to |view_|'s widget except possibly a gtk signal handler if | 748 // reference to |view_|'s widget except possibly a gtk signal handler if |
707 // this code is currently executing within the context of a gtk signal | 749 // this code is currently executing within the context of a gtk signal |
708 // handler. Note that |view_| is still alive after this call. It will be | 750 // handler. Note that |view_| is still alive after this call. It will be |
709 // deallocated in the destructor. | 751 // deallocated in the destructor. |
710 // See http://www.crbug.com/11847 for details. | 752 // See http://www.crbug.com/11847 for details. |
711 gtk_widget_destroy(view_.get()); | 753 gtk_widget_destroy(view_.get()); |
712 | 754 |
713 // The RenderWidgetHost's destruction led here, so don't call it. | 755 // The RenderWidgetHost's destruction led here, so don't call it. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
752 #if !defined(TOOLKIT_VIEWS) | 794 #if !defined(TOOLKIT_VIEWS) |
753 void RenderWidgetHostViewGtk::AppendInputMethodsContextMenu(MenuGtk* menu) { | 795 void RenderWidgetHostViewGtk::AppendInputMethodsContextMenu(MenuGtk* menu) { |
754 im_context_->AppendInputMethodsContextMenu(menu); | 796 im_context_->AppendInputMethodsContextMenu(menu); |
755 } | 797 } |
756 #endif | 798 #endif |
757 | 799 |
758 bool RenderWidgetHostViewGtk::NeedsInputGrab() { | 800 bool RenderWidgetHostViewGtk::NeedsInputGrab() { |
759 return popup_type_ == WebKit::WebPopupTypeSelect; | 801 return popup_type_ == WebKit::WebPopupTypeSelect; |
760 } | 802 } |
761 | 803 |
762 bool RenderWidgetHostViewGtk::IsPopup() { | 804 bool RenderWidgetHostViewGtk::IsPopup() const { |
763 return popup_type_ != WebKit::WebPopupTypeNone; | 805 return popup_type_ != WebKit::WebPopupTypeNone; |
764 } | 806 } |
765 | 807 |
808 void RenderWidgetHostViewGtk::DoSharedInit() { | |
809 view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this)); | |
810 im_context_.reset(new GtkIMContextWrapper(this)); | |
811 key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get())); | |
812 plugin_container_manager_.set_host_widget(view_.get()); | |
813 #if defined(OS_CHROMEOS) | |
814 tooltip_window_.reset(new views::TooltipWindowGtk(view_.get())); | |
815 #endif | |
816 } | |
817 | |
818 void RenderWidgetHostViewGtk::DoPopupOrFullscreenInit(GtkWindow* window, | |
819 const gfx::Rect& bounds) { | |
820 requested_size_ = bounds.size(); | |
821 host_->WasResized(); | |
822 | |
823 gtk_widget_set_size_request( | |
824 view_.get(), | |
825 std::min(requested_size_.width(), kMaxWindowWidth), | |
826 std::min(requested_size_.height(), kMaxWindowHeight)); | |
827 | |
828 // Don't allow the window to be resized. This also forces the window to | |
829 // shrink down to the size of its child contents. | |
830 gtk_window_set_resizable(window, FALSE); | |
831 gtk_window_set_default_size(window, -1, -1); | |
832 gtk_window_move(window, bounds.x(), bounds.y()); | |
833 | |
834 gtk_widget_show_all(GTK_WIDGET(window)); | |
835 } | |
836 | |
766 BackingStore* RenderWidgetHostViewGtk::AllocBackingStore( | 837 BackingStore* RenderWidgetHostViewGtk::AllocBackingStore( |
767 const gfx::Size& size) { | 838 const gfx::Size& size) { |
768 return new BackingStoreX(host_, size, | 839 return new BackingStoreX(host_, size, |
769 ui::GetVisualFromGtkWidget(view_.get()), | 840 ui::GetVisualFromGtkWidget(view_.get()), |
770 gtk_widget_get_visual(view_.get())->depth); | 841 gtk_widget_get_visual(view_.get())->depth); |
771 } | 842 } |
772 | 843 |
773 void RenderWidgetHostViewGtk::SetBackground(const SkBitmap& background) { | 844 void RenderWidgetHostViewGtk::SetBackground(const SkBitmap& background) { |
774 RenderWidgetHostView::SetBackground(background); | 845 RenderWidgetHostView::SetBackground(background); |
775 host_->Send(new ViewMsg_SetBackground(host_->routing_id(), background)); | 846 host_->Send(new ViewMsg_SetBackground(host_->routing_id(), background)); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
950 } | 1021 } |
951 } else { | 1022 } else { |
952 gdk_cursor = current_cursor_.GetNativeCursor(); | 1023 gdk_cursor = current_cursor_.GetNativeCursor(); |
953 } | 1024 } |
954 gdk_window_set_cursor(view_.get()->window, gdk_cursor); | 1025 gdk_window_set_cursor(view_.get()->window, gdk_cursor); |
955 // The window now owns the cursor. | 1026 // The window now owns the cursor. |
956 if (should_unref && gdk_cursor) | 1027 if (should_unref && gdk_cursor) |
957 gdk_cursor_unref(gdk_cursor); | 1028 gdk_cursor_unref(gdk_cursor); |
958 } | 1029 } |
959 | 1030 |
960 void RenderWidgetHostViewGtk::DoInitAsPopup( | |
961 RenderWidgetHostView* parent_host_view, | |
962 GtkWindowType window_type, | |
963 const gfx::Rect& pos, | |
964 bool is_fullscreen) { | |
965 // If we are not a popup, then popup will be leaked. | |
966 DCHECK(IsPopup()); | |
967 | |
968 parent_host_view_ = parent_host_view; | |
969 parent_ = parent_host_view->GetNativeView(); | |
970 GtkWidget* popup = gtk_window_new(window_type); | |
971 gtk_window_set_decorated(GTK_WINDOW(popup), FALSE); | |
972 view_.Own(RenderWidgetHostViewGtkWidget::CreateNewWidget(this)); | |
973 // |im_context_| must be created after creating |view_| widget. | |
974 im_context_.reset(new GtkIMContextWrapper(this)); | |
975 // |key_bindings_handler_| must be created after creating |view_| widget. | |
976 key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get())); | |
977 plugin_container_manager_.set_host_widget(view_.get()); | |
978 | |
979 #if defined(OS_CHROMEOS) | |
980 tooltip_window_.reset(new views::TooltipWindowGtk(view_.get())); | |
981 #endif // defined(OS_CHROMEOS) | |
982 | |
983 gtk_container_add(GTK_CONTAINER(popup), view_.get()); | |
984 | |
985 if (is_fullscreen) { | |
986 // Set the request size to the size of the screen. | |
987 // TODO(boliu): Make sure this works for multi-monitor set ups and move this | |
988 // to some utility function. | |
989 GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(popup)); | |
990 requested_size_ = gfx::Size( | |
991 std::min(gdk_screen_get_width(screen), kMaxWindowWidth), | |
992 std::min(gdk_screen_get_height(screen), kMaxWindowHeight)); | |
993 } else { | |
994 requested_size_ = gfx::Size(std::min(pos.width(), kMaxWindowWidth), | |
995 std::min(pos.height(), kMaxWindowHeight)); | |
996 } | |
997 host_->WasResized(); | |
998 | |
999 gtk_widget_set_size_request(view_.get(), requested_size_.width(), | |
1000 requested_size_.height()); | |
1001 // Don't allow the window to be resized. This also forces the window to | |
1002 // shrink down to the size of its child contents. | |
1003 gtk_window_set_resizable(GTK_WINDOW(popup), FALSE); | |
1004 gtk_window_set_default_size(GTK_WINDOW(popup), -1, -1); | |
1005 gtk_window_move(GTK_WINDOW(popup), pos.x(), pos.y()); | |
1006 if (is_fullscreen) { | |
1007 gtk_window_fullscreen(GTK_WINDOW(popup)); | |
1008 } | |
1009 | |
1010 gtk_widget_show_all(popup); | |
1011 | |
1012 // If we are not activatable, we don't want to grab keyboard input, | |
1013 // and webkit will manage our destruction. | |
1014 // For unknown reason, calling gtk_grab_add() before realizing the widget may | |
1015 // cause an assertion failure. See http://crbug.com/51834. So we do it after | |
1016 // showing the popup. | |
1017 if (NeedsInputGrab()) { | |
1018 // Grab all input for the app. If a click lands outside the bounds of the | |
1019 // popup, WebKit will notice and destroy us. Before doing this we need | |
1020 // to ensure that the the popup is added to the browser's window group, | |
1021 // to allow for the grabs to work correctly. | |
1022 gtk_window_group_add_window(gtk_window_get_group( | |
1023 GTK_WINDOW(gtk_widget_get_toplevel(parent_))), GTK_WINDOW(popup)); | |
1024 gtk_grab_add(view_.get()); | |
1025 | |
1026 // We need for the application to do an X grab as well. However if the app | |
1027 // already has an X grab (as in the case of extension popup), an app grab | |
1028 // will suffice. | |
1029 do_x_grab_ = !gdk_pointer_is_grabbed(); | |
1030 | |
1031 // Now grab all of X's input. | |
1032 if (do_x_grab_) { | |
1033 gdk_pointer_grab( | |
1034 parent_->window, | |
1035 TRUE, // Only events outside of the window are reported with respect | |
1036 // to |parent_->window|. | |
1037 static_cast<GdkEventMask>(GDK_BUTTON_PRESS_MASK | | |
1038 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK), | |
1039 NULL, | |
1040 NULL, | |
1041 GDK_CURRENT_TIME); | |
1042 // We grab keyboard events too so things like alt+tab are eaten. | |
1043 gdk_keyboard_grab(parent_->window, TRUE, GDK_CURRENT_TIME); | |
1044 } | |
1045 } | |
1046 } | |
1047 | |
1048 void RenderWidgetHostViewGtk::CreatePluginContainer( | 1031 void RenderWidgetHostViewGtk::CreatePluginContainer( |
1049 gfx::PluginWindowHandle id) { | 1032 gfx::PluginWindowHandle id) { |
1050 plugin_container_manager_.CreatePluginContainer(id); | 1033 plugin_container_manager_.CreatePluginContainer(id); |
1051 } | 1034 } |
1052 | 1035 |
1053 void RenderWidgetHostViewGtk::DestroyPluginContainer( | 1036 void RenderWidgetHostViewGtk::DestroyPluginContainer( |
1054 gfx::PluginWindowHandle id) { | 1037 gfx::PluginWindowHandle id) { |
1055 plugin_container_manager_.DestroyPluginContainer(id); | 1038 plugin_container_manager_.DestroyPluginContainer(id); |
1056 } | 1039 } |
1057 | 1040 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1121 } | 1104 } |
1122 | 1105 |
1123 // static | 1106 // static |
1124 RenderWidgetHostView* | 1107 RenderWidgetHostView* |
1125 RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView( | 1108 RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView( |
1126 gfx::NativeView widget) { | 1109 gfx::NativeView widget) { |
1127 gpointer user_data = g_object_get_data(G_OBJECT(widget), | 1110 gpointer user_data = g_object_get_data(G_OBJECT(widget), |
1128 kRenderWidgetHostViewKey); | 1111 kRenderWidgetHostViewKey); |
1129 return reinterpret_cast<RenderWidgetHostView*>(user_data); | 1112 return reinterpret_cast<RenderWidgetHostView*>(user_data); |
1130 } | 1113 } |
OLD | NEW |