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

Side by Side Diff: trunk/src/chrome/browser/ui/gtk/apps/native_app_window_gtk.cc

Issue 22355002: Revert 215753 "Move native_app_window code to apps areas" (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 4 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 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/apps/native_app_window_gtk.h"
6
7 #include <gdk/gdkx.h>
8 #include <vector>
9
10 #include "base/message_loop/message_loop.h"
11 #include "base/message_loop/message_pump_gtk.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
15 #include "chrome/browser/ui/gtk/gtk_util.h"
16 #include "chrome/browser/ui/gtk/gtk_window_util.h"
17 #include "chrome/browser/web_applications/web_app.h"
18 #include "chrome/common/extensions/extension.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/render_widget_host_view.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_view.h"
23 #include "ui/base/x/active_window_watcher_x.h"
24 #include "ui/gfx/gtk_util.h"
25 #include "ui/gfx/image/image.h"
26 #include "ui/gfx/rect.h"
27
28 using apps::ShellWindow;
29
30 namespace {
31
32 // The timeout in milliseconds before we'll get the true window position with
33 // gtk_window_get_position() after the last GTK configure-event signal.
34 const int kDebounceTimeoutMilliseconds = 100;
35
36 const char* kAtomsToCache[] = {
37 "_NET_WM_STATE",
38 "_NET_WM_STATE_HIDDEN",
39 NULL
40 };
41
42 } // namespace
43
44 NativeAppWindowGtk::NativeAppWindowGtk(ShellWindow* shell_window,
45 const ShellWindow::CreateParams& params)
46 : shell_window_(shell_window),
47 window_(NULL),
48 state_(GDK_WINDOW_STATE_WITHDRAWN),
49 is_active_(false),
50 content_thinks_its_fullscreen_(false),
51 frameless_(params.frame == ShellWindow::FRAME_NONE),
52 frame_cursor_(NULL),
53 atom_cache_(base::MessagePumpGtk::GetDefaultXDisplay(), kAtomsToCache),
54 is_x_event_listened_(false) {
55 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
56
57 gfx::NativeView native_view =
58 web_contents()->GetView()->GetNativeView();
59 gtk_container_add(GTK_CONTAINER(window_), native_view);
60
61 if (params.bounds.x() != INT_MIN && params.bounds.y() != INT_MIN)
62 gtk_window_move(window_, params.bounds.x(), params.bounds.y());
63
64 // This is done to avoid a WM "feature" where setting the window size to
65 // the monitor size causes the WM to set the EWMH for full screen mode.
66 int win_height = params.bounds.height();
67 if (frameless_ &&
68 gtk_window_util::BoundsMatchMonitorSize(window_, params.bounds)) {
69 win_height -= 1;
70 }
71 gtk_window_set_default_size(window_, params.bounds.width(), win_height);
72
73 resizable_ = params.resizable;
74 if (!resizable_) {
75 // If the window doesn't have a size request when we set resizable to
76 // false, GTK will shrink the window to 1x1px.
77 gtk_widget_set_size_request(GTK_WIDGET(window_),
78 params.bounds.width(), win_height);
79 gtk_window_set_resizable(window_, FALSE);
80 }
81
82 // make sure bounds_ and restored_bounds_ have correct values until we
83 // get our first configure-event
84 bounds_ = restored_bounds_ = params.bounds;
85 gint x, y;
86 gtk_window_get_position(window_, &x, &y);
87 bounds_.set_origin(gfx::Point(x, y));
88
89 // Hide titlebar when {frame: 'none'} specified on ShellWindow.
90 if (frameless_)
91 gtk_window_set_decorated(window_, false);
92
93 int min_width = params.minimum_size.width();
94 int min_height = params.minimum_size.height();
95 int max_width = params.maximum_size.width();
96 int max_height = params.maximum_size.height();
97 GdkGeometry hints;
98 int hints_mask = 0;
99 if (min_width || min_height) {
100 hints.min_height = min_height;
101 hints.min_width = min_width;
102 hints_mask |= GDK_HINT_MIN_SIZE;
103 }
104 if (max_width || max_height) {
105 hints.max_height = max_height ? max_height : G_MAXINT;
106 hints.max_width = max_width ? max_width : G_MAXINT;
107 hints_mask |= GDK_HINT_MAX_SIZE;
108 }
109 if (hints_mask) {
110 gtk_window_set_geometry_hints(
111 window_,
112 GTK_WIDGET(window_),
113 &hints,
114 static_cast<GdkWindowHints>(hints_mask));
115 }
116
117 // In some (older) versions of compiz, raising top-level windows when they
118 // are partially off-screen causes them to get snapped back on screen, not
119 // always even on the current virtual desktop. If we are running under
120 // compiz, suppress such raises, as they are not necessary in compiz anyway.
121 if (ui::GuessWindowManager() == ui::WM_COMPIZ)
122 suppress_window_raise_ = true;
123
124 gtk_window_set_title(window_, extension()->name().c_str());
125
126 std::string app_name = web_app::GenerateApplicationNameFromExtensionId(
127 extension()->id());
128 gtk_window_util::SetWindowCustomClass(window_,
129 web_app::GetWMClassFromAppName(app_name));
130
131 g_signal_connect(window_, "delete-event",
132 G_CALLBACK(OnMainWindowDeleteEventThunk), this);
133 g_signal_connect(window_, "configure-event",
134 G_CALLBACK(OnConfigureThunk), this);
135 g_signal_connect(window_, "window-state-event",
136 G_CALLBACK(OnWindowStateThunk), this);
137 if (frameless_) {
138 g_signal_connect(window_, "button-press-event",
139 G_CALLBACK(OnButtonPressThunk), this);
140 g_signal_connect(window_, "motion-notify-event",
141 G_CALLBACK(OnMouseMoveEventThunk), this);
142 }
143
144 // If _NET_WM_STATE_HIDDEN is in _NET_SUPPORTED, listen for XEvent to work
145 // around GTK+ not reporting minimization state changes. See comment in the
146 // |OnXEvent|.
147 std::vector< ::Atom> supported_atoms;
148 if (ui::GetAtomArrayProperty(ui::GetX11RootWindow(),
149 "_NET_SUPPORTED",
150 &supported_atoms)) {
151 if (std::find(supported_atoms.begin(),
152 supported_atoms.end(),
153 atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN")) !=
154 supported_atoms.end()) {
155 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(window_));
156 gdk_window_add_filter(window,
157 &NativeAppWindowGtk::OnXEventThunk,
158 this);
159 is_x_event_listened_ = true;
160 }
161 }
162
163 // Add the keybinding registry.
164 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryGtk(
165 shell_window_->profile(),
166 window_,
167 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
168 shell_window_));
169
170 ui::ActiveWindowWatcherX::AddObserver(this);
171 }
172
173 NativeAppWindowGtk::~NativeAppWindowGtk() {
174 ui::ActiveWindowWatcherX::RemoveObserver(this);
175 if (is_x_event_listened_) {
176 gdk_window_remove_filter(NULL,
177 &NativeAppWindowGtk::OnXEventThunk,
178 this);
179 }
180 }
181
182 bool NativeAppWindowGtk::IsActive() const {
183 if (ui::ActiveWindowWatcherX::WMSupportsActivation())
184 return is_active_;
185
186 // This still works even though we don't get the activation notification.
187 return gtk_window_is_active(window_);
188 }
189
190 bool NativeAppWindowGtk::IsMaximized() const {
191 return (state_ & GDK_WINDOW_STATE_MAXIMIZED);
192 }
193
194 bool NativeAppWindowGtk::IsMinimized() const {
195 return (state_ & GDK_WINDOW_STATE_ICONIFIED);
196 }
197
198 bool NativeAppWindowGtk::IsFullscreen() const {
199 return (state_ & GDK_WINDOW_STATE_FULLSCREEN);
200 }
201
202 gfx::NativeWindow NativeAppWindowGtk::GetNativeWindow() {
203 return window_;
204 }
205
206 gfx::Rect NativeAppWindowGtk::GetRestoredBounds() const {
207 gfx::Rect window_bounds = restored_bounds_;
208 window_bounds.Inset(-GetFrameInsets());
209 return window_bounds;
210 }
211
212 ui::WindowShowState NativeAppWindowGtk::GetRestoredState() const {
213 if (IsMaximized())
214 return ui::SHOW_STATE_MAXIMIZED;
215 return ui::SHOW_STATE_NORMAL;
216 }
217
218 gfx::Rect NativeAppWindowGtk::GetBounds() const {
219 gfx::Rect window_bounds = bounds_;
220 window_bounds.Inset(-GetFrameInsets());
221 return window_bounds;
222 }
223
224 void NativeAppWindowGtk::Show() {
225 gtk_window_present(window_);
226 }
227
228 void NativeAppWindowGtk::ShowInactive() {
229 gtk_window_set_focus_on_map(window_, false);
230 gtk_widget_show(GTK_WIDGET(window_));
231 }
232
233 void NativeAppWindowGtk::Hide() {
234 gtk_widget_hide(GTK_WIDGET(window_));
235 }
236
237 void NativeAppWindowGtk::Close() {
238 shell_window_->OnNativeWindowChanged();
239
240 // Cancel any pending callback from the window configure debounce timer.
241 window_configure_debounce_timer_.Stop();
242
243 GtkWidget* window = GTK_WIDGET(window_);
244 // To help catch bugs in any event handlers that might get fired during the
245 // destruction, set window_ to NULL before any handlers will run.
246 window_ = NULL;
247 gtk_widget_destroy(window);
248
249 // On other platforms, the native window doesn't get destroyed synchronously.
250 // We simulate that here so that ShellWindow can assume that it doesn't get
251 // deleted immediately upon calling Close().
252 base::MessageLoop::current()->PostTask(
253 FROM_HERE,
254 base::Bind(&ShellWindow::OnNativeClose,
255 base::Unretained(shell_window_)));
256 }
257
258 void NativeAppWindowGtk::Activate() {
259 gtk_window_present(window_);
260 }
261
262 void NativeAppWindowGtk::Deactivate() {
263 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
264 }
265
266 void NativeAppWindowGtk::Maximize() {
267 // Represent the window first in order to keep the maximization behavior
268 // consistency with Windows platform. Otherwise the window will be hidden if
269 // it has been minimized.
270 gtk_window_present(window_);
271 gtk_window_maximize(window_);
272 }
273
274 void NativeAppWindowGtk::Minimize() {
275 gtk_window_iconify(window_);
276 }
277
278 void NativeAppWindowGtk::Restore() {
279 if (IsMaximized())
280 gtk_window_unmaximize(window_);
281 else if (IsMinimized())
282 gtk_window_deiconify(window_);
283
284 // Represent the window to keep restoration behavior consistency with Windows
285 // platform.
286 // TODO(zhchbin): verify whether we need this until http://crbug.com/261013 is
287 // fixed.
288 gtk_window_present(window_);
289 }
290
291 void NativeAppWindowGtk::SetBounds(const gfx::Rect& bounds) {
292 gfx::Rect content_bounds = bounds;
293 content_bounds.Inset(GetFrameInsets());
294 gtk_window_move(window_, content_bounds.x(), content_bounds.y());
295 if (!resizable_) {
296 if (frameless_ &&
297 gtk_window_util::BoundsMatchMonitorSize(window_, content_bounds)) {
298 content_bounds.set_height(content_bounds.height() - 1);
299 }
300 // TODO(jeremya): set_size_request doesn't honor min/max size, so the
301 // bounds should be constrained manually.
302 gtk_widget_set_size_request(GTK_WIDGET(window_),
303 content_bounds.width(), content_bounds.height());
304 } else {
305 gtk_window_util::SetWindowSize(window_,
306 gfx::Size(bounds.width(), bounds.height()));
307 }
308 }
309
310 GdkFilterReturn NativeAppWindowGtk::OnXEvent(GdkXEvent* gdk_x_event,
311 GdkEvent* gdk_event) {
312 // Work around GTK+ not reporting minimization state changes. Listen
313 // for _NET_WM_STATE property changes and use _NET_WM_STATE_HIDDEN's
314 // presence to set or clear the iconified bit if _NET_WM_STATE_HIDDEN
315 // is supported. http://crbug.com/162794.
316 XEvent* x_event = static_cast<XEvent*>(gdk_x_event);
317 std::vector< ::Atom> atom_list;
318
319 if (x_event->type == PropertyNotify &&
320 x_event->xproperty.atom == atom_cache_.GetAtom("_NET_WM_STATE") &&
321 ui::GetAtomArrayProperty(GDK_WINDOW_XWINDOW(GTK_WIDGET(window_)->window),
322 "_NET_WM_STATE",
323 &atom_list)) {
324 std::vector< ::Atom>::iterator it =
325 std::find(atom_list.begin(),
326 atom_list.end(),
327 atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN"));
328 state_ = (it != atom_list.end()) ? GDK_WINDOW_STATE_ICONIFIED :
329 static_cast<GdkWindowState>(state_ & ~GDK_WINDOW_STATE_ICONIFIED);
330
331 shell_window_->OnNativeWindowChanged();
332 }
333
334 return GDK_FILTER_CONTINUE;
335 }
336
337 void NativeAppWindowGtk::FlashFrame(bool flash) {
338 gtk_window_set_urgency_hint(window_, flash);
339 }
340
341 bool NativeAppWindowGtk::IsAlwaysOnTop() const {
342 return false;
343 }
344
345 void NativeAppWindowGtk::RenderViewHostChanged() {
346 web_contents()->GetView()->Focus();
347 }
348
349 gfx::Insets NativeAppWindowGtk::GetFrameInsets() const {
350 if (frameless_)
351 return gfx::Insets();
352 GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
353 if (!gdk_window)
354 return gfx::Insets();
355
356 gint current_width = 0;
357 gint current_height = 0;
358 gtk_window_get_size(window_, &current_width, &current_height);
359 gint current_x = 0;
360 gint current_y = 0;
361 gdk_window_get_position(gdk_window, &current_x, &current_y);
362 GdkRectangle rect_with_decorations = {0};
363 gdk_window_get_frame_extents(gdk_window,
364 &rect_with_decorations);
365
366 int left_inset = current_x - rect_with_decorations.x;
367 int top_inset = current_y - rect_with_decorations.y;
368 return gfx::Insets(
369 top_inset,
370 left_inset,
371 rect_with_decorations.height - current_height - top_inset,
372 rect_with_decorations.width - current_width - left_inset);
373 }
374
375 gfx::NativeView NativeAppWindowGtk::GetHostView() const {
376 NOTIMPLEMENTED();
377 return NULL;
378 }
379
380 gfx::Point NativeAppWindowGtk::GetDialogPosition(const gfx::Size& size) {
381 gint current_width = 0;
382 gint current_height = 0;
383 gtk_window_get_size(window_, &current_width, &current_height);
384 return gfx::Point(current_width / 2 - size.width() / 2,
385 current_height / 2 - size.height() / 2);
386 }
387
388 void NativeAppWindowGtk::AddObserver(
389 web_modal::WebContentsModalDialogHostObserver* observer) {
390 observer_list_.AddObserver(observer);
391 }
392
393 void NativeAppWindowGtk::RemoveObserver(
394 web_modal::WebContentsModalDialogHostObserver* observer) {
395 observer_list_.RemoveObserver(observer);
396 }
397
398 void NativeAppWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
399 // Do nothing if we're in the process of closing the browser window.
400 if (!window_)
401 return;
402
403 is_active_ = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window;
404 if (is_active_)
405 shell_window_->OnNativeWindowActivated();
406 }
407
408 // Callback for the delete event. This event is fired when the user tries to
409 // close the window (e.g., clicking on the X in the window manager title bar).
410 gboolean NativeAppWindowGtk::OnMainWindowDeleteEvent(GtkWidget* widget,
411 GdkEvent* event) {
412 Close();
413
414 // Return true to prevent the GTK window from being destroyed. Close will
415 // destroy it for us.
416 return TRUE;
417 }
418
419 gboolean NativeAppWindowGtk::OnConfigure(GtkWidget* widget,
420 GdkEventConfigure* event) {
421 // We update |bounds_| but not |restored_bounds_| here. The latter needs
422 // to be updated conditionally when the window is non-maximized and non-
423 // fullscreen, but whether those state updates have been processed yet is
424 // window-manager specific. We update |restored_bounds_| in the debounced
425 // handler below, after the window state has been updated.
426 bounds_.SetRect(event->x, event->y, event->width, event->height);
427
428 // The GdkEventConfigure* we get here doesn't have quite the right
429 // coordinates though (they're relative to the drawable window area, rather
430 // than any window manager decorations, if enabled), so we need to call
431 // gtk_window_get_position() to get the right values. (Otherwise session
432 // restore, if enabled, will restore windows to incorrect positions.) That's
433 // a round trip to the X server though, so we set a debounce timer and only
434 // call it (in OnConfigureDebounced() below) after we haven't seen a
435 // reconfigure event in a short while.
436 // We don't use Reset() because the timer may not yet be running.
437 // (In that case Stop() is a no-op.)
438 window_configure_debounce_timer_.Stop();
439 window_configure_debounce_timer_.Start(FROM_HERE,
440 base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), this,
441 &NativeAppWindowGtk::OnConfigureDebounced);
442
443 return FALSE;
444 }
445
446 void NativeAppWindowGtk::OnConfigureDebounced() {
447 gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_);
448 shell_window_->OnNativeWindowChanged();
449
450 FOR_EACH_OBSERVER(web_modal::WebContentsModalDialogHostObserver,
451 observer_list_,
452 OnPositionRequiresUpdate());
453
454 // Fullscreen of non-resizable windows requires them to be made resizable
455 // first. After that takes effect and OnConfigure is called we transition
456 // to fullscreen.
457 if (!IsFullscreen() && IsFullscreenOrPending()) {
458 gtk_window_fullscreen(window_);
459 }
460 }
461
462 gboolean NativeAppWindowGtk::OnWindowState(GtkWidget* sender,
463 GdkEventWindowState* event) {
464 state_ = event->new_window_state;
465
466 if (content_thinks_its_fullscreen_ &&
467 !(state_ & GDK_WINDOW_STATE_FULLSCREEN)) {
468 content_thinks_its_fullscreen_ = false;
469 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
470 if (rvh)
471 rvh->ExitFullscreen();
472 }
473
474 return FALSE;
475 }
476
477 bool NativeAppWindowGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) {
478 if (!frameless_)
479 return false;
480
481 if (IsMaximized() || IsFullscreen())
482 return false;
483
484 return gtk_window_util::GetWindowEdge(bounds_.size(), 0, x, y, edge);
485 }
486
487 gboolean NativeAppWindowGtk::OnMouseMoveEvent(GtkWidget* widget,
488 GdkEventMotion* event) {
489 if (!frameless_) {
490 // Reset the cursor.
491 if (frame_cursor_) {
492 frame_cursor_ = NULL;
493 gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(window_)), NULL);
494 }
495 return FALSE;
496 }
497
498 if (!resizable_)
499 return FALSE;
500
501 // Update the cursor if we're on the custom frame border.
502 GdkWindowEdge edge;
503 bool has_hit_edge = GetWindowEdge(static_cast<int>(event->x),
504 static_cast<int>(event->y), &edge);
505 GdkCursorType new_cursor = GDK_LAST_CURSOR;
506 if (has_hit_edge)
507 new_cursor = gtk_window_util::GdkWindowEdgeToGdkCursorType(edge);
508
509 GdkCursorType last_cursor = GDK_LAST_CURSOR;
510 if (frame_cursor_)
511 last_cursor = frame_cursor_->type;
512
513 if (last_cursor != new_cursor) {
514 frame_cursor_ = has_hit_edge ? gfx::GetCursor(new_cursor) : NULL;
515 gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(window_)),
516 frame_cursor_);
517 }
518 return FALSE;
519 }
520
521 gboolean NativeAppWindowGtk::OnButtonPress(GtkWidget* widget,
522 GdkEventButton* event) {
523 DCHECK(frameless_);
524 // Make the button press coordinate relative to the browser window.
525 int win_x, win_y;
526 GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
527 gdk_window_get_origin(gdk_window, &win_x, &win_y);
528
529 GdkWindowEdge edge;
530 gfx::Point point(static_cast<int>(event->x_root - win_x),
531 static_cast<int>(event->y_root - win_y));
532 bool has_hit_edge = resizable_ && GetWindowEdge(point.x(), point.y(), &edge);
533 bool has_hit_titlebar =
534 draggable_region_ && draggable_region_->contains(event->x, event->y);
535
536 if (event->button == 1) {
537 if (GDK_BUTTON_PRESS == event->type) {
538 // Raise the window after a click on either the titlebar or the border to
539 // match the behavior of most window managers, unless that behavior has
540 // been suppressed.
541 if ((has_hit_titlebar || has_hit_edge) && !suppress_window_raise_)
542 gdk_window_raise(GTK_WIDGET(widget)->window);
543
544 if (has_hit_edge) {
545 gtk_window_begin_resize_drag(window_, edge, event->button,
546 static_cast<gint>(event->x_root),
547 static_cast<gint>(event->y_root),
548 event->time);
549 return TRUE;
550 } else if (has_hit_titlebar) {
551 return gtk_window_util::HandleTitleBarLeftMousePress(
552 window_, bounds_, event);
553 }
554 } else if (GDK_2BUTTON_PRESS == event->type) {
555 if (has_hit_titlebar && resizable_) {
556 // Maximize/restore on double click.
557 if (IsMaximized()) {
558 gtk_window_util::UnMaximize(GTK_WINDOW(widget),
559 bounds_, restored_bounds_);
560 } else {
561 gtk_window_maximize(window_);
562 }
563 return TRUE;
564 }
565 }
566 } else if (event->button == 2) {
567 if (has_hit_titlebar || has_hit_edge)
568 gdk_window_lower(gdk_window);
569 return TRUE;
570 }
571
572 return FALSE;
573 }
574
575 void NativeAppWindowGtk::SetFullscreen(bool fullscreen) {
576 content_thinks_its_fullscreen_ = fullscreen;
577 if (fullscreen){
578 if (resizable_) {
579 gtk_window_fullscreen(window_);
580 } else {
581 // We must first make the window resizable. That won't take effect
582 // immediately, so OnConfigureDebounced completes the fullscreen call.
583 gtk_window_set_resizable(window_, TRUE);
584 }
585 } else {
586 gtk_window_unfullscreen(window_);
587 if (!resizable_)
588 gtk_window_set_resizable(window_, FALSE);
589 }
590 }
591
592 bool NativeAppWindowGtk::IsFullscreenOrPending() const {
593 return content_thinks_its_fullscreen_;
594 }
595
596 bool NativeAppWindowGtk::IsDetached() const {
597 return false;
598 }
599
600 void NativeAppWindowGtk::UpdateWindowIcon() {
601 Profile* profile = shell_window_->profile();
602 gfx::Image app_icon = shell_window_->app_icon();
603 if (!app_icon.IsEmpty())
604 gtk_util::SetWindowIcon(window_, profile, app_icon.ToGdkPixbuf());
605 else
606 gtk_util::SetWindowIcon(window_, profile);
607 }
608
609 void NativeAppWindowGtk::UpdateWindowTitle() {
610 string16 title = shell_window_->GetTitle();
611 gtk_window_set_title(window_, UTF16ToUTF8(title).c_str());
612 }
613
614 void NativeAppWindowGtk::HandleKeyboardEvent(
615 const content::NativeWebKeyboardEvent& event) {
616 // No-op.
617 }
618
619 void NativeAppWindowGtk::UpdateDraggableRegions(
620 const std::vector<extensions::DraggableRegion>& regions) {
621 // Draggable region is not supported for non-frameless window.
622 if (!frameless_)
623 return;
624
625 draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
626 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698