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

ozone/x11: Support IME through gtkui

This CL adds initial IME support to ozone/x11 by reusing libgtkui's
LinuxInputMethodContext{Factory} implementation, which uses gtk-immodule as
backend.

Some logic has been added to be able to support the following scenarios,
possible, from now on, in ozone linux platforms:

(1) LinuxInputMethodContextFactory is implemented inside ozone backend
implementation, it is instantiated set in OzonePlatform::InitializeUI. E.g:
ozone/wayland.

(2) If the ozone platform initialization have not created/set a
LinuxInputMethodContextFactory instance and GtkUi is in place, then it is set
as the global instance. E.g: ozone/x11.

Even though the logic to support the aforementioned use cases is quite tricky,
spread over different layers (e.g: views::LinuxUI, libgtkui::GtkUi,
ui::OzonePlatform), using ifdefs, etc; it should be cleaned up and unified once
X11 migration to Ozone is completed.

It is worth noting that proper IME support for now requires GLib message pump
(at least IBus, for example) being used in UI thread (i.e: use_glib=true).

Bug: 987939, 789065
Change-Id: I700d39eec02c6bbeaafca29c9405e8e0e1ff6ade
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1798263
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@{#698627}
parent f9d9d4f2
...@@ -8,6 +8,7 @@ import("//build/config/features.gni") ...@@ -8,6 +8,7 @@ import("//build/config/features.gni")
import("//build/config/jumbo.gni") import("//build/config/jumbo.gni")
import("//build/config/linux/gtk/gtk.gni") import("//build/config/linux/gtk/gtk.gni")
import("//printing/buildflags/buildflags.gni") import("//printing/buildflags/buildflags.gni")
import("//ui/ozone/ozone.gni")
jumbo_component("libgtkui") { jumbo_component("libgtkui") {
sources = [ sources = [
...@@ -122,7 +123,7 @@ jumbo_component("libgtkui") { ...@@ -122,7 +123,7 @@ jumbo_component("libgtkui") {
"//chrome/browser:theme_properties", "//chrome/browser:theme_properties",
] ]
if (use_x11) { if (use_x11 || ozone_platform_x11) {
sources += [ sources += [
"gtk_event_loop_x11.cc", "gtk_event_loop_x11.cc",
"gtk_event_loop_x11.h", "gtk_event_loop_x11.h",
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/libgtkui/app_indicator_icon.h" #include "chrome/browser/ui/libgtkui/app_indicator_icon.h"
#include "chrome/browser/ui/libgtkui/gtk_event_loop_x11.h"
#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"
...@@ -46,6 +47,7 @@ ...@@ -46,6 +47,7 @@
#include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/core/SkShader.h"
#include "ui/base/ime/linux/fake_input_method_context.h" #include "ui/base/ime/linux/fake_input_method_context.h"
#include "ui/base/ime/linux/linux_input_method_context.h" #include "ui/base/ime/linux/linux_input_method_context.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/display/display.h" #include "ui/display/display.h"
#include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/dom_code.h"
...@@ -73,7 +75,6 @@ ...@@ -73,7 +75,6 @@
#endif #endif
#if defined(USE_X11) #if defined(USE_X11)
#include "chrome/browser/ui/libgtkui/gtk_event_loop_x11.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
...@@ -332,11 +333,13 @@ GtkUi::GtkUi() { ...@@ -332,11 +333,13 @@ GtkUi::GtkUi() {
{ActionSource::kMiddleClick, GetDefaultMiddleClickAction()}, {ActionSource::kMiddleClick, GetDefaultMiddleClickAction()},
{ActionSource::kRightClick, Action::kMenu}}; {ActionSource::kRightClick, Action::kMenu}};
// Force Gtk to use Xwayland if it would have used wayland. libgtkui assumes #if defined(USE_X11)
// the use of X11 (eg. InputMethodContextImplGtk) and will crash under // Force Gtk to use Xwayland if it would have used wayland. In Aura/X11,
// other backends. // libgtkui assumes the use of X11 (eg. InputMethodContextImplGtk) and will
// crash under 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");
#endif
// Avoid GTK initializing atk-bridge, and let AuraLinux implementation // Avoid GTK initializing atk-bridge, and let AuraLinux implementation
// do it once it is ready. // do it once it is ready.
...@@ -353,6 +356,16 @@ GtkUi::~GtkUi() { ...@@ -353,6 +356,16 @@ GtkUi::~GtkUi() {
} }
void GtkUi::Initialize() { void GtkUi::Initialize() {
#if defined(USE_OZONE)
// Linux ozone platforms may set LinuxInputMethodContextFactory instance at
// InitializeUI step (which is called in Toolkit initialization step), so
// at this point if it's not set LinuxUI (i.e: GtkUi) implementation is
// used. For example, ozone/x11 uses GtkUi context factory, but
// ozone/wayland uses it's own implementation.
if (!ui::LinuxInputMethodContextFactory::instance())
ui::LinuxInputMethodContextFactory::SetInstance(this);
#endif
GtkSettings* settings = gtk_settings_get_default(); GtkSettings* settings = gtk_settings_get_default();
g_signal_connect_after(settings, "notify::gtk-theme-name", g_signal_connect_after(settings, "notify::gtk-theme-name",
G_CALLBACK(OnThemeChangedThunk), this); G_CALLBACK(OnThemeChangedThunk), this);
...@@ -386,10 +399,8 @@ void GtkUi::Initialize() { ...@@ -386,10 +399,8 @@ void GtkUi::Initialize() {
indicators_count = 0; indicators_count = 0;
#if defined(USE_X11)
// Instantiate the singleton instance of GtkEventLoopX11. // Instantiate the singleton instance of GtkEventLoopX11.
GtkEventLoopX11::GetInstance(); GtkEventLoopX11::GetInstance();
#endif
} }
bool GtkUi::GetTint(int id, color_utils::HSL* tint) const { bool GtkUi::GetTint(int id, color_utils::HSL* tint) const {
...@@ -653,13 +664,8 @@ void GtkUi::SetWindowFrameAction(WindowFrameActionSource source, ...@@ -653,13 +664,8 @@ void GtkUi::SetWindowFrameAction(WindowFrameActionSource source,
std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext( std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext(
ui::LinuxInputMethodContextDelegate* delegate, ui::LinuxInputMethodContextDelegate* delegate,
bool is_simple) const { bool is_simple) const {
#if defined(USE_X11)
return std::unique_ptr<ui::LinuxInputMethodContext>( return std::unique_ptr<ui::LinuxInputMethodContext>(
new InputMethodContextImplGtk(delegate, is_simple)); new InputMethodContextImplGtk(delegate, is_simple));
#else
NOTIMPLEMENTED();
return std::make_unique<ui::FakeInputMethodContext>();
#endif
} }
gfx::FontRenderParams GtkUi::GetDefaultFontRenderParams() const { gfx::FontRenderParams GtkUi::GetDefaultFontRenderParams() const {
......
...@@ -366,8 +366,9 @@ Event::Event(const PlatformEvent& native_event, EventType type, int flags) ...@@ -366,8 +366,9 @@ Event::Event(const PlatformEvent& native_event, EventType type, int flags)
} }
#endif #endif
#if defined(USE_OZONE) #if defined(USE_OZONE)
source_device_id_ = source_device_id_ = native_event->source_device_id();
static_cast<const Event*>(native_event)->source_device_id(); if (auto* properties = native_event->properties())
properties_ = std::make_unique<Properties>(*properties);
#endif #endif
} }
......
...@@ -22,6 +22,22 @@ namespace ui { ...@@ -22,6 +22,22 @@ namespace ui {
namespace { namespace {
Event::Properties GetEventPropertiesFromXKeyEvent(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;
}
std::unique_ptr<TouchEvent> CreateTouchEvent(EventType event_type, std::unique_ptr<TouchEvent> CreateTouchEvent(EventType event_type,
const XEvent& xev) { const XEvent& xev) {
std::unique_ptr<TouchEvent> event = std::make_unique<TouchEvent>( std::unique_ptr<TouchEvent> event = std::make_unique<TouchEvent>(
...@@ -108,10 +124,13 @@ std::unique_ptr<ui::Event> TranslateXEventToEvent(const XEvent& xev) { ...@@ -108,10 +124,13 @@ std::unique_ptr<ui::Event> TranslateXEventToEvent(const XEvent& xev) {
EventTimeFromXEvent(xev), flags, 0); EventTimeFromXEvent(xev), flags, 0);
case KeyPress: case KeyPress:
case KeyRelease: case KeyRelease: {
return std::make_unique<KeyEvent>(EventTypeFromXEvent(xev), auto key_event = std::make_unique<KeyEvent>(
KeyboardCodeFromXKeyEvent(&xev), flags); EventTypeFromXEvent(xev), KeyboardCodeFromXKeyEvent(&xev), flags);
// Attach keyboard group to |key_event|'s properties
key_event->SetProperties(GetEventPropertiesFromXKeyEvent(xev.xkey));
return key_event;
}
case ButtonPress: case ButtonPress:
case ButtonRelease: { case ButtonRelease: {
switch (EventTypeFromXEvent(xev)) { switch (EventTypeFromXEvent(xev)) {
......
...@@ -127,17 +127,6 @@ class OzonePlatformWayland : public OzonePlatform { ...@@ -127,17 +127,6 @@ class OzonePlatformWayland : public OzonePlatform {
std::unique_ptr<InputMethod> CreateInputMethod( std::unique_ptr<InputMethod> CreateInputMethod(
internal::InputMethodDelegate* delegate) override { internal::InputMethodDelegate* delegate) override {
// Some unit tests may try to set custom input method context factory
// after InitializeUI. Thus instead of creating factory in InitializeUI
// it is set at this point if none exists
if (!LinuxInputMethodContextFactory::instance() &&
!input_method_context_factory_) {
input_method_context_factory_ =
std::make_unique<WaylandInputMethodContextFactory>(connection_.get());
LinuxInputMethodContextFactory::SetInstance(
input_method_context_factory_.get());
}
return std::make_unique<InputMethodAuraLinux>(delegate); return std::make_unique<InputMethodAuraLinux>(delegate);
} }
...@@ -177,6 +166,16 @@ class OzonePlatformWayland : public OzonePlatform { ...@@ -177,6 +166,16 @@ class OzonePlatformWayland : public OzonePlatform {
input_controller_ = CreateStubInputController(); input_controller_ = CreateStubInputController();
gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost()); gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
supported_buffer_formats_ = connection_->GetSupportedBufferFormats(); supported_buffer_formats_ = connection_->GetSupportedBufferFormats();
// Instantiate and set LinuxInputMethodContextFactory unless it is already
// set (e.g: tests may have already set it).
if (!LinuxInputMethodContextFactory::instance() &&
!input_method_context_factory_) {
input_method_context_factory_ =
std::make_unique<WaylandInputMethodContextFactory>(connection_.get());
LinuxInputMethodContextFactory::SetInstance(
input_method_context_factory_.get());
}
} }
void InitializeGPU(const InitParams& args) override { void InitializeGPU(const InitParams& args) override {
......
...@@ -64,6 +64,8 @@ source_set("x11") { ...@@ -64,6 +64,8 @@ source_set("x11") {
if (is_chromeos) { if (is_chromeos) {
deps += [ "//ui/base/ime/chromeos" ] deps += [ "//ui/base/ime/chromeos" ]
} else {
deps += [ "//ui/base/ime/linux" ]
} }
if (enable_vulkan) { if (enable_vulkan) {
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "ui/base/ime/chromeos/input_method_chromeos.h" #include "ui/base/ime/chromeos/input_method_chromeos.h"
#else #else
#include "ui/base/ime/input_method_minimal.h" #include "ui/base/ime/linux/input_method_auralinux.h"
#endif #endif
namespace ui { namespace ui {
...@@ -111,9 +111,7 @@ class OzonePlatformX11 : public OzonePlatform { ...@@ -111,9 +111,7 @@ class OzonePlatformX11 : public OzonePlatform {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
return std::make_unique<InputMethodChromeOS>(delegate); return std::make_unique<InputMethodChromeOS>(delegate);
#else #else
// TODO(spang): Fix InputMethodAuraLinux which requires another level return std::make_unique<InputMethodAuraLinux>(delegate);
// of initization.
return std::make_unique<InputMethodMinimal>(delegate);
#endif #endif
} }
......
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