0

X11: Avoid round-tripping to get the cursor position

This is a performance optimization which avoids calling XQueryPointer
when we're dispatching a mouse event.  It's become a convenience to
call GetCursorScreenPoint() all over the place in Chrome, even when an
event which has the cursor position is available.

R=sadrul@chromium.org

Review-Url: https://codereview.chromium.org/2398343002
Cr-Commit-Position: refs/heads/master@{#424645}
This commit is contained in:
thomasanderson
2016-10-11 18:57:59 -07:00
committed by Commit bot
parent 77097e7075
commit 6753a182d5
3 changed files with 56 additions and 17 deletions
ui
events
views
widget

@@ -96,7 +96,6 @@ X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
XDisplay* display) XDisplay* display)
: delegate_(delegate), : delegate_(delegate),
display_(display), display_(display),
event_timestamp_(CurrentTime),
dummy_initialized_(false), dummy_initialized_(false),
continue_stream_(true) { continue_stream_(true) {
DCHECK(!instance_); DCHECK(!instance_);
@@ -184,13 +183,43 @@ Time X11EventSource::GetCurrentServerTime() {
} }
Time X11EventSource::GetTimestamp() { Time X11EventSource::GetTimestamp() {
if (event_timestamp_ != CurrentTime) { if (!dispatching_events_.empty()) {
return event_timestamp_; DCHECK(dispatching_events_.top());
Time timestamp = ExtractTimeFromXEvent(*dispatching_events_.top());
if (timestamp != CurrentTime)
return timestamp;
} }
DVLOG(1) << "Making a round trip to get a recent server timestamp."; DVLOG(1) << "Making a round trip to get a recent server timestamp.";
return GetCurrentServerTime(); return GetCurrentServerTime();
} }
base::Optional<gfx::Point>
X11EventSource::GetRootCursorLocationFromCurrentEvent() const {
if (dispatching_events_.empty())
return base::nullopt;
XEvent* event = dispatching_events_.top();
DCHECK(event);
bool is_valid_event = false;
switch (event->type) {
case ButtonPress:
case ButtonRelease:
case MotionNotify:
case EnterNotify:
case LeaveNotify:
is_valid_event = true;
break;
case GenericEvent:
if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(event))
break;
is_valid_event = true;
}
if (is_valid_event)
return ui::EventSystemLocationFromNative(event);
return base::nullopt;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// X11EventSource, protected // X11EventSource, protected
@@ -201,12 +230,12 @@ void X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) {
have_cookie = true; have_cookie = true;
} }
event_timestamp_ = ExtractTimeFromXEvent(*xevent); dispatching_events_.push(xevent);
delegate_->ProcessXEvent(xevent); delegate_->ProcessXEvent(xevent);
PostDispatchEvent(xevent); PostDispatchEvent(xevent);
event_timestamp_ = CurrentTime; dispatching_events_.pop();
if (have_cookie) if (have_cookie)
XFreeEventData(xevent->xgeneric.display, &xevent->xcookie); XFreeEventData(xevent->xgeneric.display, &xevent->xcookie);

@@ -8,8 +8,10 @@
#include <stdint.h> #include <stdint.h>
#include <memory> #include <memory>
#include <stack>
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
#include "ui/events/events_export.h" #include "ui/events/events_export.h"
#include "ui/gfx/x/x11_types.h" #include "ui/gfx/x/x11_types.h"
@@ -18,6 +20,10 @@ using XEvent = union _XEvent;
using XID = unsigned long; using XID = unsigned long;
using XWindow = unsigned long; using XWindow = unsigned long;
namespace gfx {
class Point;
}
namespace ui { namespace ui {
class X11HotplugEventHandler; class X11HotplugEventHandler;
@@ -77,6 +83,10 @@ class EVENTS_EXPORT X11EventSource {
// current event does not have a timestamp. // current event does not have a timestamp.
Time GetTimestamp(); Time GetTimestamp();
// Returns the root pointer location only if there is an event being
// dispatched that contains that information.
base::Optional<gfx::Point> GetRootCursorLocationFromCurrentEvent() const;
void StopCurrentEventStream(); void StopCurrentEventStream();
void OnDispatcherListChanged(); void OnDispatcherListChanged();
@@ -105,8 +115,9 @@ class EVENTS_EXPORT X11EventSource {
// The connection to the X11 server used to receive the events. // The connection to the X11 server used to receive the events.
XDisplay* display_; XDisplay* display_;
// The timestamp of the event being dispatched. // Events currently being dispatched. The topmost event in this stack
Time event_timestamp_; // corresponds to the deepest-nested message loop.
std::stack<XEvent*> dispatching_events_;
// State necessary for UpdateLastSeenServerTime // State necessary for UpdateLastSeenServerTime
bool dummy_initialized_; bool dummy_initialized_;

@@ -22,6 +22,7 @@
#include "ui/display/util/display_util.h" #include "ui/display/util/display_util.h"
#include "ui/display/util/x11/edid_parser_x11.h" #include "ui/display/util/x11/edid_parser_x11.h"
#include "ui/events/platform/platform_event_source.h" #include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/font_render_params.h" #include "ui/gfx/font_render_params.h"
#include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/size_conversions.h"
@@ -133,20 +134,18 @@ DesktopScreenX11::~DesktopScreenX11() {
gfx::Point DesktopScreenX11::GetCursorScreenPoint() { gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
TRACE_EVENT0("views", "DesktopScreenX11::GetCursorScreenPoint()"); TRACE_EVENT0("views", "DesktopScreenX11::GetCursorScreenPoint()");
XDisplay* display = gfx::GetXDisplay(); if (ui::X11EventSource::HasInstance()) {
auto point = ui::X11EventSource::GetInstance()
->GetRootCursorLocationFromCurrentEvent();
if (point)
return point.value();
}
::Window root, child; ::Window root, child;
int root_x, root_y, win_x, win_y; int root_x, root_y, win_x, win_y;
unsigned int mask; unsigned int mask;
XQueryPointer(display, XQueryPointer(xdisplay_, x_root_window_, &root, &child, &root_x, &root_y,
DefaultRootWindow(display), &win_x, &win_y, &mask);
&root,
&child,
&root_x,
&root_y,
&win_x,
&win_y,
&mask);
return PixelToDIPPoint(gfx::Point(root_x, root_y)); return PixelToDIPPoint(gfx::Point(root_x, root_y));
} }