// 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 <gdk/gdk.h>
#include <gdk/gdkx.h>

#include <algorithm>
#include <vector>

#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<XID> 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<long>(num_children) - 1; i >= 0; i--)
        windows.push_back(children[i]);
      XFree(children);
    }
  }

  std::vector<XID>::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> 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;
}
