panel_view.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
116c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek// Copyright (c) 2012 The Chromium Authors. All rights reserved.
216c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek// Use of this source code is governed by a BSD-style license that can be
316c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek// found in the LICENSE file.
416c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek
516c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "chrome/browser/ui/views/panels/panel_view.h"
616c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek
716c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include <map>
816c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "base/logging.h"
916c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "base/message_loop/message_loop.h"
102e331b938b38057e333fab0ba841130ea8467794Douglas Gregor#include "base/strings/utf_string_conversions.h"
112e331b938b38057e333fab0ba841130ea8467794Douglas Gregor#include "chrome/app/chrome_command_ids.h"
122e331b938b38057e333fab0ba841130ea8467794Douglas Gregor#include "chrome/browser/profiles/profile.h"
1316c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "chrome/browser/ui/host_desktop.h"
1416c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "chrome/browser/ui/panels/panel.h"
1516c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "chrome/browser/ui/panels/panel_bounds_animation.h"
160a90d32523bfe5fa63e11b648686c9699f786d15Ted Kremenek#include "chrome/browser/ui/panels/panel_manager.h"
1716c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "chrome/browser/ui/panels/stacked_panel_collection.h"
18ed122735639d83c10f18c28c7fd117bfcd0f62cbTed Kremenek#include "chrome/browser/ui/views/auto_keep_alive.h"
19f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth#include "chrome/browser/ui/views/panels/panel_frame_view.h"
20f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth#include "content/public/browser/render_view_host.h"
2116c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "content/public/browser/render_widget_host_view.h"
226931900f43cea558c6974075256c07728dbfecc6Douglas Gregor#include "content/public/browser/web_contents.h"
23283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor#include "ui/aura/window.h"
24aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "ui/aura/window_tree_host.h"
25283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor#include "ui/gfx/image/image.h"
261f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor#include "ui/gfx/path.h"
27aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#include "ui/gfx/screen.h"
28f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth#include "ui/views/controls/button/image_button.h"
29edc8aa68ef91aeea686c5aadf64ef902c38318ddTed Kremenek#include "ui/views/controls/webview/webview.h"
3016c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "ui/views/widget/widget.h"
3116c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek
321f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor#if defined(OS_WIN)
3316c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "base/win/windows_version.h"
34bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek#include "chrome/browser/shell_integration.h"
355bfb8c128c2ac8eb4032afc180cdc400a0f953caDouglas Gregor#include "chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h"
36bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek#include "ui/base/win/shell.h"
375bfb8c128c2ac8eb4032afc180cdc400a0f953caDouglas Gregor#include "ui/gfx/icon_util.h"
3816c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#include "ui/views/win/hwnd_util.h"
3916c440a377b7ec8b722a2e2c7c864f75c95bd305Ted Kremenek#endif
40e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek
41e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek#if defined(USE_X11) && !defined(OS_CHROMEOS)
42e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek#include "chrome/browser/ui/views/panels/x11_panel_resizer.h"
43e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
44387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt#endif
45387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt
46387475d0c18aaeb022108de9d33b6c9fb7998843Sean Huntnamespace {
476639e9255489ad8e10278d5658fdd4b3c0e1e4cdArgyrios Kyrtzidis
486639e9255489ad8e10278d5658fdd4b3c0e1e4cdArgyrios Kyrtzidis#if defined(OS_WIN)
495f1c822def3efffe1d8f7299fbbbc3b1cdd4833dErik Verbruggen// If the height of a stacked panel shrinks below this threshold during the
5084b796492de8a708150dd3f86ae191041d42eef9Argyrios Kyrtzidis// user resizing, it will be treated as minimized.
51e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenekconst int kStackedPanelHeightShrinkThresholdToBecomeMinimized =
52e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek    panel::kTitlebarHeight + 20;
53e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek#endif
54e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek
55e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek// Supported accelerators.
5605756dc8d11cd2054e0cb94f0302e4eb39acc68eDmitri Gribenko// Note: We can't use the acclerator table defined in chrome/browser/ui/views
57a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek// due to checkdeps violation.
58e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenekstruct AcceleratorMapping {
593315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko  ui::KeyboardCode keycode;
60e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek  int modifiers;
61e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek  int command_id;
62e77f443dbca8cdc23e5aa94a2653367e4a7cbe47Ted Kremenek};
6367812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenkoconst AcceleratorMapping kPanelAcceleratorMap[] = {
64aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_W, ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW },
65007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenek  { ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW },
6654d67caeee4fdce81f07163832f1163d5f2af5d2Daniel Dunbar  { ui::VKEY_F4, ui::EF_ALT_DOWN, IDC_CLOSE_WINDOW },
67aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_R, ui::EF_CONTROL_DOWN, IDC_RELOAD },
68aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_F5, ui::EF_NONE, IDC_RELOAD },
69aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_R, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
70aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      IDC_RELOAD_IGNORING_CACHE },
71aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_F5, ui::EF_CONTROL_DOWN, IDC_RELOAD_IGNORING_CACHE },
72aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_F5, ui::EF_SHIFT_DOWN, IDC_RELOAD_IGNORING_CACHE },
73aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_ESCAPE, ui::EF_NONE, IDC_STOP },
74aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
75aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
76aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
77aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_NUMPAD0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
78aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
79aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_ADD, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
80aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS },
81aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  { ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
82aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    IDC_DEV_TOOLS_CONSOLE },
83aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis};
84aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
85aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisconst std::map<ui::Accelerator, int>& GetAcceleratorTable() {
86aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  static std::map<ui::Accelerator, int>* accelerators = NULL;
87aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!accelerators) {
88aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    accelerators = new std::map<ui::Accelerator, int>();
895bfb8c128c2ac8eb4032afc180cdc400a0f953caDouglas Gregor    for (size_t i = 0; i < arraysize(kPanelAcceleratorMap); ++i) {
90edc8aa68ef91aeea686c5aadf64ef902c38318ddTed Kremenek      ui::Accelerator accelerator(kPanelAcceleratorMap[i].keycode,
91edc8aa68ef91aeea686c5aadf64ef902c38318ddTed Kremenek                                  kPanelAcceleratorMap[i].modifiers);
9205756dc8d11cd2054e0cb94f0302e4eb39acc68eDmitri Gribenko      (*accelerators)[accelerator] = kPanelAcceleratorMap[i].command_id;
9367812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko    }
94aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
9554d67caeee4fdce81f07163832f1163d5f2af5d2Daniel Dunbar  return *accelerators;
9697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor}
9797b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
9897b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor// NativePanelTesting implementation.
9997b9872d5775446cb8aca1380e437649fe848d91Douglas Gregorclass NativePanelTestingWin : public NativePanelTesting {
10097b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor public:
10142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  explicit NativePanelTestingWin(PanelView* panel_view);
10297b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
10342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor private:
10442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual void PressLeftMouseButtonTitlebar(
10542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      const gfx::Point& mouse_location, panel::ClickModifier modifier) OVERRIDE;
10697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  virtual void ReleaseMouseButtonTitlebar(
10742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      panel::ClickModifier modifier) OVERRIDE;
10842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual void DragTitlebar(const gfx::Point& mouse_location) OVERRIDE;
10942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual void CancelDragTitlebar() OVERRIDE;
11042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual void FinishDragTitlebar() OVERRIDE;
11142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool VerifyDrawingAttention() const OVERRIDE;
11242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool VerifyActiveState(bool is_active) OVERRIDE;
11342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool VerifyAppIcon() const OVERRIDE;
11442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool VerifySystemMinimizeState() const OVERRIDE;
11542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool IsWindowVisible() const OVERRIDE;
11642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool IsWindowSizeKnown() const OVERRIDE;
11742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool IsAnimatingBounds() const OVERRIDE;
11842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool IsButtonVisible(
11942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      panel::TitlebarButtonType button_type) const OVERRIDE;
12042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual panel::CornerStyle GetWindowCornerStyle() const OVERRIDE;
12142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  virtual bool EnsureApplicationRunOnForeground() OVERRIDE;
12242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
12342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  PanelView* panel_view_;
12442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor};
12542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
12642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas GregorNativePanelTestingWin::NativePanelTestingWin(PanelView* panel_view)
12742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    : panel_view_(panel_view) {
12842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
12942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
13042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid NativePanelTestingWin::PressLeftMouseButtonTitlebar(
13142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    const gfx::Point& mouse_location, panel::ClickModifier modifier) {
13242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  panel_view_->OnTitlebarMousePressed(mouse_location);
13342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
13497b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
13542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid NativePanelTestingWin::ReleaseMouseButtonTitlebar(
13642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    panel::ClickModifier modifier) {
13742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  panel_view_->OnTitlebarMouseReleased(modifier);
13842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
13942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
14042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid NativePanelTestingWin::DragTitlebar(const gfx::Point& mouse_location) {
14142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  panel_view_->OnTitlebarMouseDragged(mouse_location);
14242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
14342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
14442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid NativePanelTestingWin::CancelDragTitlebar() {
14542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  panel_view_->OnTitlebarMouseCaptureLost();
14642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
14742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
14842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid NativePanelTestingWin::FinishDragTitlebar() {
14942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  panel_view_->OnTitlebarMouseReleased(panel::NO_MODIFIER);
150df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier}
151df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier
15242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::VerifyDrawingAttention() const {
1538cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier  base::MessageLoop::current()->RunUntilIdle();
1548cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier  return panel_view_->GetFrameView()->GetPaintState() ==
1558cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier         PanelFrameView::PAINT_FOR_ATTENTION;
1568cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier}
15742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
15842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::VerifyActiveState(bool is_active) {
15942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return panel_view_->GetFrameView()->GetPaintState() ==
16042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor         (is_active ? PanelFrameView::PAINT_AS_ACTIVE
16142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                    : PanelFrameView::PAINT_AS_INACTIVE);
16242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
16342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
16442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::VerifyAppIcon() const {
16542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#if defined(OS_WIN)
16642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // We only care about Windows 7 and later.
16742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (base::win::GetVersion() < base::win::VERSION_WIN7)
16842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return true;
16942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
17042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  HWND native_window = views::HWNDForWidget(panel_view_->window());
17142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  HICON app_icon = reinterpret_cast<HICON>(
17242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      ::SendMessage(native_window, WM_GETICON, ICON_BIG, 0L));
17342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (!app_icon)
17442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return false;
17542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  scoped_ptr<SkBitmap> bitmap(IconUtil::CreateSkBitmapFromHICON(app_icon));
17642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return bitmap.get() &&
17742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor         bitmap->width() == panel::kPanelAppIconSize &&
17842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor         bitmap->height() == panel::kPanelAppIconSize;
17942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#else
18042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return true;
18142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#endif
18297b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor}
18342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
18442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::VerifySystemMinimizeState() const {
18542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#if defined(OS_WIN)
18697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  HWND native_window = views::HWNDForWidget(panel_view_->window());
18742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  WINDOWPLACEMENT placement;
18842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (!::GetWindowPlacement(native_window, &placement))
18942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return false;
19042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_SHOWMINIMIZED)
19142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return true;
19242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
19342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // If the panel window has owner window, as in stacked mode, check its owner
19442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // window. Note that owner window, instead of parent window, is returned
19542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // though GWL_HWNDPARENT contains 'parent'.
19642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  HWND owner_window =
19742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      reinterpret_cast<HWND>(::GetWindowLongPtr(native_window,
19828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley                                                GWLP_HWNDPARENT));
19942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (!owner_window || !::GetWindowPlacement(owner_window, &placement))
20042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return false;
20142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return placement.showCmd == SW_MINIMIZE ||
20228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley         placement.showCmd == SW_SHOWMINIMIZED;
20342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#else
20442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return true;
20542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#endif
20628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley}
20742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
20842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::IsWindowVisible() const {
20942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#if defined(OS_WIN)
21042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  HWND native_window = views::HWNDForWidget(panel_view_->window());
21142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return ::IsWindowVisible(native_window) == TRUE;
212276b061970939293f1abaf694bd3ef05b2cbda79Eli Friedman#else
21342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return panel_view_->visible();
21442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#endif
2154ca8ac2e61c37ddadf37024af86f3e1019af8532Douglas Gregor}
21642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
21742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::IsWindowSizeKnown() const {
218c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith  return true;
21942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
22042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
22142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::IsAnimatingBounds() const {
22242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return panel_view_->IsAnimatingBounds();
22342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
22442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
22542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool NativePanelTestingWin::IsButtonVisible(
22642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    panel::TitlebarButtonType button_type) const {
22742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  PanelFrameView* frame_view = panel_view_->GetFrameView();
22803e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor
22942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  switch (button_type) {
23042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    case panel::CLOSE_BUTTON:
23142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      return frame_view->close_button()->visible();
23242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    case panel::MINIMIZE_BUTTON:
23342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      return frame_view->minimize_button()->visible();
23442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    case panel::RESTORE_BUTTON:
23542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      return frame_view->restore_button()->visible();
23642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    default:
237b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek      NOTREACHED();
238b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek  }
239eb382ec1507cf2c8c12d7443d0b67c076223aec6Patrick Beard  return false;
240b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek}
24142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
24242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorpanel::CornerStyle NativePanelTestingWin::GetWindowCornerStyle() const {
24342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return panel_view_->GetFrameView()->corner_style();
2444b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2454b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2464b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool NativePanelTestingWin::EnsureApplicationRunOnForeground() {
2474b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Not needed on views.
2484b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return true;
2494b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2504b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2514b9c2d235fb9449e249d74f48ecfec601650de93John McCall}  // namespace
2524b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2534b9c2d235fb9449e249d74f48ecfec601650de93John McCall// static
25442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas GregorNativePanel* Panel::CreateNativePanel(Panel* panel,
25542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                                      const gfx::Rect& bounds,
25697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor                                      bool always_on_top) {
257534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith  return new PanelView(panel, bounds, always_on_top);
25842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
25942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
26036897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor// The panel window has to be created as always-on-top. We cannot create it
261534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith// as non-always-on-top and then change it to always-on-top because Windows
26242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor// system might deny making a window always-on-top if the application is not
26342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor// a foreground application.
26442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas GregorPanelView::PanelView(Panel* panel, const gfx::Rect& bounds, bool always_on_top)
265534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith    : panel_(panel),
266534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith      bounds_(bounds),
267534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith      window_(NULL),
268534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith      window_closed_(false),
269534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith      web_view_(NULL),
27042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      always_on_top_(always_on_top),
27142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      focused_(false),
27242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      user_resizing_(false),
273534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith#if defined(OS_WIN)
274051303ce09291dfbed537fa33b0d8a4d92c82b75Tareq A. Siraj      user_resizing_interior_stacked_panel_edge_(false),
275051303ce09291dfbed537fa33b0d8a4d92c82b75Tareq A. Siraj#endif
276051303ce09291dfbed537fa33b0d8a4d92c82b75Tareq A. Siraj      mouse_pressed_(false),
277051303ce09291dfbed537fa33b0d8a4d92c82b75Tareq A. Siraj      mouse_dragging_state_(NO_DRAGGING),
27842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      is_drawing_attention_(false),
27942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      force_to_paint_as_inactive_(false),
28042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      old_focused_view_(NULL) {
28142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  window_ = new views::Widget;
28242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
28342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  params.delegate = this;
28442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  params.remove_standard_frame = true;
28542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  params.keep_on_top = always_on_top;
28642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  params.visible_on_all_workspaces = always_on_top;
28742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  params.bounds = bounds;
28842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  window_->Init(params);
28942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  window_->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM);
29042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  window_->set_focus_on_creation(false);
29142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  window_->AddObserver(this);
29242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
29342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // Prevent the browser process from shutting down while this window is open.
29442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  keep_alive_.reset(new AutoKeepAlive(GetNativePanelWindow()));
29542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
29642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  web_view_ = new views::WebView(NULL);
29742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  AddChildView(web_view_);
29842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
29942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // Register accelarators supported by panels.
30042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  views::FocusManager* focus_manager = GetFocusManager();
30142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  const std::map<ui::Accelerator, int>& accelerator_table =
3028ecdb65716cd7914ffb2eeee993fa9039fcd31e8Douglas Gregor      GetAcceleratorTable();
30342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  for (std::map<ui::Accelerator, int>::const_iterator iter =
30442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor           accelerator_table.begin();
305534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith       iter != accelerator_table.end(); ++iter) {
30642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    focus_manager->RegisterAccelerator(
30742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor        iter->first, ui::AcceleratorManager::kNormalPriority, this);
30842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  }
30942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
31042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#if defined(OS_WIN)
31142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  ui::win::SetAppIdForWindow(
31242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      ShellIntegration::GetAppModelIdForProfile(
31342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor          base::UTF8ToWide(panel->app_name()), panel->profile()->GetPath()),
31442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      views::HWNDForWidget(window_));
31542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  ui::win::PreventWindowFromPinning(views::HWNDForWidget(window_));
31642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#endif
31742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
31897b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor#if defined(USE_X11) && !defined(OS_CHROMEOS)
31942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // Swap the default non client event handler with one which handles resizes
32042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // for panels entirely within Chrome. This is needed because it is not
32142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // possible to tell when a resize performed by the window manager ends.
32242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  views::DesktopWindowTreeHostX11* host =
32342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      views::DesktopWindowTreeHostX11::GetHostForXID(
32442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor          window_->GetNativeView()->GetHost()->GetAcceleratedWidget());
32542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  scoped_ptr<ui::EventHandler> resizer(
32697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor      new X11PanelResizer(panel_.get(), window_->GetNativeWindow()));
32742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  host->SwapNonClientEventHandler(resizer.Pass());
32842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#endif
32942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
33042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
33142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas GregorPanelView::~PanelView() {
33242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
33342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
33442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::ShowPanel() {
33542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  ShowPanelInactive();
33642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  ActivatePanel();
33742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
33842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
33942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::ShowPanelInactive() {
34042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (window_->IsVisible())
34142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return;
34242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  window_->ShowInactive();
34342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // No animation is used for initial creation of a panel on Win.
34442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // Signal immediately that pending actions can be performed.
34542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  panel_->manager()->OnPanelAnimationEnded(panel_.get());
346f111d935722ed488144600cea5ed03a6b5069e8fPeter Collingbourne}
34742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
34842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorgfx::Rect PanelView::GetPanelBounds() const {
34942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return bounds_;
35042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
35142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
35242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::SetPanelBounds(const gfx::Rect& bounds) {
35342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  SetBoundsInternal(bounds, true);
35442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
35542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
35642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::SetPanelBoundsInstantly(const gfx::Rect& bounds) {
35742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  SetBoundsInternal(bounds, false);
35842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
35942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
36042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::SetBoundsInternal(const gfx::Rect& new_bounds, bool animate) {
36142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (bounds_ == new_bounds)
36242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return;
36342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
36442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  bounds_ = new_bounds;
36542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
36642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  if (!animate) {
36742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    // If no animation is in progress, apply bounds change instantly. Otherwise,
36842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    // continue the animation with new target bounds.
36942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    if (!IsAnimatingBounds())
37097b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor      SetWidgetBounds(bounds_);
37142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    return;
37242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  }
37342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
37442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  animation_start_bounds_ = window_->GetWindowBoundsInScreen();
37542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
37642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  bounds_animator_.reset(new PanelBoundsAnimation(
37742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      this, panel_.get(), animation_start_bounds_, new_bounds));
37842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  bounds_animator_->Start();
37942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
38042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
38142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#if defined(OS_WIN)
38242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorbool PanelView::FilterMessage(HWND hwnd,
38342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                              UINT message,
38442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                              WPARAM w_param,
38542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                              LPARAM l_param,
38642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                              LRESULT* l_result) {
38742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  switch (message) {
38842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    case WM_SIZING:
38942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      if (w_param == WMSZ_BOTTOM)
39042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor        user_resizing_interior_stacked_panel_edge_ = true;
39142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      break;
39242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  }
39342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  return false;
39442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
39542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#endif
39642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
39742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::AnimationEnded(const gfx::Animation* animation) {
39842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  panel_->manager()->OnPanelAnimationEnded(panel_.get());
39942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
40042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
40142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::AnimationProgressed(const gfx::Animation* animation) {
40242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  gfx::Rect new_bounds = bounds_animator_->CurrentValueBetween(
40342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      animation_start_bounds_, bounds_);
40442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  SetWidgetBounds(new_bounds);
40542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
40642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
40742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregorvoid PanelView::SetWidgetBounds(const gfx::Rect& new_bounds) {
40842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#if defined(OS_WIN)
40942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // An overlapped window is a top-level window that has a titlebar, border,
41042b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // and client area. The Windows system will automatically put the shadow
41142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // around the whole window. Also the system will enforce the minimum height
41242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // (38 pixels based on observation) for the overlapped window such that it
41342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // will always has the space for the titlebar.
41442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  //
41542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // On contrast, a popup window is a bare minimum window without border and
41642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // titlebar by default. It is often used for the popup menu and the window
417b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek  // with short life. The Windows system does not add the shadow around the
418b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek  // whole window though CS_DROPSHADOW class style could be passed to add the
419b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek  // drop shadow which is only around the right and bottom edges.
420b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek  //
421b3f7542a950ac0d585a7783e825cfe670e05c553Ted Kremenek  // The height of the title-only or minimized panel is smaller than the minimum
422f85e193739c953358c865005855253af4f68a497John McCall  // overlapped window height. If the panel still uses the overlapped window
42342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // style, Windows system will automatically increase the window height. To
42442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // work around this limitation, we temporarily change the window style to
42542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // popup when the height to set is smaller than the minimum overlapped window
42642b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // height and then restore the window style to overlapped when the height
42742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // grows.
42842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  static const int kMinimumOverlappedWindowHeight = 38;
42942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  gfx::Rect old_bounds = GetWidget()->GetRestoredBounds();
430be230c36e32142cbdcdbe9c97511d097beeecbabDouglas Gregor  if (old_bounds.height() > kMinimumOverlappedWindowHeight &&
43142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor      new_bounds.height() <= kMinimumOverlappedWindowHeight) {
43242b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    // When the panel height shrinks below the minimum overlapped window height,
43342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    // change the window style to popup such that we can show the title-only
434ee8aff06f6a96214731de17b2cb6df407c6c1820Douglas Gregor    // and minimized panel without additional height being added by the system.
43542b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    UpdateWindowAttribute(GWL_STYLE,
43697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor                          WS_POPUP,
43742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                          WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU,
43842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor                          true);
43942b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  } else if (old_bounds.height() <= kMinimumOverlappedWindowHeight &&
44091a5755ad73c5dc1dfb167e448fdd74e75a6df56John McCall             new_bounds.height() > kMinimumOverlappedWindowHeight) {
441c7793c73ba8a343de3f2552d984851985a46f159Douglas Gregor    // Change the window style back to overlappped when the panel height grow
4429a4db032ecd991626d236a502e770126db32bd31Richard Smith    // taller than the minimum overlapped window height.
44342b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor    UpdateWindowAttribute(GWL_STYLE,
44497b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor                          WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU,
44597b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor                          WS_POPUP,
44697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor                          true);
44742b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  }
44842b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor#endif
44997b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
45076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  GetWidget()->SetBounds(new_bounds);
45142b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor}
45297b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
45397b9872d5775446cb8aca1380e437649fe848d91Douglas Gregorvoid PanelView::ClosePanel() {
45442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor  // We're already closing. Do nothing.
45597b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  if (window_closed_)
45697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor    return;
45797b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
45897b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  if (!panel_->ShouldCloseWindow())
45997b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor    return;
46097b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
461e08ce650a2b02410eddd1f60a4aa6b3d4be71e73Peter Collingbourne  // Cancel any currently running animation since we're closing down.
46297b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  if (bounds_animator_.get())
46397b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor    bounds_animator_.reset();
46442b2984771a7fd1b17c78bbb2c59fed3db2f1960Douglas Gregor
4659fcce65e7e1307b5b8da9be13e4092d6bb94dc1dRichard Smith  if (panel_->GetWebContents()) {
46697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor    // Still have web contents. Allow renderer to shut down.
46797b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor    // When web contents are destroyed, we will be called back again.
46897b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor    panel_->OnWindowClosing();
469011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor    return;
470011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor  }
471011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor
472011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor  panel_->OnNativePanelClosed();
473ba0513de93d2fab6db5ab30b6927209fcc883078Douglas Gregor  if (window_)
47497b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor    window_->Close();
475aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  window_closed_ = true;
476aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
477aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
478aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisvoid PanelView::ActivatePanel() {
479aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  window_->Activate();
480aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
481aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
482aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisvoid PanelView::DeactivatePanel() {
483aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (!focused_)
484aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
485aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
486aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#if defined(OS_WIN)
487aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  // Need custom behavior for always-on-top panels to avoid
48897b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  // the OS activating a minimized panel when this one is
489ba0513de93d2fab6db5ab30b6927209fcc883078Douglas Gregor  // deactivated.
490ba0513de93d2fab6db5ab30b6927209fcc883078Douglas Gregor  if (always_on_top_) {
491ba0513de93d2fab6db5ab30b6927209fcc883078Douglas Gregor    ::SetForegroundWindow(::GetDesktopWindow());
492ba0513de93d2fab6db5ab30b6927209fcc883078Douglas Gregor    return;
493ba0513de93d2fab6db5ab30b6927209fcc883078Douglas Gregor  }
49497b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor#endif
495aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
49697b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  window_->Deactivate();
49797b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor}
49897b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor
4992e331b938b38057e333fab0ba841130ea8467794Douglas Gregorbool PanelView::IsPanelActive() const {
500b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregor  return focused_;
501a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek}
50254d67caeee4fdce81f07163832f1163d5f2af5d2Daniel Dunbar
503cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenkovoid PanelView::PreventActivationByOS(bool prevent_activation) {
504aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#if defined(OS_WIN)
5052e331b938b38057e333fab0ba841130ea8467794Douglas Gregor  // Set the flags "NoActivate" to make sure the minimized panels do not get
5062e331b938b38057e333fab0ba841130ea8467794Douglas Gregor  // activated by the OS. In addition, set "AppWindow" to make sure the
5072e331b938b38057e333fab0ba841130ea8467794Douglas Gregor  // minimized panels do appear in the taskbar and Alt-Tab menu if it is not
50867812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  // in a stack.
5092e331b938b38057e333fab0ba841130ea8467794Douglas Gregor  int value_to_change = WS_EX_NOACTIVATE;
5102e331b938b38057e333fab0ba841130ea8467794Douglas Gregor  if (!panel_->stack())
51167812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko    value_to_change |= WS_EX_APPWINDOW;
51262d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko  if (prevent_activation)
5132e331b938b38057e333fab0ba841130ea8467794Douglas Gregor    UpdateWindowAttribute(GWL_EXSTYLE, value_to_change, 0, false);
5142e331b938b38057e333fab0ba841130ea8467794Douglas Gregor  else
5154e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis    UpdateWindowAttribute(GWL_EXSTYLE, 0, value_to_change, false);
516b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregor#endif
517a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek}
5184e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
519cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenkogfx::NativeWindow PanelView::GetNativePanelWindow() {
5203315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko  return window_->GetNativeWindow();
52178db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregor}
52278db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregor
52378db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregorvoid PanelView::UpdatePanelTitleBar() {
52467812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  UpdateWindowTitle();
52578db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregor  UpdateWindowIcon();
52678db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregor}
52767812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko
52862d0f569360a664018316e4a21a4e960560b271dDmitri Gribenkovoid PanelView::UpdatePanelLoadingAnimations(bool should_animate) {
52978db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregor  GetFrameView()->UpdateThrobber();
53078db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregor}
5314e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
532b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregorvoid PanelView::PanelWebContentsFocused(content::WebContents* contents) {
533a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  web_view_->OnWebContentsFocused(contents);
534ebfa339321f8a4df9d5011e591a615d5765107d5Ted Kremenek}
535ebfa339321f8a4df9d5011e591a615d5765107d5Ted Kremenek
536ebfa339321f8a4df9d5011e591a615d5765107d5Ted Kremenekvoid PanelView::PanelCut() {
537ebfa339321f8a4df9d5011e591a615d5765107d5Ted Kremenek  // Nothing to do since we do not have panel-specific system menu.
538cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko  NOTREACHED();
5393315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko}
5401adb082a709f7b588f03672999294e061234b2cfDouglas Gregor
5411adb082a709f7b588f03672999294e061234b2cfDouglas Gregorvoid PanelView::PanelCopy() {
5421adb082a709f7b588f03672999294e061234b2cfDouglas Gregor  // Nothing to do since we do not have panel-specific system menu.
54367812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  NOTREACHED();
5441adb082a709f7b588f03672999294e061234b2cfDouglas Gregor}
5451adb082a709f7b588f03672999294e061234b2cfDouglas Gregor
54667812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenkovoid PanelView::PanelPaste() {
54762d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko  // Nothing to do since we do not have panel-specific system menu.
5481adb082a709f7b588f03672999294e061234b2cfDouglas Gregor  NOTREACHED();
5491adb082a709f7b588f03672999294e061234b2cfDouglas Gregor}
5504e7064fa7e344e8f87a5b8457e96dfdd252c4a9eArgyrios Kyrtzidis
551a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenekvoid PanelView::DrawAttention(bool draw_attention) {
55254d67caeee4fdce81f07163832f1163d5f2af5d2Daniel Dunbar  DCHECK((panel_->attention_mode() & Panel::USE_PANEL_ATTENTION) != 0);
553cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko
5543315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko  if (is_drawing_attention_ == draw_attention)
5557d0d40e58807f73e06ff5eb637a48e9f978b0e2aDouglas Gregor    return;
5567d0d40e58807f73e06ff5eb637a48e9f978b0e2aDouglas Gregor  is_drawing_attention_ = draw_attention;
5577d0d40e58807f73e06ff5eb637a48e9f978b0e2aDouglas Gregor  GetFrameView()->SchedulePaint();
55867812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko
5597d0d40e58807f73e06ff5eb637a48e9f978b0e2aDouglas Gregor  if ((panel_->attention_mode() & Panel::USE_SYSTEM_ATTENTION) != 0) {
5607d0d40e58807f73e06ff5eb637a48e9f978b0e2aDouglas Gregor#if defined(OS_WIN)
56167812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko    // The default implementation of Widget::FlashFrame only flashes 5 times.
56262d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko    // We need more than that.
5637d0d40e58807f73e06ff5eb637a48e9f978b0e2aDouglas Gregor    FLASHWINFO fwi;
5647d0d40e58807f73e06ff5eb637a48e9f978b0e2aDouglas Gregor    fwi.cbSize = sizeof(fwi);
565b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis    fwi.hwnd = views::HWNDForWidget(window_);
566a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek    if (draw_attention) {
567a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek      fwi.dwFlags = FLASHW_ALL;
5680b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor      fwi.uCount = panel::kNumberOfTimesToFlashPanelForAttention;
569cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko      fwi.dwTimeout = 0;
5703315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko    } else {
5710b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor      // TODO(jianli): calling FlashWindowEx with FLASHW_STOP flag for the
5720b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor      // panel window has the same problem as the stack window. However,
5730b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor      // we cannot take the similar fix since there is no background window
57467812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko      // to replace for the regular panel window. More investigation is needed.
5750b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor      fwi.dwFlags = FLASHW_STOP;
5760b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor    }
57767812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko    ::FlashWindowEx(&fwi);
57862d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko#else
5790b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor    window_->FlashFrame(draw_attention);
5800b36e614aa19df72885d5e0de996f7fbb9874ec3Douglas Gregor#endif
581b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis  }
582b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis}
583a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek
5846931900f43cea558c6974075256c07728dbfecc6Douglas Gregorbool PanelView::IsDrawingAttention() const {
5856931900f43cea558c6974075256c07728dbfecc6Douglas Gregor  return is_drawing_attention_;
5866931900f43cea558c6974075256c07728dbfecc6Douglas Gregor}
587cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko
5883315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenkovoid PanelView::HandlePanelKeyboardEvent(
5896931900f43cea558c6974075256c07728dbfecc6Douglas Gregor    const content::NativeWebKeyboardEvent& event) {
5906931900f43cea558c6974075256c07728dbfecc6Douglas Gregor  views::FocusManager* focus_manager = GetFocusManager();
5916931900f43cea558c6974075256c07728dbfecc6Douglas Gregor  if (focus_manager->shortcut_handling_suspended())
59267812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko    return;
5936931900f43cea558c6974075256c07728dbfecc6Douglas Gregor
5946931900f43cea558c6974075256c07728dbfecc6Douglas Gregor  ui::Accelerator accelerator(
59567812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko      static_cast<ui::KeyboardCode>(event.windowsKeyCode),
59662d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko      content::GetModifiersFromNativeWebKeyboardEvent(event));
5976931900f43cea558c6974075256c07728dbfecc6Douglas Gregor  if (event.type == blink::WebInputEvent::KeyUp)
5986931900f43cea558c6974075256c07728dbfecc6Douglas Gregor    accelerator.set_type(ui::ET_KEY_RELEASED);
599011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor  focus_manager->ProcessAccelerator(accelerator);
600011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor}
601011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor
602011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregorvoid PanelView::FullScreenModeChanged(bool is_full_screen) {
603cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko  if (is_full_screen) {
6043315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko    if (window_->IsVisible() && always_on_top_)
605011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor      window_->Hide();
606011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor  } else {
607011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor    if (!window_->IsVisible()) {
60867812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko      ShowPanelInactive();
609011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor
610011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor#if defined(OS_WIN)
61167812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko      // When hiding and showing again a top-most window that belongs to a
61262d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko      // background application (i.e. the application is not a foreground one),
613011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor      // the window may loose top-most placement even though its WS_EX_TOPMOST
614011d8b93b7cfa8492b8a9c909a850d6577e08dcaDouglas Gregor      // bit is still set. Re-issuing SetWindowsPos() returns the window to its
615b395c63b473bf1b3783bff371a993332e8c4c5e3Argyrios Kyrtzidis      // top-most placement.
616a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek      if (always_on_top_)
617a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor        window_->SetAlwaysOnTop(true);
618a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor#endif
619cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko    }
6203315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko  }
621a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor}
622a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor
623a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregorbool PanelView::IsPanelAlwaysOnTop() const {
62467812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  return always_on_top_;
625a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor}
626a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor
62767812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenkovoid PanelView::SetPanelAlwaysOnTop(bool on_top) {
62862d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko  if (always_on_top_ == on_top)
629a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor    return;
630a67e03fdf1ae8a1f92463a307d0b6281f1161f40Douglas Gregor  always_on_top_ = on_top;
6312957e6f8c4c2e58a4b9cb639949fea801970fe36Argyrios Kyrtzidis
632a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  window_->SetAlwaysOnTop(on_top);
6333315618561d19c99a7a52c72a31fb182111da716Dmitri Gribenko  window_->SetVisibleOnAllWorkspaces(on_top);
6343064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  window_->non_client_view()->Layout();
6353064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek  window_->client_view()->Layout();
6363064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek}
63767812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko
6383064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenekvoid PanelView::UpdatePanelMinimizeRestoreButtonVisibility() {
63967812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  GetFrameView()->UpdateTitlebarMinimizeRestoreButtonVisibility();
6403064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek}
6413064ef9e604d19a0cfd0d8e3ed3055bfd83f88fdTed Kremenek
6429f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregorvoid PanelView::SetWindowCornerStyle(panel::CornerStyle corner_style) {
643a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  GetFrameView()->SetWindowCornerStyle(corner_style);
644aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
645cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko
646cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenkovoid PanelView::PanelExpansionStateChanging(Panel::ExpansionState old_state,
6479f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor                                            Panel::ExpansionState new_state) {
6489f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor#if defined(OS_WIN)
6499f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor  // Live preview is only available since Windows 7.
6509f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor  if (base::win::GetVersion() < base::win::VERSION_WIN7)
6519f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor    return;
6529f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor
6539f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor  if (panel_->collection()->type() != PanelCollection::DOCKED)
65462d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko    return;
65562d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko
656ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis  bool is_minimized = old_state != Panel::EXPANDED;
657ee0f84fc84ed7de7975e102668d8e53a778f7a8cArgyrios Kyrtzidis  bool will_be_minimized = new_state != Panel::EXPANDED;
6584807231938d8aff28de09f78f301f9ba5845e5e4Douglas Gregor  if (is_minimized == will_be_minimized)
6594807231938d8aff28de09f78f301f9ba5845e5e4Douglas Gregor    return;
66067812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko
661a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  HWND native_window = views::HWNDForWidget(window_);
662aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
663572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregor  if (!thumbnailer_.get()) {
664572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregor    DCHECK(native_window);
665572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregor    thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window, NULL));
66667812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  }
667572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregor
66867812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  // Cache the image at this point.
669572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregor  if (will_be_minimized) {
670572feb2a190b5e8b04fb06c4ac50ee0f61e93ff0Douglas Gregor    // If the panel is still active (we will deactivate the minimizd panel at
6719e5bb85ac899eeab7c21b5ff9030c3da6ff4837bChandler Carruth    // later time), we need to paint it immediately as inactive so that we can
6729e5bb85ac899eeab7c21b5ff9030c3da6ff4837bChandler Carruth    // take a snapshot of inactive panel.
673aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (focused_) {
6744807231938d8aff28de09f78f301f9ba5845e5e4Douglas Gregor      force_to_paint_as_inactive_ = true;
6754807231938d8aff28de09f78f301f9ba5845e5e4Douglas Gregor      ::RedrawWindow(native_window, NULL, NULL,
6764807231938d8aff28de09f78f301f9ba5845e5e4Douglas Gregor                     RDW_NOCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW);
677664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    }
678664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis
679664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    // Start the thumbnailer and capture the snapshot now.
680664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    thumbnailer_->Start();
681664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    thumbnailer_->CaptureSnapshot();
682664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis  } else {
683664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    force_to_paint_as_inactive_ = false;
684664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    thumbnailer_->Stop();
685664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis  }
686664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis
687664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis#endif
688664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis}
689664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis
69067812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenkogfx::Size PanelView::WindowSizeFromContentSize(
691664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    const gfx::Size& content_size) const {
692664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis  gfx::Size frame = GetFrameView()->NonClientAreaSize();
693664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis  return gfx::Size(content_size.width() + frame.width(),
694664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis                   content_size.height() + frame.height());
695664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis}
696664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis
697664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidisgfx::Size PanelView::ContentSizeFromWindowSize(
698664b06f9bd2ea83443ddc8553feba8ba48880752Argyrios Kyrtzidis    const gfx::Size& window_size) const {
6999f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor  gfx::Size frame = GetFrameView()->NonClientAreaSize();
7009f1e3ff3b3095967e2b92b57a53524e2d6bb141cDouglas Gregor  return gfx::Size(window_size.width() - frame.width(),
701ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor                   window_size.height() - frame.height());
702a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek}
703aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
704ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregorint PanelView::TitleOnlyHeight() const {
705ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor  return panel::kTitlebarHeight;
706ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor}
70767812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko
708ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregorvoid PanelView::MinimizePanelBySystem() {
70967812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  window_->Minimize();
710ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor}
711ecdcb883cbc6bb4a2445dc6f02d58d9bdb54a0edDouglas Gregor
71236897b05ca2886e287f01802614bc10cbadcec22Douglas Gregorbool PanelView::IsPanelMinimizedBySystem() const {
713a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  return window_->IsMinimized();
71436897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor}
71536897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor
716cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenkobool PanelView::IsPanelShownOnActiveDesktop() const {
717aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#if defined(OS_WIN)
71836897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor  // Virtual desktop is not supported by the native Windows system.
71936897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor  return true;
72036897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor#else
72167812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  NOTIMPLEMENTED();
72236897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor  return true;
72336897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor#endif
72467812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko}
72562d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko
72636897b05ca2886e287f01802614bc10cbadcec22Douglas Gregorvoid PanelView::ShowShadow(bool show) {
72736897b05ca2886e287f01802614bc10cbadcec22Douglas Gregor#if defined(OS_WIN)
728e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  // The overlapped window has the shadow while the popup window does not have
729a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  // the shadow.
7301f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  int overlap_style = WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU;
7311f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  int popup_style = WS_POPUP;
732cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko  UpdateWindowAttribute(GWL_STYLE,
7331f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor                        show ? overlap_style : popup_style,
734aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis                        show ? popup_style : overlap_style,
7351f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor                        true);
7361f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor#endif
7371f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
7381f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
7391f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregorvoid PanelView::AttachWebContents(content::WebContents* contents) {
740e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  web_view_->SetWebContents(contents);
7411f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
742a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek
7431f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregorvoid PanelView::DetachWebContents(content::WebContents* contents) {
744cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko  web_view_->SetWebContents(NULL);
7451f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
7461f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
747aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios KyrtzidisNativePanelTesting* PanelView::CreateNativePanelTesting() {
7481f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  return new NativePanelTestingWin(this);
7491f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
7501f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
7511f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregorvoid PanelView::OnDisplayChanged() {
7521f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  panel_->manager()->display_settings_provider()->OnDisplaySettingsChanged();
7531f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
7541f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
755a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenekvoid PanelView::OnWorkAreaChanged() {
7561f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  panel_->manager()->display_settings_provider()->OnDisplaySettingsChanged();
757cb6bcf1c6392398ce9fccb4a0881dd4149568dcfDmitri Gribenko}
7581f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
7591f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregorbool PanelView::WillProcessWorkAreaChange() const {
760aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return true;
7611f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
7621f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
7631f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregorviews::View* PanelView::GetContentsView() {
7641f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor  return this;
7651f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
7661f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
7671f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregorviews::NonClientFrameView* PanelView::CreateNonClientFrameView(
7681f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor    views::Widget* widget) {
76967812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  PanelFrameView* frame_view = new PanelFrameView(this);
77067812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  frame_view->Init();
77162d0f569360a664018316e4a21a4e960560b271dDmitri Gribenko  return frame_view;
7721f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor}
7731f60d9ea523fc321d811fe880ba9a1ec74fa8f9bDouglas Gregor
774e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenkobool PanelView::CanResize() const {
775e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  return true;
776283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor}
777283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor
778ff74f9683943c0db9cb075423596b00ea3b38c5dDmitri Gribenkobool PanelView::CanMaximize() const {
779283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor  return false;
780283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor}
781283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor
782ff74f9683943c0db9cb075423596b00ea3b38c5dDmitri Gribenkobase::string16 PanelView::GetWindowTitle() const {
78378db0cdd49ec24034a5b2a4210fcda03a0919a81Douglas Gregor  return panel_->GetWindowTitle();
7841adb082a709f7b588f03672999294e061234b2cfDouglas Gregor}
7851adb082a709f7b588f03672999294e061234b2cfDouglas Gregor
7862e331b938b38057e333fab0ba841130ea8467794Douglas Gregorgfx::ImageSkia PanelView::GetWindowAppIcon() {
7872e331b938b38057e333fab0ba841130ea8467794Douglas Gregor  gfx::Image app_icon = panel_->app_icon();
788ff74f9683943c0db9cb075423596b00ea3b38c5dDmitri Gribenko  if (app_icon.IsEmpty())
789283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor    return GetWindowIcon();
790283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor  else
7917d91438047450869d7b881e1c63868c4b52a3cc2Dmitri Gribenko    return *app_icon.ToImageSkia();
7927d91438047450869d7b881e1c63868c4b52a3cc2Dmitri Gribenko}
79395f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenek
79495f33555a6d51b6537a9ed3968c3d1c2e4991b51Ted Kremenekgfx::ImageSkia PanelView::GetWindowIcon() {
795404628caa53a3f898047d73b38647d6fbb827e00Dmitri Gribenko  gfx::Image icon = panel_->GetCurrentPageIcon();
796404628caa53a3f898047d73b38647d6fbb827e00Dmitri Gribenko  return icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia();
7978ccac3de1335f1cfd7cea56ba1cefcf0b724ce3fArgyrios Kyrtzidis}
7988ccac3de1335f1cfd7cea56ba1cefcf0b724ce3fArgyrios Kyrtzidis
799f46034af49435a4d1a0085a4738343122aeb6521Douglas Gregorvoid PanelView::WindowClosing() {
800b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregor  // When closing a panel via window.close, API or the close button,
801b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregor  // ClosePanel() is called first, destroying the native |window_|
80297b9872d5775446cb8aca1380e437649fe848d91Douglas Gregor  // which results in this method being called. ClosePanel() sets
803b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregor  // |window_closed_| to NULL.
80446f92523918fd4ac4df5489265c7f85c1b28baeaDmitri Gribenko  // If we still have a |window_closed_| here, the close was triggered by the
8054451746d8f658b51eaf15dd24664a488457063a9Argyrios Kyrtzidis  // OS, (e.g. clicking on taskbar menu), which destroys the native |window_|
8064451746d8f658b51eaf15dd24664a488457063a9Argyrios Kyrtzidis  // without invoking ClosePanel() beforehand.
8075694feb5ccd6eb862cb600b55753cecc13794471Dmitri Gribenko  if (!window_closed_) {
808a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek    panel_->OnWindowClosing();
809a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek    ClosePanel();
810a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek    DCHECK(window_closed_);
81167812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  }
812283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor}
813283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor
814e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidisvoid PanelView::DeleteDelegate() {
815e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis  delete this;
816e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis}
81721c3607282550779c9ae5fe784928597807fd110Argyrios Kyrtzidis
818e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidisvoid PanelView::OnWindowBeginUserBoundsChange() {
819e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis  user_resizing_ = true;
820e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis  panel_->OnPanelStartUserResizing();
821e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis
82221c3607282550779c9ae5fe784928597807fd110Argyrios Kyrtzidis#if defined(OS_WIN)
82321c3607282550779c9ae5fe784928597807fd110Argyrios Kyrtzidis  StackedPanelCollection* stack = panel_->stack();
824e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis  if (stack) {
82521c3607282550779c9ae5fe784928597807fd110Argyrios Kyrtzidis    // Listen to WM_SIZING message in order to find out whether the interior
82621c3607282550779c9ae5fe784928597807fd110Argyrios Kyrtzidis    // edge is being resized such that the specific maximum size could be
82705756dc8d11cd2054e0cb94f0302e4eb39acc68eDmitri Gribenko    // passed to the system.
828e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis    if (panel_->stack()->GetPanelBelow(panel_.get())) {
829e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis      ui::HWNDSubclass::AddFilterToTarget(views::HWNDForWidget(window_), this);
830e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis      user_resizing_interior_stacked_panel_edge_ = false;
831aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
832aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
833aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // Keep track of the original full size of the resizing panel such that it
834aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // can be restored to this size once it is shrunk to minimized state.
835aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    original_full_size_of_resizing_panel_ = panel_->full_size();
836aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
837aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // Keep track of the original full size of the panel below the resizing
838aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // panel such that it can be restored to this size once it is shrunk to
839aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // minimized state.
840aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    Panel* below_panel = stack->GetPanelBelow(panel_.get());
841aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (below_panel && !below_panel->IsMinimized()) {
842aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      original_full_size_of_panel_below_resizing_panel_ =
843aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis          below_panel->full_size();
844aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
845aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
846aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#endif
847aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
848aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
849aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisvoid PanelView::OnWindowEndUserBoundsChange() {
850aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  user_resizing_ = false;
851aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  panel_->OnPanelEndUserResizing();
852aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
853aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  // No need to proceed with post-resizing update when there is no size change.
854aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  gfx::Rect new_bounds = window_->GetWindowBoundsInScreen();
855aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (bounds_ == new_bounds)
856aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    return;
857aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  bounds_ = new_bounds;
858aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
859aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  panel_->IncreaseMaxSize(bounds_.size());
860aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  panel_->set_full_size(bounds_.size());
861aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
862aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#if defined(OS_WIN)
863aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  StackedPanelCollection* stack = panel_->stack();
864aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  if (stack) {
865aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // No need to listen to WM_SIZING message any more.
866aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    ui::HWNDSubclass::RemoveFilterFromAllTargets(this);
867aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
868aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // If the height of resizing panel shrinks close to the titlebar height,
869aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // treate it as minimized. This could occur when the user is dragging
870aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // 1) the top edge of the top panel downward to shrink it; or
871aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // 2) the bottom edge of any panel upward to shrink it.
872aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (panel_->GetBounds().height() <
873aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis            kStackedPanelHeightShrinkThresholdToBecomeMinimized) {
874aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      stack->MinimizePanel(panel_.get());
875aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      panel_->set_full_size(original_full_size_of_resizing_panel_);
876aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
877aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
878aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // If the height of panel below the resizing panel shrinks close to the
879ff74f9683943c0db9cb075423596b00ea3b38c5dDmitri Gribenko    // titlebar height, treat it as minimized. This could occur when the user
880aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    // is dragging the bottom edge of non-bottom panel downward to expand it
881ff74f9683943c0db9cb075423596b00ea3b38c5dDmitri Gribenko    // and also shrink the panel below.
882aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    Panel* below_panel = stack->GetPanelBelow(panel_.get());
883aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    if (below_panel && !below_panel->IsMinimized() &&
884ff74f9683943c0db9cb075423596b00ea3b38c5dDmitri Gribenko        below_panel->GetBounds().height() <
885ff74f9683943c0db9cb075423596b00ea3b38c5dDmitri Gribenko            kStackedPanelHeightShrinkThresholdToBecomeMinimized) {
886aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      stack->MinimizePanel(below_panel);
887aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis      below_panel->set_full_size(
888aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis          original_full_size_of_panel_below_resizing_panel_);
889aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis    }
890aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  }
891aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis#endif
892aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
893aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  panel_->collection()->RefreshLayout();
894aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
895aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
896aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisviews::Widget* PanelView::GetWidget() {
897aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return window_;
898aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
89939e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie
900aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisconst views::Widget* PanelView::GetWidget() const {
901aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  return window_;
902aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
903aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
904aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisvoid PanelView::UpdateLoadingAnimations(bool should_animate) {
905aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  GetFrameView()->UpdateThrobber();
906aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
907aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
908aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidisvoid PanelView::UpdateWindowTitle() {
909aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  window_->UpdateWindowTitle();
910aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis  GetFrameView()->UpdateTitle();
911aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis}
912aed123ec3cc37e457fe20a6158fdadf8849ad916Argyrios Kyrtzidis
913283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregorvoid PanelView::UpdateWindowIcon() {
914283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor  window_->UpdateWindowIcon();
915283cae37b03047c14ef918503bc46b08405c3b69Douglas Gregor  GetFrameView()->UpdateIcon();
9162e331b938b38057e333fab0ba841130ea8467794Douglas Gregor}
917007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenek
918007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenekvoid PanelView::Layout() {
919007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenek  // |web_view_| might not be created yet when the window is first created.
920007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenek  if (web_view_)
921007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenek    web_view_->SetBounds(0, 0, width(), height());
922007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenek}
923007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenek
924007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccdTed Kremenekgfx::Size PanelView::GetMinimumSize() const {
925eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // If the panel is minimized, it can be rendered to very small size, like
926b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis  // 4-pixel lines when it is docked. Otherwise, its size should not be less
927b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis  // than its minimum size.
928b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis  return panel_->IsMinimized() ? gfx::Size() :
929fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidis      gfx::Size(panel::kPanelMinWidth, panel::kPanelMinHeight);
930fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidis}
931fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidis
932fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidisgfx::Size PanelView::GetMaximumSize() const {
933fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidis  // If the user is resizing a stacked panel by its bottom edge, make sure its
934fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidis  // height cannot grow more than what the panel below it could offer. This is
935b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis  // because growing a stacked panel by y amount will shrink the panel below it
936b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis  // by same amount and we do not want the panel below it being shrunk to be
937b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis  // smaller than the titlebar.
938b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis#if defined(OS_WIN)
939d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  if (panel_->stack() && user_resizing_interior_stacked_panel_edge_) {
940d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis    Panel* below_panel = panel_->stack()->GetPanelBelow(panel_.get());
941e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko    if (below_panel && !below_panel->IsMinimized()) {
942d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis      return gfx::Size(0, below_panel->GetBounds().bottom() -
943d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis          panel_->GetBounds().y() - panel::kTitlebarHeight);
944d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis    }
945d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  }
946d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis#endif
947d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  return gfx::Size();
948e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis}
949e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis
950e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidisbool PanelView::AcceleratorPressed(const ui::Accelerator& accelerator) {
951e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis  if (mouse_pressed_ && accelerator.key_code() == ui::VKEY_ESCAPE) {
952e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis    OnTitlebarMouseCaptureLost();
953e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis    return true;
954e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis  }
955d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis
956d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  // No other accelerator is allowed when the drag begins.
957d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  if (mouse_dragging_state_ == DRAGGING_STARTED)
958d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis    return true;
959d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis
960e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  const std::map<ui::Accelerator, int>& accelerator_table =
961e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko      GetAcceleratorTable();
962d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  std::map<ui::Accelerator, int>::const_iterator iter =
963d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis      accelerator_table.find(accelerator);
964d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  DCHECK(iter != accelerator_table.end());
965e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  return panel_->ExecuteCommandIfEnabled(iter->second);
966d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis}
967d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis
968d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidisvoid PanelView::OnWidgetDestroying(views::Widget* widget) {
969d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  window_ = NULL;
970d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis}
971d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis
972e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidisvoid PanelView::OnWidgetActivationChanged(views::Widget* widget, bool active) {
973e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis#if defined(OS_WIN)
974e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis  // WM_NCACTIVATED could be sent when an active window is being destroyed on
975e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis  // Windows. We need to guard against this.
976e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis  if (window_closed_)
977e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis    return;
978e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis
979e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis  bool focused = active;
980e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis  if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_NATIVE) {
981e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis    // The panel window is in focus (actually accepting keystrokes) if it is
982e9ebd852ec1effa393bcc4aad73d9c657a5279c1Argyrios Kyrtzidis    // active and belongs to a foreground application.
983d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis    focused = active &&
984d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis        views::HWNDForWidget(widget) == ::GetForegroundWindow();
985d98ef9ae48ab4090d4d5d703ce65cfac62807fdaArgyrios Kyrtzidis  }
986fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidis#else
987fa865df489fe68668c554dece36c68b4ce03920fArgyrios Kyrtzidis  NOTIMPLEMENTED();
988b0d6eaa6b646c18c49923aefc76973801f561701Argyrios Kyrtzidis  bool focused = active;
989eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek#endif
990eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
991eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  if (focused_ == focused)
992eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    return;
993eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  focused_ = focused;
994eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
995eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // Expand the panel if the minimized panel is activated by means other than
996eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // clicking on its titlebar. This is the workaround to support restoring the
997eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // minimized panel by other means, like alt-tabbing, win-tabbing, or clicking
998eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // the taskbar icon. Note that this workaround does not work for one edge
999eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // case: the mouse happens to be at the minimized panel when the user tries to
1000eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // bring up the panel with the above alternatives.
1001da6fb69873079a0193ed8c9fa1d1b859d4f87b95Ted Kremenek  // When the user clicks on the minimized panel, the panel expansion will be
1002eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  // done when we process the mouse button pressed message.
1003eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek#if defined(OS_WIN)
1004eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  if (focused_ && panel_->IsMinimized() &&
1005eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek      panel_->collection()->type() == PanelCollection::DOCKED &&
1006eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek      gfx::Screen::GetScreenFor(widget->GetNativeWindow())->
1007eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek          GetWindowUnderCursor() != widget->GetNativeWindow()) {
1008eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    panel_->Restore();
1009eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  }
101067812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko#endif
1011eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
1012eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  panel()->OnActiveStateChanged(focused);
1013eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
1014eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek   // Give web contents view a chance to set focus to the appropriate element.
1015eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  if (focused_) {
1016eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    content::WebContents* web_contents = panel_->GetWebContents();
1017eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    if (web_contents)
1018eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek      web_contents->RestoreFocus();
1019eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  }
1020eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek}
1021eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
1022eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenekvoid PanelView::OnWidgetBoundsChanged(views::Widget* widget,
1023eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek                                      const gfx::Rect& new_bounds) {
1024eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  if (user_resizing_)
1025eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    panel()->collection()->OnPanelResizedByMouse(panel(), new_bounds);
1026eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek}
1027eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
1028eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenekbool PanelView::OnTitlebarMousePressed(const gfx::Point& mouse_location) {
1029eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  mouse_pressed_ = true;
1030eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  mouse_dragging_state_ = NO_DRAGGING;
1031eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  last_mouse_location_ = mouse_location;
1032eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  return true;
1033eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek}
1034eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
1035eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenekbool PanelView::OnTitlebarMouseDragged(const gfx::Point& mouse_location) {
1036eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  if (!mouse_pressed_)
1037e8b3de090b9de3c27c5d381e767217ddb849d5d8Anders Carlsson    return false;
1038eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
1039eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  if (mouse_dragging_state_ == NO_DRAGGING &&
1040eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek      ExceededDragThreshold(mouse_location - last_mouse_location_)) {
1041eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    // When a drag begins, we do not want to the client area to still receive
1042eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    // the focus. We do not need to do this for the unfocused minimized panel.
1043eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    if (!panel_->IsMinimized()) {
1044eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek      old_focused_view_ = GetFocusManager()->GetFocusedView();
1045eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek      GetFocusManager()->SetFocusedView(GetFrameView());
1046eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    }
1047eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek
1048eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    panel_->manager()->StartDragging(panel_.get(), last_mouse_location_);
1049eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek    mouse_dragging_state_ = DRAGGING_STARTED;
1050eca099bdb0178d408d4f717c2e9627e0d0e673c6Ted Kremenek  }
10518fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor  if (mouse_dragging_state_ == DRAGGING_STARTED) {
10528fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    panel_->manager()->Drag(mouse_location);
10538fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor
10548fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    // Once in drag, update |last_mouse_location_| on each drag fragment, since
1055e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko    // we already dragged the panel up to the current mouse location.
1056e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko    last_mouse_location_ = mouse_location;
10578fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor  }
1058d1f09b482b3874be07dfe9dd24bfad98915989c3Douglas Gregor  return true;
10595e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidis}
10605e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidis
10615e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidisbool PanelView::OnTitlebarMouseReleased(panel::ClickModifier modifier) {
106228a83f57003469fb615ad27dd34bcf5b0a10da8cArgyrios Kyrtzidis  if (mouse_dragging_state_ != NO_DRAGGING) {
1063d99ef536b241071b6f4c01db6525dc03242ac30bDmitri Gribenko    // Ensure dragging a minimized panel does not leave it activated.
1064d99ef536b241071b6f4c01db6525dc03242ac30bDmitri Gribenko    // Windows activates a panel on mouse-down, regardless of our attempts
10655e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidis    // to prevent activation of a minimized panel. Now that we know mouse-down
10668fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    // resulted in a mouse-drag, we need to ensure the minimized panel is
10678fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    // deactivated.
10688fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    if (panel_->IsMinimized() && focused_)
106967812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko      panel_->Deactivate();
10708fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor
10718fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    if (mouse_dragging_state_ == DRAGGING_STARTED) {
1072b3958476b21702a15f64f09d2862506d03dffe7bDmitri Gribenko      // When a drag ends, restore the focus.
10735e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidis      if (old_focused_view_) {
10745e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidis        GetFocusManager()->SetFocusedView(old_focused_view_);
10755e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidis        old_focused_view_ = NULL;
107628a83f57003469fb615ad27dd34bcf5b0a10da8cArgyrios Kyrtzidis      }
1077d99ef536b241071b6f4c01db6525dc03242ac30bDmitri Gribenko      return EndDragging(false);
1078d99ef536b241071b6f4c01db6525dc03242ac30bDmitri Gribenko    }
10795e192a7d60e776fa65e633cd9c2a0d59df132f23Argyrios Kyrtzidis
10808fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    // The panel drag was cancelled before the mouse is released. Do not
10818fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    // treat this as a click.
10828fa0a80b4482ad94e82c4a19e23de17fd69140b5Douglas Gregor    return true;
10838eece46c544e79190d5b3e7c28f68c1463fbf2f9Ted Kremenek  }
1084bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1085bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  panel_->OnTitlebarClicked(modifier);
1086bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  return true;
1087cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko}
1088bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1089bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenekbool PanelView::OnTitlebarMouseCaptureLost() {
1090bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (mouse_dragging_state_ == DRAGGING_STARTED)
1091bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    return EndDragging(true);
1092bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  return true;
1093bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek}
1094bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1095bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenekbool PanelView::EndDragging(bool cancelled) {
1096bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  // Only handle clicks that started in our window.
1097bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (!mouse_pressed_)
1098bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    return false;
1099bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  mouse_pressed_ = false;
1100bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1101bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  mouse_dragging_state_ = DRAGGING_ENDED;
1102bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  panel_->manager()->EndDragging(cancelled);
1103bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  return true;
1104bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek}
1105bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1106bbf66ca1dad17773cc682d69b8482c4e179aeaebTed KremenekPanelFrameView* PanelView::GetFrameView() const {
11078eece46c544e79190d5b3e7c28f68c1463fbf2f9Ted Kremenek  return static_cast<PanelFrameView*>(window_->non_client_view()->frame_view());
11088eece46c544e79190d5b3e7c28f68c1463fbf2f9Ted Kremenek}
1109bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1110bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenekbool PanelView::IsAnimatingBounds() const {
1111bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (bounds_animator_.get() && bounds_animator_->is_animating())
1112bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    return true;
1113bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  StackedPanelCollection* stack = panel_->stack();
1114bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (!stack)
1115bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    return false;
1116bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  return stack->IsAnimatingPanelBounds(panel_.get());
1117bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek}
1118bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1119bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenekbool PanelView::IsWithinResizingArea(const gfx::Point& mouse_location) const {
1120bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  gfx::Rect bounds = window_->GetWindowBoundsInScreen();
1121bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  DCHECK(bounds.Contains(mouse_location));
1122bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  return mouse_location.x() < bounds.x() + kResizeInsideBoundsSize ||
1123bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek         mouse_location.x() >= bounds.right() - kResizeInsideBoundsSize ||
1124bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek         mouse_location.y() < bounds.y() + kResizeInsideBoundsSize ||
1125bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek         mouse_location.y() >= bounds.bottom() - kResizeInsideBoundsSize;
1126bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek}
1127bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1128bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek#if defined(OS_WIN)
1129bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenekvoid PanelView::UpdateWindowAttribute(int attribute_index,
1130bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek                                      int attribute_value_to_set,
1131bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek                                      int attribute_value_to_reset,
1132bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek                                      bool update_frame) {
1133bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  HWND native_window = views::HWNDForWidget(window_);
1134bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  int value = ::GetWindowLong(native_window, attribute_index);
1135bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  int expected_value = value;
1136bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (attribute_value_to_set)
1137bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    expected_value |=  attribute_value_to_set;
1138bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (attribute_value_to_reset)
1139bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    expected_value &=  ~attribute_value_to_reset;
1140bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (value != expected_value)
1141bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    ::SetWindowLong(native_window, attribute_index, expected_value);
1142bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek
1143bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  // Per MSDN, if any of the frame styles is changed, SetWindowPos with the
1144bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  // SWP_FRAMECHANGED flag must be called in order for the cached window data
1145bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  // to be updated properly.
1146bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx
1147bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  if (update_frame) {
1148bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek    ::SetWindowPos(native_window, NULL, 0, 0, 0, 0,
1149bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek                   SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
1150bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek                       SWP_NOZORDER | SWP_NOACTIVATE);
1151bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek  }
1152bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek}
1153bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek#endif
1154bbf66ca1dad17773cc682d69b8482c4e179aeaebTed Kremenek