Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / web_contents_modal_dialog_manager_gtk.cc
1 // Copyright (c) 2013 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/gtk_util.h"
6 #include "chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h"
7 #include "components/web_modal/native_web_contents_modal_dialog_manager.h"
8 #include "components/web_modal/web_contents_modal_dialog_manager.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "ui/base/gtk/focus_store_gtk.h"
11
12 using web_modal::NativeWebContentsModalDialog;
13 using web_modal::NativeWebContentsModalDialogManagerDelegate;
14
15 namespace {
16
17 // Web contents modal dialog manager implementation for the GTK port. Unlike the
18 // Win32 system, ConstrainedWindowGtk doesn't draw draggable fake windows and
19 // instead just centers the dialog. It is thus an order of magnitude simpler.
20 class NativeWebContentsModalDialogManagerGtk
21     : public web_modal::NativeWebContentsModalDialogManager {
22  public:
23   NativeWebContentsModalDialogManagerGtk(
24       NativeWebContentsModalDialogManagerDelegate* native_delegate)
25           : native_delegate_(native_delegate),
26             shown_widget_(NULL) {
27   }
28
29   virtual ~NativeWebContentsModalDialogManagerGtk() {
30   }
31
32   // NativeWebContentsModalDialogManager overrides
33   virtual void ManageDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
34     DCHECK(g_object_is_floating(GetGtkWidget(dialog)));
35     g_object_ref_sink(GetGtkWidget(dialog));
36
37     g_signal_connect(GetGtkWidget(dialog), "hierarchy-changed",
38                      G_CALLBACK(OnHierarchyChangedThunk), this);
39     g_signal_connect(GetGtkWidget(dialog),
40                      "destroy",
41                      G_CALLBACK(OnDestroyThunk),
42                      this);
43   }
44
45   virtual void ShowDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
46     GtkWidget* widget = GetGtkWidget(dialog);
47
48     // Any previously-shown widget should be destroyed before showing a new
49     // widget.
50     DCHECK(shown_widget_ == widget || shown_widget_ == NULL);
51     gtk_widget_show_all(widget);
52
53     if (!shown_widget_) {
54       // We collaborate with WebContentsView and stick ourselves in the
55       // WebContentsView's floating container.
56       ContainingView()->AttachWebContentsModalDialog(widget);
57     }
58
59     shown_widget_ = widget;
60   }
61
62   virtual void HideDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
63     gtk_widget_hide(GetGtkWidget(dialog));
64   }
65
66   virtual void CloseDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
67     gtk_widget_destroy(GetGtkWidget(dialog));
68   }
69
70   virtual void FocusDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
71     GtkWidget* focus_widget =
72         reinterpret_cast<GtkWidget*>(
73             g_object_get_data(G_OBJECT(GetGtkWidget(dialog)), "focus_widget"));
74
75     if (!focus_widget)
76       return;
77
78     // The user may have focused another tab. In this case do not grab focus
79     // until this tab is refocused.
80     if (gtk_util::IsWidgetAncestryVisible(focus_widget))
81       gtk_widget_grab_focus(focus_widget);
82     else
83       ContainingView()->focus_store()->SetWidget(focus_widget);
84   }
85
86   virtual void PulseDialog(NativeWebContentsModalDialog dialog) OVERRIDE {
87   }
88
89   virtual void HostChanged(
90       web_modal::WebContentsModalDialogHost* new_host) OVERRIDE {
91   }
92
93  private:
94   typedef ChromeWebContentsViewDelegateGtk TabContentsViewType;
95
96   GtkWidget* GetGtkWidget(NativeWebContentsModalDialog dialog) {
97     return GTK_WIDGET(dialog);
98   }
99
100   // Returns the View that we collaborate with to position ourselves.
101   TabContentsViewType* ContainingView() const {
102     // WebContents may be destroyed already on tab shutdown.
103      content::WebContents* web_contents = native_delegate_->GetWebContents();
104     return web_contents ?
105         ChromeWebContentsViewDelegateGtk::GetFor(web_contents) : NULL;
106   }
107
108   CHROMEGTK_CALLBACK_1(NativeWebContentsModalDialogManagerGtk,
109                        void,
110                        OnHierarchyChanged,
111                        GtkWidget*);
112   CHROMEGTK_CALLBACK_0(NativeWebContentsModalDialogManagerGtk, void, OnDestroy);
113
114   NativeWebContentsModalDialogManagerDelegate* native_delegate_;
115
116   // The widget currently being shown.
117   GtkWidget* shown_widget_;
118
119   DISALLOW_COPY_AND_ASSIGN(NativeWebContentsModalDialogManagerGtk);
120 };
121
122 void NativeWebContentsModalDialogManagerGtk::OnHierarchyChanged(
123     GtkWidget* sender,
124     GtkWidget* previous_toplevel) {
125   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
126
127   if (!gtk_widget_is_toplevel(gtk_widget_get_toplevel(sender)))
128     return;
129
130   FocusDialog(sender);
131 }
132
133 void NativeWebContentsModalDialogManagerGtk::OnDestroy(
134     GtkWidget* sender) {
135   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
136
137   if (shown_widget_ == sender) {
138     // The containing view may already be destroyed on tab shutdown.
139     if (ContainingView())
140       ContainingView()->RemoveWebContentsModalDialog(sender);
141
142     shown_widget_ = NULL;
143   }
144
145   native_delegate_->WillClose(sender);
146
147   g_object_unref(sender);
148 }
149
150 }  // namespace
151
152 namespace web_modal {
153
154 NativeWebContentsModalDialogManager*
155     WebContentsModalDialogManager::CreateNativeManager(
156         NativeWebContentsModalDialogManagerDelegate* native_delegate) {
157   return new NativeWebContentsModalDialogManagerGtk(native_delegate);
158 }
159
160 }  // namespace web_modal