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

Unified Diff: ui/aura/root_window_host_linux.cc

Issue 10913253: aura: Make sure the root-window retains the X events it was already listening for. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: tot-merge 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/aura/root_window_host_linux.h ('k') | ui/views/widget/x11_desktop_handler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 6c8a3133fe9d9c2c8a651c44204efc115efa4128..6c988c2823654ed946535cbe3038454484101424 100644
--- a/ui/aura/root_window_host_linux.cc
+++ b/ui/aura/root_window_host_linux.cc
@@ -69,6 +69,13 @@ const char* kAtomsToCache[] = {
NULL
};
+::Window FindEventTarget(const base::NativeEvent& xev) {
+ ::Window target = xev->xany.window;
+ if (xev->type == GenericEvent)
+ target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event;
+ return target;
+}
+
// 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) {
@@ -208,6 +215,18 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) {
}
void SelectEventsForRootWindow() {
+ Display* display = ui::GetXDisplay();
+ ::Window root_window = ui::GetX11RootWindow();
+
+ // Receive resize events for the root-window so |x_root_bounds_| can be
+ // updated.
+ XWindowAttributes attr;
+ XGetWindowAttributes(display, root_window, &attr);
+ if (!(attr.your_event_mask & StructureNotifyMask)) {
+ XSelectInput(display, root_window,
+ StructureNotifyMask | attr.your_event_mask);
+ }
+
XIEventMask evmask;
unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
memset(mask, 0, sizeof(mask));
@@ -230,13 +249,7 @@ void SelectEventsForRootWindow() {
evmask.mask_len = sizeof(mask);
evmask.mask = mask;
- Display* display = ui::GetXDisplay();
- ::Window root_window = ui::GetX11RootWindow();
XISelectEvents(display, root_window, &evmask, 1);
-
- // Receive resize events for the root-window so |x_root_bounds_| can be
- // updated.
- XSelectInput(display, root_window, StructureNotifyMask);
}
// We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only
@@ -422,6 +435,9 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
CheckXEventForConsistency(xev);
+ if (FindEventTarget(event) == x_root_window_)
+ return DispatchEventForRootWindow(event);
+
switch (xev->type) {
case EnterNotify: {
ui::MouseEvent mouseenter_event(xev);
@@ -465,145 +481,43 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
delegate_->OnHostLostCapture();
break;
case ConfigureNotify: {
- if (xev->xconfigure.window == xwindow_) {
- DCHECK_EQ(xwindow_, xev->xconfigure.event);
- // It's possible that the X window may be resized by some other means
- // than from within aura (e.g. the X window manager can change the
- // size). Make sure the root window size is maintained properly.
- gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
- xev->xconfigure.width, xev->xconfigure.height);
- bool size_changed = bounds_.size() != bounds.size();
- bool origin_changed = bounds_.origin() != bounds.origin();
- bounds_ = bounds;
- // Always update barrier and mouse location because |bounds_| might
- // have already been updated in |SetBounds|.
- if (pointer_barriers_.get()) {
- UnConfineCursor();
- RootWindow* root = delegate_->AsRootWindow();
- client::ScreenPositionClient* client =
- client::GetScreenPositionClient(root);
- if (client) {
- gfx::Point p = gfx::Screen::GetCursorScreenPoint();
- client->ConvertPointFromScreen(root, &p);
- if (root->ContainsPoint(p)) {
- root->ConvertPointToNativeScreen(&p);
- XWarpPointer(
- xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y());
- }
+ DCHECK_EQ(xwindow_, xev->xconfigure.event);
+ DCHECK_EQ(xwindow_, xev->xconfigure.window);
+ // It's possible that the X window may be resized by some other means
+ // than from within aura (e.g. the X window manager can change the
+ // size). Make sure the root window size is maintained properly.
+ gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
+ xev->xconfigure.width, xev->xconfigure.height);
+ bool size_changed = bounds_.size() != bounds.size();
+ bool origin_changed = bounds_.origin() != bounds.origin();
+ bounds_ = bounds;
+ // Always update barrier and mouse location because |bounds_| might
+ // have already been updated in |SetBounds|.
+ if (pointer_barriers_.get()) {
+ UnConfineCursor();
+ RootWindow* root = delegate_->AsRootWindow();
+ client::ScreenPositionClient* client =
+ client::GetScreenPositionClient(root);
+ if (client) {
+ gfx::Point p = gfx::Screen::GetCursorScreenPoint();
+ client->ConvertPointFromScreen(root, &p);
+ if (root->ContainsPoint(p)) {
+ root->ConvertPointToNativeScreen(&p);
+ XWarpPointer(
+ xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y());
}
- ConfineCursorToRootWindow();
}
- if (size_changed)
- delegate_->OnHostResized(bounds.size());
- if (origin_changed)
- delegate_->OnHostMoved(bounds_.origin());
- } else {
- DCHECK_EQ(x_root_window_, xev->xconfigure.event);
- DCHECK_EQ(x_root_window_, xev->xconfigure.window);
- x_root_bounds_.SetRect(xev->xconfigure.x, xev->xconfigure.y,
- xev->xconfigure.width, xev->xconfigure.height);
+ ConfineCursorToRootWindow();
}
+ if (size_changed)
+ delegate_->OnHostResized(bounds.size());
+ if (origin_changed)
+ delegate_->OnHostMoved(bounds_.origin());
break;
}
- case GenericEvent: {
- ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
- if (!factory->ShouldProcessXI2Event(xev))
- break;
-
- ui::EventType type = ui::EventTypeFromNative(xev);
- XEvent last_event;
- int num_coalesced = 0;
-
- switch (type) {
- case ui::ET_TOUCH_MOVED:
- num_coalesced = CoalescePendingMotionEvents(xev, &last_event);
- if (num_coalesced > 0)
- xev = &last_event;
- // fallthrough
- case ui::ET_TOUCH_PRESSED:
- case ui::ET_TOUCH_RELEASED: {
- ui::TouchEvent touchev(xev);
-#if defined(OS_CHROMEOS)
- // X maps the touch-surface to the size of the X root-window. In
- // multi-monitor setup, the X root-window size is a combination of
- // both the monitor sizes. So it is necessary to remap the location of
- // the event from the X root-window to the X host-window for the aura
- // root-window.
- if (base::chromeos::IsRunningOnChromeOS()) {
- touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size());
- if (!bounds_.Contains(touchev.location())) {
- // This might still be in the bezel region.
- gfx::Rect expanded(bounds_);
- expanded.Inset(-kXRootWindowPaddingLeft,
- -kXRootWindowPaddingTop,
- -kXRootWindowPaddingRight,
- -kXRootWindowPaddingBottom);
- if (!expanded.Contains(touchev.location()))
- break;
- }
- }
-#endif // defined(OS_CHROMEOS)
- delegate_->OnHostTouchEvent(&touchev);
- break;
- }
- case ui::ET_MOUSE_MOVED:
- case ui::ET_MOUSE_DRAGGED:
- case ui::ET_MOUSE_PRESSED:
- case ui::ET_MOUSE_RELEASED:
- case ui::ET_MOUSE_ENTERED:
- case ui::ET_MOUSE_EXITED: {
- if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
- // If this is a motion event, we want to coalesce all pending motion
- // events that are at the top of the queue.
- num_coalesced = CoalescePendingMotionEvents(xev, &last_event);
- if (num_coalesced > 0)
- xev = &last_event;
- } else if (type == ui::ET_MOUSE_PRESSED) {
- XIDeviceEvent* xievent =
- static_cast<XIDeviceEvent*>(xev->xcookie.data);
- int button = xievent->detail;
- if (button == kBackMouseButton || button == kForwardMouseButton) {
- client::UserActionClient* gesture_client =
- client::GetUserActionClient(delegate_->AsRootWindow());
- if (gesture_client) {
- bool reverse_direction =
- ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
- gesture_client->OnUserAction(
- (button == kBackMouseButton && !reverse_direction) ||
- (button == kForwardMouseButton && reverse_direction) ?
- client::UserActionClient::BACK :
- client::UserActionClient::FORWARD);
- }
- break;
- }
- }
- ui::MouseEvent mouseev(xev);
- delegate_->OnHostMouseEvent(&mouseev);
- break;
- }
- case ui::ET_MOUSEWHEEL: {
- ui::MouseWheelEvent mouseev(xev);
- delegate_->OnHostMouseEvent(&mouseev);
- break;
- }
- case ui::ET_SCROLL_FLING_START:
- case ui::ET_SCROLL_FLING_CANCEL:
- case ui::ET_SCROLL: {
- ui::ScrollEvent scrollev(xev);
- delegate_->OnHostScrollEvent(&scrollev);
- break;
- }
- case ui::ET_UNKNOWN:
- break;
- default:
- NOTREACHED();
- }
-
- // If we coalesced an event we need to free its cookie.
- if (num_coalesced > 0)
- XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
+ case GenericEvent:
+ DispatchXI2Event(event);
break;
- }
case MapNotify: {
// If there's no window manager running, we need to assign the X input
// focus to our host window.
@@ -670,6 +584,123 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
return true;
}
+bool RootWindowHostLinux::DispatchEventForRootWindow(
+ const base::NativeEvent& event) {
+ switch (event->type) {
+ case ConfigureNotify:
+ DCHECK_EQ(x_root_window_, event->xconfigure.event);
+ x_root_bounds_.SetRect(event->xconfigure.x, event->xconfigure.y,
+ event->xconfigure.width, event->xconfigure.height);
+ break;
+
+ case GenericEvent:
+ DispatchXI2Event(event);
+ break;
+ }
+
+ return true;
+}
+
+void RootWindowHostLinux::DispatchXI2Event(const base::NativeEvent& event) {
+ ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
+ XEvent* xev = event;
+ if (!factory->ShouldProcessXI2Event(xev))
+ return;
+
+ ui::EventType type = ui::EventTypeFromNative(xev);
+ XEvent last_event;
+ int num_coalesced = 0;
+
+ switch (type) {
+ case ui::ET_TOUCH_MOVED:
+ num_coalesced = CoalescePendingMotionEvents(xev, &last_event);
+ if (num_coalesced > 0)
+ xev = &last_event;
+ // fallthrough
+ case ui::ET_TOUCH_PRESSED:
+ case ui::ET_TOUCH_RELEASED: {
+ ui::TouchEvent touchev(xev);
+#if defined(OS_CHROMEOS)
+ // X maps the touch-surface to the size of the X root-window. In
+ // multi-monitor setup, the X root-window size is a combination of
+ // both the monitor sizes. So it is necessary to remap the location of
+ // the event from the X root-window to the X host-window for the aura
+ // root-window.
+ if (base::chromeos::IsRunningOnChromeOS()) {
+ touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size());
+ if (!bounds_.Contains(touchev.location())) {
+ // This might still be in the bezel region.
+ gfx::Rect expanded(bounds_);
+ expanded.Inset(-kXRootWindowPaddingLeft,
+ -kXRootWindowPaddingTop,
+ -kXRootWindowPaddingRight,
+ -kXRootWindowPaddingBottom);
+ if (!expanded.Contains(touchev.location()))
+ break;
+ }
+ }
+#endif // defined(OS_CHROMEOS)
+ delegate_->OnHostTouchEvent(&touchev);
+ break;
+ }
+ case ui::ET_MOUSE_MOVED:
+ case ui::ET_MOUSE_DRAGGED:
+ case ui::ET_MOUSE_PRESSED:
+ case ui::ET_MOUSE_RELEASED:
+ case ui::ET_MOUSE_ENTERED:
+ case ui::ET_MOUSE_EXITED: {
+ if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
+ // If this is a motion event, we want to coalesce all pending motion
+ // events that are at the top of the queue.
+ num_coalesced = CoalescePendingMotionEvents(xev, &last_event);
+ if (num_coalesced > 0)
+ xev = &last_event;
+ } else if (type == ui::ET_MOUSE_PRESSED) {
+ XIDeviceEvent* xievent =
+ static_cast<XIDeviceEvent*>(xev->xcookie.data);
+ int button = xievent->detail;
+ if (button == kBackMouseButton || button == kForwardMouseButton) {
+ client::UserActionClient* gesture_client =
+ client::GetUserActionClient(delegate_->AsRootWindow());
+ if (gesture_client) {
+ bool reverse_direction =
+ ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
+ gesture_client->OnUserAction(
+ (button == kBackMouseButton && !reverse_direction) ||
+ (button == kForwardMouseButton && reverse_direction) ?
+ client::UserActionClient::BACK :
+ client::UserActionClient::FORWARD);
+ }
+ break;
+ }
+ }
+ ui::MouseEvent mouseev(xev);
+ delegate_->OnHostMouseEvent(&mouseev);
+ break;
+ }
+ case ui::ET_MOUSEWHEEL: {
+ ui::MouseWheelEvent mouseev(xev);
+ delegate_->OnHostMouseEvent(&mouseev);
+ break;
+ }
+ case ui::ET_SCROLL_FLING_START:
+ case ui::ET_SCROLL_FLING_CANCEL:
+ case ui::ET_SCROLL: {
+ ui::ScrollEvent scrollev(xev);
+ delegate_->OnHostScrollEvent(&scrollev);
+ break;
+ }
+ case ui::ET_UNKNOWN:
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ // If we coalesced an event we need to free its cookie.
+ if (num_coalesced > 0)
+ XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
+}
+
RootWindow* RootWindowHostLinux::GetRootWindow() {
return delegate_->AsRootWindow();
}
« no previous file with comments | « ui/aura/root_window_host_linux.h ('k') | ui/views/widget/x11_desktop_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698