OLD | NEW |
(Empty) | |
| 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 <gdk/gdk.h> |
| 8 #include <gdk/gdkx.h> |
| 9 |
| 10 #include <algorithm> |
| 11 #include <vector> |
| 12 |
| 13 #include "base/basictypes.h" |
| 14 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 15 #include "gfx/rect.h" |
| 16 #include "ui/base/x/x11_util.h" |
| 17 |
| 18 namespace { |
| 19 |
| 20 // TODO (jianli): Merge with gtk_util::EnumerateTopLevelWindows. |
| 21 void EnumerateAllChildWindows(ui::EnumerateWindowsDelegate* delegate, |
| 22 XID window) { |
| 23 std::vector<XID> windows; |
| 24 |
| 25 if (!ui::GetXWindowStack(window, &windows)) { |
| 26 // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back |
| 27 // to old school enumeration of all X windows. |
| 28 XID root, parent, *children; |
| 29 unsigned int num_children; |
| 30 int status = XQueryTree(ui::GetXDisplay(), window, &root, &parent, |
| 31 &children, &num_children); |
| 32 if (status) { |
| 33 for (long i = static_cast<long>(num_children) - 1; i >= 0; i--) |
| 34 windows.push_back(children[i]); |
| 35 XFree(children); |
| 36 } |
| 37 } |
| 38 |
| 39 std::vector<XID>::iterator iter; |
| 40 for (iter = windows.begin(); iter != windows.end(); iter++) { |
| 41 if (delegate->ShouldStopIterating(*iter)) |
| 42 return; |
| 43 } |
| 44 } |
| 45 |
| 46 // To find the top-most window: |
| 47 // 1) Enumerate all top-level windows from the top to the bottom. |
| 48 // 2) For each window: |
| 49 // 2.1) If it is hidden, continue the iteration. |
| 50 // 2.2) If it is managed by the Window Manager (has a WM_STATE property). |
| 51 // Return this window as the top-most window. |
| 52 // 2.3) Enumerate all its child windows. If there is a child window that is |
| 53 // managed by the Window Manager (has a WM_STATE property). Return this |
| 54 // child window as the top-most window. |
| 55 // 2.4) Otherwise, continue the iteration. |
| 56 |
| 57 class WindowManagerWindowFinder : public ui::EnumerateWindowsDelegate { |
| 58 public: |
| 59 WindowManagerWindowFinder() : window_(None) { } |
| 60 |
| 61 XID window() const { return window_; } |
| 62 |
| 63 protected: |
| 64 virtual bool ShouldStopIterating(XID window) { |
| 65 if (ui::PropertyExists(window, "WM_STATE")) { |
| 66 window_ = window; |
| 67 return true; |
| 68 } |
| 69 return false; |
| 70 } |
| 71 |
| 72 private: |
| 73 XID window_; |
| 74 |
| 75 DISALLOW_COPY_AND_ASSIGN(WindowManagerWindowFinder); |
| 76 }; |
| 77 |
| 78 class TopMostWindowFinder : public ui::EnumerateWindowsDelegate { |
| 79 public: |
| 80 TopMostWindowFinder() |
| 81 : top_most_window_(None) {} |
| 82 |
| 83 XID top_most_window() const { return top_most_window_; } |
| 84 |
| 85 protected: |
| 86 virtual bool ShouldStopIterating(XID window) { |
| 87 if (!ui::IsWindowVisible(window)) |
| 88 return false; |
| 89 if (ui::PropertyExists(window, "WM_STATE")) { |
| 90 top_most_window_ = window; |
| 91 return true; |
| 92 } |
| 93 WindowManagerWindowFinder child_finder; |
| 94 EnumerateAllChildWindows(&child_finder, window); |
| 95 XID child_window = child_finder.window(); |
| 96 if (child_window == None) |
| 97 return false; |
| 98 top_most_window_ = child_window; |
| 99 return true; |
| 100 } |
| 101 |
| 102 private: |
| 103 XID top_most_window_; |
| 104 |
| 105 DISALLOW_COPY_AND_ASSIGN(TopMostWindowFinder); |
| 106 }; |
| 107 |
| 108 bool IsTopMostWindowFullScreen() { |
| 109 // Find the topmost window. |
| 110 TopMostWindowFinder finder; |
| 111 EnumerateAllChildWindows(&finder, ui::GetX11RootWindow()); |
| 112 XID window = finder.top_most_window(); |
| 113 if (window == None) |
| 114 return false; |
| 115 |
| 116 // Make sure it is not the desktop window. |
| 117 static Atom desktop_atom = gdk_x11_get_xatom_by_name_for_display( |
| 118 gdk_display_get_default(), "_NET_WM_WINDOW_TYPE_DESKTOP"); |
| 119 |
| 120 std::vector<Atom> atom_properties; |
| 121 if (ui::GetAtomArrayProperty(window, |
| 122 "_NET_WM_WINDOW_TYPE", |
| 123 &atom_properties) && |
| 124 std::find(atom_properties.begin(), atom_properties.end(), desktop_atom) |
| 125 != atom_properties.end()) |
| 126 return false; |
| 127 |
| 128 // If it is a GDK window, check it using gdk function. |
| 129 GdkWindow* gwindow = gdk_window_lookup(window); |
| 130 if (gwindow && window != GDK_ROOT_WINDOW()) |
| 131 return gdk_window_get_state(gwindow) == GDK_WINDOW_STATE_FULLSCREEN; |
| 132 |
| 133 // Otherwise, do the check via xlib function. |
| 134 return ui::IsX11WindowFullScreen(window); |
| 135 } |
| 136 |
| 137 } |
| 138 |
| 139 bool IsFullScreenMode() { |
| 140 gdk_error_trap_push(); |
| 141 bool result = IsTopMostWindowFullScreen(); |
| 142 bool got_error = gdk_error_trap_pop(); |
| 143 return result && !got_error; |
| 144 } |
OLD | NEW |