| Index: ui/aura/root_window_host_linux.cc
|
| diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc
|
| index 83ca3eec18e85d8fc9c8bcda3f2e97aeb47039b8..2fc1b42706099bf74654ecedc00d287c0aa6e635 100644
|
| --- a/ui/aura/root_window_host_linux.cc
|
| +++ b/ui/aura/root_window_host_linux.cc
|
| @@ -20,6 +20,7 @@
|
| #include "ui/aura/event.h"
|
| #include "ui/aura/root_window.h"
|
| #include "ui/base/cursor/cursor.h"
|
| +#include "ui/base/hit_test.h"
|
| #include "ui/base/keycodes/keyboard_codes.h"
|
| #include "ui/base/touch/touch_factory.h"
|
| #include "ui/base/view_prop.h"
|
| @@ -39,6 +40,34 @@ const int kForwardMouseButton = 9;
|
|
|
| const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__";
|
|
|
| +// These constants are defined in the Extended Window Manager Hints
|
| +// standard...and aren't in any header that I can find.
|
| +const int k_NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
|
| +const int k_NET_WM_MOVERESIZE_SIZE_TOP = 1;
|
| +const int k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
|
| +const int k_NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
|
| +const int k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
|
| +const int k_NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
|
| +const int k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
|
| +const int k_NET_WM_MOVERESIZE_SIZE_LEFT = 7;
|
| +const int k_NET_WM_MOVERESIZE_MOVE = 8;
|
| +
|
| +// This data structure represents additional hints that we send to the window
|
| +// manager and has a direct lineage back to Motif, which defined this de facto
|
| +// standard. This struct doesn't seem 64-bit safe though, but it's what GDK
|
| +// does.
|
| +typedef struct {
|
| + unsigned long flags;
|
| + unsigned long functions;
|
| + unsigned long decorations;
|
| + long input_mode;
|
| + unsigned long status;
|
| +} MotifWmHints;
|
| +
|
| +// The bitflag in |flags| in MotifWmHints that signals that the reader should
|
| +// pay attention to the value in |decorations|.
|
| +const unsigned long kHintsDecorations = (1L << 1);
|
| +
|
| // The events reported for slave devices can have incorrect information for some
|
| // fields. This utility function is used to check for such inconsistencies.
|
| void CheckXEventForConsistency(XEvent* xevent) {
|
| @@ -285,9 +314,11 @@ bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) {
|
| // X11 server. Must be kept in sync with RootWindowHostLinux::AtomList
|
| const char* kAtomList[] = {
|
| "WM_DELETE_WINDOW",
|
| + "_NET_WM_MOVERESIZE",
|
| "_NET_WM_PING",
|
| "_NET_WM_PID",
|
| - "WM_S0"
|
| + "WM_S0",
|
| + "_MOTIF_WM_HINTS"
|
| };
|
|
|
| } // namespace
|
| @@ -506,6 +537,7 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
|
| break;
|
| }
|
| }
|
| +
|
| MouseEvent mouseev(xev);
|
| root_window_->DispatchMouseEvent(&mouseev);
|
| break;
|
| @@ -786,6 +818,61 @@ void RootWindowHostLinux::PostNativeEvent(
|
| XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
|
| }
|
|
|
| +void RootWindowHostLinux::SetUseHostWindowBorders(bool use_os_border) {
|
| + MotifWmHints motif_hints;
|
| + memset(&motif_hints, 0, sizeof(motif_hints));
|
| + motif_hints.flags = kHintsDecorations;
|
| + motif_hints.decorations = use_os_border ? 1 : 0;
|
| + XChangeProperty(xdisplay_,
|
| + xwindow_,
|
| + cached_atoms_[ATOM__MOTIF_WM_HINTS],
|
| + cached_atoms_[ATOM__MOTIF_WM_HINTS],
|
| + 32,
|
| + PropModeReplace,
|
| + reinterpret_cast<unsigned char*>(&motif_hints),
|
| + sizeof(MotifWmHints)/sizeof(long));
|
| +}
|
| +
|
| +bool RootWindowHostLinux::DispatchHostWindowDragMovement(int hittest,
|
| + MouseEvent* event) {
|
| + int direction = -1;
|
| + switch (hittest) {
|
| + case HTBOTTOM:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOM;
|
| + break;
|
| + case HTBOTTOMLEFT:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
|
| + break;
|
| + case HTBOTTOMRIGHT:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
|
| + break;
|
| + case HTCAPTION:
|
| + direction = k_NET_WM_MOVERESIZE_MOVE;
|
| + break;
|
| + case HTLEFT:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_LEFT;
|
| + break;
|
| + case HTRIGHT:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_RIGHT;
|
| + break;
|
| + case HTTOP:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_TOP;
|
| + break;
|
| + case HTTOPLEFT:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_TOPLEFT;
|
| + break;
|
| + case HTTOPRIGHT:
|
| + direction = k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
|
| + break;
|
| + default:
|
| + return false;
|
| + }
|
| +
|
| + gfx::Point point = event->root_location();
|
| + SendWMMoveResize(direction, point.x(), point.y());
|
| + return true;
|
| +}
|
| +
|
| bool RootWindowHostLinux::IsWindowManagerPresent() {
|
| // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
|
| // of WM_Sn selections (where n is a screen number).
|
| @@ -802,6 +889,33 @@ void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
|
| XDefineCursor(xdisplay_, xwindow_, xcursor);
|
| }
|
|
|
| +void RootWindowHostLinux::SendWMMoveResize(int direction,
|
| + int x_root,
|
| + int y_root) {
|
| + // We most likely have an implicit grab right here. We need to dump it
|
| + // because what we're about to do is tell the window manager
|
| + // that it's now responsible for moving the window around; it immediately
|
| + // grabs when it receives the event below.
|
| + XUngrabPointer(xdisplay_, CurrentTime);
|
| +
|
| + XEvent event;
|
| + memset(&event, 0, sizeof(event));
|
| + event.xclient.type = ClientMessage;
|
| + event.xclient.display = xdisplay_;
|
| + event.xclient.window = xwindow_;
|
| + event.xclient.message_type = cached_atoms_[ATOM__NET_WM_MOVERESIZE];
|
| + event.xclient.format = 32;
|
| + event.xclient.data.l[0] = x_root;
|
| + event.xclient.data.l[1] = y_root;
|
| + event.xclient.data.l[2] = direction;
|
| + event.xclient.data.l[3] = 0;
|
| + event.xclient.data.l[4] = 0;
|
| +
|
| + XSendEvent(xdisplay_, x_root_window_, False,
|
| + SubstructureRedirectMask | SubstructureNotifyMask,
|
| + &event);
|
| +}
|
| +
|
| // static
|
| RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
|
| return new RootWindowHostLinux(bounds);
|
|
|