Commit 0d9377b2 authored by Nick Diego Yamane's avatar Nick Diego Yamane Committed by Commit Bot

x11: Get rid of ATK-related XEvent handling in DWTHX11

XEvent raw events are currently being "leaked" to views' DWTHX11 so that
they can be forwarded to ATK. This CL moves the platform specific part
of that process into platform_window level, which consists of
translating XEvent into AtkkeyEventStruct, and adds a callback into
PlatformWindowDelegateLinux to handle ATK key events, thus making it
more aligned with Ozone design and removing more platform specific code
from views.

Bug: 990756, 965991
Change-Id: I9a3ba12969dcd5582f79f118cc12879d55a56388
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1864783Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Commit-Queue: Nick Yamane <nickdiego@igalia.com>
Cr-Commit-Position: refs/heads/master@{#710118}
parent 61f0c085
......@@ -196,16 +196,6 @@ jumbo_component("accessibility") {
if (use_glib) {
configs += [ "//build/config/linux:glib" ]
}
if (use_x11) {
sources += [ "platform/atk_util_auralinux_x11.cc" ]
configs += [ "//build/config/linux:x11" ]
public_deps += [
"//ui/events/x",
"//ui/gfx/x",
]
}
}
if (use_aura) {
......
......@@ -48,10 +48,6 @@ class AX_EXPORT AtkUtilAuraLinux {
static DiscardAtkKeyEvent HandleAtkKeyEvent(AtkKeyEventStruct* key_event);
#if defined(USE_X11)
static DiscardAtkKeyEvent HandleKeyEvent(XEvent* xevent);
#endif
private:
friend struct base::DefaultSingletonTraits<AtkUtilAuraLinux>;
......
......@@ -1108,9 +1108,11 @@ void XWindow::ProcessEvent(XEvent* xev) {
}
#if !defined(USE_OZONE)
case KeyPress:
case KeyRelease:
OnXWindowRawKeyEvent(xev);
case KeyRelease: {
ui::KeyEvent key_event(xev);
OnXWindowEvent(&key_event);
break;
}
case ButtonPress:
case ButtonRelease: {
ui::EventType event_type = ui::EventTypeFromNative(xev);
......
......@@ -242,7 +242,6 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
virtual void OnXWindowEvent(ui::Event* event) = 0;
virtual void OnXWindowSelectionEvent(XEvent* xev) = 0;
virtual void OnXWindowDragDropEvent(XEvent* xev) = 0;
virtual void OnXWindowRawKeyEvent(XEvent* xev) = 0;
virtual base::Optional<gfx::Size> GetMinimumSizeForXWindow() = 0;
virtual base::Optional<gfx::Size> GetMaximumSizeForXWindow() = 0;
virtual void GetWindowMaskForXWindow(const gfx::Size& size,
......
......@@ -33,4 +33,11 @@ void PlatformWindowDelegateLinux::GetWindowMask(const gfx::Size& size,
NOTIMPLEMENTED_LOG_ONCE();
}
#if BUILDFLAG(USE_ATK)
bool PlatformWindowDelegateLinux::OnAtkKeyEvent(AtkKeyEventStruct* atk_event) {
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
#endif
} // namespace ui
......@@ -5,8 +5,13 @@
#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
#include "ui/base/buildflags.h"
#include "ui/platform_window/platform_window_delegate_base.h"
#if BUILDFLAG(USE_ATK)
using AtkKeyEventStruct = struct _AtkKeyEventStruct;
#endif
class SkPath;
namespace gfx {
......@@ -42,6 +47,10 @@ class PlatformWindowDelegateLinux : public PlatformWindowDelegateBase {
// Returns a mask to be used to clip the window for the given
// size. This is used to create the non-rectangular window shape.
virtual void GetWindowMask(const gfx::Size& size, SkPath* window_mask);
#if BUILDFLAG(USE_ATK)
virtual bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event);
#endif
};
} // namespace ui
......
......@@ -37,4 +37,13 @@ jumbo_component("x11") {
"x11_window_manager.cc",
"x11_window_manager.h",
]
if (use_atk) {
sources += [
"atk_event_conversion.cc",
"atk_event_conversion.h",
]
configs += [ "//build/config/linux/atk" ]
deps += [ "//ui/events/x" ]
}
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <atk/atk.h>
#include "ui/platform_window/x11/atk_event_conversion.h"
#include "ui/accessibility/platform/atk_util_auralinux.h"
#include "ui/events/x/events_x_utils.h"
namespace ui {
// static
DiscardAtkKeyEvent AtkUtilAuraLinux::HandleKeyEvent(XEvent* xevent) {
if (!GetInstance()->ShouldEnableAccessibility())
return DiscardAtkKeyEvent::Retain;
std::unique_ptr<AtkKeyEventStruct> AtkKeyEventFromXEvent(XEvent* xevent) {
DCHECK(xevent);
auto atk_key_event = std::make_unique<AtkKeyEventStruct>();
AtkKeyEventStruct atk_key_event;
if (xevent->type == KeyPress)
atk_key_event.type = ATK_KEY_EVENT_PRESS;
atk_key_event->type = ATK_KEY_EVENT_PRESS;
else if (xevent->type == KeyRelease)
atk_key_event.type = ATK_KEY_EVENT_RELEASE;
atk_key_event->type = ATK_KEY_EVENT_RELEASE;
else
NOTREACHED() << xevent->type;
......@@ -26,35 +23,35 @@ DiscardAtkKeyEvent AtkUtilAuraLinux::HandleKeyEvent(XEvent* xevent) {
KeySym keysym = NoSymbol;
XLookupString(&xkey, nullptr, 0, &keysym, nullptr);
atk_key_event.state = xkey.state;
atk_key_event.keyval = keysym;
atk_key_event.keycode = xkey.keycode;
atk_key_event.timestamp = xkey.time;
atk_key_event->state = xkey.state;
atk_key_event->keyval = keysym;
atk_key_event->keycode = xkey.keycode;
atk_key_event->timestamp = xkey.time;
// This string property matches the one that was removed from GdkEventKey. In
// the future, ATK clients should no longer rely on it, so we set it to null.
atk_key_event.string = nullptr;
atk_key_event.length = 0;
atk_key_event->string = nullptr;
atk_key_event->length = 0;
int flags = ui::EventFlagsFromXEvent(*xevent);
if (flags & ui::EF_SHIFT_DOWN)
atk_key_event.state |= AtkKeyModifierMask::kAtkShiftMask;
atk_key_event->state |= AtkKeyModifierMask::kAtkShiftMask;
if (flags & ui::EF_CAPS_LOCK_ON)
atk_key_event.state |= AtkKeyModifierMask::kAtkLockMask;
atk_key_event->state |= AtkKeyModifierMask::kAtkLockMask;
if (flags & ui::EF_CONTROL_DOWN)
atk_key_event.state |= AtkKeyModifierMask::kAtkControlMask;
atk_key_event->state |= AtkKeyModifierMask::kAtkControlMask;
if (flags & ui::EF_ALT_DOWN)
atk_key_event.state |= AtkKeyModifierMask::kAtkMod1Mask;
atk_key_event->state |= AtkKeyModifierMask::kAtkMod1Mask;
if (flags & ui::EF_NUM_LOCK_ON)
atk_key_event.state |= AtkKeyModifierMask::kAtkMod2Mask;
atk_key_event->state |= AtkKeyModifierMask::kAtkMod2Mask;
if (flags & ui::EF_MOD3_DOWN)
atk_key_event.state |= AtkKeyModifierMask::kAtkMod3Mask;
atk_key_event->state |= AtkKeyModifierMask::kAtkMod3Mask;
if (flags & ui::EF_COMMAND_DOWN)
atk_key_event.state |= AtkKeyModifierMask::kAtkMod4Mask;
atk_key_event->state |= AtkKeyModifierMask::kAtkMod4Mask;
if (flags & ui::EF_ALTGR_DOWN)
atk_key_event.state |= AtkKeyModifierMask::KAtkMod5Mask;
atk_key_event->state |= AtkKeyModifierMask::KAtkMod5Mask;
return HandleAtkKeyEvent(&atk_key_event);
return atk_key_event;
}
} // namespace ui
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_PLATFORM_WINDOW_X11_ATK_EVENT_CONVERSION_H_
#define UI_PLATFORM_WINDOW_X11_ATK_EVENT_CONVERSION_H_
#include <atk/atk.h>
#include <memory>
#include "ui/gfx/x/x11.h"
namespace ui {
// These values are duplicates of the GDK values that can be found in
// <gdk/gdktypes.h>. ATK expects the GDK values, but we don't want to depend on
// GDK here.
typedef enum {
kAtkShiftMask = 1 << 0,
kAtkLockMask = 1 << 1,
kAtkControlMask = 1 << 2,
kAtkMod1Mask = 1 << 3,
kAtkMod2Mask = 1 << 4,
kAtkMod3Mask = 1 << 5,
kAtkMod4Mask = 1 << 6,
KAtkMod5Mask = 1 << 7,
} AtkKeyModifierMask;
std::unique_ptr<AtkKeyEventStruct> AtkKeyEventFromXEvent(XEvent* xev);
} // namespace ui
#endif // UI_PLATFORM_WINDOW_X11_ATK_EVENT_CONVERSION_H_
......@@ -5,6 +5,7 @@
#include "ui/platform_window/x11/x11_window.h"
#include "base/trace_event/trace_event.h"
#include "ui/base/buildflags.h"
#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_util_internal.h"
#include "ui/display/screen.h"
......@@ -21,6 +22,10 @@
#include "ui/events/ozone/events_ozone.h"
#endif
#if BUILDFLAG(USE_ATK)
#include "ui/platform_window/x11/atk_event_conversion.h"
#endif
namespace ui {
namespace {
......@@ -205,7 +210,7 @@ void X11Window::ReleaseCapture() {
}
bool X11Window::HasCapture() const {
return X11WindowManager::GetInstance()->event_grabber() == this;
return X11WindowManager::GetInstance()->located_events_grabber() == this;
}
void X11Window::ToggleFullscreen() {
......@@ -437,6 +442,20 @@ bool X11Window::IsTranslucentWindowOpacitySupported() const {
return ui::XVisualManager::GetInstance()->ArgbVisualAvailable();
}
bool X11Window::HandleAsAtkEvent(XEvent* xev) {
#if !BUILDFLAG(USE_ATK)
// TODO(crbug.com/1014934): Support ATK in Ozone/X11.
NOTREACHED();
return false;
#else
DCHECK(xev);
if (xev->type != KeyPress && xev->type != KeyRelease)
return false;
auto atk_key_event = AtkKeyEventFromXEvent(xev);
return platform_window_delegate_->OnAtkKeyEvent(atk_key_event.get());
#endif
}
bool X11Window::CanDispatchEvent(const PlatformEvent& xev) {
#if defined(USE_X11)
return XWindow::IsTargetedBy(*xev);
......@@ -452,7 +471,8 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
TRACE_EVENT1("views", "X11PlatformWindow::Dispatch", "event->type",
event->type);
ProcessEvent(event);
if (!HandleAsAtkEvent(event))
ProcessEvent(event);
return POST_DISPATCH_STOP_PROPAGATION;
#else
OnXWindowEvent(event);
......@@ -521,38 +541,39 @@ void X11Window::OnXWindowLostPointerGrab() {
void X11Window::OnXWindowEvent(ui::Event* event) {
DCHECK_NE(window(), x11::None);
DCHECK(event);
auto* window_manager = X11WindowManager::GetInstance();
DCHECK(window_manager);
// If another X11PlatformWindow has capture == set self as the event grabber,
// the |event| must be rerouted to that grabber. Otherwise, just send the
// event.
auto* event_grabber = window_manager->event_grabber();
if (!event_grabber || event_grabber == this) {
if (event->IsMouseEvent())
window_manager->MouseOnWindow(this);
#if defined(USE_OZONE)
DispatchEventFromNativeUiEvent(
event, base::BindOnce(&PlatformWindowDelegate::DispatchEvent,
base::Unretained(platform_window_delegate())));
#else
platform_window_delegate_->DispatchEvent(event);
#endif
// If |event| is a located event (mouse, touch, etc) and another X11 window
// is set as the current located events grabber, the |event| must be
// re-routed to that grabber. Otherwise, just send the event.
auto* located_events_grabber = window_manager->located_events_grabber();
if (event->IsLocatedEvent() && located_events_grabber &&
located_events_grabber != this) {
if (event->IsMouseEvent() ||
(event->IsTouchEvent() && event->type() == ui::ET_TOUCH_PRESSED)) {
// Another X11Window has installed itself as capture. Translate the
// event's location and dispatch to the other.
ConvertEventLocationToTargetLocation(located_events_grabber->GetBounds(),
GetBounds(),
event->AsLocatedEvent());
}
located_events_grabber->OnXWindowEvent(event);
return;
}
DCHECK(event_grabber);
if (event->IsMouseEvent() ||
(event->IsTouchEvent() && event->type() == ui::ET_TOUCH_PRESSED)) {
// Another X11PlatformWindow has installed itself as capture. Translate the
// event's location and dispatch to the other.
ConvertEventLocationToTargetLocation(event_grabber->GetBounds(),
GetBounds(), event->AsLocatedEvent());
}
if (event->IsMouseEvent())
window_manager->MouseOnWindow(this);
event_grabber->OnXWindowEvent(event);
#if defined(USE_OZONE)
DispatchEventFromNativeUiEvent(
event, base::BindOnce(&PlatformWindowDelegate::DispatchEvent,
base::Unretained(platform_window_delegate())));
#else
platform_window_delegate_->DispatchEvent(event);
#endif
}
void X11Window::OnXWindowSelectionEvent(XEvent* xev) {
......@@ -565,11 +586,6 @@ void X11Window::OnXWindowDragDropEvent(XEvent* xev) {
x_event_delegate_->OnXWindowDragDropEvent(xev);
}
void X11Window::OnXWindowRawKeyEvent(XEvent* xev) {
if (x_event_delegate_)
x_event_delegate_->OnXWindowRawKeyEvent(xev);
}
base::Optional<gfx::Size> X11Window::GetMinimumSizeForXWindow() {
return platform_window_delegate_->GetMinimumSizeForWindow();
}
......
......@@ -27,11 +27,6 @@ class X11_WINDOW_EXPORT XEventDelegate {
// these.
virtual void OnXWindowSelectionEvent(XEvent* xev) = 0;
virtual void OnXWindowDragDropEvent(XEvent* xev) = 0;
// TODO(crbug.com/981606): DesktopWindowTreeHostX11 forward raw |XEvent|s to
// ATK components that currently live in views layer. Remove once ATK code
// is reworked to be reusable.
virtual void OnXWindowRawKeyEvent(XEvent* xev) = 0;
};
// PlatformWindow implementation for X11. PlatformEvents are XEvents.
......@@ -114,7 +109,7 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindowLinux,
void OnXWindowCreated() override;
private:
void ProcessXInput2Event(XEvent* xev);
bool HandleAsAtkEvent(XEvent* xev);
// PlatformEventDispatcher:
bool CanDispatchEvent(const PlatformEvent& event) override;
......@@ -133,7 +128,6 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindowLinux,
void OnXWindowEvent(ui::Event* event) override;
void OnXWindowSelectionEvent(XEvent* xev) override;
void OnXWindowDragDropEvent(XEvent* xev) override;
void OnXWindowRawKeyEvent(XEvent* xev) override;
base::Optional<gfx::Size> GetMinimumSizeForXWindow() override;
base::Optional<gfx::Size> GetMaximumSizeForXWindow() override;
void GetWindowMaskForXWindow(const gfx::Size& size,
......
......@@ -33,20 +33,20 @@ X11WindowManager* X11WindowManager::GetInstance() {
}
void X11WindowManager::GrabEvents(X11Window* window) {
DCHECK_NE(event_grabber_, window);
DCHECK_NE(located_events_grabber_, window);
// Grabbing the mouse is asynchronous. However, we synchronously start
// forwarding all mouse events received by Chrome to the
// aura::WindowEventDispatcher which has capture. This makes capture
// synchronous for all intents and purposes if either:
// - |event_grabber_| is set to have capture.
// - |located_events_grabber_| is set to have capture.
// OR
// - The topmost window underneath the mouse is managed by Chrome.
auto* old_grabber = event_grabber_;
auto* old_grabber = located_events_grabber_;
// Update |event_grabber_| prior to calling OnXWindowLostCapture() to
// Update |located_events_grabber_| prior to calling OnXWindowLostCapture() to
// avoid releasing pointer grab.
event_grabber_ = window;
located_events_grabber_ = window;
if (old_grabber)
old_grabber->OnXWindowLostCapture();
......@@ -54,12 +54,12 @@ void X11WindowManager::GrabEvents(X11Window* window) {
}
void X11WindowManager::UngrabEvents(X11Window* window) {
DCHECK_EQ(event_grabber_, window);
DCHECK_EQ(located_events_grabber_, window);
// Release mouse grab asynchronously. A window managed by Chrome is likely
// the topmost window underneath the mouse so the capture release being
// asynchronous is likely inconsequential.
auto* old_grabber = event_grabber_;
event_grabber_ = nullptr;
auto* old_grabber = located_events_grabber_;
located_events_grabber_ = nullptr;
old_grabber->OnXWindowLostCapture();
}
......
......@@ -23,7 +23,8 @@ class X11_WINDOW_EXPORT X11WindowManager {
static X11WindowManager* GetInstance();
// Sets a given X11Window as the recipient for events and calls
// OnLostCapture for another |event_grabber_| if it has been set previously.
// OnLostCapture for another |located_events_grabber_| if it has been set
// previously.
void GrabEvents(X11Window* window);
// Unsets a given X11Window as the recipient for events and calls
......@@ -31,7 +32,7 @@ class X11_WINDOW_EXPORT X11WindowManager {
void UngrabEvents(X11Window* window);
// Gets the current X11PlatformWindow recipient of mouse events.
X11Window* event_grabber() const { return event_grabber_; }
X11Window* located_events_grabber() const { return located_events_grabber_; }
// Gets the window corresponding to the AcceleratedWidget |widget|.
void AddWindow(X11Window* window);
......@@ -45,7 +46,7 @@ class X11_WINDOW_EXPORT X11WindowManager {
}
private:
X11Window* event_grabber_ = nullptr;
X11Window* located_events_grabber_ = nullptr;
X11Window* window_mouse_currently_on_ = nullptr;
base::flat_map<gfx::AcceleratedWidget, X11Window*> windows_;
......
......@@ -19,6 +19,10 @@
#include "ui/views/widget/desktop_aura/window_event_filter_linux.h"
#include "ui/views/widget/widget.h"
#if BUILDFLAG(USE_ATK)
#include "ui/accessibility/platform/atk_util_auralinux.h"
#endif
DEFINE_UI_CLASS_PROPERTY_TYPE(views::DesktopWindowTreeHostLinux*)
namespace views {
......@@ -301,6 +305,15 @@ void DesktopWindowTreeHostLinux::OnActivationChanged(bool active) {
DesktopWindowTreeHostPlatform::OnActivationChanged(active);
}
#if BUILDFLAG(USE_ATK)
bool DesktopWindowTreeHostLinux::OnAtkKeyEvent(AtkKeyEventStruct* atk_event) {
if (!IsActive() && !HasCapture())
return false;
return ui::AtkUtilAuraLinux::HandleAtkKeyEvent(atk_event) ==
ui::DiscardAtkKeyEvent::Discard;
}
#endif
void DesktopWindowTreeHostLinux::AddAdditionalInitProperties(
const Widget::InitParams& params,
ui::PlatformWindowInitProperties* properties) {
......
......@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "ui/aura/scoped_window_targeter.h"
#include "ui/base/buildflags.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
......@@ -83,6 +84,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
void OnClosed() override;
void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override;
void OnActivationChanged(bool active) override;
#if BUILDFLAG(USE_ATK)
bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event) override;
#endif
private:
FRIEND_TEST_ALL_PREFIXES(DesktopWindowTreeHostLinuxTest, HitTest);
......
......@@ -62,25 +62,8 @@
#include "ui/wm/core/compound_event_filter.h"
#include "ui/wm/core/window_util.h"
#if BUILDFLAG(USE_ATK)
#include "ui/accessibility/platform/atk_util_auralinux.h"
#endif
namespace views {
namespace {
bool ShouldDiscardKeyEvent(XEvent* xev) {
#if BUILDFLAG(USE_ATK)
return ui::AtkUtilAuraLinux::HandleKeyEvent(xev) ==
ui::DiscardAtkKeyEvent::Discard;
#else
return false;
#endif
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostX11, public:
DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
......@@ -201,32 +184,6 @@ void DesktopWindowTreeHostX11::OnXWindowDragDropEvent(XEvent* xev) {
}
}
void DesktopWindowTreeHostX11::OnXWindowRawKeyEvent(XEvent* xev) {
switch (xev->type) {
case KeyPress:
if (!ShouldDiscardKeyEvent(xev)) {
ui::KeyEvent keydown_event(xev);
DesktopWindowTreeHostLinux::DispatchEvent(&keydown_event);
}
break;
case KeyRelease:
// There is no way to deactivate a window in X11 so ignore input if
// window is supposed to be 'inactive'.
if (!IsActive() && !HasCapture())
break;
if (!ShouldDiscardKeyEvent(xev)) {
ui::KeyEvent keyup_event(xev);
DesktopWindowTreeHostLinux::DispatchEvent(&keyup_event);
}
break;
default:
NOTREACHED() << xev->type;
break;
}
}
const ui::XWindow* DesktopWindowTreeHostX11::GetXWindow() const {
DCHECK(platform_window());
// ui::X11Window inherits both PlatformWindow and ui::XWindow.
......
......@@ -73,7 +73,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 : public DesktopWindowTreeHostLinux,
// Overridden from ui::XEventDelegate.
void OnXWindowSelectionEvent(XEvent* xev) override;
void OnXWindowDragDropEvent(XEvent* xev) override;
void OnXWindowRawKeyEvent(XEvent* xev) override;
// Casts PlatformWindow into XWindow and returns the result. This is a temp
// solution to access XWindow, which is subclassed by the X11Window, which is
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment