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