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

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

Issue 6462017: gtk: Improve fullscreen RenderWidgetHostViewGtk. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update a comment Created 9 years, 10 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) 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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_gtk.h ('k') | chrome/browser/renderer_host/render_widget_host_view_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698