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