Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(409)

Side by Side Diff: chrome/browser/ui/gtk/panels/panel_stack_window_gtk.cc

Issue 231733005: Delete the GTK+ port of Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remerge to ToT Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/panels/panel_stack_window_gtk.h"
6
7 #include <gdk/gdkkeysyms.h>
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/ui/panels/panel.h"
10 #include "chrome/browser/ui/panels/stacked_panel_collection.h"
11 #include "ui/base/x/active_window_watcher_x.h"
12
13 // static
14 NativePanelStackWindow* NativePanelStackWindow::Create(
15 NativePanelStackWindowDelegate* delegate) {
16 return new PanelStackWindowGtk(delegate);
17 }
18
19 PanelStackWindowGtk::PanelStackWindowGtk(
20 NativePanelStackWindowDelegate* delegate)
21 : delegate_(delegate),
22 window_(NULL),
23 is_minimized_(false),
24 bounds_updates_started_(false) {
25 ui::ActiveWindowWatcherX::AddObserver(this);
26 }
27
28 PanelStackWindowGtk::~PanelStackWindowGtk() {
29 ui::ActiveWindowWatcherX::RemoveObserver(this);
30 }
31
32 void PanelStackWindowGtk::Close() {
33 if (!window_)
34 return;
35 gtk_widget_destroy(GTK_WIDGET(window_));
36 window_ = NULL;
37 }
38
39 void PanelStackWindowGtk::AddPanel(Panel* panel) {
40 panels_.push_back(panel);
41
42 EnsureWindowCreated();
43 SetStackWindowBounds();
44
45 // The panel being stacked should not appear on the taskbar.
46 gtk_window_set_skip_taskbar_hint(panel->GetNativeWindow(), true);
47 }
48
49 void PanelStackWindowGtk::RemovePanel(Panel* panel) {
50 panels_.remove(panel);
51
52 SetStackWindowBounds();
53
54 // The panel being unstacked should re-appear on the taskbar.
55 // Note that the underlying gtk window is gone when the panel is being
56 // closed.
57 GtkWindow* gtk_window = panel->GetNativeWindow();
58 if (gtk_window)
59 gtk_window_set_skip_taskbar_hint(gtk_window, false);
60 }
61
62 void PanelStackWindowGtk::MergeWith(NativePanelStackWindow* another) {
63 PanelStackWindowGtk* another_stack =
64 static_cast<PanelStackWindowGtk*>(another);
65 for (Panels::const_iterator iter = another_stack->panels_.begin();
66 iter != another_stack->panels_.end(); ++iter) {
67 Panel* panel = *iter;
68 panels_.push_back(panel);
69 }
70 another_stack->panels_.clear();
71
72 SetStackWindowBounds();
73 }
74
75 bool PanelStackWindowGtk::IsEmpty() const {
76 return panels_.empty();
77 }
78
79 bool PanelStackWindowGtk::HasPanel(Panel* panel) const {
80 return std::find(panels_.begin(), panels_.end(), panel) != panels_.end();
81 }
82
83 void PanelStackWindowGtk::MovePanelsBy(const gfx::Vector2d& delta) {
84 for (Panels::const_iterator iter = panels_.begin();
85 iter != panels_.end(); ++iter) {
86 Panel* panel = *iter;
87 gfx::Rect bounds = panel->GetBounds();
88 bounds.Offset(delta);
89 panel->SetPanelBoundsInstantly(bounds);
90 }
91
92 SetStackWindowBounds();
93 }
94
95 void PanelStackWindowGtk::BeginBatchUpdatePanelBounds(bool animate) {
96 // Bounds animation is not supported on GTK.
97 bounds_updates_started_ = true;
98 }
99
100 void PanelStackWindowGtk::AddPanelBoundsForBatchUpdate(
101 Panel* panel, const gfx::Rect& new_bounds) {
102 DCHECK(bounds_updates_started_);
103
104 // No need to track it if no change is needed.
105 if (panel->GetBounds() == new_bounds)
106 return;
107
108 // New bounds are stored as the map value.
109 bounds_updates_[panel] = new_bounds;
110 }
111
112 void PanelStackWindowGtk::EndBatchUpdatePanelBounds() {
113 DCHECK(bounds_updates_started_);
114
115 bounds_updates_started_ = false;
116
117 for (BoundsUpdates::const_iterator iter = bounds_updates_.begin();
118 iter != bounds_updates_.end(); ++iter) {
119 iter->first->SetPanelBoundsInstantly(iter->second);
120 }
121 bounds_updates_.clear();
122
123 SetStackWindowBounds();
124
125 delegate_->PanelBoundsBatchUpdateCompleted();
126 }
127
128 bool PanelStackWindowGtk::IsAnimatingPanelBounds() const {
129 return bounds_updates_started_;
130 }
131
132 void PanelStackWindowGtk::Minimize() {
133 gtk_window_iconify(window_);
134 }
135
136 bool PanelStackWindowGtk::IsMinimized() const {
137 return is_minimized_;
138 }
139
140 void PanelStackWindowGtk::DrawSystemAttention(bool draw_attention) {
141 gtk_window_set_urgency_hint(window_, draw_attention);
142 }
143
144 void PanelStackWindowGtk::OnPanelActivated(Panel* panel) {
145 // If a panel in a stack is activated, make sure all other panels in the stack
146 // are brought to the top in the z-order.
147 for (Panels::const_iterator iter = panels_.begin();
148 iter != panels_.end(); ++iter) {
149 GtkWindow* gtk_window = (*iter)->GetNativeWindow();
150 if (gtk_window) {
151 GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(gtk_window));
152 gdk_window_raise(gdk_window);
153 }
154 }
155 }
156
157 void PanelStackWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
158 // Bail out if icewm is detected. This is because icewm always creates a
159 // window as active and we do not want to perform the logic here to
160 // activate a panel window when the background window is being created.
161 if (ui::GuessWindowManager() == ui::WM_ICE_WM)
162 return;
163
164 if (!window_ || panels_.empty())
165 return;
166
167 // The background stack window is activated when its taskbar icon is clicked.
168 // When this occurs, we need to activate the most recently active panel.
169 if (gtk_widget_get_window(GTK_WIDGET(window_)) == active_window) {
170 Panel* panel_to_focus =
171 panels_.front()->stack()->most_recently_active_panel();
172 if (panel_to_focus)
173 panel_to_focus->Activate();
174 }
175 }
176
177 gboolean PanelStackWindowGtk::OnWindowDeleteEvent(GtkWidget* widget,
178 GdkEvent* event) {
179 DCHECK(!panels_.empty());
180
181 // Make a copy since closing a panel could modify the list.
182 Panels panels_copy = panels_;
183 for (Panels::const_iterator iter = panels_copy.begin();
184 iter != panels_copy.end(); ++iter) {
185 (*iter)->Close();
186 }
187
188 // Return true to prevent the gtk window from being destroyed. Close will
189 // destroy it for us.
190 return TRUE;
191 }
192
193 gboolean PanelStackWindowGtk::OnWindowState(GtkWidget* widget,
194 GdkEventWindowState* event) {
195 bool is_minimized = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED;
196 if (is_minimized_ == is_minimized)
197 return FALSE;
198 is_minimized_ = is_minimized;
199
200 for (Panels::const_iterator iter = panels_.begin();
201 iter != panels_.end(); ++iter) {
202 GtkWindow* gtk_window = (*iter)->GetNativeWindow();
203 if (is_minimized_)
204 gtk_window_iconify(gtk_window);
205 else
206 gtk_window_deiconify(gtk_window);
207 }
208
209 return FALSE;
210 }
211
212 void PanelStackWindowGtk::EnsureWindowCreated() {
213 if (window_)
214 return;
215
216 DCHECK(!panels_.empty());
217 Panel* panel = panels_.front();
218
219 // Create a small window that stays behinds the panels.
220 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
221 gtk_window_set_decorated(window_, false);
222 gtk_window_set_resizable(window_, false);
223 gtk_window_set_focus_on_map(window_, false);
224 gtk_widget_show(GTK_WIDGET(window_));
225 gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(window_)),
226 panel->GetBounds().x(), panel->GetBounds().y(), 1, 1);
227 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
228
229 // Connect signal handlers to the window.
230 g_signal_connect(window_, "delete-event",
231 G_CALLBACK(OnWindowDeleteEventThunk), this);
232 g_signal_connect(window_, "window-state-event",
233 G_CALLBACK(OnWindowStateThunk), this);
234
235 // Should appear on the taskbar.
236 gtk_window_set_skip_taskbar_hint(window_, false);
237
238 // Set the window icon and title.
239 base::string16 title = delegate_->GetTitle();
240 gtk_window_set_title(window_, base::UTF16ToUTF8(title).c_str());
241
242 gfx::Image app_icon = delegate_->GetIcon();
243 if (!app_icon.IsEmpty())
244 gtk_window_set_icon(window_, app_icon.ToGdkPixbuf());
245 }
246
247 void PanelStackWindowGtk::SetStackWindowBounds() {
248 if (panels_.empty())
249 return;
250 Panel* panel = panels_.front();
251 // Position the small background window a bit away from the left-top corner
252 // such that it will be completely invisible.
253 gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(window_)),
254 panel->GetBounds().x() + 5, panel->GetBounds().y() + 5, 1, 1);
255 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698