Home | History | Annotate | Download | only in gtk
      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
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/gtk/constrained_window_gtk.h"
      6 
      7 #include <gdk/gdkkeysyms.h>
      8 
      9 #include "chrome/browser/ui/browser_list.h"
     10 #include "chrome/browser/ui/gtk/gtk_util.h"
     11 #include "content/browser/browser_thread.h"
     12 #include "content/browser/tab_contents/tab_contents.h"
     13 
     14 #if defined(TOUCH_UI)
     15 #include "chrome/browser/ui/views/tab_contents/tab_contents_view_touch.h"
     16 #else
     17 #include "chrome/browser/tab_contents/tab_contents_view_gtk.h"
     18 #endif
     19 
     20 ConstrainedWindowGtkDelegate::~ConstrainedWindowGtkDelegate() {
     21 }
     22 
     23 bool ConstrainedWindowGtkDelegate::GetBackgroundColor(GdkColor* color) {
     24   return false;
     25 }
     26 
     27 bool ConstrainedWindowGtkDelegate::ShouldHaveBorderPadding() const {
     28   return true;
     29 }
     30 
     31 ConstrainedWindowGtk::ConstrainedWindowGtk(
     32     TabContents* owner, ConstrainedWindowGtkDelegate* delegate)
     33     : owner_(owner),
     34       delegate_(delegate),
     35       visible_(false),
     36       factory_(this) {
     37   DCHECK(owner);
     38   DCHECK(delegate);
     39   GtkWidget* dialog = delegate->GetWidgetRoot();
     40 
     41   // Unlike other users of CreateBorderBin, we need a dedicated frame around
     42   // our "window".
     43   GtkWidget* ebox = gtk_event_box_new();
     44   GtkWidget* frame = gtk_frame_new(NULL);
     45   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
     46 
     47   GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
     48   if (delegate->ShouldHaveBorderPadding()) {
     49     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
     50         gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder,
     51         gtk_util::kContentAreaBorder, gtk_util::kContentAreaBorder);
     52   }
     53 
     54   GdkColor background;
     55   if (delegate->GetBackgroundColor(&background)) {
     56     gtk_widget_modify_base(ebox, GTK_STATE_NORMAL, &background);
     57     gtk_widget_modify_fg(ebox, GTK_STATE_NORMAL, &background);
     58     gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &background);
     59   }
     60 
     61   if (gtk_widget_get_parent(dialog))
     62     gtk_widget_reparent(dialog, alignment);
     63   else
     64     gtk_container_add(GTK_CONTAINER(alignment), dialog);
     65 
     66   gtk_container_add(GTK_CONTAINER(frame), alignment);
     67   gtk_container_add(GTK_CONTAINER(ebox), frame);
     68   border_.Own(ebox);
     69 
     70   gtk_widget_add_events(widget(), GDK_KEY_PRESS_MASK);
     71   g_signal_connect(widget(), "key-press-event", G_CALLBACK(OnKeyPressThunk),
     72                    this);
     73   g_signal_connect(widget(), "hierarchy-changed",
     74                    G_CALLBACK(OnHierarchyChangedThunk), this);
     75 }
     76 
     77 ConstrainedWindowGtk::~ConstrainedWindowGtk() {
     78   border_.Destroy();
     79 }
     80 
     81 void ConstrainedWindowGtk::ShowConstrainedWindow() {
     82   gtk_widget_show_all(border_.get());
     83 
     84   // We collaborate with TabContentsView and stick ourselves in the
     85   // TabContentsView's floating container.
     86   ContainingView()->AttachConstrainedWindow(this);
     87 
     88   visible_ = true;
     89 }
     90 
     91 void ConstrainedWindowGtk::CloseConstrainedWindow() {
     92   if (visible_)
     93     ContainingView()->RemoveConstrainedWindow(this);
     94   delegate_->DeleteDelegate();
     95   owner_->WillClose(this);
     96 
     97   delete this;
     98 }
     99 
    100 void ConstrainedWindowGtk::FocusConstrainedWindow() {
    101   GtkWidget* focus_widget = delegate_->GetFocusWidget();
    102   if (!focus_widget)
    103     return;
    104 
    105   // The user may have focused another tab. In this case do not grab focus
    106   // until this tab is refocused.
    107   if ((!owner_->delegate() ||
    108           owner_->delegate()->ShouldFocusConstrainedWindow()) &&
    109       gtk_util::IsWidgetAncestryVisible(focus_widget)) {
    110     gtk_widget_grab_focus(focus_widget);
    111   } else {
    112   // TODO(estade): this define should not need to be here because this class
    113   // should not be used on linux/views.
    114 #if defined(TOOLKIT_GTK)
    115     static_cast<TabContentsViewGtk*>(owner_->view())->
    116         SetFocusedWidget(focus_widget);
    117 #endif
    118   }
    119 }
    120 
    121 ConstrainedWindowGtk::TabContentsViewType*
    122     ConstrainedWindowGtk::ContainingView() {
    123   return static_cast<TabContentsViewType*>(owner_->view());
    124 }
    125 
    126 gboolean ConstrainedWindowGtk::OnKeyPress(GtkWidget* sender,
    127                                           GdkEventKey* key) {
    128   if (key->keyval == GDK_Escape) {
    129     // Let the stack unwind so the event handler can release its ref
    130     // on widget().
    131     MessageLoop::current()->PostTask(FROM_HERE,
    132         factory_.NewRunnableMethod(
    133             &ConstrainedWindowGtk::CloseConstrainedWindow));
    134     return TRUE;
    135   }
    136 
    137   return FALSE;
    138 }
    139 
    140 void ConstrainedWindowGtk::OnHierarchyChanged(GtkWidget* sender,
    141                                               GtkWidget* previous_toplevel) {
    142   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    143   if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(widget())))
    144     return;
    145 
    146   FocusConstrainedWindow();
    147 }
    148 
    149 // static
    150 ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog(
    151     TabContents* parent,
    152     ConstrainedWindowGtkDelegate* delegate) {
    153   return new ConstrainedWindowGtk(parent, delegate);
    154 }
    155