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)
: delegate_(delegate),
display_(display),
event_timestamp_(CurrentTime),
dummy_initialized_(false),
continue_stream_(true) {
DCHECK(!instance_);
@ -184,13 +183,43 @@ Time X11EventSource::GetCurrentServerTime() {
}
Time X11EventSource::GetTimestamp() {
if (event_timestamp_ != CurrentTime) {
return event_timestamp_;
if (!dispatching_events_.empty()) {
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.";
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
@ -201,12 +230,12 @@ void X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) {
have_cookie = true;
}
event_timestamp_ = ExtractTimeFromXEvent(*xevent);
dispatching_events_.push(xevent);
delegate_->ProcessXEvent(xevent);
PostDispatchEvent(xevent);
event_timestamp_ = CurrentTime;
dispatching_events_.pop();
if (have_cookie)
XFreeEventData(xevent->xgeneric.display, &xevent->xcookie);

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

@ -22,6 +22,7 @@
#include "ui/display/util/display_util.h"
#include "ui/display/util/x11/edid_parser_x11.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/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@ -133,20 +134,18 @@ DesktopScreenX11::~DesktopScreenX11() {
gfx::Point 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;
int root_x, root_y, win_x, win_y;
unsigned int mask;
XQueryPointer(display,
DefaultRootWindow(display),
&root,
&child,
&root_x,
&root_y,
&win_x,
&win_y,
&mask);
XQueryPointer(xdisplay_, x_root_window_, &root, &child, &root_x, &root_y,
&win_x, &win_y, &mask);
return PixelToDIPPoint(gfx::Point(root_x, root_y));
}