Commit 5c9d092b authored by Nick Diego Yamane's avatar Nick Diego Yamane Committed by Commit Bot

Reland "Get rid of native event (i.e: XEvent) usage in libgtkui"

This is a reland of a798c106

Original change's description:
> Get rid of native event (i.e: XEvent) usage in libgtkui
> 
> Get rid of native event (i.e: XEvent) usage when translating ui::KeyEvent into
> GdkEvent in GtkUi GdkKeyBindingsHandler and InputMethod context implementation.
> Native event usage outside platform code is undesired and blocks changes such
> as Aura/X11 => Ozone/X11 migration (e.g: PlatformEvent migration
> crbug.com/965991).
> 
> It is worth noting that aura IME code has been slightly modified to set root
> window as Event::target() during the PRE_DISPATCH phase (for some reason
> InputMethodContext::DispatchKeyEvent() is called at this phase) so that IME
> context implementation is then able to retrieve the X11 Window id, needed by
> GdkEvent system.
> 
> To be able to retrieve XEvent group field in gtkui code, an Event::Property has
> been added and for now is set only for non-ozone X11. Ozone/X11 will be
> addressed in a follow-up CL.
> 
> Rationale:
> https://docs.google.com/document/d/1Neh2p6f8pew9SPuEAtnJMafozAY7uhAIfhwd43CLETc/edit?usp=sharing
> 
> Bug: 965991, 987939
> Change-Id: I64929d6866c1dfcfddbfe75166a1bad139c2da8d
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1789603
> Commit-Queue: Nick Yamane <nickdiego@igalia.com>
> Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
> Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#695827}

Bug: 965991, 987939
Change-Id: I921805b73cd9c55d1e069026091f0526d242b9cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1805156Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Nick Yamane <nickdiego@igalia.com>
Cr-Commit-Position: refs/heads/master@{#697433}
parent a7c1cc3c
......@@ -23,6 +23,8 @@ jumbo_component("libgtkui") {
"gtk_ui.h",
"gtk_util.cc",
"gtk_util.h",
"input_method_context_impl_gtk.cc",
"input_method_context_impl_gtk.h",
"libgtkui_export.h",
"menu_util.cc",
"menu_util.h",
......@@ -124,8 +126,6 @@ jumbo_component("libgtkui") {
sources += [
"gtk_event_loop_x11.cc",
"gtk_event_loop_x11.h",
"x11_input_method_context_impl_gtk.cc",
"x11_input_method_context_impl_gtk.h",
]
deps += [
......
......@@ -17,11 +17,6 @@
#include "ui/base/ime/text_edit_commands.h"
#include "ui/events/event.h"
#if defined(USE_X11)
#include "ui/base/x/x11_util.h" // nogncheck
#include "ui/gfx/x/x11.h" // nogncheck
#endif
using ui::TextEditCommand;
// TODO(erg): Rewrite the old gtk_key_bindings_handler_unittest.cc and get them
......@@ -41,56 +36,13 @@ GtkWidget* CreateInvisibleWindow() {
#endif
}
#if !defined(USE_X11)
GdkModifierType EventFlagsToGdkModifierType(ui::EventFlags event_flags) {
static const struct {
ui::EventFlags event_flag;
GdkModifierType gdk_modifier;
} mapping[] = {
{ui::EF_SHIFT_DOWN, GDK_SHIFT_MASK},
{ui::EF_CAPS_LOCK_ON, GDK_LOCK_MASK},
{ui::EF_CONTROL_DOWN, GDK_CONTROL_MASK},
{ui::EF_ALT_DOWN, GDK_MOD1_MASK},
{ui::EF_NUM_LOCK_ON, GDK_MOD2_MASK},
{ui::EF_MOD3_DOWN, GDK_MOD3_MASK},
{ui::EF_COMMAND_DOWN, GDK_MOD4_MASK},
{ui::EF_ALTGR_DOWN, GDK_MOD5_MASK},
{ui::EF_LEFT_MOUSE_BUTTON, GDK_BUTTON1_MASK},
{ui::EF_MIDDLE_MOUSE_BUTTON, GDK_BUTTON2_MASK},
{ui::EF_RIGHT_MOUSE_BUTTON, GDK_BUTTON3_MASK},
{ui::EF_BACK_MOUSE_BUTTON, GDK_BUTTON4_MASK},
{ui::EF_FORWARD_MOUSE_BUTTON, GDK_BUTTON5_MASK},
};
GdkModifierType gdk_modifier_type = static_cast<GdkModifierType>(0);
for (const auto& map : mapping) {
if (event_flags & map.event_flag) {
gdk_modifier_type =
static_cast<GdkModifierType>(gdk_modifier_type | map.gdk_modifier);
}
}
return gdk_modifier_type;
}
#endif
} // namespace
namespace libgtkui {
GtkKeyBindingsHandler::GtkKeyBindingsHandler()
: fake_window_(CreateInvisibleWindow()),
handler_(CreateNewHandler()),
has_xkb_(false) {
: fake_window_(CreateInvisibleWindow()), handler_(CreateNewHandler()) {
gtk_container_add(GTK_CONTAINER(fake_window_), handler_);
#if defined(USE_X11)
int opcode, event, error;
int major = XkbMajorVersion;
int minor = XkbMinorVersion;
has_xkb_ = XkbQueryExtension(gfx::GetXDisplay(), &opcode, &event, &error,
&major, &minor);
#else
has_xkb_ = false;
#endif
}
GtkKeyBindingsHandler::~GtkKeyBindingsHandler() {
......@@ -104,19 +56,19 @@ bool GtkKeyBindingsHandler::MatchEvent(
CHECK(event.IsKeyEvent());
const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event);
if (key_event.is_char() || !key_event.native_event())
if (key_event.is_char())
return false;
GdkEventKey gdk_event;
BuildGdkEventKeyFromKeyEvent(key_event, &gdk_event);
GdkEvent* gdk_event = GdkEventFromKeyEvent(key_event);
if (!gdk_event)
return false;
edit_commands_.clear();
// If this key event matches a predefined key binding, corresponding signal
// will be emitted.
gtk_bindings_activate_event(
G_OBJECT(handler_),
&gdk_event);
gtk_bindings_activate_event(G_OBJECT(handler_), &gdk_event->key);
gdk_event_free(gdk_event);
bool matched = !edit_commands_.empty();
if (edit_commands)
......@@ -149,56 +101,6 @@ void GtkKeyBindingsHandler::EditCommandMatched(TextEditCommand command,
edit_commands_.push_back(ui::TextEditCommandAuraLinux(command, value));
}
void GtkKeyBindingsHandler::BuildGdkEventKeyFromKeyEvent(
const ui::KeyEvent& key_event,
GdkEventKey* gdk_event) {
GdkKeymap* keymap = gdk_keymap_get_for_display(gdk_display_get_default());
GdkModifierType consumed, state;
#if defined(USE_X11)
const ui::PlatformEvent& xevent = key_event.native_event();
gdk_event->type =
xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
gdk_event->time = xevent->xkey.time;
gdk_event->state = static_cast<GdkModifierType>(xevent->xkey.state);
gdk_event->hardware_keycode = xevent->xkey.keycode;
if (has_xkb_) {
gdk_event->group = XkbGroupForCoreState(xevent->xkey.state);
} else {
// The overwhelming majority of people will be using X servers that support
// XKB. GDK has a fallback here that does some complicated stuff to detect
// whether a modifier key affects the keybinding, but that should be
// extremely rare.
static bool logged = false;
if (!logged) {
NOTIMPLEMENTED();
logged = true;
}
gdk_event->group = 0;
}
#else
gdk_event->type =
key_event.type() == ui::ET_KEY_PRESSED ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
gdk_event->time =
(key_event.time_stamp() - base::TimeTicks()).InMilliseconds();
gdk_event->state = EventFlagsToGdkModifierType(
static_cast<ui::EventFlags>(key_event.flags()));
gdk_event->hardware_keycode = key_event.key_code();
// TODO(crbug.com/987939): Fix keyboard layout switching in Ozone/X11
gdk_event->group = 0;
#endif
gdk_event->keyval = GDK_KEY_VoidSymbol;
gdk_keymap_translate_keyboard_state(
keymap, gdk_event->hardware_keycode,
static_cast<GdkModifierType>(gdk_event->state), gdk_event->group,
&gdk_event->keyval, nullptr, nullptr, &consumed);
state = static_cast<GdkModifierType>(gdk_event->state & ~consumed);
gdk_keymap_add_virtual_modifiers(keymap, &state);
gdk_event->state |= state;
}
void GtkKeyBindingsHandler::HandlerInit(Handler* self) {
self->owner = nullptr;
}
......
......@@ -15,7 +15,6 @@
namespace ui {
class Event;
class KeyEvent;
}
namespace libgtkui {
......@@ -70,10 +69,6 @@ class GtkKeyBindingsHandler {
void EditCommandMatched(ui::TextEditCommand command,
const std::string& value);
// Builds a fake GdkEventKey from an XEvent.
void BuildGdkEventKeyFromKeyEvent(const ui::KeyEvent& key_event,
GdkEventKey* gdk_event);
// Initializes Handler structure.
static void HandlerInit(Handler* self);
......@@ -142,9 +137,6 @@ class GtkKeyBindingsHandler {
// Buffer to store the match results.
std::vector<ui::TextEditCommandAuraLinux> edit_commands_;
// Whether the current X server has the XKeyboard extension.
bool has_xkb_;
};
} // namespace libgtkui
......
......@@ -28,6 +28,7 @@
#include "chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h"
#include "chrome/browser/ui/libgtkui/gtk_status_icon.h"
#include "chrome/browser/ui/libgtkui/gtk_util.h"
#include "chrome/browser/ui/libgtkui/input_method_context_impl_gtk.h"
#include "chrome/browser/ui/libgtkui/native_theme_gtk.h"
#include "chrome/browser/ui/libgtkui/nav_button_provider_gtk.h"
#include "chrome/browser/ui/libgtkui/print_dialog_gtk.h"
......@@ -73,7 +74,6 @@
#if defined(USE_X11)
#include "chrome/browser/ui/libgtkui/gtk_event_loop_x11.h" // nogncheck
#include "chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.h" // nogncheck
#include "ui/gfx/x/x11.h" // nogncheck
#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
......@@ -333,7 +333,7 @@ GtkUi::GtkUi() {
{ActionSource::kRightClick, Action::kMenu}};
// Force Gtk to use Xwayland if it would have used wayland. libgtkui assumes
// the use of X11 (eg. X11InputMethodContextImplGtk) and will crash under
// the use of X11 (eg. InputMethodContextImplGtk) and will crash under
// other backends.
// TODO(thomasanderson): Change this logic once Wayland support is added.
gdk_set_allowed_backends("x11");
......@@ -655,7 +655,7 @@ std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext(
bool is_simple) const {
#if defined(USE_X11)
return std::unique_ptr<ui::LinuxInputMethodContext>(
new X11InputMethodContextImplGtk(delegate, is_simple));
new InputMethodContextImplGtk(delegate, is_simple));
#else
NOTIMPLEMENTED();
return std::make_unique<ui::FakeInputMethodContext>();
......
......@@ -21,10 +21,11 @@
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "build/branding_buildflags.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/events/event_constants.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/linux_ui/linux_ui.h"
......@@ -33,6 +34,7 @@
#include <gdk/gdkx.h>
#include "ui/events/keycodes/keyboard_code_conversion_x.h" // nogncheck
#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
namespace {
......@@ -72,6 +74,57 @@ void CommonInitFromCommandLine(const base::CommandLine& command_line) {
#endif
}
GdkModifierType GetIbusFlags(const ui::KeyEvent& key_event) {
auto* properties = key_event.properties();
if (!properties)
return static_cast<GdkModifierType>(0);
auto it = properties->find(ui::kPropertyKeyboardIBusFlag);
DCHECK(it == properties->end() || it->second.size() == 1);
uint8_t flags = (it != properties->end()) ? it->second[0] : 0;
return static_cast<GdkModifierType>(flags
<< ui::kPropertyKeyboardIBusFlagOffset);
}
GdkModifierType ExtractGdkEventStateFromKeyEvent(
const ui::KeyEvent& key_event) {
auto event_flags = static_cast<ui::EventFlags>(key_event.flags());
static const struct {
ui::EventFlags event_flag;
GdkModifierType gdk_modifier;
} mapping[] = {
{ui::EF_SHIFT_DOWN, GDK_SHIFT_MASK},
{ui::EF_CAPS_LOCK_ON, GDK_LOCK_MASK},
{ui::EF_CONTROL_DOWN, GDK_CONTROL_MASK},
{ui::EF_ALT_DOWN, GDK_MOD1_MASK},
{ui::EF_NUM_LOCK_ON, GDK_MOD2_MASK},
{ui::EF_MOD3_DOWN, GDK_META_MASK},
{ui::EF_COMMAND_DOWN, GDK_MOD4_MASK},
{ui::EF_ALTGR_DOWN, GDK_MOD5_MASK},
{ui::EF_LEFT_MOUSE_BUTTON, GDK_BUTTON1_MASK},
{ui::EF_MIDDLE_MOUSE_BUTTON, GDK_BUTTON2_MASK},
{ui::EF_RIGHT_MOUSE_BUTTON, GDK_BUTTON3_MASK},
{ui::EF_BACK_MOUSE_BUTTON, GDK_BUTTON4_MASK},
{ui::EF_FORWARD_MOUSE_BUTTON, GDK_BUTTON5_MASK},
};
unsigned int gdk_modifier_type = 0;
for (const auto& map : mapping) {
if (event_flags & map.event_flag) {
gdk_modifier_type = gdk_modifier_type | map.gdk_modifier;
}
}
return static_cast<GdkModifierType>(gdk_modifier_type |
GetIbusFlags(key_event));
}
int GetKeyboardGroup(const ui::KeyEvent& key_event) {
auto* properties = key_event.properties();
if (!properties)
return 0;
auto it = properties->find(ui::kPropertyKeyboardGroup);
DCHECK(it == properties->end() || it->second.size() == 1);
return (it != properties->end()) ? it->second[0] : 0;
}
} // namespace
namespace libgtkui {
......@@ -617,4 +670,51 @@ guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator) {
}
#endif
GdkDisplay* GetGdkDisplay() {
GdkDisplay* display = nullptr;
// TODO(crbug.com/1002674): Remove once GtkIM-based LinuxInputMethodContext
// implementation is moved out of libgtkui.
#if defined(USE_X11)
display = gdk_x11_lookup_xdisplay(gfx::GetXDisplay());
#endif
if (!display) // Fall back to the default display.
display = gdk_display_get_default();
return display;
}
GdkEvent* GdkEventFromKeyEvent(const ui::KeyEvent& key_event) {
GdkEventType event_type =
key_event.type() == ui::ET_KEY_PRESSED ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
int hw_code = ui::KeycodeConverter::DomCodeToNativeKeycode(key_event.code());
auto event_time = key_event.time_stamp() - base::TimeTicks();
int group = GetKeyboardGroup(key_event);
// Get GdkKeymap
GdkKeymap* keymap = gdk_keymap_get_for_display(GetGdkDisplay());
// Get keyval and state
GdkModifierType state = ExtractGdkEventStateFromKeyEvent(key_event);
guint keyval = GDK_KEY_VoidSymbol;
GdkModifierType consumed;
gdk_keymap_translate_keyboard_state(keymap, hw_code, state, group, &keyval,
nullptr, nullptr, &consumed);
gdk_keymap_add_virtual_modifiers(keymap, &state);
DCHECK(keyval != GDK_KEY_VoidSymbol);
// Build GdkEvent
GdkEvent* gdk_event = gdk_event_new(event_type);
gdk_event->type = event_type;
gdk_event->key.time = event_time.InMilliseconds();
gdk_event->key.hardware_keycode = hw_code;
gdk_event->key.keyval = keyval;
gdk_event->key.state = state;
gdk_event->key.group = group;
gdk_event->key.send_event = key_event.flags() & ui::EF_FINAL;
gdk_event->key.is_modifier = state & GDK_MODIFIER_MASK;
gdk_event->key.length = 0;
gdk_event->key.string = nullptr;
return gdk_event;
}
} // namespace libgtkui
......@@ -12,6 +12,8 @@
#include "ui/native_theme/native_theme.h"
#include "ui/views/window/frame_buttons.h"
typedef union _GdkEvent GdkEvent;
namespace aura {
class Window;
}
......@@ -27,6 +29,7 @@ struct HSL;
namespace ui {
class Accelerator;
class KeyEvent;
}
namespace libgtkui {
......@@ -190,6 +193,17 @@ std::string GetGtkSettingsStringProperty(GtkSettings* settings,
// TODO(thomasanderson): Remove this once GtkStatusIcon is removed.
guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator);
#endif
// Get current GdkDisplay instance
GdkDisplay* GetGdkDisplay();
// Translates |key_event| into a GdkEvent. GdkEvent::key::window is the only
// field not set by this function, callers must set it, as the way for
// retrieving it may vary depending on the event being processed. E.g: for IME
// Context impl, X11 window XID is obtained through Event::target() which is
// root aura::Window targeted by that key event.
GdkEvent* GdkEventFromKeyEvent(const ui::KeyEvent& key_event);
} // namespace libgtkui
#endif // CHROME_BROWSER_UI_LIBGTKUI_GTK_UTIL_H_
......@@ -2,34 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LIBGTKUI_X11_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
#define CHROME_BROWSER_UI_LIBGTKUI_X11_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
#include <unordered_set>
#include <vector>
#ifndef CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
#define CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
#include "base/macros.h"
#include "base/strings/string16.h"
#include "ui/base/glib/glib_integers.h"
#include "ui/base/glib/glib_signal.h"
#include "ui/base/ime/linux/linux_input_method_context.h"
#include "ui/events/platform_event.h"
#include "ui/gfx/geometry/rect.h"
typedef union _GdkEvent GdkEvent;
typedef struct _GdkWindow GdkWindow;
typedef struct _GtkIMContext GtkIMContext;
namespace libgtkui {
// An implementation of LinuxInputMethodContext which is based on X11 event loop
// and uses GtkIMContext(gtk-immodule) as a bridge from/to underlying IMEs.
class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext {
// An implementation of LinuxInputMethodContext which uses GtkIMContext
// (gtk-immodule) as a bridge from/to underlying IMEs.
class InputMethodContextImplGtk : public ui::LinuxInputMethodContext {
public:
X11InputMethodContextImplGtk(ui::LinuxInputMethodContextDelegate* delegate,
InputMethodContextImplGtk(ui::LinuxInputMethodContextDelegate* delegate,
bool is_simple);
~X11InputMethodContextImplGtk() override;
~InputMethodContextImplGtk() override;
// Overriden from ui::LinuxInputMethodContext
// Overridden from ui::LinuxInputMethodContext
bool DispatchKeyEvent(const ui::KeyEvent& key_event) override;
void SetCursorLocation(const gfx::Rect& rect) override;
void Reset() override;
......@@ -39,45 +35,28 @@ class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext {
const gfx::Range& selection_range) override;
private:
// Resets the cache of X modifier keycodes.
// TODO(yukishiino): We should call this method whenever X keyboard mapping
// changes, for example when a user switched to another keyboard layout.
void ResetXModifierKeycodesCache();
// Constructs a GdkEventKey from a XKeyEvent and returns it. Otherwise,
// returns nullptr. The returned GdkEvent must be freed by gdk_event_free.
GdkEvent* GdkEventFromNativeEvent(const ui::PlatformEvent& native_event);
// Returns true if the hardware |keycode| is assigned to a modifier key.
bool IsKeycodeModifierKey(unsigned int keycode) const;
// Returns true if one of |keycodes| is pressed. |keybits| is a bit vector
// returned by XQueryKeymap, and |num_keys| is the number of keys in
// |keybits|.
bool IsAnyOfKeycodesPressed(const std::vector<int>& keycodes,
const char* keybits,
int num_keys) const;
// GtkIMContext event handlers. They are shared among |gtk_context_simple_|
// and |gtk_multicontext_|.
CHROMEG_CALLBACK_1(X11InputMethodContextImplGtk,
CHROMEG_CALLBACK_1(InputMethodContextImplGtk,
void,
OnCommit,
GtkIMContext*,
gchar*);
CHROMEG_CALLBACK_0(X11InputMethodContextImplGtk,
CHROMEG_CALLBACK_0(InputMethodContextImplGtk,
void,
OnPreeditChanged,
GtkIMContext*);
CHROMEG_CALLBACK_0(X11InputMethodContextImplGtk,
CHROMEG_CALLBACK_0(InputMethodContextImplGtk,
void,
OnPreeditEnd,
GtkIMContext*);
CHROMEG_CALLBACK_0(X11InputMethodContextImplGtk,
CHROMEG_CALLBACK_0(InputMethodContextImplGtk,
void,
OnPreeditStart,
GtkIMContext*);
void SetContextClientWindow(GdkWindow* window);
// A set of callback functions. Must not be nullptr.
ui::LinuxInputMethodContextDelegate* delegate_;
......@@ -97,17 +76,9 @@ class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext {
// Last known caret bounds relative to the screen coordinates.
gfx::Rect last_caret_bounds_;
// A set of hardware keycodes of modifier keys.
std::unordered_set<unsigned int> modifier_keycodes_;
// A list of keycodes of each modifier key.
std::vector<int> meta_keycodes_;
std::vector<int> super_keycodes_;
std::vector<int> hyper_keycodes_;
DISALLOW_COPY_AND_ASSIGN(X11InputMethodContextImplGtk);
DISALLOW_COPY_AND_ASSIGN(InputMethodContextImplGtk);
};
} // namespace libgtkui
#endif // CHROME_BROWSER_UI_LIBGTKUI_X11_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
#endif // CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
......@@ -1032,6 +1032,14 @@ DispatchDetails WindowEventDispatcher::PreDispatchKeyEvent(
!host_->ShouldSendKeyEventToIme()) {
return DispatchDetails();
}
// At this point (i.e: EP_PREDISPATCH), event target is still not set, so do
// it explicitly here thus making it possible for InputMethodContext
// implementation to retrieve target window through KeyEvent::target().
// Event::target is reset at WindowTreeHost::DispatchKeyEventPostIME(), just
// after key is processed by InputMethodContext.
ui::Event::DispatcherApi(event).set_target(window());
DispatchDetails details = host_->GetInputMethod()->DispatchKeyEvent(event);
event->StopPropagation();
return details;
......
......@@ -263,6 +263,11 @@ ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME(
// If dispatch to IME is already disabled we shouldn't reach here.
DCHECK(!dispatcher_->should_skip_ime());
dispatcher_->set_skip_ime(true);
// InputMethod::DispatchKeyEvent() is called in PRE_DISPATCH phase, so event
// target is reset here to avoid issues in subsequent processing phases.
ui::Event::DispatcherApi(event).set_target(nullptr);
// We should bypass event rewriters here as they've been tried before.
ui::EventDispatchDetails dispatch_details =
event_sink()->OnEventFromSource(event);
......
......@@ -28,6 +28,7 @@
#if defined(USE_X11)
#include "ui/events/keycodes/keyboard_code_conversion_x.h" // nogncheck
#include "ui/events/x/events_x_utils.h" // nogncheck
#include "ui/gfx/x/x11.h" // nogncheck
#elif defined(USE_OZONE)
#include "ui/events/ozone/layout/keyboard_layout_engine.h" // nogncheck
......@@ -50,6 +51,22 @@ bool X11EventHasNonStandardState(const PlatformEvent& event) {
return event && (event->xkey.state & ~kAllStateMask) != 0;
}
Event::Properties GetKeyEventPropertiesFromXKeyEvent(const XKeyEvent& xev) {
using Values = std::vector<uint8_t>;
Event::Properties properties;
// Keyboard group
uint8_t group = XkbGroupForCoreState(xev.state);
properties.emplace(kPropertyKeyboardGroup, Values{group});
// IBus-gtk specific flags
uint8_t ibus_flags = (xev.state >> kPropertyKeyboardIBusFlagOffset) &
kPropertyKeyboardIBusFlagMask;
properties.emplace(kPropertyKeyboardIBusFlag, Values{ibus_flags});
return properties;
}
#endif
constexpr int kChangedButtonFlagMask =
......@@ -890,6 +907,7 @@ KeyEvent::KeyEvent(const PlatformEvent& native_event, int event_flags)
#if defined(USE_X11)
NormalizeFlags();
SetProperties(GetKeyEventPropertiesFromXKeyEvent(native_event->xkey));
#endif
#if defined(OS_WIN)
// Only Windows has native character events.
......
......@@ -40,6 +40,16 @@ class Event;
class MouseEvent;
enum class DomCode;
// Key used to store keyboard 'group' values in Event::Properties
constexpr char kPropertyKeyboardGroup[] = "_keyevent_kbd_group_";
// IBus specific Event::Properties constants. ibus-gtk in async mode uses
// gtk-specific XKeyEvent::state bits 24 and 25 for its key events.
// https://mail.gnome.org/archives/gtk-devel-list/2013-June/msg00003.html
constexpr char kPropertyKeyboardIBusFlag[] = "_keyevent_kbd_ibus_ime_flags_";
constexpr unsigned int kPropertyKeyboardIBusFlagOffset = 24;
constexpr unsigned int kPropertyKeyboardIBusFlagMask = 0x03;
// Returns a ui::Event wrapping a native event. Ownership of the returned value
// is transferred to the caller.
EVENTS_EXPORT std::unique_ptr<Event> EventFromNative(
......
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