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

Side by Side Diff: chrome/browser/ui/gtk/extensions/shell_window_gtk.cc

Issue 11280173: Rename ShellWindow* classes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge fix Created 8 years 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) 2012 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/extensions/shell_window_gtk.h"
6
7 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
10 #include "chrome/browser/ui/gtk/gtk_util.h"
11 #include "chrome/browser/ui/gtk/gtk_window_util.h"
12 #include "chrome/browser/web_applications/web_app.h"
13 #include "chrome/common/extensions/extension.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/render_widget_host_view.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/browser/web_contents_view.h"
18 #include "ui/base/x/active_window_watcher_x.h"
19 #include "ui/gfx/image/image.h"
20 #include "ui/gfx/rect.h"
21
22 namespace {
23
24 // The timeout in milliseconds before we'll get the true window position with
25 // gtk_window_get_position() after the last GTK configure-event signal.
26 const int kDebounceTimeoutMilliseconds = 100;
27
28 } // namespace
29
30 ShellWindowGtk::ShellWindowGtk(ShellWindow* shell_window,
31 const ShellWindow::CreateParams& params)
32 : shell_window_(shell_window),
33 window_(NULL),
34 state_(GDK_WINDOW_STATE_WITHDRAWN),
35 is_active_(false),
36 content_thinks_its_fullscreen_(false),
37 frameless_(params.frame == ShellWindow::CreateParams::FRAME_NONE) {
38 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
39
40 gfx::NativeView native_view =
41 web_contents()->GetView()->GetNativeView();
42 gtk_container_add(GTK_CONTAINER(window_), native_view);
43
44 if (params.bounds.x() != INT_MIN && params.bounds.y() != INT_MIN)
45 gtk_window_move(window_, params.bounds.x(), params.bounds.y());
46
47 // This is done to avoid a WM "feature" where setting the window size to
48 // the monitor size causes the WM to set the EWMH for full screen mode.
49 if (frameless_ &&
50 gtk_window_util::BoundsMatchMonitorSize(window_, params.bounds)) {
51 gtk_window_set_default_size(
52 window_, params.bounds.width(), params.bounds.height() - 1);
53 } else {
54 gtk_window_set_default_size(
55 window_, params.bounds.width(), params.bounds.height());
56 }
57
58 // make sure bounds_ and restored_bounds_ have correct values until we
59 // get our first configure-event
60 bounds_ = restored_bounds_ = params.bounds;
61 gint x, y;
62 gtk_window_get_position(window_, &x, &y);
63 bounds_.set_origin(gfx::Point(x, y));
64
65 // Hide titlebar when {frame: 'none'} specified on ShellWindow.
66 if (frameless_)
67 gtk_window_set_decorated(window_, false);
68
69 int min_width = params.minimum_size.width();
70 int min_height = params.minimum_size.height();
71 int max_width = params.maximum_size.width();
72 int max_height = params.maximum_size.height();
73 GdkGeometry hints;
74 int hints_mask = 0;
75 if (min_width || min_height) {
76 hints.min_height = min_height;
77 hints.min_width = min_width;
78 hints_mask |= GDK_HINT_MIN_SIZE;
79 }
80 if (max_width || max_height) {
81 hints.max_height = max_height ? max_height : G_MAXINT;
82 hints.max_width = max_width ? max_width : G_MAXINT;
83 hints_mask |= GDK_HINT_MAX_SIZE;
84 }
85 if (hints_mask) {
86 gtk_window_set_geometry_hints(
87 window_,
88 GTK_WIDGET(window_),
89 &hints,
90 static_cast<GdkWindowHints>(hints_mask));
91 }
92
93 // In some (older) versions of compiz, raising top-level windows when they
94 // are partially off-screen causes them to get snapped back on screen, not
95 // always even on the current virtual desktop. If we are running under
96 // compiz, suppress such raises, as they are not necessary in compiz anyway.
97 if (ui::GuessWindowManager() == ui::WM_COMPIZ)
98 suppress_window_raise_ = true;
99
100 gtk_window_set_title(window_, extension()->name().c_str());
101
102 gtk_window_util::SetWindowCustomClass(window_,
103 web_app::GetWMClassFromAppName(extension()->name()));
104
105 g_signal_connect(window_, "delete-event",
106 G_CALLBACK(OnMainWindowDeleteEventThunk), this);
107 g_signal_connect(window_, "configure-event",
108 G_CALLBACK(OnConfigureThunk), this);
109 g_signal_connect(window_, "window-state-event",
110 G_CALLBACK(OnWindowStateThunk), this);
111 if (frameless_) {
112 g_signal_connect(window_, "button-press-event",
113 G_CALLBACK(OnButtonPressThunk), this);
114 }
115
116 // Add the keybinding registry.
117 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
118 shell_window_->profile(),
119 window_,
120 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
121 shell_window_));
122
123 ui::ActiveWindowWatcherX::AddObserver(this);
124 }
125
126 ShellWindowGtk::~ShellWindowGtk() {
127 ui::ActiveWindowWatcherX::RemoveObserver(this);
128 }
129
130 bool ShellWindowGtk::IsActive() const {
131 if (ui::ActiveWindowWatcherX::WMSupportsActivation())
132 return is_active_;
133
134 // This still works even though we don't get the activation notification.
135 return gtk_window_is_active(window_);
136 }
137
138 bool ShellWindowGtk::IsMaximized() const {
139 return (state_ & GDK_WINDOW_STATE_MAXIMIZED);
140 }
141
142 bool ShellWindowGtk::IsMinimized() const {
143 return (state_ & GDK_WINDOW_STATE_ICONIFIED);
144 }
145
146 bool ShellWindowGtk::IsFullscreen() const {
147 return false;
148 }
149
150 gfx::NativeWindow ShellWindowGtk::GetNativeWindow() {
151 return window_;
152 }
153
154 gfx::Rect ShellWindowGtk::GetRestoredBounds() const {
155 return restored_bounds_;
156 }
157
158 gfx::Rect ShellWindowGtk::GetBounds() const {
159 return bounds_;
160 }
161
162 void ShellWindowGtk::Show() {
163 gtk_window_present(window_);
164 }
165
166 void ShellWindowGtk::ShowInactive() {
167 gtk_window_set_focus_on_map(window_, false);
168 gtk_widget_show(GTK_WIDGET(window_));
169 }
170
171 void ShellWindowGtk::Hide() {
172 gtk_widget_hide(GTK_WIDGET(window_));
173 }
174
175 void ShellWindowGtk::Close() {
176 shell_window_->OnNativeWindowChanged();
177
178 // Cancel any pending callback from the window configure debounce timer.
179 window_configure_debounce_timer_.Stop();
180
181 GtkWidget* window = GTK_WIDGET(window_);
182 // To help catch bugs in any event handlers that might get fired during the
183 // destruction, set window_ to NULL before any handlers will run.
184 window_ = NULL;
185
186 // OnNativeClose does a delete this so no other members should
187 // be accessed after. gtk_widget_destroy is safe (and must
188 // be last).
189 shell_window_->OnNativeClose();
190 gtk_widget_destroy(window);
191 }
192
193 void ShellWindowGtk::Activate() {
194 gtk_window_present(window_);
195 }
196
197 void ShellWindowGtk::Deactivate() {
198 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
199 }
200
201 void ShellWindowGtk::Maximize() {
202 gtk_window_maximize(window_);
203 }
204
205 void ShellWindowGtk::Minimize() {
206 gtk_window_iconify(window_);
207 shell_window_->OnNativeWindowChanged();
208 }
209
210 void ShellWindowGtk::Restore() {
211 if (IsMaximized())
212 gtk_window_unmaximize(window_);
213 else if (IsMinimized())
214 gtk_window_deiconify(window_);
215 shell_window_->OnNativeWindowChanged();
216 }
217
218 void ShellWindowGtk::SetBounds(const gfx::Rect& bounds) {
219 gtk_window_move(window_, bounds.x(), bounds.y());
220 gtk_window_util::SetWindowSize(window_,
221 gfx::Size(bounds.width(), bounds.height()));
222 }
223
224 void ShellWindowGtk::FlashFrame(bool flash) {
225 gtk_window_set_urgency_hint(window_, flash);
226 }
227
228 bool ShellWindowGtk::IsAlwaysOnTop() const {
229 return false;
230 }
231
232 void ShellWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
233 // Do nothing if we're in the process of closing the browser window.
234 if (!window_)
235 return;
236
237 is_active_ = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window;
238 }
239
240 // Callback for the delete event. This event is fired when the user tries to
241 // close the window (e.g., clicking on the X in the window manager title bar).
242 gboolean ShellWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget,
243 GdkEvent* event) {
244 Close();
245
246 // Return true to prevent the GTK window from being destroyed. Close will
247 // destroy it for us.
248 return TRUE;
249 }
250
251 gboolean ShellWindowGtk::OnConfigure(GtkWidget* widget,
252 GdkEventConfigure* event) {
253 // We update |bounds_| but not |restored_bounds_| here. The latter needs
254 // to be updated conditionally when the window is non-maximized and non-
255 // fullscreen, but whether those state updates have been processed yet is
256 // window-manager specific. We update |restored_bounds_| in the debounced
257 // handler below, after the window state has been updated.
258 bounds_.SetRect(event->x, event->y, event->width, event->height);
259
260 // The GdkEventConfigure* we get here doesn't have quite the right
261 // coordinates though (they're relative to the drawable window area, rather
262 // than any window manager decorations, if enabled), so we need to call
263 // gtk_window_get_position() to get the right values. (Otherwise session
264 // restore, if enabled, will restore windows to incorrect positions.) That's
265 // a round trip to the X server though, so we set a debounce timer and only
266 // call it (in OnDebouncedBoundsChanged() below) after we haven't seen a
267 // reconfigure event in a short while.
268 // We don't use Reset() because the timer may not yet be running.
269 // (In that case Stop() is a no-op.)
270 window_configure_debounce_timer_.Stop();
271 window_configure_debounce_timer_.Start(FROM_HERE,
272 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), this,
273 &ShellWindowGtk::OnDebouncedBoundsChanged);
274
275 return FALSE;
276 }
277
278 void ShellWindowGtk::OnDebouncedBoundsChanged() {
279 gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_);
280 shell_window_->OnNativeWindowChanged();
281 }
282
283 gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender,
284 GdkEventWindowState* event) {
285 state_ = event->new_window_state;
286
287 if (content_thinks_its_fullscreen_ &&
288 !(state_ & GDK_WINDOW_STATE_FULLSCREEN)) {
289 content_thinks_its_fullscreen_ = false;
290 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
291 if (rvh)
292 rvh->ExitFullscreen();
293 }
294
295 shell_window_->OnNativeWindowChanged();
296 return FALSE;
297 }
298
299 gboolean ShellWindowGtk::OnButtonPress(GtkWidget* widget,
300 GdkEventButton* event) {
301 if (draggable_region_ && draggable_region_->contains(event->x, event->y)) {
302 if (event->button == 1) {
303 if (GDK_BUTTON_PRESS == event->type) {
304 if (!suppress_window_raise_)
305 gdk_window_raise(GTK_WIDGET(widget)->window);
306
307 return gtk_window_util::HandleTitleBarLeftMousePress(
308 GTK_WINDOW(widget), bounds_, event);
309 } else if (GDK_2BUTTON_PRESS == event->type) {
310 bool is_maximized = gdk_window_get_state(GTK_WIDGET(widget)->window) &
311 GDK_WINDOW_STATE_MAXIMIZED;
312 if (is_maximized) {
313 gtk_window_util::UnMaximize(GTK_WINDOW(widget),
314 bounds_, restored_bounds_);
315 } else {
316 gtk_window_maximize(GTK_WINDOW(widget));
317 }
318 return TRUE;
319 }
320 } else if (event->button == 2) {
321 gdk_window_lower(GTK_WIDGET(widget)->window);
322 return TRUE;
323 }
324 }
325
326 return FALSE;
327 }
328
329 void ShellWindowGtk::SetFullscreen(bool fullscreen) {
330 content_thinks_its_fullscreen_ = fullscreen;
331 if (fullscreen)
332 gtk_window_fullscreen(window_);
333 else
334 gtk_window_unfullscreen(window_);
335 }
336
337 bool ShellWindowGtk::IsFullscreenOrPending() const {
338 return content_thinks_its_fullscreen_;
339 }
340
341 void ShellWindowGtk::UpdateWindowIcon() {
342 Profile* profile = shell_window_->profile();
343 gfx::Image app_icon = shell_window_->app_icon();
344 if (!app_icon.IsEmpty())
345 gtk_util::SetWindowIcon(window_, profile, app_icon.ToGdkPixbuf());
346 else
347 gtk_util::SetWindowIcon(window_, profile);
348 }
349
350 void ShellWindowGtk::UpdateWindowTitle() {
351 string16 title = shell_window_->GetTitle();
352 gtk_window_set_title(window_, UTF16ToUTF8(title).c_str());
353 }
354
355 void ShellWindowGtk::HandleKeyboardEvent(
356 const content::NativeWebKeyboardEvent& event) {
357 // No-op.
358 }
359
360 void ShellWindowGtk::UpdateDraggableRegions(
361 const std::vector<extensions::DraggableRegion>& regions) {
362 // Draggable region is not supported for non-frameless window.
363 if (!frameless_)
364 return;
365
366 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
367 }
368
369 // static
370 NativeShellWindow* NativeShellWindow::Create(
371 ShellWindow* shell_window, const ShellWindow::CreateParams& params) {
372 return new ShellWindowGtk(shell_window, params);
373 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/extensions/shell_window_gtk.h ('k') | chrome/browser/ui/views/extensions/native_app_window_views.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698