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
160 changed files with 22523 additions and 5864 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:
- 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,64 +1,189 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="10" y="10" width="410.0000" height="229"/>
<outline id="default" corner-radius="1.000000">
<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 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 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 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="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.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"/>
<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.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="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>
<button name="Shift_L" oref="altline" />
<button name="BackSpace" oref="altline" />
<button name="preferences" oref="altline" />
<button name="show_numbers" oref="altline" keycode="0" />
<button name="show_letters" oref="altline" keycode="0" />
<button name="show_symbols" oref="altline" keycode="0" />
<button name="period" oref="altline" />
<button name="space" oref="spaceline" />
<button name="Return" oref="outline7" />
<view>
<section angle="0">q w e r t y u i o p</section>
<section angle="0">a s d f g h j k l</section>
<section angle="0"> Shift_L z x c v b n m BackSpace </section>
<section angle="0"> show_numbers preferences space period Return </section>
</view>
<view>
<section angle="0">Q W E R T Y U I O P</section>
<section angle="0">A S D F G H J K L</section>
<section angle="0"> Shift_L Z X C V B N M BackSpace </section>
<section angle="0"> show_numbers preferences space period Return </section>
</view>
<view>
<section angle="0">1 2 3 4 5 6 7 8 9 0</section>
<section angle="0">at numbersign dollar percent ampersand minus underscore plus parenleft parenright</section>
<section angle="0"> show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace </section>
<section angle="0"> show_letters preferences space period Return </section>
</view>
<view>
<section angle="0">asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph</section>
<section angle="0">copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright</section>
<section angle="0"> show_numbers backslash slash less greater equal bracketleft bracketright BackSpace </section>
<section angle="0"> show_letters preferences space period Return </section>
</view>
</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"/>
<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>
<button name="Shift_L" oref="altline" />
<button name="BackSpace" oref="altline" />
<button name="preferences" oref="altline" />
<button name="show_numbers" oref="altline" keycode="0" />
<button name="show_letters" oref="altline" keycode="0" />
<button name="show_symbols" oref="altline" keycode="0" />
<button name="space" oref="spaceline" />
<button name="return" oref="outline7" />
<view>
<section angle="0">q w e r t y u i o p aring</section>
<section angle="0">a s d f g h j k l oslash ae</section>
<section angle="0"> Shift_L z x c v b n m BackSpace </section>
<section angle="0"> show_numbers preferences space period Return </section>
</view>
<view>
<section angle="0">Q W E R T Y U I O P Aring</section>
<section angle="0">A S D F G H J K L Oslash AE</section>
<section angle="0"> Shift_L Z X C V B N M BackSpace </section>
<section angle="0"> show_numbers preferences space period Return </section>
</view>
<view>
<section angle="0">1 2 3 4 5 6 7 8 9 0</section>
<section angle="0">at numbersign dollar percent ampersand minus underscore plus parenleft parenright</section>
<section angle="0"> show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace </section>
<section angle="0"> show_letters preferences space period Return </section>
</view>
<view>
<section angle="0">asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph</section>
<section angle="0">copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright</section>
<section angle="0"> show_numbers backslash slash less greater equal bracketleft bracketright BackSpace </section>
<section angle="0"> show_letters preferences space period Return </section>
</view>
</geometry>

View File

@ -1,40 +0,0 @@
<?xml version="1.0"?>
<geometry version="0.90">
<bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
<outline id="default" 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="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="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>
<button name="BackSpace" oref="altline" />
<button name="space" oref="spaceline" />
<button name="Return" oref="outline7" />
<view>
<section angle="0">1 2 3 parenleft parenright</section>
<section angle="0">4 5 6 numbersign asterisk</section>
<section angle="0">7 8 9 plus minus</section>
<section angle="0">BackSpace 0 space Return</section>
</view>
</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,132 +0,0 @@
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<symbols version="0.90">
<symbol label="*">asterisk</symbol>
<symbol label="+/=">show_symbols</symbol>
<symbol label="&#964;">Greek_tau</symbol>
<symbol label="å">aring</symbol>
<symbol label="ø">oslash</symbol>
<symbol label="æ">ae</symbol>
<symbol label="Å">Aring</symbol>
<symbol label="Ø">Oslash</symbol>
<symbol label="Æ">AE</symbol>
<symbol label="q">q</symbol>
<symbol label="Q">Q</symbol>
<symbol label="1">1</symbol>
<symbol label="~">asciitilde</symbol>
<symbol label="w">w</symbol>
<symbol label="W">W</symbol>
<symbol label="2">2</symbol>
<symbol label="`">quoteleft</symbol>
<symbol label="e">e</symbol>
<symbol label="E">E</symbol>
<symbol label="3">3</symbol>
<symbol label="|">bar</symbol>
<symbol label="r">r</symbol>
<symbol label="R">R</symbol>
<symbol label="4">4</symbol>
<symbol label="&#183;">U00B7</symbol>
<symbol label="t">t</symbol>
<symbol label="T">T</symbol>
<symbol label="5">5</symbol>
<symbol label="&#8730;">squareroot</symbol>
<symbol label="y">y</symbol>
<symbol label="Y">Y</symbol>
<symbol label="6">6</symbol>
<symbol label="&#960;">Greek_pi</symbol>
<symbol label="u">u</symbol>
<symbol label="U">U</symbol>
<symbol label="7">7</symbol>
<symbol label="&#247;">division</symbol>
<symbol label="i">i</symbol>
<symbol label="I">I</symbol>
<symbol label="8">8</symbol>
<symbol label="&#215;">multiply</symbol>
<symbol label="o">o</symbol>
<symbol label="O">O</symbol>
<symbol label="9">9</symbol>
<symbol label="&#182;">paragraph</symbol>
<symbol label="p">p</symbol>
<symbol label="P">P</symbol>
<symbol label="0">0</symbol>
<symbol label="&#9651;">U25B3</symbol>
<symbol keyval="229" label="&#229;">aring</symbol>
<symbol keyval="197" label="&#197;">Aring</symbol>
<symbol label="a">a</symbol>
<symbol label="A">A</symbol>
<symbol label="@">at</symbol>
<symbol label="&#169;">copyright</symbol>
<symbol label="s">s</symbol>
<symbol label="S">S</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="&#174;">U00AE</symbol>
<symbol label="d">d</symbol>
<symbol label="D">D</symbol>
<symbol label="$">dollar</symbol>
<symbol label="&#163;">U00A3</symbol>
<symbol label="f">f</symbol>
<symbol label="F">F</symbol>
<symbol label="%">percent</symbol>
<symbol label="&#8364;">EuroSign</symbol>
<symbol label="g">g</symbol>
<symbol label="G">G</symbol>
<symbol label="&amp;">ampersand</symbol>
<symbol label="&#165;">U00A5</symbol>
<symbol label="h">h</symbol>
<symbol label="H">H</symbol>
<symbol label="-">minus</symbol>
<symbol label="^">asciicircum</symbol>
<symbol label="j">j</symbol>
<symbol label="J">J</symbol>
<symbol label="_">underscore</symbol>
<symbol label="&#176;">degree</symbol>
<symbol label="k">k</symbol>
<symbol label="K">K</symbol>
<symbol label="+">plus</symbol>
<symbol label="=">equal</symbol>
<symbol label="l">l</symbol>
<symbol label="L">L</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="{">braceleft</symbol>
<symbol keyval="248" label="&#248;">oslash</symbol>
<symbol keyval="216" label="&#216;">Oslash</symbol>
<symbol label=")">parenright</symbol>
<symbol label="}">braceright</symbol>
<symbol keyval="230" label="&#230;">ae</symbol>
<symbol keyval="198" label="&#198;">AE</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65505" icon="key-shift">Shift_L</symbol>
<symbol label="z">z</symbol>
<symbol label="Z">Z</symbol>
<symbol label=",">comma</symbol>
<symbol label="\">backslash</symbol>
<symbol label="x">x</symbol>
<symbol label="X">X</symbol>
<symbol label="&quot;">quotedbl</symbol>
<symbol label="/">slash</symbol>
<symbol label="c">c</symbol>
<symbol label="C">C</symbol>
<symbol label="'">quoteright</symbol>
<symbol label="&lt;">less</symbol>
<symbol label="v">v</symbol>
<symbol label="V">V</symbol>
<symbol label=":">colon</symbol>
<symbol label="&gt;">greater</symbol>
<symbol label="b">b</symbol>
<symbol label="B">B</symbol>
<symbol label=";">semicolon</symbol>
<symbol label="=">equal</symbol>
<symbol label="n">n</symbol>
<symbol label="N">N</symbol>
<symbol label="!">exclam</symbol>
<symbol label="[">bracketleft</symbol>
<symbol label="m">m</symbol>
<symbol label="M">M</symbol>
<symbol label="?">question</symbol>
<symbol label="]">bracketright</symbol>
<symbol label=".">period</symbol>
<symbol label="123">show_numbers</symbol>
<symbol label="ABC">show_letters</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label=" ">space</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</symbols>

View File

@ -1,22 +0,0 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<symbols version="0.90">
<symbol label="1">1</symbol>
<symbol label="2">2</symbol>
<symbol label="3">3</symbol>
<symbol label="(">parenleft</symbol>
<symbol label=")">parenright</symbol>
<symbol label="4">4</symbol>
<symbol label="5">5</symbol>
<symbol label="6">6</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="*">asterisk</symbol>
<symbol label="7">7</symbol>
<symbol label="8">8</symbol>
<symbol label="9">9</symbol>
<symbol label="+">plus</symbol>
<symbol label="-">minus</symbol>
<symbol label="0">0</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol label=" ">space</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
</symbols>

View File

@ -1,118 +1,304 @@
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
<?xml version="1.0"?>
<symbols version="0.90">
<symbol label="*">asterisk</symbol>
<symbol label="+/=">show_symbols</symbol>
<symbol label="q">q</symbol>
<symbol label="Q">Q</symbol>
<symbol label="1">1</symbol>
<symbol label="~">asciitilde</symbol>
<symbol label="w">w</symbol>
<symbol label="W">W</symbol>
<symbol label="2">2</symbol>
<symbol label="`">quoteleft</symbol>
<symbol label="e">e</symbol>
<symbol label="E">E</symbol>
<symbol label="3">3</symbol>
<symbol label="|">bar</symbol>
<symbol label="r">r</symbol>
<symbol label="R">R</symbol>
<symbol label="4">4</symbol>
<symbol label="&#183;">U00B7</symbol>
<symbol label="t">t</symbol>
<symbol label="T">T</symbol>
<symbol label="5">5</symbol>
<symbol label="&#8730;">squareroot</symbol>
<symbol label="y">y</symbol>
<symbol label="Y">Y</symbol>
<symbol label="6">6</symbol>
<symbol label="&#960;">Greek_pi</symbol>
<symbol label="u">u</symbol>
<symbol label="U">U</symbol>
<symbol label="7">7</symbol>
<symbol label="&#247;">division</symbol>
<symbol label="i">i</symbol>
<symbol label="I">I</symbol>
<symbol label="8">8</symbol>
<symbol label="&#215;">multiply</symbol>
<symbol label="o">o</symbol>
<symbol label="O">O</symbol>
<symbol label="9">9</symbol>
<symbol label="&#182;">paragraph</symbol>
<symbol label="p">p</symbol>
<symbol label="P">P</symbol>
<symbol label="0">0</symbol>
<symbol label="&#964;">Greek_tau</symbol>
<symbol label="a">a</symbol>
<symbol label="A">A</symbol>
<symbol label="@">at</symbol>
<symbol label="&#169;">copyright</symbol>
<symbol label="s">s</symbol>
<symbol label="S">S</symbol>
<symbol label="#">numbersign</symbol>
<symbol label="&#174;">U00AE</symbol>
<symbol label="d">d</symbol>
<symbol label="D">D</symbol>
<symbol label="$">dollar</symbol>
<symbol label="&#163;">U00A3</symbol>
<symbol label="f">f</symbol>
<symbol label="F">F</symbol>
<symbol label="%">percent</symbol>
<symbol label="&#8364;">EuroSign</symbol>
<symbol label="g">g</symbol>
<symbol label="G">G</symbol>
<symbol label="&amp;">ampersand</symbol>
<symbol label="&#165;">U00A5</symbol>
<symbol label="h">h</symbol>
<symbol label="H">H</symbol>
<symbol label="-">minus</symbol>
<symbol label="^">asciicircum</symbol>
<symbol label="j">j</symbol>
<symbol label="J">J</symbol>
<symbol label="_">underscore</symbol>
<symbol label="&#176;">degree</symbol>
<symbol label="k">k</symbol>
<symbol label="K">K</symbol>
<symbol label="+">plus</symbol>
<symbol label="=">equal</symbol>
<symbol label="l">l</symbol>
<symbol label="L">L</symbol>
<symbol label="(">parenleft</symbol>
<symbol label="{">braceleft</symbol>
<symbol label=")">parenright</symbol>
<symbol label="}">braceright</symbol>
<symbol keyval="65293" icon="key-enter">Return</symbol>
<symbol keyval="65505" icon="key-shift">Shift_L</symbol>
<symbol label="z">z</symbol>
<symbol label="Z">Z</symbol>
<symbol label=",">comma</symbol>
<symbol label="\">backslash</symbol>
<symbol label="x">x</symbol>
<symbol label="X">X</symbol>
<symbol label="&quot;">quotedbl</symbol>
<symbol label="/">slash</symbol>
<symbol label="c">c</symbol>
<symbol label="C">C</symbol>
<symbol label="'">quoteright</symbol>
<symbol label="&lt;">less</symbol>
<symbol label="v">v</symbol>
<symbol label="V">V</symbol>
<symbol label=":">colon</symbol>
<symbol label="&gt;">greater</symbol>
<symbol label="b">b</symbol>
<symbol label="B">B</symbol>
<symbol label=";">semicolon</symbol>
<symbol label="n">n</symbol>
<symbol label="N">N</symbol>
<symbol label="!">exclam</symbol>
<symbol label="[">bracketleft</symbol>
<symbol label="m">m</symbol>
<symbol label="M">M</symbol>
<symbol label="?">question</symbol>
<symbol label="]">bracketright</symbol>
<symbol label=".">period</symbol>
<symbol label="123">show_numbers</symbol>
<symbol label="ABC">show_letters</symbol>
<symbol label="&#9786;" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
<symbol label=" ">space</symbol>
<symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
<key keycode="9" name="ESC">
<keysym keyval="65307">Escape</keysym>
</key>
<key keycode="67" name="FK01">
<keysym keyval="65470">F1</keysym>
</key>
<key keycode="68" name="FK02">
<keysym keyval="65471">F2</keysym>
</key>
<key keycode="69" name="FK03">
<keysym keyval="65472">F3</keysym>
</key>
<key keycode="70" name="FK04">
<keysym keyval="65473">F4</keysym>
</key>
<key keycode="71" name="FK05">
<keysym keyval="65474">F5</keysym>
</key>
<key keycode="72" name="FK06">
<keysym keyval="65475">F6</keysym>
</key>
<key keycode="73" name="FK07">
<keysym keyval="65476">F7</keysym>
</key>
<key keycode="74" name="FK08">
<keysym keyval="65477">F8</keysym>
</key>
<key keycode="75" name="FK09">
<keysym keyval="65478">F9</keysym>
</key>
<key keycode="76" name="FK10">
<keysym keyval="65479">F10</keysym>
</key>
<key keycode="95" name="FK11">
<keysym keyval="65480">F11</keysym>
</key>
<key keycode="96" name="FK12">
<keysym keyval="65481">F12</keysym>
</key>
<key keycode="49" name="TLDE">
<keysym keyval="96">quoteleft</keysym>
<keysym keyval="126">asciitilde</keysym>
</key>
<key keycode="10" name="AE01">
<keysym keyval="49">1</keysym>
<keysym keyval="33">exclam</keysym>
</key>
<key keycode="11" name="AE02">
<keysym keyval="50">2</keysym>
<keysym keyval="64">at</keysym>
</key>
<key keycode="12" name="AE03">
<keysym keyval="51">3</keysym>
<keysym keyval="35">numbersign</keysym>
</key>
<key keycode="13" name="AE04">
<keysym keyval="52">4</keysym>
<keysym keyval="36">dollar</keysym>
</key>
<key keycode="14" name="AE05">
<keysym keyval="53">5</keysym>
<keysym keyval="37">percent</keysym>
<keysym keyval="8364">EuroSign</keysym>
</key>
<key keycode="15" name="AE06">
<keysym keyval="54">6</keysym>
<keysym keyval="94">asciicircum</keysym>
</key>
<key keycode="16" name="AE07">
<keysym keyval="55">7</keysym>
<keysym keyval="38">ampersand</keysym>
</key>
<key keycode="17" name="AE08">
<keysym keyval="56">8</keysym>
<keysym keyval="42">asterisk</keysym>
</key>
<key keycode="18" name="AE09">
<keysym keyval="57">9</keysym>
<keysym keyval="40">parenleft</keysym>
</key>
<key keycode="19" name="AE10">
<keysym keyval="48">0</keysym>
<keysym keyval="41">parenright</keysym>
</key>
<key keycode="20" name="AE11">
<keysym keyval="45">minus</keysym>
<keysym keyval="95">underscore</keysym>
</key>
<key keycode="21" name="AE12">
<keysym keyval="61">equal</keysym>
<keysym keyval="43">plus</keysym>
</key>
<key keycode="22" name="BKSP">
<keysym keyval="65288">BackSpace</keysym>
</key>
<key keycode="23" name="TAB">
<keysym keyval="65289">Tab</keysym>
<keysym keyval="65056">ISO_Left_Tab</keysym>
</key>
<key keycode="24" name="AD01">
<keysym keyval="113">q</keysym>
<keysym keyval="81">Q</keysym>
<keysym keyval="49">1</keysym>
</key>
<key keycode="25" name="AD02">
<keysym keyval="119">w</keysym>
<keysym keyval="87">W</keysym>
<keysym keyval="50">2</keysym>
</key>
<key keycode="26" name="AD03">
<keysym keyval="101">e</keysym>
<keysym keyval="69">E</keysym>
<keysym keyval="51">3</keysym>
</key>
<key keycode="27" name="AD04">
<keysym keyval="114">r</keysym>
<keysym keyval="82">R</keysym>
<keysym keyval="52">4</keysym>
</key>
<key keycode="28" name="AD05">
<keysym keyval="116">t</keysym>
<keysym keyval="84">T</keysym>
<keysym keyval="53">5</keysym>
</key>
<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

View File

@ -7,8 +7,7 @@
.key {
color: #deddda;
background: #464448;
border-style: solid;
border-width: 1px;
border-width: 0.5px;
border-color: #5e5c64;
border-radius: 2px;
}

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

57
debian/copyright vendored
View File

@ -1,60 +1,9 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: squeekboard
Source: https://source.puri.sm/Librem5/squeekboard
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

234
eek/eek-container.c Normal file
View File

@ -0,0 +1,234 @@
/*
* 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-container
* @short_description: Base class of a keyboard container
*
* The #EekContainerClass class represents a keyboard container, which
* shall be used to implement #EekKeyboard and #EekSection.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-container.h"
enum {
CHILD_ADDED,
CHILD_REMOVED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekContainerPrivate
{
GList *head;
GList *last;
} EekContainerPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekContainer, eek_container, EEK_TYPE_ELEMENT)
static void
eek_container_real_add_child (EekContainer *self,
EekElement *child)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
g_return_if_fail (EEK_IS_ELEMENT(child));
g_object_ref (child);
if (!priv->head) {
priv->head = priv->last = g_list_prepend (priv->head, child);
} else {
priv->last->next = g_list_prepend (priv->last->next, child);
priv->last = priv->last->next;
}
eek_element_set_parent (child, EEK_ELEMENT(self));
g_signal_emit (self, signals[CHILD_ADDED], 0, child);
}
static void
eek_container_real_remove_child (EekContainer *self,
EekElement *child)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
g_return_if_fail (EEK_IS_ELEMENT(child));
head = g_list_find (priv->head, child);
g_return_if_fail (head);
g_object_unref (child);
if (head == priv->last)
priv->last = g_list_previous (priv->last);
priv->head = g_list_remove_link (priv->head, head);
eek_element_set_parent (child, NULL);
g_signal_emit (self, signals[CHILD_REMOVED], 0, child);
}
static void
eek_container_real_foreach_child (EekContainer *self,
EekCallback callback,
gpointer user_data)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
for (head = priv->head; head; head = g_list_next (head))
(*callback) (EEK_ELEMENT(head->data), user_data);
}
static EekElement *
eek_container_real_find (EekContainer *self,
EekCompareFunc func,
gpointer user_data)
{
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
head = g_list_find_custom (priv->head, user_data, (GCompareFunc)func);
if (head)
return head->data;
return NULL;
}
static void
eek_container_dispose (GObject *object)
{
EekContainer *self = EEK_CONTAINER (object);
EekContainerPrivate *priv = eek_container_get_instance_private (self);
GList *head;
for (head = priv->head; head; head = priv->head) {
g_object_unref (head->data);
priv->head = g_list_next (head);
g_list_free1 (head);
}
G_OBJECT_CLASS(eek_container_parent_class)->dispose (object);
}
static void
eek_container_class_init (EekContainerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
klass->add_child = eek_container_real_add_child;
klass->remove_child = eek_container_real_remove_child;
klass->foreach_child = eek_container_real_foreach_child;
klass->find = eek_container_real_find;
/* signals */
klass->child_added = NULL;
klass->child_removed = NULL;
gobject_class->dispose = eek_container_dispose;
/**
* EekContainer::child-added:
* @container: an #EekContainer
* @element: an #EekElement
*
* The ::child-added signal is emitted each time an element is
* added to @container.
*/
signals[CHILD_ADDED] =
g_signal_new (I_("child-added"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekContainerClass, child_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
EEK_TYPE_ELEMENT);
/**
* EekContainer::child-removed:
* @container: an #EekContainer
* @element: an #EekElement
*
* The ::child-removed signal is emitted each time an element is
* removed from @container.
*/
signals[CHILD_REMOVED] =
g_signal_new (I_("child-removed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekContainerClass, child_removed),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
EEK_TYPE_ELEMENT);
}
static void
eek_container_init (EekContainer *self)
{
/* void */
}
/**
* eek_container_foreach_child:
* @container: an #EekContainer
* @callback: (scope call): an #EekCallback
* @user_data: additional data passed to @callback
*
* Enumerate children of @container and run @callback with each child.
*/
void
eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data)
{
g_return_if_fail (EEK_IS_CONTAINER(container));
EEK_CONTAINER_GET_CLASS(container)->foreach_child (container,
callback,
user_data);
}
/**
* eek_container_find:
* @container: an #EekContainer
* @func: function to be used to compare two children
* @user_data: additional data passed to @func
*
* Find a child which matches the criteria supplied as @func, in @container.
* Returns: an #EekElement or NULL on failure
*/
EekElement *
eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data)
{
g_return_val_if_fail (EEK_IS_CONTAINER(container), NULL);
return EEK_CONTAINER_GET_CLASS(container)->find (container,
func,
user_data);
}
void
eek_container_add_child (EekContainer *container, EekElement *element)
{
g_return_if_fail (EEK_IS_CONTAINER(container));
g_return_if_fail (EEK_IS_ELEMENT(element));
return EEK_CONTAINER_GET_CLASS(container)->add_child (container, element);
}

94
eek/eek-container.h Normal file
View File

@ -0,0 +1,94 @@
/*
* 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.h> can be included directly."
#endif
#ifndef EEK_CONTAINER_H
#define EEK_CONTAINER_H 1
#include "eek-element.h"
G_BEGIN_DECLS
#define EEK_TYPE_CONTAINER (eek_container_get_type())
G_DECLARE_DERIVABLE_TYPE (EekContainer, eek_container, EEK, CONTAINER, EekElement)
/**
* EekCallback:
* @element: an #EekElement
* @user_data: user-supplied data
*
* The type of the callback function used for iterating over the
* children of a container, see eek_container_foreach_child().
*/
typedef void (*EekCallback) (EekElement *element, gpointer user_data);
typedef gint (*EekCompareFunc) (EekElement *element, gpointer user_data);
/**
* EekContainerClass:
* @foreach_child: virtual function for iterating over the container's children
* @find: virtual function for looking up a child
* @child_added: class handler for #EekContainer::child-added
* @child_removed: class handler for #EekContainer::child-added
*/
struct _EekContainerClass
{
/*< private >*/
EekElementClass parent_class;
void (* add_child) (EekContainer *self,
EekElement *element);
void (* remove_child) (EekContainer *self,
EekElement *element);
/*< public >*/
void (* foreach_child) (EekContainer *self,
EekCallback callback,
gpointer user_data);
EekElement *(* find) (EekContainer *self,
EekCompareFunc func,
gpointer data);
/* signals */
void (* child_added) (EekContainer *self,
EekElement *element);
void (* child_removed) (EekContainer *self,
EekElement *element);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_container_get_type (void) G_GNUC_CONST;
void eek_container_foreach_child (EekContainer *container,
EekCallback callback,
gpointer user_data);
EekElement *eek_container_find (EekContainer *container,
EekCompareFunc func,
gpointer user_data);
void eek_container_add_child (EekContainer *container,
EekElement *element);
G_END_DECLS
#endif /* EEK_CONTAINER_H */

View File

@ -26,28 +26,58 @@
* shall be used to implement #EekKeyboard, #EekSection, or #EekKey.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include "eek-element.h"
#include "eek-container.h"
#include "eek-marshalers.h"
enum {
PROP_0,
PROP_NAME,
PROP_BOUNDS,
PROP_GROUP,
PROP_LEVEL,
PROP_LAST
};
enum {
SYMBOL_INDEX_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekElementPrivate
{
gchar *name;
EekBounds bounds;
EekElement *parent;
gint group;
gint level;
} EekElementPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekElement, eek_element, G_TYPE_OBJECT)
static void
eek_element_real_symbol_index_changed (EekElement *self,
gint group,
gint level)
{
// g_debug ("symbol-index-changed");
}
static void
eek_element_finalize (GObject *object)
{
EekElement *self = EEK_ELEMENT (object);
EekElementPrivate *priv = eek_element_get_instance_private (self);
g_free (priv->name);
G_OBJECT_CLASS (eek_element_parent_class)->finalize (object);
}
@ -60,9 +90,18 @@ eek_element_set_property (GObject *object,
EekElement *element = EEK_ELEMENT(object);
switch (prop_id) {
case PROP_NAME:
eek_element_set_name (element,
g_value_dup_string (value));
break;
case PROP_BOUNDS:
eek_element_set_bounds (element, g_value_get_boxed (value));
break;
case PROP_GROUP:
eek_element_set_group (element, g_value_get_int (value));
break;
case PROP_LEVEL:
eek_element_set_level (element, g_value_get_int (value));
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -79,10 +118,19 @@ eek_element_get_property (GObject *object,
EekBounds bounds;
switch (prop_id) {
case PROP_NAME:
g_value_set_string (value, eek_element_get_name (element));
break;
case PROP_BOUNDS:
eek_element_get_bounds (element, &bounds);
g_value_set_boxed (value, &bounds);
break;
case PROP_GROUP:
g_value_set_int (value, eek_element_get_group (element));
break;
case PROP_LEVEL:
g_value_set_int (value, eek_element_get_level (element));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -96,10 +144,26 @@ eek_element_class_init (EekElementClass *klass)
GParamSpec *pspec;
/* signals */
klass->symbol_index_changed = eek_element_real_symbol_index_changed;
gobject_class->set_property = eek_element_set_property;
gobject_class->get_property = eek_element_get_property;
gobject_class->finalize = eek_element_finalize;
/**
* EekElement:name:
*
* The name of #EekElement.
*/
pspec = g_param_spec_string ("name",
"Name",
"Name",
NULL,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_NAME,
pspec);
/**
* EekElement:bounds:
*
@ -113,12 +177,149 @@ eek_element_class_init (EekElementClass *klass)
g_object_class_install_property (gobject_class,
PROP_BOUNDS,
pspec);
/**
* EekElement:group:
*
* The group value of the symbol index of #EekElement.
*/
pspec = g_param_spec_int ("group",
"Group",
"Group value of the symbol index",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_GROUP,
pspec);
/**
* EekElement:level:
*
* The level value of the symbol index of #EekElement.
*/
pspec = g_param_spec_int ("level",
"Level",
"Level value of the symbol index",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_LEVEL,
pspec);
/**
* EekElement::symbol-index-changed:
* @element: an #EekElement
* @group: row index of the symbol matrix of keys on @element
* @level: column index of the symbol matrix of keys on @element
*
* The ::symbol-index-changed signal is emitted each time the
* global configuration of group/level index changes.
*/
signals[SYMBOL_INDEX_CHANGED] =
g_signal_new (I_("symbol-index-changed"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekElementClass, symbol_index_changed),
NULL,
NULL,
_eek_marshal_VOID__INT_INT,
G_TYPE_NONE,
2,
G_TYPE_INT,
G_TYPE_INT);
}
static void
eek_element_init (EekElement *self)
{
(void)self;
EekElementPrivate *priv = eek_element_get_instance_private (self);
priv->group = -1;
priv->level = -1;
}
/**
* eek_element_set_parent:
* @element: an #EekElement
* @parent: (allow-none): an #EekElement or %NULL
*
* Set the parent of @element to @parent.
*/
void
eek_element_set_parent (EekElement *element,
EekElement *parent)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (parent == NULL || EEK_IS_ELEMENT(parent));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->parent == parent)
return;
if (priv->parent != NULL) {
/* release self-reference acquired when setting parent */
g_object_unref (element);
}
if (parent != NULL) {
g_object_ref (element);
}
priv->parent = parent;
}
/**
* eek_element_get_parent:
* @element: an #EekElement
*
* Get the parent of @element.
* Returns: an #EekElement if the parent is set
*/
EekElement *
eek_element_get_parent (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->parent;
}
/**
* eek_element_set_name:
* @element: an #EekElement
* @name: name of @element
*
* Set the name of @element to @name.
*/
void
eek_element_set_name (EekElement *element,
const gchar *name)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
g_free (priv->name);
priv->name = g_strdup (name);
}
/**
* eek_element_get_name:
* @element: an #EekElement
*
* Get the name of @element.
* Returns: the name of @element or NULL when the name is not set
*/
const gchar *
eek_element_get_name (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->name;
}
/**
@ -161,3 +362,211 @@ eek_element_get_bounds (EekElement *element,
memcpy (bounds, &priv->bounds, sizeof(EekBounds));
}
/**
* eek_element_get_absolute_position:
* @element: an #EekElement
* @x: pointer where the X coordinate of @element will be stored
* @y: pointer where the Y coordinate of @element will be stored
*
* Compute the absolute position of @element.
*/
void
eek_element_get_absolute_position (EekElement *element,
gdouble *x,
gdouble *y)
{
EekBounds bounds;
gdouble ax = 0.0, ay = 0.0;
do {
eek_element_get_bounds (element, &bounds);
ax += bounds.x;
ay += bounds.y;
} while ((element = eek_element_get_parent (element)) != NULL);
*x = ax;
*y = ay;
}
/**
* eek_element_set_position:
* @element: an #EekElement
* @x: X coordinate of top left corner
* @y: Y coordinate of top left corner
*
* Set the relative position of @element.
*/
void
eek_element_set_position (EekElement *element,
gdouble x,
gdouble y)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.x = x;
bounds.y = y;
eek_element_set_bounds (element, &bounds);
}
/**
* eek_element_set_size:
* @element: an #EekElement
* @width: width of @element
* @height: height of @element
*
* Set the size of @element.
*/
void
eek_element_set_size (EekElement *element,
gdouble width,
gdouble height)
{
EekBounds bounds;
eek_element_get_bounds (element, &bounds);
bounds.width = width;
bounds.height = height;
eek_element_set_bounds (element, &bounds);
}
/**
* eek_element_set_symbol_index:
* @element: an #EekElement
* @group: row index of the symbol matrix
* @level: column index of the symbol matrix
*
* Set the default index of the symbol matrices of @element. The
* setting affects the child, if child does not have the index set, as
* well as this element. To unset, pass -1 as group/level.
*/
void
eek_element_set_symbol_index (EekElement *element,
gint group,
gint level)
{
gboolean emit_signal;
g_return_if_fail (EEK_IS_ELEMENT(element));
emit_signal = group != eek_element_get_group (element) ||
level != eek_element_get_level (element);
eek_element_set_group (element, group);
eek_element_set_level (element, level);
if (emit_signal)
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0, group, level);
}
/**
* eek_element_get_symbol_index:
* @element: an #EekElement
* @group: a pointer where the group value of the symbol index will be stored
* @level: a pointer where the level value of the symbol index will be stored
*
* Get the default index of the symbol matrices of @element.
* If the index is not set, -1 will be returned.
*/
void
eek_element_get_symbol_index (EekElement *element,
gint *group,
gint *level)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (group != NULL || level != NULL);
if (group != NULL)
*group = eek_element_get_group (element);
if (level != NULL)
*level = eek_element_get_level (element);
}
/**
* eek_element_set_group:
* @element: an #EekElement
* @group: group index of @element
*
* Set the group value of the default symbol index of @element. To
* unset, pass -1 as @group.
*
* See also: eek_element_set_symbol_index()
*/
void
eek_element_set_group (EekElement *element,
gint group)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->group != group) {
priv->group = group;
g_object_notify (G_OBJECT(element), "group");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
group, priv->level);
}
}
/**
* eek_element_set_level:
* @element: an #EekElement
* @level: level index of @element
*
* Set the level value of the default symbol index of @element. To
* unset, pass -1 as @level.
*
* See also: eek_element_set_symbol_index()
*/
void
eek_element_set_level (EekElement *element,
gint level)
{
g_return_if_fail (EEK_IS_ELEMENT(element));
EekElementPrivate *priv = eek_element_get_instance_private (element);
if (priv->level != level) {
priv->level = level;
g_object_notify (G_OBJECT(element), "level");
g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
priv->group, level);
}
}
/**
* eek_element_get_group:
* @element: an #EekElement
*
* Return the group value of the default symbol index of @element.
* If the value is not set, -1 will be returned.
*
* See also: eek_element_get_symbol_index()
*/
gint
eek_element_get_group (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->group;
}
/**
* eek_element_get_level:
* @element: an #EekElement
*
* Return the level value of the default symbol index of @element.
* If the value is not set, -1 will be returned.
*
* See also: eek_element_get_symbol_index()
*/
gint
eek_element_get_level (EekElement *element)
{
g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
EekElementPrivate *priv = eek_element_get_instance_private (element);
return priv->level;
}

View File

@ -36,10 +36,18 @@ struct _EekElementClass
{
/*< private >*/
GObjectClass parent_class;
/* signals */
void (* symbol_index_changed) (EekElement *self,
gint group,
gint level);
};
GType eek_element_get_type (void) G_GNUC_CONST;
void eek_element_set_parent (EekElement *element,
EekElement *parent);
EekElement *eek_element_get_parent (EekElement *element);
void eek_element_set_name (EekElement *element,
const gchar *name);
@ -51,5 +59,29 @@ void eek_element_set_bounds (EekElement *element,
void eek_element_get_bounds (EekElement *element,
EekBounds *bounds);
void eek_element_set_position (EekElement *element,
gdouble x,
gdouble y);
void eek_element_set_size (EekElement *element,
gdouble width,
gdouble height);
void eek_element_get_absolute_position (EekElement *element,
gdouble *x,
gdouble *y);
void eek_element_set_symbol_index (EekElement *element,
gint group,
gint level);
void eek_element_get_symbol_index (EekElement *element,
gint *group,
gint *level);
void eek_element_set_group (EekElement *element,
gint group);
void eek_element_set_level (EekElement *element,
gint level);
gint eek_element_get_group (EekElement *element);
gint eek_element_get_level (EekElement *element);
G_END_DECLS
#endif /* EEK_ELEMENT_H */

View File

@ -23,23 +23,26 @@
* @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-renderer.h"
#include "eek-keyboard.h"
#include "src/symbol.h"
#include "eek-gtk-keyboard.h"
#include "eek-gtk-renderer.h"
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
enum {
PROP_0,
PROP_KEYBOARD,
PROP_LAST
};
@ -52,25 +55,37 @@ enum {
typedef struct _EekGtkKeyboardPrivate
{
EekRenderer *renderer;
LevelKeyboard *keyboard;
GtkCssProvider *css_provider;
GtkStyleContext *scontext;
EekKeyboard *keyboard;
gulong key_locked_handler;
gulong key_unlocked_handler;
gulong symbol_index_changed_handler;
EekTheme *theme;
GdkEventSequence *sequence; // unowned reference
} EekGtkKeyboardPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
static void on_button_pressed (struct squeek_button *button, struct squeek_view *view,
static void on_key_pressed (EekKey *key,
EekGtkKeyboard *self);
static void on_button_released (struct squeek_button *button,
struct squeek_view *view,
static void on_key_released (EekKey *key,
EekGtkKeyboard *self);
static void render_pressed_button (GtkWidget *widget, struct button_place *place);
static void render_locked_button (GtkWidget *widget,
struct button_place *place);
static void render_released_button (GtkWidget *widget,
struct squeek_button *button);
static void on_key_locked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_key_unlocked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data);
static void on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data);
static void render_pressed_key (GtkWidget *widget,
EekKey *key);
static void render_locked_key (GtkWidget *widget,
EekKey *key);
static void render_released_key (GtkWidget *widget,
EekKey *key);
static void
eek_gtk_keyboard_real_realize (GtkWidget *self)
@ -93,45 +108,38 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
EekGtkKeyboardPrivate *priv =
eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
GtkAllocation allocation;
GList *list, *head;
gtk_widget_get_allocation (self, &allocation);
if (!priv->renderer) {
PangoContext *pcontext = gtk_widget_get_pango_context (self);
PangoContext *pcontext;
priv->renderer = eek_renderer_new (priv->keyboard, pcontext, priv->scontext);
pcontext = gtk_widget_get_pango_context (self);
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);
struct squeek_view *view = priv->keyboard->views[priv->keyboard->level];
/* redraw pressed key */
const GList *list = priv->keyboard->pressed_buttons;
for (const GList *head = list; head; head = g_list_next (head)) {
struct button_place place = squeek_view_find_key(
view, squeek_button_get_key(head->data)
);
if (place.button)
render_pressed_button (self, &place);
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_pressed_key (self, head->data);
}
g_list_free (list);
/* redraw locked key */
list = priv->keyboard->locked_buttons;
for (const GList *head = list; head; head = g_list_next (head)) {
struct button_place place = squeek_view_find_key(
view, squeek_button_get_key(
((EekModifierKey *)head->data)->button
)
);
if (place.button)
render_locked_button (self, &place);
list = eek_keyboard_get_locked_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
render_locked_key (self, ((EekModifierKey *)head->data)->key);
}
g_list_free (list);
return FALSE;
}
@ -153,63 +161,50 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self,
}
static void depress(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time)
{
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
struct squeek_view *view = level_keyboard_current(priv->keyboard);
struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
if (button) {
eek_keyboard_press_button(priv->keyboard, button, time);
on_button_pressed(button, view, 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);
}
}
static void drag(EekGtkKeyboard *self,
gdouble x, gdouble y, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
struct squeek_view *view = level_keyboard_current(priv->keyboard);
struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
GList *list, *head;
EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
list = g_list_copy(priv->keyboard->pressed_buttons);
if (button) {
if (key) {
GList *list, *head;
gboolean found = FALSE;
list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (head = list; head; head = g_list_next (head)) {
if (head->data == button) {
if (head->data == key)
found = TRUE;
} else {
eek_keyboard_release_button(priv->keyboard, head->data, time);
on_button_released(button, view, self);
else {
eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time);
on_key_released(key, self);
}
}
g_list_free (list);
if (!found) {
eek_keyboard_press_button(priv->keyboard, button, time);
on_button_pressed(button, view, self);
eek_keyboard_press_key(priv->keyboard, key, time);
on_key_pressed(key, self);
}
} else {
for (head = list; head; head = g_list_next (head)) {
eek_keyboard_release_button(priv->keyboard, head->data, time);
on_button_released(head->data, view, self);
}
g_list_free (list);
}
}
static void release(EekGtkKeyboard *self, guint32 time) {
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
struct squeek_view *view = level_keyboard_current(priv->keyboard);
GList *list = g_list_copy(priv->keyboard->pressed_buttons);
GList *list = eek_keyboard_get_pressed_keys (priv->keyboard);
for (GList *head = list; head; head = g_list_next (head)) {
struct squeek_button *button = head->data;
eek_keyboard_release_button(priv->keyboard, button, time);
on_button_released(button, view, self);
EekKey *key = EEK_KEY(head->data);
eek_keyboard_release_key(priv->keyboard, key, time);
on_key_released(key, self);
}
g_list_free (list);
}
@ -292,7 +287,7 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
elements, so that the default handler of
EekKeyboard::key-released signal can remove elements from its
internal copy */
list = g_list_copy(priv->keyboard->pressed_buttons);
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 released");
g_signal_emit_by_name (head->data, "released");
@ -312,15 +307,15 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget *widget,
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
struct squeek_view *view = level_keyboard_current(priv->keyboard);
struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer,
view,
(gdouble)x,
(gdouble)y);
if (button) {
//struct squeek_symbol *symbol = eek_key_get_symbol_at_index(key, 0, priv->keyboard->level);
const gchar *text = NULL; // FIXME
EekKey *key;
key = eek_renderer_find_key_by_position (priv->renderer,
(gdouble)x,
(gdouble)y);
if (key) {
EekSymbol *symbol = eek_key_get_symbol (key);
const gchar *text = eek_symbol_get_tooltip (symbol);
if (text) {
gtk_tooltip_set_text (tooltip, text);
return TRUE;
@ -329,13 +324,37 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget *widget,
return FALSE;
}
static void
eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
EekKeyboard *keyboard)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
priv->keyboard = g_object_ref (keyboard);
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
eek_gtk_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekKeyboard *keyboard;
switch (prop_id) {
case PROP_KEYBOARD:
keyboard = g_value_get_object (value);
eek_gtk_keyboard_set_keyboard (EEK_GTK_KEYBOARD(object), keyboard);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -354,18 +373,37 @@ 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;
list = g_list_copy(priv->keyboard->pressed_buttons);
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");
g_signal_emit_by_name (head->data, "released", level_keyboard_current(priv->keyboard));
g_signal_emit_by_name (head->data, "released", priv->keyboard);
}
g_list_free (list);
g_object_unref (priv->keyboard);
priv->keyboard = NULL;
}
if (priv->theme) {
g_object_unref (priv->theme);
priv->theme = NULL;
}
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
}
@ -374,6 +412,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
widget_class->realize = eek_gtk_keyboard_real_realize;
widget_class->unmap = eek_gtk_keyboard_real_unmap;
@ -391,25 +430,21 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
gobject_class->set_property = eek_gtk_keyboard_set_property;
gobject_class->dispose = eek_gtk_keyboard_dispose;
pspec = g_param_spec_object ("keyboard",
"Keyboard",
"Keyboard",
EEK_TYPE_KEYBOARD,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_KEYBOARD,
pspec);
}
static void
eek_gtk_keyboard_init (EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* Create a default CSS provider and load a style sheet */
priv->css_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (priv->css_provider,
"/sm/puri/squeekboard/style.css");
/* Apply the style to the widget */
priv->scontext = gtk_widget_get_style_context (GTK_WIDGET(self));
gtk_style_context_add_class (priv->scontext, "keyboard");
gtk_style_context_add_provider (priv->scontext,
GTK_STYLE_PROVIDER(priv->css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_style_context_set_state (priv->scontext, GTK_STATE_FLAG_NORMAL);
/* void */
}
/**
@ -420,76 +455,126 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self)
* Returns: a #GtkWidget
*/
GtkWidget *
eek_gtk_keyboard_new (LevelKeyboard *keyboard)
eek_gtk_keyboard_new (EekKeyboard *keyboard)
{
EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL));
EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret);
priv->keyboard = keyboard;
return GTK_WIDGET(ret);
return g_object_new (EEK_TYPE_GTK_KEYBOARD, "keyboard", keyboard, NULL);
}
static void
render_pressed_button (GtkWidget *widget,
struct button_place *place)
magnify_bounds (GtkWidget *self,
EekBounds *bounds,
EekBounds *large_bounds,
gdouble scale)
{
GtkAllocation allocation;
gdouble x, y;
g_assert (scale >= 1.0);
gtk_widget_get_allocation (self, &allocation);
large_bounds->width = bounds->width * scale;
large_bounds->height = bounds->height * scale;
x = bounds->x - (large_bounds->width - bounds->width) / 2;
y = bounds->y - large_bounds->height;
large_bounds->x = CLAMP(x, 0, allocation.width - large_bounds->width);
large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
}
static void
render_pressed_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (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);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
/*
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_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);
*/
gdk_window_end_draw_frame (window, context);
cairo_restore (cr);
cairo_region_destroy (region);
gdk_window_end_draw_frame(window, context);
cairo_region_destroy(region);
}
static void
render_locked_button (GtkWidget *widget, struct button_place *place)
render_locked_key (GtkWidget *widget,
EekKey *key)
{
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget);
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
EekBounds 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);
eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
cairo_translate (cr, bounds.x, bounds.y);
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
gdk_window_end_draw_frame (window, context);
cairo_region_destroy (region);
cairo_region_destroy(region);
}
static void
render_released_button (GtkWidget *widget,
struct squeek_button *button)
render_released_key (GtkWidget *widget,
EekKey *key)
{
(void)button;
EekGtkKeyboard *self = EEK_GTK_KEYBOARD (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);
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
on_button_pressed (struct squeek_button *button,
struct squeek_view *view,
on_key_pressed (EekKey *key,
EekGtkKeyboard *self)
{
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
@ -498,15 +583,7 @@ on_button_pressed (struct squeek_button *button,
if (!priv->renderer)
return;
struct button_place place = {
.button = button,
.row = squeek_view_get_row(view, button),
};
if (!place.row) {
return;
}
render_pressed_button (GTK_WIDGET(self), &place);
gtk_widget_queue_draw (GTK_WIDGET(self));
render_pressed_key (GTK_WIDGET(self), key);
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
@ -518,19 +595,16 @@ on_button_pressed (struct squeek_button *button,
}
static void
on_button_released (struct squeek_button *button,
struct squeek_view *view,
on_key_released (EekKey *key,
EekGtkKeyboard *self)
{
(void)view;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_button (GTK_WIDGET(self), button);
gtk_widget_queue_draw (GTK_WIDGET(self));
render_released_key (GTK_WIDGET(self), key);
#if HAVE_LIBCANBERRA
ca_gtk_play_for_widget (widget, 0,
@ -540,3 +614,55 @@ on_button_released (struct squeek_button *button,
NULL);
#endif
}
static void
on_key_locked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_locked_key (widget, key);
}
static void
on_key_unlocked (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
GtkWidget *widget = user_data;
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
/* renderer may have not been set yet if the widget is a popup */
if (!priv->renderer)
return;
render_released_key (widget, key);
}
static void
on_symbol_index_changed (EekKeyboard *keyboard,
gint group,
gint level,
gpointer user_data)
{
GtkWidget *widget = user_data;
gtk_widget_queue_draw (widget);
}
void
eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme)
{
g_return_if_fail (EEK_IS_GTK_KEYBOARD(keyboard));
g_return_if_fail (EEK_IS_THEME(theme));
EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard);
priv->theme = g_object_ref (theme);
}

View File

@ -45,7 +45,9 @@ struct _EekGtkKeyboardClass
};
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
GtkWidget *eek_gtk_keyboard_new (LevelKeyboard *keyboard);
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
void eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_GTK_KEYBOARD_H */

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 */

613
eek/eek-key.c Normal file
View File

@ -0,0 +1,613 @@
/*
* 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-key
* @short_description: Base class of a key
*
* The #EekKeyClass class represents a key.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include "eek-key.h"
#include "eek-section.h"
#include "eek-keyboard.h"
#include "eek-symbol.h"
enum {
PROP_0,
PROP_KEYCODE,
PROP_SYMBOL_MATRIX,
PROP_COLUMN,
PROP_ROW,
PROP_OREF,
PROP_LAST
};
enum {
LOCKED,
UNLOCKED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
typedef struct _EekKeyPrivate
{
guint keycode;
EekSymbolMatrix *symbol_matrix;
gint column;
gint row;
gulong oref; // UI outline reference
gboolean is_pressed;
gboolean is_locked;
} EekKeyPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekKey, eek_key, EEK_TYPE_ELEMENT)
static void
eek_key_real_locked (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->is_locked = TRUE;
#if DEBUG
g_debug ("locked %X", eek_key_get_keycode (self));
#endif
}
static void
eek_key_real_unlocked (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->is_locked = FALSE;
#if DEBUG
g_debug ("unlocked %X", eek_key_get_keycode (self));
#endif
}
static void
eek_key_finalize (GObject *object)
{
EekKey *self = EEK_KEY (object);
EekKeyPrivate *priv = eek_key_get_instance_private (self);
eek_symbol_matrix_free (priv->symbol_matrix);
G_OBJECT_CLASS (eek_key_parent_class)->finalize (object);
}
static void
eek_key_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekSymbolMatrix *matrix;
gint column, row;
switch (prop_id) {
case PROP_KEYCODE:
eek_key_set_keycode (EEK_KEY(object), g_value_get_uint (value));
break;
case PROP_SYMBOL_MATRIX:
matrix = g_value_get_boxed (value);
eek_key_set_symbol_matrix (EEK_KEY(object), matrix);
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), g_value_get_int (value), row);
break;
case PROP_ROW:
eek_key_get_index (EEK_KEY(object), &column, &row);
eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
break;
case PROP_OREF:
eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_key_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
gint column, row;
switch (prop_id) {
case PROP_KEYCODE:
g_value_set_uint (value, eek_key_get_keycode (EEK_KEY(object)));
break;
case PROP_SYMBOL_MATRIX:
g_value_set_boxed (value,
eek_key_get_symbol_matrix (EEK_KEY(object)));
break;
case PROP_COLUMN:
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, column);
break;
case PROP_ROW:
eek_key_get_index (EEK_KEY(object), &column, &row);
g_value_set_int (value, row);
break;
case PROP_OREF:
g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_key_class_init (EekKeyClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = eek_key_set_property;
gobject_class->get_property = eek_key_get_property;
gobject_class->finalize = eek_key_finalize;
/* signals */
klass->locked = eek_key_real_locked;
klass->unlocked = eek_key_real_unlocked;
/**
* EekKey:keycode:
*
* The keycode of #EekKey.
*/
pspec = g_param_spec_uint ("keycode",
"Keycode",
"Keycode of the key",
0, G_MAXUINT, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_KEYCODE, pspec);
/**
* EekKey:symbol-matrix:
*
* The symbol matrix of #EekKey.
*/
pspec = g_param_spec_boxed ("symbol-matrix",
"Symbol matrix",
"Symbol matrix of the key",
EEK_TYPE_SYMBOL_MATRIX,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_SYMBOL_MATRIX, pspec);
/**
* EekKey:column:
*
* The column index of #EekKey in the parent #EekSection.
*/
pspec = g_param_spec_int ("column",
"Column",
"Column index of the key in section",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_COLUMN, pspec);
/**
* EekKey:row:
*
* The row index of #EekKey in the parent #EekSection.
*/
pspec = g_param_spec_int ("row",
"Row",
"Row index of the key in section",
-1, G_MAXINT, -1,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ROW, pspec);
/**
* EekKey:oref:
*
* The outline id of #EekKey.
*/
pspec = g_param_spec_ulong ("oref",
"Oref",
"Outline id of the key",
0, G_MAXULONG, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_OREF, pspec);
/**
* EekKey::locked:
* @key: an #EekKey
*
* The ::locked signal is emitted each time @key is shifted to
* the locked state. The class handler runs before signal
* handlers to allow signal handlers to read the status of @key
* with eek_key_is_locked().
*/
signals[LOCKED] =
g_signal_new (I_("locked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(EekKeyClass, locked),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* EekKey::unlocked:
* @key: an #EekKey
*
* The ::unlocked signal is emitted each time @key is shifted to
* the unlocked state.
*/
signals[UNLOCKED] =
g_signal_new (I_("unlocked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyClass, unlocked),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
eek_key_init (EekKey *self)
{
EekKeyPrivate *priv = eek_key_get_instance_private (self);
priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
}
/**
* eek_key_set_keycode:
* @key: an #EekKey
* @keycode: keycode
*
* Set the keycode of @key to @keycode. Since typically the keycode
* value is used to find a key in a keyboard by calling
* eek_keyboard_find_key_by_keycode, it is not necessarily the same as
* the X keycode but it should be unique in the keyboard @key belongs
* to.
*/
void
eek_key_set_keycode (EekKey *key,
guint keycode)
{
g_return_if_fail (EEK_IS_KEY (key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->keycode = keycode;
}
/**
* eek_key_get_keycode:
* @key: an #EekKey
*
* Get keycode of @key.
* Returns: keycode or %EEK_INVALID_KEYCODE on failure
*/
guint
eek_key_get_keycode (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), EEK_INVALID_KEYCODE);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->keycode;
}
/**
* eek_key_set_symbol_matrix:
* @key: an #EekKey
* @matrix: an #EekSymbolMatrix
*
* Set the symbol matrix of @key to @matrix.
*/
void
eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix)
{
g_return_if_fail (EEK_IS_KEY(key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
eek_symbol_matrix_free (priv->symbol_matrix);
priv->symbol_matrix = eek_symbol_matrix_copy (matrix);
}
/**
* eek_key_get_symbol_matrix:
* @key: an #EekKey
*
* Get the symbol matrix of @key.
* Returns: (transfer none): #EekSymbolMatrix or %NULL
*/
EekSymbolMatrix *
eek_key_get_symbol_matrix (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->symbol_matrix;
}
/**
* eek_key_get_symbol:
* @key: an #EekKey
*
* Get the current symbol of @key.
* Return value: (transfer none): the current #EekSymbol or %NULL on failure
*/
EekSymbol *
eek_key_get_symbol (EekKey *key)
{
return eek_key_get_symbol_with_fallback (key, 0, 0);
}
/**
* eek_key_get_symbol_with_fallback:
* @key: an #EekKey
* @fallback_group: fallback group index
* @fallback_level: fallback level index
*
* Get the current symbol of @key.
* Return value: (transfer none): the current #EekSymbol or %NULL on failure
*/
EekSymbol *
eek_key_get_symbol_with_fallback (EekKey *key,
gint fallback_group,
gint fallback_level)
{
gint group, level;
g_return_val_if_fail (EEK_IS_KEY (key), NULL);
g_return_val_if_fail (fallback_group >= 0, NULL);
g_return_val_if_fail (fallback_level >= 0, NULL);
eek_element_get_symbol_index (EEK_ELEMENT(key), &group, &level);
if (group < 0 || level < 0) {
EekElement *section;
section = eek_element_get_parent (EEK_ELEMENT(key));
g_return_val_if_fail (EEK_IS_SECTION (section), NULL);
if (group < 0)
group = eek_element_get_group (section);
if (level < 0)
level = eek_element_get_level (section);
if (group < 0 || level < 0) {
EekElement *keyboard;
keyboard = eek_element_get_parent (section);
g_return_val_if_fail (EEK_IS_KEYBOARD (keyboard), NULL);
if (group < 0)
group = eek_element_get_group (keyboard);
if (level < 0)
level = eek_element_get_level (keyboard);
}
}
return eek_key_get_symbol_at_index (key,
group,
level,
fallback_group,
fallback_level);
}
/**
* eek_key_get_symbol_at_index:
* @key: an #EekKey
* @group: group index of the symbol matrix
* @level: level index of the symbol matrix
* @fallback_group: fallback group index
* @fallback_level: fallback level index
*
* Get the symbol at (@group, @level) in the symbol matrix of @key.
* Return value: (transfer none): an #EekSymbol at (@group, @level), or %NULL
*/
EekSymbol *
eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level)
{
EekKeyPrivate *priv = eek_key_get_instance_private (key);
gint num_symbols;
g_return_val_if_fail (fallback_group >= 0, NULL);
g_return_val_if_fail (fallback_level >= 0, NULL);
if (group < 0)
group = fallback_group;
if (level < 0)
level = fallback_level;
if (!priv->symbol_matrix)
return NULL;
num_symbols = priv->symbol_matrix->num_groups *
priv->symbol_matrix->num_levels;
if (num_symbols == 0)
return NULL;
if (group >= priv->symbol_matrix->num_groups) {
if (fallback_group < 0)
return NULL;
group = fallback_group;
}
if (level >= priv->symbol_matrix->num_levels) {
if (fallback_level < 0)
return NULL;
level = fallback_level;
}
return priv->symbol_matrix->data[group * priv->symbol_matrix->num_levels +
level];
}
/**
* eek_key_set_index:
* @key: an #EekKey
* @column: column index of @key in #EekSection
* @row: row index of @key in #EekSection
*
* Set the location of @key in #EekSection with @column and @row.
*/
void
eek_key_set_index (EekKey *key,
gint column,
gint row)
{
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (0 <= column);
g_return_if_fail (0 <= row);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (priv->column != column) {
priv->column = column;
g_object_notify (G_OBJECT(key), "column");
}
if (priv->row != row) {
priv->row = row;
g_object_notify (G_OBJECT(key), "row");
}
}
/**
* eek_key_get_index:
* @key: an #EekKey
* @column: (allow-none): pointer where the column index of @key in #EekSection will be stored
* @row: (allow-none): pointer where the row index of @key in #EekSection will be stored
*
* Get the location of @key in #EekSection.
*/
void
eek_key_get_index (EekKey *key,
gint *column,
gint *row)
{
g_return_if_fail (EEK_IS_KEY(key));
g_return_if_fail (column != NULL || row != NULL);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (column != NULL)
*column = priv->column;
if (row != NULL)
*row = priv->row;
}
/**
* eek_key_set_oref:
* @key: an #EekKey
* @oref: outline id of @key
*
* Set the outline id of @key to @oref.
*/
void
eek_key_set_oref (EekKey *key,
guint oref)
{
g_return_if_fail (EEK_IS_KEY(key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
if (priv->oref != oref) {
priv->oref = oref;
g_object_notify (G_OBJECT(key), "oref");
}
}
/**
* eek_key_get_oref:
* @key: an #EekKey
*
* Get the outline id of @key.
* Returns: unsigned integer
*/
guint
eek_key_get_oref (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY (key), 0);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->oref;
}
/**
* eek_key_is_pressed:
* @key: an #EekKey
*
* Return %TRUE if key is marked as pressed.
*/
gboolean
eek_key_is_pressed (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->is_pressed;
}
/**
* eek_key_is_locked:
* @key: an #EekKey
*
* Return %TRUE if key is marked as locked.
*/
gboolean
eek_key_is_locked (EekKey *key)
{
g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
EekKeyPrivate *priv = eek_key_get_instance_private (key);
return priv->is_locked;
}
void eek_key_set_pressed(EekKey *key, gboolean value)
{
g_return_if_fail (EEK_IS_KEY(key));
EekKeyPrivate *priv = eek_key_get_instance_private (key);
priv->is_pressed = value;
}

93
eek/eek-key.h Normal file
View File

@ -0,0 +1,93 @@
/*
* 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.h> can be included directly."
#endif
#ifndef EEK_KEY_H
#define EEK_KEY_H 1
#include "eek-element.h"
#include "eek-symbol-matrix.h"
G_BEGIN_DECLS
#define EEK_TYPE_KEY (eek_key_get_type())
G_DECLARE_DERIVABLE_TYPE(EekKey, eek_key, EEK, KEY, EekElement)
/**
* EekKeyClass:
* @pressed: class handler for #EekKey::pressed signal
* @released: class handler for #EekKey::released signal
* @locked: class handler for #EekKey::locked signal
* @unlocked: class handler for #EekKey::unlocked signal
* @cancelled: class handler for #EekKey::cancelled signal
* @is_pressed: virtual function for getting whether the key is pressed
* @is_locked: virtual function for getting whether the key is locked
*/
struct _EekKeyClass
{
/*< private >*/
EekElementClass parent_class;
/*< public >*/
/* signals */
void (* locked) (EekKey *key);
void (* unlocked) (EekKey *key);
};
GType eek_key_get_type (void) G_GNUC_CONST;
void eek_key_set_keycode (EekKey *key,
guint keycode);
guint eek_key_get_keycode (EekKey *key);
void eek_key_set_symbol_matrix (EekKey *key,
EekSymbolMatrix *matrix);
EekSymbolMatrix *eek_key_get_symbol_matrix (EekKey *key);
EekSymbol *eek_key_get_symbol (EekKey *key);
EekSymbol *eek_key_get_symbol_with_fallback
(EekKey *key,
gint fallback_group,
gint fallback_level);
EekSymbol *eek_key_get_symbol_at_index (EekKey *key,
gint group,
gint level,
gint fallback_group,
gint fallback_level);
void eek_key_set_index (EekKey *key,
gint column,
gint row);
void eek_key_get_index (EekKey *key,
gint *column,
gint *row);
void eek_key_set_oref (EekKey *key,
guint oref);
guint eek_key_get_oref (EekKey *key);
gboolean eek_key_is_pressed (EekKey *key);
gboolean eek_key_is_locked (EekKey *key);
void eek_key_set_pressed (EekKey *key,
gboolean value);
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

@ -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,16 +27,56 @@
* of one or more sections of the #EekSectionClass class.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include <glib/gprintf.h>
#include "eek-enumtypes.h"
#include "eekboard/key-emitter.h"
#include "keymap.h"
#include "src/keyboard.h"
#include "src/symbol.h"
#endif /* HAVE_CONFIG_H */
#include "eek-keyboard.h"
#include "eek-marshalers.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
#include "eek-enumtypes.h"
#include "eekboard/key-emitter.h"
enum {
PROP_0,
PROP_LAYOUT,
PROP_MODIFIER_BEHAVIOR,
PROP_LAST
};
enum {
KEY_RELEASED,
KEY_LOCKED,
KEY_UNLOCKED,
LAST_SIGNAL
};
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))
struct _EekKeyboardPrivate
{
EekLayout *layout;
EekModifierBehavior modifier_behavior;
EekModifierType modifiers;
GList *pressed_keys;
GList *locked_keys;
GArray *outline_array;
GHashTable *keycodes;
/* modifiers dynamically assigned at run time */
EekModifierType num_lock_mask;
EekModifierType alt_gr_mask;
};
G_DEFINE_BOXED_TYPE(EekModifierKey, eek_modifier_key,
eek_modifier_key_copy, eek_modifier_key_free);
EekModifierKey *
eek_modifier_key_copy (EekModifierKey *modkey)
@ -47,162 +87,543 @@ eek_modifier_key_copy (EekModifierKey *modkey)
void
eek_modifier_key_free (EekModifierKey *modkey)
{
g_object_unref (modkey->key);
g_slice_free (EekModifierKey, modkey);
}
/// Updates the state of locked keys based on the key that was activated
/// FIXME: make independent of what the key are named,
/// and instead refer to the contained symbols
static guint
set_key_states (LevelKeyboard *keyboard,
struct squeek_button *button,
guint new_level)
{
struct squeek_key *key = squeek_button_get_key(button);
// Keys locking rules hardcoded for the time being...
const gchar *name = squeek_symbol_get_name(squeek_key_get_symbol(key));
// Lock the shift whenever it's pressed on the baselevel
// TODO: need to lock shift on the destination level
if (g_strcmp0(name, "Shift_L") == 0 && keyboard->level == 0) {
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
modifier_key->modifiers = 0;
modifier_key->button = button;
keyboard->locked_buttons =
g_list_prepend (keyboard->locked_buttons, modifier_key);
squeek_key_set_locked(key, true);
}
if (keyboard->level == 1) {
// Only shift is locked in this state, unlock on any key press
for (GList *head = keyboard->locked_buttons; head; ) {
EekModifierKey *modifier_key = head->data;
GList *next = g_list_next (head);
keyboard->locked_buttons =
g_list_remove_link (keyboard->locked_buttons, head);
squeek_key_set_locked(squeek_button_get_key(modifier_key->button), false);
g_list_free1 (head);
head = next;
}
return 0;
}
return new_level;
}
// FIXME: unhardcode, parse some user information as to which key triggers which view (level)
static void
set_level_from_press (LevelKeyboard *keyboard, struct squeek_button *button)
on_key_locked (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
/* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
guint level = keyboard->level;
/* Handle non-emitting keys */
if (button) {
const gchar *name = squeek_symbol_get_name(squeek_key_get_symbol(squeek_button_get_key(button)));
if (g_strcmp0(name, "show_numbers") == 0) {
level = 2;
} else if (g_strcmp0(name, "show_letters") == 0) {
level = 0;
} else if (g_strcmp0(name, "show_symbols") == 0) {
level = 3;
} else if (g_strcmp0(name, "Shift_L") == 0) {
level ^= 1;
g_signal_emit (keyboard, signals[KEY_LOCKED], 0, key);
}
static void
on_key_unlocked (EekSection *section,
EekKey *key,
EekKeyboard *keyboard)
{
g_signal_emit (keyboard, signals[KEY_UNLOCKED], 0, key);
}
static void
on_symbol_index_changed (EekSection *section,
gint group,
gint level,
EekKeyboard *keyboard)
{
g_signal_emit_by_name (keyboard, "symbol-index-changed", group, level);
}
static void
section_child_added_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
guint keycode = eek_key_get_keycode (EEK_KEY(element));
g_hash_table_insert (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode),
element);
}
static void
section_child_removed_cb (EekContainer *container,
EekElement *element,
EekKeyboard *keyboard)
{
guint keycode = eek_key_get_keycode (EEK_KEY(element));
g_hash_table_remove (keyboard->priv->keycodes,
GUINT_TO_POINTER(keycode));
}
static EekSection *
eek_keyboard_real_create_section (EekKeyboard *self)
{
EekSection *section;
section = g_object_new (EEK_TYPE_SECTION, NULL);
g_return_val_if_fail (section, NULL);
g_signal_connect (G_OBJECT(section), "child-added",
G_CALLBACK(section_child_added_cb), self);
g_signal_connect (G_OBJECT(section), "child-removed",
G_CALLBACK(section_child_removed_cb), self);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(section));
return section;
}
static void
eek_keyboard_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
switch (prop_id) {
case PROP_LAYOUT:
priv->layout = g_value_get_object (value);
if (priv->layout)
g_object_ref (priv->layout);
break;
case PROP_MODIFIER_BEHAVIOR:
eek_keyboard_set_modifier_behavior (EEK_KEYBOARD(object),
g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_keyboard_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
switch (prop_id) {
case PROP_LAYOUT:
g_value_set_object (value, priv->layout);
break;
case PROP_MODIFIER_BEHAVIOR:
g_value_set_enum (value,
eek_keyboard_get_modifier_behavior (EEK_KEYBOARD(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_level_from_modifiers (EekKeyboard *self)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
gint level = 0;
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);
}
static void
set_modifiers_with_key (EekKeyboard *self,
EekKey *key,
EekModifierType modifiers)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
EekModifierType enabled = (priv->modifiers ^ modifiers) & modifiers;
EekModifierType disabled = (priv->modifiers ^ modifiers) & priv->modifiers;
if (enabled != 0) {
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
modifier_key->modifiers = enabled;
modifier_key->key = g_object_ref (key);
priv->locked_keys =
g_list_prepend (priv->locked_keys, modifier_key);
g_signal_emit_by_name (modifier_key->key, "locked");
}
} else {
if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
GList *head;
for (head = priv->locked_keys; head; ) {
EekModifierKey *modifier_key = head->data;
if (modifier_key->modifiers & disabled) {
GList *next = g_list_next (head);
priv->locked_keys =
g_list_remove_link (priv->locked_keys, head);
g_signal_emit_by_name (modifier_key->key, "unlocked");
g_list_free1 (head);
head = next;
} else
head = g_list_next (head);
}
}
}
keyboard->level = set_key_states(keyboard, button, level);
eek_layout_update_layout(keyboard);
priv->modifiers = modifiers;
}
void eek_keyboard_press_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp) {
struct squeek_key *key = squeek_button_get_key(button);
squeek_key_set_pressed(key, TRUE);
keyboard->pressed_buttons = g_list_prepend (keyboard->pressed_buttons, button);
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp) {
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
struct squeek_symbol *symbol = squeek_key_get_symbol(key);
eek_key_set_pressed(key, TRUE);
priv->pressed_keys = g_list_prepend (priv->pressed_keys, key);
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
// Only take action about setting level *after* the key has taken effect, i.e. on release
//set_level_from_press (keyboard, key);
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);
}
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = squeek_key_get_keycode (key);
guint keycode = eek_key_get_keycode (key);
EekModifierType modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, TRUE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, TRUE, timestamp);
}
void eek_keyboard_release_button(LevelKeyboard *keyboard,
struct squeek_button *button,
void eek_keyboard_release_key( EekKeyboard *keyboard,
EekKey *key,
guint32 timestamp) {
for (GList *head = keyboard->pressed_buttons; head; head = g_list_next (head)) {
if (head->data == button) {
keyboard->pressed_buttons = g_list_remove_link (keyboard->pressed_buttons, head);
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
for (GList *head = priv->pressed_keys; head; head = g_list_next (head)) {
if (head->data == key) {
priv->pressed_keys = g_list_remove_link (priv->pressed_keys, head);
g_list_free1 (head);
break;
}
}
struct squeek_symbol *symbol = squeek_button_get_symbol(button);
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
set_level_from_press (keyboard, button);
EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
if (!symbol)
return;
modifier = eek_symbol_get_modifier_mask (symbol);
switch (priv->modifier_behavior) {
case EEK_MODIFIER_BEHAVIOR_NONE:
set_modifiers_with_key (keyboard, key, priv->modifiers & ~modifier);
break;
case EEK_MODIFIER_BEHAVIOR_LOCK:
priv->modifiers ^= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LATCH:
if (modifier)
set_modifiers_with_key (keyboard, key, priv->modifiers ^ modifier);
else
set_modifiers_with_key (keyboard, key,
(priv->modifiers ^ modifier) & modifier);
break;
}
set_level_from_modifiers (keyboard);
// "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
guint keycode = squeek_key_get_keycode (squeek_button_get_key(button));
guint keycode = eek_key_get_keycode (key);
guint modifiers = eek_keyboard_get_modifiers (keyboard);
emit_key_activated(keyboard->manager, keyboard, keycode, FALSE, timestamp);
emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, FALSE, timestamp);
}
void level_keyboard_deinit(LevelKeyboard *self) {
g_hash_table_destroy (self->names);
for (guint i = 0; i < self->outline_array->len; i++) {
EekOutline *outline = &g_array_index (self->outline_array,
static void
eek_keyboard_dispose (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
if (priv->layout) {
g_object_unref (priv->layout);
priv->layout = NULL;
}
G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object);
}
static void
eek_keyboard_finalize (GObject *object)
{
EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
guint i;
g_list_free (priv->pressed_keys);
g_list_free_full (priv->locked_keys,
(GDestroyNotify) eek_modifier_key_free);
g_hash_table_destroy (priv->keycodes);
for (i = 0; i < priv->outline_array->len; i++) {
EekOutline *outline = &g_array_index (priv->outline_array,
EekOutline,
i);
g_slice_free1 (sizeof (EekPoint) * outline->num_points,
outline->points);
}
g_array_free (self->outline_array, TRUE);
for (guint i = 0; i < 4; i++) {
// free self->view[i];
}
g_array_free (priv->outline_array, TRUE);
G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
}
void level_keyboard_free(LevelKeyboard *self) {
level_keyboard_deinit(self);
g_free(self);
static void
eek_keyboard_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "key-locked",
G_CALLBACK(on_key_locked), self);
g_signal_connect (element, "key-unlocked",
G_CALLBACK(on_key_unlocked), self);
g_signal_connect (element, "symbol-index-changed",
G_CALLBACK(on_symbol_index_changed), self);
}
void level_keyboard_init(LevelKeyboard *self) {
self->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
static void
eek_keyboard_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_key_locked, self);
g_signal_handlers_disconnect_by_func (element, on_key_unlocked, self);
}
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_view *views[4], GHashTable *name_button_hash) {
LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
level_keyboard_init(keyboard);
for (uint i = 0; i < 4; i++) {
keyboard->views[i] = views[i];
}
keyboard->manager = manager;
keyboard->names = name_button_hash;
return keyboard;
static void
eek_keyboard_class_init (EekKeyboardClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (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 */
container_class->child_added = eek_keyboard_real_child_added;
container_class->child_removed = eek_keyboard_real_child_removed;
gobject_class->get_property = eek_keyboard_get_property;
gobject_class->set_property = eek_keyboard_set_property;
gobject_class->dispose = eek_keyboard_dispose;
gobject_class->finalize = eek_keyboard_finalize;
/**
* EekKeyboard:layout:
*
* The layout used to create this #EekKeyboard.
*/
pspec = g_param_spec_object ("layout",
"Layout",
"Layout used to create the keyboard",
EEK_TYPE_LAYOUT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_LAYOUT,
pspec);
/**
* EekKeyboard:modifier-behavior:
*
* The modifier handling mode of #EekKeyboard.
*/
pspec = g_param_spec_enum ("modifier-behavior",
"Modifier behavior",
"Modifier handling mode of the keyboard",
EEK_TYPE_MODIFIER_BEHAVIOR,
EEK_MODIFIER_BEHAVIOR_NONE,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_MODIFIER_BEHAVIOR,
pspec);
/**
* EekKeyboard::key-locked:
* @keyboard: an #EekKeyboard
* @key: an #EekKey
*
* The ::key-locked signal is emitted each time a key in @keyboard
* is shifted to the locked state.
*/
signals[KEY_LOCKED] =
g_signal_new (I_("key-locked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyboardClass, key_locked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
/**
* EekKeyboard::key-unlocked:
* @keyboard: an #EekKeyboard
* @key: an #EekKey
*
* The ::key-unlocked signal is emitted each time a key in @keyboard
* is shifted to the unlocked state.
*/
signals[KEY_UNLOCKED] =
g_signal_new (I_("key-unlocked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekKeyboardClass, key_unlocked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
}
static void
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->keycodes = g_hash_table_new (g_direct_hash, g_direct_equal);
eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
}
/**
* eek_keyboard_find_key_by_name:
* eek_keyboard_create_section:
* @keyboard: an #EekKeyboard
* @name: a key name
*
* Find an #EekKey whose name is @name.
* Return value: (transfer none): #EekKey whose name is @name
* Create an #EekSection instance and append it to @keyboard. This
* function is rarely called by application but called by #EekLayout
* implementation.
*/
struct squeek_button*
eek_keyboard_find_button_by_name (LevelKeyboard *keyboard,
const gchar *name)
EekSection *
eek_keyboard_create_section (EekKeyboard *keyboard)
{
return g_hash_table_lookup (keyboard->names, name);
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return EEK_KEYBOARD_GET_CLASS(keyboard)->create_section (keyboard);
}
/**
* eek_keyboard_find_key_by_keycode:
* @keyboard: an #EekKeyboard
* @keycode: a keycode
*
* Find an #EekKey whose keycode is @keycode.
* Return value: (transfer none): #EekKey whose keycode is @keycode
*/
EekKey *
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->keycodes,
GUINT_TO_POINTER(keycode));
}
/**
* eek_keyboard_get_layout:
* @keyboard: an #EekKeyboard
*
* Get the layout used to create @keyboard.
* Returns: an #EekLayout
*/
EekLayout *
eek_keyboard_get_layout (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return keyboard->priv->layout;
}
/**
* eek_keyboard_get_size:
* @keyboard: an #EekKeyboard
* @width: width of @keyboard
* @height: height of @keyboard
*
* Get the size of @keyboard.
*/
void
eek_keyboard_get_size (EekKeyboard *keyboard,
gdouble *width,
gdouble *height)
{
EekBounds bounds;
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
*width = bounds.width;
*height = bounds.height;
}
/**
* eek_keyboard_set_modifier_behavior:
* @keyboard: an #EekKeyboard
* @modifier_behavior: modifier behavior of @keyboard
*
* Set the modifier handling mode of @keyboard.
*/
void
eek_keyboard_set_modifier_behavior (EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifier_behavior = modifier_behavior;
}
/**
* eek_keyboard_get_modifier_behavior:
* @keyboard: an #EekKeyboard
*
* Get the modifier handling mode of @keyboard.
* Returns: #EekModifierBehavior
*/
EekModifierBehavior
eek_keyboard_get_modifier_behavior (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->modifier_behavior;
}
void
eek_keyboard_set_modifiers (EekKeyboard *keyboard,
EekModifierType modifiers)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->modifiers = modifiers;
set_level_from_modifiers (keyboard);
}
/**
* eek_keyboard_get_modifiers:
* @keyboard: an #EekKeyboard
*
* Get the current modifier status of @keyboard.
* Returns: #EekModifierType
*/
EekModifierType
eek_keyboard_get_modifiers (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->modifiers;
}
/**
* eek_keyboard_add_outline:
* @keyboard: an #EekKeyboard
* @outline: an #EekOutline
*
* Register an outline of @keyboard.
* Returns: an unsigned integer ID of the registered outline, for
* later reference
*/
guint
eek_keyboard_add_outline (EekKeyboard *keyboard,
EekOutline *outline)
{
EekOutline *_outline;
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
_outline = eek_outline_copy (outline);
g_array_append_val (keyboard->priv->outline_array, *_outline);
/* don't use eek_outline_free here, so as to keep _outline->points */
g_slice_free (EekOutline, _outline);
return keyboard->priv->outline_array->len - 1;
}
/**
@ -214,76 +635,115 @@ eek_keyboard_find_button_by_name (LevelKeyboard *keyboard,
* Returns: an #EekOutline, which should not be released
*/
EekOutline *
level_keyboard_get_outline (LevelKeyboard *keyboard,
eek_keyboard_get_outline (EekKeyboard *keyboard,
guint oref)
{
if (oref > keyboard->outline_array->len)
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
if (oref > keyboard->priv->outline_array->len)
return NULL;
return &g_array_index (keyboard->outline_array, EekOutline, oref);
return &g_array_index (keyboard->priv->outline_array, EekOutline, oref);
}
/**
* eek_keyboard_get_keymap:
* eek_keyboard_get_n_outlines:
* @keyboard: an #EekKeyboard
*
* Get the keymap for the keyboard.
* Returns: a string containing the XKB keymap.
* Get the number of outlines defined in @keyboard.
* Returns: integer
*/
gchar *
eek_keyboard_get_keymap(LevelKeyboard *keyboard)
gsize
eek_keyboard_get_n_outlines (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;
gchar *button_name;
gpointer button_ptr;
g_hash_table_iter_init(&iter, keyboard->names);
while (g_hash_table_iter_next(&iter, (gpointer)&button_name, &button_ptr)) {
gchar *current, *line;
struct squeek_button *button = button_ptr;
struct squeek_key *key = squeek_button_get_key(button);
guint keycode = squeek_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 *)button_name, keycode);
keycodes = g_strconcat(current, line, NULL);
g_free(line);
g_free(current);
// FIXME: free
const char *key_str = squeek_key_to_keymap_entry(
(char*)button_name,
key
);
current = symbols;
symbols = g_strconcat(current, key_str, NULL);
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;
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->outline_array->len;
}
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard)
/**
* eek_keyboard_set_num_lock_mask:
* @keyboard: an #EekKeyboard
* @num_lock_mask: an #EekModifierType
*
* Set modifier mask used as Num_Lock.
*/
void
eek_keyboard_set_num_lock_mask (EekKeyboard *keyboard,
EekModifierType num_lock_mask)
{
return keyboard->views[keyboard->level];
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->num_lock_mask = num_lock_mask;
}
/**
* eek_keyboard_get_num_lock_mask:
* @keyboard: an #EekKeyboard
*
* Get modifier mask used as Num_Lock.
* Returns: an #EekModifierType
*/
EekModifierType
eek_keyboard_get_num_lock_mask (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->num_lock_mask;
}
/**
* eek_keyboard_set_alt_gr_mask:
* @keyboard: an #EekKeyboard
* @alt_gr_mask: an #EekModifierType
*
* Set modifier mask used as Alt_Gr.
*/
void
eek_keyboard_set_alt_gr_mask (EekKeyboard *keyboard,
EekModifierType alt_gr_mask)
{
g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
keyboard->priv->alt_gr_mask = alt_gr_mask;
}
/**
* eek_keyboard_get_alt_gr_mask:
* @keyboard: an #EekKeyboard
*
* Get modifier mask used as Alt_Gr.
* Returns: an #EekModifierType
*/
EekModifierType
eek_keyboard_get_alt_gr_mask (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
return keyboard->priv->alt_gr_mask;
}
/**
* eek_keyboard_get_pressed_keys:
* @keyboard: an #EekKeyboard
*
* Get pressed keys.
* Returns: (transfer container) (element-type EekKey): A list of
* pressed keys.
*/
GList *
eek_keyboard_get_pressed_keys (EekKeyboard *keyboard)
{
g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
return g_list_copy (keyboard->priv->pressed_keys);
}
/**
* eek_keyboard_get_locked_keys:
* @keyboard: an #EekKeyboard
*
* Get locked keys.
* Returns: (transfer container) (element-type Eek.ModifierKey): A list
* of locked keys.
*/
GList *
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);
}

View File

@ -27,67 +27,172 @@
#include <glib-object.h>
#include <xkbcommon/xkbcommon.h>
#include "eek-container.h"
#include "eek-types.h"
#include "eek-layout.h"
#include "src/layout.h"
G_BEGIN_DECLS
struct _EekModifierKey {
/*< public >*/
EekModifierType modifiers;
struct squeek_button *button;
};
typedef struct _EekModifierKey EekModifierKey;
#define EEK_TYPE_KEYBOARD (eek_keyboard_get_type())
#define EEK_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_KEYBOARD, EekKeyboard))
#define EEK_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_KEYBOARD, EekKeyboardClass))
#define EEK_IS_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_KEYBOARD))
#define EEK_IS_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_KEYBOARD))
#define EEK_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_KEYBOARD, EekKeyboardClass))
/// Keyboard state holder
struct _LevelKeyboard {
struct squeek_view *views[4];
guint level;
typedef struct _EekKeyboardClass EekKeyboardClass;
typedef struct _EekKeyboardPrivate EekKeyboardPrivate;
/**
* EekKeyboard:
*
* Contains the state of the physical keyboard.
*
* Is also a graphical element...
*
* The #EekKeyboard structure contains only private data and should
* only be accessed using the provided API.
*/
struct _EekKeyboard
{
/*< private >*/
EekContainer parent;
EekKeyboardPrivate *priv;
struct xkb_keymap *keymap;
int keymap_fd; // keymap formatted as XKB string
size_t keymap_len; // length of the data inside keymap_fd
GArray *outline_array;
GList *pressed_buttons; // struct squeek_button*
GList *locked_buttons; // struct squeek_button*
/* Map button names to button objects: */
GHashTable *names;
guint id; // as a key to layout choices
EekboardContextService *manager; // unowned reference
};
typedef struct _LevelKeyboard LevelKeyboard;
struct squeek_button *eek_keyboard_find_button_by_name(LevelKeyboard *keyboard,
const gchar *name);
/**
* EekKeyboardClass:
* @create_section: virtual function for creating a section
* @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
* @key_unlocked: class handler for #EekKeyboard::key-unlocked signal
* @key_cancelled: class handler for #EekKeyboard::key-cancelled signal
*/
struct _EekKeyboardClass
{
/*< private >*/
EekContainerClass parent_class;
/// Represents the path to the button within a view
struct button_place {
const struct squeek_row *row;
const struct squeek_button *button;
/* obsolete members moved to EekElement */
gpointer set_symbol_index;
gpointer get_symbol_index;
/*< public >*/
EekSection *(* create_section) (EekKeyboard *self);
EekKey *(* find_key_by_keycode) (EekKeyboard *self,
guint keycode);
/*< private >*/
/* obsolete members moved to EekElement */
gpointer symbol_index_changed;
/*< public >*/
/* signals */
void (* key_locked) (EekKeyboard *self,
EekKey *key);
void (* key_unlocked) (EekKeyboard *self,
EekKey *key);
/*< private >*/
/* padding */
gpointer pdummy[21];
};
EekOutline *level_keyboard_get_outline
(LevelKeyboard *keyboard,
/**
* EekModifierKey:
* @modifiers: an #EekModifierType which @key triggers
* @key: an #EekKey
*
* Entry which associates modifier mask to a key. This is returned by
* eek_keyboard_get_locked_keys().
*/
struct _EekModifierKey {
/*< public >*/
EekModifierType modifiers;
EekKey *key;
};
typedef struct _EekModifierKey EekModifierKey;
EekKeyboard *eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height);
GType eek_keyboard_get_type
(void) G_GNUC_CONST;
EekLayout *eek_keyboard_get_layout
(EekKeyboard *keyboard);
void eek_keyboard_get_size
(EekKeyboard *keyboard,
gdouble *width,
gdouble *height);
void eek_keyboard_set_size
(EekKeyboard *keyboard,
gdouble width,
gdouble height);
void eek_keyboard_set_modifier_behavior
(EekKeyboard *keyboard,
EekModifierBehavior modifier_behavior);
EekModifierBehavior eek_keyboard_get_modifier_behavior
(EekKeyboard *keyboard);
void eek_keyboard_set_modifiers
(EekKeyboard *keyboard,
EekModifierType modifiers);
EekModifierType eek_keyboard_get_modifiers
(EekKeyboard *keyboard);
EekSection *eek_keyboard_create_section
(EekKeyboard *keyboard);
EekKey *eek_keyboard_find_key_by_keycode
(EekKeyboard *keyboard,
guint keycode);
guint eek_keyboard_add_outline
(EekKeyboard *keyboard,
EekOutline *outline);
EekOutline *eek_keyboard_get_outline
(EekKeyboard *keyboard,
guint oref);
gsize eek_keyboard_get_n_outlines
(EekKeyboard *keyboard);
void eek_keyboard_set_num_lock_mask
(EekKeyboard *keyboard,
EekModifierType num_lock_mask);
EekModifierType eek_keyboard_get_num_lock_mask
(EekKeyboard *keyboard);
void eek_keyboard_set_alt_gr_mask
(EekKeyboard *keyboard,
EekModifierType alt_gr_mask);
EekModifierType eek_keyboard_get_alt_gr_mask
(EekKeyboard *keyboard);
GList *eek_keyboard_get_pressed_keys
(EekKeyboard *keyboard);
GList *eek_keyboard_get_locked_keys
(EekKeyboard *keyboard);
EekModifierKey *eek_modifier_key_copy
(EekModifierKey *modkey);
void eek_modifier_key_free
(EekModifierKey *modkey);
void eek_keyboard_press_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp);
void eek_keyboard_release_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp);
gchar * eek_keyboard_get_keymap
(LevelKeyboard *keyboard);
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard);
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_view *views[], GHashTable *name_button_hash);
void level_keyboard_deinit(LevelKeyboard *self);
void level_keyboard_free(LevelKeyboard *self);
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
G_END_DECLS
#endif /* EEK_KEYBOARD_H */

View File

@ -23,9 +23,15 @@
* @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>
#include "eek-keysym.h"
#include "eek-serializable.h"
/* modifier keys */
#define EEK_KEYSYM_Shift_L 0xffe1
@ -44,22 +50,301 @@
#define EEK_KEYSYM_Hyper_L 0xffed
#define EEK_KEYSYM_Hyper_R 0xffee
typedef struct _EekKeysymPrivate
{
guint xkeysym;
} EekKeysymPrivate;
struct _EekKeysymEntry {
guint xkeysym;
const gchar *name;
EekSymbolCategory category;
};
typedef struct _EekKeysymEntry EekKeysymEntry;
#include "eek-special-keysym-entries.h"
#include "eek-unicode-keysym-entries.h"
#include "eek-xkeysym-keysym-entries.h"
guint32
eek_keysym_from_name (const gchar *name)
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_EXTENDED (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekKeysym)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static EekSerializableIface *eek_keysym_parent_serializable_iface;
static void
eek_keysym_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
for (uint i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++) {
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0) {
return xkeysym_keysym_entries[i].xkeysym;
}
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
eek_keysym_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "u", priv->xkeysym);
}
static gsize
eek_keysym_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekKeysymPrivate *priv = eek_keysym_get_instance_private (
EEK_KEYSYM(self));
index = eek_keysym_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "u", &priv->xkeysym);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_keysym_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_keysym_real_serialize;
iface->deserialize = eek_keysym_real_deserialize;
}
static gchar *
unichar_to_utf8 (gunichar uc)
{
if (g_unichar_isgraph (uc)) {
gchar *buf;
gint len;
len = g_unichar_to_utf8 (uc, NULL);
buf = g_malloc0 (len + 1);
g_unichar_to_utf8 (uc, buf);
return buf;
}
return g_strdup ("");
}
static int
keysym_entry_compare_by_xkeysym (const void *key0, const void *key1)
{
const EekKeysymEntry *entry0 = key0, *entry1 = key1;
return (gint) (entry0->xkeysym - entry1->xkeysym);
}
static EekKeysymEntry *
find_keysym_entry_by_xkeysym (guint xkeysym,
const EekKeysymEntry *entries,
gint num_entries)
{
EekKeysymEntry key;
key.xkeysym = xkeysym;
return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry),
keysym_entry_compare_by_xkeysym);
}
static gboolean
get_unichar (guint xkeysym, gunichar *uc) {
/* Check for Latin-1 characters (1:1 mapping) */
if ((xkeysym >= 0x0020 && xkeysym <= 0x007e) ||
(xkeysym >= 0x00a0 && xkeysym <= 0x00ff)) {
*uc = xkeysym;
return TRUE;
}
/* Also check for directly encoded 24-bit UCS characters:
*/
if ((xkeysym & 0xff000000) == 0x01000000) {
*uc = xkeysym & 0x00ffffff;
return TRUE;
}
return FALSE;
}
G_INLINE_FUNC EekModifierType
get_modifier_mask (guint xkeysym)
{
switch (xkeysym) {
case EEK_KEYSYM_Shift_L:
case EEK_KEYSYM_Shift_R:
case EEK_KEYSYM_Caps_Lock:
case EEK_KEYSYM_Shift_Lock:
return EEK_SHIFT_MASK;
case EEK_KEYSYM_ISO_Level3_Shift:
return EEK_BUTTON1_MASK;
case EEK_KEYSYM_Control_L:
case EEK_KEYSYM_Control_R:
return EEK_CONTROL_MASK;
case EEK_KEYSYM_Alt_L:
case EEK_KEYSYM_Alt_R:
return EEK_MOD1_MASK;
case EEK_KEYSYM_Meta_L:
case EEK_KEYSYM_Meta_R:
return EEK_META_MASK;
case EEK_KEYSYM_Super_L:
case EEK_KEYSYM_Super_R:
return EEK_SUPER_MASK;
case EEK_KEYSYM_Hyper_L:
case EEK_KEYSYM_Hyper_R:
return EEK_HYPER_MASK;
}
return 0;
}
static void
eek_keysym_class_init (EekKeysymClass *klass)
{
/* void */
}
static void
eek_keysym_init (EekKeysym *self)
{
/* void */
}
/**
* eek_keysym_new_with_modifier:
* @xkeysym: an X keysym value
* @modifier_mask: modifier assigned to @xkeysym
*
* Create an #EekKeysym with given X keysym value @xkeysym and
* modifier @modifier_mask.
*/
EekKeysym *
eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask)
{
EekKeysym *keysym;
EekKeysymPrivate *priv;
EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
*unichar_entry;
gchar *name, *label;
EekSymbolCategory category;
gunichar uc;
special_entry =
find_keysym_entry_by_xkeysym (xkeysym,
special_keysym_entries,
G_N_ELEMENTS(special_keysym_entries));
xkeysym_entry =
find_keysym_entry_by_xkeysym (xkeysym,
xkeysym_keysym_entries,
G_N_ELEMENTS(xkeysym_keysym_entries));
unicode_entry =
find_keysym_entry_by_xkeysym (xkeysym,
unicode_keysym_entries,
G_N_ELEMENTS(unicode_keysym_entries));
unichar_entry = NULL;
if (get_unichar (xkeysym, &uc)) {
unichar_entry = g_slice_new (EekKeysymEntry);
unichar_entry->xkeysym = xkeysym;
unichar_entry->name = unichar_to_utf8 (uc);
unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
}
/* name and category */
name = NULL;
if (xkeysym_entry) {
name = g_strdup (xkeysym_entry->name);
category = xkeysym_entry->category;
} else if (unichar_entry) {
name = g_strdup (unichar_entry->name);
category = unichar_entry->category;
} else if (unicode_entry) {
name = g_strdup (unicode_entry->name);
category = unicode_entry->category;
} else {
name = g_strdup ("");
category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
/* label */
if (special_entry)
label = g_strdup (special_entry->name);
else if (unichar_entry)
label = g_strdup (unichar_entry->name);
else if (unicode_entry)
label = g_strdup (unicode_entry->name);
else
label = g_strdup (name);
keysym = g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", label,
"category", category,
"modifier-mask", modifier_mask,
NULL);
g_free (name);
g_free (label);
if (unichar_entry) {
g_free ((gpointer) unichar_entry->name);
g_slice_free (EekKeysymEntry, unichar_entry);
}
priv = eek_keysym_get_instance_private (keysym);
priv->xkeysym = xkeysym;
return keysym;
}
/**
* eek_keysym_new:
* @xkeysym: an X keysym value
*
* Create an #EekKeysym with given X keysym value @xkeysym.
*/
EekKeysym *
eek_keysym_new (guint xkeysym)
{
return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (xkeysym));
}
/**
* eek_keysym_new_from_name:
* @name: an X keysym name
*
* Create an #EekKeysym with an X keysym value looked up by @name.
*/
EekKeysym *
eek_keysym_new_from_name (const gchar *name)
{
gint i;
for (i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
// g_warning ("can't find keysym entry for %s", name);
return g_object_new (EEK_TYPE_KEYSYM,
"name", name,
"label", name,
"category", EEK_SYMBOL_CATEGORY_UNKNOWN,
"modifier-mask", 0,
NULL);
}
/**
* eek_keysym_get_xkeysym:
* @keysym: an #EekKeysym
*
* Get an X keysym value associated with @keysym
*/
guint
eek_keysym_get_xkeysym (EekKeysym *keysym)
{
EekKeysymPrivate *priv;
g_assert (EEK_IS_KEYSYM(keysym));
priv = eek_keysym_get_instance_private (keysym);
return priv->xkeysym;
}

View File

@ -25,8 +25,34 @@
#ifndef EEK_KEYSYM_H
#define EEK_KEYSYM_H 1
#include "glib.h"
#include <X11/XKBlib.h>
#include "eek-symbol.h"
guint32 eek_keysym_from_name (const gchar *name);
G_BEGIN_DECLS
/**
* EEK_INVALID_KEYSYM:
*
* Pseudo keysym used for error reporting.
*/
#define EEK_INVALID_KEYSYM (0)
#define EEK_TYPE_KEYSYM (eek_keysym_get_type())
G_DECLARE_DERIVABLE_TYPE (EekKeysym, eek_keysym, EEK, KEYSYM, EekSymbol)
struct _EekKeysymClass {
/*< private >*/
EekSymbolClass parent_class;
};
GType eek_keysym_get_type (void) G_GNUC_CONST;
EekKeysym *eek_keysym_new (guint xkeysym);
guint eek_keysym_get_xkeysym (EekKeysym *keysym);
EekKeysym *eek_keysym_new_from_name (const gchar *name);
EekKeysym *eek_keysym_new_with_modifier (guint xkeysym,
EekModifierType modifier_mask);
G_END_DECLS
#endif /* EEK_KEYSYM_H */

View File

@ -26,12 +26,13 @@
* arranges keyboard elements.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-layout.h"
#include "eek-keyboard.h"
#include "eekboard/eekboard-context-service.h"
#include "eek-xml-layout.h"
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT)
@ -46,8 +47,25 @@ eek_layout_init (EekLayout *self)
{
}
void
eek_layout_update_layout(LevelKeyboard *keyboard)
/**
* eek_keyboard_new:
* @layout: an #EekLayout
* @initial_width: initial width of the keyboard
* @initial_height: initial height of the keyboard
*
* Create a new #EekKeyboard based on @layout.
*/
EekKeyboard *
eek_keyboard_new (EekboardContextService *manager,
EekLayout *layout,
gdouble initial_width,
gdouble initial_height)
{
squeek_view_place_contents(level_keyboard_current(keyboard), keyboard);
g_assert (EEK_IS_LAYOUT(layout));
g_assert (EEK_LAYOUT_GET_CLASS(layout)->create_keyboard);
return EEK_LAYOUT_GET_CLASS(layout)->create_keyboard (manager,
layout,
initial_width,
initial_height);
}

View File

@ -27,7 +27,6 @@
#include <glib-object.h>
#include "eek-types.h"
#include "src/layout.h"
G_BEGIN_DECLS
@ -44,7 +43,7 @@ struct _EekLayoutClass
GObjectClass parent_class;
/*< public >*/
LevelKeyboard* (* create_keyboard) (EekboardContextService *manager,
EekKeyboard* (* create_keyboard) (EekboardContextService *manager,
EekLayout *self,
gdouble initial_width,
gdouble initial_height);
@ -56,14 +55,5 @@ struct _EekLayoutClass
GType eek_layout_get_type (void) G_GNUC_CONST;
void eek_layout_place_rows(LevelKeyboard *keyboard, struct squeek_view *level);
void eek_layout_update_layout(LevelKeyboard *keyboard);
LevelKeyboard *
level_keyboard_from_layout (EekLayout *layout,
gdouble initial_width,
gdouble initial_height);
G_END_DECLS
#endif /* EEK_LAYOUT_H */

1
eek/eek-marshalers.list Normal file
View File

@ -0,0 +1 @@
VOID:INT,INT

File diff suppressed because it is too large Load Diff

View File

@ -21,11 +21,12 @@
#ifndef EEK_RENDERER_H
#define EEK_RENDERER_H 1
#include <gtk/gtk.h>
#include <pango/pangocairo.h>
#include "eek-keyboard.h"
#include "eek-keysym.h"
#include "eek-types.h"
#include "eek-theme.h"
#include "eek-theme-context.h"
G_BEGIN_DECLS
@ -36,9 +37,19 @@ struct _EekRendererClass
{
GObjectClass parent_class;
void (* render_button) (EekRenderer *self,
void (* render_key_label) (EekRenderer *self,
PangoLayout *layout,
EekKey *key);
void (* render_key_outline) (EekRenderer *self,
cairo_t *cr,
struct button_place *place,
EekKey *key,
gdouble scale,
gboolean rotate);
void (* render_key) (EekRenderer *self,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
@ -47,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 */
@ -56,9 +66,8 @@ struct _EekRendererClass
};
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (LevelKeyboard *keyboard,
PangoContext *pcontext,
GtkStyleContext *scontext);
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext);
void eek_renderer_set_allocation_size
(EekRenderer *renderer,
gdouble width,
@ -66,27 +75,35 @@ void eek_renderer_set_allocation_size
void eek_renderer_get_size (EekRenderer *renderer,
gdouble *width,
gdouble *height);
void eek_renderer_get_button_bounds (EekRenderer *renderer,
struct button_place *button,
void eek_renderer_get_key_bounds (EekRenderer *renderer,
EekKey *key,
EekBounds *bounds,
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);
void eek_renderer_render_button (EekRenderer *renderer,
void eek_renderer_render_key_label (EekRenderer *renderer,
PangoLayout *layout,
EekKey *key);
void eek_renderer_render_key_outline
(EekRenderer *renderer,
cairo_t *cr,
struct button_place *place,
EekKey *key,
gdouble scale,
gboolean rotate);
void eek_renderer_render_key (EekRenderer *renderer,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
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);
@ -99,18 +116,33 @@ void eek_renderer_set_default_background_color
const EekColor *color);
void eek_renderer_get_foreground_color
(EekRenderer *renderer,
GtkStyleContext *context,
EekElement *element,
EekColor *color);
void eek_renderer_get_background_color
(EekRenderer *renderer,
EekElement *element,
EekColor *color);
void eek_renderer_get_background_gradient
(EekRenderer *renderer,
EekElement *element,
EekGradientType *type,
EekColor *start,
EekColor *end);
void eek_renderer_set_border_width (EekRenderer *renderer,
gdouble border_width);
struct squeek_button *eek_renderer_find_button_by_position(EekRenderer *renderer, struct squeek_view *view,
EekKey *eek_renderer_find_key_by_position
(EekRenderer *renderer,
gdouble x,
gdouble y);
void eek_renderer_apply_transformation_for_button
void eek_renderer_apply_transformation_for_key
(EekRenderer *renderer,
cairo_t *cr, struct button_place *place,
cairo_t *cr,
EekKey *key,
gdouble scale,
gboolean rotate);
void eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_RENDERER_H */

View File

@ -1,29 +1,494 @@
/*
/*
* 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-section
* @short_description: Base class of a section
* @see_also: #EekKey
*
* The #EekSectionClass class represents a section, which consists
* of one or more keys of the #EekKeyClass class.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include "eek-keyboard.h"
#include "eek-section.h"
#include "eek-key.h"
#include "eek-symbol.h"
EekBounds eek_get_outline_size(LevelKeyboard *keyboard, uint32_t oref) {
EekOutline *outline = level_keyboard_get_outline (keyboard, oref);
enum {
PROP_0,
PROP_ANGLE,
PROP_LAST
};
enum {
KEY_LOCKED,
KEY_UNLOCKED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
struct _EekRow
{
gint num_columns;
EekOrientation orientation;
};
typedef struct _EekRow EekRow;
typedef struct _EekSectionPrivate
{
gint angle;
GSList *rows;
EekModifierType modifiers;
} EekSectionPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_CONTAINER)
static gint
eek_section_real_get_n_rows (EekSection *self)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
return g_slist_length (priv->rows);
}
static void
eek_section_real_add_row (EekSection *self,
gint num_columns,
EekOrientation orientation)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slice_new (EekRow);
row->num_columns = num_columns;
row->orientation = orientation;
priv->rows = g_slist_append (priv->rows, row);
}
static void
eek_section_real_get_row (EekSection *self,
gint index,
gint *num_columns,
EekOrientation *orientation)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekRow *row;
row = g_slist_nth_data (priv->rows, index);
g_return_if_fail (row);
if (num_columns)
*num_columns = row->num_columns;
if (orientation)
*orientation = row->orientation;
}
static void
on_locked (EekKey *key,
EekSection *section)
{
g_signal_emit (section, signals[KEY_LOCKED], 0, key);
}
static void
on_unlocked (EekKey *key,
EekSection *section)
{
g_signal_emit (section, signals[KEY_UNLOCKED], 0, key);
}
static EekKey *
eek_section_real_create_key (EekSection *self,
guint keycode,
gint column_index,
guint row_index)
{
EekKey *key;
gint num_rows;
EekRow *row;
num_rows = eek_section_get_n_rows (self);
g_return_val_if_fail (0 <= row_index && row_index < num_rows, NULL);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
row = g_slist_nth_data (priv->rows, row_index);
if (row->num_columns < column_index + 1)
row->num_columns = column_index + 1;
key = g_object_new (EEK_TYPE_KEY,
"keycode", keycode,
"column", column_index,
"row", row_index,
NULL);
g_return_val_if_fail (key, NULL);
EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
EEK_ELEMENT(key));
return key;
}
static void
set_level_from_modifiers (EekSection *self)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekKeyboard *keyboard;
EekModifierType num_lock_mask;
gint level = -1;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard);
if (priv->modifiers & num_lock_mask)
level = 1;
eek_element_set_level (EEK_ELEMENT(self), level);
}
static void
eek_section_real_key_pressed (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
EekModifierType modifier;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
behavior = eek_keyboard_get_modifier_behavior (keyboard);
modifier = eek_symbol_get_modifier_mask (symbol);
if (behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
priv->modifiers |= modifier;
set_level_from_modifiers (self);
}
}
static void
eek_section_real_key_released (EekSection *self, EekKey *key)
{
EekSectionPrivate *priv = eek_section_get_instance_private (self);
EekSymbol *symbol;
EekKeyboard *keyboard;
EekModifierBehavior behavior;
EekModifierType modifier;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
return;
keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
behavior = eek_keyboard_get_modifier_behavior (keyboard);
modifier = eek_symbol_get_modifier_mask (symbol);
switch (behavior) {
case EEK_MODIFIER_BEHAVIOR_NONE:
priv->modifiers &= ~modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LOCK:
priv->modifiers ^= modifier;
break;
case EEK_MODIFIER_BEHAVIOR_LATCH:
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
break;
}
set_level_from_modifiers (self);
}
static void
eek_section_finalize (GObject *object)
{
EekSection *self = EEK_SECTION (object);
EekSectionPrivate *priv = eek_section_get_instance_private (self);
GSList *head;
for (head = priv->rows; head; head = g_slist_next (head))
g_slice_free (EekRow, head->data);
g_slist_free (priv->rows);
G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
}
static void
eek_section_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_ANGLE:
eek_section_set_angle (EEK_SECTION(object),
g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_section_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_ANGLE:
g_value_set_int (value, eek_section_get_angle (EEK_SECTION(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_section_real_child_added (EekContainer *self,
EekElement *element)
{
g_signal_connect (element, "locked", G_CALLBACK(on_locked), self);
g_signal_connect (element, "unlocked", G_CALLBACK(on_unlocked), self);
}
static void
eek_section_real_child_removed (EekContainer *self,
EekElement *element)
{
g_signal_handlers_disconnect_by_func (element, on_locked, self);
g_signal_handlers_disconnect_by_func (element, on_unlocked, self);
}
static void
eek_section_class_init (EekSectionClass *klass)
{
EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
klass->get_n_rows = eek_section_real_get_n_rows;
klass->add_row = eek_section_real_add_row;
klass->get_row = eek_section_real_get_row;
klass->create_key = eek_section_real_create_key;
/* signals */
klass->key_pressed = eek_section_real_key_pressed;
klass->key_released = eek_section_real_key_released;
container_class->child_added = eek_section_real_child_added;
container_class->child_removed = eek_section_real_child_removed;
gobject_class->set_property = eek_section_set_property;
gobject_class->get_property = eek_section_get_property;
gobject_class->finalize = eek_section_finalize;
/**
* EekSection:angle:
*
* The rotation angle of #EekSection.
*/
pspec = g_param_spec_int ("angle",
"Angle",
"Rotation angle of the section",
-360, 360, 0,
G_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_ANGLE,
pspec);
/**
* EekSection::key-locked:
* @section: an #EekSection
* @key: an #EekKey
*
* The ::key-locked signal is emitted each time a key in @section
* is shifted to the locked state.
*/
signals[KEY_LOCKED] =
g_signal_new (I_("key-locked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekSectionClass, key_locked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
/**
* EekSection::key-unlocked:
* @section: an #EekSection
* @key: an #EekKey
*
* The ::key-unlocked signal is emitted each time a key in @section
* is shifted to the unlocked state.
*/
signals[KEY_UNLOCKED] =
g_signal_new (I_("key-unlocked"),
G_TYPE_FROM_CLASS(gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(EekSectionClass, key_unlocked),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
EEK_TYPE_KEY);
}
static void
eek_section_init (EekSection *self)
{
/* void */
}
/**
* eek_section_set_angle:
* @section: an #EekSection
* @angle: rotation angle
*
* Set rotation angle of @section to @angle.
*/
void
eek_section_set_angle (EekSection *section,
gint angle)
{
g_return_if_fail (EEK_IS_SECTION(section));
EekSectionPrivate *priv = eek_section_get_instance_private (section);
if (priv->angle != angle) {
priv->angle = angle;
g_object_notify (G_OBJECT(section), "angle");
}
}
/**
* eek_section_get_angle:
* @section: an #EekSection
*
* Get rotation angle of @section.
*/
gint
eek_section_get_angle (EekSection *section)
{
g_return_val_if_fail (EEK_IS_SECTION(section), -1);
EekSectionPrivate *priv = eek_section_get_instance_private (section);
return priv->angle;
}
/**
* eek_section_get_n_rows:
* @section: an #EekSection
*
* Get the number of rows in @section.
*/
gint
eek_section_get_n_rows (EekSection *section)
{
g_return_val_if_fail (EEK_IS_SECTION(section), -1);
return EEK_SECTION_GET_CLASS(section)->get_n_rows (section);
}
/**
* eek_section_add_row:
* @section: an #EekSection
* @num_columns: the number of column in the row
* @orientation: #EekOrientation of the row
*
* Add a row which has @num_columns columns and whose orientation is
* @orientation to @section.
*/
void
eek_section_add_row (EekSection *section,
gint num_columns,
EekOrientation orientation)
{
g_return_if_fail (EEK_IS_SECTION(section));
EEK_SECTION_GET_CLASS(section)->add_row (section,
num_columns,
orientation);
}
/**
* eek_section_get_row:
* @section: an #EekSection
* @index: the index of row
* @num_columns: pointer where the number of column in the row will be stored
* @orientation: pointer where #EekOrientation of the row will be stored
*
* Get the information about the @index-th row in @section.
*/
void
eek_section_get_row (EekSection *section,
gint index,
gint *num_columns,
EekOrientation *orientation)
{
g_return_if_fail (EEK_IS_SECTION(section));
EEK_SECTION_GET_CLASS(section)->get_row (section,
index,
num_columns,
orientation);
}
/**
* eek_section_create_key:
* @section: an #EekSection
* @keycode: a keycode
* @column: the column index of the key
* @row: the row index of the key
*
* Create an #EekKey instance and append it to @section. This
* function is rarely called by application but called by #EekLayout
* implementation.
*/
EekKey *
eek_section_create_key (EekSection *section,
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,
keycode,
column,
row);
}
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);
if (outline && outline->num_points > 0) {
double minx = outline->points[0].x;
double maxx = minx;
@ -43,14 +508,55 @@ EekBounds eek_get_outline_size(LevelKeyboard *keyboard, uint32_t oref) {
maxy = p.y;
}
}
EekBounds key_bounds = {
.height = maxy - miny,
.width = maxx - minx,
.x = 0,
.y = 0,
};
return key_bounds;
EekBounds key_bounds = {0};
eek_element_get_bounds(element, &key_bounds);
key_bounds.height = maxy - miny;
key_bounds.width = maxx - minx;
eek_element_set_bounds(element, &key_bounds);
}
EekBounds bounds = {0, 0, 0, 0};
return bounds;
}
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};
eek_element_get_bounds(element, &key_bounds);
data->total_width += key_bounds.width;
if (key_bounds.height > data->biggest_height) {
data->biggest_height = key_bounds.height;
}
}
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);
key_bounds.x = *current_offset;
key_bounds.y = 0;
eek_element_set_bounds(element, &key_bounds);
*current_offset += key_bounds.width + keyspacing;
}
void eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
{
eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard);
struct keys_info keyinfo = {0};
eek_container_foreach_child(EEK_CONTAINER(section), keycounter, &keyinfo);
EekBounds section_bounds = {0};
eek_element_get_bounds(EEK_ELEMENT(section), &section_bounds);
double key_offset = (section_bounds.width - (keyinfo.total_width + (keyinfo.count - 1) * keyspacing)) / 2;
eek_container_foreach_child(EEK_CONTAINER(section), keyplacer, &key_offset);
section_bounds.height = keyinfo.biggest_height;
eek_element_set_bounds(EEK_ELEMENT(section), &section_bounds);
}

View File

@ -25,10 +25,88 @@
#ifndef EEK_SECTION_H
#define EEK_SECTION_H 1
/* Contains row-related functions that couldn't be done in Rust easily. */
#include <glib-object.h>
#include "eek-keyboard.h"
#include "src/layout.h"
#include "eek-container.h"
#include "eek-types.h"
G_BEGIN_DECLS
#define EEK_TYPE_SECTION (eek_section_get_type())
G_DECLARE_DERIVABLE_TYPE(EekSection, eek_section, EEK, SECTION, EekContainer)
/**
* EekSectionClass:
* @get_n_rows: virtual function for getting the number of rows in the section
* @add_row: virtual function for adding a new row to the section
* @get_row: virtual function for accessing a row in the section
* @create_key: virtual function for creating key in the section
* @key_pressed: class handler for #EekSection::key-pressed signal
* @key_released: class handler for #EekSection::key-released signal
* @key_locked: class handler for #EekSection::key-locked signal
* @key_unlocked: class handler for #EekSection::key-unlocked signal
* @key_cancelled: class handler for #EekSection::key-cancelled signal
*/
struct _EekSectionClass
{
/*< private >*/
EekContainerClass parent_class;
/*< public >*/
gint (* get_n_rows) (EekSection *self);
void (* add_row) (EekSection *self,
gint num_columns,
EekOrientation orientation);
void (* get_row) (EekSection *self,
gint index,
gint *num_columns,
EekOrientation *orientation);
EekKey *(* create_key) (EekSection *self,
guint keycode,
gint row,
gint column);
/* signals */
void (* key_pressed) (EekSection *self,
EekKey *key);
void (* key_released) (EekSection *self,
EekKey *key);
void (* key_locked) (EekSection *self,
EekKey *key);
void (* key_unlocked) (EekSection *self,
EekKey *key);
void (* key_cancelled) (EekSection *self,
EekKey *key);
/*< private >*/
/* padding */
gpointer pdummy[19];
};
GType eek_section_get_type (void) G_GNUC_CONST;
void eek_section_set_angle (EekSection *section,
gint angle);
gint eek_section_get_angle (EekSection *section);
gint eek_section_get_n_rows (EekSection *section);
void eek_section_add_row (EekSection *section,
gint num_columns,
EekOrientation orientation);
void eek_section_get_row (EekSection *section,
gint index,
gint *num_columns,
EekOrientation *orientation);
EekKey *eek_section_create_key (EekSection *section,
guint keycode,
gint column,
gint row);
EekKey *eek_section_find_key_by_keycode (EekSection *section,
guint keycode);
void eek_section_place_keys (EekSection *section, EekKeyboard *keyboard);
G_END_DECLS
#endif /* EEK_SECTION_H */

93
eek/eek-serializable.c Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
* Copyright (C) 2008-2010 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:eek-serializable
* @short_description: Interface which provides object serialization
* into #GVariant
*
* The #EekSerializableIface interface defines serialize/deserialize
* method.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "eek-serializable.h"
GType
eek_serializable_get_type (void)
{
static GType iface_type = 0;
if (iface_type == 0) {
static const GTypeInfo info = {
sizeof (EekSerializableIface),
NULL,
NULL,
};
iface_type = g_type_register_static (G_TYPE_INTERFACE,
"EekSerializable",
&info, 0);
}
return iface_type;
}
GVariant *
eek_serializable_serialize (EekSerializable *object)
{
GVariantBuilder builder;
g_return_val_if_fail (EEK_IS_SERIALIZABLE (object), FALSE);
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
g_variant_builder_add (&builder, "s", g_type_name (G_OBJECT_TYPE (object)));
EEK_SERIALIZABLE_GET_IFACE (object)->serialize (object, &builder);
return g_variant_builder_end (&builder);
}
EekSerializable *
eek_serializable_deserialize (GVariant *variant)
{
gchar *type_name = NULL;
GType type;
EekSerializable *object;
gsize index = 0;
g_return_val_if_fail (variant != NULL, NULL);
g_variant_get_child (variant, index++, "&s", &type_name);
type = g_type_from_name (type_name);
g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL);
object = g_object_new (type, NULL);
index = EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object,
variant,
index);
if (index < 0) {
g_object_unref (object);
g_return_val_if_reached (NULL);
}
return object;
}

66
eek/eek-serializable.h Normal file
View File

@ -0,0 +1,66 @@
/*
* 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_SERIALIZABLE_H
#define EEK_SERIALIZABLE_H 1
#include <glib-object.h>
G_BEGIN_DECLS
#define EEK_TYPE_SERIALIZABLE (eek_serializable_get_type())
#define EEK_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_SERIALIZABLE, EekSerializable))
#define EEK_IS_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_SERIALIZABLE))
#define EEK_SERIALIZABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EEK_TYPE_SERIALIZABLE, EekSerializableIface))
typedef struct _EekSerializable EekSerializable;
typedef struct _EekSerializableIface EekSerializableIface;
/**
* EekSerializableIface:
*
* @serialize: virtual function for serializing object into #GVariant
* @deserialize: virtual function for deserializing object from #GVariant
*/
struct _EekSerializableIface
{
/*< private >*/
GTypeInterface parent_iface;
void (* serialize) (EekSerializable *object,
GVariantBuilder *builder);
gsize (* deserialize) (EekSerializable *object,
GVariant *variant,
gsize index);
/*< private >*/
/* padding */
gpointer pdummy[24];
};
GType eek_serializable_get_type (void);
GVariant *eek_serializable_serialize (EekSerializable *object);
EekSerializable *eek_serializable_deserialize (GVariant *variant);
G_END_DECLS
#endif /* EEK_SERIALIZABLE_H */

105
eek/eek-symbol-matrix.c Normal file
View File

@ -0,0 +1,105 @@
/*
* 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 "eek-symbol-matrix.h"
EekSymbolMatrix *
eek_symbol_matrix_new (gint num_groups,
gint num_levels)
{
EekSymbolMatrix *matrix = g_slice_new (EekSymbolMatrix);
matrix->num_groups = num_groups;
matrix->num_levels = num_levels;
matrix->data = g_slice_alloc0 (sizeof (EekSymbol *) *
num_groups * num_levels);
return matrix;
}
EekSymbolMatrix *
eek_symbol_matrix_copy (const EekSymbolMatrix *matrix)
{
EekSymbolMatrix *retval;
gint i, num_symbols = matrix->num_groups * matrix->num_levels;
retval = g_slice_dup (EekSymbolMatrix, matrix);
retval->data = g_slice_copy (sizeof (EekSymbol *) * num_symbols,
matrix->data);
for (i = 0; i < num_symbols; i++)
if (retval->data[i])
g_object_ref (retval->data[i]);
return retval;
}
void
eek_symbol_matrix_free (EekSymbolMatrix *matrix)
{
gint i, num_symbols = matrix->num_groups * matrix->num_levels;
for (i = 0; i < num_symbols; i++)
if (matrix->data[i])
g_object_unref (matrix->data[i]);
g_slice_free1 (sizeof (EekSymbol *) * num_symbols, matrix->data);
g_slice_free (EekSymbolMatrix, matrix);
}
GType
eek_symbol_matrix_get_type (void)
{
static GType our_type = 0;
if (our_type == 0)
our_type =
g_boxed_type_register_static ("EekSymbolMatrix",
(GBoxedCopyFunc)eek_symbol_matrix_copy,
(GBoxedFreeFunc)eek_symbol_matrix_free);
return our_type;
}
void
eek_symbol_matrix_set_symbol (EekSymbolMatrix *matrix,
gint group,
gint level,
EekSymbol *symbol)
{
g_return_if_fail (group >= 0 && group < matrix->num_groups);
g_return_if_fail (level >= 0 && level < matrix->num_levels);
g_return_if_fail (EEK_IS_SYMBOL(symbol));
matrix->data[group * matrix->num_levels + level] = g_object_ref (symbol);
}
/**
* eek_symbol_matrix_get_symbol:
* @matrix: an #EekSymbolMatrix
* @group: group index of @matrix
* @level: level index of @matrix
*
* Get an #EekSymbol stored in the cell selected by (@group, @level)
* in @matrix.
*
* Return value: (transfer none): an #EekSymbol.
*/
EekSymbol *
eek_symbol_matrix_get_symbol (EekSymbolMatrix *matrix,
gint group,
gint level)
{
g_return_val_if_fail (group >= 0 && group < matrix->num_groups, NULL);
g_return_val_if_fail (level >= 0 && level < matrix->num_levels, NULL);
return matrix->data[group * matrix->num_levels + level];
}

62
eek/eek-symbol-matrix.h Normal file
View File

@ -0,0 +1,62 @@
/*
* 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 EEK_SYMBOL_MATRIX_H
#define EEK_SYMBOL_MATRIX_H 1
#include "eek-symbol.h"
G_BEGIN_DECLS
/**
* EekSymbolMatrix:
* @data: array of symbols
* @num_groups: the number of groups (rows)
* @num_levels: the number of levels (columns)
*
* Symbol matrix of a key.
*/
struct _EekSymbolMatrix
{
/*< public >*/
gint num_groups;
gint num_levels;
EekSymbol **data;
};
#define EEK_TYPE_SYMBOL_MATRIX (eek_symbol_matrix_get_type ())
GType eek_symbol_matrix_get_type (void) G_GNUC_CONST;
EekSymbolMatrix *eek_symbol_matrix_new (gint num_groups,
gint num_levels);
EekSymbolMatrix *eek_symbol_matrix_copy (const EekSymbolMatrix *matrix);
void eek_symbol_matrix_free (EekSymbolMatrix *matrix);
void eek_symbol_matrix_set_symbol
(EekSymbolMatrix *matrix,
gint group,
gint level,
EekSymbol *symbol);
EekSymbol *eek_symbol_matrix_get_symbol
(EekSymbolMatrix *matrix,
gint group,
gint level);
G_END_DECLS
#endif /* EEK_SYMBOL_MATRIX_H */

View File

@ -25,18 +25,275 @@
* 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"
#include "eek-enumtypes.h"
enum {
PROP_0,
PROP_NAME,
PROP_LABEL,
PROP_CATEGORY,
PROP_MODIFIER_MASK,
PROP_ICON_NAME,
PROP_TOOLTIP,
PROP_LAST
};
typedef struct _EekSymbolPrivate
{
gchar *name;
gchar *label;
EekSymbolCategory category;
EekModifierType modifier_mask;
gchar *icon_name;
gchar *tooltip;
} EekSymbolPrivate;
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_EXTENDED (EekSymbol,
eek_symbol,
G_TYPE_OBJECT,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekSymbol)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static void
eek_symbol_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
#define NOTNULL(s) ((s) != NULL ? (s) : "")
g_variant_builder_add (builder, "s", NOTNULL(priv->name));
g_variant_builder_add (builder, "s", NOTNULL(priv->label));
g_variant_builder_add (builder, "u", priv->category);
g_variant_builder_add (builder, "u", priv->modifier_mask);
g_variant_builder_add (builder, "s", NOTNULL(priv->icon_name));
g_variant_builder_add (builder, "s", NOTNULL(priv->tooltip));
#undef NOTNULL
}
static gsize
eek_symbol_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
g_variant_get_child (variant, index++, "s", &priv->name);
g_variant_get_child (variant, index++, "s", &priv->label);
g_variant_get_child (variant, index++, "u", &priv->category);
g_variant_get_child (variant, index++, "u", &priv->modifier_mask);
g_variant_get_child (variant, index++, "s", &priv->icon_name);
g_variant_get_child (variant, index++, "s", &priv->tooltip);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
iface->serialize = eek_symbol_real_serialize;
iface->deserialize = eek_symbol_real_deserialize;
}
static void
eek_symbol_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_NAME:
eek_symbol_set_name (EEK_SYMBOL(object), g_value_get_string (value));
break;
case PROP_LABEL:
eek_symbol_set_label (EEK_SYMBOL(object), g_value_get_string (value));
break;
case PROP_CATEGORY:
eek_symbol_set_category (EEK_SYMBOL(object), g_value_get_enum (value));
break;
case PROP_MODIFIER_MASK:
eek_symbol_set_modifier_mask (EEK_SYMBOL(object),
g_value_get_flags (value));
break;
case PROP_ICON_NAME:
eek_symbol_set_icon_name (EEK_SYMBOL(object),
g_value_get_string (value));
break;
case PROP_TOOLTIP:
eek_symbol_set_tooltip (EEK_SYMBOL(object),
g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_symbol_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
case PROP_NAME:
g_value_set_string (value, eek_symbol_get_name (EEK_SYMBOL(object)));
break;
case PROP_LABEL:
g_value_set_string (value, eek_symbol_get_label (EEK_SYMBOL(object)));
break;
case PROP_CATEGORY:
g_value_set_enum (value, eek_symbol_get_category (EEK_SYMBOL(object)));
break;
case PROP_MODIFIER_MASK:
g_value_set_flags (value,
eek_symbol_get_modifier_mask (EEK_SYMBOL(object)));
break;
case PROP_ICON_NAME:
g_value_set_string (value,
eek_symbol_get_icon_name (EEK_SYMBOL(object)));
break;
case PROP_TOOLTIP:
g_value_set_string (value,
eek_symbol_get_tooltip (EEK_SYMBOL(object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_symbol_finalize (GObject *object)
{
EekSymbol *self = EEK_SYMBOL (object);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
g_free (priv->name);
g_free (priv->label);
g_free (priv->icon_name);
g_free (priv->tooltip);
G_OBJECT_CLASS (eek_symbol_parent_class)->finalize (object);
}
static void
eek_symbol_class_init (EekSymbolClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = eek_symbol_set_property;
gobject_class->get_property = eek_symbol_get_property;
gobject_class->finalize = eek_symbol_finalize;
pspec = g_param_spec_string ("name",
"Name",
"Canonical name of the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("label",
"Label",
"Text used to display the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
pspec = g_param_spec_enum ("category",
"Category",
"Category of the symbol",
EEK_TYPE_SYMBOL_CATEGORY,
EEK_SYMBOL_CATEGORY_UNKNOWN,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_CATEGORY, pspec);
pspec = g_param_spec_flags ("modifier-mask",
"Modifier mask",
"Modifier mask of the symbol",
EEK_TYPE_MODIFIER_TYPE,
0,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_MODIFIER_MASK, pspec);
pspec = g_param_spec_string ("icon-name",
"Icon name",
"Icon name used to render the symbol",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ICON_NAME, pspec);
pspec = g_param_spec_string ("tooltip",
"Tooltip",
"Tooltip text",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TOOLTIP, pspec);
}
static void
eek_symbol_init (EekSymbol *self)
{
EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
priv->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
}
/**
* eek_symbol_new:
* @name: name of the symbol
*
* Create a new #EekSymbol with @name.
*/
EekSymbol *
eek_symbol_new (const gchar *name)
{
EekSymbol *self = g_new0(EekSymbol, 1);
self->name = g_strdup (name);
self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
return self;
return g_object_new (EEK_TYPE_SYMBOL, "name", name, NULL);
}
/**
* eek_symbol_set_name:
* @symbol: an #EekSymbol
* @name: name of the symbol
*
* Set the name of @symbol to @name.
*/
void
eek_symbol_set_name (EekSymbol *symbol,
const gchar *name)
{
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->name);
priv->name = g_strdup (name);
}
/**
* eek_symbol_get_name:
* @symbol: an #EekSymbol
*
* Get the name of @symbol.
*/
const gchar *
eek_symbol_get_name (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->name == NULL || *priv->name == '\0')
return NULL;
return priv->name;
}
/**
@ -50,8 +307,64 @@ void
eek_symbol_set_label (EekSymbol *symbol,
const gchar *label)
{
g_free (symbol->label);
symbol->label = g_strdup (label);
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->label);
priv->label = g_strdup (label);
}
/**
* eek_symbol_get_label:
* @symbol: an #EekSymbol
*
* Get the label text of @symbol.
*/
const gchar *
eek_symbol_get_label (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->label == NULL || *priv->label == '\0')
return NULL;
return priv->label;
}
/**
* eek_symbol_set_category:
* @symbol: an #EekSymbol
* @category: an #EekSymbolCategory
*
* Set symbol category of @symbol to @category.
*/
void
eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category)
{
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
priv->category = category;
}
/**
* eek_symbol_get_category:
* @symbol: an #EekSymbol
*
* Get symbol category of @symbol.
*/
EekSymbolCategory
eek_symbol_get_category (EekSymbol *symbol)
{
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), EEK_SYMBOL_CATEGORY_UNKNOWN);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
return priv->category;
}
/**
@ -65,7 +378,11 @@ void
eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType mask)
{
symbol->modifier_mask = mask;
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
priv->modifier_mask = mask;
}
/**
@ -77,37 +394,131 @@ eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType
eek_symbol_get_modifier_mask (EekSymbol *symbol)
{
return 0;
return symbol->modifier_mask;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), 0);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
return priv->modifier_mask;
}
/**
* eek_symbol_is_modifier:
* @symbol: an #EekSymbol
*
* Check if @symbol is a modifier.
* Returns: %TRUE if @symbol is a modifier.
*/
gboolean
eek_symbol_is_modifier (EekSymbol *symbol)
{
return eek_symbol_get_modifier_mask (symbol) != 0;
}
/**
* eek_symbol_set_icon_name:
* @symbol: an #EekSymbol
* @icon_name: icon name of @symbol
*
* Set the icon name of @symbol to @icon_name.
*/
void
eek_symbol_set_icon_name (EekSymbol *symbol,
const gchar *icon_name)
{
g_free (symbol->icon_name);
symbol->icon_name = g_strdup (icon_name);
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->icon_name);
priv->icon_name = g_strdup (icon_name);
}
/**
* eek_symbol_get_icon_name:
* @symbol: an #EekSymbol
*
* Get the icon name of @symbol.
*/
const gchar *
eek_symbol_get_icon_name (EekSymbol *symbol)
{
return NULL;
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->icon_name == NULL || *priv->icon_name == '\0')
return NULL;
return priv->icon_name;
}
/**
* eek_symbol_set_tooltip:
* @symbol: an #EekSymbol
* @tooltip: icon name of @symbol
*
* Set the tooltip text of @symbol to @tooltip.
*/
void
eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *tooltip)
{
g_free (symbol->tooltip);
symbol->tooltip = g_strdup (tooltip);
g_return_if_fail (EEK_IS_SYMBOL(symbol));
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
g_free (priv->tooltip);
priv->tooltip = g_strdup (tooltip);
}
/**
* eek_symbol_get_tooltip:
* @symbol: an #EekSymbol
*
* Get the tooltip text of @symbol.
*/
const gchar *
eek_symbol_get_tooltip (EekSymbol *symbol)
{
return NULL;
if (symbol->tooltip == NULL || *symbol->tooltip == '\0')
g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
if (priv->tooltip == NULL || *priv->tooltip == '\0')
return NULL;
return symbol->tooltip;
return priv->tooltip;
}
static const struct {
EekSymbolCategory category;
gchar *name;
} category_names[] = {
{ EEK_SYMBOL_CATEGORY_LETTER, "letter" },
{ EEK_SYMBOL_CATEGORY_FUNCTION, "function" },
{ EEK_SYMBOL_CATEGORY_KEYNAME, "keyname" },
{ EEK_SYMBOL_CATEGORY_USER0, "user0" },
{ EEK_SYMBOL_CATEGORY_USER1, "user1" },
{ EEK_SYMBOL_CATEGORY_USER2, "user2" },
{ EEK_SYMBOL_CATEGORY_USER3, "user3" },
{ EEK_SYMBOL_CATEGORY_USER4, "user4" },
{ EEK_SYMBOL_CATEGORY_UNKNOWN, NULL }
};
const gchar *
eek_symbol_category_get_name (EekSymbolCategory category)
{
gint i;
for (i = 0; i < G_N_ELEMENTS(category_names); i++)
if (category_names[i].category == category)
return category_names[i].name;
return NULL;
}
EekSymbolCategory
eek_symbol_category_from_name (const gchar *name)
{
gint i;
for (i = 0; i < G_N_ELEMENTS(category_names); i++)
if (g_strcmp0 (category_names[i].name, name) == 0)
return category_names[i].category;
return EEK_SYMBOL_CATEGORY_UNKNOWN;
}

100
eek/eek-symbol.h Normal file
View File

@ -0,0 +1,100 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_SYMBOL_H
#define EEK_SYMBOL_H 1
#include "eek-types.h"
G_BEGIN_DECLS
/**
* EekSymbolCategory:
* @EEK_SYMBOL_CATEGORY_LETTER: the symbol represents an alphabet letter
* @EEK_SYMBOL_CATEGORY_FUNCTION: the symbol represents a function
* @EEK_SYMBOL_CATEGORY_KEYNAME: the symbol does not have meaning but
* have a name
* @EEK_SYMBOL_CATEGORY_USER0: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER1: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER2: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER3: reserved for future use
* @EEK_SYMBOL_CATEGORY_USER4: reserved for future use
* @EEK_SYMBOL_CATEGORY_UNKNOWN: used for error reporting
* @EEK_SYMBOL_CATEGORY_LAST: the last symbol category
*
* Category of the key symbols.
*/
typedef enum {
EEK_SYMBOL_CATEGORY_LETTER,
EEK_SYMBOL_CATEGORY_FUNCTION,
EEK_SYMBOL_CATEGORY_KEYNAME,
EEK_SYMBOL_CATEGORY_USER0,
EEK_SYMBOL_CATEGORY_USER1,
EEK_SYMBOL_CATEGORY_USER2,
EEK_SYMBOL_CATEGORY_USER3,
EEK_SYMBOL_CATEGORY_USER4,
EEK_SYMBOL_CATEGORY_UNKNOWN,
EEK_SYMBOL_CATEGORY_LAST = EEK_SYMBOL_CATEGORY_UNKNOWN
} EekSymbolCategory;
#define EEK_TYPE_SYMBOL (eek_symbol_get_type())
G_DECLARE_DERIVABLE_TYPE(EekSymbol, eek_symbol, EEK, SYMBOL, GObject)
/**
* EekSymbolClass:
*/
struct _EekSymbolClass {
/*< private >*/
GObjectClass parent_class;
};
GType eek_symbol_get_type (void) G_GNUC_CONST;
EekSymbol *eek_symbol_new (const gchar *name);
void eek_symbol_set_name (EekSymbol *symbol,
const gchar *name);
const gchar *eek_symbol_get_name (EekSymbol *symbol);
void eek_symbol_set_label (EekSymbol *symbol,
const gchar *label);
const gchar *eek_symbol_get_label (EekSymbol *symbol);
void eek_symbol_set_category (EekSymbol *symbol,
EekSymbolCategory category);
EekSymbolCategory eek_symbol_get_category (EekSymbol *symbol);
EekModifierType eek_symbol_get_modifier_mask (EekSymbol *symbol);
void eek_symbol_set_modifier_mask (EekSymbol *symbol,
EekModifierType mask);
gboolean eek_symbol_is_modifier (EekSymbol *symbol);
void eek_symbol_set_icon_name (EekSymbol *symbol,
const gchar *icon_name);
const gchar *eek_symbol_get_icon_name (EekSymbol *symbol);
void eek_symbol_set_tooltip (EekSymbol *symbol,
const gchar *tooltip);
const gchar * eek_symbol_get_tooltip (EekSymbol *symbol);
const gchar *eek_symbol_category_get_name (EekSymbolCategory category);
EekSymbolCategory eek_symbol_category_from_name (const gchar *name);
G_END_DECLS
#endif /* EEK_SYMBOL_H */

187
eek/eek-text.c Normal file
View File

@ -0,0 +1,187 @@
/*
* 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
*/
/**
* SECTION:eek-text
* @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"
enum {
PROP_0,
PROP_TEXT,
PROP_LAST
};
typedef struct _EekTextPrivate
{
gchar *text;
} EekTextPrivate;
static void eek_serializable_iface_init (EekSerializableIface *iface);
G_DEFINE_TYPE_EXTENDED (EekText,
eek_text,
EEK_TYPE_SYMBOL,
0, /* GTypeFlags */
G_ADD_PRIVATE (EekText)
G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
eek_serializable_iface_init))
static EekSerializableIface *eek_text_parent_serializable_iface;
static void
eek_text_real_serialize (EekSerializable *self,
GVariantBuilder *builder)
{
EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
eek_text_parent_serializable_iface->serialize (self, builder);
g_variant_builder_add (builder, "s", priv->text);
}
static gsize
eek_text_real_deserialize (EekSerializable *self,
GVariant *variant,
gsize index)
{
EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
index = eek_text_parent_serializable_iface->deserialize (self,
variant,
index);
g_variant_get_child (variant, index++, "s", &priv->text);
return index;
}
static void
eek_serializable_iface_init (EekSerializableIface *iface)
{
eek_text_parent_serializable_iface =
g_type_interface_peek_parent (iface);
iface->serialize = eek_text_real_serialize;
iface->deserialize = eek_text_real_deserialize;
}
static void
eek_text_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
switch (prop_id) {
case PROP_TEXT:
g_free (priv->text);
priv->text = g_strdup (g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_text_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
switch (prop_id) {
case PROP_TEXT:
g_value_set_string (value, priv->text);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
eek_text_finalize (GObject *object)
{
EekText *self = EEK_TEXT (object);
EekTextPrivate *priv = eek_text_get_instance_private (self);
g_free (priv->text);
G_OBJECT_CLASS (eek_text_parent_class)->finalize (object);
}
static void
eek_text_class_init (EekTextClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = eek_text_set_property;
gobject_class->get_property = eek_text_get_property;
gobject_class->finalize = eek_text_finalize;
pspec = g_param_spec_string ("text",
"Text",
"Text",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
}
static void
eek_text_init (EekText *self)
{
/* void */
}
EekText *
eek_text_new (const gchar *text)
{
return g_object_new (EEK_TYPE_TEXT,
"label", text,
"category", EEK_SYMBOL_CATEGORY_FUNCTION,
"text", text,
NULL);
}
/**
* eek_text_get_text:
* @text: an #EekText
*
* Get a text value associated with @text
*/
const gchar *
eek_text_get_text (EekText *text)
{
EekTextPrivate *priv = eek_text_get_instance_private (text);
return priv->text;
}

46
eek/eek-text.h Normal file
View File

@ -0,0 +1,46 @@
/*
* 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
*/
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef EEK_TEXT_H
#define EEK_TEXT_H 1
#include "eek-symbol.h"
G_BEGIN_DECLS
#define EEK_TYPE_TEXT (eek_text_get_type())
G_DECLARE_DERIVABLE_TYPE(EekText, eek_text, EEK, TEXT, EekSymbol)
struct _EekTextClass {
/*< private >*/
EekSymbolClass parent_class;
};
GType eek_text_get_type (void) G_GNUC_CONST;
EekText *eek_text_new (const gchar *text);
const gchar *eek_text_get_text (EekText *text);
G_END_DECLS
#endif /* EEK_TEXT_H */

289
eek/eek-theme-context.c Normal file
View File

@ -0,0 +1,289 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/*
* eek-theme-context.c: holds global information about a tree of styled objects
*
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright 2009 Florian Müllner
*
* This program 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.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope 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 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"
struct _EekThemeContext {
GObject parent;
double resolution;
PangoFontDescription *font;
EekThemeNode *root_node;
EekTheme *theme;
};
struct _EekThemeContextClass {
GObjectClass parent_class;
};
#define DEFAULT_RESOLUTION 96.
#define DEFAULT_FONT "sans-serif 10"
enum
{
CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (EekThemeContext, eek_theme_context, G_TYPE_OBJECT)
static void
eek_theme_context_finalize (GObject *object)
{
EekThemeContext *context = EEK_THEME_CONTEXT (object);
if (context->root_node)
g_object_unref (context->root_node);
if (context->theme)
g_object_unref (context->theme);
pango_font_description_free (context->font);
G_OBJECT_CLASS (eek_theme_context_parent_class)->finalize (object);
}
static void
eek_theme_context_class_init (EekThemeContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = eek_theme_context_finalize;
signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, /* no default handler slot */
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
eek_theme_context_init (EekThemeContext *context)
{
context->resolution = DEFAULT_RESOLUTION;
context->font = pango_font_description_from_string (DEFAULT_FONT);
}
/**
* eek_theme_context_new:
*
* Create a new theme context.
*/
EekThemeContext *
eek_theme_context_new (void)
{
EekThemeContext *context;
context = g_object_new (EEK_TYPE_THEME_CONTEXT, NULL);
return context;
}
static void
eek_theme_context_changed (EekThemeContext *context)
{
EekThemeNode *old_root = context->root_node;
context->root_node = NULL;
g_signal_emit (context, signals[CHANGED], 0);
if (old_root)
g_object_unref (old_root);
}
/**
* eek_theme_context_set_theme:
* @context: an #EekThemeContext
* @theme: an #EekTheme
*
* Sets the default set of theme stylesheets for the context. This theme will
* be used for the root node and for nodes descending from it, unless some other
* style is explicitely specified.
*/
void
eek_theme_context_set_theme (EekThemeContext *context,
EekTheme *theme)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
g_return_if_fail (theme == NULL || EEK_IS_THEME (theme));
if (context->theme != theme)
{
if (context->theme)
g_object_unref (context->theme);
context->theme = theme;
if (context->theme)
g_object_ref (context->theme);
eek_theme_context_changed (context);
}
}
/**
* eek_theme_context_get_theme:
* @context: a #EekThemeContext
*
* Gets the default theme for the context. See eek_theme_context_set_theme()
*
* Return value: (transfer none): the default theme for the context
*/
EekTheme *
eek_theme_context_get_theme (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
return context->theme;
}
/**
* eek_theme_context_set_resolution:
* @context: a #EekThemeContext
* @resolution: resolution of the context (number of pixels in an "inch")
*
* Sets the resolution of the theme context. This is the scale factor
* used to convert between points and the length units pt, in, and cm.
* This does not necessarily need to correspond to the actual number
* resolution of the device. A value of 72. means that points and
* pixels are identical. The default value is 96.
*/
void
eek_theme_context_set_resolution (EekThemeContext *context,
double resolution)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
if (resolution == context->resolution)
return;
context->resolution = resolution;
eek_theme_context_changed (context);
}
/**
* eek_theme_context_set_default_resolution:
* @context: a #EekThemeContext
*
* Sets the resolution of the theme context to the default value of 96.
* See eek_theme_context_set_resolution().
*/
void
eek_theme_context_set_default_resolution (EekThemeContext *context)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
if (context->resolution == DEFAULT_RESOLUTION)
return;
context->resolution = DEFAULT_RESOLUTION;
eek_theme_context_changed (context);
}
/**
* eek_theme_context_get_resolution:
* @context: a #EekThemeContext
*
* Gets the current resolution of the theme context.
* See eek_theme_context_set_resolution().
*
* Return value: the resolution (in dots-per-"inch")
*/
double
eek_theme_context_get_resolution (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), DEFAULT_RESOLUTION);
return context->resolution;
}
/**
* eek_theme_context_set_font:
* @context: a #EekThemeContext
* @font: the default font for theme context
*
* Sets the default font for the theme context. This is the font that
* is inherited by the root node of the tree of theme nodes. If the
* font is not overriden, then this font will be used. If the font is
* partially modified (for example, with 'font-size: 110%', then that
* modification is based on this font.
*/
void
eek_theme_context_set_font (EekThemeContext *context,
const PangoFontDescription *font)
{
g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
g_return_if_fail (font != NULL);
if (context->font == font ||
pango_font_description_equal (context->font, font))
return;
pango_font_description_free (context->font);
context->font = pango_font_description_copy (font);
eek_theme_context_changed (context);
}
/**
* eek_theme_context_get_font:
* @context: a #EekThemeContext
*
* Gets the default font for the theme context. See eek_theme_context_set_font().
*
* Return value: the default font for the theme context.
*/
const PangoFontDescription *
eek_theme_context_get_font (EekThemeContext *context)
{
g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
return context->font;
}
/**
* eek_theme_context_get_root_node:
* @context: a #EekThemeContext
*
* Gets the root node of the tree of theme style nodes that associated with this
* context. For the node tree associated with a stage, this node represents
* styles applied to the stage itself.
*
* Return value: (transfer none): the root node of the context's style tree
*/
EekThemeNode *
eek_theme_context_get_root_node (EekThemeContext *context)
{
if (context->root_node == NULL)
context->root_node = eek_theme_node_new (context, NULL, context->theme,
G_TYPE_NONE, NULL, NULL, NULL, NULL);
return context->root_node;
}

78
eek/eek-theme-context.h Normal file
View File

@ -0,0 +1,78 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* eek-theme-context.c: holds global information about a tree of styled objects
*
* Copyright 2009, 2010 Red Hat, Inc.
* Copyright 2009 Florian Müllner
*
* This program 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.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EEK_THEME_CONTEXT_H__
#define __EEK_THEME_CONTEXT_H__
#include <pango/pango.h>
#include "eek-theme-node.h"
G_BEGIN_DECLS
/**
* SECTION:eek-theme-context
* @short_description: holds global information about a tree of styled objects
*
* #EekThemeContext is responsible for managing information global to
* a tree of styled objects, such as the set of stylesheets or the
* default font.
*/
typedef struct _EekThemeContextClass EekThemeContextClass;
#define EEK_TYPE_THEME_CONTEXT (eek_theme_context_get_type ())
#define EEK_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EEK_TYPE_THEME_CONTEXT, EekThemeContext))
#define EEK_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
#define EEK_IS_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EEK_TYPE_THEME_CONTEXT))
#define EEK_IS_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_CONTEXT))
#define EEK_THEME_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
GType eek_theme_context_get_type
(void) G_GNUC_CONST;
EekThemeContext *eek_theme_context_new
(void);
void eek_theme_context_set_theme
(EekThemeContext *context,
EekTheme *theme);
EekTheme * eek_theme_context_get_theme
(EekThemeContext *context);
void eek_theme_context_set_resolution
(EekThemeContext *context,
gdouble resolution);
void eek_theme_context_set_default_resolution
(EekThemeContext *context);
double eek_theme_context_get_resolution
(EekThemeContext *context);
void eek_theme_context_set_font
(EekThemeContext *context,
const PangoFontDescription *font);
const PangoFontDescription *eek_theme_context_get_font
(EekThemeContext *context);
EekThemeNode * eek_theme_context_get_root_node
(EekThemeContext *context);
G_END_DECLS
#endif /* __EEK_THEME_CONTEXT_H__ */

1869
eek/eek-theme-node.c Normal file

File diff suppressed because it is too large Load Diff

141
eek/eek-theme-node.h Normal file
View File

@ -0,0 +1,141 @@
/*
* 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_THEME_NODE_H__
#define __EEK_THEME_NODE_H__
#include <pango/pango.h>
#include "eek-types.h"
G_BEGIN_DECLS
/**
* SECTION:eek-theme-node
* @short_description: style information for one node in a tree of
* themed objects
*
* The #EekThemeNode class represents the CSS style information (the
* set of CSS properties) for one node in a tree of themed objects. In
* typical usage, it represents the style information for a single
* #EekElement. A #EekThemeNode is immutable: attributes such as the
* CSS classes for the node are passed in at construction. If the
* attributes of the node or any parent node change, the node should
* be discarded and a new node created. #EekThemeNode has generic
* accessors to look up properties by name and specific accessors for
* standard CSS properties that add caching and handling of various
* details of the CSS specification. #EekThemeNode also has
* convenience functions to help in implementing a #EekElement with
* borders and padding.
*/
typedef enum {
EEK_SIDE_TOP,
EEK_SIDE_RIGHT,
EEK_SIDE_BOTTOM,
EEK_SIDE_LEFT
} EekSide;
typedef enum {
EEK_CORNER_TOPLEFT,
EEK_CORNER_TOPRIGHT,
EEK_CORNER_BOTTOMRIGHT,
EEK_CORNER_BOTTOMLEFT
} EekCorner;
#define EEK_TYPE_THEME_NODE (eek_theme_node_get_type())
#define EEK_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME_NODE, EekThemeNode))
#define EEK_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
#define EEK_IS_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME_NODE))
#define EEK_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_NODE))
#define EEK_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
typedef struct _EekThemeNodeClass EekThemeNodeClass;
typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
GType eek_theme_node_get_type
(void) G_GNUC_CONST;
EekThemeNode *eek_theme_node_new (EekThemeContext *context,
EekThemeNode *parent_node,
/* can be null */ EekTheme *theme,
/* can be null */ GType element_type,
const char *element_id,
const char *element_class,
const char *pseudo_class,
const char *inline_style);
EekThemeNode *eek_theme_node_get_parent
(EekThemeNode *node);
EekTheme *eek_theme_node_get_theme
(EekThemeNode *node);
GType eek_theme_node_get_element_type
(EekThemeNode *node);
const char *eek_theme_node_get_element_id
(EekThemeNode *node);
const char *eek_theme_node_get_element_class
(EekThemeNode *node);
const char *eek_theme_node_get_pseudo_class
(EekThemeNode *node);
/* Generic getters ... these are not cached so are less efficient. The other
* reason for adding the more specific version is that we can handle the
* details of the actual CSS rules, which can be complicated, especially
* for fonts
*/
void eek_theme_node_get_color
(EekThemeNode *node,
const char *property_name,
EekColor *color);
/* Specific getters for particular properties: cached
*/
void eek_theme_node_get_background_color
(EekThemeNode *node,
EekColor *color);
void eek_theme_node_get_foreground_color
(EekThemeNode *node,
EekColor *color);
void eek_theme_node_get_background_gradient
(EekThemeNode *node,
EekGradientType *type,
EekColor *start,
EekColor *end);
int eek_theme_node_get_border_width
(EekThemeNode *node,
EekSide side);
int eek_theme_node_get_border_radius
(EekThemeNode *node,
EekCorner corner);
void eek_theme_node_get_border_color
(EekThemeNode *node,
EekSide side,
EekColor *color);
/* Font rule processing is pretty complicated, so we just hardcode it
* under the standard font/font-family/font-size/etc names. This means
* you can't have multiple separate styled fonts for a single item,
* but that should be OK.
*/
const PangoFontDescription *eek_theme_node_get_font (EekThemeNode *node);
G_END_DECLS
#endif /* __EEK_THEME_NODE_H__ */

22
eek/eek-theme-private.h Normal file
View File

@ -0,0 +1,22 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef __EEK_THEME_PRIVATE_H__
#define __EEK_THEME_PRIVATE_H__
#include <libcroco/libcroco.h>
#include "eek-theme.h"
G_BEGIN_DECLS
GPtrArray *_eek_theme_get_matched_properties (EekTheme *theme,
EekThemeNode *node);
/* Resolve an URL from the stylesheet to a filename */
char *_eek_theme_resolve_url (EekTheme *theme,
CRStyleSheet *base_stylesheet,
const char *url);
CRDeclaration *_eek_theme_parse_declaration_list (const char *str);
G_END_DECLS
#endif /* __EEK_THEME_PRIVATE_H__ */

1133
eek/eek-theme.c Normal file

File diff suppressed because it is too large Load Diff

49
eek/eek-theme.h Normal file
View File

@ -0,0 +1,49 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
#error "Only <eek/eek.h> can be included directly."
#endif
#ifndef __EEK_THEME_H__
#define __EEK_THEME_H__
#include <glib-object.h>
#include "eek-types.h"
G_BEGIN_DECLS
/**
* SECTION:EekTheme
* @short_description: a set of stylesheets
*
* #EekTheme holds a set of stylesheets. (The "cascade" of the name
* Cascading Stylesheets.) An #EekTheme can be set to apply to all the
* keyboard elements.
*/
typedef struct _EekThemeClass EekThemeClass;
#define EEK_TYPE_THEME (eek_theme_get_type())
#define EEK_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME, EekTheme))
#define EEK_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME, EekThemeClass))
#define EEK_IS_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME))
#define EEK_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME))
#define EEK_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME, EekThemeClass))
GType eek_theme_get_type (void) G_GNUC_CONST;
EekTheme *eek_theme_new (const char *application_stylesheet,
const char *theme_stylesheet,
const char *default_stylesheet);
gboolean eek_theme_load_stylesheet (EekTheme *theme,
const char *path,
GError **error);
void eek_theme_unload_stylesheet (EekTheme *theme,
const char *path);
G_END_DECLS
#endif /* __EEK_THEME_H__ */

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>

View File

@ -134,7 +134,12 @@ typedef enum
#define EEK_INVALID_KEYCODE (0)
typedef struct _EekElement EekElement;
typedef struct _EekContainer EekContainer;
typedef struct _EekKey EekKey;
typedef struct _EekSection EekSection;
typedef struct _EekKeyboard EekKeyboard;
typedef struct _EekSymbol EekSymbol;
typedef struct _EekKeysym EekKeysym;
typedef struct _EekText EekText;
typedef struct _EekTheme EekTheme;
typedef struct _EekThemeContext EekThemeContext;
@ -146,7 +151,6 @@ typedef struct _EekOutline EekOutline;
typedef struct _EekColor EekColor;
typedef struct _EekboardContextService EekboardContextService;
typedef struct _LevelKeyboard LevelKeyboard;
/**
* EekPoint:
@ -191,6 +195,12 @@ GType eek_bounds_get_type (void) G_GNUC_CONST;
EekBounds *eek_bounds_copy (const EekBounds *bounds);
void eek_bounds_free (EekBounds *bounds);
G_INLINE_FUNC gdouble
eek_bounds_long_side (EekBounds *bounds)
{
return bounds->width > bounds->height ? bounds->width : bounds->height;
}
/**
* EekOutline:
* @corner_radius: radius of corners of rounded polygon

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 */

File diff suppressed because it is too large Load Diff

View File

@ -62,8 +62,5 @@ GList *eek_xml_list_keyboards (void);
EekXmlKeyboardDesc *eek_xml_keyboard_desc_copy (EekXmlKeyboardDesc *desc);
void eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc);
LevelKeyboard *
eek_xml_layout_real_create_keyboard (EekLayout *self,
EekboardContextService *manager);
G_END_DECLS
#endif /* EEK_XML_LAYOUT_H */

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 */

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