Compare commits

..

4 Commits

Author SHA1 Message Date
33662d42ae Cleanups: fix g_type_init() deprecation warning
None of this seems necessary anymore. This file could be axed, but leave
it for now.
2019-07-04 22:11:24 +02:00
bf8e765c89 Cleanups: fix deprecations
gtk_widget_get_root_window()
	gdk_screen_get_monitor_at_window()
	gdk_screen_get_monitor_geometry()
2019-07-04 21:47:39 +02:00
36ee547506 Cleanups: fix gdk_cairo_create() deprecation warning 2019-07-04 21:37:06 +02:00
8e014aaaf8 Cleanups: fix deprecated g_type_class_add_private()
- use G_DECLARE_ and G_DEFINE_ macros
- move all data into ClassNamePrivate
- use _get_instance_private()

This should not introduce any functional changes or breakage.

Skipped two classes (EekKeyboard and EekboardContextService) for now in
order not to break the build.

These two classes are used in some very funky WIP code that tries to
circumvent encapsulation.

(Funky code is in eekboard/key-emitter.c and eekboard/eekboard-context-service.c)
2019-07-04 19:55:15 +02:00
131 changed files with 12558 additions and 4085 deletions

9
.gitignore vendored
View File

@ -1,9 +0,0 @@
.zanata-cache/
_build
TAGS
tags
vgdump
*.swp
*~
\#*#
.\#*

View File

@ -2,30 +2,20 @@ image: debian:buster
stages:
- build
- test
.tags: &tags
tags:
- librem5
before_script:
- apt-get -y update
- apt-get -y install wget gnupg2
- echo "deb http://ci.puri.sm/ scratch librem5" > /etc/apt/sources.list.d/ci.list
- wget -O- https://ci.puri.sm/ci-repo.key | apt-key add -
- apt-get -y update
- apt-get -y build-dep .
build_meson:
<<: *tags
stage: build
artifacts:
paths:
- _build
tags:
- librem5
script:
- meson . _build/ -Ddepdatadir=/usr/share
- ninja -C _build install
test:
<<: *tags
stage: test
dependencies:
- build_meson
script:
- xvfb-run -s -noreset ninja -C _build test

0
ChangeLog Normal file
View File

41
Makefile.am Normal file
View File

@ -0,0 +1,41 @@
# 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
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = eek eekboard src tests bindings docs po data examples
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection
AUTOMAKE_OPTIONS = foreign # allow README.md to exist
GITIGNOREFILES = \
INSTALL \
aclocal.m4 \
compile \
config.guess \
config.h.in \
config.sub \
depcomp \
gtk-doc.make \
install-sh \
ltmain.sh \
m4 \
missing \
mkinstalldirs \
$(NULL)
-include $(top_srcdir)/git.mk

0
NEWS Normal file
View File

View File

@ -33,8 +33,8 @@ See `.gitlab-ci.yml`.
### Build from git repo
```
$ git clone https://source.puri.sm/Librem5/squeekboard.git
$ cd squeekboard
$ git clone https://source.puri.sm/Librem5/eekboard.git
$ cd eekboard
$ mkdir ../build
$ meson ../build/
$ cd ../build

1
TODO Normal file
View File

@ -0,0 +1 @@
See https://github.com/ueno/eekboard/wiki/TODO

20
autogen.sh Executable file
View File

@ -0,0 +1,20 @@
#!/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

21
bindings/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
# 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
SUBDIRS = vala
-include $(top_srcdir)/git.mk

96
bindings/vala/Makefile.am Normal file
View File

@ -0,0 +1,96 @@
# 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
NULL =
if ENABLE_VALA
vapidir = $(datadir)/vala/vapi
dist_vapi_DATA = \
eek-$(EEK_API_VERSION).vapi \
eek-$(EEK_API_VERSION).deps \
eek-gtk-$(EEK_API_VERSION).vapi \
eek-gtk-$(EEK_API_VERSION).deps \
eek-xkl-$(EEK_API_VERSION).vapi \
eek-xkl-$(EEK_API_VERSION).deps \
$(NULL)
EXTRA_DIST = \
Eek-$(EEK_API_VERSION).metadata \
EekGtk-$(EEK_API_VERSION).metadata \
EekXkl-$(EEK_API_VERSION).metadata \
$(NULL)
GITIGNOREFILES = \
eek-$(EEK_API_VERSION).vapi \
eek-gtk-$(EEK_API_VERSION).vapi \
eek-xkl-$(EEK_API_VERSION).vapi \
$(NULL)
maintainer-clean-local:
rm -f *.vapi
eek_vapi_deps = \
$(srcdir)/Eek-$(EEK_API_VERSION).metadata \
| \
$(top_builddir)/eek/Eek-$(EEK_API_VERSION).gir \
$(NULL)
eek-$(EEK_API_VERSION).vapi: $(eek_vapi_deps)
$(VAPIGEN_V)$(VAPIGEN) \
--library eek-$(EEK_API_VERSION) \
--pkg gio-2.0 \
--metadatadir=$(srcdir) \
$(top_builddir)/eek/Eek-$(EEK_API_VERSION).gir
eek_gtk_vapi_deps = \
$(srcdir)/EekGtk-$(EEK_API_VERSION).metadata \
| \
$(top_builddir)/eek/EekGtk-$(EEK_API_VERSION).gir \
$(NULL)
eek-gtk-$(EEK_API_VERSION).vapi: $(eek_gtk_vapi_deps)
$(VAPIGEN_V)$(VAPIGEN) --vapidir=$(builddir) \
--library eek-gtk-$(EEK_API_VERSION) \
--pkg eek-$(EEK_API_VERSION) \
--pkg gio-2.0 \
--pkg gtk+-3.0 \
--metadatadir=$(srcdir) \
$(top_builddir)/eek/EekGtk-$(EEK_API_VERSION).gir
eek_xkl_vapi_deps = \
$(srcdir)/EekXkl-$(EEK_API_VERSION).metadata \
| \
$(top_builddir)/eek/EekXkl-$(EEK_API_VERSION).gir \
$(NULL)
eek-xkl-$(EEK_API_VERSION).vapi: $(eek_xkl_vapi_deps)
$(VAPIGEN_V)$(VAPIGEN) \
--vapidir=$(builddir) \
--library eek-xkl-$(EEK_API_VERSION) \
--pkg eek-$(EEK_API_VERSION) \
--pkg gio-2.0 \
--metadatadir=$(srcdir) \
$(top_builddir)/eek/EekXkl-$(EEK_API_VERSION).gir
# set up the verbosity rules to avoid some build noise
VAPIGEN_V = $(VAPIGEN_V_$(V))
VAPIGEN_V_ = $(VAPIGEN_V_$(AM_DEFAULT_VERBOSITY))
VAPIGEN_V_0 = @echo " VAPIG " $@;
endif
-include $(top_srcdir)/git.mk

245
configure.ac Normal file
View File

@ -0,0 +1,245 @@
# 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
AC_PREREQ(2.63)
dnl AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
AC_INIT([eekboard], [1.0.8], [ueno@unixuser.org])
dnl Init automake
AM_INIT_AUTOMAKE
AM_MAINTAINER_MODE([enable])
AC_GNU_SOURCE
dnl Support silent build
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
dnl Check for programs
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CC_STDC
AC_PROG_INSTALL
AC_PROG_CXX
# define PACKAGE_VERSION_* variables
AM_DISABLE_STATIC
AC_ISC_POSIX
AC_HEADER_STDC
LT_INIT
IT_PROG_INTLTOOL([0.35.0])
GTK_API_VERSION=3.0
GTK_REQUIRED=2.91.0
EEK_API_VERSION=0.90
EEK_API_MAJOR_VERSION=0
EEK_API_MINOR_VERSION=90
EEK_API_PC_VERSION=0.90
EEK_LIBRARY_SUFFIX="-$EEK_API_VERSION"
AC_SUBST([GTK_API_VERSION])
AC_SUBST([EEK_API_VERSION])
AC_SUBST([EEK_API_MAJOR_VERSION])
AC_SUBST([EEK_API_MINOR_VERSION])
AC_SUBST([EEK_API_PC_VERSION])
AC_SUBST([EEK_LIBRARY_SUFFIX])
AC_SUBST([EEK_LIBRARY_SUFFIX_U],[AS_TR_SH([$EEK_LIBRARY_SUFFIX])])
AM_PATH_GLIB_2_0
PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.26.0], ,
[AC_MSG_ERROR([GLib2 not found])])
PKG_CHECK_MODULES([GIO2], [gio-2.0], ,
[AC_MSG_ERROR([Gio2 not found])])
GLIB_GSETTINGS
PKG_CHECK_MODULES([PANGOCAIRO], [pangocairo], ,
[AC_MSG_ERROR([PangoCairo not found])])
PKG_CHECK_MODULES([GTK], [
gtk+-$GTK_API_VERSION >= $GTK_REQUIRED
gdk-$GTK_API_VERSION >= $GTK_REQUIRED], ,
[AC_MSG_ERROR([GTK not found])])
PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], ,
[AC_MSG_ERROR([Libxklavier not found])])
PKG_CHECK_MODULES([LIBCROCO], [libcroco-0.6], ,
[AC_MSG_ERROR([libcroco not found])])
dnl use XTest to generate key events
AC_MSG_CHECKING([whether you enable XTest])
AC_ARG_ENABLE(xtest,
AS_HELP_STRING([--enable-xtest=no/yes],
[Enable XTest default=yes]),
enable_xtest=$enableval,
enable_xtest=yes)
if test x$enable_xtest = xyes; then
PKG_CHECK_MODULES([XTEST], [xtst], , enable_xtest=no)
if test x$enable_xtest = xyes; then
AC_DEFINE([HAVE_XTEST], [1], [Define if XTest is found])
fi
fi
AM_CONDITIONAL(ENABLE_XTEST, [test x$enable_xtest = xyes])
AC_MSG_RESULT($enable_xtest)
dnl use X to mark the fullscreen window as dock
AC_MSG_CHECKING([whether you enable X dock])
AC_ARG_ENABLE(x-dock,
AS_HELP_STRING([--enable-x-dock=no/yes],
[Enable X dock default=yes]),
enable_x_dock=$enableval,
enable_x_dock=yes)
if test x$enable_x_dock = xyes; then
PKG_CHECK_MODULES([XDOCK], [x11], , enable_x_dock=no)
if test x$enable_x_dock = xyes; then
AC_DEFINE([HAVE_XDOCK], [1], [Define if X dock is found])
fi
fi
AM_CONDITIONAL(ENABLE_XDOCK, [test x$enable_x_dock = xyes])
AC_MSG_RESULT($enable_x_dock)
focus_listeners="ibus"
keystroke_listeners=""
dnl use AT-SPI 2 to capture focus/keystroke events
AC_MSG_CHECKING([whether you enable AT-SPI 2 event handling])
AC_ARG_ENABLE(atspi,
AS_HELP_STRING([--enable-atspi=no/yes],
[Enable AT-SPI 2 event handling default=yes]),
enable_atspi=$enableval,
enable_atspi=yes)
if test x$enable_atspi = xyes; then
PKG_CHECK_MODULES([ATSPI2], [atspi-2], , enable_atspi=no)
if test x$enable_atspi = xyes; then
AC_DEFINE([HAVE_ATSPI], [1], [Define if AT-SPI 2 is found])
focus_listeners="atspi $focus_listeners"
keystroke_listeners="atspi $keystroke_listeners"
fi
fi
AC_MSG_RESULT($enable_atspi)
AM_CONDITIONAL(ENABLE_ATSPI, [test x$enable_atspi = xyes])
if test -n "$focus_listeners"; then
AC_DEFINE(ENABLE_FOCUS_LISTENER, [1], [Define if eekboard can follow focus changes])
fi
GOBJECT_INTROSPECTION_CHECK([0.9.0])
dnl Vala langauge binding
AC_MSG_CHECKING([whether you enable Vala language support])
AC_ARG_ENABLE(vala,
AS_HELP_STRING([--enable-vala=no/yes],
[Enable Vala language binding default=yes]),
enable_vala=$enableval,
enable_vala=yes)
if test x$enable_vala = xyes; then
if test "x$INTROSPECTION_SCANNER" = x; then
enable_vala=no
AC_MSG_WARN([GObject-Introspection must be enabled for Vala bindings])
fi
AM_PROG_VALAC([0.10.0])
have_vala=yes
AC_PATH_PROG(VALAC, valac, valac)
AC_SUBST(VALAC)
AC_SUBST(VALAFLAGS)
AC_PATH_PROG([VAPIGEN], [vapigen], [false])
if test "x$VAPIGEN" = "xfalse"; then
enable_vala=no
AC_MSG_WARN([vapigen not found. Was vala compiled with --enable-vapigen?])
fi
AC_SUBST(VAPIGEN)
fi
AC_MSG_RESULT($enable_vala)
AM_CONDITIONAL(ENABLE_VALA, [test x$enable_vala = xyes])
dnl libcanberra
AC_MSG_CHECKING([whether you enable libcanberra])
AC_ARG_ENABLE(libcanberra,
AS_HELP_STRING([--enable-libcanberra=no/yes],
[Enable libcanberra user interface default=no]),
enable_libcanberra=$enableval,
enable_libcanberra=yes)
if test x$enable_libcanberra = xyes; then
PKG_CHECK_MODULES([LIBCANBERRA], [libcanberra-gtk3], , enable_libcanberra=no)
if test x$enable_libcanberra = xyes; then
AC_DEFINE([HAVE_LIBCANBERRA], [1], [Define if libcanberra is found])
fi
fi
AM_CONDITIONAL(ENABLE_LIBCANBERRA, [test x$enable_libcanberra = xyes])
AC_MSG_RESULT($enable_libcanberra)
GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
dnl define GETTEXT_* variables
GETTEXT_PACKAGE=$PACKAGE
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Define to the read-only architecture-independent data directory.])
AM_GLIB_GNU_GETTEXT
AM_GLIB_DEFINE_LOCALEDIR(EEKBOARD_LOCALEDIR)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile
eek/Makefile
eekboard/Makefile
src/Makefile
tests/Makefile
bindings/Makefile
bindings/vala/Makefile
docs/Makefile
docs/reference/Makefile
docs/reference/eek/Makefile
docs/reference/eekboard/Makefile
po/Makefile.in
data/Makefile
data/icons/Makefile
data/icons/16x16/Makefile
data/icons/22x22/Makefile
data/icons/24x24/Makefile
data/icons/32x32/Makefile
data/icons/48x48/Makefile
data/icons/scalable/Makefile
data/themes/Makefile
data/keyboards/Makefile
examples/Makefile
examples/simple-client/Makefile
eek/eek-${EEK_API_VERSION}.pc
eek/eek-gtk-${EEK_API_VERSION}.pc
eek/eek-xkl-${EEK_API_VERSION}.pc
eekboard/eekboard-${EEK_API_VERSION}.pc])
AC_OUTPUT
AC_MSG_RESULT([
Build options:
Version $VERSION
Install prefix $prefix
Build shared libs $enable_shared
Build static libs $enable_static
CFLAGS $CFLAGS
Build Vala binding $enable_vala
Sound support $enable_libcanberra
Build document $enable_gtk_doc
Focus listeners $focus_listeners
Keystroke listeners $keystroke_listeners
])

35
data/Makefile.am Normal file
View File

@ -0,0 +1,35 @@
SUBDIRS = icons themes keyboards
@GSETTINGS_RULES@
@INTLTOOL_XML_NOMERGE_RULE@
gsettings_schemas_in_files = org.fedorahosted.eekboard.gschema.xml.in
gsettings_SCHEMAS = $(gsettings_schemas_in_files:.gschema.xml.in=.gschema.xml)
servicedir = $(datadir)/dbus-1/services
service_in_files = eekboard-server.service.in
service_DATA = $(service_in_files:.service.in=.service)
$(service_DATA): $(service_in_files) Makefile
$(AM_V_GEN) sed -e "s|\@bindir\@|$(bindir)|" $< > $@
desktopdir = $(datadir)/applications
desktop_in_files = eekboard.desktop.in
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
if ENABLE_ATSPI
autostartdir = $(sysconfdir)/xdg/autostart
autostart_in_files = eekboard-autostart.desktop.in
autostart_DATA = $(autostart_in_files:.desktop.in=.desktop)
endif
@INTLTOOL_DESKTOP_RULE@
CLEANFILES = $(service_DATA) $(desktop_DATA) $(gsettings_SCHEMAS)
EXTRA_DIST = $(service_in_files) $(desktop_in_files) $(gsettings_schemas_in_files)
if ENABLE_ATSPI
CLEANFILES += $(autostart_DATA)
EXTRA_DIST += $(autostart_in_files)
endif
-include $(top_srcdir)/git.mk

View File

@ -1,20 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name="sm.puri.OSK0">
<method name="SetVisible">
<arg name="visible" type="b" direction="in"/>
<doc:doc><doc:description>
Switch keyboard visibility
</doc:description></doc:doc>
</method>
<method name="GetVisible">
<arg name="visible" type="b" direction="out"/>
<doc:doc><doc:description>
Get keyboard visibility
</doc:description></doc:doc>
</method>
<property name="Visible" type="b" access="read">
</property>
</interface>
</node>

View File

@ -0,0 +1,17 @@
size = 16x16
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi
-include $(top_srcdir)/git.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

View File

@ -0,0 +1,17 @@
size = 22x22
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi
-include $(top_srcdir)/git.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

View File

@ -0,0 +1,17 @@
size = 24x24
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi
-include $(top_srcdir)/git.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 B

View File

@ -0,0 +1,17 @@
size = 32x32
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi
-include $(top_srcdir)/git.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,17 @@
size = 48x48
icondir = $(datadir)/icons/hicolor/$(size)/apps
dist_icon_DATA = eekboard.png
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi
-include $(top_srcdir)/git.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

3
data/icons/Makefile.am Normal file
View File

@ -0,0 +1,3 @@
SUBDIRS = 16x16 22x22 24x24 32x32 48x48 scalable
-include $(top_srcdir)/git.mk

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
version="1.1" viewBox="0 0 24 24">
<path d="M 24,1 L 24,10 C 24,15 20,17 17,17 L 7,17 L 10,20 L 10,23
L 7,23 L 0,15 L 7,7 L 10,7 L 10,10 L 7,13 L 17,13
C 19,13 20,12 20,10 L 20,1 Z"
stroke="none" fill="black" />
</svg>

Before

Width:  |  Height:  |  Size: 388 B

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"
version="1.1" viewBox="0 0 24 24">
<path d="M 12,2 L 22,14 L 16,14 L 16,22 L 8,22 L 8,14 L 2,14 Z"
stroke="none" fill="black" />
</svg>

Before

Width:  |  Height:  |  Size: 279 B

View File

@ -1,52 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,15 @@
icondir = $(datadir)/icons/hicolor/scalable/apps
dist_icon_DATA = eekboard.svg
gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
install-data-hook:
@-if test -z "$(DESTDIR)"; then \
echo "Updating Gtk icon cache."; \
$(gtk_update_icon_cache); \
else \
echo "*** Icon cache not updated. After install, run this:"; \
echo "*** $(gtk_update_icon_cache)"; \
fi
-include $(top_srcdir)/git.mk

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 472 KiB

View File

@ -0,0 +1,40 @@
keyboardsdir = $(pkgdatadir)/keyboards
nobase_dist_keyboards_DATA = \
keyboards.xml \
geometry/compact.xml \
symbols/ar.xml \
symbols/be.xml \
symbols/fa.xml \
symbols/he.xml \
symbols/ja-kana.xml \
symbols/kk.xml \
symbols/ks.xml \
symbols/my.xml \
symbols/ru.xml \
symbols/th.xml \
symbols/ua.xml \
symbols/ug.xml \
symbols/us.xml \
symbols/zh-bopomofo.xml \
$(inscript_symbols) \
$(NULL)
inscript_symbols = \
symbols/as-inscript.xml \
symbols/bn-inscript.xml \
symbols/gu-inscript.xml \
symbols/hi-inscript.xml \
symbols/kn-inscript.xml \
symbols/ks-inscript.xml \
symbols/mai-inscript.xml \
symbols/ml-inscript.xml \
symbols/mr-inscript.xml \
symbols/or-inscript.xml \
symbols/pa-inscript.xml \
symbols/sd-inscript.xml \
symbols/ta-inscript.xml \
symbols/te-inscript.xml \
$(NULL)
-include $(top_srcdir)/git.mk

View File

@ -1,120 +1,189 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="10" y="10" width="410.0000" height="229"/>
<bounds x="0.000000" y="0.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
<key name="AD06" oref="outline2" />
<key name="AD07" oref="outline2" />
<key name="AD08" oref="outline2" />
<key name="AD09" oref="outline2" />
<key name="AD10" oref="outline2" />
<key keycode="24" name="AD01" oref="outline2">
<bounds x="65.56097" y="42.14634" width="37.46341" height="52.44877"/>
</key>
<key keycode="25" name="AD02" oref="outline2">
<bounds x="106.1463" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="26" name="AD03" oref="outline2">
<bounds x="145.1707" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="27" name="AD04" oref="outline2">
<bounds x="185.7560" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="28" name="AD05" oref="outline2">
<bounds x="226.3414" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="29" name="AD06" oref="outline2">
<bounds x="266.9268" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="30" name="AD07" oref="outline2">
<bounds x="307.5121" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="31" name="AD08" oref="outline2">
<bounds x="348.0975" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="32" name="AD09" oref="outline2">
<bounds x="388.6829" y="42.14634" width="37.46341" height="37.46341"/>
</key>
<key keycode="33" name="AD10" oref="outline2">
<bounds x="429.2682" y="42.14634" width="37.46341" height="37.46341"/>
</key>
</row>
</section>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
<key name="AC06" oref="outline2" />
<key name="AC07" oref="outline2" />
<key name="AC08" oref="outline2" />
<key name="AC09" oref="outline2" />
<key name="AC10" oref="outline2" />
<key keycode="38" name="AC01" oref="outline2">
<bounds x="76.48780" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="39" name="AC02" oref="outline2">
<bounds x="115.5121" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="40" name="AC03" oref="outline2">
<bounds x="156.0975" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="41" name="AC04" oref="outline2">
<bounds x="196.6829" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="42" name="AC05" oref="outline2">
<bounds x="237.2682" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="43" name="AC06" oref="outline2">
<bounds x="277.8536" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="44" name="AC07" oref="outline2">
<bounds x="318.4390" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="45" name="AC08" oref="outline2">
<bounds x="359.0243" y="82.73170" width="37.46341" height="37.46341"/>
</key>
<key keycode="46" name="AC09" oref="outline2">
<bounds x="399.6097" y="82.73170" width="37.46341" height="37.46341"/>
</key>
</row>
</section>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key name="LFSH" oref="altline" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
<key name="AB06" oref="outline2" />
<key name="AB07" oref="outline2" />
<key name="BKSP" oref="altline" />
<key keycode="50" name="LFSH" oref="altline">
<bounds x="3.121951" y="121.7560" width="88.97561" height="37.46341"/>
</key>
<key keycode="52" name="AB01" oref="outline2">
<bounds x="95.21951" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="53" name="AB02" oref="outline2">
<bounds x="135.8048" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="54" name="AB03" oref="outline2">
<bounds x="176.3902" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="55" name="AB04" oref="outline2">
<bounds x="215.4146" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="56" name="AB05" oref="outline2">
<bounds x="256.0000" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="57" name="AB06" oref="outline2">
<bounds x="296.5853" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="58" name="AB07" oref="outline2">
<bounds x="337.1707" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="22" name="BKSP" oref="altline">
<bounds x="529.1707" y="1.560976" width="79.60975" height="37.46341"/>
</key>
</row>
</section>
<section angle="0">
<bounds x="0" y="0" width="608.7804" height="201.3658"/>
<row orientation="1">
<key keycode="0" name="ABC123" oref="altline" />
<key name="I149" oref="altline" />
<key name="SPCE" oref="spaceline" />
<key name="AB08" oref="outline2" />
<key name="RTRN" oref="outline7" />
<key keycode="37" name="LCTL" oref="altline">
<bounds x="62.43902" y="162.3414" width="48.39024" height="37.46341"/>
</key>
<key keycode="66" name="ALTGR" oref="altline">
<bounds x="113.9512" y="162.3414" width="48.39024" height="37.46341"/>
</key>
<key keycode="65" name="SPCE" oref="spaceline">
<bounds x="165.4634" y="162.3414" width="217.5853" height="37.46341"/>
</key>
<key keycode="60" name="AB09" oref="outline2">
<bounds x="418.3414" y="121.7560" width="37.46341" height="37.46341"/>
</key>
<key keycode="36" name="RTRN" oref="outline7">
<bounds x="519.8048" y="82.73170" width="88.97561" height="37.46341"/>
</key>
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52"/>
<point x="0.000000" y="52"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="altline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="48.39024" y="0.000000"/>
<point x="48.39024" y="52"/>
<point x="0.000000" y="52"/>
<point x="48.39024" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52"/>
<point x="0.000000" y="52"/>
<point x="68.68292" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52"/>
<point x="0.000000" y="52"/>
<point x="109.2682" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52"/>
<point x="0.000000" y="52"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52"/>
<point x="0.000000" y="52"/>
<point x="79.60975" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="150.5853" y="0.000000"/>
<point x="150.5853" y="52"/>
<point x="0.000000" y="52"/>
<point x="150.5853" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
</geometry>

View File

@ -1,122 +0,0 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
<key name="AD06" oref="outline2" />
<key name="AD07" oref="outline2" />
<key name="AD08" oref="outline2" />
<key name="AD09" oref="outline2" />
<key name="AD10" oref="outline2" />
<key name="AD11" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
<key name="AC06" oref="outline2" />
<key name="AC07" oref="outline2" />
<key name="AC08" oref="outline2" />
<key name="AC09" oref="outline2" />
<key name="AC10" oref="outline2" />
<key name="AC11" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="LFSH" oref="altline" />
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
<key name="AB06" oref="outline2" />
<key name="AB07" oref="outline2" />
<key name="BKSP" oref="altline" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key keycode="0" name="ABC123" oref="altline" />
<key name="I149" oref="altline" />
<key name="SPCE" oref="spaceline" />
<key name="AB08" oref="outline2" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="32" y="0.000000"/>
<point x="32" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="altline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="48.39024" y="0.000000"/>
<point x="48.39024" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52"/>
<point x="0.000000" y="52"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="150.5853" y="0.000000"/>
<point x="150.5853" y="52"/>
<point x="0.000000" y="52"/>
</outline>
</geometry>

View File

@ -1,105 +0,0 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<section angle="0">
<row orientation="1">
<key name="AD01" oref="outline2" />
<key name="AD02" oref="outline2" />
<key name="AD03" oref="outline2" />
<key name="AD04" oref="outline2" />
<key name="AD05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AC01" oref="outline2" />
<key name="AC02" oref="outline2" />
<key name="AC03" oref="outline2" />
<key name="AC04" oref="outline2" />
<key name="AC05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="AB01" oref="outline2" />
<key name="AB02" oref="outline2" />
<key name="AB03" oref="outline2" />
<key name="AB04" oref="outline2" />
<key name="AB05" oref="outline2" />
</row>
</section>
<section angle="0">
<row orientation="1">
<key name="BKSP" oref="altline" />
<key name="AB06" oref="outline2" />
<key name="SPCE" oref="spaceline" />
<key name="RTRN" oref="outline7" />
</row>
</section>
<outline id="outline2" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="altline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="48.39024" y="0.000000"/>
<point x="48.39024" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline4" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline5" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="59.31707" y="0.000000"/>
<point x="59.31707" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline6" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="68.68292" y="0.000000"/>
<point x="68.68292" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline7" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline8" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="88.97561" y="0.000000"/>
<point x="88.97561" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline9" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="109.2682" y="0.000000"/>
<point x="109.2682" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline10" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="37.46341" y="0.000000"/>
<point x="37.46341" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="outline13" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="79.60975" y="0.000000"/>
<point x="79.60975" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
<outline id="spaceline" corner-radius="1.000000">
<point x="0.000000" y="0.000000"/>
<point x="120.5853" y="0.000000"/>
<point x="120.5853" y="52.44877"/>
<point x="0.000000" y="52.44877"/>
</outline>
</geometry>

View File

@ -24,9 +24,6 @@
<keyboard id="my" name="my"
geometry="compact" symbols="my"
longname="Myanmar" language="my"/>
<keyboard id="nb" name="nb"
geometry="extended" symbols="nb"
longname="Norwegian" language="nb"/>
<keyboard id="ru" name="ru"
geometry="compact" symbols="us"
longname="Russian" language="ru"/>
@ -88,13 +85,4 @@
<keyboard id="te-inscript" name="te-inscript"
geometry="compact" symbols="te-inscript"
longname="Telugu (Inscript)" language="te"/>
<!-- Common keyboards -->
<keyboard id="number" name="number"
geometry="number-keypad" symbols="special/number"
longname="Numeric keypad" language="all"/>
<keyboard id="phone" name="phone"
geometry="number-keypad" symbols="special/number"
longname="Phone keypad" language="all"/>
</keyboards>

View File

@ -1,206 +0,0 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<symbols version="0.90">
<key name="AD01">
<symbol label="q">q</symbol>
<symbol label="Q">Q</symbol>
<symbol label="1">1</symbol>
<symbol label="~">asciitilde</symbol>
</key>
<key name="AD02">
<symbol label="w">w</symbol>
<symbol label="W">W</symbol>
<symbol label="2">2</symbol>
<symbol label="`">quoteleft</symbol>
</key>
<key name="AD03">
<symbol label="e">e</symbol>
<symbol label="E">E</symbol>
<symbol label="3">3</symbol>
<symbol label="|">bar</symbol>
</key>
<key name="AD04">
<symbol label="r">r</symbol>
<symbol label="R">R</symbol>
<symbol label="4">4</symbol>
<symbol label="&#183;">U00B7</symbol>
</key>
<key name="AD05">
<symbol label="t">t</symbol>
<symbol label="T">T</symbol>
<symbol label="5">5</symbol>
<symbol label="&#8730;">squareroot</symbol>
</key>
<key name="AD06">
<symbol label="y">y</symbol>
<symbol label="Y">Y</symbol>
<symbol label="6">6</symbol>
<symbol label="&#960;">Greek_pi</symbol>
</key>
<key name="AD07">
<symbol label="u">u</symbol>
<symbol label="U">U</symbol>
<symbol label="7">7</symbol>
<symbol label="&#247;">division</symbol>
</key>
<key name="AD08">
<symbol label="i">i</symbol>
<symbol label="I">I</symbol>
<symbol label="8">8</symbol>
<symbol label="&#215;">multiply</symbol>
</key>
<key name="AD09">
<symbol label="o">o</symbol>
<symbol label="O">O</symbol>
<symbol label="9">9</symbol>
<symbol label="&#182;">paragraph</symbol>
</key>
<key name="AD10">
<symbol label="p">p</symbol>
<symbol label="P">P</symbol>
<symbol label="0">0</symbol>
<symbol label="&#9651;">U25B3</symbol>
</key>
<key name="AD11">
<symbol keyval="229" label="&#229;">aring</symbol>
<symbol keyval="197" label="&#197;">Aring</symbol>
<symbol label=""></symbol>
<symbol label=""></symbol>
<!-- Empty labels cause keys to be hidden when the level they are defined
for is shown. -->
</key>
<key name="AC01">
<symbol label="a">a</symbol>
<symbol label="A">A</symbol>
<symbol label="@">at</symbol>
<symbol label="&#169;">copyright</symbol>
</key>
<key name="AC02">
<symbol label="s">s</symbol>
<symbol label="S">S</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="&#174;">U00AE</symbol>
</key>
<key name="AC03">
<symbol label="d">d</symbol>
<symbol label="D">D</symbol>
<symbol label="$">dollar</symbol>
<symbol label="&#163;">U00A3</symbol>
</key>
<key name="AC04">
<symbol label="f">f</symbol>
<symbol label="F">F</symbol>
<symbol label="%">percent</symbol>
<symbol label="&#8364;">EuroSign</symbol>
</key>
<key name="AC05">
<symbol label="g">g</symbol>
<symbol label="G">G</symbol>
<symbol label="&amp;">ampersand</symbol>
<symbol label="&#165;">U00A5</symbol>
</key>
<key name="AC06">
<symbol label="h">h</symbol>
<symbol label="H">H</symbol>
<symbol label="-">minus</symbol>
<symbol label="^">asciicircum</symbol>
</key>
<key name="AC07">
<symbol label="j">j</symbol>
<symbol label="J">J</symbol>
<symbol label="_">underscore</symbol>
<symbol label="&#176;">degree</symbol>
</key>
<key name="AC08">
<symbol label="k">k</symbol>
<symbol label="K">K</symbol>
<symbol label="+">plus</symbol>
<symbol label="=">equal</symbol>
</key>
<key name="AC09">
<symbol label="l">l</symbol>
<symbol label="L">L</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="{">braceleft</symbol>
</key>
<key name="AC10">
<symbol keyval="248" label="&#248;">oslash</symbol>
<symbol keyval="216" label="&#216;">Oslash</symbol>
<symbol label=")">parenright</symbol>
<symbol label="}">braceright</symbol>
</key>
<key name="AC11">
<symbol keyval="230" label="&#230;">ae</symbol>
<symbol keyval="198" label="&#198;">AE</symbol>
<symbol label=""></symbol>
<symbol label=""></symbol>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key>
<key name="LFSH">
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" label="=/+">Shift_L</keysym>
<keysym keyval="65505" label="123">Shift_L</keysym>
</key>
<key name="AB01">
<symbol label="z">z</symbol>
<symbol label="Z">Z</symbol>
<symbol label=",">comma</symbol>
<symbol label="\">backslash</symbol>
</key>
<key name="AB02">
<symbol label="x">x</symbol>
<symbol label="X">X</symbol>
<symbol label="&quot;">quotedbl</symbol>
<symbol label="/">slash</symbol>
</key>
<key name="AB03">
<symbol label="c">c</symbol>
<symbol label="C">C</symbol>
<symbol label="'">quoteright</symbol>
<symbol label="&lt;">less</symbol>
</key>
<key name="AB04">
<symbol label="v">v</symbol>
<symbol label="V">V</symbol>
<symbol label=":">colon</symbol>
<symbol label="&gt;">greater</symbol>
</key>
<key name="AB05">
<symbol label="b">b</symbol>
<symbol label="B">B</symbol>
<symbol label=";">semicolon</symbol>
<symbol label="=">equal</symbol>
</key>
<key name="AB06">
<symbol label="n">n</symbol>
<symbol label="N">N</symbol>
<symbol label="!">exclam</symbol>
<symbol label="[">bracketleft</symbol>
</key>
<key name="AB07">
<symbol label="m">m</symbol>
<symbol label="M">M</symbol>
<symbol label="?">question</symbol>
<symbol label="]">bracketright</symbol>
</key>
<key name="AB08">
<symbol label=".">period</symbol>
</key>
<key name="ABC123">
<symbol label="123">show-numbers</symbol>
<symbol label="123">show-numbers</symbol>
<symbol label="ABC">show-letters</symbol>
<symbol label="ABC">show-letters</symbol>
</key>
<key name="I149">
<symbol icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
</key>
<key name="SPCE">
<symbol label=" ">space</symbol>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key>
</symbols>

View File

@ -1,60 +0,0 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<symbols version="0.90">
<key name="AD01">
<symbol label="1">1</symbol>
</key>
<key name="AD02">
<symbol label="2">2</symbol>
</key>
<key name="AD03">
<symbol label="3">3</symbol>
</key>
<key name="AD04">
<symbol label="(">parenleft</symbol>
</key>
<key name="AD05">
<symbol label=")">parenright</symbol>
</key>
<key name="AC01">
<symbol label="4">4</symbol>
</key>
<key name="AC02">
<symbol label="5">5</symbol>
</key>
<key name="AC03">
<symbol label="6">6</symbol>
</key>
<key name="AC04">
<symbol label="#">numbersign</symbol>
</key>
<key name="AC05">
<symbol label="*">asterisk</symbol>
</key>
<key name="AB01">
<symbol label="7">7</symbol>
</key>
<key name="AB02">
<symbol label="8">8</symbol>
</key>
<key name="AB03">
<symbol label="9">9</symbol>
</key>
<key name="AB04">
<symbol label="+">plus</symbol>
</key>
<key name="AB05">
<symbol label="-">minus</symbol>
</key>
<key name="AB06">
<symbol label="0">0</symbol>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
</key>
<key name="SPCE">
<symbol label=" ">space</symbol>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</key>
</symbols>

View File

@ -1,194 +1,304 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<?xml version="1.0"?>
<symbols version="0.90">
<key name="AD01">
<symbol label="q">q</symbol>
<symbol label="Q">Q</symbol>
<symbol label="1">1</symbol>
<symbol label="~">asciitilde</symbol>
<key keycode="9" name="ESC">
<keysym keyval="65307">Escape</keysym>
</key>
<key name="AD02">
<symbol label="w">w</symbol>
<symbol label="W">W</symbol>
<symbol label="2">2</symbol>
<symbol label="`">quoteleft</symbol>
<key keycode="67" name="FK01">
<keysym keyval="65470">F1</keysym>
</key>
<key name="AD03">
<symbol label="e">e</symbol>
<symbol label="E">E</symbol>
<symbol label="3">3</symbol>
<symbol label="|">bar</symbol>
<key keycode="68" name="FK02">
<keysym keyval="65471">F2</keysym>
</key>
<key name="AD04">
<symbol label="r">r</symbol>
<symbol label="R">R</symbol>
<symbol label="4">4</symbol>
<symbol label="&#183;">U00B7</symbol>
<key keycode="69" name="FK03">
<keysym keyval="65472">F3</keysym>
</key>
<key name="AD05">
<symbol label="t">t</symbol>
<symbol label="T">T</symbol>
<symbol label="5">5</symbol>
<symbol label="&#8730;">squareroot</symbol>
<key keycode="70" name="FK04">
<keysym keyval="65473">F4</keysym>
</key>
<key name="AD06">
<symbol label="y">y</symbol>
<symbol label="Y">Y</symbol>
<symbol label="6">6</symbol>
<symbol label="&#960;">Greek_pi</symbol>
<key keycode="71" name="FK05">
<keysym keyval="65474">F5</keysym>
</key>
<key name="AD07">
<symbol label="u">u</symbol>
<symbol label="U">U</symbol>
<symbol label="7">7</symbol>
<symbol label="&#247;">division</symbol>
<key keycode="72" name="FK06">
<keysym keyval="65475">F6</keysym>
</key>
<key name="AD08">
<symbol label="i">i</symbol>
<symbol label="I">I</symbol>
<symbol label="8">8</symbol>
<symbol label="&#215;">multiply</symbol>
<key keycode="73" name="FK07">
<keysym keyval="65476">F7</keysym>
</key>
<key name="AD09">
<symbol label="o">o</symbol>
<symbol label="O">O</symbol>
<symbol label="9">9</symbol>
<symbol label="&#182;">paragraph</symbol>
<key keycode="74" name="FK08">
<keysym keyval="65477">F8</keysym>
</key>
<key name="AD10">
<symbol label="p">p</symbol>
<symbol label="P">P</symbol>
<symbol label="0">0</symbol>
<symbol label="&#9651;">U25B3</symbol>
<key keycode="75" name="FK09">
<keysym keyval="65478">F9</keysym>
</key>
<key name="AC01">
<symbol label="a">a</symbol>
<symbol label="A">A</symbol>
<symbol label="@">at</symbol>
<symbol label="&#169;">copyright</symbol>
<key keycode="76" name="FK10">
<keysym keyval="65479">F10</keysym>
</key>
<key name="AC02">
<symbol label="s">s</symbol>
<symbol label="S">S</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="&#174;">U00AE</symbol>
<key keycode="95" name="FK11">
<keysym keyval="65480">F11</keysym>
</key>
<key name="AC03">
<symbol label="d">d</symbol>
<symbol label="D">D</symbol>
<symbol label="$">dollar</symbol>
<symbol label="&#163;">U00A3</symbol>
<key keycode="96" name="FK12">
<keysym keyval="65481">F12</keysym>
</key>
<key name="AC04">
<symbol label="f">f</symbol>
<symbol label="F">F</symbol>
<symbol label="%">percent</symbol>
<symbol label="&#8364;">EuroSign</symbol>
<key keycode="49" name="TLDE">
<keysym keyval="96">quoteleft</keysym>
<keysym keyval="126">asciitilde</keysym>
</key>
<key name="AC05">
<symbol label="g">g</symbol>
<symbol label="G">G</symbol>
<symbol label="&amp;">ampersand</symbol>
<symbol label="&#165;">U00A5</symbol>
<key keycode="10" name="AE01">
<keysym keyval="49">1</keysym>
<keysym keyval="33">exclam</keysym>
</key>
<key name="AC06">
<symbol label="h">h</symbol>
<symbol label="H">H</symbol>
<symbol label="-">minus</symbol>
<symbol label="^">asciicircum</symbol>
<key keycode="11" name="AE02">
<keysym keyval="50">2</keysym>
<keysym keyval="64">at</keysym>
</key>
<key name="AC07">
<symbol label="j">j</symbol>
<symbol label="J">J</symbol>
<symbol label="_">underscore</symbol>
<symbol label="&#176;">degree</symbol>
<key keycode="12" name="AE03">
<keysym keyval="51">3</keysym>
<keysym keyval="35">numbersign</keysym>
</key>
<key name="AC08">
<symbol label="k">k</symbol>
<symbol label="K">K</symbol>
<symbol label="+">plus</symbol>
<symbol label="=">equal</symbol>
<key keycode="13" name="AE04">
<keysym keyval="52">4</keysym>
<keysym keyval="36">dollar</keysym>
</key>
<key name="AC09">
<symbol label="l">l</symbol>
<symbol label="L">L</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="{">braceleft</symbol>
<key keycode="14" name="AE05">
<keysym keyval="53">5</keysym>
<keysym keyval="37">percent</keysym>
<keysym keyval="8364">EuroSign</keysym>
</key>
<key name="AC10">
<!-- Empty labels cause keys to be hidden when the level they are defined
for is shown. -->
<symbol label=""></symbol>
<symbol label=""></symbol>
<symbol label=")">parenright</symbol>
<symbol label="}">braceright</symbol>
<key keycode="15" name="AE06">
<keysym keyval="54">6</keysym>
<keysym keyval="94">asciicircum</keysym>
</key>
<key name="RTRN">
<symbol keyval="65293" icon="key-enter">Return</symbol>
<key keycode="16" name="AE07">
<keysym keyval="55">7</keysym>
<keysym keyval="38">ampersand</keysym>
</key>
<key name="LFSH">
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" icon="key-shift">Shift_L</keysym>
<keysym keyval="65505" label="=/+">Shift_L</keysym>
<keysym keyval="65505" label="123">Shift_L</keysym>
<key keycode="17" name="AE08">
<keysym keyval="56">8</keysym>
<keysym keyval="42">asterisk</keysym>
</key>
<key name="AB01">
<symbol label="z">z</symbol>
<symbol label="Z">Z</symbol>
<symbol label=",">comma</symbol>
<symbol label="\">backslash</symbol>
<key keycode="18" name="AE09">
<keysym keyval="57">9</keysym>
<keysym keyval="40">parenleft</keysym>
</key>
<key name="AB02">
<symbol label="x">x</symbol>
<symbol label="X">X</symbol>
<symbol label="&quot;">quotedbl</symbol>
<symbol label="/">slash</symbol>
<key keycode="19" name="AE10">
<keysym keyval="48">0</keysym>
<keysym keyval="41">parenright</keysym>
</key>
<key name="AB03">
<symbol label="c">c</symbol>
<symbol label="C">C</symbol>
<symbol label="'">quoteright</symbol>
<symbol label="&lt;">less</symbol>
<key keycode="20" name="AE11">
<keysym keyval="45">minus</keysym>
<keysym keyval="95">underscore</keysym>
</key>
<key name="AB04">
<symbol label="v">v</symbol>
<symbol label="V">V</symbol>
<symbol label=":">colon</symbol>
<symbol label="&gt;">greater</symbol>
<key keycode="21" name="AE12">
<keysym keyval="61">equal</keysym>
<keysym keyval="43">plus</keysym>
</key>
<key name="AB05">
<symbol label="b">b</symbol>
<symbol label="B">B</symbol>
<symbol label=";">semicolon</symbol>
<symbol label="=">equal</symbol>
<key keycode="22" name="BKSP">
<keysym keyval="65288">BackSpace</keysym>
</key>
<key name="AB06">
<symbol label="n">n</symbol>
<symbol label="N">N</symbol>
<symbol label="!">exclam</symbol>
<symbol label="[">bracketleft</symbol>
<key keycode="23" name="TAB">
<keysym keyval="65289">Tab</keysym>
<keysym keyval="65056">ISO_Left_Tab</keysym>
</key>
<key name="AB07">
<symbol label="m">m</symbol>
<symbol label="M">M</symbol>
<symbol label="?">question</symbol>
<symbol label="]">bracketright</symbol>
<key keycode="24" name="AD01">
<keysym keyval="113">q</keysym>
<keysym keyval="81">Q</keysym>
<keysym keyval="49">1</keysym>
</key>
<key name="AB08">
<symbol label=".">period</symbol>
<key keycode="25" name="AD02">
<keysym keyval="119">w</keysym>
<keysym keyval="87">W</keysym>
<keysym keyval="50">2</keysym>
</key>
<key name="ABC123">
<symbol label="123">show-numbers</symbol>
<symbol label="123">show-numbers</symbol>
<symbol label="ABC">show-letters</symbol>
<symbol label="ABC">show-letters</symbol>
<key keycode="26" name="AD03">
<keysym keyval="101">e</keysym>
<keysym keyval="69">E</keysym>
<keysym keyval="51">3</keysym>
</key>
<key name="I149">
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<key keycode="27" name="AD04">
<keysym keyval="114">r</keysym>
<keysym keyval="82">R</keysym>
<keysym keyval="52">4</keysym>
</key>
<key name="SPCE">
<symbol label=" ">space</symbol>
<key keycode="28" name="AD05">
<keysym keyval="116">t</keysym>
<keysym keyval="84">T</keysym>
<keysym keyval="53">5</keysym>
</key>
<key name="BKSP">
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<key keycode="29" name="AD06">
<keysym keyval="121">y</keysym>
<keysym keyval="89">Y</keysym>
<keysym keyval="54">6</keysym>
</key>
<key keycode="30" name="AD07">
<keysym keyval="117">u</keysym>
<keysym keyval="85">U</keysym>
<keysym keyval="55">7</keysym>
</key>
<key keycode="31" name="AD08">
<keysym keyval="105">i</keysym>
<keysym keyval="73">I</keysym>
<keysym keyval="56">8</keysym>
</key>
<key keycode="32" name="AD09">
<keysym keyval="111">o</keysym>
<keysym keyval="79">O</keysym>
<keysym keyval="57">9</keysym>
</key>
<key keycode="33" name="AD10">
<keysym keyval="112">p</keysym>
<keysym keyval="80">P</keysym>
<keysym keyval="48">0</keysym>
</key>
<key keycode="34" name="AD11">
<keysym keyval="91">bracketleft</keysym>
<keysym keyval="123">braceleft</keysym>
</key>
<key keycode="35" name="AD12">
<keysym keyval="93">bracketright</keysym>
<keysym keyval="125">braceright</keysym>
</key>
<key keycode="51" name="BKSL">
<keysym keyval="92">backslash</keysym>
<keysym keyval="124">bar</keysym>
</key>
<key keycode="66" name="ALTGR">
<keysym keyval="65027">ISO_Level3_Shift</keysym>
</key>
<key keycode="38" name="AC01">
<keysym keyval="97">a</keysym>
<keysym keyval="65">A</keysym>
<keysym keyval="64">at</keysym>
</key>
<key keycode="39" name="AC02">
<keysym keyval="115">s</keysym>
<keysym keyval="83">S</keysym>
<keysym keyval="35">numbersign</keysym>
</key>
<key keycode="40" name="AC03">
<keysym keyval="100">d</keysym>
<keysym keyval="68">D</keysym>
<keysym keyval="36">dollar</keysym>
</key>
<key keycode="41" name="AC04">
<keysym keyval="102">f</keysym>
<keysym keyval="70">F</keysym>
<keysym keyval="37">percent</keysym>
</key>
<key keycode="42" name="AC05">
<keysym keyval="103">g</keysym>
<keysym keyval="71">G</keysym>
<keysym keyval="38">ampersand</keysym>
</key>
<key keycode="43" name="AC06">
<keysym keyval="104">h</keysym>
<keysym keyval="72">H</keysym>
<keysym keyval="45">minus</keysym>
</key>
<key keycode="44" name="AC07">
<keysym keyval="106">j</keysym>
<keysym keyval="74">J</keysym>
<keysym keyval="95">underscore</keysym>
</key>
<key keycode="45" name="AC08">
<keysym keyval="107">k</keysym>
<keysym keyval="75">K</keysym>
<keysym keyval="123">braceleft</keysym>
</key>
<key keycode="46" name="AC09">
<keysym keyval="108">l</keysym>
<keysym keyval="76">L</keysym>
<keysym keyval="125">braceright</keysym>
</key>
<key keycode="47" name="AC10">
<keysym keyval="59">semicolon</keysym>
<keysym keyval="58">colon</keysym>
</key>
<key keycode="48" name="AC11">
<keysym keyval="39">quoteright</keysym>
<keysym keyval="34">quotedbl</keysym>
</key>
<key keycode="36" name="RTRN">
<keysym keyval="65293">Return</keysym>
</key>
<key keycode="50" name="LFSH">
<keysym keyval="65505">Shift_L</keysym>
</key>
<key keycode="52" name="AB01">
<keysym keyval="122">z</keysym>
<keysym keyval="90">Z</keysym>
<keysym keyval="43">plus</keysym>
</key>
<key keycode="53" name="AB02">
<keysym keyval="120">x</keysym>
<keysym keyval="88">X</keysym>
<keysym keyval="34">quotedbl</keysym>
</key>
<key keycode="54" name="AB03">
<keysym keyval="99">c</keysym>
<keysym keyval="67">C</keysym>
<keysym keyval="39">quoteright</keysym>
</key>
<key keycode="55" name="AB04">
<keysym keyval="118">v</keysym>
<keysym keyval="86">V</keysym>
<keysym keyval="58">colon</keysym>
</key>
<key keycode="56" name="AB05">
<keysym keyval="98">b</keysym>
<keysym keyval="66">B</keysym>
<keysym keyval="59">semicolon</keysym>
</key>
<key keycode="57" name="AB06">
<keysym keyval="110">n</keysym>
<keysym keyval="78">N</keysym>
<keysym keyval="33">exclam</keysym>
</key>
<key keycode="58" name="AB07">
<keysym keyval="109">m</keysym>
<keysym keyval="77">M</keysym>
<keysym keyval="63">question</keysym>
</key>
<key keycode="59" name="AB08">
<keysym keyval="44">comma</keysym>
<keysym keyval="60">less</keysym>
</key>
<key keycode="60" name="AB09">
<keysym keyval="46">period</keysym>
<keysym keyval="62">greater</keysym>
</key>
<key keycode="61" name="AB10">
<keysym keyval="47">slash</keysym>
<keysym keyval="63">question</keysym>
</key>
<key keycode="62" name="RTSH">
<keysym keyval="65506">Shift_R</keysym>
</key>
<key keycode="149" name="I149">
<symbol label="⌨" icon="input-keyboard-symbolic" tooltip="Change keyboard">cycle-keyboard</symbol>
</key>
<key keycode="150" name="I150">
<symbol label="☺" icon="preferences-system-symbolic" tooltip="Setup">preferences</symbol>
</key>
<key keycode="37" name="LCTL">
<keysym keyval="65507">Control_L</keysym>
</key>
<key keycode="64" name="LALT">
<keysym keyval="65513">Alt_L</keysym>
<keysym keyval="65511">Meta_L</keysym>
</key>
<key keycode="65" name="SPCE">
<keysym keyval="32">space</keysym>
</key>
<key keycode="113" name="LEFT">
<keysym keyval="65361">Left</keysym>
</key>
<key keycode="111" name="UP">
<keysym keyval="65362">Up</keysym>
</key>
<key keycode="116" name="DOWN">
<keysym keyval="65364">Down</keysym>
</key>
<key keycode="114" name="RGHT">
<keysym keyval="65363">Right</keysym>
</key>
</symbols>

View File

@ -1,12 +1,57 @@
gnome = import('gnome')
squeekboard_resources = gnome.compile_resources(
'squeekboard-resources',
'squeekboard.gresources.xml',
c_name: 'squeekboard',
install_data(
'themes/default.css',
install_dir: pkgdatadir + '/themes',
)
install_data(
'keyboards/keyboards.xml',
install_dir: pkgdatadir + '/keyboards/',
)
install_data(
'keyboards/geometry/compact.xml',
install_dir: pkgdatadir + '/keyboards/geometry/',
)
symbols = [
'ar.xml',
'as-inscript.xml',
'be.xml',
'bn-inscript.xml',
'fa.xml',
'gu-inscript.xml',
'he.xml',
'hi-inscript.xml',
'ja-kana.xml',
'kk.xml',
'kn-inscript.xml',
'ks-inscript.xml',
'ks.xml',
'mai-inscript.xml',
'ml-inscript.xml',
'mr-inscript.xml',
'my.xml',
'or-inscript.xml',
'pa-inscript.xml',
'ru.xml',
'sd-inscript.xml',
'ta-inscript.xml',
'te-inscript.xml',
'th.xml',
'ua.xml',
'ug.xml',
'us.xml',
'zh-bopomofo.xml',
]
foreach symbol: symbols
install_data(
'keyboards/symbols/' + symbol,
install_dir: pkgdatadir + '/keyboards/symbols/',
)
endforeach
desktop_file = 'sm.puri.Squeekboard.desktop'
i18n.merge_file('desktop',

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/sm/puri/squeekboard">
<file compressed="true">style.css</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/compact.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/extended.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/geometry/number-keypad.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/keyboards.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ar.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/as-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/be.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/bn-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/fa.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/gu-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/he.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/hi-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ja-kana.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/kk.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/kn-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ks-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ks.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/mai-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ml-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/mr-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/my.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/nb.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/or-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/pa-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ru.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/sd-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ta-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/te-inscript.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/th.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ua.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/ug.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/us.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/zh-bopomofo.xml</file>
<file compressed="true" preprocess="xml-stripblanks">keyboards/symbols/special/number.xml</file>
<file>icons/key-enter.svg</file>
<file>icons/key-shift.svg</file>
<file>icons/keyboard-mode-symbolic.svg</file>
</gresource>
</gresources>

4
data/themes/Makefile.am Normal file
View File

@ -0,0 +1,4 @@
themedir = $(pkgdatadir)/themes
dist_theme_DATA = default.css
-include $(top_srcdir)/git.mk

6
debian/control vendored
View File

@ -11,10 +11,8 @@ Build-Depends:
libcroco3-dev,
libwayland-dev (>= 1.16),
rustc,
wayland-protocols (>= 1.14),
# for running the tests
xvfb,
xauth,
virtboard,
wayland-protocols (>= 1.14)
Standards-Version: 4.1.3
Homepage: https://source.puri.sm/Librem5/squeekboard

53
debian/copyright vendored
View File

@ -3,58 +3,7 @@ Upstream-Name: evscript
Source: https://source.puri.sm/david.boddie/evscript
Files: *
Copyright: 2010-2011 Daiki Ueno <ueno@unixuser.org>
2010-2011 Red Hat, Inc.
2019 Purism SPC
License: GPL-3+
Files: eek/layersurface.c
src/wayland.c
src/key-emitter.c
meson.build
src/meson.build
po/meson.build
Copyright: 2018-2019 Purism SPC
License: GPL-3+
Files: eekboard/keymap.c
Copyright: 2000 Red Hat, Inc.
2019 Purism, SPC
License: LGPL-2+
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, see <http://www.gnu.org/licenses/>.
Files: protocols/wlr-layer-shell-unstable-v1.xml
Copytight: Copyright © 2017 Drew DeVault
License: X11
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee, provided
that the above copyright notice appear in all copies and fthat both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of the copyright holders not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission. The copyright holders make
no representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied warranty.
.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Copyright: 2019 Purism SPC
License: GPL-3+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

21
docs/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
# 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
SUBDIRS = reference
-include $(top_srcdir)/git.mk

View File

@ -0,0 +1,21 @@
# 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
SUBDIRS = eek eekboard
-include $(top_srcdir)/git.mk

View File

@ -0,0 +1,133 @@
# 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
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=eek
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# The directory containing the source code. Relative to $(srcdir).
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting the functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk
DOC_SOURCE_DIR=../../../eek
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--rebuild-types --deprecated-guards="EEK_DISABLE_DEPRECATED"
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
MKDB_OPTIONS=--sgml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/eek/*.h
CFILE_GLOB=$(top_srcdir)/eek/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files to ignore when scanning. Use base file name, no paths
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES = \
config.h \
eek-renderer.h \
eek-gtk-renderer.h \
eek-theme.h \
eek-theme-node.h \
eek-enumtypes.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=eek-overview.xml
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=eek-overview.xml
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS = $(GIO2_CFLAGS)
GTKDOC_LIBS = $(top_builddir)/eek/libeek.la \
$(top_builddir)/eek/libeek-gtk.la \
$(top_builddir)/eek/libeek-xkl.la \
$(GIO2_LIBS) \
$(GTK_LIBS) \
$(LIBXKLAVIER_LIBS)
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
#DISTCLEANFILES +=
# Comment this out if you want your docs-status tested during 'make check'
if ENABLE_GTK_DOC
#TESTS_ENVIRONMENT = cd $(srcsrc) &&
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/gtk-doc.mk
-include $(top_srcdir)/git.mk

View File

@ -0,0 +1,122 @@
# 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
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=eekboard
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# The directory containing the source code. Relative to $(srcdir).
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting the functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk
DOC_SOURCE_DIR=../../../eekboard
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
MKDB_OPTIONS=--sgml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/eekboard/*.h
CFILE_GLOB=$(top_srcdir)/eekboard/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files to ignore when scanning. Use base file name, no paths
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES=config.h eekboard.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
# content_files=eekboard-overview.xml
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
# expand_content_files=eekboard-overview.xml
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS = $(GIO2_CFLAGS)
GTKDOC_LIBS = $(top_builddir)/eekboard/libeekboard.la $(GIO2_LIBS)
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
# EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
#DISTCLEANFILES +=
# Comment this out if you want your docs-status tested during 'make check'
if ENABLE_GTK_DOC
#TESTS_ENVIRONMENT = cd $(srcsrc) &&
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/gtk-doc.mk
-include $(top_srcdir)/git.mk

298
eek/Makefile.am Normal file
View File

@ -0,0 +1,298 @@
# 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
NULL =
lib_LTLIBRARIES = \
libeek.la \
libeek-gtk.la \
libeek-xkl.la \
$(NULL)
libeek_public_headers = \
$(srcdir)/eek-layout.h \
$(srcdir)/eek-element.h \
$(srcdir)/eek-container.h \
$(srcdir)/eek-keyboard.h \
$(srcdir)/eek-section.h \
$(srcdir)/eek-key.h \
$(srcdir)/eek-symbol.h \
$(srcdir)/eek-keysym.h \
$(srcdir)/eek-text.h \
$(srcdir)/eek-symbol-matrix.h \
$(srcdir)/eek-types.h \
$(srcdir)/eek-xml.h \
$(srcdir)/eek-xml-layout.h \
$(srcdir)/eek-serializable.h \
$(srcdir)/eek-theme.h \
$(srcdir)/eek.h \
$(NULL)
libeek_private_headers = \
$(srcdir)/eek-renderer.h \
$(libeek_keysym_headers) \
$(builddir)/eek-marshalers.h \
$(srcdir)/eek-theme-context.h \
$(srcdir)/eek-theme-private.h \
$(srcdir)/eek-theme-node.h \
$(NULL)
libeek_sources = \
$(srcdir)/eek.c \
$(srcdir)/eek-layout.c \
$(srcdir)/eek-element.c \
$(srcdir)/eek-container.c \
$(srcdir)/eek-keyboard.c \
$(srcdir)/eek-section.c \
$(srcdir)/eek-key.c \
$(srcdir)/eek-symbol-matrix.c \
$(srcdir)/eek-symbol.c \
$(srcdir)/eek-keysym.c \
$(srcdir)/eek-text.c \
$(srcdir)/eek-types.c \
$(srcdir)/eek-serializable.c \
$(srcdir)/eek-xml.c \
$(srcdir)/eek-xml-layout.c \
$(srcdir)/eek-renderer.c \
$(srcdir)/eek-keyboard-drawing.c \
$(srcdir)/eek-theme.c \
$(srcdir)/eek-theme-context.c \
$(srcdir)/eek-theme-node.c \
$(NULL)
libeek_keysym_headers = \
$(builddir)/eek-special-keysym-entries.h \
$(builddir)/eek-unicode-keysym-entries.h \
$(builddir)/eek-xkeysym-keysym-entries.h \
$(NULL)
libeek_enumtypes_sources = \
$(builddir)/eek-enumtypes.c \
$(builddir)/eek-enumtypes.h \
$(NULL)
libeek_marshalers_sources = \
$(builddir)/eek-marshalers.c \
$(builddir)/eek-marshalers.h \
$(NULL)
BUILT_SOURCES = \
$(libeek_keysym_headers) \
$(libeek_enumtypes_sources) \
$(libeek_marshalers_sources) \
$(NULL)
libeek_la_SOURCES = \
$(libeek_sources) \
$(builddir)/eek-enumtypes.c \
$(builddir)/eek-marshalers.c \
$(NULL)
libeek_la_CFLAGS = \
-DEEK_COMPILATION=1 \
-DKEYBOARDSDIR=\"$(pkgdatadir)/keyboards\" \
$(GIO2_CFLAGS) \
$(PANGOCAIRO_CFLAGS) \
$(LIBCROCO_CFLAGS) \
$(NULL)
libeek_la_LIBADD = \
$(GIO2_LIBS) \
$(PANGOCAIRO_LIBS) \
$(LIBCROCO_LIBS) \
-lm \
$(NULL)
libeek_gtk_public_headers = \
$(srcdir)/eek-gtk-keyboard.h \
$(srcdir)/eek-gtk.h \
$(NULL)
libeek_gtk_private_headers = \
$(srcdir)/eek-gtk-renderer.h \
$(NULL)
libeek_gtk_sources = \
$(srcdir)/eek-gtk-keyboard.c \
$(srcdir)/eek-gtk-renderer.c \
$(NULL)
libeek_gtk_la_SOURCES = $(libeek_gtk_sources)
libeek_gtk_la_CFLAGS = -DEEK_COMPILATION=1 $(GTK_CFLAGS) $(LIBCANBERRA_CFLAGS)
libeek_gtk_la_LIBADD = libeek.la $(GTK_LIBS) $(LIBCANBERRA_LIBS)
libeek_xkl_public_headers = \
$(srcdir)/eek-xkl-layout.h \
$(srcdir)/eek-xkl.h \
$(srcdir)/eek-xkb-layout.h \
$(srcdir)/eek-xkb.h \
$(NULL)
libeek_xkl_sources = \
$(srcdir)/eek-xkb-layout.c \
$(srcdir)/eek-xkl-layout.c \
$(NULL)
libeek_xkl_la_SOURCES = $(libeek_xkl_sources)
libeek_xkl_la_CFLAGS = -DEEK_COMPILATION=1 $(LIBXKLAVIER_CFLAGS)
libeek_xkl_la_LIBADD = libeek.la $(LIBXKLAVIER_LIBS)
eekdir = $(includedir)/eek-$(EEK_API_VERSION)/eek
eek_HEADERS = \
$(libeek_public_headers) \
$(builddir)/eek-enumtypes.h \
$(libeek_gtk_public_headers) \
$(libeek_xkl_public_headers) \
$(NULL)
noinst_HEADERS = \
$(libeek_private_headers) \
$(libeek_gtk_private_headers) \
$(libeek_xkl_private_headers) \
$(NULL)
eek-special-keysym-entries.h: special-keysym-entries.txt
$(AM_V_GEN) $(PYTHON) $(srcdir)/gen-keysym-entries.py \
special_keysym_entries \
< $< > $@
eek-unicode-keysym-entries.h: unicode-keysym-entries.txt
$(AM_V_GEN) $(PYTHON) $(srcdir)/gen-keysym-entries.py \
unicode_keysym_entries \
< $< > $@
eek-xkeysym-keysym-entries.h: xkeysym-keysym-entries.txt
$(AM_V_GEN) $(PYTHON) $(srcdir)/gen-keysym-entries.py \
xkeysym_keysym_entries \
< $< > $@
eek-enumtypes.h: $(libeek_public_headers) eek-enumtypes.h.template
$(AM_V_GEN) $(GLIB_MKENUMS) \
--template $(srcdir)/eek-enumtypes.h.template \
$(libeek_public_headers) > eek-enumtypes.h.tmp && \
mv eek-enumtypes.h.tmp eek-enumtypes.h
eek-enumtypes.c: $(libeek_public_headers) eek-enumtypes.c.template
$(AM_V_GEN) $(GLIB_MKENUMS) \
--template $(srcdir)/eek-enumtypes.c.template \
$(libeek_public_headers) > eek-enumtypes.c.tmp && \
mv eek-enumtypes.c.tmp eek-enumtypes.c
# gen marshal
eek-marshalers.h: eek-marshalers.list
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
--prefix=_eek_marshal $(srcdir)/eek-marshalers.list \
--header --internal > $@.tmp && \
mv $@.tmp $@
eek-marshalers.c: eek-marshalers.list eek-marshalers.h
$(AM_V_GEN) (echo "#include \"eek-marshalers.h\""; \
$(GLIB_GENMARSHAL) --prefix=_eek_marshal \
$(srcdir)/eek-marshalers.list --body --internal) > $@.tmp && \
mv $@.tmp $@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
eek-$(EEK_API_VERSION).pc \
eek-gtk-$(EEK_API_VERSION).pc \
eek-xkl-$(EEK_API_VERSION).pc \
$(NULL)
CLEANFILES =
DISTCLEANFILES = \
$(BUILT_SOURCES) \
$(pkgconfig_DATA) \
$(NULL)
EXTRA_DIST = \
gen-keysym-entries.py \
special-keysym-entries.txt \
unicode-keysym-entries.txt \
xkeysym-keysym-entries.txt \
eek-enumtypes.h.template \
eek-enumtypes.c.template \
eek-marshalers.list \
$(NULL)
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(builddir)
INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
if HAVE_INTROSPECTION
Eek@EEK_LIBRARY_SUFFIX@.gir: libeek.la
Eek@EEK_LIBRARY_SUFFIX_U@_gir_SCANNERFLAGS = \
--identifier-prefix=Eek \
--symbol-prefix=eek \
--pkg=glib-2.0 \
--pkg-export=eek-$(EEK_API_VERSION) \
$(NULL)
Eek@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = GLib-2.0 GObject-2.0 Gio-2.0
Eek@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_la_CFLAGS)
Eek@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek.la
Eek@EEK_LIBRARY_SUFFIX_U@_gir_FILES = \
$(libeek_sources) \
$(libeek_public_headers) \
$(builddir)/eek-enumtypes.h \
$(NULL)
EekGtk@EEK_LIBRARY_SUFFIX@.gir: libeek-gtk.la Eek@EEK_LIBRARY_SUFFIX@.gir
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_SCANNERFLAGS = \
--identifier-prefix=Eek \
--symbol-prefix=eek \
--pkg-export=eek-gtk-$(EEK_API_VERSION) \
$(NULL)
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = \
GObject-2.0 \
Gtk-@GTK_API_VERSION@ \
Eek@EEK_LIBRARY_SUFFIX@ \
$(NULL)
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_gtk_la_CFLAGS)
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek-gtk.la
EekGtk@EEK_LIBRARY_SUFFIX_U@_gir_FILES = \
$(libeek_gtk_sources) \
$(libeek_gtk_public_headers) \
$(NULL)
EekXkl@EEK_LIBRARY_SUFFIX@.gir: libeek-xkl.la Eek@EEK_LIBRARY_SUFFIX@.gir
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_SCANNERFLAGS = \
--identifier-prefix=Eek \
--symbol-prefix=eek \
$(NULL)
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = GObject-2.0 Eek@EEK_LIBRARY_SUFFIX@
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeek_xkl_la_CFLAGS)
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeek-xkl.la
EekXkl@EEK_LIBRARY_SUFFIX_U@_gir_FILES = \
$(libeek_xkl_sources) \
$(libeek_xkl_public_headers) \
$(NULL)
INTROSPECTION_GIRS += \
Eek@EEK_LIBRARY_SUFFIX@.gir \
EekGtk@EEK_LIBRARY_SUFFIX@.gir \
EekXkl@EEK_LIBRARY_SUFFIX@.gir \
$(NULL)
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)
typelibdir = $(libdir)/girepository-1.0
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
CLEANFILES += $(gir_DATA) $(typelib_DATA)
endif
-include $(top_srcdir)/git.mk

0
eek/config.h Normal file
View File

View File

@ -26,7 +26,9 @@
* shall be used to implement #EekKeyboard and #EekSection.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-container.h"

View File

@ -26,7 +26,9 @@
* shall be used to implement #EekKeyboard, #EekSection, or #EekKey.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
@ -100,7 +102,6 @@ eek_element_set_property (GObject *object,
break;
case PROP_LEVEL:
eek_element_set_level (element, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View File

@ -23,17 +23,18 @@
* @short_description: a #GtkWidget displaying #EekKeyboard
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
#endif
#include <math.h>
#include <string.h>
#include "eek-gtk-keyboard.h"
#include "eek-renderer.h"
#include "eek-gtk-renderer.h"
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
@ -55,6 +56,9 @@ typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer;
EekKeyboard *keyboard;
gulong key_locked_handler;
gulong key_unlocked_handler;
gulong symbol_index_changed_handler;
EekTheme *theme;
GdkEventSequence *sequence; // unowned reference
@ -112,15 +116,13 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
PangoContext *pcontext;
pcontext = gtk_widget_get_pango_context (self);
priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
priv->renderer = eek_gtk_renderer_new (priv->keyboard, pcontext, self);
if (priv->theme)
eek_renderer_set_theme (priv->renderer, priv->theme);
eek_renderer_set_allocation_size (priv->renderer,
allocation.width,
allocation.height);
eek_renderer_set_scale_factor (priv->renderer,
gtk_widget_get_scale_factor (self));
}
eek_renderer_render_keyboard (priv->renderer, cr);
@ -162,7 +164,6 @@ static void depress(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
if (key) {
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
@ -328,23 +329,17 @@ eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
EekKeyboard *keyboard)
{
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);
g_signal_connect (priv->keyboard, "key-locked",
G_CALLBACK(on_key_locked), self);
g_signal_connect (priv->keyboard, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
priv->key_locked_handler =
g_signal_connect (priv->keyboard, "key-locked",
G_CALLBACK(on_key_locked), self);
priv->key_unlocked_handler =
g_signal_connect (priv->keyboard, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
priv->symbol_index_changed_handler =
g_signal_connect (priv->keyboard, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
static void
@ -378,9 +373,21 @@ eek_gtk_keyboard_dispose (GObject *object)
}
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;
g_signal_handlers_disconnect_by_data(priv->keyboard, self);
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
@ -484,29 +491,28 @@ render_pressed_key (GtkWidget *widget,
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds bounds, large_bounds;
GdkWindow *window = gtk_widget_get_window (widget);
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
gdouble scale = eek_renderer_get_scale (priv->renderer);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
GdkWindow *window = GDK_DRAWABLE (gtk_widget_get_window (widget));
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame(
window, region
);
cairo_t *cr = gdk_drawing_context_get_cairo_context(context);
cairo_save (cr);
cairo_scale (cr, scale, scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
/*
cairo_save (cr);
cairo_translate (cr, large_bounds.x, large_bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
cairo_restore (cr);
*/
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
gdk_window_end_draw_frame(window, context);
cairo_region_destroy(region);
}
static void
@ -521,19 +527,15 @@ render_locked_key (GtkWidget *widget,
cairo_region_t *region = gdk_window_get_clip_region (window);
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
gdouble scale = eek_renderer_get_scale (priv->renderer);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
cairo_save (cr);
cairo_scale (cr, scale, scale);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
cairo_restore (cr);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
cairo_region_destroy(region);
}
static void
@ -549,11 +551,26 @@ render_released_key (GtkWidget *widget,
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 2.0);
cairo_rectangle (cr,
large_bounds.x,
large_bounds.y,
large_bounds.width,
large_bounds.height);
cairo_rectangle (cr,
bounds.x,
bounds.y,
bounds.width,
bounds.height);
cairo_clip (cr);
eek_renderer_render_keyboard (priv->renderer, cr);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
cairo_region_destroy(region);
}
static void
@ -567,7 +584,6 @@ on_key_pressed (EekKey *key,
return;
render_pressed_key (GTK_WIDGET(self), key);
gtk_widget_queue_draw (GTK_WIDGET(self));
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
@ -589,7 +605,6 @@ on_key_released (EekKey *key,
return;
render_released_key (GTK_WIDGET(self), key);
gtk_widget_queue_draw (GTK_WIDGET(self));
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
@ -613,7 +628,6 @@ on_key_locked (EekKeyboard *keyboard,
return;
render_locked_key (widget, key);
gtk_widget_queue_draw (widget);
}
static void
@ -629,7 +643,6 @@ on_key_unlocked (EekKeyboard *keyboard,
return;
render_released_key (widget, key);
gtk_widget_queue_draw (GTK_WIDGET(widget));
}
static void

104
eek/eek-gtk-renderer.c Normal file
View File

@ -0,0 +1,104 @@
/*
* 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
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "eek-gtk-renderer.h"
#include "eek-key.h"
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 *
eek_gtk_renderer_real_get_icon_surface (EekRenderer *self,
const gchar *icon_name,
gint size)
{
GdkPixbuf *pixbuf;
GError *error;
cairo_surface_t *surface;
error = NULL;
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
icon_name,
size,
0,
&error);
if (pixbuf == NULL) {
g_warning ("can't get icon pixbuf for %s: %s",
icon_name,
error->message);
g_error_free (error);
return NULL;
}
surface = pixbuf_to_cairo_surface (pixbuf);
g_object_unref (pixbuf);
return surface;
}
static void
eek_gtk_renderer_class_init (EekGtkRendererClass *klass)
{
EekRendererClass *renderer_class = EEK_RENDERER_CLASS (klass);
renderer_class->get_icon_surface = eek_gtk_renderer_real_get_icon_surface;
}
static void
eek_gtk_renderer_init (EekGtkRenderer *self)
{
}
EekRenderer *
eek_gtk_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext,
GtkWidget *widget)
{
return g_object_new (EEK_TYPE_GTK_RENDERER,
"keyboard", keyboard,
"pango-context", pcontext,
NULL);
}

61
eek/eek-gtk-renderer.h Normal file
View File

@ -0,0 +1,61 @@
/*
* 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_GTK_RENDERER_H
#define EEK_GTK_RENDERER_H 1
#include <gtk/gtk.h>
#include "eek-renderer.h"
G_BEGIN_DECLS
#define EEK_TYPE_GTK_RENDERER (eek_gtk_renderer_get_type())
#define EEK_GTK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_GTK_RENDERER, EekGtkRenderer))
#define EEK_GTK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_GTK_RENDERER, EekGtkRendererClass))
#define EEK_IS_GTK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_GTK_RENDERER))
#define EEK_IS_GTK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_GTK_RENDERER))
#define EEK_GTK_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_GTK_RENDERER, EekGtkRendererClass))
typedef struct _EekGtkRenderer EekGtkRenderer;
typedef struct _EekGtkRendererClass EekGtkRendererClass;
typedef struct _EekGtkRendererPrivate EekGtkRendererPrivate;
struct _EekGtkRenderer {
EekRenderer parent;
EekGtkRendererPrivate *priv;
};
struct _EekGtkRendererClass
{
EekRendererClass parent_class;
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_gtk_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_gtk_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext,
GtkWidget *widget);
G_END_DECLS
#endif /* EEK_GTK_RENDERER_H */

View File

@ -25,7 +25,9 @@
* The #EekKeyClass class represents a key.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
@ -609,11 +611,3 @@ void eek_key_set_pressed(EekKey *key, gboolean value)
priv->is_pressed = value;
}
gboolean
eek_key_has_label(EekKey *key)
{
EekSymbol *symbol = eek_key_get_symbol(key);
return (eek_symbol_get_label(symbol) != NULL) ||
(eek_symbol_get_icon_name(symbol) != NULL);
}

View File

@ -89,7 +89,5 @@ gboolean eek_key_is_locked (EekKey *key);
void eek_key_set_pressed (EekKey *key,
gboolean value);
gboolean eek_key_has_label (EekKey *key);
G_END_DECLS
#endif /* EEK_KEY_H */

View File

@ -17,7 +17,9 @@
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <math.h>
#include <pango/pangocairo.h>

View File

@ -27,8 +27,9 @@
* of one or more sections of the #EekSectionClass class.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include <glib/gprintf.h>
#endif /* HAVE_CONFIG_H */
#include "eek-keyboard.h"
#include "eek-marshalers.h"
@ -37,7 +38,6 @@
#include "eek-symbol.h"
#include "eek-enumtypes.h"
#include "eekboard/key-emitter.h"
#include "keymap.h"
enum {
PROP_0,
@ -53,15 +53,10 @@ enum {
LAST_SIGNAL
};
enum {
VIEW_LETTERS_LOWER,
VIEW_LETTERS_UPPER,
VIEW_NUMBERS,
VIEW_SYMBOLS
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
#define EEK_KEYBOARD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
@ -70,21 +65,16 @@ struct _EekKeyboardPrivate
EekLayout *layout;
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
unsigned int old_level;
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
/* Map key names to key objects: */
GHashTable *names;
GHashTable *keycodes;
/* modifiers dynamically assigned at run time */
EekModifierType num_lock_mask;
EekModifierType alt_gr_mask;
};
G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
G_DEFINE_BOXED_TYPE(EekModifierKey, eek_modifier_key,
eek_modifier_key_copy, eek_modifier_key_free);
@ -131,9 +121,9 @@ section_child_added_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
const gchar *name = eek_element_get_name(element);
g_hash_table_insert (keyboard->priv->names,
(gpointer)name,
guint keycode = eek_key_get_keycode (EEK_KEY(element));
g_hash_table_insert (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode),
element);
}
@ -142,9 +132,9 @@ section_child_removed_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
const gchar *name = eek_element_get_name(element);
g_hash_table_remove (keyboard->priv->names,
name);
guint keycode = eek_key_get_keycode (EEK_KEY(element));
g_hash_table_remove (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode));
}
static EekSection *
@ -213,61 +203,16 @@ eek_keyboard_get_property (GObject *object,
}
static void
set_level_from_modifiers (EekKeyboard *self, EekKey *key)
set_level_from_modifiers (EekKeyboard *self)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
gint level = 0;
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
/* Use the numbers/letters bit from the old level */
gint level = priv->old_level & 2;
/* Handle non-emitting keys */
if (key) {
const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
if (g_strcmp0(name, "ABC123") == 0)
level ^= 2;
}
level |= ((priv->modifiers & EEK_SHIFT_MASK) ? 1 : 0);
switch (priv->old_level) {
case VIEW_LETTERS_UPPER:
{
/* Redirect upper case letters to numbers instead of symbols, clearing
the shift modifier to keep the modifiers in sync with the level */
if (level == VIEW_SYMBOLS) {
level = VIEW_NUMBERS;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_SYMBOLS:
{
/* Redirect symbols to lower case letters instead of upper case,
clearing the shift modifier to keep the modifiers in sync with the
level */
if (level == VIEW_LETTERS_UPPER) {
level = VIEW_LETTERS_LOWER;
priv->modifiers &= ~EEK_SHIFT_MASK;
}
break;
}
case VIEW_LETTERS_LOWER: /* Direct transitions between views */
case VIEW_NUMBERS:
default:
break;
}
if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
else
priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
priv->old_level = level;
if (priv->modifiers & priv->alt_gr_mask)
level |= 2;
if (priv->modifiers & EEK_SHIFT_MASK)
level |= 1;
eek_element_set_level (EEK_ELEMENT(self), level);
eek_layout_update_layout(self);
}
static void
@ -322,7 +267,7 @@ void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestam
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
set_modifiers_with_key (keyboard, key, priv->modifiers | modifier);
set_level_from_modifiers (keyboard, key);
set_level_from_modifiers (keyboard);
}
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
@ -371,7 +316,7 @@ void eek_keyboard_release_key( EekKeyboard *keyboard,
(priv->modifiers ^ modifier) & modifier);
break;
}
set_level_from_modifiers (keyboard, key);
set_level_from_modifiers (keyboard);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
@ -404,7 +349,7 @@ eek_keyboard_finalize (GObject *object)
g_list_free_full (priv->locked_keys,
(GDestroyNotify) eek_modifier_key_free);
g_hash_table_destroy (priv->names);
g_hash_table_destroy (priv->keycodes);
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
@ -445,6 +390,9 @@ eek_keyboard_class_init (EekKeyboardClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekKeyboardPrivate));
klass->create_section = eek_keyboard_real_create_section;
/* signals */
@ -532,9 +480,8 @@ eek_keyboard_init (EekKeyboard *self)
self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
self->priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
self->priv->names = g_hash_table_new (g_str_hash, g_str_equal);
self->priv->keycodes = g_hash_table_new (g_direct_hash, g_direct_equal);
eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
self->scale = 1.0;
}
/**
@ -553,20 +500,20 @@ eek_keyboard_create_section (EekKeyboard *keyboard)
}
/**
* eek_keyboard_find_key_by_name:
* eek_keyboard_find_key_by_keycode:
* @keyboard: an #EekKeyboard
* @name: a key name
* @keycode: a keycode
*
* Find an #EekKey whose name is @name.
* Return value: (transfer none): #EekKey whose name is @name
* Find an #EekKey whose keycode is @keycode.
* Return value: (transfer none): #EekKey whose keycode is @keycode
*/
EekKey *
eek_keyboard_find_key_by_name (EekKeyboard *keyboard,
const gchar *name)
eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
guint keycode)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_hash_table_lookup (keyboard->priv->names,
name);
return g_hash_table_lookup (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode));
}
/**
@ -638,7 +585,7 @@ eek_keyboard_set_modifiers (EekKeyboard *keyboard,
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifiers = modifiers;
set_level_from_modifiers (keyboard, NULL);
set_level_from_modifiers (keyboard);
}
/**
@ -800,93 +747,3 @@ eek_keyboard_get_locked_keys (EekKeyboard *keyboard)
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_list_copy (keyboard->priv->locked_keys);
}
/**
* eek_keyboard_get_keymap:
* @keyboard: an #EekKeyboard
*
* Get the keymap for the keyboard.
* Returns: a string containing the XKB keymap.
*/
gchar *
eek_keyboard_get_keymap(EekKeyboard *keyboard)
{
/* Start the keycodes and symbols sections with their respective headers. */
gchar *keycodes = g_strdup(keymap_keycodes_header);
gchar *symbols = g_strdup(keymap_symbols_header);
/* Iterate over the keys in the name-to-key hash table. */
GHashTableIter iter;
gpointer key_name, key_ptr;
g_hash_table_iter_init(&iter, keyboard->priv->names);
while (g_hash_table_iter_next(&iter, &key_name, &key_ptr)) {
gchar *current, *line;
EekKey *key = EEK_KEY(key_ptr);
int keycode = eek_key_get_keycode(key);
/* Don't include invalid keycodes in the keymap. */
if (keycode == EEK_INVALID_KEYCODE)
continue;
/* Append a key name-to-keycode definition to the keycodes section. */
current = keycodes;
line = g_strdup_printf(" <%s> = %i;\n", (char *)key_name, keycode);
keycodes = g_strconcat(current, line, NULL);
g_free(line);
g_free(current);
/* Find the symbols associated with the key. */
EekSymbolMatrix *matrix = eek_key_get_symbol_matrix(key);
EekSymbol *syms[4];
int i, j;
/* Get the symbols for all the levels defined for the key, then
pad it out with the first symbol for all levels up to the fourth. */
for (i = 0; i < matrix->num_levels; ++i)
syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, i);
while (i < 4) {
syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, 0);
i++;
}
/* The four levels are split into two groups in the keymap.
Generate strings for each of these groups, where an empty group is
treated specially. */
gchar *groups[2];
for (i = 0, j = 0; i < 2; ++i, j += 2) {
if (syms[j] && syms[j + 1])
groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]),
eek_symbol_get_name(syms[j + 1]),
NULL);
else
groups[i] = "";
}
/* Append a key definition to the symbols section. */
current = symbols;
line = g_strdup_printf(" key <%s> { [ %s ], [ %s ] };\n",
(char *)key_name, groups[0], groups[1]);
g_free(groups[0]);
g_free(groups[1]);
symbols = g_strconcat(current, line, NULL);
g_free(line);
g_free(current);
}
/* Assemble the keymap file from the header, sections and footer. */
gchar *keymap = g_strconcat(keymap_header,
keycodes, " };\n\n",
symbols, " };\n\n",
keymap_footer, NULL);
g_free(keycodes);
g_free(symbols);
return keymap;
}

View File

@ -62,7 +62,6 @@ struct _EekKeyboard
struct xkb_keymap *keymap;
int keymap_fd; // keymap formatted as XKB string
size_t keymap_len; // length of the data inside keymap_fd
double scale;
EekboardContextService *manager; // unowned reference
};
@ -70,8 +69,8 @@ struct _EekKeyboard
/**
* EekKeyboardClass:
* @create_section: virtual function for creating a section
* @find_key_by_name: virtual function for finding a key in the
* keyboard by name
* @find_key_by_keycode: virtual function for finding a key in the
* keyboard by keycode
* @key_pressed: class handler for #EekKeyboard::key-pressed signal
* @key_released: class handler for #EekKeyboard::key-released signal
* @key_locked: class handler for #EekKeyboard::key-locked signal
@ -90,8 +89,8 @@ struct _EekKeyboardClass
/*< public >*/
EekSection *(* create_section) (EekKeyboard *self);
EekKey *(* find_key_by_name) (EekKeyboard *self,
const gchar *name);
EekKey *(* find_key_by_keycode) (EekKeyboard *self,
guint keycode);
/*< private >*/
/* obsolete members moved to EekElement */
@ -156,9 +155,9 @@ EekModifierType eek_keyboard_get_modifiers
EekSection *eek_keyboard_create_section
(EekKeyboard *keyboard);
EekKey *eek_keyboard_find_key_by_name
EekKey *eek_keyboard_find_key_by_keycode
(EekKeyboard *keyboard,
const gchar *name);
guint keycode);
guint eek_keyboard_add_outline
(EekKeyboard *keyboard,
@ -195,8 +194,5 @@ void eek_modifier_key_free
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
gchar * eek_keyboard_get_keymap
(EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */

View File

@ -23,7 +23,9 @@
* @short_description: an #EekSymbol represents an X keysym
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include <stdlib.h>

View File

@ -26,7 +26,9 @@
* arranges keyboard elements.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-layout.h"
#include "eek-keyboard.h"
@ -67,70 +69,3 @@ eek_keyboard_new (EekboardContextService *manager,
initial_width,
initial_height);
}
const double section_spacing = 7.0;
struct place_data {
double desired_width;
double current_offset;
EekKeyboard *keyboard;
};
static void
section_placer(EekElement *element, gpointer user_data)
{
struct place_data *data = (struct place_data*)user_data;
EekBounds section_bounds = {0};
eek_element_get_bounds(element, &section_bounds);
section_bounds.width = data->desired_width;
eek_element_set_bounds(element, &section_bounds);
// Sections are rows now. Gather up all the keys and adjust their bounds.
eek_section_place_keys(EEK_SECTION(element), EEK_KEYBOARD(data->keyboard));
eek_element_get_bounds(element, &section_bounds);
section_bounds.y = data->current_offset;
eek_element_set_bounds(element, &section_bounds);
data->current_offset += section_bounds.height + section_spacing;
}
static void
section_counter(EekElement *element, gpointer user_data) {
double *total_height = user_data;
EekBounds section_bounds = {0};
eek_element_get_bounds(element, &section_bounds);
*total_height += section_bounds.height + section_spacing;
}
void
eek_layout_place_sections(EekKeyboard *keyboard)
{
/* Order rows */
// This needs to be done after outlines, because outlines define key sizes
// TODO: do this only for rows without bounds
// The keyboard width is given by the user via screen size. The height will be given dynamically.
// TODO: calculate max line width beforehand for button centering. Leave keyboard centering to the renderer later
EekBounds keyboard_bounds = {0};
eek_element_get_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
struct place_data placer_data = {
.desired_width = keyboard_bounds.width,
.current_offset = 0,
.keyboard = keyboard,
};
eek_container_foreach_child(EEK_CONTAINER(keyboard), section_placer, &placer_data);
double total_height = 0;
eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height);
keyboard_bounds.height = total_height;
eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
}
void
eek_layout_update_layout(EekKeyboard *keyboard)
{
eek_layout_place_sections(keyboard);
}

View File

@ -55,9 +55,5 @@ struct _EekLayoutClass
GType eek_layout_get_type (void) G_GNUC_CONST;
void eek_layout_place_sections(EekKeyboard *keyboard);
void eek_layout_update_layout(EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_LAYOUT_H */

View File

@ -1,29 +1,29 @@
/*
/*
* 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
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <math.h>
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtk.h>
#include "eek-key.h"
#include "eek-section.h"
@ -48,15 +48,11 @@ typedef struct _EekRendererPrivate
gdouble allocation_width;
gdouble allocation_height;
gdouble scale;
gint scale_factor; /* the outputs scale factor */
gint origin_x;
gint origin_y;
PangoFontDescription *ascii_font;
PangoFontDescription *font;
GHashTable *outline_surface_cache;
GHashTable *active_outline_surface_cache;
GHashTable *icons;
cairo_surface_t *keyboard_surface;
gulong symbol_index_changed_handler;
@ -107,17 +103,18 @@ create_keyboard_surface_key_callback (EekElement *element,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
EekBounds bounds;
cairo_save (data->cr);
eek_element_get_bounds (element, &bounds);
cairo_translate (data->cr, bounds.x, bounds.y);
cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
cairo_rectangle (data->cr,
0.0,
0.0,
bounds.width + 100,
bounds.height + 100);
bounds.width * priv->scale + 100,
bounds.height * priv->scale + 100);
cairo_clip (data->cr);
render_key (data->renderer, data->cr, EEK_KEY(element), FALSE);
@ -129,17 +126,18 @@ create_keyboard_surface_section_callback (EekElement *element,
gpointer user_data)
{
CreateKeyboardSurfaceCallbackData *data = user_data;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
EekBounds bounds;
gint angle;
cairo_save (data->cr);
eek_element_get_bounds (element, &bounds);
cairo_translate (data->cr, bounds.x, bounds.y);
cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale);
angle = eek_section_get_angle (EEK_SECTION(element));
cairo_rotate (data->cr, angle * G_PI / 180);
eek_container_foreach_child (EEK_CONTAINER(element),
create_keyboard_surface_key_callback,
data);
@ -147,11 +145,12 @@ create_keyboard_surface_section_callback (EekElement *element,
cairo_restore (data->cr);
}
void
render_keyboard_surface (EekRenderer *renderer)
static cairo_surface_t *
create_keyboard_surface (EekRenderer *renderer)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
EekBounds bounds;
cairo_surface_t *keyboard_surface;
CreateKeyboardSurfaceCallbackData data;
EekColor foreground, background;
@ -163,13 +162,13 @@ render_keyboard_surface (EekRenderer *renderer)
&background);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
data.cr = cairo_create (priv->keyboard_surface);
keyboard_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
ceil(bounds.width * priv->scale),
ceil(bounds.height * priv->scale));
data.cr = cairo_create (keyboard_surface);
data.renderer = renderer;
cairo_save (data.cr);
cairo_scale (data.cr, priv->scale, priv->scale);
cairo_translate (data.cr, bounds.x, bounds.y);
cairo_translate (data.cr, bounds.x * priv->scale, bounds.y * priv->scale);
/* blank background */
cairo_set_source_rgba (data.cr,
@ -189,9 +188,9 @@ render_keyboard_surface (EekRenderer *renderer)
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
create_keyboard_surface_section_callback,
&data);
cairo_restore (data.cr);
cairo_destroy (data.cr);
return keyboard_surface;
}
static void
@ -214,7 +213,7 @@ render_key_outline (EekRenderer *renderer,
outline = eek_keyboard_get_outline (priv->keyboard, oref);
if (outline == NULL)
return;
theme_node = g_object_get_data (G_OBJECT(key),
active ?
"theme-node-pressed" :
@ -244,10 +243,15 @@ render_key_outline (EekRenderer *renderer,
border_color.alpha = foreground.alpha;
}
eek_element_get_bounds(EEK_ELEMENT(key), &bounds);
outline = eek_outline_copy (outline);
for (guint i = 0; i < outline->num_points; i++) {
outline->points[i].x *= priv->scale;
outline->points[i].y *= priv->scale;
}
cairo_translate (cr, border_width, border_width);
cairo_translate (cr,
border_width * priv->scale,
border_width * priv->scale);
if (gradient_type != EEK_GRADIENT_NONE) {
cairo_pattern_t *pat;
@ -258,17 +262,17 @@ render_key_outline (EekRenderer *renderer,
pat = cairo_pattern_create_linear (0.0,
0.0,
0.0,
bounds.height);
bounds.height * priv->scale);
break;
case EEK_GRADIENT_HORIZONTAL:
pat = cairo_pattern_create_linear (0.0,
0.0,
bounds.width,
bounds.width * priv->scale,
0.0);
break;
case EEK_GRADIENT_RADIAL:
cx = bounds.width / 2;
cy = bounds.height / 2;
cx = bounds.width / 2 * priv->scale;
cy = bounds.height / 2 * priv->scale;
pat = cairo_pattern_create_radial (cx,
cy,
0,
@ -325,11 +329,98 @@ render_key_outline (EekRenderer *renderer,
outline->num_points);
cairo_stroke (cr);
cairo_translate (cr, -border_width, -border_width);
cairo_translate (cr,
-border_width * priv->scale,
-border_width * priv->scale);
eek_outline_free (outline);
}
struct _CalculateFontSizeCallbackData {
gdouble size;
gboolean ascii;
EekRenderer *renderer;
const PangoFontDescription *base_font;
};
typedef struct _CalculateFontSizeCallbackData CalculateFontSizeCallbackData;
static void
calculate_font_size_key_callback (EekElement *element, gpointer user_data)
{
CalculateFontSizeCallbackData *data = user_data;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
gdouble sx, sy;
PangoFontDescription *font;
PangoRectangle extents = { 0, };
PangoLayout *layout;
gdouble size;
EekBounds bounds;
const gchar *label = NULL;
if (data->ascii)
label = "M";
else {
EekSymbol *symbol;
symbol = eek_key_get_symbol (EEK_KEY(element));
if (symbol &&
eek_symbol_get_category (symbol) == EEK_SYMBOL_CATEGORY_LETTER)
label = eek_symbol_get_label (symbol);
if (!label)
label = "M";
}
font = pango_font_description_copy (data->base_font);
eek_element_get_bounds (element, &bounds);
size = eek_bounds_long_side (&bounds) * PANGO_SCALE;
pango_font_description_set_size (font, size);
layout = pango_layout_new (priv->pcontext);
pango_layout_set_font_description (layout, font);
pango_font_description_free (font);
pango_layout_set_text (layout, label, -1);
pango_layout_get_extents (layout, NULL, &extents);
g_object_unref (layout);
sx = sy = 1.0;
if (extents.width > bounds.width * PANGO_SCALE)
sx = bounds.width * PANGO_SCALE / extents.width;
if (extents.height > bounds.height * PANGO_SCALE)
sy = bounds.height * PANGO_SCALE / extents.height;
size *= MIN(sx, sy);
if (size < data->size)
data->size = size;
}
static void
calculate_font_size_section_callback (EekElement *element, gpointer user_data)
{
eek_container_foreach_child (EEK_CONTAINER(element),
calculate_font_size_key_callback,
user_data);
}
static gdouble
calculate_font_size (EekRenderer *renderer,
const PangoFontDescription *base_font,
gboolean ascii)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
CalculateFontSizeCallbackData data;
data.size = G_MAXDOUBLE;
data.ascii = ascii;
data.renderer = renderer;
data.base_font = base_font;
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
calculate_font_size_section_callback,
&data);
return data.size;
}
static void
render_key (EekRenderer *self,
cairo_t *cr,
@ -347,9 +438,6 @@ render_key (EekRenderer *self,
PangoRectangle extents = { 0, };
EekColor foreground;
if (!eek_key_has_label(key))
return;
oref = eek_key_get_oref (key);
outline = eek_keyboard_get_outline (priv->keyboard, oref);
if (outline == NULL)
@ -357,6 +445,8 @@ render_key (EekRenderer *self,
/* render outline */
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
bounds.width *= priv->scale;
bounds.height *= priv->scale;
if (active)
outline_surface_cache = priv->active_outline_surface_cache;
@ -367,8 +457,7 @@ render_key (EekRenderer *self,
if (!outline_surface) {
cairo_t *cr;
// Outline will be drawn on the outside of the button, so the
// surface needs to be bigger than the button
// Outline will be drawn on the outside of the button, so the surface needs to be bigger than the button
outline_surface =
cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
(int)ceil(bounds.width) + 10,
@ -394,37 +483,44 @@ render_key (EekRenderer *self,
cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
cairo_paint (cr);
eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground);
/* render icon (if any) */
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
if (eek_symbol_get_icon_name (symbol)) {
gint scale = priv->scale_factor;
cairo_surface_t *icon_surface =
eek_renderer_get_icon_surface (self,
eek_symbol_get_icon_name (symbol),
16,
scale);
MIN(bounds.width, bounds.height) * 0.7);
if (icon_surface) {
gint width = cairo_image_surface_get_width (icon_surface);
gint height = cairo_image_surface_get_height (icon_surface);
gdouble scale;
if (width < bounds.width && height < bounds.height)
scale = 1;
else {
if (height * bounds.width / width <= bounds.height)
scale = bounds.width / width;
else if (width * bounds.height / height <= bounds.width)
scale = bounds.height / height;
else {
if (width * bounds.height < height * bounds.width)
scale = width / bounds.width;
else
scale = height / bounds.height;
}
}
cairo_save (cr);
cairo_translate (cr,
(bounds.width - width / scale) / 2,
(bounds.height - height / scale) / 2);
(bounds.width - width * scale) / 2,
(bounds.height - height * scale) / 2);
cairo_rectangle (cr, 0, 0, width, height);
cairo_clip (cr);
/* Draw the shape of the icon using the foreground color */
cairo_set_source_rgba (cr, foreground.red,
foreground.green,
foreground.blue,
foreground.alpha);
cairo_mask_surface (cr, icon_surface, 0.0, 0.0);
cairo_fill (cr);
cairo_set_source_surface (cr, icon_surface, 0.0, 0.0);
cairo_paint (cr);
cairo_restore (cr);
return;
}
@ -441,6 +537,7 @@ render_key (EekRenderer *self,
(bounds.width - extents.width / PANGO_SCALE) / 2,
(bounds.height - extents.height / PANGO_SCALE) / 2);
eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground);
cairo_set_source_rgba (cr,
foreground.red,
foreground.green,
@ -489,8 +586,9 @@ get_text_property_for_category (EekSymbolCategory category)
{ EEK_SYMBOL_CATEGORY_FUNCTION, TRUE, 0.5, FALSE },
{ EEK_SYMBOL_CATEGORY_KEYNAME, TRUE, 0.5, TRUE }
};
gint i;
for (uint i = 0; i < G_N_ELEMENTS(props); i++)
for (i = 0; i < G_N_ELEMENTS(props); i++)
if (props[i].category == category)
return &props[i];
@ -530,16 +628,13 @@ eek_renderer_real_render_key_label (EekRenderer *self,
base_font = eek_theme_node_get_font (theme_node);
else
base_font = pango_context_get_font_description (priv->pcontext);
// FIXME: Base font size on the same size unit used for button sizing,
// and make the default about 1/3 of the current row height
ascii_size = 30000.0;
ascii_size = calculate_font_size (self, base_font, TRUE);
priv->ascii_font = pango_font_description_copy (base_font);
pango_font_description_set_size (priv->ascii_font,
(gint)round(ascii_size));
pango_font_description_set_size (priv->ascii_font, ascii_size);
size = 30000.0;
size = calculate_font_size (self, base_font, FALSE);
priv->font = pango_font_description_copy (base_font);
pango_font_description_set_size (priv->font, (gint)round(size * 0.6));
pango_font_description_set_size (priv->font, size * 0.6);
}
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
@ -553,8 +648,8 @@ eek_renderer_real_render_key_label (EekRenderer *self,
priv->ascii_font :
priv->font);
pango_font_description_set_size (font,
(gint)round(pango_font_description_get_size (font) *
prop->scale * scale));
pango_font_description_get_size (font) *
prop->scale * priv->scale * scale);
pango_layout_set_font_description (layout, font);
pango_font_description_free (font);
@ -563,7 +658,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
if (line->resolved_dir == PANGO_DIRECTION_RTL)
pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
pango_layout_set_width (layout,
PANGO_SCALE * bounds.width * scale);
PANGO_SCALE * bounds.width * priv->scale * scale);
if (prop->ellipses)
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
}
@ -588,10 +683,7 @@ eek_renderer_real_render_key (EekRenderer *self,
gdouble scale,
gboolean rotate)
{
EekRendererPrivate *priv = eek_renderer_get_instance_private (self);
cairo_save (cr);
cairo_translate (cr, priv->origin_x, priv->origin_y);
eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate);
render_key (self, cr, key, eek_key_is_pressed (key) || eek_key_is_locked (key));
cairo_restore (cr);
@ -608,25 +700,13 @@ eek_renderer_real_render_keyboard (EekRenderer *self,
g_return_if_fail (priv->allocation_width > 0.0);
g_return_if_fail (priv->allocation_height > 0.0);
cairo_save (cr);
cairo_translate (cr, priv->origin_x, priv->origin_y);
if (priv->keyboard_surface)
cairo_surface_destroy (priv->keyboard_surface);
priv->keyboard_surface = cairo_surface_create_for_rectangle (
cairo_get_target (cr), 0, 0,
priv->allocation_width, priv->allocation_height);
render_keyboard_surface (self);
if (!priv->keyboard_surface)
priv->keyboard_surface = create_keyboard_surface (self);
cairo_set_source_surface (cr, priv->keyboard_surface, 0.0, 0.0);
source = cairo_get_source (cr);
cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD);
cairo_paint (cr);
cairo_restore (cr);
}
static void
@ -696,8 +776,6 @@ eek_renderer_dispose (GObject *object)
priv->pcontext = NULL;
}
g_clear_pointer (&priv->icons, g_hash_table_destroy);
/* this will release all allocated surfaces and font if any */
invalidate (EEK_RENDERER(object));
@ -765,7 +843,6 @@ eek_renderer_init (EekRenderer *self)
priv->allocation_width = 0.0;
priv->allocation_height = 0.0;
priv->scale = 1.0;
priv->scale_factor = 1;
priv->font = NULL;
priv->outline_surface_cache =
g_hash_table_new_full (g_direct_hash,
@ -779,14 +856,6 @@ eek_renderer_init (EekRenderer *self)
(GDestroyNotify)cairo_surface_destroy);
priv->keyboard_surface = NULL;
priv->symbol_index_changed_handler = 0;
GtkIconTheme *theme = gtk_icon_theme_get_default ();
gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
priv->icons = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify)cairo_surface_destroy);
}
static void
@ -842,19 +911,21 @@ eek_renderer_set_allocation_size (EekRenderer *renderer,
priv->allocation_width = width;
priv->allocation_height = height;
/* Calculate a scale factor to use when rendering the keyboard into the
available space. */
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
gdouble w = (bounds.x * 2) + bounds.width;
gdouble h = (bounds.y * 2) + bounds.height;
scale = MIN(width / w, height / h);
if (bounds.height * width / bounds.width <= height)
scale = width / bounds.width;
else if (bounds.width * height / bounds.height <= width)
scale = height / bounds.height;
else {
if (bounds.width * height < bounds.height * width)
scale = bounds.width / width;
else
scale = bounds.height / height;
}
if (scale != priv->scale) {
priv->scale = scale;
priv->origin_x = 0;
priv->origin_y = 0;
invalidate (renderer);
}
}
@ -872,9 +943,9 @@ eek_renderer_get_size (EekRenderer *renderer,
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (width)
*width = bounds.width;
*width = bounds.width * priv->scale;
if (height)
*height = bounds.height;
*height = bounds.height * priv->scale;
}
void
@ -887,6 +958,7 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
EekBounds section_bounds, keyboard_bounds;
gint angle = 0;
EekPoint points[4], min, max;
gint i;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_KEY(key));
@ -904,6 +976,10 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
if (!rotate) {
bounds->x += keyboard_bounds.x + section_bounds.x;
bounds->y += keyboard_bounds.y + section_bounds.y;
bounds->x *= priv->scale;
bounds->y *= priv->scale;
bounds->width *= priv->scale;
bounds->height *= priv->scale;
return;
}
points[0].x = bounds->x;
@ -920,7 +996,7 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
min = points[2];
max = points[0];
for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
for (i = 0; i < G_N_ELEMENTS(points); i++) {
eek_point_rotate (&points[i], angle);
if (points[i].x < min.x)
min.x = points[i].x;
@ -935,6 +1011,10 @@ eek_renderer_get_key_bounds (EekRenderer *renderer,
bounds->y = keyboard_bounds.y + section_bounds.y + min.y;
bounds->width = (max.x - min.x);
bounds->height = (max.y - min.y);
bounds->x *= priv->scale;
bounds->y *= priv->scale;
bounds->width *= priv->scale;
bounds->height *= priv->scale;
}
gdouble
@ -947,15 +1027,6 @@ eek_renderer_get_scale (EekRenderer *renderer)
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 *
eek_renderer_create_pango_layout (EekRenderer *renderer)
{
@ -999,35 +1070,16 @@ eek_renderer_render_key_outline (EekRenderer *renderer,
cairo_surface_t *
eek_renderer_get_icon_surface (EekRenderer *renderer,
const gchar *icon_name,
gint size,
gint scale)
gint size)
{
GError *error = NULL;
cairo_surface_t *surface;
EekRendererClass *klass;
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
surface = g_hash_table_lookup (priv->icons, icon_name);
if (!surface) {
surface = gtk_icon_theme_load_surface (gtk_icon_theme_get_default (),
icon_name,
size,
scale,
NULL,
0,
&error);
g_hash_table_insert (priv->icons, g_strdup(icon_name), surface);
if (surface == NULL) {
g_warning ("can't get icon surface for %s: %s",
icon_name,
error->message);
g_error_free (error);
return NULL;
}
}
return surface;
klass = EEK_RENDERER_GET_CLASS(renderer);
if (klass->get_icon_surface)
return klass->get_icon_surface (renderer, icon_name, size);
return NULL;
}
void
@ -1162,6 +1214,7 @@ find_key_by_position_key_callback (EekElement *element,
FindKeyByPositionCallbackData *data = user_data;
EekBounds bounds;
EekPoint points[4];
gint i;
gboolean b1, b2, b3;
eek_element_get_bounds (element, &bounds);
@ -1175,10 +1228,14 @@ find_key_by_position_key_callback (EekElement *element,
points[3].x = points[0].x;
points[3].y = points[2].y;
for (uint i = 0; i < G_N_ELEMENTS(points); i++) {
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
for (i = 0; i < G_N_ELEMENTS(points); i++) {
eek_point_rotate (&points[i], data->angle);
points[i].x += data->origin.x;
points[i].y += data->origin.y;
points[i].x *= priv->scale;
points[i].y *= priv->scale;
}
b1 = sign (&data->point, &points[0], &points[1]) < 0.0;
@ -1234,17 +1291,13 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
x /= priv->scale;
y /= priv->scale;
x -= priv->origin_x;
y -= priv->origin_y;
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
if (x < bounds.x ||
y < bounds.y ||
x > bounds.width ||
y > bounds.height)
if (x < bounds.x * priv->scale ||
y < bounds.y * priv->scale ||
x > bounds.width * priv->scale ||
y > bounds.height * priv->scale)
return NULL;
data.point.x = x;

View File

@ -58,8 +58,7 @@ struct _EekRendererClass
cairo_surface_t *(* get_icon_surface) (EekRenderer *self,
const gchar *icon_name,
gint size,
gint scale);
gint size);
/*< private >*/
/* padding */
@ -82,8 +81,6 @@ void eek_renderer_get_key_bounds (EekRenderer *renderer,
gboolean rotate);
gdouble eek_renderer_get_scale (EekRenderer *renderer);
void eek_renderer_set_scale_factor (EekRenderer *renderer,
gint scale);
PangoLayout *eek_renderer_create_pango_layout
(EekRenderer *renderer);
@ -106,8 +103,7 @@ void eek_renderer_render_key (EekRenderer *renderer,
cairo_surface_t *eek_renderer_get_icon_surface (EekRenderer *renderer,
const gchar *icon_name,
gint size,
gint scale);
gint size);
void eek_renderer_render_keyboard (EekRenderer *renderer,
cairo_t *cr);

View File

@ -1,17 +1,17 @@
/*
/*
* 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
@ -27,7 +27,9 @@
* of one or more keys of the #EekKeyClass class.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
@ -122,10 +124,9 @@ on_unlocked (EekKey *key,
static EekKey *
eek_section_real_create_key (EekSection *self,
const gchar *name,
gint keycode,
guint keycode,
gint column_index,
gint row_index)
guint row_index)
{
EekKey *key;
gint num_rows;
@ -141,7 +142,6 @@ eek_section_real_create_key (EekSection *self,
row->num_columns = column_index + 1;
key = g_object_new (EEK_TYPE_KEY,
"name", name,
"keycode", keycode,
"column", column_index,
"row", row_index,
@ -463,7 +463,6 @@ eek_section_get_row (EekSection *section,
/**
* eek_section_create_key:
* @section: an #EekSection
* @name: a name
* @keycode: a keycode
* @column: the column index of the key
* @row: the row index of the key
@ -474,32 +473,19 @@ eek_section_get_row (EekSection *section,
*/
EekKey *
eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode,
guint keycode,
gint column,
gint row)
{
g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
return EEK_SECTION_GET_CLASS(section)->create_key (section,
name,
keycode,
column,
row);
}
const double keyspacing = 4.0;
struct keys_info {
uint count;
double total_width;
double biggest_height;
};
static void
keysizer(EekElement *element, gpointer user_data)
{
static void keysizer(EekElement *element, gpointer user_data) {
EekKey *key = EEK_KEY(element);
EekKeyboard *keyboard = EEK_KEYBOARD(user_data);
uint oref = eek_key_get_oref (key);
EekOutline *outline = eek_keyboard_get_outline (keyboard, oref);
@ -530,16 +516,13 @@ keysizer(EekElement *element, gpointer user_data)
}
}
static void
keycounter (EekElement *element, gpointer user_data)
{
EekKey *key = EEK_KEY(element);
/* Skip keys without labels for the current level. This causes those
keys to be hidden in the visible layout. */
if (!eek_key_has_label(key))
return;
struct keys_info {
uint count;
double total_width;
double biggest_height;
};
static void keycounter (EekElement *element, gpointer user_data) {
struct keys_info *data = user_data;
data->count++;
EekBounds key_bounds = {0};
@ -550,15 +533,9 @@ keycounter (EekElement *element, gpointer user_data)
}
}
static void
keyplacer(EekElement *element, gpointer user_data)
{
EekKey *key = EEK_KEY(element);
/* Skip keys without labels for the current level. */
if (!eek_key_has_label(key))
return;
const double keyspacing = 4.0;
static void keyplacer(EekElement *element, gpointer user_data) {
double *current_offset = user_data;
EekBounds key_bounds = {0};
eek_element_get_bounds(element, &key_bounds);
@ -568,8 +545,7 @@ keyplacer(EekElement *element, gpointer user_data)
*current_offset += key_bounds.width + keyspacing;
}
void
eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
void eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
{
eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard);

View File

@ -62,8 +62,7 @@ struct _EekSectionClass
EekOrientation *orientation);
EekKey *(* create_key) (EekSection *self,
const gchar *name,
gint keycode,
guint keycode,
gint row,
gint column);
@ -100,8 +99,7 @@ void eek_section_get_row (EekSection *section,
EekOrientation *orientation);
EekKey *eek_section_create_key (EekSection *section,
const gchar *name,
gint keycode,
guint keycode,
gint column,
gint row);

View File

@ -27,7 +27,9 @@
* method.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-serializable.h"

View File

@ -25,7 +25,9 @@
* The #EekSymbolClass class represents a symbol assigned to a key.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-symbol.h"
#include "eek-serializable.h"

View File

@ -23,7 +23,9 @@
* @short_description: an #EekText represents a text symbol
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-text.h"
#include "eek-serializable.h"

View File

@ -19,7 +19,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-theme.h"
#include "eek-theme-context.h"

View File

@ -23,7 +23,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include <string.h>
@ -87,6 +89,9 @@ static void eek_theme_node_finalize (GObject *object);
static const EekColor BLACK_COLOR = { 0, 0, 0, 0xff };
static const EekColor TRANSPARENT_COLOR = { 0, 0, 0, 0 };
static const EekColor DEFAULT_SUCCESS_COLOR = { 0x4e, 0x9a, 0x06, 0xff };
static const EekColor DEFAULT_WARNING_COLOR = { 0xf5, 0x79, 0x3e, 0xff };
static const EekColor DEFAULT_ERROR_COLOR = { 0xcc, 0x00, 0x00, 0xff };
static void
eek_theme_node_init (EekThemeNode *self)

View File

@ -43,7 +43,6 @@
* Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
*/
#define G_LOG_DOMAIN "eek-theme"
#include <stdlib.h>
#include <string.h>
@ -167,65 +166,103 @@ eek_theme_class_init (EekThemeClass *klass)
}
/* This is a workaround for a bug in libcroco < 0.6.2 where
* function starting with 'r' (and 'u') are misparsed. We work
* around this by exploiting the fact that libcroco is incomformant
* with the CSS-spec and case sensitive and pre-convert all
* occurrences of rgba to RGBA. Then we make our own parsing
* code check for RGBA as well.
*/
#if LIBCROCO_VERSION_NUMBER < 602
static gboolean
is_identifier_character (char c)
{
/* Actual CSS rules allow for unicode > 0x00a1 and escaped
* characters, but we'll assume we won't do that in our stylesheets
* or at least not next to the string 'rgba'.
*/
return g_ascii_isalnum(c) || c == '-' || c == '_';
}
static void
convert_rgba_RGBA (char *buf)
{
char *p;
p = strstr (buf, "rgba");
while (p)
{
/* Check if this looks like a complete token; this is to
* avoiding mangling, say, a selector '.rgba-entry' */
if (!((p > buf && is_identifier_character (*(p - 1))) ||
(is_identifier_character (*(p + 4)))))
memcpy(p, "RGBA", 4);
p += 4;
p = strstr (p, "rgba");
}
}
static CRStyleSheet *
parse_stylesheet (const char *filename,
GError **error)
{
enum CRStatus status;
char *contents;
gsize length;
CRStyleSheet *stylesheet = NULL;
if (filename == NULL)
return NULL;
if (!g_file_get_contents (filename, &contents, &length, error))
return NULL;
convert_rgba_RGBA (contents);
status = cr_om_parser_simply_parse_buf ((const guchar *) contents,
length,
CR_UTF_8,
&stylesheet);
g_free (contents);
if (status != CR_OK)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Error parsing stylesheet '%s'; errcode:%d", filename, status);
return NULL;
}
return stylesheet;
}
CRDeclaration *
_eek_theme_parse_declaration_list (const char *str)
{
char *copy = g_strdup (str);
CRDeclaration *result;
convert_rgba_RGBA (copy);
result = cr_declaration_parse_list_from_buf ((const guchar *)copy,
CR_UTF_8);
g_free (copy);
return result;
}
#else /* LIBCROCO_VERSION_NUMBER >= 602 */
static CRStyleSheet *
parse_stylesheet (const char *filename,
GError **error)
{
enum CRStatus status;
CRStyleSheet *stylesheet;
g_autoptr (GFileInputStream) stream = NULL;
g_autoptr (GFileInfo) info = NULL;
g_autoptr (GFile) file = NULL;
g_autofree guchar* contents = NULL;
goffset size;
gsize out = 0;
GError *err = NULL;
if (filename == NULL)
return NULL;
g_debug ("Parsing %s", filename);
if (g_strcmp0 (filename, "resource://") > 0) {
file = g_file_new_for_uri (filename);
stream = g_file_read (file, NULL, &err);
if (!stream) {
g_warning ("Failed to open %s: %s", filename, err->message);
g_clear_error (&err);
return NULL;
}
info = g_file_input_stream_query_info (stream,
G_FILE_ATTRIBUTE_STANDARD_SIZE,
NULL,
&err);
if (!info) {
g_warning ("Failed to stat %s: %s", filename, err->message);
g_clear_error (&err);
return NULL;
}
size = g_file_info_get_size (info);
contents = g_malloc0 (size);
if (!g_input_stream_read_all (G_INPUT_STREAM (stream),
contents,
size,
&out,
NULL,
&err)) {
g_warning ("Failed to read %s: %s", filename, err->message);
g_clear_error (&err);
return NULL;
}
status = cr_om_parser_simply_parse_buf (contents,
size,
CR_UTF_8,
&stylesheet);
} else {
status = cr_om_parser_simply_parse_file ((const guchar *) filename,
CR_UTF_8,
&stylesheet);
}
status = cr_om_parser_simply_parse_file ((const guchar *) filename,
CR_UTF_8,
&stylesheet);
if (status != CR_OK)
{
@ -243,6 +280,7 @@ _eek_theme_parse_declaration_list (const char *str)
return cr_declaration_parse_list_from_buf ((const guchar *)str,
CR_UTF_8);
}
#endif /* LIBCROCO_VERSION_NUMBER < 602 */
/* Just g_warning for now until we have something nicer to do */
static CRStyleSheet *

View File

@ -24,7 +24,9 @@
* @short_description: Miscellaneous types used in Libeek
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include <math.h>

30
eek/eek-xkb-0.90.pc.in Normal file
View File

@ -0,0 +1,30 @@
# 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@

684
eek/eek-xkb-layout.c Normal file
View File

@ -0,0 +1,684 @@
/*
* 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;
}

55
eek/eek-xkb-layout.h Normal file
View File

@ -0,0 +1,55 @@
/*
* 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 */

26
eek/eek-xkb.h Normal file
View File

@ -0,0 +1,26 @@
/*
* 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 */

30
eek/eek-xkl-0.90.pc.in Normal file
View File

@ -0,0 +1,30 @@
# 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@

662
eek/eek-xkl-layout.c Normal file
View File

@ -0,0 +1,662 @@
/*
* 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;
}

81
eek/eek-xkl-layout.h Normal file
View File

@ -0,0 +1,81 @@
/*
* 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 */

26
eek/eek-xkl.h Normal file
View File

@ -0,0 +1,26 @@
/*
* 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 */

View File

@ -1,7 +1,7 @@
/*
/*
* 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
@ -21,9 +21,10 @@
* @short_description: Layout engine which loads layout information from XML
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <gio/gio.h> /* GResource */
#include <stdlib.h>
#include <string.h>
@ -34,8 +35,6 @@
#include "eek-keysym.h"
#include "eek-text.h"
#include "squeekboard-resources.h"
enum {
PROP_0,
PROP_ID,
@ -79,6 +78,10 @@ static gboolean parse_symbols (const gchar *path,
EekKeyboard *keyboard,
GError **error);
static void scale_keyboard (EekKeyboard *keyboard,
gdouble width,
gdouble height);
static gboolean validate (const gchar **valid_path_list,
gsize valid_path_list_len,
const gchar *element_name,
@ -243,7 +246,6 @@ struct _GeometryParseData {
gchar *name;
EekOutline outline;
gchar *oref;
gint keycode;
GHashTable *key_oref_hash;
GHashTable *oref_outline_hash;
@ -266,7 +268,6 @@ geometry_parse_data_new (EekKeyboard *keyboard)
g_str_equal,
g_free,
(GDestroyNotify)eek_outline_free);
data->keycode = 8;
return data;
}
@ -358,6 +359,8 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
if (g_strcmp0 (data->element_stack->data, "geometry") == 0)
eek_element_set_bounds (EEK_ELEMENT(data->keyboard), &bounds);
else if (g_strcmp0 (data->element_stack->data, "section") == 0)
eek_element_set_bounds (EEK_ELEMENT(data->section), &bounds);
goto out;
}
@ -395,29 +398,26 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
guint keycode;
attribute = get_attribute (attribute_names, attribute_values,
"name");
"keycode");
if (attribute == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"no \"name\" attribute for \"key\"");
"no \"keycode\" attribute for \"key\"");
return;
}
gchar *name = g_strdup (attribute);
attribute = get_attribute (attribute_names, attribute_values,
"keycode");
if (attribute != NULL)
keycode = strtol (attribute, NULL, 10);
else
keycode = data->keycode++;
keycode = strtoul (attribute, NULL, 10);
data->key = eek_section_create_key (data->section,
name,
keycode,
data->num_columns,
data->num_rows - 1);
attribute = get_attribute (attribute_names, attribute_values,
"name");
if (attribute != NULL)
eek_element_set_name (EEK_ELEMENT(data->key), attribute);
attribute = get_attribute (attribute_names, attribute_values,
"oref");
if (attribute == NULL) {
@ -451,7 +451,7 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
"corner-radius");
if (attribute != NULL)
data->corner_radius = g_strtod (attribute, NULL);
goto out;
}
@ -621,25 +621,28 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
return;
if (g_strcmp0 (element_name, "key") == 0) {
guint keycode;
attribute = get_attribute (attribute_names, attribute_values,
"name");
"keycode");
if (attribute == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
"no \"name\" attribute for \"key\"");
"no \"keycode\" attribute for \"key\"");
return;
}
keycode = strtoul (attribute, NULL, 10);
data->key = eek_keyboard_find_key_by_name (data->keyboard,
attribute);
if (data->key == NULL) {
data->key = eek_keyboard_find_key_by_keycode (data->keyboard,
keycode);
/*if (data->key == NULL) {
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
"no such key %s", attribute);
}
"no such keycode %u", keycode);
return;
}*/
attribute = get_attribute (attribute_names, attribute_values,
"groups");
@ -722,6 +725,7 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
gint levels = num_symbols / data->groups;
EekSymbolMatrix *matrix = eek_symbol_matrix_new (data->groups,
levels);
head = data->symbols = g_slist_reverse (data->symbols);
for (i = 0; i < num_symbols; i++) {
if (head && head->data) {
@ -940,7 +944,8 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
return NULL;
}
eek_layout_place_sections(keyboard);
/* Fit keyboard in the given width and hight. */
scale_keyboard (keyboard, initial_width, initial_height);
/* Use pre-defined modifier mask here. */
eek_keyboard_set_num_lock_mask (keyboard, EEK_MOD2_MASK);
@ -1053,10 +1058,10 @@ initable_init (GInitable *initable,
gchar *path;
EekXmlKeyboardDesc *desc;
priv->keyboards_dir = g_strdup ((gchar *) g_getenv ("EEKBOARD_KEYBOARDSDIR"));
priv->keyboards_dir = (gchar *) g_getenv ("EEKBOARD_KEYBOARDSDIR");
if (priv->keyboards_dir == NULL)
priv->keyboards_dir = g_strdup ("resource:///sm/puri/squeekboard/keyboards/");
priv->keyboards_dir = KEYBOARDSDIR;
priv->keyboards_dir = g_strdup (priv->keyboards_dir);
path = g_build_filename (priv->keyboards_dir, "keyboards.xml", NULL);
keyboards = parse_keyboards (path, error);
@ -1107,7 +1112,7 @@ eek_xml_list_keyboards (void)
keyboards_dir = g_getenv ("EEKBOARD_KEYBOARDSDIR");
if (keyboards_dir == NULL)
keyboards_dir = g_strdup ("resource:///sm/puri/squeekboard/keyboards/");
keyboards_dir = KEYBOARDSDIR;
path = g_build_filename (keyboards_dir, "keyboards.xml", NULL);
keyboards = parse_keyboards (path, NULL);
g_free (path);
@ -1132,6 +1137,38 @@ eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc)
g_slice_free (EekXmlKeyboardDesc, desc);
}
struct place_data {
double desired_width;
double current_offset;
EekKeyboard *keyboard;
};
const double section_spacing = 7.0;
static void section_placer(EekElement *element, gpointer user_data) {
struct place_data *data = (struct place_data*)user_data;
EekBounds section_bounds = {0};
eek_element_get_bounds(element, &section_bounds);
section_bounds.width = data->desired_width;
eek_element_set_bounds(element, &section_bounds);
// Sections are rows now. Gather up all the keys and adjust their bounds.
eek_section_place_keys(EEK_SECTION(element), EEK_KEYBOARD(data->keyboard));
eek_element_get_bounds(element, &section_bounds);
section_bounds.y = data->current_offset;
eek_element_set_bounds(element, &section_bounds);
data->current_offset += section_bounds.height + section_spacing;
}
static void section_counter(EekElement *element, gpointer user_data) {
double *total_height = user_data;
EekBounds section_bounds = {0};
eek_element_get_bounds(element, &section_bounds);
*total_height += section_bounds.height + section_spacing;
}
static gboolean
parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
{
@ -1144,9 +1181,7 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
GFileInputStream *input;
gboolean retval;
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
file = g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1186,6 +1221,27 @@ parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
}
g_hash_table_destroy (oref_hash);
/* Order rows */
// This needs to be done after outlines, because outlines define key sizes
// TODO: do this only for rows without bounds
// The keyboard width is given by the user via screen size. The height will be given dynamically.
// TODO: calculate max line width beforehand for button centering. Leave keyboard centering to the renderer later
EekBounds keyboard_bounds = {0};
eek_element_get_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
struct place_data placer_data = {
.desired_width = keyboard_bounds.width,
.current_offset = 0,
.keyboard = keyboard,
};
eek_container_foreach_child(EEK_CONTAINER(keyboard), section_placer, &placer_data);
double total_height = 0;
eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height);
keyboard_bounds.height = total_height;
eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
geometry_parse_data_free (data);
return TRUE;
}
@ -1251,9 +1307,7 @@ parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error)
GFileInputStream *input;
gboolean retval;
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
file = g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1286,9 +1340,7 @@ parse_prerequisites (const gchar *path, GError **error)
GList *prerequisites;
gboolean retval;
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
file = g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1323,9 +1375,7 @@ parse_keyboards (const gchar *path, GError **error)
GList *keyboards;
gboolean retval;
file = g_str_has_prefix (path, "resource://")
? g_file_new_for_uri (path)
: g_file_new_for_path (path);
file = g_file_new_for_path (path);
input = g_file_read (file, NULL, error);
g_object_unref (file);
@ -1351,6 +1401,65 @@ parse_keyboards (const gchar *path, GError **error)
return keyboards;
}
static void scale_bounds_callback (EekElement *element,
gpointer user_data);
static void
scale_bounds (EekElement *element,
gdouble scale)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.x *= scale;
bounds.y *= scale;
bounds.width *= scale;
bounds.height *= scale;
eek_element_set_bounds (element, &bounds);
if (EEK_IS_CONTAINER(element))
eek_container_foreach_child (EEK_CONTAINER(element),
scale_bounds_callback,
&scale);
}
static void
scale_bounds_callback (EekElement *element,
gpointer user_data)
{
scale_bounds (element, *(gdouble *)user_data);
}
static void scale_keyboard (EekKeyboard *keyboard,
gdouble width,
gdouble height)
{
gdouble scale;
EekBounds bounds;
gsize n_outlines;
guint i;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
if (width * bounds.height < height * bounds.width)
scale = width / bounds.width;
else
scale = height / bounds.height;
scale_bounds (EEK_ELEMENT(keyboard), scale);
n_outlines = eek_keyboard_get_n_outlines (keyboard);
for (i = 0; i < n_outlines; i++) {
EekOutline *outline = eek_keyboard_get_outline (keyboard, i);
gint j;
for (j = 0; j < outline->num_points; j++) {
outline->points[j].x *= scale;
outline->points[j].y *= scale;
}
}
}
static gboolean
validate (const gchar **valid_path_list,
gsize valid_path_list_len,

317
eek/eek-xml.c Normal file
View File

@ -0,0 +1,317 @@
/*
* 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: eek-xml
* @title: XML Conversion Utilities
* @short_description: #EekKeyboard to XML conversion utilities
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdarg.h>
#include <glib/gprintf.h>
#include "eek-section.h"
#include "eek-key.h"
#include "eek-xml.h"
#include "eek-keysym.h"
#include "eek-text.h"
#define g_string_append_indent(string, indent) \
{ \
gint i; \
for (i = 0; i < (indent); i++) { \
g_string_append (string, " "); \
} \
}
void
g_string_markup_printf (GString *output, const gchar *format, ...)
{
gchar *escaped_text;
va_list ap;
va_start (ap, format);
escaped_text = g_markup_vprintf_escaped (format, ap);
va_end (ap);
g_string_append (output, escaped_text);
g_free (escaped_text);
}
struct _OutputCallbackData {
GString *output;
gint indent;
GHashTable *oref_hash;
gint key_serial;
};
typedef struct _OutputCallbackData OutputCallbackData;
static void
output_bounds (GString *output, EekBounds *bounds)
{
g_string_markup_printf (output,
"<bounds>%lf,%lf,%lf,%lf</bounds>\n",
bounds->x,
bounds->y,
bounds->width,
bounds->height);
}
static void
output_symbol_attributes (GString *output,
EekSymbol *symbol)
{
if (eek_symbol_get_name (symbol) != NULL)
g_string_markup_printf (output, " name=\"%s\"",
eek_symbol_get_name (symbol));
if (eek_symbol_get_label (symbol) != NULL)
g_string_markup_printf (output, " label=\"%s\"",
eek_symbol_get_label (symbol));
if (eek_symbol_get_category (symbol) != EEK_SYMBOL_CATEGORY_UNKNOWN)
g_string_markup_printf (output, " category=\"%s\"",
eek_symbol_category_get_name (eek_symbol_get_category (symbol)));
}
static void
output_key_callback (EekElement *element, gpointer user_data)
{
OutputCallbackData *data = user_data;
EekBounds bounds;
gint i, num_symbols;
EekSymbolMatrix *matrix;
gint column, row;
guint keycode;
gchar *id;
gulong oref;
keycode = eek_key_get_keycode (EEK_KEY(element));
if (keycode == EEK_INVALID_KEYCODE)
id = g_strdup_printf ("key%d", data->key_serial);
else
id = g_strdup_printf ("keycode%d", keycode);
data->key_serial++;
eek_key_get_index (EEK_KEY(element), &column, &row);
g_string_append_indent (data->output, data->indent);
if (eek_element_get_name (element))
g_string_markup_printf (data->output,
"<key id=\"%s\" name=\"%s\" "
"column=\"%d\" row=\"%d\">\n",
id,
eek_element_get_name (element),
column,
row);
else
g_string_markup_printf (data->output,
"<key id=\"%s\" "
"column=\"%d\" row=\"%d\">\n",
id,
column,
row);
g_free (id);
eek_element_get_bounds (element, &bounds);
g_string_append_indent (data->output, data->indent + 1);
output_bounds (data->output, &bounds);
oref = eek_key_get_oref (EEK_KEY(element));
if (oref != 0) {
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output,
"<oref>outline%u</oref>\n",
oref);
if (!g_hash_table_lookup (data->oref_hash, (gpointer)oref))
g_hash_table_insert (data->oref_hash,
(gpointer)oref,
(gpointer)TRUE);
}
matrix = eek_key_get_symbol_matrix (EEK_KEY(element));
num_symbols = matrix->num_groups * matrix->num_levels;
if (num_symbols > 0) {
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output,
"<symbols groups=\"%d\" levels=\"%d\">\n",
matrix->num_groups, matrix->num_levels);
for (i = 0; i < num_symbols; i++) {
EekSymbol *symbol = matrix->data[i];
g_string_append_indent (data->output, data->indent + 2);
if (EEK_IS_KEYSYM(symbol)) {
guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
g_string_markup_printf (data->output, "<keysym");
output_symbol_attributes (data->output, symbol);
if (xkeysym != EEK_INVALID_KEYSYM)
g_string_markup_printf (data->output, " keyval=\"%u\"",
xkeysym);
g_string_markup_printf (data->output, ">%s</keysym>\n",
eek_symbol_get_name (symbol));
}
else if (EEK_IS_TEXT(symbol)) {
g_string_markup_printf (data->output, "<text");
output_symbol_attributes (data->output, symbol);
g_string_markup_printf (data->output,
">%s</text>\n",
eek_text_get_text (EEK_TEXT(symbol)));
}
else {
g_string_markup_printf (data->output, "<symbol");
output_symbol_attributes (data->output, symbol);
g_string_markup_printf (data->output,
">%s</symbol>\n",
eek_symbol_get_name (symbol));
}
}
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "</symbols>\n");
}
g_string_append_indent (data->output, data->indent);
g_string_markup_printf (data->output, "</key>\n");
}
static void
output_section_callback (EekElement *element, gpointer user_data)
{
OutputCallbackData *data = user_data;
EekBounds bounds;
gint angle, n_rows, i;
g_string_append_indent (data->output, data->indent);
if (eek_element_get_name (element))
g_string_markup_printf (data->output, "<section name=\"%s\">\n",
eek_element_get_name (element));
else
g_string_markup_printf (data->output, "<section>\n");
eek_element_get_bounds (element, &bounds);
g_string_append_indent (data->output, data->indent + 1);
output_bounds (data->output, &bounds);
angle = eek_section_get_angle (EEK_SECTION(element));
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "<angle>%d</angle>\n", angle);
n_rows = eek_section_get_n_rows (EEK_SECTION(element));
for (i = 0; i < n_rows; i++) {
gint num_columns;
EekOrientation orientation;
eek_section_get_row (EEK_SECTION(element),
i,
&num_columns,
&orientation);
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "<row>\n");
g_string_append_indent (data->output, data->indent + 2);
g_string_markup_printf (data->output, "<columns>%d</columns>\n",
num_columns);
g_string_append_indent (data->output, data->indent + 2);
g_string_markup_printf (data->output, "<orientation>%d</orientation>\n",
orientation);
g_string_append_indent (data->output, data->indent + 1);
g_string_markup_printf (data->output, "</row>\n");
}
data->indent++;
eek_container_foreach_child (EEK_CONTAINER(element),
output_key_callback,
data);
data->indent--;
g_string_append_indent (data->output, data->indent);
g_string_markup_printf (data->output, "</section>\n");
}
/**
* eek_keyboard_output:
* @keyboard: an #EekKeyboard
* @output: a GString
* @indent: an integer
*
* Convert @keyboard into the XML format and store it into @output.
*/
void
eek_keyboard_output (EekKeyboard *keyboard, GString *output, gint indent)
{
OutputCallbackData data;
EekBounds bounds;
gulong oref;
GHashTableIter iter;
g_assert (EEK_IS_KEYBOARD(keyboard));
g_string_append_indent (output, indent);
if (eek_element_get_name (EEK_ELEMENT(keyboard)))
g_string_markup_printf (output, "<?xml version=\"1.0\"?>\n"
"<keyboard version=\"%s\" id=\"%s\">\n",
EEK_XML_SCHEMA_VERSION,
eek_element_get_name (EEK_ELEMENT(keyboard)));
else
g_string_markup_printf (output, "<?xml version=\"1.0\"?>\n"
"<keyboard version=\"%s\">\n",
EEK_XML_SCHEMA_VERSION);
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
g_string_append_indent (output, indent + 1);
output_bounds (output, &bounds);
data.output = output;
data.indent = indent;
data.oref_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
data.key_serial = 0;
data.indent++;
eek_container_foreach_child (EEK_CONTAINER(keyboard),
output_section_callback,
&data);
data.indent--;
g_hash_table_iter_init (&iter, data.oref_hash);
while (g_hash_table_iter_next (&iter, (gpointer *)&oref, NULL)) {
EekOutline *outline;
gint j;
outline = eek_keyboard_get_outline (keyboard, oref);
g_string_append_indent (output, indent + 1);
g_string_markup_printf (output, "<outline id=\"outline%u\">\n", oref);
g_string_append_indent (output, indent + 2);
g_string_markup_printf (output, "<corner-radius>%lf</corner-radius>\n",
outline->corner_radius);
for (j = 0; j < outline->num_points; j++) {
g_string_append_indent (output, indent + 2);
g_string_markup_printf (output, "<point>%lf,%lf</point>\n",
outline->points[j].x,
outline->points[j].y);
}
g_string_append_indent (output, indent + 1);
g_string_markup_printf (output, "</outline>\n");
}
g_hash_table_destroy (data.oref_hash);
g_string_append_indent (output, indent);
g_string_markup_printf (output, "</keyboard>\n");
}

39
eek/eek-xml.h Normal file
View File

@ -0,0 +1,39 @@
/*
* 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/>.
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_XML_H
#define EEK_XML_H 1
#include <glib-object.h>
#include "eek-keyboard.h"
#include "eek-xml-layout.h"
G_BEGIN_DECLS
#define EEK_XML_SCHEMA_VERSION "0.90"
void eek_keyboard_output (EekKeyboard *keyboard,
GString *output,
gint indent);
G_END_DECLS
#endif /* EEK_XML_H */

View File

@ -23,7 +23,9 @@
* @title: Library Initialization
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek.h"

View File

@ -29,6 +29,7 @@
#include "eek-symbol.h"
#include "eek-keysym.h"
#include "eek-text.h"
#include "eek-xml.h"
#include "eek-serializable.h"
#include "eek-theme.h"

View File

@ -1,39 +0,0 @@
#include <gdk/gdk.h>
#include <xkbcommon/xkbcommon.h>
gboolean
squeek_keymap_get_entries_for_keyval (struct xkb_keymap *xkb_keymap,
guint keyval,
GdkKeymapKey **keys,
guint *n_keys);
static const char *keymap_header = "xkb_keymap {\n\
\n";
static const char *keymap_keycodes_header = "\
xkb_keycodes \"squeekboard\" {\n\n\
minimum = 8;\n\
maximum = 255;\n\
\n";
static const char *keymap_symbols_header = "\
xkb_symbols \"squeekboard\" {\n\
\n\
name[Group1] = \"Letters\";\n\
name[Group2] = \"Numbers/Symbols\";\n\
\n";
static const char *keymap_footer = "\
xkb_types \"squeekboard\" {\n\
\n\
type \"TWO_LEVEL\" {\n\
modifiers = Shift;\n\
map[Shift] = Level2;\n\
level_name[Level1] = \"Base\";\n\
level_name[Level2] = \"Shift\";\n\
};\n\
};\n\
\n\
xkb_compatibility \"squeekboard\" {\n\
};\n\
};";

View File

@ -65,9 +65,9 @@ static void layer_surface_configure(void *data,
uint32_t height)
{
PhoshLayerSurface *self = data;
gtk_window_resize (GTK_WINDOW (self), width, height);
zwlr_layer_surface_v1_ack_configure(surface, serial);
gtk_widget_show_all (GTK_WIDGET (self));
g_signal_emit (self, signals[CONFIGURED], 0);
}
@ -180,39 +180,22 @@ phosh_layer_surface_get_property (GObject *object,
static void
on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused)
phosh_layer_surface_constructed (GObject *object)
{
PhoshLayerSurfacePrivate *priv;
PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
GdkWindow *gdk_window;
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object);
priv = phosh_layer_surface_get_instance_private (self);
gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
/* Realize the window so we can get the GDK window */
gtk_widget_realize(GTK_WIDGET (self));
gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
gdk_wayland_window_set_use_custom_surface (gdk_window);
priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
}
static void
on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
{
PhoshLayerSurfacePrivate *priv;
GdkWindow *gdk_window;
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
priv = phosh_layer_surface_get_instance_private (self);
if (!priv->wl_surface) {
gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
gdk_wayland_window_set_use_custom_surface (gdk_window);
priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
}
g_debug ("Mapped %p", priv->wl_surface);
priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
priv->wl_surface,
priv->wl_output,
@ -226,45 +209,8 @@ on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
&layer_surface_listener,
self);
wl_surface_commit(priv->wl_surface);
/* Process all pending events, otherwise we end up sending ack configure
* to a not yet configured surface */
wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ()));
}
static void
on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused)
{
PhoshLayerSurfacePrivate *priv;
g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
priv = phosh_layer_surface_get_instance_private (self);
priv = phosh_layer_surface_get_instance_private (self);
if (priv->layer_surface) {
zwlr_layer_surface_v1_destroy(priv->layer_surface);
priv->layer_surface = NULL;
}
priv->wl_surface = NULL;
}
static void
phosh_layer_surface_constructed (GObject *object)
{
PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
g_signal_connect (self, "realize",
G_CALLBACK (on_phosh_layer_surface_realized),
NULL);
g_signal_connect (self, "map",
G_CALLBACK (on_phosh_layer_surface_mapped),
NULL);
g_signal_connect (self, "unmap",
G_CALLBACK (on_phosh_layer_surface_unmapped),
NULL);
}
static void
phosh_layer_surface_dispose (GObject *object)
{
@ -406,12 +352,6 @@ phosh_layer_surface_new (gpointer layer_shell,
"wl-output", wl_output);
}
/**
* phosh_layer_surface_get_surface:
*
* Get the layer layer surface or #NULL if the window
* is not yet realized.
*/
struct zwlr_layer_surface_v1 *
phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
{
@ -423,12 +363,6 @@ phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
}
/**
* phosh_layer_surface_get_wl_surface:
*
* Get the layer wayland surface or #NULL if the window
* is not yet realized.
*/
struct wl_surface *
phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self)
{

136
eekboard/Makefile.am Normal file
View File

@ -0,0 +1,136 @@
# 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
NULL =
lib_LTLIBRARIES = libeekboard.la
libeekboard_headers = \
$(srcdir)/eekboard-service.h \
$(srcdir)/eekboard-context-service.h \
$(srcdir)/eekboard-client.h \
$(srcdir)/eekboard-context.h \
$(srcdir)/eekboard-xklutil.h \
$(NULL)
libeekboard_private_headers = \
$(builddir)/eekboard-marshalers.h \
$(NULL)
libeekboard_sources = \
$(srcdir)/eekboard-service.c \
$(srcdir)/eekboard-context-service.c \
$(srcdir)/eekboard-client.c \
$(srcdir)/eekboard-context.c \
$(srcdir)/eekboard-xklutil.c \
$(NULL)
libeekboard_marshalers_sources = \
$(builddir)/eekboard-marshalers.c \
$(builddir)/eekboard-marshalers.h \
$(NULL)
BUILT_SOURCES = \
$(libeekboard_marshalers_sources) \
$(NULL)
libeekboard_la_SOURCES = \
$(libeekboard_sources) \
$(builddir)/eekboard-marshalers.c \
$(NULL)
libeekboard_la_CFLAGS = \
-DEEKBOARD_COMPILATION=1 \
-DKEYBOARDDIR=\"$(pkgdatadir)/keyboards\" \
-I$(top_srcdir) \
$(GIO2_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) \
$(NULL)
libeekboard_la_LIBADD = \
$(top_builddir)/eek/libeek.la \
$(top_builddir)/eek/libeek-xkl.la \
$(GIO2_LIBS) \
$(LIBXKLAVIER_LIBS) \
$(NULL)
eekboarddir = $(includedir)/eekboard-$(EEK_API_VERSION)/eekboard
eekboard_HEADERS = $(libeekboard_headers)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
eekboard-$(EEK_API_VERSION).pc \
$(NULL)
DISTCLEANFILES = \
$(BUILT_SOURCES) \
$(pkgconfig_DATA) \
$(NULL)
CLEANFILES =
EXTRA_DIST = eekboard-marshalers.list
# gen marshal
eekboard-marshalers.h: eekboard-marshalers.list
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
--prefix=_eekboard_marshal \
$(srcdir)/eekboard-marshalers.list --header --internal \
> $@.tmp && \
mv $@.tmp $@
eekboard-marshalers.c: eekboard-marshalers.list eekboard-marshalers.h
$(AM_V_GEN) (echo "#include \"eekboard-marshalers.h\""; \
$(GLIB_GENMARSHAL) \
--prefix=_eekboard_marshal \
$(srcdir)/eekboard-marshalers.list --body --internal) \
> $@.tmp && \
mv $@.tmp $@
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = \
--add-include-path=$(builddir) \
--add-include-path=$(top_builddir)/eek \
$(NULL)
INTROSPECTION_COMPILER_ARGS = \
--includedir=$(builddir) \
--includedir=$(top_builddir)/eek \
$(NULL)
if HAVE_INTROSPECTION
Eekboard@EEK_LIBRARY_SUFFIX@.gir: libeekboard.la
Eekboard@EEK_LIBRARY_SUFFIX_U@_gir_SCANNERFLAGS = \
--identifier-prefix=Eekboard \
--symbol-prefix=eekboard \
$(NULL)
Eekboard@EEK_LIBRARY_SUFFIX_U@_gir_INCLUDES = Eek@EEK_LIBRARY_SUFFIX@
Eekboard@EEK_LIBRARY_SUFFIX_U@_gir_CFLAGS = $(libeekboard_la_CFLAGS)
Eekboard@EEK_LIBRARY_SUFFIX_U@_gir_LIBS = libeekboard.la
Eekboard@EEK_LIBRARY_SUFFIX_U@_gir_FILES = $(libeekboard_sources) $(libeekboard_headers)
INTROSPECTION_GIRS += Eekboard@EEK_LIBRARY_SUFFIX@.gir
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)
typelibdir = $(libdir)/girepository-1.0
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
CLEANFILES += $(gir_DATA) $(typelib_DATA)
endif
-include $(top_srcdir)/git.mk

404
eekboard/eekboard-client.c Normal file
View File

@ -0,0 +1,404 @@
/*
* 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);
}

View File

@ -0,0 +1,64 @@
/*
* 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 */

View File

@ -1,7 +1,7 @@
/*
/*
* 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
@ -25,7 +25,11 @@
* implementation of eekboard input context service.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eekboard/eekboard-context-service.h"
#include <fcntl.h>
#include <stdio.h>
@ -34,14 +38,10 @@
#include <sys/random.h> // TODO: this is Linux-specific
#include <xkbcommon/xkbcommon.h>
#include <gio/gio.h>
#include "eekboard/key-emitter.h"
#include "wayland.h"
#include "eek/eek-xml-layout.h"
#include "eekboard/eekboard-context-service.h"
//#include "eekboard/eekboard-xklutil.h"
//#include "eek/eek-xkl.h"
#define CSW 640
#define CSH 480
@ -80,11 +80,11 @@ struct _EekboardContextServicePrivate {
gboolean repeat_triggered;
GSettings *settings;
uint32_t hint;
uint32_t purpose;
};
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
G_DEFINE_TYPE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
static Display *display = NULL;
static EekKeyboard *
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
@ -146,23 +146,17 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
g_error("No context created");
}
gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
free(keymap_str);
xkb_context_unref(context);
struct xkb_rule_names rules = { 0 };
rules.layout = strdup(keyboard_type);
struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, &rules,
XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!keymap) {
g_error("Bad keymap");
}
keyboard->keymap = keymap;
keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
keyboard->keymap_len = strlen(keymap_str) + 1;
g_autofree char *path = strdup("/eek_keymap-XXXXXX");
char *path = strdup("/eek_keymap-XXXXXX");
char *r = &path[strlen(path) - 6];
getrandom(r, 6, GRND_NONBLOCK);
for (uint i = 0; i < 6; i++) {
@ -217,7 +211,12 @@ eekboard_context_service_set_property (GObject *object,
context->priv->keyboard = g_value_get_object (value);
break;
case PROP_VISIBLE:
context->priv->visible = g_value_get_boolean (value);
/*if (context->priv->keyboard) {
if (g_value_get_boolean (value))
eekboard_context_service_show_keyboard (context);
else
eekboard_context_service_hide_keyboard (context);
}*/
break;
case PROP_FULLSCREEN:
context->priv->fullscreen = g_value_get_boolean (value);
@ -285,12 +284,10 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
}
}
g_variant_iter_free(iter);
g_variant_unref(inputs);
}
static void
settings_update_layout(EekboardContextService *context)
{
settings_update_layout(EekboardContextService *context) {
g_autofree gchar *keyboard_type = NULL;
g_autofree gchar *keyboard_layout = NULL;
settings_get_layout(context->priv->settings, &keyboard_type, &keyboard_layout);
@ -302,17 +299,6 @@ settings_update_layout(EekboardContextService *context)
keyboard_layout = g_strdup("undefined");
}
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
switch (priv->purpose) {
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
keyboard_layout = g_strdup("number");
break;
default:
;
}
// generic part follows
static guint keyboard_id = 0;
EekKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
@ -370,6 +356,9 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class,
sizeof (EekboardContextServicePrivate));
klass->create_keyboard = eekboard_context_service_real_create_keyboard;
klass->show_keyboard = eekboard_context_service_real_show_keyboard;
klass->hide_keyboard = eekboard_context_service_real_hide_keyboard;
@ -494,6 +483,51 @@ eekboard_context_service_init (EekboardContextService *self)
}
}
static gboolean on_repeat_timeout (EekboardContextService *context);
static gboolean
on_repeat_timeout (EekboardContextService *context)
{
guint delay = 500; // ms
// hardcoding; needs to connect to yet another settings path because
// org.gnome.desktop.input-sources doesn't control repeating
//g_settings_get (context->priv->settings, "repeat-interval", "u", &delay);
context->priv->repeat_timeout_id =
g_timeout_add (delay,
(GSourceFunc)on_repeat_timeout,
context);
return FALSE;
}
static gboolean
on_repeat_timeout_init (EekboardContextService *context)
{
/* FIXME: clear modifiers for further key repeat; better not
depend on modifier behavior is LATCH */
eek_keyboard_set_modifiers (context->priv->keyboard, 0);
/* reschedule repeat timeout only when "repeat" option is set */
/* TODO: org.gnome.desktop.input-sources doesn't have repeat info.
* In addition, repeat is only useful when the keyboard is not in text
* input mode */
/*
if (g_settings_get_boolean (context->priv->settings, "repeat")) {
guint delay;
g_settings_get (context->priv->settings, "repeat-interval", "u", &delay);
context->priv->repeat_timeout_id =
g_timeout_add (delay,
(GSourceFunc)on_repeat_timeout,
context);
} else */
context->priv->repeat_timeout_id = 0;
return FALSE;
}
/**
* eekboard_context_service_enable:
* @context: an #EekboardContextService
@ -535,9 +569,7 @@ eekboard_context_service_show_keyboard (EekboardContextService *context)
{
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
if (!context->priv->visible) {
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->show_keyboard (context);
}
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->show_keyboard (context);
}
void
@ -545,9 +577,7 @@ eekboard_context_service_hide_keyboard (EekboardContextService *context)
{
g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context));
if (context->priv->visible) {
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->hide_keyboard (context);
}
EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context)->hide_keyboard (context);
}
/**
@ -600,15 +630,3 @@ void eekboard_context_service_set_keymap(EekboardContextService *context,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
keyboard->keymap_fd, keyboard->keymap_len);
}
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint, uint32_t purpose)
{
EekboardContextServicePrivate *priv = EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE(context);
if (priv->hint != hint || priv->purpose != purpose) {
priv->hint = hint;
priv->purpose = purpose;
settings_update_layout(context);
}
}

View File

@ -25,7 +25,6 @@
#include <eek/eek.h>
#include "virtual-keyboard-unstable-v1-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
G_BEGIN_DECLS
@ -105,9 +104,5 @@ gboolean eekboard_context_service_get_fullscreen
void eekboard_context_service_set_keymap(EekboardContextService *context,
const EekKeyboard *keyboard);
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
uint32_t hint,
uint32_t purpose);
G_END_DECLS
#endif /* EEKBOARD_CONTEXT_SERVICE_H */

View File

@ -24,7 +24,9 @@
* context.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eekboard/eekboard-context.h"
//#include "eekboard/eekboard-marshalers.h"

View File

@ -26,16 +26,16 @@
* implementation of eekboard service.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eekboard/eekboard-service.h"
#include "sm.puri.OSK0.h"
#include <stdio.h>
#include <gio/gio.h>
#include "eekboard/eekboard-service.h"
enum {
PROP_0,
PROP_OBJECT_PATH,
@ -135,11 +135,6 @@ eekboard_service_dispose (GObject *object)
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);
}
@ -171,22 +166,6 @@ handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation,
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
eekboard_service_constructed (GObject *object)
{
@ -194,6 +173,7 @@ eekboard_service_constructed (GObject *object)
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
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_CALLBACK(handle_set_visible), service);
@ -299,12 +279,5 @@ eekboard_service_set_context(EekboardService *service,
{
EekboardServicePrivate *priv = eekboard_service_get_instance_private (service);
g_return_if_fail (!priv->context);
priv->context = context;
g_signal_connect_swapped (priv->context,
"notify::visible",
G_CALLBACK(on_visible),
service);
}

168
eekboard/eekboard-xklutil.c Normal file
View File

@ -0,0 +1,168 @@
/*
* 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);
}

View File

@ -0,0 +1,39 @@
/*
* 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 */

View File

@ -20,6 +20,7 @@
/* This file is responsible for managing keycode data and emitting keycodes. */
#include "eekboard/key-emitter.h"
#include "eekboard/keymap.h"
#include <gdk/gdk.h>
@ -38,6 +39,97 @@ typedef struct {
} SeatEmitter;
/* The following functions for keyboard mapping change are direct
translation of the code in Caribou (in libcaribou/xadapter.vala):
- get_replaced_keycode (Caribou: get_reserved_keycode)
- replace_keycode
- get_keycode_from_gdk_keymap (Caribou: best_keycode_keyval_match)
*/
/* Find an unused keycode where a keysym can be assigned. Restricted to Level 1 */
static guint
get_replaced_keycode (SeatEmitter *client)
{
guint keycode;
return 0; // FIXME: no xkb allocated yet
for (keycode = client->xkb->max_key_code;
keycode >= client->xkb->min_key_code;
--keycode) {
guint offset = client->xkb->map->key_sym_map[keycode].offset;
if (client->xkb->map->key_sym_map[keycode].kt_index[0] == XkbOneLevelIndex &&
client->xkb->map->syms[offset] != NoSymbol) {
return keycode;
}
}
return 0;
}
/* Replace keysym assigned to KEYCODE to KEYSYM. Both args are used
as in-out. If KEYCODE points to 0, this function picks a keycode
from the current map and replace the associated keysym to KEYSYM.
In that case, the replaced keycode is stored in KEYCODE and the old
keysym is stored in KEYSYM. If otherwise (KEYCODE points to
non-zero keycode), it simply changes the current map with the
specified KEYCODE and KEYSYM. */
static gboolean
replace_keycode (SeatEmitter *emitter,
guint keycode,
guint *keysym)
{
GdkDisplay *display = gdk_display_get_default ();
//Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
guint old_keysym;
int keysyms_per_keycode;
KeySym *syms;
return TRUE; // FIXME: no xkb allocated at the moment, pretending all is fine
g_return_val_if_fail (emitter->xkb->min_key_code <= keycode &&
keycode <= emitter->xkb->max_key_code,
FALSE);
g_return_val_if_fail (keysym != NULL, FALSE);
/*
* Update keyboard mapping. Wayland receives keyboard mapping as a string, so XChangeKeyboardMapping needs to translate from the symbol tbale t the string. TODO.
*
syms = XGetKeyboardMapping (xdisplay, keycode, 1, &keysyms_per_keycode);
old_keysym = syms[0];
syms[0] = *keysym;
XChangeKeyboardMapping (xdisplay, keycode, 1, syms, 1);
XSync (xdisplay, False);
XFree (syms);
*keysym = old_keysym;
*/
return TRUE;
}
static gboolean
get_keycode_from_gdk_keymap (SeatEmitter *emitter,
guint keysym,
guint *keycode,
guint *modifiers)
{
GdkKeymapKey *keys, *best_match = NULL;
guint n_keys, i;
if (!squeek_keymap_get_entries_for_keyval (emitter->keymap, keysym, &keys, &n_keys))
return FALSE;
for (i = 0; i < n_keys; i++)
if ((guint)keys[i].group == emitter->group)
best_match = &keys[i];
if (!best_match) {
g_free (keys);
return FALSE;
}
*keycode = best_match->keycode;
*modifiers = best_match->level == 1 ? EEK_SHIFT_MASK : 0;
g_free (keys);
return TRUE;
}
int send_virtual_keyboard_key(
struct zwp_virtual_keyboard_v1 *keyboard,
unsigned int keycode,
@ -50,8 +142,8 @@ int send_virtual_keyboard_key(
static void
send_fake_modifiers_events (SeatEmitter *emitter,
EekModifierType modifiers,
uint32_t timestamp)
EekModifierType modifiers,
uint32_t timestamp)
{
(void)timestamp;
@ -68,6 +160,95 @@ send_fake_modifiers_events (SeatEmitter *emitter,
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, emitter->group);
}
static void
send_fake_key_event (SeatEmitter *emitter,
guint xkeysym,
guint keyboard_modifiers,
gboolean pressed,
uint32_t timestamp)
{
EekModifierType modifiers;
guint old_keysym = xkeysym;
g_return_if_fail (xkeysym > 0);
guint keycode;
if (!get_keycode_from_gdk_keymap (emitter, xkeysym, &keycode, &modifiers)) {
keycode = get_replaced_keycode (emitter);
if (keycode == 0) {
g_warning ("no available keycode to replace");
return;
}
if (!replace_keycode (emitter, keycode, &old_keysym)) {
g_warning ("failed to lookup X keysym %X", xkeysym);
return;
}
}
/* Clear level shift modifiers */
keyboard_modifiers &= (unsigned)~EEK_SHIFT_MASK;
keyboard_modifiers &= (unsigned)~EEK_LOCK_MASK;
/* FIXME: may need to remap ISO_Level3_Shift and NumLock */
modifiers |= keyboard_modifiers;
send_fake_modifiers_events (emitter, modifiers, timestamp);
// There's something magical about subtracting/adding 8 to keycodes for some reason
send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
send_fake_modifiers_events (emitter, modifiers, timestamp);
if (old_keysym != xkeysym)
replace_keycode (emitter, keycode, &old_keysym);
}
static void
send_fake_key_events (SeatEmitter *emitter,
EekSymbol *symbol,
EekModifierType keyboard_modifiers,
gboolean pressed,
uint32_t timestamp)
{
/* Ignore modifier keys */
if (eek_symbol_is_modifier (symbol))
return;
/* If symbol is a text, convert chars in it to keysym */
if (EEK_IS_TEXT(symbol)) {
const gchar *utf8 = eek_text_get_text (EEK_TEXT(symbol));
printf("Attempting to send text %s\n", utf8);
/* FIXME:
glong items_written;
gunichar *ucs4 = g_utf8_to_ucs4_fast (utf8, -1, &items_written);
gint i;
for (i = 0; i < items_written; i++) {
guint xkeysym;
EekKeysym *keysym;
gchar *name;
name = g_strdup_printf ("U%04X", ucs4[i]);
xkeysym = XStringToKeysym (name); // TODO: use xkb_get_keysym_from_name
g_free (name);
keysym = eek_keysym_new (xkeysym);
send_fake_key_events (client,
EEK_SYMBOL(keysym),
keyboard_modifiers);
}
g_free (ucs4);
*/
return;
}
if (EEK_IS_KEYSYM(symbol)) {
guint xkeysym = eek_keysym_get_xkeysym (EEK_KEYSYM(symbol));
send_fake_key_event (emitter, xkeysym, keyboard_modifiers, pressed, timestamp);
}
}
/* Finds the first key code for each modifier and saves it in modifier_keycodes */
static void
update_modifier_info (SeatEmitter *client)
@ -102,26 +283,6 @@ update_modifier_info (SeatEmitter *client)
}*/
}
static void
send_fake_key (SeatEmitter *emitter,
EekKeyboard *keyboard,
guint keycode,
guint keyboard_modifiers,
gboolean pressed,
uint32_t timestamp)
{
uint32_t proto_modifiers = 0;
guint level = eek_element_get_level(EEK_ELEMENT(keyboard));
uint32_t group = (level / 2);
if (keyboard_modifiers & EEK_SHIFT_MASK)
proto_modifiers |= 1<<MOD_IDX_SHIFT;
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group);
send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group);
}
void
emit_key_activated (EekboardContextService *manager,
EekKeyboard *keyboard,
@ -162,5 +323,5 @@ emit_key_activated (EekboardContextService *manager,
emitter.virtual_keyboard = manager->virtual_keyboard;
emitter.keymap = keyboard->keymap;
update_modifier_info (&emitter);
send_fake_key (&emitter, keyboard, keycode, modifiers, pressed, timestamp);
send_fake_key_events (&emitter, symbol, modifiers, pressed, timestamp);
}

View File

@ -3,6 +3,7 @@
#include <inttypes.h>
#include <glib.h>
#include <X11/XKBlib.h>
#include "eek/eek.h"

66
eekboard/keymap.c Normal file
View File

@ -0,0 +1,66 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2000 Red Hat, Inc.
* Copyright (C) 2019 Purism, SPC
*
* 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified for squeekboard based on GTK
*/
#include "keymap.h"
gboolean
squeek_keymap_get_entries_for_keyval (struct xkb_keymap *xkb_keymap,
guint keyval,
GdkKeymapKey **keys,
guint *n_keys)
{
GArray *retval;
guint keycode;
xkb_keycode_t min_keycode, max_keycode;
retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
min_keycode = xkb_keymap_min_keycode (xkb_keymap);
max_keycode = xkb_keymap_max_keycode (xkb_keymap);
for (keycode = min_keycode; keycode < max_keycode; keycode++)
{
xkb_layout_index_t num_layouts, layout;
num_layouts = xkb_keymap_num_layouts_for_key (xkb_keymap, keycode);
for (layout = 0; layout < num_layouts; layout++)
{
xkb_layout_index_t num_levels, level;
num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
for (level = 0; level < num_levels; level++)
{
const xkb_keysym_t *syms;
gint num_syms, sym;
num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
for (sym = 0; sym < num_syms; sym++)
{
if (syms[sym] == keyval)
{
GdkKeymapKey key;
key.keycode = keycode;
key.group = (gint)layout;
key.level = (gint)level;
g_array_append_val (retval, key);
}
}
}
}
}
*n_keys = retval->len;
*keys = (GdkKeymapKey*) g_array_free (retval, FALSE);
return TRUE;
}

Some files were not shown because too many files have changed in this diff Show More