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); |