diff options
author | Alexander Larsson <alexl@redhat.com> | 2013-11-13 12:20:07 +0100 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2013-11-13 12:23:06 +0100 |
commit | 4226f97d540ecd8cb5995184bfba7a1102560740 (patch) | |
tree | 8be015371a590bba0143c3ebb337ee934c4cdcfd | |
parent | ca89f5ab93da6745fb7f5d3483ed2943fce6f94e (diff) | |
download | gtk+-4226f97d540ecd8cb5995184bfba7a1102560740.tar.gz |
broadway: Support ipad on-screen keyboard
We add a custom im module for broadway that calls some broadway
specific APIs to show/hide the keyboard on focus in/out. We then forward this
to the browser, and on the ipad we focus an input field to activate
the keyboard.
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | gdk/broadway/broadway-output.c | 7 | ||||
-rw-r--r-- | gdk/broadway/broadway-output.h | 2 | ||||
-rw-r--r-- | gdk/broadway/broadway-protocol.h | 10 | ||||
-rw-r--r-- | gdk/broadway/broadway-server.c | 17 | ||||
-rw-r--r-- | gdk/broadway/broadway.js | 32 | ||||
-rw-r--r-- | gdk/broadway/broadwayd.c | 3 | ||||
-rw-r--r-- | gdk/broadway/gdkbroadway-server.c | 13 | ||||
-rw-r--r-- | gdk/broadway/gdkbroadway-server.h | 2 | ||||
-rw-r--r-- | gdk/broadway/gdkbroadwaydisplay.h | 5 | ||||
-rw-r--r-- | gdk/broadway/gdkdisplay-broadway.c | 16 | ||||
-rw-r--r-- | gtk/gtkimmodule.c | 12 | ||||
-rw-r--r-- | gtk/gtksettings.c | 25 | ||||
-rw-r--r-- | modules/input/Makefile.am | 15 | ||||
-rw-r--r-- | modules/input/imbroadway.c | 163 |
15 files changed, 318 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac index fa644c2cc7..f24cf3dec9 100644 --- a/configure.ac +++ b/configure.ac @@ -386,6 +386,7 @@ AC_SUBST(DISABLE_ON_QUARTZ) if test "x$enable_broadway_backend" = xyes; then GDK_BACKENDS="$GDK_BACKENDS broadway" cairo_backends="$cairo_backends cairo" + backend_immodules="$backend_immodules,broadway" if test "$host_os" != "mingw*|windows*|winnt"; then have_gio_unix=yes fi @@ -888,6 +889,7 @@ AM_CONDITIONAL(INCLUDE_IM_INUKTITUT, [test x"$INCLUDE_inuktitut" = xyes]) AM_CONDITIONAL(INCLUDE_IM_IPA, [test x"$INCLUDE_ipa" = xyes]) AM_CONDITIONAL(INCLUDE_IM_MULTIPRESS, [test x"$INCLUDE_multipress" = xyes]) AM_CONDITIONAL(INCLUDE_IM_QUARTZ, [test x"$INCLUDE_quartz" = xyes]) +AM_CONDITIONAL(INCLUDE_IM_BROADWAY, [test x"$INCLUDE_broadway" = xyes]) AM_CONDITIONAL(INCLUDE_IM_THAI, [test x"$INCLUDE_thai" = xyes]) AM_CONDITIONAL(INCLUDE_IM_TI_ER, [test x"$INCLUDE_ti_er" = xyes]) AM_CONDITIONAL(INCLUDE_IM_TI_ET, [test x"$INCLUDE_ti_et" = xyes]) diff --git a/gdk/broadway/broadway-output.c b/gdk/broadway/broadway-output.c index 42ad59f050..631c542890 100644 --- a/gdk/broadway/broadway-output.c +++ b/gdk/broadway/broadway-output.c @@ -237,6 +237,13 @@ broadway_output_destroy_surface(BroadwayOutput *output, int id) append_uint16 (output, id); } +void +broadway_output_set_show_keyboard (BroadwayOutput *output, + gboolean show) +{ + write_header (output, BROADWAY_OP_SET_SHOW_KEYBOARD); + append_uint16 (output, show); +} void broadway_output_move_resize_surface (BroadwayOutput *output, diff --git a/gdk/broadway/broadway-output.h b/gdk/broadway/broadway-output.h index 6d6bb61b31..0ccda2484d 100644 --- a/gdk/broadway/broadway-output.h +++ b/gdk/broadway/broadway-output.h @@ -63,5 +63,7 @@ void broadway_output_grab_pointer (BroadwayOutput *output, gboolean owner_event); guint32 broadway_output_ungrab_pointer (BroadwayOutput *output); void broadway_output_pong (BroadwayOutput *output); +void broadway_output_set_show_keyboard (BroadwayOutput *output, + gboolean show); #endif /* __BROADWAY_H__ */ diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h index 8447bd567a..db0c4f1c93 100644 --- a/gdk/broadway/broadway-protocol.h +++ b/gdk/broadway/broadway-protocol.h @@ -42,6 +42,7 @@ typedef enum { BROADWAY_OP_AUTH_OK = 'L', BROADWAY_OP_DISCONNECTED = 'D', BROADWAY_OP_PUT_BUFFER = 'b', + BROADWAY_OP_SET_SHOW_KEYBOARD = 'k', } BroadwayOpType; typedef struct { @@ -154,7 +155,8 @@ typedef enum { BROADWAY_REQUEST_MOVE_RESIZE, BROADWAY_REQUEST_GRAB_POINTER, BROADWAY_REQUEST_UNGRAB_POINTER, - BROADWAY_REQUEST_FOCUS_WINDOW + BROADWAY_REQUEST_FOCUS_WINDOW, + BROADWAY_REQUEST_SET_SHOW_KEYBOARD } BroadwayRequestType; typedef struct { @@ -223,6 +225,11 @@ typedef struct { guint32 height; } BroadwayRequestMoveResize; +typedef struct { + BroadwayRequestBase base; + guint32 show_keyboard; +} BroadwayRequestSetShowKeyboard; + typedef union { BroadwayRequestBase base; BroadwayRequestNewWindow new_window; @@ -239,6 +246,7 @@ typedef union { BroadwayRequestUngrabPointer ungrab_pointer; BroadwayRequestTranslate translate; BroadwayRequestFocusWindow focus_window; + BroadwayRequestSetShowKeyboard set_show_keyboard; } BroadwayRequest; typedef enum { diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c index 6aedd37b55..3b3baa896b 100644 --- a/gdk/broadway/broadway-server.c +++ b/gdk/broadway/broadway-server.c @@ -55,6 +55,7 @@ struct _BroadwayServer { GList *toplevels; BroadwayWindow *root; gint32 focused_window_id; /* -1 => none */ + gint show_keyboard; guint32 screen_width; guint32 screen_height; @@ -1413,6 +1414,19 @@ broadway_server_window_raise (BroadwayServer *server, } void +broadway_server_set_show_keyboard (BroadwayServer *server, + gboolean show) +{ + server->show_keyboard = show; + + if (server->output) + { + broadway_output_set_show_keyboard (server->output, server->show_keyboard); + broadway_server_flush (server); + } +} + +void broadway_server_window_lower (BroadwayServer *server, gint id) { @@ -1783,5 +1797,8 @@ broadway_server_resync_windows (BroadwayServer *server) } } + if (server->show_keyboard) + broadway_output_set_show_keyboard (server->output, TRUE); + broadway_server_flush (server); } diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js index ed0a9e06eb..f8a944075e 100644 --- a/gdk/broadway/broadway.js +++ b/gdk/broadway/broadway.js @@ -103,6 +103,9 @@ var stackingOrder = []; var outstandingCommands = new Array(); var inputSocket = null; var debugDecoding = false; +var fakeInput = null; +var showKeyboard = false; +var showKeyboardChanged = false; var GDK_CROSSING_NORMAL = 0; var GDK_CROSSING_GRAB = 1; @@ -630,6 +633,12 @@ function handleCommands(cmd) case 'u': // Ungrab cmdUngrabPointer(); break; + + case 'k': // show keyboard + showKeyboard = cmd.get_16() != 0; + showKeyboardChanged = true; + break; + default: alert("Unknown op " + command); } @@ -763,6 +772,16 @@ function getEffectiveEventTarget (id) { return id; } +function updateKeyboardStatus() { + if (fakeInput != null && showKeyboardChanged) { + showKeyboardChanged = false; + if (showKeyboard) + fakeInput.focus(); + else + fakeInput.blur(); + } +} + function updateForEvent(ev) { lastState &= ~(GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK); if (ev.shiftKey) @@ -2463,6 +2482,7 @@ function onMouseWheel(ev) function onTouchStart(ev) { event.preventDefault(); + updateKeyboardStatus(); updateForEvent(ev); for (var i = 0; i < ev.changedTouches.length; i++) { @@ -2478,6 +2498,7 @@ function onTouchStart(ev) { function onTouchMove(ev) { event.preventDefault(); + updateKeyboardStatus(); updateForEvent(ev); for (var i = 0; i < ev.changedTouches.length; i++) { @@ -2493,6 +2514,7 @@ function onTouchMove(ev) { function onTouchEnd(ev) { event.preventDefault(); + updateKeyboardStatus(); updateForEvent(ev); for (var i = 0; i < ev.changedTouches.length; i++) { @@ -2574,4 +2596,14 @@ function connect() ws.onmessage = function(event) { handleMessage(event.data); }; + + var iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent ); + if (iOS) { + fakeInput = document.createElement("input"); + fakeInput.type = "text"; + fakeInput.style.position = "absolute"; + fakeInput.style.left = "-1000px"; + fakeInput.style.top = "-1000px"; + document.body.appendChild(fakeInput); + } } diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c index a4bed341c5..84f95eee3e 100644 --- a/gdk/broadway/broadwayd.c +++ b/gdk/broadway/broadwayd.c @@ -297,6 +297,9 @@ client_handle_request (BroadwayClient *client, case BROADWAY_REQUEST_FOCUS_WINDOW: broadway_server_focus_window (server, request->focus_window.id); break; + case BROADWAY_REQUEST_SET_SHOW_KEYBOARD: + broadway_server_set_show_keyboard (server, request->set_show_keyboard.show_keyboard); + break; default: g_warning ("Unknown request of type %d\n", request->base.type); } diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c index d85cfa522c..6389c7fdb4 100644 --- a/gdk/broadway/gdkbroadway-server.c +++ b/gdk/broadway/gdkbroadway-server.c @@ -794,3 +794,16 @@ _gdk_broadway_server_ungrab_pointer (GdkBroadwayServer *server, return status; } + +void +_gdk_broadway_server_set_show_keyboard (GdkBroadwayServer *server, + gboolean show) +{ + BroadwayRequestSetShowKeyboard msg; + + msg.show_keyboard = show; + gdk_broadway_server_send_message (server, msg, + BROADWAY_REQUEST_SET_SHOW_KEYBOARD); + + return TRUE; +} diff --git a/gdk/broadway/gdkbroadway-server.h b/gdk/broadway/gdkbroadway-server.h index 0ddf39e349..89a3076992 100644 --- a/gdk/broadway/gdkbroadway-server.h +++ b/gdk/broadway/gdkbroadway-server.h @@ -52,6 +52,8 @@ void _gdk_broadway_server_window_focus (GdkBroadwaySer void _gdk_broadway_server_window_set_transient_for (GdkBroadwayServer *server, gint id, gint parent); +void _gdk_broadway_server_set_show_keyboard (GdkBroadwayServer *server, + gboolean show_keyboard); gboolean _gdk_broadway_server_window_translate (GdkBroadwayServer *server, gint id, cairo_region_t *area, diff --git a/gdk/broadway/gdkbroadwaydisplay.h b/gdk/broadway/gdkbroadwaydisplay.h index 805e1deff0..6648a55a07 100644 --- a/gdk/broadway/gdkbroadwaydisplay.h +++ b/gdk/broadway/gdkbroadwaydisplay.h @@ -43,6 +43,11 @@ typedef struct _GdkBroadwayDisplayClass GdkBroadwayDisplayClass; GDK_AVAILABLE_IN_ALL GType gdk_broadway_display_get_type (void); +GDK_AVAILABLE_IN_3_12 +void gdk_broadway_display_show_keyboard (GdkBroadwayDisplay *display); +GDK_AVAILABLE_IN_3_12 +void gdk_broadway_display_hide_keyboard (GdkBroadwayDisplay *display); + G_END_DECLS #endif /* __GDK_BROADWAY_DISPLAY_H__ */ diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c index 94a324e071..c4f1d3122a 100644 --- a/gdk/broadway/gdkdisplay-broadway.c +++ b/gdk/broadway/gdkdisplay-broadway.c @@ -346,6 +346,22 @@ gdk_broadway_display_event_data_free (GdkDisplay *display, { } +void +gdk_broadway_display_show_keyboard (GdkBroadwayDisplay *display) +{ + g_return_if_fail (GDK_IS_BROADWAY_DISPLAY (display)); + + _gdk_broadway_server_set_show_keyboard (display->server, TRUE); +} + +void +gdk_broadway_display_hide_keyboard (GdkBroadwayDisplay *display) +{ + g_return_if_fail (GDK_IS_BROADWAY_DISPLAY (display)); + + _gdk_broadway_server_set_show_keyboard (display->server, FALSE); +} + static void gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class) { diff --git a/gtk/gtkimmodule.c b/gtk/gtkimmodule.c index 1660ba34e0..ab3442d8f6 100644 --- a/gtk/gtkimmodule.c +++ b/gtk/gtkimmodule.c @@ -45,6 +45,10 @@ #include "wayland/gdkwayland.h" #endif +#ifdef GDK_WINDOWING_BROADWAY +#include "broadway/gdkbroadway.h" +#endif + #ifdef GDK_WINDOWING_WIN32 #include "win32/gdkwin32.h" #endif @@ -381,6 +385,9 @@ gtk_im_module_initialize (void) #ifdef INCLUDE_IM_xim do_builtin (xim); #endif +#ifdef INCLUDE_IM_broadway + do_builtin (broadway); +#endif #undef do_builtin @@ -662,6 +669,11 @@ match_backend (GtkIMContextInfo *context) return GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()); #endif +#ifdef GDK_WINDOWING_BROADWAY + if (g_strcmp0 (context->context_id, "broadway") == 0) + return GDK_IS_BROADWAY_DISPLAY (gdk_display_get_default ()); +#endif + #ifdef GDK_WINDOWING_X11 if (g_strcmp0 (context->context_id, "xim") == 0) return GDK_IS_X11_DISPLAY (gdk_display_get_default ()); diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index e61a4b7be5..329624bb22 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -44,6 +44,10 @@ #include "wayland/gdkwayland.h" #endif +#ifdef GDK_WINDOWING_BROADWAY +#include "broadway/gdkbroadway.h" +#endif + #ifdef GDK_WINDOWING_QUARTZ #include "quartz/gdkquartz.h" #endif @@ -1670,11 +1674,22 @@ gtk_settings_get_for_screen (GdkScreen *screen) { #ifdef GDK_WINDOWING_QUARTZ if (GDK_IS_QUARTZ_SCREEN (screen)) - settings = g_object_new (GTK_TYPE_SETTINGS, - "gtk-key-theme-name", "Mac", - "gtk-shell-shows-app-menu", TRUE, - "gtk-shell-shows-menubar", TRUE, - NULL); + { + settings = g_object_new (GTK_TYPE_SETTINGS, + "gtk-key-theme-name", "Mac", + "gtk-shell-shows-app-menu", TRUE, + "gtk-shell-shows-menubar", TRUE, + NULL); + } + else +#endif +#ifdef GDK_WINDOWING_BROADWAY + if (GDK_IS_BROADWAY_DISPLAY (gdk_screen_get_display (screen))) + { + settings = g_object_new (GTK_TYPE_SETTINGS, + "gtk-im-module", "broadway", + NULL); + } else #endif settings = g_object_new (GTK_TYPE_SETTINGS, NULL); diff --git a/modules/input/Makefile.am b/modules/input/Makefile.am index 3ad28d1172..44df55f509 100644 --- a/modules/input/Makefile.am +++ b/modules/input/Makefile.am @@ -164,6 +164,19 @@ QUARTZ_MODULE = im-quartz.la endif endif +im_broadway_la_CPPFLAGS = $(AM_CPPFLAGS) +im_broadway_la_LDFLAGS = -rpath $(moduledir) -avoid-version -module $(no_undefined) +im_broadway_la_SOURCES = imbroadway.c +libstatic_im_broadway_la_SOURCES = $(im_broadway_la_SOURCES) +im_broadway_la_LIBADD = $(LDADDS) +if INCLUDE_IM_BROADWAY +STATIC_BROADWAY_MODULE = libstatic-im-broadway.la +else +if USE_BROADWAY +BROADWAY_MODULE = im-broadway.la +endif +endif + multipress_defs = -DMULTIPRESS_LOCALEDIR=\""$(mplocaledir)"\" -DMULTIPRESS_CONFDIR=\""$(sysconfdir)/gtk-2.0"\" im_multipress_la_CPPFLAGS = $(AM_CPPFLAGS) $(multipress_defs) libstatic_im_multipress_la_CPPFLAGS = $(im_multipress_la_CPPFLAGS) @@ -224,6 +237,7 @@ module_LTLIBRARIES = \ $(IPA_MODULE) \ $(MULTIPRESS_MODULE) \ $(QUARTZ_MODULE) \ + $(BROADWAY_MODULE) \ $(THAI_MODULE) \ $(TI_ER_MODULE) \ $(TI_ET_MODULE) \ @@ -241,6 +255,7 @@ noinst_LTLIBRARIES = \ $(STATIC_IPA_MODULE) \ $(STATIC_MULTIPRESS_MODULE) \ $(STATIC_QUARTZ_MODULE) \ + $(STATIC_BROADWAY_MODULE) \ $(STATIC_THAI_MODULE) \ $(STATIC_TI_ER_MODULE) \ $(STATIC_TI_ET_MODULE) \ diff --git a/modules/input/imbroadway.c b/modules/input/imbroadway.c new file mode 100644 index 0000000000..4e9c130977 --- /dev/null +++ b/modules/input/imbroadway.c @@ -0,0 +1,163 @@ +/* + * gtkimmodulebroadway + * Copyright (C) 2013 Alexander Larsson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * $Id:$ + */ + +#include "config.h" +#include <string.h> + +#include <gtk/gtk.h> +#include "gtk/gtkintl.h" +#include "gtk/gtkimmodule.h" + +#include "gdk/broadway/gdkbroadway.h" + +#define GTK_IM_CONTEXT_TYPE_BROADWAY (type_broadway) +#define GTK_IM_CONTEXT_BROADWAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_IM_CONTEXT_TYPE_BROADWAY, GtkIMContextBroadway)) +#define GTK_IM_CONTEXT_BROADWAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_IM_CONTEXT_TYPE_BROADWAY, GtkIMContextBroadwayClass)) + +typedef struct _GtkIMContextBroadway +{ + GtkIMContextSimple parent; + GdkWindow *client_window; +} GtkIMContextBroadway; + +typedef struct _GtkIMContextBroadwayClass +{ + GtkIMContextSimpleClass parent_class; +} GtkIMContextBroadwayClass; + +GType type_broadway = 0; +static GObjectClass *parent_class; + +static const GtkIMContextInfo imbroadway_info = +{ + "broadway", /* ID */ + "Broadway", /* Human readable name */ + GETTEXT_PACKAGE, /* Translation domain */ + GTK_LOCALEDIR, /* Dir for bindtextdomain (not strictly needed for "gtk+") */ + "", /* Languages for which this module is the default */ +}; + +static const GtkIMContextInfo *info_list[] = +{ + &imbroadway_info, +}; + +#ifndef INCLUDE_IM_broadway +#define MODULE_ENTRY(type,function) G_MODULE_EXPORT type im_module_ ## function +#else +#define MODULE_ENTRY(type, function) type _gtk_immodule_broadway_ ## function +#endif + +static void +broadway_set_client_window (GtkIMContext *context, GdkWindow *window) +{ + GtkIMContextBroadway *bw = GTK_IM_CONTEXT_BROADWAY (context); + + bw->client_window = window; +} + +static void +broadway_focus_in (GtkIMContext *context) +{ + GtkIMContextBroadway *bw = GTK_IM_CONTEXT_BROADWAY (context); + GdkDisplay *display; + + if (bw->client_window) + { + display = gdk_window_get_display (bw->client_window); + gdk_broadway_display_show_keyboard (GDK_BROADWAY_DISPLAY (display)); + } +} + +static void +broadway_focus_out (GtkIMContext *context) +{ + GtkIMContextBroadway *bw = GTK_IM_CONTEXT_BROADWAY (context); + GdkDisplay *display; + + if (bw->client_window) + { + display = gdk_window_get_display (bw->client_window); + gdk_broadway_display_hide_keyboard (GDK_BROADWAY_DISPLAY (display)); + } +} + +static void +gtk_im_context_broadway_class_init (GtkIMContextClass *klass) +{ + parent_class = g_type_class_peek_parent (klass); + + klass->focus_in = broadway_focus_in; + klass->focus_out = broadway_focus_out; + klass->set_client_window = broadway_set_client_window; +} + +static void +gtk_im_context_broadway_init (GtkIMContext *im_context) +{ +} + +static void +gtk_im_context_broadway_register_type (GTypeModule *module) +{ + const GTypeInfo object_info = + { + sizeof (GtkIMContextBroadwayClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gtk_im_context_broadway_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkIMContextBroadway), + 0, + (GInstanceInitFunc) gtk_im_context_broadway_init, + }; + + type_broadway = + g_type_module_register_type (module, + GTK_TYPE_IM_CONTEXT_SIMPLE, + "GtkIMContextBroadway", + &object_info, 0); +} + +MODULE_ENTRY (void, init) (GTypeModule * module) +{ + gtk_im_context_broadway_register_type (module); +} + +MODULE_ENTRY (void, exit) (void) +{ +} + +MODULE_ENTRY (void, list) (const GtkIMContextInfo *** contexts, int *n_contexts) +{ + *contexts = info_list; + *n_contexts = G_N_ELEMENTS (info_list); +} + +MODULE_ENTRY (GtkIMContext *, create) (const gchar * context_id) +{ + if (!strcmp (context_id, "broadway")) + return g_object_new (type_broadway, NULL); + else + return NULL; +} |