1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/events/platform/x11/x11_event_source.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <type_traits>
10 
11 #include "base/auto_reset.h"
12 #include "base/logging.h"
13 #include "base/memory/free_deleter.h"
14 #include "base/memory/ref_counted_memory.h"
15 #include "base/metrics/histogram_macros.h"
16 #include "ui/events/devices/x11/device_data_manager_x11.h"
17 #include "ui/events/devices/x11/touch_factory_x11.h"
18 #include "ui/events/event_utils.h"
19 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
20 #include "ui/events/platform/platform_event_dispatcher.h"
21 #include "ui/events/platform/x11/x11_hotplug_event_handler.h"
22 #include "ui/events/x/events_x_utils.h"
23 #include "ui/events/x/x11_event_translation.h"
24 #include "ui/events/x/x11_window_event_manager.h"
25 #include "ui/gfx/x/connection.h"
26 #include "ui/gfx/x/extension_manager.h"
27 #include "ui/gfx/x/x11_atom_cache.h"
28 #include "ui/gfx/x/xkb.h"
29 #include "ui/gfx/x/xproto.h"
30 
31 #if defined(USE_GLIB)
32 #include "ui/events/platform/x11/x11_event_watcher_glib.h"
33 #else
34 #include "ui/events/platform/x11/x11_event_watcher_fdwatch.h"
35 #endif
36 
37 #if defined(OS_CHROMEOS)
38 #include "ui/events/ozone/chromeos/cursor_controller.h"
39 #endif
40 
41 #if defined(USE_OZONE)
42 #include "ui/base/ui_base_features.h"
43 #endif
44 
45 namespace ui {
46 
47 namespace {
48 
InitializeXkb(x11::Connection * connection)49 void InitializeXkb(x11::Connection* connection) {
50   if (!connection)
51     return;
52 
53   auto& xkb = connection->xkb();
54 
55   // Ask the server not to send KeyRelease event when the user holds down a key.
56   // crbug.com/138092
57   xkb
58       .PerClientFlags({
59           .deviceSpec =
60               static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd),
61           .change = x11::Xkb::PerClientFlag::DetectableAutoRepeat,
62           .value = x11::Xkb::PerClientFlag::DetectableAutoRepeat,
63       })
64       .OnResponse(base::BindOnce([](x11::Xkb::PerClientFlagsResponse response) {
65         if (!response ||
66             !static_cast<bool>(response->supported &
67                                x11::Xkb::PerClientFlag::DetectableAutoRepeat)) {
68           DVLOG(1) << "Could not set XKB auto repeat flag.";
69         }
70       }));
71 
72   constexpr auto kXkbAllMapPartMask = static_cast<x11::Xkb::MapPart>(0xff);
73   xkb.SelectEvents(x11::Xkb::SelectEventsRequest{
74       .deviceSpec = static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd),
75       .affectWhich = x11::Xkb::EventType::NewKeyboardNotify,
76       .selectAll = x11::Xkb::EventType::NewKeyboardNotify,
77       .affectMap = kXkbAllMapPartMask,
78   });
79 }
80 
ExtractTimeFromXEvent(const x11::Event & xev)81 x11::Time ExtractTimeFromXEvent(const x11::Event& xev) {
82   if (auto* key = xev.As<x11::KeyEvent>())
83     return key->time;
84   if (auto* button = xev.As<x11::ButtonEvent>())
85     return button->time;
86   if (auto* motion = xev.As<x11::MotionNotifyEvent>())
87     return motion->time;
88   if (auto* crossing = xev.As<x11::CrossingEvent>())
89     return crossing->time;
90   if (auto* prop = xev.As<x11::PropertyNotifyEvent>())
91     return prop->time;
92   if (auto* sel_clear = xev.As<x11::SelectionClearEvent>())
93     return sel_clear->time;
94   if (auto* sel_req = xev.As<x11::SelectionRequestEvent>())
95     return sel_req->time;
96   if (auto* sel_notify = xev.As<x11::SelectionNotifyEvent>())
97     return sel_notify->time;
98   if (auto* dev_changed = xev.As<x11::Input::DeviceChangedEvent>())
99     return dev_changed->time;
100   if (auto* device = xev.As<x11::Input::DeviceEvent>())
101     return device->time;
102   if (auto* xi_crossing = xev.As<x11::Input::CrossingEvent>())
103     return xi_crossing->time;
104   return x11::Time::CurrentTime;
105 }
106 
UpdateDeviceList()107 void UpdateDeviceList() {
108   auto* connection = x11::Connection::Get();
109   DeviceListCacheX11::GetInstance()->UpdateDeviceList(connection);
110   TouchFactory::GetInstance()->UpdateDeviceList(connection);
111   DeviceDataManagerX11::GetInstance()->UpdateDeviceList(connection);
112 }
113 
114 }  // namespace
115 
116 #if defined(USE_GLIB)
117 using X11EventWatcherImpl = X11EventWatcherGlib;
118 #else
119 using X11EventWatcherImpl = X11EventWatcherFdWatch;
120 #endif
121 
X11EventSource(x11::Connection * connection)122 X11EventSource::X11EventSource(x11::Connection* connection)
123     : watcher_(std::make_unique<X11EventWatcherImpl>(this)),
124       connection_(connection),
125       dispatching_event_(nullptr),
126       dummy_initialized_(false),
127       distribution_(0, 999) {
128   DCHECK(connection_);
129   DeviceDataManagerX11::CreateInstance();
130   InitializeXkb(connection_);
131 
132   watcher_->StartWatching();
133 }
134 
~X11EventSource()135 X11EventSource::~X11EventSource() {
136   if (dummy_initialized_)
137     connection_->DestroyWindow({dummy_window_});
138 }
139 
140 // static
HasInstance()141 bool X11EventSource::HasInstance() {
142   return GetInstance();
143 }
144 
145 // static
GetInstance()146 X11EventSource* X11EventSource::GetInstance() {
147   return static_cast<X11EventSource*>(PlatformEventSource::GetInstance());
148 }
149 
150 ////////////////////////////////////////////////////////////////////////////////
151 // X11EventSource, public
152 
DispatchXEvents()153 void X11EventSource::DispatchXEvents() {
154   continue_stream_ = true;
155   connection_->Dispatch(this);
156 }
157 
GetCurrentServerTime()158 x11::Time X11EventSource::GetCurrentServerTime() {
159   DCHECK(connection_);
160 
161   if (!dummy_initialized_) {
162     // Create a new Window and Atom that will be used for the property change.
163     dummy_window_ = connection_->GenerateId<x11::Window>();
164     connection_->CreateWindow(x11::CreateWindowRequest{
165         .wid = dummy_window_,
166         .parent = connection_->default_root(),
167         .width = 1,
168         .height = 1,
169         .override_redirect = x11::Bool32(true),
170     });
171     dummy_atom_ = gfx::GetAtom("CHROMIUM_TIMESTAMP");
172     dummy_window_events_ = std::make_unique<XScopedEventSelector>(
173         dummy_window_, x11::EventMask::PropertyChange);
174     dummy_initialized_ = true;
175   }
176 
177   // No need to measure Linux.X11.ServerRTT on every call.
178   // base::TimeTicks::Now() itself has non-trivial overhead.
179   bool measure_rtt = distribution_(generator_) == 0;
180 
181   base::TimeTicks start;
182   if (measure_rtt)
183     start = base::TimeTicks::Now();
184 
185   // Make a no-op property change on |dummy_window_|.
186   std::vector<uint8_t> data{0};
187   connection_->ChangeProperty(x11::ChangePropertyRequest{
188       .window = static_cast<x11::Window>(dummy_window_),
189       .property = dummy_atom_,
190       .type = x11::Atom::STRING,
191       .format = CHAR_BIT,
192       .data_len = 1,
193       .data = base::RefCountedBytes::TakeVector(&data),
194   });
195 
196   // Observe the resulting PropertyNotify event to obtain the timestamp.
197   connection_->Sync();
198   if (measure_rtt) {
199     UMA_HISTOGRAM_CUSTOM_COUNTS(
200         "Linux.X11.ServerRTT",
201         (base::TimeTicks::Now() - start).InMicroseconds(), 1,
202         base::TimeDelta::FromMilliseconds(50).InMicroseconds(), 50);
203   }
204   connection_->ReadResponses();
205 
206   auto time = x11::Time::CurrentTime;
207   auto pred = [&](const x11::Event& event) {
208     auto* prop = event.As<x11::PropertyNotifyEvent>();
209     if (prop && prop->window == dummy_window_) {
210       time = prop->time;
211       return true;
212     }
213     return false;
214   };
215 
216   auto& events = connection_->events();
217   auto it = std::find_if(events.begin(), events.end(), pred);
218   if (it != events.end())
219     *it = x11::Event();
220   return time;
221 }
222 
GetTimestamp()223 x11::Time X11EventSource::GetTimestamp() {
224   if (dispatching_event_) {
225     auto timestamp = ExtractTimeFromXEvent(*dispatching_event_);
226     if (timestamp != x11::Time::CurrentTime)
227       return timestamp;
228   }
229   DVLOG(1) << "Making a round trip to get a recent server timestamp.";
230   return GetCurrentServerTime();
231 }
232 
233 base::Optional<gfx::Point>
GetRootCursorLocationFromCurrentEvent() const234 X11EventSource::GetRootCursorLocationFromCurrentEvent() const {
235   if (!dispatching_event_)
236     return base::nullopt;
237 
238   DCHECK(dispatching_event_);
239   x11::Event* event = dispatching_event_;
240 
241   auto* device = event->As<x11::Input::DeviceEvent>();
242   auto* crossing = event->As<x11::Input::CrossingEvent>();
243   auto* touch_factory = ui::TouchFactory::GetInstance();
244 
245   bool is_valid_event = false;
246   if (event->As<x11::ButtonEvent>() || event->As<x11::MotionNotifyEvent>() ||
247       event->As<x11::CrossingEvent>()) {
248     is_valid_event = true;
249   } else if (device &&
250              (device->opcode == x11::Input::DeviceEvent::ButtonPress ||
251               device->opcode == x11::Input::DeviceEvent::ButtonRelease ||
252               device->opcode == x11::Input::DeviceEvent::Motion)) {
253     is_valid_event = touch_factory->ShouldProcessDeviceEvent(*device);
254   } else if (crossing &&
255              (crossing->opcode == x11::Input::CrossingEvent::Enter ||
256               crossing->opcode == x11::Input::CrossingEvent::Leave)) {
257     is_valid_event = touch_factory->ShouldProcessCrossingEvent(*crossing);
258   }
259 
260   if (is_valid_event)
261     return ui::EventSystemLocationFromXEvent(*dispatching_event_);
262   return base::nullopt;
263 }
264 
AddXEventDispatcher(XEventDispatcher * dispatcher)265 void X11EventSource::AddXEventDispatcher(XEventDispatcher* dispatcher) {
266   dispatchers_xevent_.AddObserver(dispatcher);
267   PlatformEventDispatcher* event_dispatcher =
268       dispatcher->GetPlatformEventDispatcher();
269   if (event_dispatcher)
270     AddPlatformEventDispatcher(event_dispatcher);
271 }
272 
RemoveXEventDispatcher(XEventDispatcher * dispatcher)273 void X11EventSource::RemoveXEventDispatcher(XEventDispatcher* dispatcher) {
274   dispatchers_xevent_.RemoveObserver(dispatcher);
275   PlatformEventDispatcher* event_dispatcher =
276       dispatcher->GetPlatformEventDispatcher();
277   if (event_dispatcher)
278     RemovePlatformEventDispatcher(event_dispatcher);
279 }
280 
AddXEventObserver(XEventObserver * observer)281 void X11EventSource::AddXEventObserver(XEventObserver* observer) {
282   CHECK(observer);
283   observers_.AddObserver(observer);
284 }
285 
RemoveXEventObserver(XEventObserver * observer)286 void X11EventSource::RemoveXEventObserver(XEventObserver* observer) {
287   CHECK(observer);
288   observers_.RemoveObserver(observer);
289 }
290 
291 std::unique_ptr<ScopedXEventDispatcher>
OverrideXEventDispatcher(XEventDispatcher * dispatcher)292 X11EventSource::OverrideXEventDispatcher(XEventDispatcher* dispatcher) {
293   CHECK(dispatcher);
294   overridden_dispatcher_restored_ = false;
295   return std::make_unique<ScopedXEventDispatcher>(&overridden_dispatcher_,
296                                                   dispatcher);
297 }
298 
RestoreOverridenXEventDispatcher()299 void X11EventSource::RestoreOverridenXEventDispatcher() {
300   CHECK(overridden_dispatcher_);
301   overridden_dispatcher_restored_ = true;
302 }
303 
DispatchPlatformEvent(const PlatformEvent & event,x11::Event * xevent)304 void X11EventSource::DispatchPlatformEvent(const PlatformEvent& event,
305                                            x11::Event* xevent) {
306   DCHECK(event);
307 
308   // First, tell the XEventDispatchers, which can have PlatformEventDispatcher,
309   // an ui::Event is going to be sent next. It must make a promise to handle
310   // next translated |event| sent by PlatformEventSource based on a XID in
311   // |xevent| tested in CheckCanDispatchNextPlatformEvent(). This is needed
312   // because it is not possible to access |event|'s associated NativeEvent* and
313   // check if it is the event's target window (XID).
314   for (XEventDispatcher& dispatcher : dispatchers_xevent_)
315     dispatcher.CheckCanDispatchNextPlatformEvent(xevent);
316 
317   DispatchEvent(event);
318 
319   // Explicitly reset a promise to handle next translated event.
320   for (XEventDispatcher& dispatcher : dispatchers_xevent_)
321     dispatcher.PlatformEventDispatchFinished();
322 }
323 
DispatchXEventToXEventDispatchers(x11::Event * xevent)324 void X11EventSource::DispatchXEventToXEventDispatchers(x11::Event* xevent) {
325   bool stop_dispatching = false;
326 
327   for (auto& observer : observers_)
328     observer.WillProcessXEvent(xevent);
329 
330   if (overridden_dispatcher_) {
331     stop_dispatching = overridden_dispatcher_->DispatchXEvent(xevent);
332   }
333 
334   if (!stop_dispatching) {
335     for (XEventDispatcher& dispatcher : dispatchers_xevent_) {
336       if (dispatcher.DispatchXEvent(xevent))
337         break;
338     }
339   }
340 
341   for (auto& observer : observers_)
342     observer.DidProcessXEvent(xevent);
343 
344   // If an overridden dispatcher has been destroyed, then the event source
345   // should halt dispatching the current stream of events, and wait until the
346   // next message-loop iteration for dispatching events. This lets any nested
347   // message-loop to unwind correctly and any new dispatchers to receive the
348   // correct sequence of events.
349   if (overridden_dispatcher_restored_)
350     StopCurrentEventStream();
351 
352   overridden_dispatcher_restored_ = false;
353 }
354 
CheckCanDispatchNextPlatformEvent(x11::Event * xev)355 void XEventDispatcher::CheckCanDispatchNextPlatformEvent(x11::Event* xev) {}
356 
PlatformEventDispatchFinished()357 void XEventDispatcher::PlatformEventDispatchFinished() {}
358 
GetPlatformEventDispatcher()359 PlatformEventDispatcher* XEventDispatcher::GetPlatformEventDispatcher() {
360   return nullptr;
361 }
362 
ProcessXEvent(x11::Event * xevent)363 void X11EventSource::ProcessXEvent(x11::Event* xevent) {
364   auto translated_event = ui::BuildEventFromXEvent(*xevent);
365   // Ignore native platform-events only if they correspond to mouse events.
366   // Allow other types of events to still be handled
367   if (ui::PlatformEventSource::ShouldIgnoreNativePlatformEvents() &&
368       translated_event && translated_event->IsMouseEvent()) {
369     return;
370   }
371   if (translated_event && translated_event->type() != ET_UNKNOWN) {
372 #if defined(OS_CHROMEOS)
373     if (translated_event->IsLocatedEvent()) {
374       ui::CursorController::GetInstance()->SetCursorLocation(
375           translated_event->AsLocatedEvent()->location_f());
376     }
377 #endif
378     DispatchPlatformEvent(translated_event.get(), xevent);
379   } else {
380     // Only if we can't translate XEvent into ui::Event, try to dispatch XEvent
381     // directly to XEventDispatchers.
382     DispatchXEventToXEventDispatchers(xevent);
383   }
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 // X11EventSource, protected
388 
PostDispatchEvent(x11::Event * x11_event)389 void X11EventSource::PostDispatchEvent(x11::Event* x11_event) {
390   bool should_update_device_list = false;
391 
392   if (x11_event->As<x11::Input::HierarchyEvent>()) {
393     should_update_device_list = true;
394   } else if (auto* device = x11_event->As<x11::Input::DeviceChangedEvent>()) {
395     if (device->reason == x11::Input::ChangeReason::DeviceChange) {
396       should_update_device_list = true;
397     } else if (device->reason == x11::Input::ChangeReason::SlaveSwitch) {
398       ui::DeviceDataManagerX11::GetInstance()->InvalidateScrollClasses(
399           device->sourceid);
400     }
401   }
402 
403   if (should_update_device_list) {
404     UpdateDeviceList();
405     hotplug_event_handler_->OnHotplugEvent();
406   }
407 
408   auto* crossing = x11_event->As<x11::CrossingEvent>();
409   if (crossing && crossing->opcode == x11::CrossingEvent::EnterNotify &&
410       crossing->detail != x11::NotifyDetail::Inferior &&
411       crossing->mode != x11::NotifyMode::Ungrab) {
412     // Clear stored scroll data
413     ui::DeviceDataManagerX11::GetInstance()->InvalidateScrollClasses(
414         DeviceDataManagerX11::kAllDevices);
415   }
416 
417   auto* mapping = x11_event->As<x11::MappingNotifyEvent>();
418   if (mapping && mapping->request == x11::Mapping::Pointer)
419     DeviceDataManagerX11::GetInstance()->UpdateButtonMap();
420 }
421 
StopCurrentEventStream()422 void X11EventSource::StopCurrentEventStream() {
423   continue_stream_ = false;
424 }
425 
OnDispatcherListChanged()426 void X11EventSource::OnDispatcherListChanged() {
427   watcher_->StartWatching();
428 
429   if (!hotplug_event_handler_) {
430     hotplug_event_handler_ = std::make_unique<X11HotplugEventHandler>();
431     // Force the initial device query to have an update list of active devices.
432     hotplug_event_handler_->OnHotplugEvent();
433   }
434 }
435 
ShouldContinueStream() const436 bool X11EventSource::ShouldContinueStream() const {
437   return continue_stream_;
438 }
439 
DispatchXEvent(x11::Event * event)440 void X11EventSource::DispatchXEvent(x11::Event* event) {
441   // NB: The event should be reset to nullptr when this function
442   // returns, not to its initial value, otherwise nested message loops
443   // will incorrectly think that the current event being dispatched is
444   // an old event.  This means base::AutoReset should not be used.
445   dispatching_event_ = event;
446 
447   ProcessXEvent(event);
448   PostDispatchEvent(event);
449 
450   dispatching_event_ = nullptr;
451 }
452 
453 // ScopedXEventDispatcher implementation
ScopedXEventDispatcher(XEventDispatcher ** scoped_dispatcher,XEventDispatcher * new_dispatcher)454 ScopedXEventDispatcher::ScopedXEventDispatcher(
455     XEventDispatcher** scoped_dispatcher,
456     XEventDispatcher* new_dispatcher)
457     : original_(*scoped_dispatcher),
458       restore_(scoped_dispatcher, new_dispatcher) {}
459 
~ScopedXEventDispatcher()460 ScopedXEventDispatcher::~ScopedXEventDispatcher() {
461   DCHECK(X11EventSource::HasInstance());
462   X11EventSource::GetInstance()->RestoreOverridenXEventDispatcher();
463 }
464 
465 // static
466 #if defined(USE_X11)
CreateDefault()467 std::unique_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() {
468 #if defined(USE_OZONE)
469   if (features::IsUsingOzonePlatform())
470     return nullptr;
471 #endif
472   return std::make_unique<X11EventSource>(x11::Connection::Get());
473 }
474 #endif
475 
476 }  // namespace ui
477