1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/views/win/fullscreen_handler.h"
6
7#include "base/logging.h"
8#include "ui/gfx/rect.h"
9#include "ui/views/win/scoped_fullscreen_visibility.h"
10
11namespace views {
12
13////////////////////////////////////////////////////////////////////////////////
14// FullscreenHandler, public:
15
16FullscreenHandler::FullscreenHandler()
17    : hwnd_(NULL),
18      fullscreen_(false),
19      metro_snap_(false) {
20}
21
22FullscreenHandler::~FullscreenHandler() {
23}
24
25void FullscreenHandler::SetFullscreen(bool fullscreen) {
26  if (fullscreen_ == fullscreen)
27    return;
28
29  SetFullscreenImpl(fullscreen, false);
30}
31
32void FullscreenHandler::SetMetroSnap(bool metro_snap) {
33  if (metro_snap_ == metro_snap)
34    return;
35
36  SetFullscreenImpl(metro_snap, true);
37  metro_snap_ = metro_snap;
38}
39
40gfx::Rect FullscreenHandler::GetRestoreBounds() const {
41  return gfx::Rect(saved_window_info_.window_rect);
42}
43
44////////////////////////////////////////////////////////////////////////////////
45// FullscreenHandler, private:
46
47void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
48  ScopedFullscreenVisibility visibility(hwnd_);
49
50  // Save current window state if not already fullscreen.
51  if (!fullscreen_) {
52    // Save current window information.  We force the window into restored mode
53    // before going fullscreen because Windows doesn't seem to hide the
54    // taskbar if the window is in the maximized state.
55    saved_window_info_.maximized = !!::IsZoomed(hwnd_);
56    if (saved_window_info_.maximized)
57      ::SendMessage(hwnd_, WM_SYSCOMMAND, SC_RESTORE, 0);
58    saved_window_info_.style = GetWindowLong(hwnd_, GWL_STYLE);
59    saved_window_info_.ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);
60    GetWindowRect(hwnd_, &saved_window_info_.window_rect);
61  }
62
63  fullscreen_ = fullscreen;
64
65  if (fullscreen_) {
66    // Set new window style and size.
67    SetWindowLong(hwnd_, GWL_STYLE,
68                  saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME));
69    SetWindowLong(hwnd_, GWL_EXSTYLE,
70                  saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME |
71                  WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
72
73    // On expand, if we're given a window_rect, grow to it, otherwise do
74    // not resize.
75    if (!for_metro) {
76      MONITORINFO monitor_info;
77      monitor_info.cbSize = sizeof(monitor_info);
78      GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST),
79                     &monitor_info);
80      gfx::Rect window_rect(monitor_info.rcMonitor);
81      SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(),
82                   window_rect.width(), window_rect.height(),
83                   SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
84    }
85  } else {
86    // Reset original window style and size.  The multiple window size/moves
87    // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be
88    // repainted.  Better-looking methods welcome.
89    SetWindowLong(hwnd_, GWL_STYLE, saved_window_info_.style);
90    SetWindowLong(hwnd_, GWL_EXSTYLE, saved_window_info_.ex_style);
91
92    if (!for_metro) {
93      // On restore, resize to the previous saved rect size.
94      gfx::Rect new_rect(saved_window_info_.window_rect);
95      SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(),
96                   new_rect.width(), new_rect.height(),
97                   SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
98    }
99    if (saved_window_info_.maximized)
100      ::SendMessage(hwnd_, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
101  }
102}
103
104}  // namespace views
105