x11_desktop_handler.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright (c) 2012 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 "ui/views/widget/desktop_aura/x11_desktop_handler.h" 6 7#include "base/message_loop/message_loop.h" 8#include "ui/aura/env.h" 9#include "ui/aura/focus_manager.h" 10#include "ui/aura/root_window.h" 11#include "ui/base/x/x11_util.h" 12 13#if !defined(OS_CHROMEOS) 14#include "ui/views/ime/input_method.h" 15#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h" 16#endif 17 18namespace { 19 20const char* kAtomsToCache[] = { 21 "_NET_ACTIVE_WINDOW", 22 NULL 23}; 24 25// Our global instance. Deleted when our Env() is deleted. 26views::X11DesktopHandler* g_handler = NULL; 27 28} // namespace 29 30namespace views { 31 32// static 33X11DesktopHandler* X11DesktopHandler::get() { 34 if (!g_handler) 35 g_handler = new X11DesktopHandler; 36 37 return g_handler; 38} 39 40X11DesktopHandler::X11DesktopHandler() 41 : xdisplay_(ui::GetXDisplay()), 42 x_root_window_(DefaultRootWindow(xdisplay_)), 43 current_window_(None), 44 atom_cache_(xdisplay_, kAtomsToCache) { 45 base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this); 46 aura::Env::GetInstance()->AddObserver(this); 47 48 XWindowAttributes attr; 49 XGetWindowAttributes(xdisplay_, x_root_window_, &attr); 50 XSelectInput(xdisplay_, x_root_window_, 51 attr.your_event_mask | PropertyChangeMask | 52 StructureNotifyMask | SubstructureNotifyMask); 53} 54 55X11DesktopHandler::~X11DesktopHandler() { 56 aura::Env::GetInstance()->RemoveObserver(this); 57 base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this); 58} 59 60void X11DesktopHandler::ActivateWindow(::Window window) { 61 DCHECK_EQ(ui::GetXDisplay(), xdisplay_); 62 63 XEvent xclient; 64 memset(&xclient, 0, sizeof(xclient)); 65 xclient.type = ClientMessage; 66 xclient.xclient.window = window; 67 xclient.xclient.message_type = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW"); 68 xclient.xclient.format = 32; 69 xclient.xclient.data.l[0] = 1; // Specified we are an app. 70 xclient.xclient.data.l[1] = CurrentTime; 71 xclient.xclient.data.l[2] = None; 72 xclient.xclient.data.l[3] = 0; 73 xclient.xclient.data.l[4] = 0; 74 75 XSendEvent(xdisplay_, x_root_window_, False, 76 SubstructureRedirectMask | SubstructureNotifyMask, 77 &xclient); 78} 79 80bool X11DesktopHandler::IsActiveWindow(::Window window) const { 81 return window == current_window_; 82} 83 84bool X11DesktopHandler::Dispatch(const base::NativeEvent& event) { 85 // Check for a change to the active window. 86 switch (event->type) { 87 case PropertyNotify: { 88 ::Atom active_window = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW"); 89 90 if (event->xproperty.window == x_root_window_ && 91 event->xproperty.atom == active_window) { 92 int window; 93 if (ui::GetIntProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) && 94 window) { 95 OnActiveWindowChanged(static_cast< ::Window>(window)); 96 } 97 } 98 break; 99 } 100 } 101 102 return true; 103} 104 105void X11DesktopHandler::OnWindowInitialized(aura::Window* window) { 106} 107 108void X11DesktopHandler::OnWillDestroyEnv() { 109 g_handler = NULL; 110 delete this; 111} 112 113void X11DesktopHandler::OnActiveWindowChanged(::Window xid) { 114 DesktopRootWindowHostX11* old_host = 115 views::DesktopRootWindowHostX11::GetHostForXID(current_window_); 116 if (old_host) 117 old_host->HandleNativeWidgetActivationChanged(false); 118 119 DesktopRootWindowHostX11* new_host = 120 views::DesktopRootWindowHostX11::GetHostForXID(xid); 121 if (new_host) 122 new_host->HandleNativeWidgetActivationChanged(true); 123 124 current_window_ = xid; 125} 126 127} // namespace views 128