Compare commits
30 Commits
update-deb
...
click
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c0b55d7f8 | |||
| 72da6d02ae | |||
| 9c61d8de72 | |||
| 38133d326b | |||
| cc00fcb5c9 | |||
| 53f7a14717 | |||
| 922495ca06 | |||
| e5e2e08ff4 | |||
| c7c410210b | |||
| cb7c214aa0 | |||
| 6f5f49729c | |||
| 94c9442de1 | |||
| 8c044d0852 | |||
| 1f0cc0a5f3 | |||
| 5693ce3df7 | |||
| bcf04ab11e | |||
| 086f6bd772 | |||
| d0fa444a0e | |||
| cd81aeb286 | |||
| 7db33bc92e | |||
| fb6c501e44 | |||
| ce7b398f7b | |||
| 4d8d3a8109 | |||
| a183cf8b63 | |||
| f834edcf94 | |||
| 17802a9408 | |||
| ac1aad881c | |||
| 928110a92d | |||
| f6479fafe2 | |||
| 62b1c2ba84 |
20
autogen.sh
20
autogen.sh
@ -1,20 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# Run this to generate all the initial makefiles, etc.
|
|
||||||
|
|
||||||
srcdir=`dirname $0`
|
|
||||||
test -z "$srcdir" && srcdir=.
|
|
||||||
|
|
||||||
PKG_NAME="eekboard"
|
|
||||||
|
|
||||||
(test -f $srcdir/configure.ac \
|
|
||||||
&& test -f $srcdir/README.md ) || {
|
|
||||||
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
|
|
||||||
echo " top-level $PKG_NAME directory"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4"
|
|
||||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
|
||||||
REQUIRED_AUTOCONF_VERSION=2.60
|
|
||||||
|
|
||||||
. gnome-autogen.sh
|
|
||||||
52
data/icons/keyboard-mode-symbolic.svg
Normal file
52
data/icons/keyboard-mode-symbolic.svg
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
id="svg4043"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 4.2333331 4.2333093"
|
||||||
|
height="4.2333093mm"
|
||||||
|
width="4.2333331mm">
|
||||||
|
<defs
|
||||||
|
id="defs4037" />
|
||||||
|
<metadata
|
||||||
|
id="metadata4040">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
transform="translate(-86.329776,-68.097636)"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
style="stroke-width:1.00004983;fill:#2e3436;fill-opacity:1"
|
||||||
|
transform="matrix(0.99990029,0,0,1,-7.1823833,-1.8799927)"
|
||||||
|
id="g842">
|
||||||
|
<g
|
||||||
|
style="stroke-width:1.00004983;fill:#2e3436;fill-opacity:1"
|
||||||
|
id="g836">
|
||||||
|
<path
|
||||||
|
id="path5166"
|
||||||
|
d="m 95.636719,69.978516 c -1.165869,0 -2.115235,0.949365 -2.115235,2.115234 0,1.165869 0.949366,2.117188 2.115235,2.117188 1.165869,0 2.117187,-0.951319 2.117187,-2.117188 0,-1.165869 -0.951318,-2.115234 -2.117187,-2.115234 z m 0,0.529296 c 0.879886,0 1.58789,0.706052 1.58789,1.585938 0,0.879886 -0.708004,1.587891 -1.58789,1.587891 -0.879886,0 -1.585938,-0.708005 -1.585938,-1.587891 0,-0.879886 0.706052,-1.585937 1.585938,-1.585938 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52919304;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26459652;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 95.636719,70.109375 c -0.144398,0 -0.27248,0.07793 -0.373047,0.189453 -0.100567,0.111521 -0.18209,0.261405 -0.25,0.439453 -0.135821,0.356096 -0.214844,0.830395 -0.214844,1.355469 0,0.525074 0.07902,1.001326 0.214844,1.357422 0.06791,0.178048 0.149433,0.327932 0.25,0.439453 0.100567,0.111521 0.228649,0.1875 0.373047,0.1875 0.144397,0 0.27248,-0.07598 0.373047,-0.1875 0.100566,-0.111521 0.182089,-0.261405 0.25,-0.439453 0.135821,-0.356096 0.216797,-0.832348 0.216796,-1.357422 0,-0.525074 -0.08097,-0.999373 -0.216796,-1.355469 -0.06791,-0.178048 -0.149434,-0.327932 -0.25,-0.439453 -0.100567,-0.111521 -0.22865,-0.189453 -0.373047,-0.189453 z m 0,0.265625 c 0.05067,0 0.109272,0.02564 0.177734,0.101562 0.06846,0.07592 0.139293,0.198356 0.199219,0.355469 0.119851,0.314227 0.197266,0.763915 0.197266,1.261719 0,0.497804 -0.07742,0.949446 -0.197266,1.263672 -0.05993,0.157113 -0.130756,0.279549 -0.199219,0.355469 -0.06846,0.07592 -0.12706,0.101562 -0.177734,0.101562 -0.05067,0 -0.107319,-0.02564 -0.175781,-0.101562 -0.06846,-0.07592 -0.139294,-0.198356 -0.199219,-0.355469 C 95.141867,73.043196 95.0625,72.591554 95.0625,72.09375 c 0,-0.497804 0.07937,-0.947492 0.199219,-1.261719 0.05993,-0.157113 0.130756,-0.279549 0.199219,-0.355469 C 95.5294,70.400643 95.586045,70.375 95.636719,70.375 Z"
|
||||||
|
id="circle5168" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26459652;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 93.697266,71.962891 v 0.263671 h 3.96875 v -0.263671 z"
|
||||||
|
id="path5170" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.6 KiB |
@ -249,7 +249,7 @@
|
|||||||
<symbol label="⌨" icon="input-keyboard-symbolic" tooltip="Change keyboard">cycle-keyboard</symbol>
|
<symbol label="⌨" icon="input-keyboard-symbolic" tooltip="Change keyboard">cycle-keyboard</symbol>
|
||||||
</key>
|
</key>
|
||||||
<key keycode="150" name="I150">
|
<key keycode="150" name="I150">
|
||||||
<symbol label="☺" icon="preferences-system-symbolic" tooltip="Setup">preferences</symbol>
|
<symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
|
||||||
</key>
|
</key>
|
||||||
<key keycode="37" name="LCTL">
|
<key keycode="37" name="LCTL">
|
||||||
<keysym keyval="65507">Control_L</keysym>
|
<keysym keyval="65507">Control_L</keysym>
|
||||||
|
|||||||
@ -34,5 +34,6 @@
|
|||||||
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/zh-bopomofo.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/zh-bopomofo.xml</file>
|
||||||
<file>icons/key-enter.svg</file>
|
<file>icons/key-enter.svg</file>
|
||||||
<file>icons/key-shift.svg</file>
|
<file>icons/key-shift.svg</file>
|
||||||
|
<file>icons/keyboard-mode-symbolic.svg</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|||||||
@ -23,12 +23,10 @@
|
|||||||
* @short_description: a #GtkWidget displaying #EekKeyboard
|
* @short_description: a #GtkWidget displaying #EekKeyboard
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBCANBERRA
|
#ifdef HAVE_GSOUND
|
||||||
#include <canberra-gtk.h>
|
#include <gsound.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -57,10 +55,10 @@ typedef struct _EekGtkKeyboardPrivate
|
|||||||
{
|
{
|
||||||
EekRenderer *renderer;
|
EekRenderer *renderer;
|
||||||
EekKeyboard *keyboard;
|
EekKeyboard *keyboard;
|
||||||
gulong key_locked_handler;
|
|
||||||
gulong key_unlocked_handler;
|
|
||||||
gulong symbol_index_changed_handler;
|
|
||||||
EekTheme *theme;
|
EekTheme *theme;
|
||||||
|
#ifdef HAVE_GSOUND
|
||||||
|
GSoundContext *sound_ctx;
|
||||||
|
#endif
|
||||||
|
|
||||||
GdkEventSequence *sequence; // unowned reference
|
GdkEventSequence *sequence; // unowned reference
|
||||||
} EekGtkKeyboardPrivate;
|
} EekGtkKeyboardPrivate;
|
||||||
@ -124,6 +122,8 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
|||||||
eek_renderer_set_allocation_size (priv->renderer,
|
eek_renderer_set_allocation_size (priv->renderer,
|
||||||
allocation.width,
|
allocation.width,
|
||||||
allocation.height);
|
allocation.height);
|
||||||
|
eek_renderer_set_scale_factor (priv->renderer,
|
||||||
|
gtk_widget_get_scale_factor (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
eek_renderer_render_keyboard (priv->renderer, cr);
|
eek_renderer_render_keyboard (priv->renderer, cr);
|
||||||
@ -330,15 +330,21 @@ eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
|
|||||||
EekKeyboard *keyboard)
|
EekKeyboard *keyboard)
|
||||||
{
|
{
|
||||||
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||||
|
|
||||||
|
if (priv->keyboard == keyboard)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (priv->keyboard) {
|
||||||
|
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
|
||||||
|
g_object_unref (priv->keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
priv->keyboard = g_object_ref (keyboard);
|
priv->keyboard = g_object_ref (keyboard);
|
||||||
|
|
||||||
priv->key_locked_handler =
|
|
||||||
g_signal_connect (priv->keyboard, "key-locked",
|
g_signal_connect (priv->keyboard, "key-locked",
|
||||||
G_CALLBACK(on_key_locked), self);
|
G_CALLBACK(on_key_locked), self);
|
||||||
priv->key_unlocked_handler =
|
|
||||||
g_signal_connect (priv->keyboard, "key-unlocked",
|
g_signal_connect (priv->keyboard, "key-unlocked",
|
||||||
G_CALLBACK(on_key_unlocked), self);
|
G_CALLBACK(on_key_unlocked), self);
|
||||||
priv->symbol_index_changed_handler =
|
|
||||||
g_signal_connect (priv->keyboard, "symbol-index-changed",
|
g_signal_connect (priv->keyboard, "symbol-index-changed",
|
||||||
G_CALLBACK(on_symbol_index_changed), self);
|
G_CALLBACK(on_symbol_index_changed), self);
|
||||||
}
|
}
|
||||||
@ -374,21 +380,9 @@ eek_gtk_keyboard_dispose (GObject *object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (priv->keyboard) {
|
if (priv->keyboard) {
|
||||||
if (g_signal_handler_is_connected (priv->keyboard,
|
|
||||||
priv->key_locked_handler))
|
|
||||||
g_signal_handler_disconnect (priv->keyboard,
|
|
||||||
priv->key_locked_handler);
|
|
||||||
if (g_signal_handler_is_connected (priv->keyboard,
|
|
||||||
priv->key_unlocked_handler))
|
|
||||||
g_signal_handler_disconnect (priv->keyboard,
|
|
||||||
priv->key_unlocked_handler);
|
|
||||||
if (g_signal_handler_is_connected (priv->keyboard,
|
|
||||||
priv->symbol_index_changed_handler))
|
|
||||||
g_signal_handler_disconnect (priv->keyboard,
|
|
||||||
priv->symbol_index_changed_handler);
|
|
||||||
|
|
||||||
GList *list, *head;
|
GList *list, *head;
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
|
||||||
list = eek_keyboard_get_pressed_keys (priv->keyboard);
|
list = eek_keyboard_get_pressed_keys (priv->keyboard);
|
||||||
for (head = list; head; head = g_list_next (head)) {
|
for (head = list; head; head = g_list_next (head)) {
|
||||||
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
|
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
|
||||||
@ -445,7 +439,16 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
|
|||||||
static void
|
static void
|
||||||
eek_gtk_keyboard_init (EekGtkKeyboard *self)
|
eek_gtk_keyboard_init (EekGtkKeyboard *self)
|
||||||
{
|
{
|
||||||
/* void */
|
#if HAVE_GSOUND
|
||||||
|
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
|
priv->sound_ctx = gsound_context_new(NULL, &err);
|
||||||
|
if (!priv->sound_ctx) {
|
||||||
|
g_warning ("GSound init failed: %s", err->message);
|
||||||
|
g_clear_error (&err);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -484,45 +487,6 @@ magnify_bounds (GtkWidget *self,
|
|||||||
large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
|
large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Alleviate the asymmetry between drawing a pressed key and a released key,
|
|
||||||
* and consistently draw to the exact same area.
|
|
||||||
*
|
|
||||||
* By saving the dirty rectangle we can limit drawing of the backbuffer to
|
|
||||||
* the screen as well, eg gdk_window_invalidate_rect() instead of
|
|
||||||
* gtk_widget_queue_draw() which redraws the entire widget.
|
|
||||||
*
|
|
||||||
* b1 is mandatory, b2 is optional
|
|
||||||
*/
|
|
||||||
static GdkRectangle
|
|
||||||
clip_bounds_to_dirty_rectangle (cairo_t *cr, EekBounds *b1, EekBounds *b2)
|
|
||||||
{
|
|
||||||
if (b2)
|
|
||||||
cairo_rectangle (cr, b2->x, b2->y, b2->width, b2->height);
|
|
||||||
|
|
||||||
cairo_rectangle (cr, b1->x, b1->y, b1->width, b1->height);
|
|
||||||
cairo_clip (cr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* save the clipped region to a bounding box so we can limit
|
|
||||||
* the drawing of the backbuffer to the screen to the same area
|
|
||||||
*/
|
|
||||||
cairo_rectangle_t bbox;
|
|
||||||
|
|
||||||
cairo_clip_extents (cr, &bbox.x, &bbox.y, &bbox.width, &bbox.height);
|
|
||||||
|
|
||||||
/* convert double to int, making sure r strictly covers bbox to avoid
|
|
||||||
* artefacts. floor() is unnecessary, ceil() is not */
|
|
||||||
GdkRectangle r = {
|
|
||||||
floor (bbox.x),
|
|
||||||
floor (bbox.y),
|
|
||||||
ceil (bbox.width),
|
|
||||||
ceil (bbox.height)
|
|
||||||
};
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
render_pressed_key (GtkWidget *widget,
|
render_pressed_key (GtkWidget *widget,
|
||||||
EekKey *key)
|
EekKey *key)
|
||||||
@ -539,12 +503,6 @@ render_pressed_key (GtkWidget *widget,
|
|||||||
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
||||||
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
|
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
|
||||||
|
|
||||||
/*
|
|
||||||
* clip to limit drawing to backbuffer and save clip region to dirty_rect
|
|
||||||
* to limit redrawing of the backbuffer to the same area
|
|
||||||
*/
|
|
||||||
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle (cr, &bounds, &large_bounds);
|
|
||||||
|
|
||||||
cairo_save (cr);
|
cairo_save (cr);
|
||||||
cairo_translate (cr, bounds.x, bounds.y);
|
cairo_translate (cr, bounds.x, bounds.y);
|
||||||
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
||||||
@ -558,9 +516,6 @@ render_pressed_key (GtkWidget *widget,
|
|||||||
gdk_window_end_draw_frame (window, context);
|
gdk_window_end_draw_frame (window, context);
|
||||||
|
|
||||||
cairo_region_destroy (region);
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
/* force immediate drawing of the backbuffer to the screen */
|
|
||||||
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -578,21 +533,12 @@ render_locked_key (GtkWidget *widget,
|
|||||||
|
|
||||||
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
||||||
|
|
||||||
/*
|
|
||||||
* clip to limit drawing to backbuffer and save clip region to dirty_rect
|
|
||||||
* to limit redrawing of the backbuffer to the same area
|
|
||||||
*/
|
|
||||||
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle (cr, &bounds, NULL);
|
|
||||||
|
|
||||||
cairo_translate (cr, bounds.x, bounds.y);
|
cairo_translate (cr, bounds.x, bounds.y);
|
||||||
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
||||||
|
|
||||||
gdk_window_end_draw_frame (window, context);
|
gdk_window_end_draw_frame (window, context);
|
||||||
|
|
||||||
cairo_region_destroy (region);
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
/* force immediate drawing of the backbuffer to the screen */
|
|
||||||
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -611,20 +557,11 @@ render_released_key (GtkWidget *widget,
|
|||||||
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
||||||
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
|
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
|
||||||
|
|
||||||
/*
|
|
||||||
* clip to limit drawing to backbuffer and save clip region to dirty_rect
|
|
||||||
* to limit redrawing of the backbuffer to the same area
|
|
||||||
*/
|
|
||||||
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle(cr, &bounds, &large_bounds);
|
|
||||||
|
|
||||||
eek_renderer_render_keyboard (priv->renderer, cr);
|
eek_renderer_render_keyboard (priv->renderer, cr);
|
||||||
|
|
||||||
gdk_window_end_draw_frame (window, context);
|
gdk_window_end_draw_frame (window, context);
|
||||||
|
|
||||||
cairo_region_destroy (region);
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
/* force immediate drawing of the backbuffer to the screen */
|
|
||||||
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -638,12 +575,13 @@ on_key_pressed (EekKey *key,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
render_pressed_key (GTK_WIDGET(self), key);
|
render_pressed_key (GTK_WIDGET(self), key);
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET(self));
|
||||||
|
|
||||||
#if HAVE_LIBCANBERRA
|
#if HAVE_GSOUND
|
||||||
ca_gtk_play_for_widget (widget, 0,
|
g_return_if_fail (GSOUND_IS_CONTEXT (priv->sound_ctx));
|
||||||
CA_PROP_EVENT_ID, "button-pressed",
|
gsound_context_play_simple(priv->sound_ctx, NULL, NULL,
|
||||||
CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
|
GSOUND_ATTR_EVENT_ID, "button-pressed",
|
||||||
CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
|
GSOUND_ATTR_EVENT_DESCRIPTION, "Button pressed",
|
||||||
NULL);
|
NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -659,12 +597,13 @@ on_key_released (EekKey *key,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
render_released_key (GTK_WIDGET(self), key);
|
render_released_key (GTK_WIDGET(self), key);
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET(self));
|
||||||
|
|
||||||
#if HAVE_LIBCANBERRA
|
#if HAVE_GSOUND
|
||||||
ca_gtk_play_for_widget (widget, 0,
|
g_return_if_fail (GSOUND_IS_CONTEXT (priv->sound_ctx));
|
||||||
CA_PROP_EVENT_ID, "button-released",
|
gsound_context_play_simple(priv->sound_ctx, NULL, NULL,
|
||||||
CA_PROP_EVENT_DESCRIPTION, "virtual key pressed",
|
GSOUND_ATTR_EVENT_ID, "button-released",
|
||||||
CA_PROP_APPLICATION_ID, "org.fedorahosted.Eekboard",
|
GSOUND_ATTR_EVENT_DESCRIPTION, "Button released",
|
||||||
NULL);
|
NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -682,6 +621,7 @@ on_key_locked (EekKeyboard *keyboard,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
render_locked_key (widget, key);
|
render_locked_key (widget, key);
|
||||||
|
gtk_widget_queue_draw (widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -697,6 +637,7 @@ on_key_unlocked (EekKeyboard *keyboard,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
render_released_key (widget, key);
|
render_released_key (widget, key);
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET(widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@ -30,66 +30,29 @@
|
|||||||
|
|
||||||
G_DEFINE_TYPE (EekGtkRenderer, eek_gtk_renderer, EEK_TYPE_RENDERER);
|
G_DEFINE_TYPE (EekGtkRenderer, eek_gtk_renderer, EEK_TYPE_RENDERER);
|
||||||
|
|
||||||
static cairo_surface_t *
|
|
||||||
pixbuf_to_cairo_surface (GdkPixbuf *pixbuf)
|
|
||||||
{
|
|
||||||
cairo_surface_t *dummy_surface;
|
|
||||||
cairo_pattern_t *pattern;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
dummy_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
|
|
||||||
|
|
||||||
cr = cairo_create (dummy_surface);
|
|
||||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
|
||||||
pattern = cairo_get_source (cr);
|
|
||||||
cairo_pattern_get_surface (pattern, &surface);
|
|
||||||
cairo_surface_reference (surface);
|
|
||||||
cairo_destroy (cr);
|
|
||||||
cairo_surface_destroy (dummy_surface);
|
|
||||||
|
|
||||||
return surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cairo_surface_t *
|
static cairo_surface_t *
|
||||||
eek_gtk_renderer_real_get_icon_surface (EekRenderer *self,
|
eek_gtk_renderer_real_get_icon_surface (EekRenderer *self,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
gint size)
|
gint size,
|
||||||
|
gint scale)
|
||||||
{
|
{
|
||||||
GdkPixbuf *pixbuf;
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
|
|
||||||
gchar *path = g_strconcat("/sm/puri/squeekboard/icons/", icon_name, ".svg", NULL);
|
surface = gtk_icon_theme_load_surface (gtk_icon_theme_get_default (),
|
||||||
|
|
||||||
pixbuf = gdk_pixbuf_new_from_resource_at_scale (path, size, size,
|
|
||||||
TRUE, &error);
|
|
||||||
|
|
||||||
if (pixbuf != NULL)
|
|
||||||
goto found;
|
|
||||||
else {
|
|
||||||
g_warning ("can't get icon pixbuf for %s: %s", path, error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
error = NULL;
|
|
||||||
}
|
|
||||||
g_free(path);
|
|
||||||
|
|
||||||
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
|
|
||||||
icon_name,
|
icon_name,
|
||||||
size,
|
size,
|
||||||
|
scale,
|
||||||
|
NULL,
|
||||||
0,
|
0,
|
||||||
&error);
|
&error);
|
||||||
if (pixbuf == NULL) {
|
if (surface == NULL) {
|
||||||
g_warning ("can't get icon pixbuf for %s: %s",
|
g_warning ("can't get icon surface for %s: %s",
|
||||||
icon_name,
|
icon_name,
|
||||||
error->message);
|
error->message);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
found:
|
|
||||||
surface = pixbuf_to_cairo_surface (pixbuf);
|
|
||||||
g_object_unref (pixbuf);
|
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +67,9 @@ eek_gtk_renderer_class_init (EekGtkRendererClass *klass)
|
|||||||
static void
|
static void
|
||||||
eek_gtk_renderer_init (EekGtkRenderer *self)
|
eek_gtk_renderer_init (EekGtkRenderer *self)
|
||||||
{
|
{
|
||||||
|
GtkIconTheme *theme = gtk_icon_theme_get_default ();
|
||||||
|
|
||||||
|
gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
|
||||||
}
|
}
|
||||||
|
|
||||||
EekRenderer *
|
EekRenderer *
|
||||||
|
|||||||
@ -70,7 +70,7 @@ struct _EekKeyboardPrivate
|
|||||||
EekLayout *layout;
|
EekLayout *layout;
|
||||||
EekModifierBehavior modifier_behavior;
|
EekModifierBehavior modifier_behavior;
|
||||||
EekModifierType modifiers;
|
EekModifierType modifiers;
|
||||||
EekModifierType old_level;
|
unsigned int old_level;
|
||||||
GList *pressed_keys;
|
GList *pressed_keys;
|
||||||
GList *locked_keys;
|
GList *locked_keys;
|
||||||
GArray *outline_array;
|
GArray *outline_array;
|
||||||
@ -259,7 +259,7 @@ set_level_from_modifiers (EekKeyboard *self, EekKey *key)
|
|||||||
|
|
||||||
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
|
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
|
||||||
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
|
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
|
||||||
else if (level == VIEW_LETTERS_UPPER)
|
else
|
||||||
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
|
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
|
||||||
|
|
||||||
priv->old_level = level;
|
priv->old_level = level;
|
||||||
|
|||||||
@ -48,6 +48,7 @@ typedef struct _EekRendererPrivate
|
|||||||
gdouble allocation_width;
|
gdouble allocation_width;
|
||||||
gdouble allocation_height;
|
gdouble allocation_height;
|
||||||
gdouble scale;
|
gdouble scale;
|
||||||
|
gint scale_factor; /* the outputs scale factor */
|
||||||
|
|
||||||
PangoFontDescription *ascii_font;
|
PangoFontDescription *ascii_font;
|
||||||
PangoFontDescription *font;
|
PangoFontDescription *font;
|
||||||
@ -499,21 +500,21 @@ render_key (EekRenderer *self,
|
|||||||
|
|
||||||
#define SCALE 0.4
|
#define SCALE 0.4
|
||||||
if (eek_symbol_get_icon_name (symbol)) {
|
if (eek_symbol_get_icon_name (symbol)) {
|
||||||
|
gint scale = priv->scale_factor;
|
||||||
cairo_surface_t *icon_surface =
|
cairo_surface_t *icon_surface =
|
||||||
eek_renderer_get_icon_surface (self,
|
eek_renderer_get_icon_surface (self,
|
||||||
eek_symbol_get_icon_name (symbol),
|
eek_symbol_get_icon_name (symbol),
|
||||||
MIN(bounds.width, bounds.height));
|
SCALE * MIN(bounds.width, bounds.height),
|
||||||
|
scale);
|
||||||
if (icon_surface) {
|
if (icon_surface) {
|
||||||
gint width = cairo_image_surface_get_width (icon_surface);
|
gint width = cairo_image_surface_get_width (icon_surface);
|
||||||
gint height = cairo_image_surface_get_height (icon_surface);
|
gint height = cairo_image_surface_get_height (icon_surface);
|
||||||
|
|
||||||
cairo_save (cr);
|
cairo_save (cr);
|
||||||
cairo_translate (cr,
|
cairo_translate (cr,
|
||||||
(bounds.width - width * SCALE) / 2,
|
(bounds.width - width / scale) / 2,
|
||||||
(bounds.height - height * SCALE) / 2);
|
(bounds.height - height / scale) / 2);
|
||||||
cairo_rectangle (cr, 0, 0, width, height);
|
cairo_rectangle (cr, 0, 0, width, height);
|
||||||
cairo_scale (cr, SCALE, SCALE);
|
|
||||||
cairo_clip (cr);
|
cairo_clip (cr);
|
||||||
/* Draw the shape of the icon using the foreground color */
|
/* Draw the shape of the icon using the foreground color */
|
||||||
cairo_set_source_rgba (cr, foreground.red,
|
cairo_set_source_rgba (cr, foreground.red,
|
||||||
@ -844,6 +845,7 @@ eek_renderer_init (EekRenderer *self)
|
|||||||
priv->allocation_width = 0.0;
|
priv->allocation_width = 0.0;
|
||||||
priv->allocation_height = 0.0;
|
priv->allocation_height = 0.0;
|
||||||
priv->scale = 1.0;
|
priv->scale = 1.0;
|
||||||
|
priv->scale_factor = 1;
|
||||||
priv->font = NULL;
|
priv->font = NULL;
|
||||||
priv->outline_surface_cache =
|
priv->outline_surface_cache =
|
||||||
g_hash_table_new_full (g_direct_hash,
|
g_hash_table_new_full (g_direct_hash,
|
||||||
@ -1028,6 +1030,15 @@ eek_renderer_get_scale (EekRenderer *renderer)
|
|||||||
return priv->scale;
|
return priv->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale)
|
||||||
|
{
|
||||||
|
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
||||||
|
|
||||||
|
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
|
||||||
|
priv->scale_factor = scale;
|
||||||
|
}
|
||||||
|
|
||||||
PangoLayout *
|
PangoLayout *
|
||||||
eek_renderer_create_pango_layout (EekRenderer *renderer)
|
eek_renderer_create_pango_layout (EekRenderer *renderer)
|
||||||
{
|
{
|
||||||
@ -1071,7 +1082,8 @@ eek_renderer_render_key_outline (EekRenderer *renderer,
|
|||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
eek_renderer_get_icon_surface (EekRenderer *renderer,
|
eek_renderer_get_icon_surface (EekRenderer *renderer,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
gint size)
|
gint size,
|
||||||
|
gint scale)
|
||||||
{
|
{
|
||||||
EekRendererClass *klass;
|
EekRendererClass *klass;
|
||||||
|
|
||||||
@ -1079,7 +1091,7 @@ eek_renderer_get_icon_surface (EekRenderer *renderer,
|
|||||||
|
|
||||||
klass = EEK_RENDERER_GET_CLASS(renderer);
|
klass = EEK_RENDERER_GET_CLASS(renderer);
|
||||||
if (klass->get_icon_surface)
|
if (klass->get_icon_surface)
|
||||||
return klass->get_icon_surface (renderer, icon_name, size);
|
return klass->get_icon_surface (renderer, icon_name, size, scale);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,8 @@ struct _EekRendererClass
|
|||||||
|
|
||||||
cairo_surface_t *(* get_icon_surface) (EekRenderer *self,
|
cairo_surface_t *(* get_icon_surface) (EekRenderer *self,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
gint size);
|
gint size,
|
||||||
|
gint scale);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* padding */
|
/* padding */
|
||||||
@ -81,6 +82,8 @@ void eek_renderer_get_key_bounds (EekRenderer *renderer,
|
|||||||
gboolean rotate);
|
gboolean rotate);
|
||||||
|
|
||||||
gdouble eek_renderer_get_scale (EekRenderer *renderer);
|
gdouble eek_renderer_get_scale (EekRenderer *renderer);
|
||||||
|
void eek_renderer_set_scale_factor (EekRenderer *renderer,
|
||||||
|
gint scale);
|
||||||
|
|
||||||
PangoLayout *eek_renderer_create_pango_layout
|
PangoLayout *eek_renderer_create_pango_layout
|
||||||
(EekRenderer *renderer);
|
(EekRenderer *renderer);
|
||||||
@ -103,7 +106,8 @@ void eek_renderer_render_key (EekRenderer *renderer,
|
|||||||
|
|
||||||
cairo_surface_t *eek_renderer_get_icon_surface (EekRenderer *renderer,
|
cairo_surface_t *eek_renderer_get_icon_surface (EekRenderer *renderer,
|
||||||
const gchar *icon_name,
|
const gchar *icon_name,
|
||||||
gint size);
|
gint size,
|
||||||
|
gint scale);
|
||||||
|
|
||||||
void eek_renderer_render_keyboard (EekRenderer *renderer,
|
void eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||||
cairo_t *cr);
|
cairo_t *cr);
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
# Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
# Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
|
|
||||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
# 02110-1301 USA
|
|
||||||
|
|
||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
libdir=@libdir@
|
|
||||||
includedir=@includedir@
|
|
||||||
|
|
||||||
Name: libeek-xkb
|
|
||||||
Description: A Library to Create Keyboard-like UI (XKB Support)
|
|
||||||
URL: http://fedorahosted.org/eekboard/
|
|
||||||
Version: @VERSION@
|
|
||||||
Requires: eek-@EEK_API_VERSION@ gtk+-x11-@GTK_API_VERSION@
|
|
||||||
Libs: -L${libdir} -leek-xkb
|
|
||||||
Cflags: -I${includedir}/eek-@EEK_API_VERSION@
|
|
||||||
@ -1,684 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:eek-xkb-layout
|
|
||||||
* @short_description: Layout engine using XKB configuration
|
|
||||||
*
|
|
||||||
* The #EekXkbLayout inherits #EekLayout class and arranges keyboard
|
|
||||||
* elements using XKB.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif /* HAVE_CONFIG_H */
|
|
||||||
|
|
||||||
#include "eek-xkb-layout.h"
|
|
||||||
|
|
||||||
#include <X11/keysym.h>
|
|
||||||
#include <X11/extensions/XKBgeom.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <gio/gio.h>
|
|
||||||
|
|
||||||
#include "eek-keyboard.h"
|
|
||||||
#include "eek-section.h"
|
|
||||||
#include "eek-key.h"
|
|
||||||
#include "eek-keysym.h"
|
|
||||||
|
|
||||||
#define XKB_COMPONENT_MASK (XkbGBN_GeometryMask | \
|
|
||||||
XkbGBN_KeyNamesMask | \
|
|
||||||
XkbGBN_OtherNamesMask | \
|
|
||||||
XkbGBN_SymbolsMask | \
|
|
||||||
XkbGBN_IndicatorMapMask)
|
|
||||||
|
|
||||||
static void initable_iface_init (GInitableIface *initable_iface);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PROP_0,
|
|
||||||
PROP_DISPLAY,
|
|
||||||
PROP_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _EekXkbLayoutPrivate
|
|
||||||
{
|
|
||||||
/* Configuration names that should synch'ed to the symbolic names
|
|
||||||
in priv->xkb->names. Since we use GLib's memory allocator,
|
|
||||||
don't store any address returned from the X server here. */
|
|
||||||
XkbComponentNamesRec names;
|
|
||||||
|
|
||||||
Display *display;
|
|
||||||
|
|
||||||
/* Actual XKB configuration of DISPLAY. */
|
|
||||||
XkbDescRec *xkb;
|
|
||||||
|
|
||||||
/* Hash table to cache orefs by shape address. */
|
|
||||||
GHashTable *shape_oref_hash;
|
|
||||||
|
|
||||||
gint scale_numerator;
|
|
||||||
gint scale_denominator;
|
|
||||||
} EekXkbLayoutPrivate;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_EXTENDED (EekXkbLayout, eek_xkb_layout, EEK_TYPE_LAYOUT,
|
|
||||||
0, /* GTypeFlags */
|
|
||||||
G_ADD_PRIVATE(EekXkbLayout)
|
|
||||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
|
||||||
initable_iface_init))
|
|
||||||
|
|
||||||
static guint find_keycode (EekXkbLayout *layout,
|
|
||||||
gchar *key_name);
|
|
||||||
|
|
||||||
static gboolean get_keyboard_from_server (EekXkbLayout *layout,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
static gboolean get_names_from_server (EekXkbLayout *layout,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
static void setup_scaling (EekXkbLayout *layout,
|
|
||||||
gdouble width,
|
|
||||||
gdouble height);
|
|
||||||
|
|
||||||
G_INLINE_FUNC gint
|
|
||||||
xkb_to_pixmap_coord (EekXkbLayout *layout,
|
|
||||||
gint n)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
return n * priv->scale_numerator / priv->scale_denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_INLINE_FUNC gdouble
|
|
||||||
xkb_to_pixmap_double (EekXkbLayout *layout,
|
|
||||||
gdouble d)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
return d * priv->scale_numerator / priv->scale_denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
create_key (EekXkbLayout *layout,
|
|
||||||
EekKeyboard *keyboard,
|
|
||||||
EekSection *section,
|
|
||||||
gint column,
|
|
||||||
gint row,
|
|
||||||
gdouble x,
|
|
||||||
gdouble y,
|
|
||||||
XkbKeyRec *xkbkey)
|
|
||||||
{
|
|
||||||
XkbGeometryRec *xkbgeometry;
|
|
||||||
XkbBoundsRec *xkbbounds;
|
|
||||||
XkbShapeRec *xkbshape;
|
|
||||||
XkbOutlineRec *xkboutline;
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
EekKey *key;
|
|
||||||
EekBounds bounds;
|
|
||||||
EekSymbolMatrix *matrix = NULL;
|
|
||||||
gchar name[XkbKeyNameLength + 1];
|
|
||||||
KeyCode keycode;
|
|
||||||
gint num_groups, num_levels;
|
|
||||||
guint oref;
|
|
||||||
gpointer v;
|
|
||||||
|
|
||||||
xkbgeometry = priv->xkb->geom;
|
|
||||||
xkbshape = &xkbgeometry->shapes[xkbkey->shape_ndx];
|
|
||||||
if (g_hash_table_lookup_extended (priv->shape_oref_hash, xkbshape,
|
|
||||||
NULL, &v)) {
|
|
||||||
oref = GPOINTER_TO_UINT(v);
|
|
||||||
} else {
|
|
||||||
EekOutline *outline;
|
|
||||||
|
|
||||||
xkboutline = xkbshape->primary == NULL ? &xkbshape->outlines[0] :
|
|
||||||
xkbshape->primary;
|
|
||||||
|
|
||||||
outline = g_slice_new (EekOutline);
|
|
||||||
outline->corner_radius = xkb_to_pixmap_coord(layout,
|
|
||||||
xkboutline->corner_radius);
|
|
||||||
|
|
||||||
if (xkboutline->num_points <= 2) { /* rectangular */
|
|
||||||
gdouble x1, y1, x2, y2;
|
|
||||||
|
|
||||||
outline->num_points = 4;
|
|
||||||
outline->points = g_slice_alloc0 (sizeof (EekPoint) *
|
|
||||||
outline->num_points);
|
|
||||||
if (xkboutline->num_points == 1) {
|
|
||||||
x1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.x1);
|
|
||||||
y1 = xkb_to_pixmap_coord(layout, xkbshape->bounds.y1);
|
|
||||||
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
|
|
||||||
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
|
|
||||||
} else {
|
|
||||||
x1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].x);
|
|
||||||
y1 = xkb_to_pixmap_coord(layout, xkboutline->points[0].y);
|
|
||||||
x2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].x);
|
|
||||||
y2 = xkb_to_pixmap_coord(layout, xkboutline->points[1].y);
|
|
||||||
}
|
|
||||||
outline->points[0].x = outline->points[3].x = x1;
|
|
||||||
outline->points[0].y = outline->points[1].y = y1;
|
|
||||||
outline->points[1].x = outline->points[2].x = x2;
|
|
||||||
outline->points[2].y = outline->points[3].y = y2;
|
|
||||||
} else { /* polygon */
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
outline->num_points = xkboutline->num_points;
|
|
||||||
outline->points = g_new0 (EekPoint, outline->num_points);
|
|
||||||
for (i = 0; i < xkboutline->num_points; i++) {
|
|
||||||
outline->points[i].x =
|
|
||||||
xkb_to_pixmap_coord(layout, xkboutline->points[i].x);
|
|
||||||
outline->points[i].y =
|
|
||||||
xkb_to_pixmap_coord(layout, xkboutline->points[i].y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
oref = eek_keyboard_add_outline (keyboard, outline);
|
|
||||||
eek_outline_free (outline);
|
|
||||||
g_hash_table_insert (priv->shape_oref_hash, xkbshape,
|
|
||||||
GUINT_TO_POINTER(oref));
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (name, 0, sizeof name);
|
|
||||||
memcpy (name, xkbkey->name.name, sizeof name - 1);
|
|
||||||
|
|
||||||
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
|
|
||||||
bounds.x = xkb_to_pixmap_coord(layout, xkbbounds->x1 + x);
|
|
||||||
bounds.y = xkb_to_pixmap_coord(layout, xkbbounds->y1 + y);
|
|
||||||
bounds.width = xkb_to_pixmap_coord(layout, xkbbounds->x2 - xkbbounds->x1);
|
|
||||||
bounds.height = xkb_to_pixmap_coord(layout, xkbbounds->y2 - xkbbounds->y1);
|
|
||||||
|
|
||||||
keycode = find_keycode (layout, name);
|
|
||||||
if (keycode == EEK_INVALID_KEYCODE) {
|
|
||||||
num_groups = num_levels = 0;
|
|
||||||
matrix = eek_symbol_matrix_new (0, 0);
|
|
||||||
} else {
|
|
||||||
KeySym keysym;
|
|
||||||
gint i, j;
|
|
||||||
|
|
||||||
num_groups = XkbKeyNumGroups (priv->xkb, keycode);
|
|
||||||
num_levels = XkbKeyGroupsWidth (priv->xkb, keycode);
|
|
||||||
matrix = eek_symbol_matrix_new (num_groups, num_levels);
|
|
||||||
for (i = 0; i < num_groups; i++)
|
|
||||||
for (j = 0; j < num_levels; j++) {
|
|
||||||
EekModifierType modifier;
|
|
||||||
|
|
||||||
keysym = XkbKeySymEntry (priv->xkb, keycode, j, i);
|
|
||||||
modifier = XkbKeysymToModifiers (priv->display, keysym);
|
|
||||||
matrix->data[i * num_levels + j] =
|
|
||||||
EEK_SYMBOL(eek_keysym_new_with_modifier (keysym,
|
|
||||||
modifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
key = eek_section_create_key (section, keycode, column, row);
|
|
||||||
eek_element_set_name (EEK_ELEMENT(key), name);
|
|
||||||
eek_element_set_bounds (EEK_ELEMENT(key), &bounds);
|
|
||||||
eek_key_set_symbol_matrix (key, matrix);
|
|
||||||
eek_symbol_matrix_free (matrix);
|
|
||||||
eek_key_set_oref (key, oref);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
create_section (EekXkbLayout *layout,
|
|
||||||
EekKeyboard *keyboard,
|
|
||||||
XkbSectionRec *xkbsection)
|
|
||||||
{
|
|
||||||
XkbGeometryRec *xkbgeometry;
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
EekSection *section;
|
|
||||||
EekBounds bounds;
|
|
||||||
gchar *name;
|
|
||||||
gfloat left, top;
|
|
||||||
gint i, j;
|
|
||||||
|
|
||||||
bounds.x = xkb_to_pixmap_coord(layout, xkbsection->left);
|
|
||||||
bounds.y = xkb_to_pixmap_coord(layout, xkbsection->top);
|
|
||||||
bounds.width = xkb_to_pixmap_coord(layout, xkbsection->width);
|
|
||||||
bounds.height = xkb_to_pixmap_coord(layout, xkbsection->height);
|
|
||||||
|
|
||||||
xkbgeometry = priv->xkb->geom;
|
|
||||||
section = eek_keyboard_create_section (keyboard);
|
|
||||||
name = XGetAtomName (priv->display, xkbsection->name);
|
|
||||||
eek_element_set_name (EEK_ELEMENT(section), name);
|
|
||||||
XFree (name);
|
|
||||||
eek_element_set_bounds (EEK_ELEMENT(section), &bounds);
|
|
||||||
eek_section_set_angle (section,
|
|
||||||
/* angle is in tenth of degree */
|
|
||||||
xkbsection->angle / 10);
|
|
||||||
|
|
||||||
for (i = 0; i < xkbsection->num_rows; i++) {
|
|
||||||
XkbRowRec *xkbrow;
|
|
||||||
|
|
||||||
xkbrow = &xkbsection->rows[i];
|
|
||||||
left = xkbrow->left;
|
|
||||||
top = xkbrow->top;
|
|
||||||
eek_section_add_row (section,
|
|
||||||
xkbrow->num_keys,
|
|
||||||
xkbrow->vertical ?
|
|
||||||
EEK_ORIENTATION_VERTICAL :
|
|
||||||
EEK_ORIENTATION_HORIZONTAL);
|
|
||||||
for (j = 0; j < xkbrow->num_keys; j++) {
|
|
||||||
XkbKeyRec *xkbkey;
|
|
||||||
XkbBoundsRec *xkbbounds;
|
|
||||||
|
|
||||||
xkbkey = &xkbrow->keys[j];
|
|
||||||
if (xkbrow->vertical)
|
|
||||||
top += xkbkey->gap;
|
|
||||||
else
|
|
||||||
left += xkbkey->gap;
|
|
||||||
create_key (layout, keyboard, section, j, i, left, top, xkbkey);
|
|
||||||
xkbbounds = &xkbgeometry->shapes[xkbkey->shape_ndx].bounds;
|
|
||||||
if (xkbrow->vertical)
|
|
||||||
top += xkbbounds->y2 - xkbbounds->y1;
|
|
||||||
else
|
|
||||||
left += xkbbounds->x2 - xkbbounds->x1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
create_keyboard (EekXkbLayout *layout, EekKeyboard *keyboard)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
XkbGeometryRec *xkbgeometry;
|
|
||||||
EekBounds bounds;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
g_return_if_fail (priv->xkb);
|
|
||||||
g_return_if_fail (priv->xkb->geom);
|
|
||||||
|
|
||||||
xkbgeometry = priv->xkb->geom;
|
|
||||||
|
|
||||||
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
|
|
||||||
setup_scaling (EEK_XKB_LAYOUT(layout), bounds.width, bounds.height);
|
|
||||||
|
|
||||||
bounds.x = bounds.y = 0;
|
|
||||||
bounds.width = xkb_to_pixmap_coord(layout, xkbgeometry->width_mm);
|
|
||||||
bounds.height = xkb_to_pixmap_coord(layout, xkbgeometry->height_mm);
|
|
||||||
|
|
||||||
for (i = 0; i < xkbgeometry->num_sections; i++) {
|
|
||||||
XkbSectionRec *xkbsection;
|
|
||||||
|
|
||||||
xkbsection = &xkbgeometry->sections[i];
|
|
||||||
create_section (layout, keyboard, xkbsection);
|
|
||||||
}
|
|
||||||
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
static EekKeyboard *
|
|
||||||
eek_xkb_layout_real_create_keyboard (EekboardContextService *manager,
|
|
||||||
EekLayout *self,
|
|
||||||
gdouble initial_width,
|
|
||||||
gdouble initial_height)
|
|
||||||
{
|
|
||||||
EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", self, NULL);
|
|
||||||
keyboard->manager = manager;
|
|
||||||
|
|
||||||
EekBounds bounds = {
|
|
||||||
.x = 0.0,
|
|
||||||
.y = 0.0,
|
|
||||||
.width = initial_width,
|
|
||||||
.height = initial_height
|
|
||||||
};
|
|
||||||
eek_element_set_bounds (EEK_ELEMENT(keyboard), &bounds);
|
|
||||||
|
|
||||||
/* resolve modifiers dynamically assigned at run time */
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (
|
|
||||||
EEK_XKB_LAYOUT(self));
|
|
||||||
eek_keyboard_set_num_lock_mask (keyboard,
|
|
||||||
XkbKeysymToModifiers (priv->display,
|
|
||||||
XK_Num_Lock));
|
|
||||||
eek_keyboard_set_alt_gr_mask (keyboard,
|
|
||||||
XkbKeysymToModifiers (priv->display,
|
|
||||||
XK_ISO_Level3_Shift));
|
|
||||||
|
|
||||||
if (priv->shape_oref_hash)
|
|
||||||
g_hash_table_destroy (priv->shape_oref_hash);
|
|
||||||
|
|
||||||
priv->shape_oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
||||||
create_keyboard (EEK_XKB_LAYOUT(self), keyboard);
|
|
||||||
g_hash_table_destroy (priv->shape_oref_hash);
|
|
||||||
|
|
||||||
return keyboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkb_layout_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (
|
|
||||||
EEK_XKB_LAYOUT (object));
|
|
||||||
|
|
||||||
g_free (priv->names.keycodes);
|
|
||||||
g_free (priv->names.geometry);
|
|
||||||
g_free (priv->names.symbols);
|
|
||||||
XkbFreeKeyboard (priv->xkb, 0, TRUE); /* free_all = TRUE */
|
|
||||||
G_OBJECT_CLASS (eek_xkb_layout_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkb_layout_set_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_DISPLAY:
|
|
||||||
priv->display = g_value_get_pointer (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkb_layout_get_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
EekXkbLayout *layout = EEK_XKB_LAYOUT (object);
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_DISPLAY:
|
|
||||||
g_value_set_pointer (value, priv->display);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkb_layout_class_init (EekXkbLayoutClass *klass)
|
|
||||||
{
|
|
||||||
EekLayoutClass *layout_class = EEK_LAYOUT_CLASS (klass);
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
GParamSpec *pspec;
|
|
||||||
|
|
||||||
layout_class->create_keyboard = eek_xkb_layout_real_create_keyboard;
|
|
||||||
|
|
||||||
gobject_class->finalize = eek_xkb_layout_finalize;
|
|
||||||
gobject_class->set_property = eek_xkb_layout_set_property;
|
|
||||||
gobject_class->get_property = eek_xkb_layout_get_property;
|
|
||||||
|
|
||||||
pspec = g_param_spec_pointer ("display",
|
|
||||||
"Display",
|
|
||||||
"X Display",
|
|
||||||
G_PARAM_READWRITE |
|
|
||||||
G_PARAM_CONSTRUCT_ONLY);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_DISPLAY, pspec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkb_layout_init (EekXkbLayout *self)
|
|
||||||
{
|
|
||||||
/* void */
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
get_names_from_server (EekXkbLayout *layout,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
gchar *name;
|
|
||||||
|
|
||||||
XkbGetNames (priv->display, XkbAllNamesMask, priv->xkb);
|
|
||||||
|
|
||||||
if (priv->xkb->names->keycodes <= 0)
|
|
||||||
g_warning ("XKB keycodes setting is not loaded properly");
|
|
||||||
else {
|
|
||||||
name = XGetAtomName (priv->display, priv->xkb->names->keycodes);
|
|
||||||
if (!name)
|
|
||||||
g_warning ("Can't get the name of keycodes");
|
|
||||||
else if (!priv->names.keycodes ||
|
|
||||||
g_strcmp0 (name, priv->names.keycodes)) {
|
|
||||||
g_free (priv->names.keycodes);
|
|
||||||
priv->names.keycodes = g_strdup (name);
|
|
||||||
XFree (name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->xkb->names->geometry <= 0)
|
|
||||||
g_warning ("XKB geometry setting is not loaded");
|
|
||||||
else {
|
|
||||||
name = XGetAtomName (priv->display, priv->xkb->names->geometry);
|
|
||||||
if (!name)
|
|
||||||
g_warning ("Can't get the name of geometry");
|
|
||||||
else if (!priv->names.geometry ||
|
|
||||||
g_strcmp0 (name, priv->names.geometry)) {
|
|
||||||
g_free (priv->names.geometry);
|
|
||||||
priv->names.geometry = g_strdup (name);
|
|
||||||
XFree (name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->xkb->names->symbols <= 0)
|
|
||||||
g_warning ("XKB symbols setting is not loaded");
|
|
||||||
else {
|
|
||||||
name = XGetAtomName (priv->display, priv->xkb->names->symbols);
|
|
||||||
if (!name)
|
|
||||||
g_warning ("Can't get the name of symbols");
|
|
||||||
else if (!priv->names.symbols ||
|
|
||||||
g_strcmp0 (name, priv->names.symbols)) {
|
|
||||||
g_free (priv->names.symbols);
|
|
||||||
priv->names.symbols = g_strdup (name);
|
|
||||||
XFree (name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkb_layout_new:
|
|
||||||
*
|
|
||||||
* Create a new #EekXkbLayout.
|
|
||||||
*/
|
|
||||||
EekLayout *
|
|
||||||
eek_xkb_layout_new (Display *display,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
return (EekLayout *) g_initable_new (EEK_TYPE_XKB_LAYOUT,
|
|
||||||
NULL,
|
|
||||||
error,
|
|
||||||
"display", display,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkb_layout_set_names: (skip)
|
|
||||||
* @layout: an #EekXkbLayout
|
|
||||||
* @names: XKB component names
|
|
||||||
* @error: a #GError
|
|
||||||
*
|
|
||||||
* Set the XKB component names to @layout.
|
|
||||||
* Returns: %TRUE if the component names are successfully set, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkb_layout_set_names (EekXkbLayout *layout,
|
|
||||||
XkbComponentNamesRec *names,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
if (g_strcmp0 (names->keycodes, priv->names.keycodes)) {
|
|
||||||
g_free (priv->names.keycodes);
|
|
||||||
priv->names.keycodes = g_strdup (names->keycodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_strcmp0 (names->geometry, priv->names.geometry)) {
|
|
||||||
g_free (priv->names.geometry);
|
|
||||||
priv->names.geometry = g_strdup (names->geometry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_strcmp0 (names->symbols, priv->names.symbols)) {
|
|
||||||
g_free (priv->names.symbols);
|
|
||||||
priv->names.symbols = g_strdup (names->symbols);
|
|
||||||
}
|
|
||||||
|
|
||||||
return get_keyboard_from_server (layout, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
get_keyboard_from_server (EekXkbLayout *layout,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
if (priv->xkb) {
|
|
||||||
XkbFreeKeyboard (priv->xkb, 0, True);
|
|
||||||
priv->xkb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->names.keycodes && priv->names.geometry && priv->names.symbols) {
|
|
||||||
priv->xkb = XkbGetKeyboardByName (priv->display,
|
|
||||||
XkbUseCoreKbd,
|
|
||||||
&priv->names,
|
|
||||||
0,
|
|
||||||
XKB_COMPONENT_MASK,
|
|
||||||
False);
|
|
||||||
} else {
|
|
||||||
priv->xkb = XkbGetKeyboard (priv->display,
|
|
||||||
XKB_COMPONENT_MASK,
|
|
||||||
XkbUseCoreKbd);
|
|
||||||
if (!get_names_from_server (layout, error)) {
|
|
||||||
XkbFreeKeyboard (priv->xkb, 0, True);
|
|
||||||
priv->xkb = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->xkb == NULL) {
|
|
||||||
g_set_error (error,
|
|
||||||
EEK_ERROR,
|
|
||||||
EEK_ERROR_LAYOUT_ERROR,
|
|
||||||
"can't get keyboard from server");
|
|
||||||
g_free (priv->names.keycodes);
|
|
||||||
priv->names.keycodes = NULL;
|
|
||||||
g_free (priv->names.geometry);
|
|
||||||
priv->names.geometry = NULL;
|
|
||||||
g_free (priv->names.symbols);
|
|
||||||
priv->names.symbols = NULL;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static guint
|
|
||||||
find_keycode (EekXkbLayout *layout, gchar *key_name)
|
|
||||||
{
|
|
||||||
#define KEYSYM_NAME_MAX_LENGTH 4
|
|
||||||
guint keycode;
|
|
||||||
gint i, j;
|
|
||||||
XkbKeyNamePtr pkey;
|
|
||||||
XkbKeyAliasPtr palias;
|
|
||||||
guint is_name_matched;
|
|
||||||
gchar *src, *dst;
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
if (!priv->xkb)
|
|
||||||
return EEK_INVALID_KEYCODE;
|
|
||||||
|
|
||||||
pkey = priv->xkb->names->keys + priv->xkb->min_key_code;
|
|
||||||
for (keycode = priv->xkb->min_key_code;
|
|
||||||
keycode <= priv->xkb->max_key_code; keycode++) {
|
|
||||||
is_name_matched = 1;
|
|
||||||
src = key_name;
|
|
||||||
dst = pkey->name;
|
|
||||||
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
|
|
||||||
if ('\0' == *src)
|
|
||||||
break;
|
|
||||||
if (*src++ != *dst++) {
|
|
||||||
is_name_matched = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_name_matched)
|
|
||||||
return keycode;
|
|
||||||
pkey++;
|
|
||||||
}
|
|
||||||
|
|
||||||
palias = priv->xkb->names->key_aliases;
|
|
||||||
for (j = priv->xkb->names->num_key_aliases; --j >= 0;) {
|
|
||||||
is_name_matched = 1;
|
|
||||||
src = key_name;
|
|
||||||
dst = palias->alias;
|
|
||||||
for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
|
|
||||||
if ('\0' == *src)
|
|
||||||
break;
|
|
||||||
if (*src++ != *dst++) {
|
|
||||||
is_name_matched = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_name_matched) {
|
|
||||||
keycode = find_keycode (layout, palias->real);
|
|
||||||
return keycode;
|
|
||||||
}
|
|
||||||
palias++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EEK_INVALID_KEYCODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setup_scaling (EekXkbLayout *layout,
|
|
||||||
gdouble width,
|
|
||||||
gdouble height)
|
|
||||||
{
|
|
||||||
EekXkbLayoutPrivate *priv = eek_xkb_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
g_return_if_fail (priv->xkb);
|
|
||||||
|
|
||||||
g_return_if_fail (priv->xkb->geom->width_mm > 0);
|
|
||||||
g_return_if_fail (priv->xkb->geom->height_mm > 0);
|
|
||||||
|
|
||||||
if (width * priv->xkb->geom->height_mm <
|
|
||||||
height * priv->xkb->geom->width_mm) {
|
|
||||||
priv->scale_numerator = width;
|
|
||||||
priv->scale_denominator = priv->xkb->geom->width_mm;
|
|
||||||
} else {
|
|
||||||
priv->scale_numerator = height;
|
|
||||||
priv->scale_denominator = priv->xkb->geom->height_mm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
initable_init (GInitable *initable,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
EekXkbLayout *layout = EEK_XKB_LAYOUT (initable);
|
|
||||||
|
|
||||||
if (!get_keyboard_from_server (layout, error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!get_names_from_server (layout, error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
initable_iface_init (GInitableIface *initable_iface)
|
|
||||||
{
|
|
||||||
initable_iface->init = initable_init;
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
|
|
||||||
#error "Only <eek/eek-xkb.h> can be included directly."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EEK_XKB_LAYOUT_H
|
|
||||||
#define EEK_XKB_LAYOUT_H 1
|
|
||||||
|
|
||||||
#include <X11/XKBlib.h>
|
|
||||||
#include "eek-layout.h"
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define EEK_TYPE_XKB_LAYOUT (eek_xkb_layout_get_type())
|
|
||||||
G_DECLARE_DERIVABLE_TYPE (EekXkbLayout, eek_xkb_layout, EEK, XKB_LAYOUT, EekLayout)
|
|
||||||
|
|
||||||
struct _EekXkbLayoutClass
|
|
||||||
{
|
|
||||||
/*< private >*/
|
|
||||||
EekLayoutClass parent_class;
|
|
||||||
|
|
||||||
/*< private >*/
|
|
||||||
/* padding */
|
|
||||||
gpointer pdummy[24];
|
|
||||||
};
|
|
||||||
|
|
||||||
GType eek_xkb_layout_get_type (void) G_GNUC_CONST;
|
|
||||||
EekLayout *eek_xkb_layout_new (Display *display,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean eek_xkb_layout_set_names (EekXkbLayout *layout,
|
|
||||||
XkbComponentNamesRec *names,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
#endif /* #ifndef EEK_XKB_LAYOUT_H */
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#ifndef EEK_XKB_H
|
|
||||||
#define EEK_XKB_H 1
|
|
||||||
|
|
||||||
#include "eek.h"
|
|
||||||
#include "eek-xkb-layout.h"
|
|
||||||
|
|
||||||
#endif /* EEK_XKB_H */
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
# Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
# Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
|
|
||||||
# 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
# 02110-1301 USA
|
|
||||||
|
|
||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
libdir=@libdir@
|
|
||||||
includedir=@includedir@
|
|
||||||
|
|
||||||
Name: libeek-xkl
|
|
||||||
Description: A Library to Create Keyboard-like UI (Libxklavier Support)
|
|
||||||
URL: http://fedorahosted.org/eekboard/
|
|
||||||
Version: @VERSION@
|
|
||||||
Requires: eek-@EEK_API_VERSION@ libxklavier
|
|
||||||
Libs: -L${libdir} -leek-xkl
|
|
||||||
Cflags: -I${includedir}/eek-@EEK_API_VERSION@
|
|
||||||
@ -1,662 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:eek-xkl-layout
|
|
||||||
* @short_description: Layout engine using Libxklavier configuration
|
|
||||||
*
|
|
||||||
* The #EekXklLayout is a simple wrapper around #EekXkbLayout class
|
|
||||||
* to use Libxklavier configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif /* HAVE_CONFIG_H */
|
|
||||||
|
|
||||||
#include <libxklavier/xklavier.h>
|
|
||||||
#include <gio/gio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "eek-xkl-layout.h"
|
|
||||||
|
|
||||||
#define noKBDRAW_DEBUG
|
|
||||||
|
|
||||||
static GInitableIface *parent_initable_iface;
|
|
||||||
|
|
||||||
static void initable_iface_init (GInitableIface *initable_iface);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PROP_0,
|
|
||||||
PROP_MODEL,
|
|
||||||
PROP_LAYOUTS,
|
|
||||||
PROP_VARIANTS,
|
|
||||||
PROP_OPTIONS,
|
|
||||||
PROP_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _EekXklLayoutPrivate
|
|
||||||
{
|
|
||||||
XklEngine *engine;
|
|
||||||
XklConfigRec *config;
|
|
||||||
} EekXklLayoutPrivate;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_EXTENDED (EekXklLayout, eek_xkl_layout, EEK_TYPE_XKB_LAYOUT,
|
|
||||||
0, /* GTypeFlags */
|
|
||||||
G_ADD_PRIVATE (EekXklLayout)
|
|
||||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
|
||||||
initable_iface_init))
|
|
||||||
|
|
||||||
/* from gnome-keyboard-properties-xkbpv.c:
|
|
||||||
* BAD STYLE: Taken from xklavier_private_xkb.h
|
|
||||||
* Any ideas on architectural improvements are WELCOME
|
|
||||||
*/
|
|
||||||
extern gboolean xkl_xkb_config_native_prepare (XklEngine * engine,
|
|
||||||
const XklConfigRec * data,
|
|
||||||
XkbComponentNamesPtr
|
|
||||||
component_names);
|
|
||||||
|
|
||||||
extern void xkl_xkb_config_native_cleanup (XklEngine * engine,
|
|
||||||
XkbComponentNamesPtr
|
|
||||||
component_names);
|
|
||||||
|
|
||||||
static gboolean set_xkb_component_names (EekXklLayout *layout,
|
|
||||||
XklConfigRec *config);
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkl_layout_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (
|
|
||||||
EEK_XKL_LAYOUT (object));
|
|
||||||
|
|
||||||
if (priv->config) {
|
|
||||||
g_object_unref (priv->config);
|
|
||||||
priv->config = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_xkl_layout_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkl_layout_set_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
EekXklLayout *layout = EEK_XKL_LAYOUT(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_MODEL:
|
|
||||||
eek_xkl_layout_set_model (layout, g_value_get_string (value));
|
|
||||||
break;
|
|
||||||
case PROP_LAYOUTS:
|
|
||||||
eek_xkl_layout_set_layouts (layout, g_value_get_boxed (value));
|
|
||||||
break;
|
|
||||||
case PROP_VARIANTS:
|
|
||||||
eek_xkl_layout_set_variants (layout, g_value_get_boxed (value));
|
|
||||||
break;
|
|
||||||
case PROP_OPTIONS:
|
|
||||||
eek_xkl_layout_set_options (layout, g_value_get_boxed (value));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkl_layout_get_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
EekXklLayout *layout = EEK_XKL_LAYOUT(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_MODEL:
|
|
||||||
g_value_set_string (value,
|
|
||||||
eek_xkl_layout_get_model (layout));
|
|
||||||
break;
|
|
||||||
case PROP_LAYOUTS:
|
|
||||||
g_value_set_boxed (value,
|
|
||||||
eek_xkl_layout_get_layouts (layout));
|
|
||||||
break;
|
|
||||||
case PROP_VARIANTS:
|
|
||||||
g_value_set_boxed (value,
|
|
||||||
eek_xkl_layout_get_variants (layout));
|
|
||||||
break;
|
|
||||||
case PROP_OPTIONS:
|
|
||||||
g_value_set_boxed (value,
|
|
||||||
eek_xkl_layout_get_options (layout));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkl_layout_class_init (EekXklLayoutClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
GParamSpec *pspec;
|
|
||||||
|
|
||||||
gobject_class->dispose = eek_xkl_layout_dispose;
|
|
||||||
gobject_class->set_property = eek_xkl_layout_set_property;
|
|
||||||
gobject_class->get_property = eek_xkl_layout_get_property;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EekXklLayout:model:
|
|
||||||
*
|
|
||||||
* The libxklavier model name of #EekXklLayout.
|
|
||||||
*/
|
|
||||||
pspec = g_param_spec_string ("model",
|
|
||||||
"Model",
|
|
||||||
"Libxklavier model",
|
|
||||||
NULL,
|
|
||||||
G_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_MODEL, pspec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EekXklLayout:layouts:
|
|
||||||
*
|
|
||||||
* The libxklavier layout names of #EekXklLayout.
|
|
||||||
*/
|
|
||||||
pspec = g_param_spec_boxed ("layouts",
|
|
||||||
"Layouts",
|
|
||||||
"Libxklavier layouts",
|
|
||||||
G_TYPE_STRV,
|
|
||||||
G_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LAYOUTS, pspec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EekXklLayout:variants:
|
|
||||||
*
|
|
||||||
* The libxklavier variant names of #EekXklLayout.
|
|
||||||
*/
|
|
||||||
pspec = g_param_spec_boxed ("variants",
|
|
||||||
"Variants",
|
|
||||||
"Libxklavier variants",
|
|
||||||
G_TYPE_STRV,
|
|
||||||
G_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_VARIANTS, pspec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EekXklLayout:options:
|
|
||||||
*
|
|
||||||
* The libxklavier option names of #EekXklLayout.
|
|
||||||
*/
|
|
||||||
pspec = g_param_spec_boxed ("options",
|
|
||||||
"Options",
|
|
||||||
"Libxklavier options",
|
|
||||||
G_TYPE_STRV,
|
|
||||||
G_PARAM_READWRITE);
|
|
||||||
g_object_class_install_property (gobject_class, PROP_OPTIONS, pspec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eek_xkl_layout_init (EekXklLayout *self)
|
|
||||||
{
|
|
||||||
/* void */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_new:
|
|
||||||
*
|
|
||||||
* Create a new #EekXklLayout.
|
|
||||||
*/
|
|
||||||
EekLayout *
|
|
||||||
eek_xkl_layout_new (Display *display, GError **error)
|
|
||||||
{
|
|
||||||
return (EekLayout *) g_initable_new (EEK_TYPE_XKL_LAYOUT,
|
|
||||||
NULL,
|
|
||||||
error,
|
|
||||||
"display", display,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_INLINE_FUNC void
|
|
||||||
merge_xkl_config_rec (XklConfigRec *dst, XklConfigRec *src)
|
|
||||||
{
|
|
||||||
if (src->model) {
|
|
||||||
g_free (dst->model);
|
|
||||||
dst->model = g_strdup (src->model);
|
|
||||||
}
|
|
||||||
if (src->layouts) {
|
|
||||||
g_strfreev (dst->layouts);
|
|
||||||
dst->layouts = g_strdupv (src->layouts);
|
|
||||||
}
|
|
||||||
if (src->variants) {
|
|
||||||
g_strfreev (dst->variants);
|
|
||||||
dst->variants = g_strdupv (src->variants);
|
|
||||||
}
|
|
||||||
if (src->options) {
|
|
||||||
g_strfreev (dst->options);
|
|
||||||
dst->options = g_strdupv (src->options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_set_config: (skip)
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @config: Libxklavier configuration
|
|
||||||
*
|
|
||||||
* Reconfigure @layout with @config.
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_set_config (EekXklLayout *layout,
|
|
||||||
XklConfigRec *config)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
XklConfigRec *c;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, FALSE);
|
|
||||||
c = xkl_config_rec_new ();
|
|
||||||
merge_xkl_config_rec (c, priv->config);
|
|
||||||
merge_xkl_config_rec (c, config);
|
|
||||||
retval = set_xkb_component_names (layout, c);
|
|
||||||
g_object_unref (c);
|
|
||||||
merge_xkl_config_rec (priv->config, config);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_set_config_full:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @model: Libxklavier model name
|
|
||||||
* @layouts: Libxklavier layouts
|
|
||||||
* @variants: Libxklavier variants
|
|
||||||
* @options: Libxklavier options
|
|
||||||
*
|
|
||||||
* Reconfigure @layout with @model, @layouts, @variants, and @options.
|
|
||||||
* This function is merely a wrapper around
|
|
||||||
* eek_xkl_layout_set_config() to avoid passing a pointer of
|
|
||||||
* XklConfigRec, which is not currently available in the
|
|
||||||
* gobject-introspection repository.
|
|
||||||
*
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
* Since: 0.0.2
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_set_config_full (EekXklLayout *layout,
|
|
||||||
gchar *model,
|
|
||||||
gchar **layouts,
|
|
||||||
gchar **variants,
|
|
||||||
gchar **options)
|
|
||||||
{
|
|
||||||
XklConfigRec *config;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
config = xkl_config_rec_new ();
|
|
||||||
config->model = g_strdup (model);
|
|
||||||
config->layouts = g_strdupv (layouts);
|
|
||||||
config->variants = g_strdupv (variants);
|
|
||||||
config->options = g_strdupv (options);
|
|
||||||
retval = eek_xkl_layout_set_config (layout, config);
|
|
||||||
g_object_unref (config);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_set_model:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @model: model name
|
|
||||||
*
|
|
||||||
* Set the model name of @layout configuration (in the Libxklavier terminology).
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_set_model (EekXklLayout *layout,
|
|
||||||
const gchar *model)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
XklConfigRec *config;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, FALSE);
|
|
||||||
config = xkl_config_rec_new ();
|
|
||||||
/* config->model will be freed on g_object_unref (config) */
|
|
||||||
if (model)
|
|
||||||
config->model = g_strdup (model);
|
|
||||||
else
|
|
||||||
config->model = NULL;
|
|
||||||
retval = eek_xkl_layout_set_config (layout, config);
|
|
||||||
g_object_unref (config);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_set_layouts:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @layouts: layout names
|
|
||||||
*
|
|
||||||
* Set the layout names of @layout (in the Libxklavier terminology).
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_set_layouts (EekXklLayout *layout,
|
|
||||||
gchar **layouts)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
XklConfigRec *config;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, FALSE);
|
|
||||||
config = xkl_config_rec_new ();
|
|
||||||
/* config->layouts will be freed on g_object_unref (config) */
|
|
||||||
if (layouts)
|
|
||||||
config->layouts = g_strdupv (layouts);
|
|
||||||
else
|
|
||||||
config->layouts = layouts;
|
|
||||||
retval = eek_xkl_layout_set_config (layout, config);
|
|
||||||
g_object_unref (config);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_set_variants:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @variants: variant names
|
|
||||||
*
|
|
||||||
* Set the variant names of @layout (in the Libxklavier terminology).
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_set_variants (EekXklLayout *layout,
|
|
||||||
gchar **variants)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
XklConfigRec *config;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, FALSE);
|
|
||||||
config = xkl_config_rec_new ();
|
|
||||||
/* config->variants will be freed on g_object_unref (config) */
|
|
||||||
if (variants)
|
|
||||||
config->variants = g_strdupv (variants);
|
|
||||||
else
|
|
||||||
config->variants = NULL;
|
|
||||||
retval = eek_xkl_layout_set_config (layout, config);
|
|
||||||
g_object_unref (config);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_set_options:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @options: option names
|
|
||||||
*
|
|
||||||
* Set the option names of @layout (in the Libxklavier terminology).
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_set_options (EekXklLayout *layout,
|
|
||||||
gchar **options)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
XklConfigRec *config;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, FALSE);
|
|
||||||
config = xkl_config_rec_new ();
|
|
||||||
/* config->options will be freed on g_object_unref (config) */
|
|
||||||
if (options)
|
|
||||||
config->options = options;
|
|
||||||
else
|
|
||||||
config->options = NULL;
|
|
||||||
retval = eek_xkl_layout_set_config (layout, config);
|
|
||||||
g_object_unref (config);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_enable_option:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @option: option name
|
|
||||||
*
|
|
||||||
* Set the option of @layout (in the Libxklavier terminology).
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_enable_option (EekXklLayout *layout,
|
|
||||||
const gchar *option)
|
|
||||||
{
|
|
||||||
gchar **options, **_options;
|
|
||||||
gint i, j;
|
|
||||||
|
|
||||||
options = eek_xkl_layout_get_options (layout);
|
|
||||||
for (i = 0; options && options[i]; i++)
|
|
||||||
if (g_strcmp0 (options[i], option) == 0)
|
|
||||||
return TRUE;
|
|
||||||
_options = g_new0 (gchar *, (i + 2));
|
|
||||||
for (j = 0; j < i; j++)
|
|
||||||
_options[j] = g_strdup (options[j]);
|
|
||||||
_options[i] = g_strdup (option);
|
|
||||||
/* eek_xkl_layout_set_options() will free _options and its elements. */
|
|
||||||
return eek_xkl_layout_set_options (layout, _options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_disable_option:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @option: option name
|
|
||||||
*
|
|
||||||
* Unset the option of @layout (in the Libxklavier terminology).
|
|
||||||
* Returns: %TRUE if the current layout changed, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_disable_option (EekXklLayout *layout,
|
|
||||||
const gchar *option)
|
|
||||||
{
|
|
||||||
gchar **options, **_options;
|
|
||||||
gint i, j, k;
|
|
||||||
|
|
||||||
options = eek_xkl_layout_get_options (layout);
|
|
||||||
if (!options)
|
|
||||||
return TRUE;
|
|
||||||
for (i = 0, k = 0; options[i]; i++)
|
|
||||||
if (g_strcmp0 (options[i], option) == 0)
|
|
||||||
k = i;
|
|
||||||
if (options[k] == NULL)
|
|
||||||
return TRUE;
|
|
||||||
_options = g_new0 (gchar *, i);
|
|
||||||
for (j = 0; j < k; j++)
|
|
||||||
_options[j] = g_strdup (options[j]);
|
|
||||||
for (j = k + 1; j < i; j++)
|
|
||||||
_options[j] = g_strdup (options[j]);
|
|
||||||
/* eek_xkl_layout_set_options() will free _options and its elements. */
|
|
||||||
return eek_xkl_layout_set_options (layout, _options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_get_model:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
*
|
|
||||||
* Get the model name of @layout configuration (in the Libxklavier terminology).
|
|
||||||
*/
|
|
||||||
gchar *
|
|
||||||
eek_xkl_layout_get_model (EekXklLayout *layout)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, NULL);
|
|
||||||
return g_strdup (priv->config->model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_get_layouts:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
*
|
|
||||||
* Get the layout names of @layout configuration (in the Libxklavier
|
|
||||||
* terminology).
|
|
||||||
*/
|
|
||||||
gchar **
|
|
||||||
eek_xkl_layout_get_layouts (EekXklLayout *layout)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, NULL);
|
|
||||||
return g_strdupv (priv->config->layouts);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_get_variants:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
*
|
|
||||||
* Get the variant names of @layout configuration (in the Libxklavier
|
|
||||||
* terminology).
|
|
||||||
*/
|
|
||||||
gchar **
|
|
||||||
eek_xkl_layout_get_variants (EekXklLayout *layout)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, NULL);
|
|
||||||
return g_strdupv (priv->config->variants);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_get_options:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
*
|
|
||||||
* Get the option names of @layout configuration (in the Libxklavier
|
|
||||||
* terminology).
|
|
||||||
*/
|
|
||||||
gchar **
|
|
||||||
eek_xkl_layout_get_options (EekXklLayout *layout)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv, NULL);
|
|
||||||
return g_strdupv (priv->config->options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
set_xkb_component_names (EekXklLayout *layout, XklConfigRec *config)
|
|
||||||
{
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
XkbComponentNamesRec names;
|
|
||||||
gboolean retval = FALSE;
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (config->layouts) {
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
fprintf (stderr, "layout = ");
|
|
||||||
for (i = 0; config->layouts[i] != NULL; i++)
|
|
||||||
fprintf (stderr, "\"%s\" ", config->layouts[i]);
|
|
||||||
fputc ('\n', stderr);
|
|
||||||
} else
|
|
||||||
fprintf (stderr, "layouts = NULL\n");
|
|
||||||
if (config->variants) {
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
fprintf (stderr, "variant = ");
|
|
||||||
for (i = 0; config->variants[i]; i++)
|
|
||||||
fprintf (stderr, "\"%s\" ", config->variants[i]);
|
|
||||||
fputc ('\n', stderr);
|
|
||||||
} else
|
|
||||||
fprintf (stderr, "variants = NULL\n");
|
|
||||||
if (config->options) {
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
fprintf (stderr, "option = ");
|
|
||||||
for (i = 0; config->options[i]; i++)
|
|
||||||
fprintf (stderr, "\"%s\" ", config->options[i]);
|
|
||||||
fputc ('\n', stderr);
|
|
||||||
} else
|
|
||||||
fprintf (stderr, "options = NULL\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (xkl_xkb_config_native_prepare (priv->engine, config, &names)) {
|
|
||||||
GError *error = NULL;
|
|
||||||
retval = eek_xkb_layout_set_names (EEK_XKB_LAYOUT(layout),
|
|
||||||
&names,
|
|
||||||
&error);
|
|
||||||
if (!retval)
|
|
||||||
g_warning ("can't set XKB layout");
|
|
||||||
xkl_xkb_config_native_cleanup (priv->engine, &names);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eek_xkl_layout_get_option:
|
|
||||||
* @layout: an #EekXklLayout
|
|
||||||
* @option: option name
|
|
||||||
*
|
|
||||||
* Tell if the option of @layout (in the Libxklavier terminology) is set.
|
|
||||||
* Returns: %TRUE if the option is set, %FALSE otherwise
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
eek_xkl_layout_get_option (EekXklLayout *layout,
|
|
||||||
const gchar *option)
|
|
||||||
{
|
|
||||||
gchar **options;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
options = eek_xkl_layout_get_options (layout);
|
|
||||||
for (i = 0; options && options[i]; i++)
|
|
||||||
if (g_strcmp0 (options[i], option) == 0)
|
|
||||||
return TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
initable_init (GInitable *initable,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
EekXklLayout *layout = EEK_XKL_LAYOUT (initable);
|
|
||||||
EekXklLayoutPrivate *priv = eek_xkl_layout_get_instance_private (layout);
|
|
||||||
Display *display;
|
|
||||||
|
|
||||||
if (!parent_initable_iface->init (initable, cancellable, error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
priv->config = xkl_config_rec_new ();
|
|
||||||
|
|
||||||
g_object_get (G_OBJECT (initable),
|
|
||||||
"display", &display,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
priv->engine = xkl_engine_get_instance (display);
|
|
||||||
|
|
||||||
if (!xkl_config_rec_get_from_server (priv->config,
|
|
||||||
priv->engine)) {
|
|
||||||
g_set_error (error,
|
|
||||||
EEK_ERROR,
|
|
||||||
EEK_ERROR_LAYOUT_ERROR,
|
|
||||||
"can't load libxklavier configuration");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_xkb_component_names (layout, priv->config);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
initable_iface_init (GInitableIface *initable_iface)
|
|
||||||
{
|
|
||||||
parent_initable_iface = g_type_interface_peek_parent (initable_iface);
|
|
||||||
initable_iface->init = initable_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
|
|
||||||
#error "Only <eek/eek-xkl.h> can be included directly."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EEK_XKL_LAYOUT_H
|
|
||||||
#define EEK_XKL_LAYOUT_H 1
|
|
||||||
|
|
||||||
#include <libxklavier/xklavier.h>
|
|
||||||
#include "eek-xkb-layout.h"
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define EEK_TYPE_XKL_LAYOUT (eek_xkl_layout_get_type())
|
|
||||||
G_DECLARE_DERIVABLE_TYPE (EekXklLayout, eek_xkl_layout, EEK, XKL_LAYOUT, EekLayout)
|
|
||||||
|
|
||||||
struct _EekXklLayoutClass
|
|
||||||
{
|
|
||||||
/*< private >*/
|
|
||||||
EekXkbLayoutClass parent_class;
|
|
||||||
|
|
||||||
/*< private >*/
|
|
||||||
/* padding */
|
|
||||||
gpointer pdummy[24];
|
|
||||||
};
|
|
||||||
|
|
||||||
GType eek_xkl_layout_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
EekLayout *eek_xkl_layout_new (Display *display,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean eek_xkl_layout_set_config (EekXklLayout *layout,
|
|
||||||
XklConfigRec *config);
|
|
||||||
|
|
||||||
gboolean eek_xkl_layout_set_config_full (EekXklLayout *layout,
|
|
||||||
gchar *model,
|
|
||||||
gchar **layouts,
|
|
||||||
gchar **variants,
|
|
||||||
gchar **options);
|
|
||||||
|
|
||||||
gboolean eek_xkl_layout_set_model (EekXklLayout *layout,
|
|
||||||
const gchar *model);
|
|
||||||
gboolean eek_xkl_layout_set_layouts (EekXklLayout *layout,
|
|
||||||
gchar **layouts);
|
|
||||||
gboolean eek_xkl_layout_set_variants (EekXklLayout *layout,
|
|
||||||
gchar **variants);
|
|
||||||
gboolean eek_xkl_layout_set_options (EekXklLayout *layout,
|
|
||||||
gchar **options);
|
|
||||||
gboolean eek_xkl_layout_enable_option (EekXklLayout *layout,
|
|
||||||
const gchar *option);
|
|
||||||
gboolean eek_xkl_layout_disable_option (EekXklLayout *layout,
|
|
||||||
const gchar *option);
|
|
||||||
|
|
||||||
gchar *eek_xkl_layout_get_model (EekXklLayout *layout);
|
|
||||||
gchar **eek_xkl_layout_get_layouts (EekXklLayout *layout);
|
|
||||||
gchar **eek_xkl_layout_get_variants (EekXklLayout *layout);
|
|
||||||
gchar **eek_xkl_layout_get_options (EekXklLayout *layout);
|
|
||||||
gboolean eek_xkl_layout_get_option (EekXklLayout *layout,
|
|
||||||
const gchar *option);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
#endif /* #ifndef EEK_XKL_LAYOUT_H */
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#ifndef EEK_XKL_H
|
|
||||||
#define EEK_XKL_H 1
|
|
||||||
|
|
||||||
#include "eek.h"
|
|
||||||
#include "eek-xkl-layout.h"
|
|
||||||
|
|
||||||
#endif /* EEK_XKL_H */
|
|
||||||
@ -1,404 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:eekboard-client
|
|
||||||
* @short_description: client interface of eekboard service
|
|
||||||
*
|
|
||||||
* The #EekboardClient class provides a client side access to eekboard-server.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif /* HAVE_CONFIG_H */
|
|
||||||
|
|
||||||
#include "eekboard/eekboard-client.h"
|
|
||||||
|
|
||||||
enum {
|
|
||||||
DESTROYED,
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
static guint signals[LAST_SIGNAL] = { 0, };
|
|
||||||
|
|
||||||
typedef struct _EekboardClientPrivate
|
|
||||||
{
|
|
||||||
GHashTable *context_hash;
|
|
||||||
} EekboardClientPrivate;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (EekboardClient, eekboard_client, G_TYPE_DBUS_PROXY)
|
|
||||||
|
|
||||||
static void send_destroy_context (EekboardClient *client,
|
|
||||||
EekboardContext *context,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_client_real_destroyed (EekboardClient *self)
|
|
||||||
{
|
|
||||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (self);
|
|
||||||
|
|
||||||
// g_debug ("eekboard_client_real_destroyed");
|
|
||||||
g_hash_table_remove_all (priv->context_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_client_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
EekboardClient *client = EEKBOARD_CLIENT(object);
|
|
||||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
|
||||||
|
|
||||||
if (priv->context_hash) {
|
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key, value;
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, priv->context_hash);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
||||||
send_destroy_context (client, (EekboardContext *)value, NULL);
|
|
||||||
g_hash_table_iter_remove (&iter);
|
|
||||||
}
|
|
||||||
g_hash_table_destroy (priv->context_hash);
|
|
||||||
priv->context_hash = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (eekboard_client_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_client_class_init (EekboardClientClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
klass->destroyed = eekboard_client_real_destroyed;
|
|
||||||
|
|
||||||
gobject_class->dispose = eekboard_client_dispose;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EekboardClient::destroyed:
|
|
||||||
* @eekboard: an #EekboardClient
|
|
||||||
*
|
|
||||||
* The ::destroyed signal is emitted each time the name of remote
|
|
||||||
* end is vanished.
|
|
||||||
*/
|
|
||||||
signals[DESTROYED] =
|
|
||||||
g_signal_new (I_("destroyed"),
|
|
||||||
G_TYPE_FROM_CLASS(gobject_class),
|
|
||||||
G_SIGNAL_RUN_LAST,
|
|
||||||
G_STRUCT_OFFSET(EekboardClientClass, destroyed),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
g_cclosure_marshal_VOID__VOID,
|
|
||||||
G_TYPE_NONE,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_client_init (EekboardClient *self)
|
|
||||||
{
|
|
||||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (self);
|
|
||||||
|
|
||||||
priv->context_hash =
|
|
||||||
g_hash_table_new_full (g_str_hash,
|
|
||||||
g_str_equal,
|
|
||||||
(GDestroyNotify)g_free,
|
|
||||||
(GDestroyNotify)g_object_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_name_vanished_callback (GDBusConnection *connection,
|
|
||||||
const gchar *name,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
EekboardClient *client = user_data;
|
|
||||||
g_signal_emit_by_name (client, "destroyed", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eekboard_client_new:
|
|
||||||
* @connection: a #GDBusConnection
|
|
||||||
* @cancellable: a #GCancellable
|
|
||||||
*
|
|
||||||
* Create a client.
|
|
||||||
*/
|
|
||||||
EekboardClient *
|
|
||||||
eekboard_client_new (GDBusConnection *connection,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
GInitable *initable;
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
g_assert (G_IS_DBUS_CONNECTION(connection));
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
initable =
|
|
||||||
g_initable_new (EEKBOARD_TYPE_CLIENT,
|
|
||||||
cancellable,
|
|
||||||
&error,
|
|
||||||
"g-connection", connection,
|
|
||||||
"g-name", "org.fedorahosted.Eekboard",
|
|
||||||
"g-interface-name", "org.fedorahosted.Eekboard",
|
|
||||||
"g-object-path", "/org/fedorahosted/Eekboard",
|
|
||||||
NULL);
|
|
||||||
if (initable != NULL) {
|
|
||||||
EekboardClient *client = EEKBOARD_CLIENT (initable);
|
|
||||||
gchar *name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY(client));
|
|
||||||
if (name_owner == NULL) {
|
|
||||||
g_object_unref (client);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the vanished callback is called when the server is disconnected */
|
|
||||||
g_bus_watch_name_on_connection (connection,
|
|
||||||
name_owner,
|
|
||||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
||||||
NULL,
|
|
||||||
eekboard_name_vanished_callback,
|
|
||||||
client,
|
|
||||||
NULL);
|
|
||||||
g_free (name_owner);
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_warning ("can't create client: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_context_destroyed (EekboardContext *context,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
EekboardClient *client = user_data;
|
|
||||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
|
||||||
|
|
||||||
g_hash_table_remove (priv->context_hash,
|
|
||||||
g_dbus_proxy_get_object_path (G_DBUS_PROXY(context)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eekboard_client_create_context:
|
|
||||||
* @eekboard: an #EekboardClient
|
|
||||||
* @client_name: name of the client
|
|
||||||
* @cancellable: a #GCancellable
|
|
||||||
*
|
|
||||||
* Create a new input context.
|
|
||||||
*
|
|
||||||
* Return value: (transfer full): a newly created #EekboardContext.
|
|
||||||
*/
|
|
||||||
EekboardContext *
|
|
||||||
eekboard_client_create_context (EekboardClient *client,
|
|
||||||
const gchar *client_name,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
GVariant *variant;
|
|
||||||
const gchar *object_path;
|
|
||||||
EekboardContext *context;
|
|
||||||
GError *error;
|
|
||||||
GDBusConnection *connection;
|
|
||||||
|
|
||||||
g_assert (EEKBOARD_IS_CLIENT(client));
|
|
||||||
g_assert (client_name);
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
variant = g_dbus_proxy_call_sync (G_DBUS_PROXY(client),
|
|
||||||
"CreateContext",
|
|
||||||
g_variant_new ("(s)", client_name),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
cancellable,
|
|
||||||
&error);
|
|
||||||
if (!variant) {
|
|
||||||
g_warning ("failed to call CreateContext: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_variant_get (variant, "(&s)", &object_path);
|
|
||||||
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY(client));
|
|
||||||
context = eekboard_context_new (connection, object_path, cancellable);
|
|
||||||
if (!context) {
|
|
||||||
g_variant_unref (variant);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
|
||||||
|
|
||||||
g_hash_table_insert (priv->context_hash,
|
|
||||||
g_strdup (object_path),
|
|
||||||
g_object_ref (context));
|
|
||||||
g_signal_connect (context, "destroyed",
|
|
||||||
G_CALLBACK(on_context_destroyed), client);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
eekboard_async_ready_callback (GObject *source_object,
|
|
||||||
GAsyncResult *res,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
GVariant *result;
|
|
||||||
|
|
||||||
result = g_dbus_proxy_call_finish (G_DBUS_PROXY(source_object),
|
|
||||||
res,
|
|
||||||
&error);
|
|
||||||
if (result)
|
|
||||||
g_variant_unref (result);
|
|
||||||
else {
|
|
||||||
g_warning ("error in D-Bus proxy call: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eekboard_client_push_context:
|
|
||||||
* @eekboard: an #EekboardClient
|
|
||||||
* @context: an #EekboardContext
|
|
||||||
* @cancellable: a #GCancellable
|
|
||||||
*
|
|
||||||
* Enable the input context @context and disable the others.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
eekboard_client_push_context (EekboardClient *client,
|
|
||||||
EekboardContext *context,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
const gchar *object_path;
|
|
||||||
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
|
||||||
|
|
||||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
|
||||||
|
|
||||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
|
|
||||||
|
|
||||||
context = g_hash_table_lookup (priv->context_hash,
|
|
||||||
object_path);
|
|
||||||
if (!context)
|
|
||||||
return;
|
|
||||||
|
|
||||||
eekboard_context_set_enabled (context, TRUE);
|
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
|
||||||
"PushContext",
|
|
||||||
g_variant_new ("(s)", object_path),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
cancellable,
|
|
||||||
eekboard_async_ready_callback,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eekboard_client_pop_context:
|
|
||||||
* @eekboard: an #EekboardClient
|
|
||||||
* @cancellable: a #GCancellable
|
|
||||||
*
|
|
||||||
* Disable the current input context and enable the previous one.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
eekboard_client_pop_context (EekboardClient *client,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
|
||||||
|
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
|
||||||
"PopContext",
|
|
||||||
NULL,
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
cancellable,
|
|
||||||
eekboard_async_ready_callback,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
eekboard_client_show_keyboard (EekboardClient *client,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
|
||||||
|
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
|
||||||
"ShowKeyboard",
|
|
||||||
NULL,
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
cancellable,
|
|
||||||
eekboard_async_ready_callback,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
eekboard_client_hide_keyboard (EekboardClient *client,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
|
||||||
|
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
|
||||||
"HideKeyboard",
|
|
||||||
NULL,
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
cancellable,
|
|
||||||
eekboard_async_ready_callback,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_destroy_context (EekboardClient *client,
|
|
||||||
EekboardContext *context,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
const gchar *object_path;
|
|
||||||
|
|
||||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
|
|
||||||
|
|
||||||
g_dbus_proxy_call (G_DBUS_PROXY(client),
|
|
||||||
"DestroyContext",
|
|
||||||
g_variant_new ("(s)", object_path),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
cancellable,
|
|
||||||
eekboard_async_ready_callback,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* eekboard_client_destroy_context:
|
|
||||||
* @eekboard: an #EekboardClient
|
|
||||||
* @context: an #EekboardContext
|
|
||||||
* @cancellable: a #GCancellable
|
|
||||||
*
|
|
||||||
* Remove @context from @eekboard.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
eekboard_client_destroy_context (EekboardClient *client,
|
|
||||||
EekboardContext *context,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
const gchar *object_path;
|
|
||||||
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CLIENT(client));
|
|
||||||
g_return_if_fail (EEKBOARD_IS_CONTEXT(context));
|
|
||||||
|
|
||||||
EekboardClientPrivate *priv = eekboard_client_get_instance_private (client);
|
|
||||||
|
|
||||||
object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY(context));
|
|
||||||
g_hash_table_remove (priv->context_hash, object_path);
|
|
||||||
|
|
||||||
send_destroy_context (client, context, cancellable);
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef EEKBOARD_CLIENT_H
|
|
||||||
#define EEKBOARD_CLIENT_H 1
|
|
||||||
|
|
||||||
#define __EEKBOARD_CLIENT_H_INSIDE__ 1
|
|
||||||
|
|
||||||
#include <gio/gio.h>
|
|
||||||
#include "eekboard/eekboard-context.h"
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define EEKBOARD_TYPE_CLIENT (eekboard_client_get_type())
|
|
||||||
G_DECLARE_DERIVABLE_TYPE (EekboardClient, eekboard_client, EEKBOARD, CLIENT, GDBusProxy)
|
|
||||||
|
|
||||||
struct _EekboardClientClass {
|
|
||||||
/*< private >*/
|
|
||||||
GDBusProxyClass parent_class;
|
|
||||||
|
|
||||||
/* signals */
|
|
||||||
void (* destroyed) (EekboardClient *self);
|
|
||||||
|
|
||||||
/*< private >*/
|
|
||||||
/* padding */
|
|
||||||
gpointer pdummy[23];
|
|
||||||
};
|
|
||||||
|
|
||||||
GType eekboard_client_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
EekboardClient *eekboard_client_new (GDBusConnection *connection,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
EekboardContext *eekboard_client_create_context (EekboardClient *eekboard,
|
|
||||||
const gchar *client_name,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
void eekboard_client_push_context (EekboardClient *eekboard,
|
|
||||||
EekboardContext *context,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
void eekboard_client_pop_context (EekboardClient *eekboard,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
void eekboard_client_show_keyboard (EekboardClient *eekboard,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
void eekboard_client_hide_keyboard (EekboardClient *eekboard,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
void eekboard_client_destroy_context (EekboardClient *eekboard,
|
|
||||||
EekboardContext *context,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
#endif /* EEKBOARD_CLIENT_H */
|
|
||||||
@ -135,6 +135,11 @@ eekboard_service_dispose (GObject *object)
|
|||||||
priv->introspection_data = NULL;
|
priv->introspection_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->context) {
|
||||||
|
g_signal_handlers_disconnect_by_data (priv->context, service);
|
||||||
|
priv->context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (eekboard_service_parent_class)->dispose (object);
|
G_OBJECT_CLASS (eekboard_service_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +171,22 @@ handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_visible(EekboardService *service,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
EekboardContextService *context)
|
||||||
|
{
|
||||||
|
gboolean visible;
|
||||||
|
EekboardServicePrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (EEKBOARD_IS_SERVICE (service));
|
||||||
|
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE (context));
|
||||||
|
|
||||||
|
priv = eekboard_service_get_instance_private (service);
|
||||||
|
g_object_get (context, "visible", &visible, NULL);
|
||||||
|
|
||||||
|
sm_puri_osk0_set_visible(priv->dbus_interface, visible);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eekboard_service_constructed (GObject *object)
|
eekboard_service_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
@ -173,7 +194,6 @@ eekboard_service_constructed (GObject *object)
|
|||||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||||
|
|
||||||
priv->dbus_interface = sm_puri_osk0_skeleton_new();
|
priv->dbus_interface = sm_puri_osk0_skeleton_new();
|
||||||
sm_puri_osk0_set_visible(priv->dbus_interface, FALSE); // TODO: use actual value
|
|
||||||
g_signal_connect(priv->dbus_interface, "handle-set-visible",
|
g_signal_connect(priv->dbus_interface, "handle-set-visible",
|
||||||
G_CALLBACK(handle_set_visible), service);
|
G_CALLBACK(handle_set_visible), service);
|
||||||
|
|
||||||
@ -279,5 +299,12 @@ eekboard_service_set_context(EekboardService *service,
|
|||||||
{
|
{
|
||||||
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
|
||||||
|
|
||||||
|
g_return_if_fail (!priv->context);
|
||||||
|
|
||||||
priv->context = context;
|
priv->context = context;
|
||||||
|
|
||||||
|
g_signal_connect_swapped (priv->context,
|
||||||
|
"notify::visible",
|
||||||
|
G_CALLBACK(on_visible),
|
||||||
|
service);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,168 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#include <string.h>
|
|
||||||
#include "eekboard/eekboard-xklutil.h"
|
|
||||||
|
|
||||||
XklConfigRec *
|
|
||||||
eekboard_xkl_config_rec_from_string (const gchar *layouts)
|
|
||||||
{
|
|
||||||
XklConfigRec *rec;
|
|
||||||
gchar **strv, **l, **v;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
strv = g_strsplit (layouts, "/", -1);
|
|
||||||
g_return_val_if_fail (g_strv_length (strv) == 3, NULL);
|
|
||||||
|
|
||||||
l = g_strsplit (strv[1], ";", -1);
|
|
||||||
v = g_strdupv (l);
|
|
||||||
for (i = 0; l[i]; i++) {
|
|
||||||
gchar *layout = l[i], *variant = v[i],
|
|
||||||
*variant_start, *variant_end;
|
|
||||||
|
|
||||||
variant_start = strchr (layout, '(');
|
|
||||||
variant_end = strrchr (layout, ')');
|
|
||||||
if (variant_start && variant_end) {
|
|
||||||
*variant_start++ = '\0';
|
|
||||||
g_strlcpy (variant, variant_start,
|
|
||||||
variant_end - variant_start + 1);
|
|
||||||
} else
|
|
||||||
*variant = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
rec = xkl_config_rec_new ();
|
|
||||||
rec->model = g_strdup (strv[0]);
|
|
||||||
rec->layouts = l;
|
|
||||||
rec->variants = v;
|
|
||||||
rec->options = g_strsplit (strv[2], ";", -1);
|
|
||||||
g_strfreev (strv);
|
|
||||||
|
|
||||||
return rec;
|
|
||||||
}
|
|
||||||
|
|
||||||
gchar *
|
|
||||||
eekboard_xkl_config_rec_to_string (XklConfigRec *rec)
|
|
||||||
{
|
|
||||||
gchar **strv, **sp, **lp, **vp, *p;
|
|
||||||
gint n_layouts;
|
|
||||||
GString *str;
|
|
||||||
|
|
||||||
n_layouts = g_strv_length (rec->layouts);
|
|
||||||
strv = g_malloc0_n (n_layouts + 2, sizeof (gchar *));
|
|
||||||
for (sp = strv, lp = rec->layouts, vp = rec->variants; *lp; sp++, lp++) {
|
|
||||||
if (*vp != NULL && **vp != '\0')
|
|
||||||
*sp = g_strdup_printf ("%s(%s)", *lp, *vp++);
|
|
||||||
else
|
|
||||||
*sp = g_strdup_printf ("%s", *lp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MODEL/L0(V0);L1(V1);...;Ln(Vn)/O0;O1;...;On */
|
|
||||||
str = g_string_new (rec->model);
|
|
||||||
|
|
||||||
g_string_append_c (str, '/');
|
|
||||||
p = g_strjoinv (";", strv);
|
|
||||||
g_strfreev (strv);
|
|
||||||
g_string_append (str, p);
|
|
||||||
g_free (p);
|
|
||||||
|
|
||||||
g_string_append_c (str, '/');
|
|
||||||
p = g_strjoinv (";", rec->options);
|
|
||||||
g_string_append (str, p);
|
|
||||||
g_free (p);
|
|
||||||
|
|
||||||
return g_string_free (str,FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static XklConfigItem *
|
|
||||||
xkl_config_item_copy (const XklConfigItem *item)
|
|
||||||
{
|
|
||||||
XklConfigItem *_item = xkl_config_item_new ();
|
|
||||||
memcpy (_item->name,
|
|
||||||
item->name,
|
|
||||||
sizeof (item->name));
|
|
||||||
memcpy (_item->short_description,
|
|
||||||
item->short_description,
|
|
||||||
sizeof (item->short_description));
|
|
||||||
memcpy (_item->description,
|
|
||||||
item->description,
|
|
||||||
sizeof (item->description));
|
|
||||||
return _item;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
prepend_item (XklConfigRegistry *registry,
|
|
||||||
const XklConfigItem *item,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GSList **list = data;
|
|
||||||
XklConfigItem *_item = xkl_config_item_copy (item);
|
|
||||||
*list = g_slist_prepend (*list, _item);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
compare_item_by_name (gconstpointer a, gconstpointer b)
|
|
||||||
{
|
|
||||||
const XklConfigItem *ia = a, *ib = b;
|
|
||||||
return g_strcmp0 (ia->name, ib->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList *
|
|
||||||
eekboard_xkl_list_models (XklConfigRegistry *registry)
|
|
||||||
{
|
|
||||||
GSList *list = NULL;
|
|
||||||
xkl_config_registry_foreach_model (registry, prepend_item, &list);
|
|
||||||
return g_slist_sort (list, compare_item_by_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList *
|
|
||||||
eekboard_xkl_list_layouts (XklConfigRegistry *registry)
|
|
||||||
{
|
|
||||||
GSList *list = NULL;
|
|
||||||
xkl_config_registry_foreach_layout (registry, prepend_item, &list);
|
|
||||||
return g_slist_sort (list, compare_item_by_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList *
|
|
||||||
eekboard_xkl_list_option_groups (XklConfigRegistry *registry)
|
|
||||||
{
|
|
||||||
GSList *list = NULL;
|
|
||||||
xkl_config_registry_foreach_option_group (registry, prepend_item, &list);
|
|
||||||
return g_slist_sort (list, compare_item_by_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList *
|
|
||||||
eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
|
|
||||||
const gchar *layout)
|
|
||||||
{
|
|
||||||
GSList *list = NULL;
|
|
||||||
xkl_config_registry_foreach_layout_variant (registry,
|
|
||||||
layout,
|
|
||||||
prepend_item,
|
|
||||||
&list);
|
|
||||||
return g_slist_sort (list, compare_item_by_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList *
|
|
||||||
eekboard_xkl_list_options (XklConfigRegistry *registry,
|
|
||||||
const gchar *group)
|
|
||||||
{
|
|
||||||
GSList *list = NULL;
|
|
||||||
xkl_config_registry_foreach_option (registry, group, prepend_item, &list);
|
|
||||||
return g_slist_sort (list, compare_item_by_name);
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* Copyright (C) 2011 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#ifndef EEKBOARD_XKLUTIL_H
|
|
||||||
#define EEKBOARD_XKLUTIL_H 1
|
|
||||||
|
|
||||||
#include <libxklavier/xklavier.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
XklConfigRec *eekboard_xkl_config_rec_from_string (const gchar *layouts);
|
|
||||||
gchar *eekboard_xkl_config_rec_to_string (XklConfigRec *rec);
|
|
||||||
|
|
||||||
GSList *eekboard_xkl_list_models (XklConfigRegistry *registry);
|
|
||||||
GSList *eekboard_xkl_list_layouts (XklConfigRegistry *registry);
|
|
||||||
GSList *eekboard_xkl_list_option_groups (XklConfigRegistry *registry);
|
|
||||||
GSList *eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
|
|
||||||
const gchar *layout);
|
|
||||||
GSList *eekboard_xkl_list_options (XklConfigRegistry *registry,
|
|
||||||
const gchar *group);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
#endif /* EEKBOARD_XKLUTIL_H */
|
|
||||||
20
meson.build
20
meson.build
@ -3,12 +3,14 @@ project(
|
|||||||
'c', 'rust',
|
'c', 'rust',
|
||||||
version: '1.0.10',
|
version: '1.0.10',
|
||||||
license: 'GPLv3',
|
license: 'GPLv3',
|
||||||
meson_version: '>=0.43.0',
|
meson_version: '>=0.49.0',
|
||||||
default_options: [ 'warning_level=1', 'buildtype=debugoptimized', 'c_std=gnu11' ],
|
default_options: [ 'warning_level=1', 'buildtype=debugoptimized', 'c_std=gnu11' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
i18n = import('i18n')
|
i18n = import('i18n')
|
||||||
|
|
||||||
|
conf_data = configuration_data()
|
||||||
|
|
||||||
if get_option('buildtype').startswith('debug')
|
if get_option('buildtype').startswith('debug')
|
||||||
add_project_arguments('-DDEBUG=1', language : 'c')
|
add_project_arguments('-DDEBUG=1', language : 'c')
|
||||||
endif
|
endif
|
||||||
@ -26,6 +28,22 @@ else
|
|||||||
endif
|
endif
|
||||||
dbusdir = join_paths(depdatadir, 'dbus-1/interfaces')
|
dbusdir = join_paths(depdatadir, 'dbus-1/interfaces')
|
||||||
|
|
||||||
|
gsound_dep = dependency('gsound', required : false)
|
||||||
|
if gsound_dep.found()
|
||||||
|
conf_data.set10('HAVE_GSOUND', true)
|
||||||
|
endif
|
||||||
|
|
||||||
|
summary = [
|
||||||
|
'',
|
||||||
|
'------------------',
|
||||||
|
'squeekboard @0@'.format(meson.project_version()),
|
||||||
|
'',
|
||||||
|
' gsound: @0@'.format(conf_data.get('HAVE_GSOUND', false)),
|
||||||
|
'------------------',
|
||||||
|
''
|
||||||
|
]
|
||||||
|
message('\n'.join(summary))
|
||||||
|
|
||||||
subdir('data')
|
subdir('data')
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
subdir('eek')
|
subdir('eek')
|
||||||
|
|||||||
6
src/config.h.in
Normal file
6
src/config.h.in
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
* Autogenerated by the Meson build system.
|
||||||
|
* Do not edit, your changes will be lost.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#mesondefine HAVE_GSOUND
|
||||||
@ -4,7 +4,10 @@ dbus_src = gnome.gdbus_codegen(
|
|||||||
join_paths(meson.source_root() / 'data' / 'dbus', 'sm.puri.OSK0.xml')
|
join_paths(meson.source_root() / 'data' / 'dbus', 'sm.puri.OSK0.xml')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
config_h = configure_file(input: 'config.h.in', output: 'config.h',configuration: conf_data)
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
|
config_h,
|
||||||
'imservice.c',
|
'imservice.c',
|
||||||
'server-context-service.c',
|
'server-context-service.c',
|
||||||
'server-main.c',
|
'server-main.c',
|
||||||
@ -60,6 +63,7 @@ deps = [
|
|||||||
cc.find_library('dl'),
|
cc.find_library('dl'),
|
||||||
cc.find_library('pthread'),
|
cc.find_library('pthread'),
|
||||||
# dependency('libxklavier'), # FIXME remove
|
# dependency('libxklavier'), # FIXME remove
|
||||||
|
gsound_dep,
|
||||||
]
|
]
|
||||||
|
|
||||||
# Replacement for eekboard-server
|
# Replacement for eekboard-server
|
||||||
|
|||||||
@ -275,6 +275,7 @@ set_geometry (ServerContextService *context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define KEYBOARD_HEIGHT 210
|
||||||
static void
|
static void
|
||||||
make_window (ServerContextService *context)
|
make_window (ServerContextService *context)
|
||||||
{
|
{
|
||||||
@ -285,13 +286,13 @@ make_window (ServerContextService *context)
|
|||||||
PHOSH_TYPE_LAYER_SURFACE,
|
PHOSH_TYPE_LAYER_SURFACE,
|
||||||
"layer-shell", squeek_wayland->layer_shell,
|
"layer-shell", squeek_wayland->layer_shell,
|
||||||
"wl-output", g_ptr_array_index(squeek_wayland->outputs, 0), // TODO: select output as needed,
|
"wl-output", g_ptr_array_index(squeek_wayland->outputs, 0), // TODO: select output as needed,
|
||||||
"height", 210,
|
"height", KEYBOARD_HEIGHT,
|
||||||
"anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
|
"anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
|
||||||
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
|
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
|
||||||
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
|
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
|
||||||
"layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
|
"layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
|
||||||
"kbd-interactivity", FALSE,
|
"kbd-interactivity", FALSE,
|
||||||
"exclusive-zone", 200,
|
"exclusive-zone", KEYBOARD_HEIGHT,
|
||||||
//"namespace", "phosh home",
|
//"namespace", "phosh home",
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user