Chromium Code Reviews| 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..e41e6e7174c0420d744a592e69250fb8800b6d4b 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,33 @@ 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. |
| +typedef struct { |
| + unsigned long flags; |
|
Daniel Erat
2012/05/09 20:58:27
nit: indent 2 spaces instead of 4
|
| + unsigned long functions; |
| + unsigned long decorations; |
| + long input_mode; |
| + unsigned long status; |
|
Daniel Erat
2012/05/09 20:58:27
Holy 64-bit-unsafety! Still, it looks like this i
|
| +} 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 +313,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 +536,7 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { |
| break; |
| } |
| } |
| + |
| MouseEvent mouseev(xev); |
| root_window_->DispatchMouseEvent(&mouseev); |
| break; |
| @@ -786,6 +817,61 @@ void RootWindowHostLinux::PostNativeEvent( |
| XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); |
| } |
| +void RootWindowHostLinux::SetUseOSWindowBorders(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)); |
|
Daniel Erat
2012/05/09 20:58:27
does this break on 64-bit? should you be dividing
Elliot Glaysher
2012/05/09 22:23:09
This is what GDK does and I'm testing this in a 64
Daniel Erat
2012/05/09 22:38:16
Okay.
|
| +} |
| + |
| +bool RootWindowHostLinux::DispatchWindowDragMovement(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 +888,30 @@ 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. Release it. |
| + XUngrabPointer(xdisplay_, CurrentTime); |
|
Daniel Erat
2012/05/09 20:58:27
this seems strange to me. won't it get released a
Elliot Glaysher
2012/05/09 22:23:09
Yeap, and that's the point. The application needs
Daniel Erat
2012/05/09 22:38:16
Thanks, had forgotten the super-flaky, racy "grab
|
| + |
| + 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); |