// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/fullscreen.h" #include #include #include #include #include "base/basictypes.h" #include "chrome/browser/ui/gtk/gtk_util.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/rect.h" namespace { // TODO (jianli): Merge with gtk_util::EnumerateTopLevelWindows. void EnumerateAllChildWindows(ui::EnumerateWindowsDelegate* delegate, XID window) { std::vector windows; if (!ui::GetXWindowStack(window, &windows)) { // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back // to old school enumeration of all X windows. XID root, parent, *children; unsigned int num_children; int status = XQueryTree(ui::GetXDisplay(), window, &root, &parent, &children, &num_children); if (status) { for (long i = static_cast(num_children) - 1; i >= 0; i--) windows.push_back(children[i]); XFree(children); } } std::vector::iterator iter; for (iter = windows.begin(); iter != windows.end(); iter++) { if (delegate->ShouldStopIterating(*iter)) return; } } // To find the top-most window: // 1) Enumerate all top-level windows from the top to the bottom. // 2) For each window: // 2.1) If it is hidden, continue the iteration. // 2.2) If it is managed by the Window Manager (has a WM_STATE property). // Return this window as the top-most window. // 2.3) Enumerate all its child windows. If there is a child window that is // managed by the Window Manager (has a WM_STATE property). Return this // child window as the top-most window. // 2.4) Otherwise, continue the iteration. class WindowManagerWindowFinder : public ui::EnumerateWindowsDelegate { public: WindowManagerWindowFinder() : window_(None) { } XID window() const { return window_; } protected: virtual bool ShouldStopIterating(XID window) { if (ui::PropertyExists(window, "WM_STATE")) { window_ = window; return true; } return false; } private: XID window_; DISALLOW_COPY_AND_ASSIGN(WindowManagerWindowFinder); }; class TopMostWindowFinder : public ui::EnumerateWindowsDelegate { public: TopMostWindowFinder() : top_most_window_(None) {} XID top_most_window() const { return top_most_window_; } protected: virtual bool ShouldStopIterating(XID window) { if (!ui::IsWindowVisible(window)) return false; if (ui::PropertyExists(window, "WM_STATE")) { top_most_window_ = window; return true; } WindowManagerWindowFinder child_finder; EnumerateAllChildWindows(&child_finder, window); XID child_window = child_finder.window(); if (child_window == None) return false; top_most_window_ = child_window; return true; } private: XID top_most_window_; DISALLOW_COPY_AND_ASSIGN(TopMostWindowFinder); }; bool IsTopMostWindowFullScreen() { // Find the topmost window. TopMostWindowFinder finder; EnumerateAllChildWindows(&finder, ui::GetX11RootWindow()); XID window = finder.top_most_window(); if (window == None) return false; // Make sure it is not the desktop window. static Atom desktop_atom = gdk_x11_get_xatom_by_name_for_display( gdk_display_get_default(), "_NET_WM_WINDOW_TYPE_DESKTOP"); std::vector atom_properties; if (ui::GetAtomArrayProperty(window, "_NET_WM_WINDOW_TYPE", &atom_properties) && std::find(atom_properties.begin(), atom_properties.end(), desktop_atom) != atom_properties.end()) return false; // If it is a GDK window, check it using gdk function. GdkWindow* gwindow = gdk_window_lookup(window); if (gwindow && window != GDK_ROOT_WINDOW()) return gdk_window_get_state(gwindow) == GDK_WINDOW_STATE_FULLSCREEN; // Otherwise, do the check via xlib function. return ui::IsX11WindowFullScreen(window); } } bool IsFullScreenMode() { gdk_error_trap_push(); bool result = IsTopMostWindowFullScreen(); bool got_error = gdk_error_trap_pop(); return result && !got_error; }