WebKitInputMethodContextImplGtk.cpp [plain text]
#include "config.h"
#include "WebKitInputMethodContextImplGtk.h"
#include <gtk/gtk.h>
#include <wtf/MathExtras.h>
#include <wtf/glib/GRefPtr.h>
#include <wtf/glib/WTFGType.h>
struct _WebKitInputMethodContextImplGtkPrivate {
GRefPtr<GtkIMContext> context;
};
WEBKIT_DEFINE_TYPE(WebKitInputMethodContextImplGtk, webkit_input_method_context_impl_gtk, WEBKIT_TYPE_INPUT_METHOD_CONTEXT)
static void contextPreeditStartCallback(WebKitInputMethodContextImplGtk* context)
{
g_signal_emit_by_name(context, "preedit-started", nullptr);
}
static void contextPreeditChangedCallback(WebKitInputMethodContextImplGtk* context)
{
g_signal_emit_by_name(context, "preedit-changed", nullptr);
}
static void contextPreeditEndCallback(WebKitInputMethodContextImplGtk* context)
{
g_signal_emit_by_name(context, "preedit-finished", nullptr);
}
static void contextCommitCallback(WebKitInputMethodContextImplGtk* context, const char* text)
{
g_signal_emit_by_name(context, "committed", text, nullptr);
}
static void webkitInputMethodContextImplGtkConstructed(GObject* object)
{
G_OBJECT_CLASS(webkit_input_method_context_impl_gtk_parent_class)->constructed(object);
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(object)->priv;
priv->context = adoptGRef(gtk_im_multicontext_new());
g_signal_connect_object(priv->context.get(), "preedit-start", G_CALLBACK(contextPreeditStartCallback), object, G_CONNECT_SWAPPED);
g_signal_connect_object(priv->context.get(), "preedit-changed", G_CALLBACK(contextPreeditChangedCallback), object, G_CONNECT_SWAPPED);
g_signal_connect_object(priv->context.get(), "preedit-end", G_CALLBACK(contextPreeditEndCallback), object, G_CONNECT_SWAPPED);
g_signal_connect_object(priv->context.get(), "commit", G_CALLBACK(contextCommitCallback), object, G_CONNECT_SWAPPED);
}
static void webkitInputMethodContextImplGtkSetEnablePreedit(WebKitInputMethodContext* context, gboolean enabled)
{
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(context)->priv;
gtk_im_context_set_use_preedit(priv->context.get(), enabled);
}
static void webkitInputMethodContextImplGtkGetPreedit(WebKitInputMethodContext* context, char** text, GList** underlines, guint* cursorOffset)
{
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(context)->priv;
PangoAttrList* attrList = nullptr;
int offset;
gtk_im_context_get_preedit_string(priv->context.get(), text, underlines ? &attrList : nullptr, &offset);
if (underlines) {
*underlines = nullptr;
if (attrList) {
PangoAttrIterator* iter = pango_attr_list_get_iterator(attrList);
do {
if (!pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE))
continue;
int start, end;
pango_attr_iterator_range(iter, &start, &end);
auto* underline = webkit_input_method_underline_new(clampTo<unsigned>(start), clampTo<unsigned>(end));
if (auto* colorAttribute = pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE_COLOR)) {
PangoColor* color = &(reinterpret_cast<PangoAttrColor*>(colorAttribute))->color;
GdkRGBA rgba = { color->red / 65535., color->green / 65535., color->blue / 65535., 1. };
webkit_input_method_underline_set_color(underline, &rgba);
}
*underlines = g_list_prepend(*underlines, underline);
} while (pango_attr_iterator_next(iter));
}
}
if (cursorOffset)
*cursorOffset = clampTo<unsigned>(offset);
}
static gboolean webkitInputMethodContextImplGtkFilterKeyEvent(WebKitInputMethodContext* context, GdkEventKey* keyEvent)
{
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(context)->priv;
return gtk_im_context_filter_keypress(priv->context.get(), keyEvent);
}
static void webkitInputMethodContextImplGtkNotifyFocusIn(WebKitInputMethodContext* context)
{
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(context)->priv;
gtk_im_context_focus_in(priv->context.get());
}
static void webkitInputMethodContextImplGtkNotifyFocusOut(WebKitInputMethodContext* context)
{
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(context)->priv;
gtk_im_context_focus_out(priv->context.get());
}
static void webkitInputMethodContextImplGtkNotifyCursorArea(WebKitInputMethodContext* context, int x, int y, int width, int height)
{
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(context)->priv;
GdkRectangle cursorRect = { x, y, width, height };
gtk_im_context_set_cursor_location(priv->context.get(), &cursorRect);
}
static void webkitInputMethodContextImplGtkReset(WebKitInputMethodContext* context)
{
auto* priv = WEBKIT_INPUT_METHOD_CONTEXT_IMPL_GTK(context)->priv;
gtk_im_context_reset(priv->context.get());
}
static void webkit_input_method_context_impl_gtk_class_init(WebKitInputMethodContextImplGtkClass* klass)
{
GObjectClass* objectClass = G_OBJECT_CLASS(klass);
objectClass->constructed = webkitInputMethodContextImplGtkConstructed;
auto* imClass = WEBKIT_INPUT_METHOD_CONTEXT_CLASS(klass);
imClass->set_enable_preedit = webkitInputMethodContextImplGtkSetEnablePreedit;
imClass->get_preedit = webkitInputMethodContextImplGtkGetPreedit;
imClass->filter_key_event = webkitInputMethodContextImplGtkFilterKeyEvent;
imClass->notify_focus_in = webkitInputMethodContextImplGtkNotifyFocusIn;
imClass->notify_focus_out = webkitInputMethodContextImplGtkNotifyFocusOut;
imClass->notify_cursor_area = webkitInputMethodContextImplGtkNotifyCursorArea;
imClass->reset = webkitInputMethodContextImplGtkReset;
}
WebKitInputMethodContext* webkitInputMethodContextImplGtkNew()
{
return WEBKIT_INPUT_METHOD_CONTEXT(g_object_new(WEBKIT_TYPE_INPUT_METHOD_CONTEXT_IMPL_GTK, nullptr));
}
void webkitInputMethodContextImplGtkSetClientWindow(WebKitInputMethodContextImplGtk* context, GdkWindow* window)
{
gtk_im_context_set_client_window(context->priv->context.get(), window);
}