Commit a798c106 authored by Nick Diego Yamane's avatar Nick Diego Yamane Committed by Commit Bot

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: default avatarSadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695827}
parent cbc5d515
...@@ -23,6 +23,8 @@ jumbo_component("libgtkui") { ...@@ -23,6 +23,8 @@ jumbo_component("libgtkui") {
"gtk_ui.h", "gtk_ui.h",
"gtk_util.cc", "gtk_util.cc",
"gtk_util.h", "gtk_util.h",
"input_method_context_impl_gtk.cc",
"input_method_context_impl_gtk.h",
"libgtkui_export.h", "libgtkui_export.h",
"menu_util.cc", "menu_util.cc",
"menu_util.h", "menu_util.h",
...@@ -124,8 +126,6 @@ jumbo_component("libgtkui") { ...@@ -124,8 +126,6 @@ jumbo_component("libgtkui") {
sources += [ sources += [
"gtk_event_loop_x11.cc", "gtk_event_loop_x11.cc",
"gtk_event_loop_x11.h", "gtk_event_loop_x11.h",
"x11_input_method_context_impl_gtk.cc",
"x11_input_method_context_impl_gtk.h",
] ]
deps += [ deps += [
......
...@@ -17,11 +17,6 @@ ...@@ -17,11 +17,6 @@
#include "ui/base/ime/text_edit_commands.h" #include "ui/base/ime/text_edit_commands.h"
#include "ui/events/event.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; using ui::TextEditCommand;
// TODO(erg): Rewrite the old gtk_key_bindings_handler_unittest.cc and get them // TODO(erg): Rewrite the old gtk_key_bindings_handler_unittest.cc and get them
...@@ -41,56 +36,13 @@ GtkWidget* CreateInvisibleWindow() { ...@@ -41,56 +36,13 @@ GtkWidget* CreateInvisibleWindow() {
#endif #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
namespace libgtkui { namespace libgtkui {
GtkKeyBindingsHandler::GtkKeyBindingsHandler() GtkKeyBindingsHandler::GtkKeyBindingsHandler()
: fake_window_(CreateInvisibleWindow()), : fake_window_(CreateInvisibleWindow()), handler_(CreateNewHandler()) {
handler_(CreateNewHandler()),
has_xkb_(false) {
gtk_container_add(GTK_CONTAINER(fake_window_), handler_); 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() { GtkKeyBindingsHandler::~GtkKeyBindingsHandler() {
...@@ -104,19 +56,19 @@ bool GtkKeyBindingsHandler::MatchEvent( ...@@ -104,19 +56,19 @@ bool GtkKeyBindingsHandler::MatchEvent(
CHECK(event.IsKeyEvent()); CHECK(event.IsKeyEvent());
const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); 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; return false;
GdkEventKey gdk_event; GdkEvent* gdk_event = GdkEventFromKeyEvent(key_event);
BuildGdkEventKeyFromKeyEvent(key_event, &gdk_event); if (!gdk_event)
return false;
edit_commands_.clear(); edit_commands_.clear();
// If this key event matches a predefined key binding, corresponding signal // If this key event matches a predefined key binding, corresponding signal
// will be emitted. // will be emitted.
gtk_bindings_activate_event( gtk_bindings_activate_event(G_OBJECT(handler_), &gdk_event->key);
G_OBJECT(handler_), gdk_event_free(gdk_event);
&gdk_event);
bool matched = !edit_commands_.empty(); bool matched = !edit_commands_.empty();
if (edit_commands) if (edit_commands)
...@@ -149,56 +101,6 @@ void GtkKeyBindingsHandler::EditCommandMatched(TextEditCommand command, ...@@ -149,56 +101,6 @@ void GtkKeyBindingsHandler::EditCommandMatched(TextEditCommand command,
edit_commands_.push_back(ui::TextEditCommandAuraLinux(command, value)); 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) { void GtkKeyBindingsHandler::HandlerInit(Handler* self) {
self->owner = nullptr; self->owner = nullptr;
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
namespace ui { namespace ui {
class Event; class Event;
class KeyEvent;
} }
namespace libgtkui { namespace libgtkui {
...@@ -70,10 +69,6 @@ class GtkKeyBindingsHandler { ...@@ -70,10 +69,6 @@ class GtkKeyBindingsHandler {
void EditCommandMatched(ui::TextEditCommand command, void EditCommandMatched(ui::TextEditCommand command,
const std::string& value); const std::string& value);
// Builds a fake GdkEventKey from an XEvent.
void BuildGdkEventKeyFromKeyEvent(const ui::KeyEvent& key_event,
GdkEventKey* gdk_event);
// Initializes Handler structure. // Initializes Handler structure.
static void HandlerInit(Handler* self); static void HandlerInit(Handler* self);
...@@ -142,9 +137,6 @@ class GtkKeyBindingsHandler { ...@@ -142,9 +137,6 @@ class GtkKeyBindingsHandler {
// Buffer to store the match results. // Buffer to store the match results.
std::vector<ui::TextEditCommandAuraLinux> edit_commands_; std::vector<ui::TextEditCommandAuraLinux> edit_commands_;
// Whether the current X server has the XKeyboard extension.
bool has_xkb_;
}; };
} // namespace libgtkui } // namespace libgtkui
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h" #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_status_icon.h"
#include "chrome/browser/ui/libgtkui/gtk_util.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/native_theme_gtk.h"
#include "chrome/browser/ui/libgtkui/nav_button_provider_gtk.h" #include "chrome/browser/ui/libgtkui/nav_button_provider_gtk.h"
#include "chrome/browser/ui/libgtkui/print_dialog_gtk.h" #include "chrome/browser/ui/libgtkui/print_dialog_gtk.h"
...@@ -73,7 +74,6 @@ ...@@ -73,7 +74,6 @@
#if defined(USE_X11) #if defined(USE_X11)
#include "chrome/browser/ui/libgtkui/gtk_event_loop_x11.h" // nogncheck #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.h" // nogncheck
#include "ui/gfx/x/x11_types.h" // nogncheck #include "ui/gfx/x/x11_types.h" // nogncheck
#endif #endif
...@@ -333,7 +333,7 @@ GtkUi::GtkUi() { ...@@ -333,7 +333,7 @@ GtkUi::GtkUi() {
{ActionSource::kRightClick, Action::kMenu}}; {ActionSource::kRightClick, Action::kMenu}};
// Force Gtk to use Xwayland if it would have used wayland. libgtkui assumes // 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. // other backends.
// TODO(thomasanderson): Change this logic once Wayland support is added. // TODO(thomasanderson): Change this logic once Wayland support is added.
gdk_set_allowed_backends("x11"); gdk_set_allowed_backends("x11");
...@@ -655,7 +655,7 @@ std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext( ...@@ -655,7 +655,7 @@ std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext(
bool is_simple) const { bool is_simple) const {
#if defined(USE_X11) #if defined(USE_X11)
return std::unique_ptr<ui::LinuxInputMethodContext>( return std::unique_ptr<ui::LinuxInputMethodContext>(
new X11InputMethodContextImplGtk(delegate, is_simple)); new InputMethodContextImplGtk(delegate, is_simple));
#else #else
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return std::make_unique<ui::FakeInputMethodContext>(); return std::make_unique<ui::FakeInputMethodContext>();
......
...@@ -21,10 +21,11 @@ ...@@ -21,10 +21,11 @@
#include "base/strings/string_tokenizer.h" #include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "build/branding_buildflags.h" #include "build/branding_buildflags.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
#include "ui/base/accelerators/accelerator.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/color_utils.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/views/linux_ui/linux_ui.h" #include "ui/views/linux_ui/linux_ui.h"
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#include "ui/events/keycodes/keyboard_code_conversion_x.h" // nogncheck #include "ui/events/keycodes/keyboard_code_conversion_x.h" // nogncheck
#include "ui/gfx/x/x11_types.h" // nogncheck
#endif #endif
namespace { namespace {
...@@ -72,6 +74,44 @@ void CommonInitFromCommandLine(const base::CommandLine& command_line) { ...@@ -72,6 +74,44 @@ void CommonInitFromCommandLine(const base::CommandLine& command_line) {
#endif #endif
} }
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_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},
};
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;
}
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
namespace libgtkui { namespace libgtkui {
...@@ -617,4 +657,52 @@ guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator) { ...@@ -617,4 +657,52 @@ guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator) {
} }
#endif #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 = EventFlagsToGdkModifierType(
static_cast<ui::EventFlags>(key_event.flags()));
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 } // namespace libgtkui
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "ui/native_theme/native_theme.h" #include "ui/native_theme/native_theme.h"
#include "ui/views/window/frame_buttons.h" #include "ui/views/window/frame_buttons.h"
typedef union _GdkEvent GdkEvent;
namespace aura { namespace aura {
class Window; class Window;
} }
...@@ -27,6 +29,7 @@ struct HSL; ...@@ -27,6 +29,7 @@ struct HSL;
namespace ui { namespace ui {
class Accelerator; class Accelerator;
class KeyEvent;
} }
namespace libgtkui { namespace libgtkui {
...@@ -190,6 +193,17 @@ std::string GetGtkSettingsStringProperty(GtkSettings* settings, ...@@ -190,6 +193,17 @@ std::string GetGtkSettingsStringProperty(GtkSettings* settings,
// TODO(thomasanderson): Remove this once GtkStatusIcon is removed. // TODO(thomasanderson): Remove this once GtkStatusIcon is removed.
guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator); guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator);
#endif #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 } // namespace libgtkui
#endif // CHROME_BROWSER_UI_LIBGTKUI_GTK_UTIL_H_ #endif // CHROME_BROWSER_UI_LIBGTKUI_GTK_UTIL_H_
...@@ -2,34 +2,30 @@ ...@@ -2,34 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LIBGTKUI_X11_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ #ifndef CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
#define CHROME_BROWSER_UI_LIBGTKUI_X11_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ #define CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
#include <unordered_set>
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "ui/base/glib/glib_integers.h" #include "ui/base/glib/glib_integers.h"
#include "ui/base/glib/glib_signal.h" #include "ui/base/glib/glib_signal.h"
#include "ui/base/ime/linux/linux_input_method_context.h" #include "ui/base/ime/linux/linux_input_method_context.h"
#include "ui/events/platform_event.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
typedef union _GdkEvent GdkEvent; typedef struct _GdkWindow GdkWindow;
typedef struct _GtkIMContext GtkIMContext; typedef struct _GtkIMContext GtkIMContext;
namespace libgtkui { namespace libgtkui {
// An implementation of LinuxInputMethodContext which is based on X11 event loop // An implementation of LinuxInputMethodContext which uses GtkIMContext
// and uses GtkIMContext(gtk-immodule) as a bridge from/to underlying IMEs. // (gtk-immodule) as a bridge from/to underlying IMEs.
class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext { class InputMethodContextImplGtk : public ui::LinuxInputMethodContext {
public: public:
X11InputMethodContextImplGtk(ui::LinuxInputMethodContextDelegate* delegate, InputMethodContextImplGtk(ui::LinuxInputMethodContextDelegate* delegate,
bool is_simple); bool is_simple);
~X11InputMethodContextImplGtk() override; ~InputMethodContextImplGtk() override;
// Overriden from ui::LinuxInputMethodContext // Overridden from ui::LinuxInputMethodContext
bool DispatchKeyEvent(const ui::KeyEvent& key_event) override; bool DispatchKeyEvent(const ui::KeyEvent& key_event) override;
void SetCursorLocation(const gfx::Rect& rect) override; void SetCursorLocation(const gfx::Rect& rect) override;
void Reset() override; void Reset() override;
...@@ -39,45 +35,28 @@ class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext { ...@@ -39,45 +35,28 @@ class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext {
const gfx::Range& selection_range) override; const gfx::Range& selection_range) override;
private: 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_| // GtkIMContext event handlers. They are shared among |gtk_context_simple_|
// and |gtk_multicontext_|. // and |gtk_multicontext_|.
CHROMEG_CALLBACK_1(X11InputMethodContextImplGtk, CHROMEG_CALLBACK_1(InputMethodContextImplGtk,
void, void,
OnCommit, OnCommit,
GtkIMContext*, GtkIMContext*,
gchar*); gchar*);
CHROMEG_CALLBACK_0(X11InputMethodContextImplGtk, CHROMEG_CALLBACK_0(InputMethodContextImplGtk,
void, void,
OnPreeditChanged, OnPreeditChanged,
GtkIMContext*); GtkIMContext*);
CHROMEG_CALLBACK_0(X11InputMethodContextImplGtk, CHROMEG_CALLBACK_0(InputMethodContextImplGtk,
void, void,
OnPreeditEnd, OnPreeditEnd,
GtkIMContext*); GtkIMContext*);
CHROMEG_CALLBACK_0(X11InputMethodContextImplGtk, CHROMEG_CALLBACK_0(InputMethodContextImplGtk,
void, void,
OnPreeditStart, OnPreeditStart,
GtkIMContext*); GtkIMContext*);
void SetContextClientWindow(GdkWindow* window);
// A set of callback functions. Must not be nullptr. // A set of callback functions. Must not be nullptr.
ui::LinuxInputMethodContextDelegate* delegate_; ui::LinuxInputMethodContextDelegate* delegate_;
...@@ -97,17 +76,9 @@ class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext { ...@@ -97,17 +76,9 @@ class X11InputMethodContextImplGtk : public ui::LinuxInputMethodContext {
// Last known caret bounds relative to the screen coordinates. // Last known caret bounds relative to the screen coordinates.
gfx::Rect last_caret_bounds_; gfx::Rect last_caret_bounds_;
// A set of hardware keycodes of modifier keys. DISALLOW_COPY_AND_ASSIGN(InputMethodContextImplGtk);
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);
}; };
} // namespace libgtkui } // 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( ...@@ -1032,6 +1032,14 @@ DispatchDetails WindowEventDispatcher::PreDispatchKeyEvent(
!host_->ShouldSendKeyEventToIme()) { !host_->ShouldSendKeyEventToIme()) {
return DispatchDetails(); 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); DispatchDetails details = host_->GetInputMethod()->DispatchKeyEvent(event);
event->StopPropagation(); event->StopPropagation();
return details; return details;
......
...@@ -263,6 +263,11 @@ ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME( ...@@ -263,6 +263,11 @@ ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME(
// If dispatch to IME is already disabled we shouldn't reach here. // If dispatch to IME is already disabled we shouldn't reach here.
DCHECK(!dispatcher_->should_skip_ime()); DCHECK(!dispatcher_->should_skip_ime());
dispatcher_->set_skip_ime(true); 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. // We should bypass event rewriters here as they've been tried before.
ui::EventDispatchDetails dispatch_details = ui::EventDispatchDetails dispatch_details =
event_sink()->OnEventFromSource(event); event_sink()->OnEventFromSource(event);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#if defined(USE_X11) #if defined(USE_X11)
#include "ui/events/keycodes/keyboard_code_conversion_x.h" // nogncheck #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 #include "ui/gfx/x/x11.h" // nogncheck
#elif defined(USE_OZONE) #elif defined(USE_OZONE)
#include "ui/events/ozone/layout/keyboard_layout_engine.h" // nogncheck #include "ui/events/ozone/layout/keyboard_layout_engine.h" // nogncheck
...@@ -202,6 +203,12 @@ void Event::SetProperties(const Properties& properties) { ...@@ -202,6 +203,12 @@ void Event::SetProperties(const Properties& properties) {
properties_ = std::make_unique<Properties>(properties); properties_ = std::make_unique<Properties>(properties);
} }
void Event::SetProperty(const char* key, const std::vector<uint8_t>& values) {
if (!properties_)
properties_ = std::make_unique<Properties>();
properties_->insert_or_assign(key, values);
}
CancelModeEvent* Event::AsCancelModeEvent() { CancelModeEvent* Event::AsCancelModeEvent() {
CHECK(IsCancelModeEvent()); CHECK(IsCancelModeEvent());
return static_cast<CancelModeEvent*>(this); return static_cast<CancelModeEvent*>(this);
...@@ -890,6 +897,9 @@ KeyEvent::KeyEvent(const PlatformEvent& native_event, int event_flags) ...@@ -890,6 +897,9 @@ KeyEvent::KeyEvent(const PlatformEvent& native_event, int event_flags)
#if defined(USE_X11) #if defined(USE_X11)
NormalizeFlags(); NormalizeFlags();
// Attach keyboard group to Event::properties
uint8_t group = XkbGroupForCoreState(native_event->xkey.state);
SetProperty(ui::kPropertyKeyboardGroup, {group});
#endif #endif
#if defined(OS_WIN) #if defined(OS_WIN)
// Only Windows has native character events. // Only Windows has native character events.
......
...@@ -105,6 +105,9 @@ class EVENTS_EXPORT Event { ...@@ -105,6 +105,9 @@ class EVENTS_EXPORT Event {
// Sets the properties associated with this Event. // Sets the properties associated with this Event.
void SetProperties(const Properties& properties); void SetProperties(const Properties& properties);
// Inserts/updates a key/values property pair
void SetProperty(const char* key, const std::vector<uint8_t>& values);
// Returns the properties associated with this event, which may be null. // Returns the properties associated with this event, which may be null.
// The properties are meant to provide a way to associate arbitrary key/value // The properties are meant to provide a way to associate arbitrary key/value
// pairs with Events and not used by Event. // pairs with Events and not used by Event.
......
...@@ -40,6 +40,9 @@ class Event; ...@@ -40,6 +40,9 @@ class Event;
class MouseEvent; class MouseEvent;
enum class DomCode; enum class DomCode;
// Key used to store keyboard 'group' values in Event::Properties
constexpr char kPropertyKeyboardGroup[] = "_keyevent_kbd_group_";
// Returns a ui::Event wrapping a native event. Ownership of the returned value // Returns a ui::Event wrapping a native event. Ownership of the returned value
// is transferred to the caller. // is transferred to the caller.
EVENTS_EXPORT std::unique_ptr<Event> EventFromNative( 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