Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / views / widget / desktop_aura / x11_desktop_handler.cc
index 198b9c6..f33d416 100644 (file)
@@ -9,19 +9,18 @@
 
 #include "base/message_loop/message_loop.h"
 #include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/x/x11_menu_list.h"
 #include "ui/base/x/x11_util.h"
-
-#if !defined(OS_CHROMEOS)
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/gfx/x/x11_error_tracker.h"
 #include "ui/views/ime/input_method.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
-#endif
 
 namespace {
 
 const char* kAtomsToCache[] = {
   "_NET_ACTIVE_WINDOW",
-  "_NET_WM_STATE_HIDDEN",
   NULL
 };
 
@@ -46,7 +45,8 @@ X11DesktopHandler::X11DesktopHandler()
       current_window_(None),
       atom_cache_(xdisplay_, kAtomsToCache),
       wm_supports_active_window_(false) {
-  base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this);
+  if (ui::PlatformEventSource::GetInstance())
+    ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
   aura::Env::GetInstance()->AddObserver(this);
 
   XWindowAttributes attr;
@@ -63,7 +63,8 @@ X11DesktopHandler::X11DesktopHandler()
 
 X11DesktopHandler::~X11DesktopHandler() {
   aura::Env::GetInstance()->RemoveObserver(this);
-  base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this);
+  if (ui::PlatformEventSource::GetInstance())
+    ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
 }
 
 void X11DesktopHandler::ActivateWindow(::Window window) {
@@ -97,66 +98,38 @@ void X11DesktopHandler::ActivateWindow(::Window window) {
   }
 }
 
-void X11DesktopHandler::DeactivateWindow(::Window window) {
-  DCHECK(IsActiveWindow(window));
-
-  std::vector< ::Window > windows;
-  if (!ui::GetXWindowStack(x_root_window_, &windows)) {
-    // TODO(mlamouri): use XQueryTree in case of _NET_CLIENT_LIST_STACKING is
-    // not supported by the WM.
-    NOTIMPLEMENTED();
-    return;
-  }
-
-  // To deactivate the window, we want to activate the window below in z-order.
-  ::Window to_activate = GetNextToActivateInStack(windows);
-  // TODO(mlamouri): some WM might not have a "Desktop" to activate when there
-  // are no other windows. In which case, we should handle the case where
-  // |to_activate| == 0.
-  if (!to_activate) {
-    DLOG(WARNING) << "Not deactivating because there are no other window to "
-                  << "activate. If you see this please file a bug and mention "
-                  << "the window manager you are using.";
-    return;
-  }
-
-  ActivateWindow(to_activate);
-}
-
 bool X11DesktopHandler::IsActiveWindow(::Window window) const {
   return window == current_window_;
 }
 
-void X11DesktopHandler::ProcessXEvent(const base::NativeEvent& event) {
+void X11DesktopHandler::ProcessXEvent(XEvent* event) {
   switch (event->type) {
-    case EnterNotify:
-      if (event->xcrossing.focus == True &&
-          current_window_ != event->xcrossing.window)
-        OnActiveWindowChanged(event->xcrossing.window);
-      break;
-    case LeaveNotify:
-      if (event->xcrossing.focus == False &&
-          current_window_ == event->xcrossing.window)
-        OnActiveWindowChanged(None);
-      break;
     case FocusIn:
-      if (event->xfocus.mode == NotifyNormal &&
-          current_window_ != event->xfocus.window)
+      if (current_window_ != event->xfocus.window)
         OnActiveWindowChanged(event->xfocus.window);
       break;
+    case FocusOut:
+      if (current_window_ == event->xfocus.window)
+        OnActiveWindowChanged(None);
+      break;
     default:
       NOTREACHED();
   }
 }
 
-uint32_t X11DesktopHandler::Dispatch(const base::NativeEvent& event) {
-  // Check for a change to the active window.
+bool X11DesktopHandler::CanDispatchEvent(const ui::PlatformEvent& event) {
+  return event->type == CreateNotify || event->type == DestroyNotify ||
+         (event->type == PropertyNotify &&
+          event->xproperty.window == x_root_window_);
+}
+
+uint32_t X11DesktopHandler::DispatchEvent(const ui::PlatformEvent& event) {
   switch (event->type) {
     case PropertyNotify: {
+      // Check for a change to the active window.
+      CHECK_EQ(x_root_window_, event->xproperty.window);
       ::Atom active_window_atom = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW");
-
-      if (event->xproperty.window == x_root_window_ &&
-          event->xproperty.atom == active_window_atom) {
+      if (event->xproperty.atom == active_window_atom) {
         ::Window window;
         if (ui::GetXIDProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) &&
             window) {
@@ -165,9 +138,32 @@ uint32_t X11DesktopHandler::Dispatch(const base::NativeEvent& event) {
       }
       break;
     }
+
+    // Menus created by Chrome can be drag and drop targets. Since they are
+    // direct children of the screen root window and have override_redirect
+    // we cannot use regular _NET_CLIENT_LIST_STACKING property to find them
+    // and use a separate cache to keep track of them.
+    // TODO(varkha): Implement caching of all top level X windows and their
+    // coordinates and stacking order to eliminate repeated calls to X server
+    // during mouse movement, drag and shaping events.
+    case CreateNotify: {
+      // The window might be destroyed if the message pump haven't gotten a
+      // chance to run but we can safely ignore the X error.
+      gfx::X11ErrorTracker error_tracker;
+      XCreateWindowEvent *xcwe = &event->xcreatewindow;
+      ui::XMenuList::GetInstance()->MaybeRegisterMenu(xcwe->window);
+      break;
+    }
+    case DestroyNotify: {
+      XDestroyWindowEvent *xdwe = &event->xdestroywindow;
+      ui::XMenuList::GetInstance()->MaybeUnregisterMenu(xdwe->window);
+      break;
+    }
+    default:
+      NOTREACHED();
   }
 
-  return POST_DISPATCH_NONE;
+  return ui::POST_DISPATCH_NONE;
 }
 
 void X11DesktopHandler::OnWindowInitialized(aura::Window* window) {
@@ -186,54 +182,13 @@ void X11DesktopHandler::OnActiveWindowChanged(::Window xid) {
   if (old_host)
     old_host->HandleNativeWidgetActivationChanged(false);
 
+  // Update the current window ID to effectively change the active widget.
+  current_window_ = xid;
+
   DesktopWindowTreeHostX11* new_host =
       views::DesktopWindowTreeHostX11::GetHostForXID(xid);
   if (new_host)
     new_host->HandleNativeWidgetActivationChanged(true);
-
-  current_window_ = xid;
-}
-
-::Window X11DesktopHandler::GetNextToActivateInStack(
-    const std::vector< ::Window >& windows) {
-  DCHECK(current_window_);
-
-  // We start by doing a fast forward in the stack to find the active window.
-  std::vector< ::Window >::const_iterator it =
-      std::find(windows.begin(), windows.end(), current_window_);
-
-  // We expect to find the currently active window in the |windows| list. Not
-  // finding it is an unexpected behavior.
-  CHECK(it != windows.end());
-
-  // After that, we want to activate the next window that is not minimized.
-  for (++it; it != windows.end(); ++it) {
-    std::vector<Atom> wm_states;
-    if (!ui::GetAtomArrayProperty(*it, "_NET_WM_STATE", &wm_states))
-      continue;
-
-    std::vector<Atom>::const_iterator hidden_atom =
-        std::find(wm_states.begin(),
-                  wm_states.end(),
-                  atom_cache_.GetAtom("_NET_WM_STATE_HIDDEN"));
-
-    if (hidden_atom != wm_states.end())
-      continue;
-
-    // We could do more checks like verifying that _NET_WM_WINDOW_TYPE is a
-    // value we are happy with or that _NET_WM_STATE does not contain
-    // _NET_WM_STATE_SKIP_PAGER or _NET_WM_STATE_SKIP_TASKBAR but those calls
-    // would cost and so far, the tested WM put the special window before the
-    // active one in the stack and the desktop at the end of the stack. That
-    // matches pretty well the behavior we are looking for.
-
-    return *it;
-  }
-
-  // If we reached that point, that means we have not found an appropriate
-  // window to activate. There is nothing we can do about it and the caller
-  // should take care of doing the right thing.
-  return 0;
 }
 
 }  // namespace views