Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: ui/aura/root_window_host_linux.cc

Issue 10381063: Aura/ash split: Don't use X11 window borders. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Now with windows/mac implementations Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/aura/root_window_host_linux.h" 5 #include "ui/aura/root_window_host_linux.h"
6 6
7 #include <X11/Xatom.h> 7 #include <X11/Xatom.h>
8 #include <X11/cursorfont.h> 8 #include <X11/cursorfont.h>
9 #include <X11/extensions/XInput2.h> 9 #include <X11/extensions/XInput2.h>
10 #include <X11/extensions/Xfixes.h> 10 #include <X11/extensions/Xfixes.h>
11 #include <X11/extensions/Xrandr.h> 11 #include <X11/extensions/Xrandr.h>
12 #include <algorithm> 12 #include <algorithm>
13 13
14 #include "base/message_pump_x.h" 14 #include "base/message_pump_x.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
17 #include "ui/aura/client/user_gesture_client.h" 17 #include "ui/aura/client/user_gesture_client.h"
18 #include "ui/aura/dispatcher_linux.h" 18 #include "ui/aura/dispatcher_linux.h"
19 #include "ui/aura/env.h" 19 #include "ui/aura/env.h"
20 #include "ui/aura/event.h" 20 #include "ui/aura/event.h"
21 #include "ui/aura/root_window.h" 21 #include "ui/aura/root_window.h"
22 #include "ui/base/cursor/cursor.h" 22 #include "ui/base/cursor/cursor.h"
23 #include "ui/base/hit_test.h"
23 #include "ui/base/keycodes/keyboard_codes.h" 24 #include "ui/base/keycodes/keyboard_codes.h"
24 #include "ui/base/touch/touch_factory.h" 25 #include "ui/base/touch/touch_factory.h"
25 #include "ui/base/view_prop.h" 26 #include "ui/base/view_prop.h"
26 #include "ui/base/x/x11_util.h" 27 #include "ui/base/x/x11_util.h"
27 #include "ui/compositor/layer.h" 28 #include "ui/compositor/layer.h"
28 29
29 using std::max; 30 using std::max;
30 using std::min; 31 using std::min;
31 32
32 namespace aura { 33 namespace aura {
33 34
34 namespace { 35 namespace {
35 36
36 // Standard Linux mouse buttons for going back and forward. 37 // Standard Linux mouse buttons for going back and forward.
37 const int kBackMouseButton = 8; 38 const int kBackMouseButton = 8;
38 const int kForwardMouseButton = 9; 39 const int kForwardMouseButton = 9;
39 40
40 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; 41 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__";
41 42
43 // These constants are defined in the Extended Window Manager Hints
44 // standard...and aren't in any header that I can find.
45 const int k_NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
46 const int k_NET_WM_MOVERESIZE_SIZE_TOP = 1;
47 const int k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
48 const int k_NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
49 const int k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
50 const int k_NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
51 const int k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
52 const int k_NET_WM_MOVERESIZE_SIZE_LEFT = 7;
53 const int k_NET_WM_MOVERESIZE_MOVE = 8;
54
55 // This data structure represents additional hints that we send to the window
56 // manager and has a direct lineage back to Motif, which defined this de facto
57 // standard.
58 typedef struct {
59 unsigned long flags;
Daniel Erat 2012/05/09 20:58:27 nit: indent 2 spaces instead of 4
60 unsigned long functions;
61 unsigned long decorations;
62 long input_mode;
63 unsigned long status;
Daniel Erat 2012/05/09 20:58:27 Holy 64-bit-unsafety! Still, it looks like this i
64 } MotifWmHints;
65
66 // The bitflag in |flags| in MotifWmHints that signals that the reader should
67 // pay attention to the value in |decorations|.
68 const unsigned long kHintsDecorations = (1L << 1);
69
42 // The events reported for slave devices can have incorrect information for some 70 // The events reported for slave devices can have incorrect information for some
43 // fields. This utility function is used to check for such inconsistencies. 71 // fields. This utility function is used to check for such inconsistencies.
44 void CheckXEventForConsistency(XEvent* xevent) { 72 void CheckXEventForConsistency(XEvent* xevent) {
45 #if defined(USE_XI2_MT) 73 #if defined(USE_XI2_MT)
46 static bool expect_master_event = false; 74 static bool expect_master_event = false;
47 static XIDeviceEvent slave_event; 75 static XIDeviceEvent slave_event;
48 static gfx::Point slave_location; 76 static gfx::Point slave_location;
49 static int slave_button; 77 static int slave_button;
50 78
51 // Note: If an event comes from a slave pointer device, then it will be 79 // Note: If an event comes from a slave pointer device, then it will be
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 return true; 306 return true;
279 default: 307 default:
280 return false; 308 return false;
281 } 309 }
282 } 310 }
283 311
284 // A list of atoms that we'll intern on host creation to save roundtrips to the 312 // A list of atoms that we'll intern on host creation to save roundtrips to the
285 // X11 server. Must be kept in sync with RootWindowHostLinux::AtomList 313 // X11 server. Must be kept in sync with RootWindowHostLinux::AtomList
286 const char* kAtomList[] = { 314 const char* kAtomList[] = {
287 "WM_DELETE_WINDOW", 315 "WM_DELETE_WINDOW",
316 "_NET_WM_MOVERESIZE",
288 "_NET_WM_PING", 317 "_NET_WM_PING",
289 "_NET_WM_PID", 318 "_NET_WM_PID",
290 "WM_S0" 319 "WM_S0",
320 "_MOTIF_WM_HINTS"
291 }; 321 };
292 322
293 } // namespace 323 } // namespace
294 324
295 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) 325 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds)
296 : root_window_(NULL), 326 : root_window_(NULL),
297 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), 327 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
298 xwindow_(0), 328 xwindow_(0),
299 x_root_window_(DefaultRootWindow(xdisplay_)), 329 x_root_window_(DefaultRootWindow(xdisplay_)),
300 current_cursor_(ui::kCursorNull), 330 current_cursor_(ui::kCursorNull),
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled(); 529 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
500 gesture_client->OnUserGesture( 530 gesture_client->OnUserGesture(
501 (button == kBackMouseButton && !reverse_direction) || 531 (button == kBackMouseButton && !reverse_direction) ||
502 (button == kForwardMouseButton && reverse_direction) ? 532 (button == kForwardMouseButton && reverse_direction) ?
503 client::UserGestureClient::GESTURE_BACK : 533 client::UserGestureClient::GESTURE_BACK :
504 client::UserGestureClient::GESTURE_FORWARD); 534 client::UserGestureClient::GESTURE_FORWARD);
505 } 535 }
506 break; 536 break;
507 } 537 }
508 } 538 }
539
509 MouseEvent mouseev(xev); 540 MouseEvent mouseev(xev);
510 root_window_->DispatchMouseEvent(&mouseev); 541 root_window_->DispatchMouseEvent(&mouseev);
511 break; 542 break;
512 } 543 }
513 case ui::ET_SCROLL_FLING_START: 544 case ui::ET_SCROLL_FLING_START:
514 case ui::ET_SCROLL_FLING_CANCEL: 545 case ui::ET_SCROLL_FLING_CANCEL:
515 case ui::ET_SCROLL: { 546 case ui::ET_SCROLL: {
516 ScrollEvent scrollev(xev); 547 ScrollEvent scrollev(xev);
517 root_window_->DispatchScrollEvent(&scrollev); 548 root_window_->DispatchScrollEvent(&scrollev);
518 break; 549 break;
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 root_window_->ConvertPointToNativeScreen(&point); 810 root_window_->ConvertPointToNativeScreen(&point);
780 xevent.xmotion.x_root = point.x(); 811 xevent.xmotion.x_root = point.x();
781 xevent.xmotion.y_root = point.y(); 812 xevent.xmotion.y_root = point.y();
782 } 813 }
783 default: 814 default:
784 break; 815 break;
785 } 816 }
786 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); 817 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
787 } 818 }
788 819
820 void RootWindowHostLinux::SetUseOSWindowBorders(bool use_os_border) {
821 MotifWmHints motif_hints;
822 memset(&motif_hints, 0, sizeof(motif_hints));
823 motif_hints.flags = kHintsDecorations;
824 motif_hints.decorations = use_os_border ? 1 : 0;
825 XChangeProperty(xdisplay_,
826 xwindow_,
827 cached_atoms_[ATOM__MOTIF_WM_HINTS],
828 cached_atoms_[ATOM__MOTIF_WM_HINTS],
829 32,
830 PropModeReplace,
831 reinterpret_cast<unsigned char*>(&motif_hints),
832 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.
833 }
834
835 bool RootWindowHostLinux::DispatchWindowDragMovement(int hittest,
836 MouseEvent* event) {
837 int direction = -1;
838 switch (hittest) {
839 case HTBOTTOM:
840 direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOM;
841 break;
842 case HTBOTTOMLEFT:
843 direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
844 break;
845 case HTBOTTOMRIGHT:
846 direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
847 break;
848 case HTCAPTION:
849 direction = k_NET_WM_MOVERESIZE_MOVE;
850 break;
851 case HTLEFT:
852 direction = k_NET_WM_MOVERESIZE_SIZE_LEFT;
853 break;
854 case HTRIGHT:
855 direction = k_NET_WM_MOVERESIZE_SIZE_RIGHT;
856 break;
857 case HTTOP:
858 direction = k_NET_WM_MOVERESIZE_SIZE_TOP;
859 break;
860 case HTTOPLEFT:
861 direction = k_NET_WM_MOVERESIZE_SIZE_TOPLEFT;
862 break;
863 case HTTOPRIGHT:
864 direction = k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
865 break;
866 default:
867 return false;
868 }
869
870 gfx::Point point = event->root_location();
871 SendWMMoveResize(direction, point.x(), point.y());
872 return true;
873 }
874
789 bool RootWindowHostLinux::IsWindowManagerPresent() { 875 bool RootWindowHostLinux::IsWindowManagerPresent() {
790 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 876 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
791 // of WM_Sn selections (where n is a screen number). 877 // of WM_Sn selections (where n is a screen number).
792 return XGetSelectionOwner(xdisplay_, cached_atoms_[ATOM_WM_S0]) != None; 878 return XGetSelectionOwner(xdisplay_, cached_atoms_[ATOM_WM_S0]) != None;
793 } 879 }
794 880
795 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { 881 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
796 ::Cursor xcursor = 882 ::Cursor xcursor =
797 cursor == ui::kCursorNone ? 883 cursor == ui::kCursorNone ?
798 invisible_cursor_ : 884 invisible_cursor_ :
799 cursor == ui::kCursorCustom ? 885 cursor == ui::kCursorCustom ?
800 cursor.platform() : 886 cursor.platform() :
801 ui::GetXCursor(CursorShapeFromNative(cursor)); 887 ui::GetXCursor(CursorShapeFromNative(cursor));
802 XDefineCursor(xdisplay_, xwindow_, xcursor); 888 XDefineCursor(xdisplay_, xwindow_, xcursor);
803 } 889 }
804 890
891 void RootWindowHostLinux::SendWMMoveResize(int direction,
892 int x_root,
893 int y_root) {
894 // We most likely have an implicit grab right here. Release it.
895 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
896
897 XEvent event;
898 memset(&event, 0, sizeof(event));
899 event.xclient.type = ClientMessage;
900 event.xclient.display = xdisplay_;
901 event.xclient.window = xwindow_;
902 event.xclient.message_type = cached_atoms_[ATOM__NET_WM_MOVERESIZE];
903 event.xclient.format = 32;
904 event.xclient.data.l[0] = x_root;
905 event.xclient.data.l[1] = y_root;
906 event.xclient.data.l[2] = direction;
907 event.xclient.data.l[3] = 0;
908 event.xclient.data.l[4] = 0;
909
910 XSendEvent(xdisplay_, x_root_window_, False,
911 SubstructureRedirectMask | SubstructureNotifyMask,
912 &event);
913 }
914
805 // static 915 // static
806 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { 916 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
807 return new RootWindowHostLinux(bounds); 917 return new RootWindowHostLinux(bounds);
808 } 918 }
809 919
810 // static 920 // static
811 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( 921 RootWindowHost* RootWindowHost::GetForAcceleratedWidget(
812 gfx::AcceleratedWidget accelerated_widget) { 922 gfx::AcceleratedWidget accelerated_widget) {
813 return reinterpret_cast<RootWindowHost*>( 923 return reinterpret_cast<RootWindowHost*>(
814 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); 924 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey));
815 } 925 }
816 926
817 // static 927 // static
818 gfx::Size RootWindowHost::GetNativeScreenSize() { 928 gfx::Size RootWindowHost::GetNativeScreenSize() {
819 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); 929 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
820 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 930 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
821 } 931 }
822 932
823 } // namespace aura 933 } // namespace aura
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698