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

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: Commnet that we're racing the window manager. 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. This struct doesn't seem 64-bit safe though, but it's what GDK
58 // does.
59 typedef struct {
60 unsigned long flags;
61 unsigned long functions;
62 unsigned long decorations;
63 long input_mode;
64 unsigned long status;
65 } MotifWmHints;
66
67 // The bitflag in |flags| in MotifWmHints that signals that the reader should
68 // pay attention to the value in |decorations|.
69 const unsigned long kHintsDecorations = (1L << 1);
70
42 // The events reported for slave devices can have incorrect information for some 71 // The events reported for slave devices can have incorrect information for some
43 // fields. This utility function is used to check for such inconsistencies. 72 // fields. This utility function is used to check for such inconsistencies.
44 void CheckXEventForConsistency(XEvent* xevent) { 73 void CheckXEventForConsistency(XEvent* xevent) {
45 #if defined(USE_XI2_MT) 74 #if defined(USE_XI2_MT)
46 static bool expect_master_event = false; 75 static bool expect_master_event = false;
47 static XIDeviceEvent slave_event; 76 static XIDeviceEvent slave_event;
48 static gfx::Point slave_location; 77 static gfx::Point slave_location;
49 static int slave_button; 78 static int slave_button;
50 79
51 // Note: If an event comes from a slave pointer device, then it will be 80 // 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; 307 return true;
279 default: 308 default:
280 return false; 309 return false;
281 } 310 }
282 } 311 }
283 312
284 // A list of atoms that we'll intern on host creation to save roundtrips to the 313 // 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 314 // X11 server. Must be kept in sync with RootWindowHostLinux::AtomList
286 const char* kAtomList[] = { 315 const char* kAtomList[] = {
287 "WM_DELETE_WINDOW", 316 "WM_DELETE_WINDOW",
317 "_NET_WM_MOVERESIZE",
288 "_NET_WM_PING", 318 "_NET_WM_PING",
289 "_NET_WM_PID", 319 "_NET_WM_PID",
290 "WM_S0" 320 "WM_S0",
321 "_MOTIF_WM_HINTS"
291 }; 322 };
292 323
293 } // namespace 324 } // namespace
294 325
295 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) 326 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds)
296 : root_window_(NULL), 327 : root_window_(NULL),
297 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), 328 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
298 xwindow_(0), 329 xwindow_(0),
299 x_root_window_(DefaultRootWindow(xdisplay_)), 330 x_root_window_(DefaultRootWindow(xdisplay_)),
300 current_cursor_(ui::kCursorNull), 331 current_cursor_(ui::kCursorNull),
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled(); 530 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
500 gesture_client->OnUserGesture( 531 gesture_client->OnUserGesture(
501 (button == kBackMouseButton && !reverse_direction) || 532 (button == kBackMouseButton && !reverse_direction) ||
502 (button == kForwardMouseButton && reverse_direction) ? 533 (button == kForwardMouseButton && reverse_direction) ?
503 client::UserGestureClient::GESTURE_BACK : 534 client::UserGestureClient::GESTURE_BACK :
504 client::UserGestureClient::GESTURE_FORWARD); 535 client::UserGestureClient::GESTURE_FORWARD);
505 } 536 }
506 break; 537 break;
507 } 538 }
508 } 539 }
540
509 MouseEvent mouseev(xev); 541 MouseEvent mouseev(xev);
510 root_window_->DispatchMouseEvent(&mouseev); 542 root_window_->DispatchMouseEvent(&mouseev);
511 break; 543 break;
512 } 544 }
513 case ui::ET_SCROLL_FLING_START: 545 case ui::ET_SCROLL_FLING_START:
514 case ui::ET_SCROLL_FLING_CANCEL: 546 case ui::ET_SCROLL_FLING_CANCEL:
515 case ui::ET_SCROLL: { 547 case ui::ET_SCROLL: {
516 ScrollEvent scrollev(xev); 548 ScrollEvent scrollev(xev);
517 root_window_->DispatchScrollEvent(&scrollev); 549 root_window_->DispatchScrollEvent(&scrollev);
518 break; 550 break;
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 root_window_->ConvertPointToNativeScreen(&point); 811 root_window_->ConvertPointToNativeScreen(&point);
780 xevent.xmotion.x_root = point.x(); 812 xevent.xmotion.x_root = point.x();
781 xevent.xmotion.y_root = point.y(); 813 xevent.xmotion.y_root = point.y();
782 } 814 }
783 default: 815 default:
784 break; 816 break;
785 } 817 }
786 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); 818 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
787 } 819 }
788 820
821 void RootWindowHostLinux::SetUseHostWindowBorders(bool use_os_border) {
822 MotifWmHints motif_hints;
823 memset(&motif_hints, 0, sizeof(motif_hints));
824 motif_hints.flags = kHintsDecorations;
825 motif_hints.decorations = use_os_border ? 1 : 0;
826 XChangeProperty(xdisplay_,
827 xwindow_,
828 cached_atoms_[ATOM__MOTIF_WM_HINTS],
829 cached_atoms_[ATOM__MOTIF_WM_HINTS],
830 32,
831 PropModeReplace,
832 reinterpret_cast<unsigned char*>(&motif_hints),
833 sizeof(MotifWmHints)/sizeof(long));
834 }
835
836 bool RootWindowHostLinux::DispatchHostWindowDragMovement(int hittest,
837 MouseEvent* event) {
838 int direction = -1;
839 switch (hittest) {
840 case HTBOTTOM:
841 direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOM;
842 break;
843 case HTBOTTOMLEFT:
844 direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
845 break;
846 case HTBOTTOMRIGHT:
847 direction = k_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
848 break;
849 case HTCAPTION:
850 direction = k_NET_WM_MOVERESIZE_MOVE;
851 break;
852 case HTLEFT:
853 direction = k_NET_WM_MOVERESIZE_SIZE_LEFT;
854 break;
855 case HTRIGHT:
856 direction = k_NET_WM_MOVERESIZE_SIZE_RIGHT;
857 break;
858 case HTTOP:
859 direction = k_NET_WM_MOVERESIZE_SIZE_TOP;
860 break;
861 case HTTOPLEFT:
862 direction = k_NET_WM_MOVERESIZE_SIZE_TOPLEFT;
863 break;
864 case HTTOPRIGHT:
865 direction = k_NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
866 break;
867 default:
868 return false;
869 }
870
871 gfx::Point point = event->root_location();
872 SendWMMoveResize(direction, point.x(), point.y());
873 return true;
874 }
875
789 bool RootWindowHostLinux::IsWindowManagerPresent() { 876 bool RootWindowHostLinux::IsWindowManagerPresent() {
790 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 877 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
791 // of WM_Sn selections (where n is a screen number). 878 // of WM_Sn selections (where n is a screen number).
792 return XGetSelectionOwner(xdisplay_, cached_atoms_[ATOM_WM_S0]) != None; 879 return XGetSelectionOwner(xdisplay_, cached_atoms_[ATOM_WM_S0]) != None;
793 } 880 }
794 881
795 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { 882 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
796 ::Cursor xcursor = 883 ::Cursor xcursor =
797 cursor == ui::kCursorNone ? 884 cursor == ui::kCursorNone ?
798 invisible_cursor_ : 885 invisible_cursor_ :
799 cursor == ui::kCursorCustom ? 886 cursor == ui::kCursorCustom ?
800 cursor.platform() : 887 cursor.platform() :
801 ui::GetXCursor(CursorShapeFromNative(cursor)); 888 ui::GetXCursor(CursorShapeFromNative(cursor));
802 XDefineCursor(xdisplay_, xwindow_, xcursor); 889 XDefineCursor(xdisplay_, xwindow_, xcursor);
803 } 890 }
804 891
892 void RootWindowHostLinux::SendWMMoveResize(int direction,
893 int x_root,
894 int y_root) {
895 // We most likely have an implicit grab right here. We need to dump it
896 // because what we're about to do is tell the window manager
897 // that it's now responsible for moving the window around; it immediately
898 // grabs when it receives the event below.
899 XUngrabPointer(xdisplay_, CurrentTime);
900
901 XEvent event;
902 memset(&event, 0, sizeof(event));
903 event.xclient.type = ClientMessage;
904 event.xclient.display = xdisplay_;
905 event.xclient.window = xwindow_;
906 event.xclient.message_type = cached_atoms_[ATOM__NET_WM_MOVERESIZE];
907 event.xclient.format = 32;
908 event.xclient.data.l[0] = x_root;
909 event.xclient.data.l[1] = y_root;
910 event.xclient.data.l[2] = direction;
911 event.xclient.data.l[3] = 0;
912 event.xclient.data.l[4] = 0;
913
914 XSendEvent(xdisplay_, x_root_window_, False,
915 SubstructureRedirectMask | SubstructureNotifyMask,
916 &event);
917 }
918
805 // static 919 // static
806 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { 920 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
807 return new RootWindowHostLinux(bounds); 921 return new RootWindowHostLinux(bounds);
808 } 922 }
809 923
810 // static 924 // static
811 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( 925 RootWindowHost* RootWindowHost::GetForAcceleratedWidget(
812 gfx::AcceleratedWidget accelerated_widget) { 926 gfx::AcceleratedWidget accelerated_widget) {
813 return reinterpret_cast<RootWindowHost*>( 927 return reinterpret_cast<RootWindowHost*>(
814 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); 928 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey));
815 } 929 }
816 930
817 // static 931 // static
818 gfx::Size RootWindowHost::GetNativeScreenSize() { 932 gfx::Size RootWindowHost::GetNativeScreenSize() {
819 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); 933 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
820 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 934 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
821 } 935 }
822 936
823 } // namespace aura 937 } // namespace aura
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698