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