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/sys_info.h"
12
13static bool IsPlatformFullScreenMode() {
14  // SHQueryUserNotificationState is only available for Vista and above.
15#if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_VISTA)
16  int32 major_version, minor_version, fix_version;
17  base::SysInfo::OperatingSystemVersionNumbers(&major_version,
18                                               &minor_version,
19                                               &fix_version);
20  if (major_version < 6)
21    return false;
22
23  typedef HRESULT(WINAPI *SHQueryUserNotificationStatePtr)(
24      QUERY_USER_NOTIFICATION_STATE* state);
25
26  HMODULE shell32_base = ::GetModuleHandle(L"shell32.dll");
27  if (!shell32_base) {
28    NOTREACHED();
29    return false;
30  }
31  SHQueryUserNotificationStatePtr query_user_notification_state_ptr =
32        reinterpret_cast<SHQueryUserNotificationStatePtr>
33            (::GetProcAddress(shell32_base, "SHQueryUserNotificationState"));
34  if (!query_user_notification_state_ptr) {
35    NOTREACHED();
36    return false;
37  }
38
39  QUERY_USER_NOTIFICATION_STATE state;
40  if (FAILED((*query_user_notification_state_ptr)(&state)))
41    return false;
42  return state == QUNS_RUNNING_D3D_FULL_SCREEN ||
43         state == QUNS_PRESENTATION_MODE;
44#else
45  return false;
46#endif
47}
48
49static bool IsFullScreenWindowMode() {
50  // Get the foreground window which the user is currently working on.
51  HWND wnd = ::GetForegroundWindow();
52  if (!wnd)
53    return false;
54
55  // Get the monitor where the window is located.
56  RECT wnd_rect;
57  if (!::GetWindowRect(wnd, &wnd_rect))
58    return false;
59  HMONITOR monitor = ::MonitorFromRect(&wnd_rect, MONITOR_DEFAULTTONULL);
60  if (!monitor)
61    return false;
62  MONITORINFO monitor_info = { sizeof(monitor_info) };
63  if (!::GetMonitorInfo(monitor, &monitor_info))
64    return false;
65
66  // It should be the main monitor.
67  if (!(monitor_info.dwFlags & MONITORINFOF_PRIMARY))
68    return false;
69
70  // The window should be at least as large as the monitor.
71  if (!::IntersectRect(&wnd_rect, &wnd_rect, &monitor_info.rcMonitor))
72    return false;
73  if (!::EqualRect(&wnd_rect, &monitor_info.rcMonitor))
74    return false;
75
76  // At last, the window style should not have WS_DLGFRAME and WS_THICKFRAME and
77  // its extended style should not have WS_EX_WINDOWEDGE and WS_EX_TOOLWINDOW.
78  LONG style = ::GetWindowLong(wnd, GWL_STYLE);
79  LONG ext_style = ::GetWindowLong(wnd, GWL_EXSTYLE);
80  return !((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
81           (ext_style & (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW)));
82}
83
84static bool IsFullScreenConsoleMode() {
85  // We detect this by attaching the current process to the console of the
86  // foreground window and then checking if it is in full screen mode.
87  DWORD pid = 0;
88  ::GetWindowThreadProcessId(::GetForegroundWindow(), &pid);
89  if (!pid)
90    return false;
91
92  if (!::AttachConsole(pid))
93    return false;
94
95  DWORD modes = 0;
96  ::GetConsoleDisplayMode(&modes);
97  ::FreeConsole();
98
99  return (modes & (CONSOLE_FULLSCREEN | CONSOLE_FULLSCREEN_HARDWARE)) != 0;
100}
101
102bool IsFullScreenMode() {
103  return IsPlatformFullScreenMode() ||
104         IsFullScreenWindowMode() ||
105         IsFullScreenConsoleMode();
106}
107