1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/fullscreen.h"
6
7#include <windows.h>
8#include <shellapi.h>
9
10#include "base/logging.h"
11#include "base/win/win_util.h"
12#include "base/win/windows_version.h"
13
14#if defined(USE_ASH)
15#include "ash/root_window_controller.h"
16#include "chrome/browser/ui/host_desktop.h"
17#endif
18
19static bool IsPlatformFullScreenMode() {
20  // SHQueryUserNotificationState is only available for Vista and above.
21#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_VISTA)
22  if (base::win::GetVersion() < base::win::VERSION_VISTA)
23    return false;
24
25  typedef HRESULT(WINAPI *SHQueryUserNotificationStatePtr)(
26      QUERY_USER_NOTIFICATION_STATE* state);
27
28  HMODULE shell32_base = ::GetModuleHandle(L"shell32.dll");
29  if (!shell32_base) {
30    NOTREACHED();
31    return false;
32  }
33  SHQueryUserNotificationStatePtr query_user_notification_state_ptr =
34        reinterpret_cast<SHQueryUserNotificationStatePtr>
35            (::GetProcAddress(shell32_base, "SHQueryUserNotificationState"));
36  if (!query_user_notification_state_ptr) {
37    NOTREACHED();
38    return false;
39  }
40
41  QUERY_USER_NOTIFICATION_STATE state;
42  if (FAILED((*query_user_notification_state_ptr)(&state)))
43    return false;
44  return state == QUNS_RUNNING_D3D_FULL_SCREEN ||
45         state == QUNS_PRESENTATION_MODE;
46#else
47  return false;
48#endif
49}
50
51static bool IsFullScreenWindowMode() {
52  // Get the foreground window which the user is currently working on.
53  HWND wnd = ::GetForegroundWindow();
54  if (!wnd)
55    return false;
56
57  // Get the monitor where the window is located.
58  RECT wnd_rect;
59  if (!::GetWindowRect(wnd, &wnd_rect))
60    return false;
61  HMONITOR monitor = ::MonitorFromRect(&wnd_rect, MONITOR_DEFAULTTONULL);
62  if (!monitor)
63    return false;
64  MONITORINFO monitor_info = { sizeof(monitor_info) };
65  if (!::GetMonitorInfo(monitor, &monitor_info))
66    return false;
67
68  // It should be the main monitor.
69  if (!(monitor_info.dwFlags & MONITORINFOF_PRIMARY))
70    return false;
71
72  // The window should be at least as large as the monitor.
73  if (!::IntersectRect(&wnd_rect, &wnd_rect, &monitor_info.rcMonitor))
74    return false;
75  if (!::EqualRect(&wnd_rect, &monitor_info.rcMonitor))
76    return false;
77
78  // At last, the window style should not have WS_DLGFRAME and WS_THICKFRAME and
79  // its extended style should not have WS_EX_WINDOWEDGE and WS_EX_TOOLWINDOW.
80  LONG style = ::GetWindowLong(wnd, GWL_STYLE);
81  LONG ext_style = ::GetWindowLong(wnd, GWL_EXSTYLE);
82  return !((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
83           (ext_style & (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW)));
84}
85
86static bool IsFullScreenConsoleMode() {
87  // We detect this by attaching the current process to the console of the
88  // foreground window and then checking if it is in full screen mode.
89  DWORD pid = 0;
90  ::GetWindowThreadProcessId(::GetForegroundWindow(), &pid);
91  if (!pid)
92    return false;
93
94  if (!::AttachConsole(pid))
95    return false;
96
97  DWORD modes = 0;
98  ::GetConsoleDisplayMode(&modes);
99  ::FreeConsole();
100
101  return (modes & (CONSOLE_FULLSCREEN | CONSOLE_FULLSCREEN_HARDWARE)) != 0;
102}
103
104bool IsFullScreenMode() {
105#if defined(USE_ASH)
106  if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH) {
107    ash::RootWindowController* controller =
108        ash::RootWindowController::ForTargetRootWindow();
109    return controller && controller->GetWindowForFullscreenMode();
110  }
111#endif
112  return IsPlatformFullScreenMode() ||
113         IsFullScreenWindowMode() ||
114         IsFullScreenConsoleMode();
115}
116