constrained_window_gtk.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/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) 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/tab_contents/tab_contents_view_touch.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 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ConstrainedWindowGtkDelegate::ShouldHaveBorderPadding() const { 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochConstrainedWindowGtk::ConstrainedWindowGtk( 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* owner, ConstrainedWindowGtkDelegate* delegate) 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : owner_(owner), 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_(delegate), 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visible_(false), 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick factory_(this) { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(owner); 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(delegate); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* dialog = delegate->GetWidgetRoot(); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unlike other users of CreateBorderBin, we need a dedicated frame around 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // our "window". 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* ebox = gtk_event_box_new(); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* frame = gtk_frame_new(NULL); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (delegate->ShouldHaveBorderPadding()) { 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder, 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder); 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GdkColor background; 55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (delegate->GetBackgroundColor(&background)) { 56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_widget_modify_base(ebox, GTK_STATE_NORMAL, &background); 57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_widget_modify_fg(ebox, GTK_STATE_NORMAL, &background); 58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &background); 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (gtk_widget_get_parent(dialog)) 624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch gtk_widget_reparent(dialog, alignment); 634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch else 644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch gtk_container_add(GTK_CONTAINER(alignment), dialog); 654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_container_add(GTK_CONTAINER(frame), alignment); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_container_add(GTK_CONTAINER(ebox), frame); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch border_.Own(ebox); 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_add_events(widget(), GDK_KEY_PRESS_MASK); 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick g_signal_connect(widget(), "key-press-event", G_CALLBACK(OnKeyPressThunk), 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this); 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen g_signal_connect(widget(), "hierarchy-changed", 74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen G_CALLBACK(OnHierarchyChangedThunk), this); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochConstrainedWindowGtk::~ConstrainedWindowGtk() { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch border_.Destroy(); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConstrainedWindowGtk::ShowConstrainedWindow() { 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show_all(border_.get()); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // We collaborate with TabContentsView and stick ourselves in the 85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // TabContentsView's floating container. 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ContainingView()->AttachConstrainedWindow(this); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visible_ = true; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConstrainedWindowGtk::CloseConstrainedWindow() { 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visible_) 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ContainingView()->RemoveConstrainedWindow(this); 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->DeleteDelegate(); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch owner_->WillClose(this); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete this; 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ConstrainedWindowGtk::FocusConstrainedWindow() { 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GtkWidget* focus_widget = delegate_->GetFocusWidget(); 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!focus_widget) 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // The user may have focused another tab. In this case do not grab focus 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // until this tab is refocused. 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ((!owner_->delegate() || 108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen owner_->delegate()->ShouldFocusConstrainedWindow()) && 109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_util::IsWidgetAncestryVisible(focus_widget)) { 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen gtk_widget_grab_focus(focus_widget); 111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(estade): this define should not need to be here because this class 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // should not be used on linux/views. 114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(TOOLKIT_GTK) 115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static_cast<TabContentsViewGtk*>(owner_->view())-> 116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SetFocusedWidget(focus_widget); 117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif 118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochConstrainedWindowGtk::TabContentsViewType* 122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ConstrainedWindowGtk::ContainingView() { 123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return static_cast<TabContentsViewType*>(owner_->view()); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickgboolean ConstrainedWindowGtk::OnKeyPress(GtkWidget* sender, 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GdkEventKey* key) { 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (key->keyval == GDK_Escape) { 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Let the stack unwind so the event handler can release its ref 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // on widget(). 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MessageLoop::current()->PostTask(FROM_HERE, 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick factory_.NewRunnableMethod( 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &ConstrainedWindowGtk::CloseConstrainedWindow)); 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return TRUE; 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return FALSE; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ConstrainedWindowGtk::OnHierarchyChanged(GtkWidget* sender, 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GtkWidget* previous_toplevel) { 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(widget()))) 144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FocusConstrainedWindow(); 147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog( 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* parent, 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConstrainedWindowGtkDelegate* delegate) { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new ConstrainedWindowGtk(parent, delegate); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 155