constrained_window_gtk.cc revision dc0f95d653279beabeb9817299e2902918ba123e
172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/constrained_window_gtk.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gdk/gdkkeysyms.h> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_list.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 13201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if defined(TOUCH_UI) 15201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h" 16201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#else 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents_view_gtk.h" 18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickConstrainedWindowGtkDelegate::~ConstrainedWindowGtkDelegate() { 21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ConstrainedWindowGtkDelegate::GetBackgroundColor(GdkColor* color) { 24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochConstrainedWindowGtk::ConstrainedWindowGtk( 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* owner, ConstrainedWindowGtkDelegate* delegate) 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : owner_(owner), 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_(delegate), 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visible_(false), 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick factory_(this) { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(owner); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(delegate); 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* dialog = delegate->GetWidgetRoot(); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unlike other users of CreateBorderBin, we need a dedicated frame around 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // our "window". 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* ebox = gtk_event_box_new(); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* frame = gtk_frame_new(NULL); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); 42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder, 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder); 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GdkColor background; 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (delegate->GetBackgroundColor(&background)) { 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_widget_modify_base(ebox, GTK_STATE_NORMAL, &background); 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_widget_modify_fg(ebox, GTK_STATE_NORMAL, &background); 51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &background); 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (gtk_widget_get_parent(dialog)) 554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch gtk_widget_reparent(dialog, alignment); 564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch else 574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch gtk_container_add(GTK_CONTAINER(alignment), dialog); 584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_container_add(GTK_CONTAINER(frame), alignment); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_container_add(GTK_CONTAINER(ebox), frame); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch border_.Own(ebox); 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_add_events(widget(), GDK_KEY_PRESS_MASK); 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_signal_connect(widget(), "key-press-event", G_CALLBACK(OnKeyPressThunk), 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this); 66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen g_signal_connect(widget(), "hierarchy-changed", 67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen G_CALLBACK(OnHierarchyChangedThunk), this); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochConstrainedWindowGtk::~ConstrainedWindowGtk() { 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch border_.Destroy(); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConstrainedWindowGtk::ShowConstrainedWindow() { 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show_all(border_.get()); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // We collaborate with TabContentsView and stick ourselves in the 78201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // TabContentsView's floating container. 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ContainingView()->AttachConstrainedWindow(this); 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visible_ = true; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConstrainedWindowGtk::CloseConstrainedWindow() { 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visible_) 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ContainingView()->RemoveConstrainedWindow(this); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->DeleteDelegate(); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch owner_->WillClose(this); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete this; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ConstrainedWindowGtk::FocusConstrainedWindow() { 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GtkWidget* focus_widget = delegate_->GetFocusWidget(); 95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!focus_widget) 96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // The user may have focused another tab. In this case do not grab focus 99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // until this tab is refocused. 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ((!owner_->delegate() || 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen owner_->delegate()->ShouldFocusConstrainedWindow()) && 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_util::IsWidgetAncestryVisible(focus_widget)) { 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_widget_grab_focus(focus_widget); 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(estade): this define should not need to be here because this class 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // should not be used on linux/views. 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(TOOLKIT_GTK) 108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static_cast<TabContentsViewGtk*>(owner_->view())-> 109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetFocusedWidget(focus_widget); 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif 111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochConstrainedWindowGtk::TabContentsViewType* 115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ConstrainedWindowGtk::ContainingView() { 116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return static_cast<TabContentsViewType*>(owner_->view()); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickgboolean ConstrainedWindowGtk::OnKeyPress(GtkWidget* sender, 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GdkEventKey* key) { 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (key->keyval == GDK_Escape) { 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Let the stack unwind so the event handler can release its ref 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // on widget(). 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MessageLoop::current()->PostTask(FROM_HERE, 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick factory_.NewRunnableMethod( 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &ConstrainedWindowGtk::CloseConstrainedWindow)); 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return TRUE; 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return FALSE; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ConstrainedWindowGtk::OnHierarchyChanged(GtkWidget* sender, 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GtkWidget* previous_toplevel) { 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(widget()))) 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FocusConstrainedWindow(); 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog( 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* parent, 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConstrainedWindowGtkDelegate* delegate) { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new ConstrainedWindowGtk(parent, delegate); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 148