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

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

Issue 10905163: aura-x11: Fix touch-calibration for multi-monitor setups. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 3 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/cursorfont.h> 7 #include <X11/cursorfont.h>
8 #include <X11/extensions/Xfixes.h> 8 #include <X11/extensions/Xfixes.h>
9 #include <X11/extensions/XInput2.h> 9 #include <X11/extensions/XInput2.h>
10 #include <X11/extensions/Xrandr.h> 10 #include <X11/extensions/Xrandr.h>
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 namespace aura { 44 namespace aura {
45 45
46 namespace { 46 namespace {
47 47
48 // Standard Linux mouse buttons for going back and forward. 48 // Standard Linux mouse buttons for going back and forward.
49 const int kBackMouseButton = 8; 49 const int kBackMouseButton = 8;
50 const int kForwardMouseButton = 9; 50 const int kForwardMouseButton = 9;
51 51
52 const int kAnimatedCursorFrameDelayMs = 25; 52 const int kAnimatedCursorFrameDelayMs = 25;
53 53
54 const int kXRootWindowPaddingLeft = 40;
Daniel Erat 2012/09/10 17:27:31 nit: add a comment documenting what these are, and
sadrul 2012/09/10 18:19:32 Done (to make sure this gets fixed properly, I hav
55 const int kXRootWindowPaddingRight = 40;
56 const int kXRootWindowPaddingBottom = 30;
57 const int kXRootWindowPaddingTop = 0;
58
54 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; 59 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__";
55 60
56 const char* kAtomsToCache[] = { 61 const char* kAtomsToCache[] = {
57 "WM_DELETE_WINDOW", 62 "WM_DELETE_WINDOW",
58 "_NET_WM_PING", 63 "_NET_WM_PING",
59 "_NET_WM_PID", 64 "_NET_WM_PID",
60 "WM_S0", 65 "WM_S0",
61 NULL 66 NULL
62 }; 67 };
63 68
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 } else { 266 } else {
262 // This isn't an event we want so free its cookie data. 267 // This isn't an event we want so free its cookie data.
263 XFreeEventData(display, &next_event.xcookie); 268 XFreeEventData(display, &next_event.xcookie);
264 } 269 }
265 } 270 }
266 break; 271 break;
267 } 272 }
268 return num_coalesed; 273 return num_coalesed;
269 } 274 }
270 275
276 void SelectEventsForRootWindow() {
277 XIEventMask evmask;
278 unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
279 memset(mask, 0, sizeof(mask));
280
281 XISetMask(mask, XI_HierarchyChanged);
282
283 XISetMask(mask, XI_KeyPress);
284 XISetMask(mask, XI_KeyRelease);
285
286 #if defined(USE_XI2_MT)
287 XISetMask(mask, XI_TouchBegin);
288 XISetMask(mask, XI_TouchUpdate);
289 XISetMask(mask, XI_TouchEnd);
290 #endif
291 XISetMask(mask, XI_ButtonPress);
292 XISetMask(mask, XI_ButtonRelease);
293 XISetMask(mask, XI_Motion);
294
295 evmask.deviceid = XIAllDevices;
296 evmask.mask_len = sizeof(mask);
297 evmask.mask = mask;
298
299 Display* display = ui::GetXDisplay();
300 XISelectEvents(display, ui::GetX11RootWindow(), &evmask, 1);
301 }
302
271 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only 303 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only
272 // generated for certain keys; see 304 // generated for certain keys; see
273 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx. Per 305 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx. Per
274 // discussion on http://crbug.com/108480, char events should furthermore not be 306 // discussion on http://crbug.com/108480, char events should furthermore not be
275 // generated for Tab, Escape, and Backspace. 307 // generated for Tab, Escape, and Backspace.
276 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) { 308 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) {
277 if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) || 309 if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) ||
278 (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) || 310 (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) ||
279 (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) { 311 (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) {
280 return true; 312 return true;
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 xwindow_ = XCreateWindow( 556 xwindow_ = XCreateWindow(
525 xdisplay_, x_root_window_, 557 xdisplay_, x_root_window_,
526 bounds.x(), bounds.y(), bounds.width(), bounds.height(), 558 bounds.x(), bounds.y(), bounds.width(), bounds.height(),
527 0, // border width 559 0, // border width
528 CopyFromParent, // depth 560 CopyFromParent, // depth
529 InputOutput, 561 InputOutput,
530 CopyFromParent, // visual 562 CopyFromParent, // visual
531 CWBackPixmap, 563 CWBackPixmap,
532 &swa); 564 &swa);
533 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); 565 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_);
566 base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this);
567
568 // Get the initial size of the X root window.
569 XWindowAttributes attrs;
570 XGetWindowAttributes(xdisplay_, x_root_window_, &attrs);
Daniel Erat 2012/09/10 17:27:31 i was going to suggest XGetGeometry() instead, but
sadrul 2012/09/10 18:19:32 If XGetGeometry is less expensive than XGetWindowA
571 root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height);
534 572
535 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); 573 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this));
536 574
537 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | 575 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
538 KeyPressMask | KeyReleaseMask | 576 KeyPressMask | KeyReleaseMask |
539 EnterWindowMask | LeaveWindowMask | 577 EnterWindowMask | LeaveWindowMask |
540 ExposureMask | VisibilityChangeMask | 578 ExposureMask | VisibilityChangeMask |
541 StructureNotifyMask | PropertyChangeMask | 579 StructureNotifyMask | PropertyChangeMask |
542 PointerMotionMask; 580 PointerMotionMask;
543 XSelectInput(xdisplay_, xwindow_, event_mask); 581 XSelectInput(xdisplay_, xwindow_, event_mask);
544 XFlush(xdisplay_); 582 XFlush(xdisplay_);
545 583
584 // Receive resize events for the root-window so |root_bounds_| can be updated.
585 XSelectInput(xdisplay_, x_root_window_, StructureNotifyMask);
Daniel Erat 2012/09/10 17:27:31 do this before you query the bounds; otherwise the
sadrul 2012/09/10 18:19:32 Done.
586
546 if (base::MessagePumpForUI::HasXInput2()) 587 if (base::MessagePumpForUI::HasXInput2())
547 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); 588 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
548 589
590 SelectEventsForRootWindow();
591
549 // Initialize invisible cursor. 592 // Initialize invisible cursor.
550 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 593 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
551 XColor black; 594 XColor black;
552 black.red = black.green = black.blue = 0; 595 black.red = black.green = black.blue = 0;
553 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, 596 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_,
554 nodata, 8, 8); 597 nodata, 8, 8);
555 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, 598 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank,
556 &black, &black, 0, 0); 599 &black, &black, 0, 0);
557 XFreePixmap(xdisplay_, blank); 600 XFreePixmap(xdisplay_, blank);
558 601
(...skipping 27 matching lines...) Expand all
586 // window to broadcast. 629 // window to broadcast.
587 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting. 630 // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
588 static int root_window_number = 0; 631 static int root_window_number = 0;
589 std::string name = StringPrintf("aura_root_%d", root_window_number++); 632 std::string name = StringPrintf("aura_root_%d", root_window_number++);
590 XStoreName(xdisplay_, xwindow_, name.c_str()); 633 XStoreName(xdisplay_, xwindow_, name.c_str());
591 XRRSelectInput(xdisplay_, x_root_window_, 634 XRRSelectInput(xdisplay_, x_root_window_,
592 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); 635 RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
593 } 636 }
594 637
595 RootWindowHostLinux::~RootWindowHostLinux() { 638 RootWindowHostLinux::~RootWindowHostLinux() {
639 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this);
596 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); 640 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
597 641
598 UnConfineCursor(); 642 UnConfineCursor();
599 643
600 XDestroyWindow(xdisplay_, xwindow_); 644 XDestroyWindow(xdisplay_, xwindow_);
601 645
602 // Clears XCursorCache. 646 // Clears XCursorCache.
603 ui::GetXCursor(ui::kCursorClearXCursorCache); 647 ui::GetXCursor(ui::kCursorClearXCursorCache);
604 648
605 XFreeCursor(xdisplay_, invisible_cursor_); 649 XFreeCursor(xdisplay_, invisible_cursor_);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 case ButtonRelease: { 685 case ButtonRelease: {
642 ui::MouseEvent mouseev(xev); 686 ui::MouseEvent mouseev(xev);
643 delegate_->OnHostMouseEvent(&mouseev); 687 delegate_->OnHostMouseEvent(&mouseev);
644 break; 688 break;
645 } 689 }
646 case FocusOut: 690 case FocusOut:
647 if (xev->xfocus.mode != NotifyGrab) 691 if (xev->xfocus.mode != NotifyGrab)
648 delegate_->OnHostLostCapture(); 692 delegate_->OnHostLostCapture();
649 break; 693 break;
650 case ConfigureNotify: { 694 case ConfigureNotify: {
651 DCHECK_EQ(xwindow_, xev->xconfigure.window); 695 if (xev->xconfigure.window == xwindow_) {
652 DCHECK_EQ(xwindow_, xev->xconfigure.event); 696 DCHECK_EQ(xwindow_, xev->xconfigure.event);
653 // It's possible that the X window may be resized by some other means than 697 // It's possible that the X window may be resized by some other means
654 // from within aura (e.g. the X window manager can change the size). Make 698 // than from within aura (e.g. the X window manager can change the
655 // sure the root window size is maintained properly. 699 // size). Make sure the root window size is maintained properly.
656 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, 700 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
657 xev->xconfigure.width, xev->xconfigure.height); 701 xev->xconfigure.width, xev->xconfigure.height);
658 bool size_changed = bounds_.size() != bounds.size(); 702 bool size_changed = bounds_.size() != bounds.size();
659 bool origin_changed = bounds_.origin() != bounds.origin(); 703 bool origin_changed = bounds_.origin() != bounds.origin();
660 bounds_ = bounds; 704 bounds_ = bounds;
661 // Update barrier and mouse location when the root window has 705 // Update barrier and mouse location when the root window has
662 // moved/resized. 706 // moved/resized.
663 if (pointer_barriers_.get() && (size_changed || origin_changed)) { 707 if (pointer_barriers_.get() && (size_changed || origin_changed)) {
664 UnConfineCursor(); 708 UnConfineCursor();
665 RootWindow* root = delegate_->AsRootWindow(); 709 RootWindow* root = delegate_->AsRootWindow();
666 client::ScreenPositionClient* client = 710 client::ScreenPositionClient* client =
667 client::GetScreenPositionClient(root); 711 client::GetScreenPositionClient(root);
668 if (client) { 712 if (client) {
669 gfx::Point p = gfx::Screen::GetCursorScreenPoint(); 713 gfx::Point p = gfx::Screen::GetCursorScreenPoint();
670 client->ConvertPointFromScreen(root, &p); 714 client->ConvertPointFromScreen(root, &p);
671 if (root->ContainsPoint(p)) { 715 if (root->ContainsPoint(p)) {
672 root->ConvertPointToNativeScreen(&p); 716 root->ConvertPointToNativeScreen(&p);
673 XWarpPointer( 717 XWarpPointer(
674 xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y()); 718 xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y());
719 }
675 } 720 }
721 ConfineCursorToRootWindow();
676 } 722 }
677 ConfineCursorToRootWindow(); 723 if (size_changed)
724 delegate_->OnHostResized(bounds.size());
725 if (origin_changed)
726 delegate_->OnHostMoved(bounds_.origin());
727 } else {
728 DCHECK_EQ(x_root_window_, xev->xconfigure.event);
729 DCHECK_EQ(x_root_window_, xev->xconfigure.window);
730 root_bounds_.SetRect(xev->xconfigure.x, xev->xconfigure.y,
731 xev->xconfigure.width, xev->xconfigure.height);
678 } 732 }
679 if (size_changed)
680 delegate_->OnHostResized(bounds.size());
681 if (origin_changed)
682 delegate_->OnHostMoved(bounds_.origin());
683 break; 733 break;
684 } 734 }
685 case GenericEvent: { 735 case GenericEvent: {
686 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 736 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
687 if (!factory->ShouldProcessXI2Event(xev)) 737 if (!factory->ShouldProcessXI2Event(xev))
688 break; 738 break;
689 739
690 ui::EventType type = ui::EventTypeFromNative(xev); 740 ui::EventType type = ui::EventTypeFromNative(xev);
691 XEvent last_event; 741 XEvent last_event;
692 int num_coalesced = 0; 742 int num_coalesced = 0;
693 743
694 switch (type) { 744 switch (type) {
695 case ui::ET_TOUCH_MOVED: 745 case ui::ET_TOUCH_MOVED:
696 num_coalesced = CoalescePendingMotionEvents(xev, &last_event); 746 num_coalesced = CoalescePendingMotionEvents(xev, &last_event);
697 if (num_coalesced > 0) 747 if (num_coalesced > 0)
698 xev = &last_event; 748 xev = &last_event;
699 // fallthrough 749 // fallthrough
700 case ui::ET_TOUCH_PRESSED: 750 case ui::ET_TOUCH_PRESSED:
701 case ui::ET_TOUCH_RELEASED: { 751 case ui::ET_TOUCH_RELEASED: {
702 ui::TouchEvent touchev(xev); 752 ui::TouchEvent touchev(xev);
753 // X maps the touch-surface to the size of the X root-window. In
754 // multi-monitor setup, the X root-window size is a combination of
755 // both the monitor sizes. So it is necessary to remap the location of
756 // the event from the X root-window to the X host-window for the aura
757 // root-window.
758 touchev.CalibrateLocation(root_bounds_.size(), bounds_.size());
759 if (!bounds_.Contains(touchev.location())) {
760 // This might still be in the bezel region.
761 gfx::Rect expanded(bounds_);
762 expanded.Inset(-kXRootWindowPaddingLeft,
763 -kXRootWindowPaddingTop,
764 -kXRootWindowPaddingRight,
765 -kXRootWindowPaddingBottom);
766 if (!expanded.Contains(touchev.location()))
767 break;
768 }
703 delegate_->OnHostTouchEvent(&touchev); 769 delegate_->OnHostTouchEvent(&touchev);
704 break; 770 break;
705 } 771 }
706 case ui::ET_MOUSE_MOVED: 772 case ui::ET_MOUSE_MOVED:
707 case ui::ET_MOUSE_DRAGGED: 773 case ui::ET_MOUSE_DRAGGED:
708 case ui::ET_MOUSE_PRESSED: 774 case ui::ET_MOUSE_PRESSED:
709 case ui::ET_MOUSE_RELEASED: 775 case ui::ET_MOUSE_RELEASED:
710 case ui::ET_MOUSE_ENTERED: 776 case ui::ET_MOUSE_ENTERED:
711 case ui::ET_MOUSE_EXITED: { 777 case ui::ET_MOUSE_EXITED: {
712 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { 778 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); 1202 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey));
1137 } 1203 }
1138 1204
1139 // static 1205 // static
1140 gfx::Size RootWindowHost::GetNativeScreenSize() { 1206 gfx::Size RootWindowHost::GetNativeScreenSize() {
1141 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); 1207 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay();
1142 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 1208 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
1143 } 1209 }
1144 1210
1145 } // namespace aura 1211 } // namespace aura
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698