Compare commits

...

26 Commits

Author SHA1 Message Date
87a0540627 0.90.5 released. 2011-03-11 16:17:46 +09:00
878a1c73fd Install eekboard.desktop. 2011-03-11 16:00:56 +09:00
b465cbc5de Add --list option to eekboard-inscript. 2011-03-11 15:52:15 +09:00
2622e4eb59 Add --keyboard option to eekboard. 2011-03-11 15:14:20 +09:00
0177f96795 Move eekboard-client from src to examples; rename eekboard-desktop-client to eekboard. 2011-03-11 14:25:48 +09:00
ec56773dc6 Don't hardcode gtk.main_quit() in inscript.py. 2011-03-11 13:24:22 +09:00
881bf34ec4 Handle the case when both shift and altgr keys are pressed. 2011-03-11 13:11:05 +09:00
6787308061 Set label/category anyway if inscript key cannot convert to keyval. 2011-03-11 12:53:54 +09:00
0cd01bf165 Fix make distcheck. 2011-03-11 12:53:35 +09:00
132ae3899f Terminate eekboard-inscript when the window is closed. 2011-03-11 12:06:07 +09:00
72f84fa4ef Export EekSymbolCategory in python binding. 2011-03-11 12:06:00 +09:00
16d81f3f71 Generate inscript keyboard on-the-fly. 2011-03-11 11:38:53 +09:00
42a0ea148b Handle "destroyed" signal in eekboard-inscript. 2011-03-10 19:38:42 +09:00
2021311a4e Add destroyed signal in python binding. 2011-03-10 19:37:30 +09:00
b64e91dffa Latch modifiers in eekboard-inscript. 2011-03-10 19:18:56 +09:00
57bb7030fb Fix toggle English feature. 2011-03-10 18:54:53 +09:00
425fe7829b Add toggle English. 2011-03-10 18:43:24 +09:00
aa88315924 Set AltGr mask in python binding. 2011-03-10 18:24:09 +09:00
39a59fb049 Serialize alt_gr_mask. 2011-03-10 18:23:49 +09:00
e0993a5e55 Add eekboard-inscript. 2011-03-10 18:14:06 +09:00
4eb59ba7ed Display client name as window title. 2011-03-10 18:11:48 +09:00
cc9fb31e61 Add examples. 2011-03-10 17:17:37 +09:00
c44ebecfb2 Improve font size computation. 2011-03-10 17:16:31 +09:00
f60e1d763e Move EekSymbolMatrix code from eek-types.[ch] to eek-symbol-matrix.[ch]. 2011-03-09 11:57:02 +09:00
5c3cb477ef Let PopContext return error if the current context is not owned by the client. 2011-03-08 19:00:04 +09:00
5fd4005967 Add transfer mode annotation for eekboard_eekboard_create_context(). 2011-03-08 14:39:41 +09:00
38 changed files with 1935 additions and 653 deletions

2
.gitignore vendored
View File

@ -72,3 +72,5 @@ po/Makefile.in.in
po/POTFILES po/POTFILES
po/stamp-it po/stamp-it
bindings/vala/*.vapi bindings/vala/*.vapi
py-compile

View File

@ -17,5 +17,5 @@
# 02110-1301 USA # 02110-1301 USA
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
SUBDIRS = eek eekboard src tests bindings docs po data SUBDIRS = eek eekboard src tests bindings docs po data examples
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection

24
README
View File

@ -26,7 +26,7 @@ OPTIONAL: fakekey, CSPI, Clutter, Clutter-Gtk, Vala, gobject-introspection
* How to test * How to test
eekboard currently includes 4 tools to implement your own virtual eekboard currently includes 3 tools to implement your own virtual
keyboard. keyboard.
** eekboard-server ** eekboard-server
@ -38,14 +38,14 @@ do that with:
$ eekboard-server & $ eekboard-server &
** eekboard-desktop-client ** eekboard
eekboard-desktop-client is a client of eekboard-server. It listens eekboard is a client of eekboard-server. It listens desktop events
desktop events (keyboard change, focus in/out, and keystroke) and (keyboard change, focus in/out, and keystroke) and generates key
generates key events when some keys are pressed on the on-screen events when some keys are pressed on the on-screen keyboard. It can
keyboard. It can be started with: be started with:
$ eekboard-desktop-client $ eekboard
** eekboard-xml ** eekboard-xml
@ -60,16 +60,6 @@ You can display the dumped layout with:
$ eekboard-xml --load keyboard.xml $ eekboard-xml --load keyboard.xml
** eekboard-client
eekboard-client is a simple test client of eekboard-server. To upload
the keyboard description to the server, display it, and listen
key events.
$ eekboard-client --set-keyboard keyboard.xml --show-keyboard --listen
KeyPressed XXXXX
KeyReleased XXXXX
* Documentation * Documentation
See file:docs/reference/eek/html/index.html See file:docs/reference/eek/html/index.html

View File

@ -25,6 +25,7 @@ Section = Eek.Section
Key = Eek.Key Key = Eek.Key
Symbol = Eek.Symbol Symbol = Eek.Symbol
Keysym = Eek.Keysym Keysym = Eek.Keysym
SymbolMatrix = Eek.SymbolMatrix
MODIFIER_BEHAVIOR_NONE, \ MODIFIER_BEHAVIOR_NONE, \
MODIFIER_BEHAVIOR_LOCK, \ MODIFIER_BEHAVIOR_LOCK, \
@ -33,6 +34,8 @@ MODIFIER_BEHAVIOR_LATCH = \
Eek.ModifierBehavior.LOCK, Eek.ModifierBehavior.LOCK,
Eek.ModifierBehavior.LATCH) Eek.ModifierBehavior.LATCH)
SymbolCategory = Eek.SymbolCategory
CSW = 640 CSW = 640
CSH = 480 CSH = 480
@ -41,6 +44,7 @@ def XmlKeyboard(path, modifier_behavior=MODIFIER_BEHAVIOR_NONE):
layout = Eek.XmlLayout.new(_file.read()) layout = Eek.XmlLayout.new(_file.read())
keyboard = Eek.Keyboard.new(layout, CSW, CSH) keyboard = Eek.Keyboard.new(layout, CSW, CSH)
keyboard.set_modifier_behavior(modifier_behavior) keyboard.set_modifier_behavior(modifier_behavior)
keyboard.set_alt_gr_mask(Eek.ModifierType.MOD5_MASK)
return keyboard return keyboard
def XklKeyboard(modifier_behavior=MODIFIER_BEHAVIOR_NONE): def XklKeyboard(modifier_behavior=MODIFIER_BEHAVIOR_NONE):

View File

@ -36,17 +36,38 @@ class Context(gobject.GObject):
'key-released': ( 'key-released': (
gobject.SIGNAL_RUN_LAST, gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE, gobject.TYPE_NONE,
(gobject.TYPE_UINT,)) (gobject.TYPE_UINT,)),
'destroyed': (
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
}
__gproperties__ = {
'keyboard-visible': (bool, None, None, False, gobject.PARAM_READWRITE),
} }
def __init__(self, giobject): def __init__(self, giobject):
super(Context, self).__init__() super(Context, self).__init__()
import sys self.__properties = dict()
self.__giobject = giobject self.__giobject = giobject
self.__giobject.connect('enabled', lambda *args: self.emit('enabled')) self.__giobject.connect('enabled', lambda *args: self.emit('enabled'))
self.__giobject.connect('disabled', lambda *args: self.emit('disabled')) self.__giobject.connect('disabled', lambda *args: self.emit('disabled'))
self.__giobject.connect('key-pressed', lambda *args: self.emit('key-pressed', args[1])) self.__giobject.connect('key-pressed', lambda *args: self.emit('key-pressed', args[1]))
self.__giobject.connect('key-released', lambda *args: self.emit('key-released', args[1])) self.__giobject.connect('key-released', lambda *args: self.emit('key-released', args[1]))
self.__giobject.connect('destroyed', lambda *args: self.emit('destroyed'))
self.__giobject.connect('notify::keyboard-visible', self.__notify_keyboard_visible_cb)
def do_set_property(self, pspec, value):
self.__properties[pspec.name] = value
def do_get_property(self, pspec):
return self.__properties[pspec.name]
def __notify_keyboard_visible_cb(self, *args):
self.set_property('keyboard-visible',
self.__giobject.get_property(args[1].name))
self.notify('keyboard-visible')
def get_giobject(self): def get_giobject(self):
return self.__giobject return self.__giobject

View File

@ -22,11 +22,18 @@ from context import Context
class Eekboard(gobject.GObject): class Eekboard(gobject.GObject):
__gtype_name__ = "PYEekboardEekboard" __gtype_name__ = "PYEekboardEekboard"
__gsignals__ = {
'destroyed': (
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
())
}
def __init__(self): def __init__(self):
super(Eekboard, self).__init__() super(Eekboard, self).__init__()
self.__connection = Gio.bus_get_sync(Gio.BusType.SESSION, None) self.__connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
self.__eekboard = gi.repository.Eekboard.Eekboard.new(self.__connection, None); self.__eekboard = gi.repository.Eekboard.Eekboard.new(self.__connection, None);
self.__eekboard.connect('destroyed', lambda *args: self.emit('destroyed'))
def create_context(self, client_name): def create_context(self, client_name):
context = self.__eekboard.create_context(client_name, None) context = self.__eekboard.create_context(client_name, None)

View File

@ -20,7 +20,7 @@ AC_PREREQ(2.63)
dnl AC_CONFIG_SRCDIR([configure.ac]) dnl AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_INIT([eekboard], [0.90.4], [ueno@unixuser.org]) AC_INIT([eekboard], [0.90.5], [ueno@unixuser.org])
dnl Init automake dnl Init automake
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
@ -245,6 +245,10 @@ data/icons/32x32/Makefile
data/icons/48x48/Makefile data/icons/48x48/Makefile
data/icons/scalable/Makefile data/icons/scalable/Makefile
data/themes/Makefile data/themes/Makefile
data/keyboards/Makefile
examples/Makefile
examples/eekboard-inscript/Makefile
examples/simple-client/Makefile
eek/eek-${EEK_API_VERSION}.pc eek/eek-${EEK_API_VERSION}.pc
eek/eek-clutter-${EEK_API_VERSION}.pc eek/eek-clutter-${EEK_API_VERSION}.pc
eek/eek-gtk-${EEK_API_VERSION}.pc eek/eek-gtk-${EEK_API_VERSION}.pc

View File

@ -1 +1,6 @@
SUBDIRS = icons themes SUBDIRS = icons themes keyboards
desktopdir = $(datadir)/applications
desktop_in_files = eekboard.desktop.in
dist_desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
@INTLTOOL_DESKTOP_RULE@

9
data/eekboard.desktop.in Normal file
View File

@ -0,0 +1,9 @@
[Desktop Entry]
Name=Eekboard
GenericName=Eekboard Virtual Keyboard
Comment=Virtual Keyboard
Exec=eekboard-desktop-client
Icon=eekboard
Terminal=false
Type=Application
Categories=GTK;Utility;

View File

@ -0,0 +1,2 @@
keyboarddir = $(pkgdatadir)/keyboards
dist_keyboard_DATA = us-qwerty.xml

View File

@ -0,0 +1,707 @@
<?xml version="1.0"?>
<keyboard version="0.90">
<bounds>0.000000,0.000000,410.000000,190.000000</bounds>
<section name="Alpha">
<bounds>10.000000,50.000000,390.000000,129.000000</bounds>
<angle>0</angle>
<row>
<columns>14</columns>
<orientation>1</orientation>
</row>
<row>
<columns>14</columns>
<orientation>1</orientation>
</row>
<row>
<columns>13</columns>
<orientation>1</orientation>
</row>
<row>
<columns>12</columns>
<orientation>1</orientation>
</row>
<row>
<columns>8</columns>
<orientation>1</orientation>
</row>
<key id="keycode105" name="RCTL" column="7" row="4">
<bounds>359.000000,104.000000,31.000000,24.000000</bounds>
<oref>outline10</oref>
<symbols groups="1" levels="1">
<keysym keyval="65508">Control_R</keysym>
</symbols>
</key>
<key id="keycode135" name="MENU" column="6" row="4">
<bounds>326.000000,104.000000,31.000000,24.000000</bounds>
<oref>outline10</oref>
<symbols groups="1" levels="1">
<keysym keyval="65383">Menu</keysym>
</symbols>
</key>
<key id="keycode134" name="RWIN" column="5" row="4">
<bounds>294.000000,104.000000,31.000000,24.000000</bounds>
<oref>outline10</oref>
<symbols groups="1" levels="1">
<keysym keyval="65516">Super_R</keysym>
</symbols>
</key>
<key id="keycode108" name="RALT" column="4" row="4">
<bounds>261.000000,104.000000,31.000000,24.000000</bounds>
<oref>outline10</oref>
<symbols groups="1" levels="1">
<keysym keyval="65027">ISO_Level3_Shift</keysym>
</symbols>
</key>
<key id="keycode65" name="SPCE" column="3" row="4">
<bounds>106.000000,104.000000,153.000000,24.000000</bounds>
<oref>outline11</oref>
<symbols groups="1" levels="1">
<keysym keyval="32">space</keysym>
</symbols>
</key>
<key id="keycode64" name="LALT" column="2" row="4">
<bounds>73.000000,104.000000,31.000000,24.000000</bounds>
<oref>outline10</oref>
<symbols groups="1" levels="2">
<keysym keyval="65513">Alt_L</keysym>
<keysym keyval="65511">Meta_L</keysym>
</symbols>
</key>
<key id="keycode133" name="LWIN" column="1" row="4">
<bounds>40.000000,104.000000,31.000000,24.000000</bounds>
<oref>outline10</oref>
<symbols groups="1" levels="1">
<keysym keyval="65515">Super_L</keysym>
</symbols>
</key>
<key id="keycode37" name="LCTL" column="0" row="4">
<bounds>2.000000,104.000000,36.000000,24.000000</bounds>
<oref>outline9</oref>
<symbols groups="1" levels="1">
<keysym keyval="65507">Control_L</keysym>
</symbols>
</key>
<key id="keycode62" name="RTSH" column="11" row="3">
<bounds>320.000000,78.000000,70.000000,24.000000</bounds>
<oref>outline8</oref>
<symbols groups="1" levels="1">
<keysym keyval="65506">Shift_R</keysym>
</symbols>
</key>
<key id="keycode61" name="AB10" column="10" row="3">
<bounds>294.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="47">slash</keysym>
<keysym keyval="63">question</keysym>
</symbols>
</key>
<key id="keycode60" name="AB09" column="9" row="3">
<bounds>268.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="46">period</keysym>
<keysym keyval="62">greater</keysym>
</symbols>
</key>
<key id="keycode59" name="AB08" column="8" row="3">
<bounds>242.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="44">comma</keysym>
<keysym keyval="60">less</keysym>
</symbols>
</key>
<key id="keycode58" name="AB07" column="7" row="3">
<bounds>216.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="109">m</keysym>
<keysym keyval="77">M</keysym>
</symbols>
</key>
<key id="keycode57" name="AB06" column="6" row="3">
<bounds>190.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="110">n</keysym>
<keysym keyval="78">N</keysym>
</symbols>
</key>
<key id="keycode56" name="AB05" column="5" row="3">
<bounds>164.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="98">b</keysym>
<keysym keyval="66">B</keysym>
</symbols>
</key>
<key id="keycode55" name="AB04" column="4" row="3">
<bounds>138.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="118">v</keysym>
<keysym keyval="86">V</keysym>
</symbols>
</key>
<key id="keycode54" name="AB03" column="3" row="3">
<bounds>113.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="99">c</keysym>
<keysym keyval="67">C</keysym>
</symbols>
</key>
<key id="keycode53" name="AB02" column="2" row="3">
<bounds>87.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="120">x</keysym>
<keysym keyval="88">X</keysym>
</symbols>
</key>
<key id="keycode52" name="AB01" column="1" row="3">
<bounds>61.000000,78.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="122">z</keysym>
<keysym keyval="90">Z</keysym>
</symbols>
</key>
<key id="keycode50" name="LFSH" column="0" row="3">
<bounds>2.000000,78.000000,57.000000,24.000000</bounds>
<oref>outline7</oref>
<symbols groups="1" levels="1">
<keysym keyval="65505">Shift_L</keysym>
</symbols>
</key>
<key id="keycode36" name="RTRN" column="12" row="2">
<bounds>333.000000,53.000000,57.000000,24.000000</bounds>
<oref>outline6</oref>
<symbols groups="1" levels="1">
<keysym keyval="65293">Return</keysym>
</symbols>
</key>
<key id="keycode48" name="AC11" column="11" row="2">
<bounds>307.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="39">quoteright</keysym>
<keysym keyval="34">quotedbl</keysym>
</symbols>
</key>
<key id="keycode47" name="AC10" column="10" row="2">
<bounds>281.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="59">semicolon</keysym>
<keysym keyval="58">colon</keysym>
</symbols>
</key>
<key id="keycode46" name="AC09" column="9" row="2">
<bounds>256.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="108">l</keysym>
<keysym keyval="76">L</keysym>
</symbols>
</key>
<key id="keycode45" name="AC08" column="8" row="2">
<bounds>230.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="107">k</keysym>
<keysym keyval="75">K</keysym>
</symbols>
</key>
<key id="keycode44" name="AC07" column="7" row="2">
<bounds>204.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="106">j</keysym>
<keysym keyval="74">J</keysym>
</symbols>
</key>
<key id="keycode43" name="AC06" column="6" row="2">
<bounds>178.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="104">h</keysym>
<keysym keyval="72">H</keysym>
</symbols>
</key>
<key id="keycode42" name="AC05" column="5" row="2">
<bounds>152.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="103">g</keysym>
<keysym keyval="71">G</keysym>
</symbols>
</key>
<key id="keycode41" name="AC04" column="4" row="2">
<bounds>126.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="102">f</keysym>
<keysym keyval="70">F</keysym>
</symbols>
</key>
<key id="keycode40" name="AC03" column="3" row="2">
<bounds>100.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="100">d</keysym>
<keysym keyval="68">D</keysym>
</symbols>
</key>
<key id="keycode39" name="AC02" column="2" row="2">
<bounds>74.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="115">s</keysym>
<keysym keyval="83">S</keysym>
</symbols>
</key>
<key id="keycode38" name="AC01" column="1" row="2">
<bounds>49.000000,53.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="97">a</keysym>
<keysym keyval="65">A</keysym>
</symbols>
</key>
<key id="keycode66" name="CAPS" column="0" row="2">
<bounds>2.000000,53.000000,44.000000,24.000000</bounds>
<oref>outline5</oref>
<symbols groups="1" levels="2">
<keysym keyval="65507">Control_L</keysym>
<keysym keyval="65507">Control_L</keysym>
</symbols>
</key>
<key id="keycode51" name="BKSL" column="13" row="1">
<bounds>352.000000,27.000000,38.000000,24.000000</bounds>
<oref>outline4</oref>
<symbols groups="1" levels="2">
<keysym keyval="92">backslash</keysym>
<keysym keyval="124">bar</keysym>
</symbols>
</key>
<key id="keycode35" name="AD12" column="12" row="1">
<bounds>326.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="93">bracketright</keysym>
<keysym keyval="125">braceright</keysym>
</symbols>
</key>
<key id="keycode34" name="AD11" column="11" row="1">
<bounds>300.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="91">bracketleft</keysym>
<keysym keyval="123">braceleft</keysym>
</symbols>
</key>
<key id="keycode33" name="AD10" column="10" row="1">
<bounds>275.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="112">p</keysym>
<keysym keyval="80">P</keysym>
</symbols>
</key>
<key id="keycode32" name="AD09" column="9" row="1">
<bounds>249.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="111">o</keysym>
<keysym keyval="79">O</keysym>
</symbols>
</key>
<key id="keycode31" name="AD08" column="8" row="1">
<bounds>223.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="105">i</keysym>
<keysym keyval="73">I</keysym>
</symbols>
</key>
<key id="keycode30" name="AD07" column="7" row="1">
<bounds>197.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="117">u</keysym>
<keysym keyval="85">U</keysym>
</symbols>
</key>
<key id="keycode29" name="AD06" column="6" row="1">
<bounds>171.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="121">y</keysym>
<keysym keyval="89">Y</keysym>
</symbols>
</key>
<key id="keycode28" name="AD05" column="5" row="1">
<bounds>145.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="116">t</keysym>
<keysym keyval="84">T</keysym>
</symbols>
</key>
<key id="keycode27" name="AD04" column="4" row="1">
<bounds>119.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="114">r</keysym>
<keysym keyval="82">R</keysym>
</symbols>
</key>
<key id="keycode26" name="AD03" column="3" row="1">
<bounds>93.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="101">e</keysym>
<keysym keyval="69">E</keysym>
</symbols>
</key>
<key id="keycode25" name="AD02" column="2" row="1">
<bounds>68.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="119">w</keysym>
<keysym keyval="87">W</keysym>
</symbols>
</key>
<key id="keycode24" name="AD01" column="1" row="1">
<bounds>42.000000,27.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="113">q</keysym>
<keysym keyval="81">Q</keysym>
</symbols>
</key>
<key id="keycode23" name="TAB" column="0" row="1">
<bounds>2.000000,27.000000,38.000000,24.000000</bounds>
<oref>outline3</oref>
<symbols groups="1" levels="2">
<keysym keyval="65289">Tab</keysym>
<keysym keyval="65056">ISO_Left_Tab</keysym>
</symbols>
</key>
<key id="keycode22" name="BKSP" column="13" row="0">
<bounds>339.000000,1.000000,51.000000,24.000000</bounds>
<oref>outline2</oref>
<symbols groups="1" levels="1">
<keysym keyval="65288">BackSpace</keysym>
</symbols>
</key>
<key id="keycode21" name="AE12" column="12" row="0">
<bounds>313.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="61">equal</keysym>
<keysym keyval="43">plus</keysym>
</symbols>
</key>
<key id="keycode20" name="AE11" column="11" row="0">
<bounds>287.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="45">minus</keysym>
<keysym keyval="95">underscore</keysym>
</symbols>
</key>
<key id="keycode19" name="AE10" column="10" row="0">
<bounds>261.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="48">0</keysym>
<keysym keyval="41">parenright</keysym>
</symbols>
</key>
<key id="keycode18" name="AE09" column="9" row="0">
<bounds>235.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="57">9</keysym>
<keysym keyval="40">parenleft</keysym>
</symbols>
</key>
<key id="keycode17" name="AE08" column="8" row="0">
<bounds>209.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="56">8</keysym>
<keysym keyval="42">asterisk</keysym>
</symbols>
</key>
<key id="keycode16" name="AE07" column="7" row="0">
<bounds>183.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="55">7</keysym>
<keysym keyval="38">ampersand</keysym>
</symbols>
</key>
<key id="keycode15" name="AE06" column="6" row="0">
<bounds>157.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="54">6</keysym>
<keysym keyval="94">asciicircum</keysym>
</symbols>
</key>
<key id="keycode14" name="AE05" column="5" row="0">
<bounds>132.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="53">5</keysym>
<keysym keyval="37">percent</keysym>
</symbols>
</key>
<key id="keycode13" name="AE04" column="4" row="0">
<bounds>106.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="52">4</keysym>
<keysym keyval="36">dollar</keysym>
</symbols>
</key>
<key id="keycode12" name="AE03" column="3" row="0">
<bounds>80.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="51">3</keysym>
<keysym keyval="35">numbersign</keysym>
</symbols>
</key>
<key id="keycode11" name="AE02" column="2" row="0">
<bounds>54.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="50">2</keysym>
<keysym keyval="64">at</keysym>
</symbols>
</key>
<key id="keycode10" name="AE01" column="1" row="0">
<bounds>28.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="49">1</keysym>
<keysym keyval="33">exclam</keysym>
</symbols>
</key>
<key id="keycode49" name="TLDE" column="0" row="0">
<bounds>2.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="96">quoteleft</keysym>
<keysym keyval="126">asciitilde</keysym>
</symbols>
</key>
</section>
<section name="Function">
<bounds>10.000000,10.000000,410.000000,25.000000</bounds>
<angle>0</angle>
<row>
<columns>16</columns>
<orientation>1</orientation>
</row>
<key id="keycode96" name="FK12" column="12" row="0">
<bounds>366.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65481">F12</keysym>
<keysym keyval="269024780">(null)</keysym>
</symbols>
</key>
<key id="keycode95" name="FK11" column="11" row="0">
<bounds>340.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65480">F11</keysym>
<keysym keyval="269024779">(null)</keysym>
</symbols>
</key>
<key id="keycode76" name="FK10" column="10" row="0">
<bounds>314.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65479">F10</keysym>
<keysym keyval="269024778">(null)</keysym>
</symbols>
</key>
<key id="keycode75" name="FK09" column="9" row="0">
<bounds>288.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65478">F9</keysym>
<keysym keyval="269024777">(null)</keysym>
</symbols>
</key>
<key id="keycode74" name="FK08" column="8" row="0">
<bounds>249.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65477">F8</keysym>
<keysym keyval="269024776">(null)</keysym>
</symbols>
</key>
<key id="keycode73" name="FK07" column="7" row="0">
<bounds>223.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65476">F7</keysym>
<keysym keyval="269024775">(null)</keysym>
</symbols>
</key>
<key id="keycode72" name="FK06" column="6" row="0">
<bounds>197.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65475">F6</keysym>
<keysym keyval="269024774">(null)</keysym>
</symbols>
</key>
<key id="keycode71" name="FK05" column="5" row="0">
<bounds>171.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65474">F5</keysym>
<keysym keyval="269024773">(null)</keysym>
</symbols>
</key>
<key id="keycode70" name="FK04" column="4" row="0">
<bounds>132.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65473">F4</keysym>
<keysym keyval="269024772">(null)</keysym>
</symbols>
</key>
<key id="keycode69" name="FK03" column="3" row="0">
<bounds>106.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65472">F3</keysym>
<keysym keyval="269024771">(null)</keysym>
</symbols>
</key>
<key id="keycode68" name="FK02" column="2" row="0">
<bounds>80.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65471">F2</keysym>
<keysym keyval="269024770">(null)</keysym>
</symbols>
</key>
<key id="keycode67" name="FK01" column="1" row="0">
<bounds>54.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="2">
<keysym keyval="65470">F1</keysym>
<keysym keyval="269024769">(null)</keysym>
</symbols>
</key>
<key id="keycode9" name="ESC" column="0" row="0">
<bounds>2.000000,1.000000,24.000000,24.000000</bounds>
<oref>outline1</oref>
<symbols groups="1" levels="1">
<keysym keyval="65307">Escape</keysym>
</symbols>
</key>
</section>
<outline id="outline1">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>24.000000,0.000000</point>
<point>24.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline3">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>38.000000,0.000000</point>
<point>38.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline4">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>38.000000,0.000000</point>
<point>38.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline5">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>44.000000,0.000000</point>
<point>44.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline6">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>57.000000,0.000000</point>
<point>57.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline7">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>57.000000,0.000000</point>
<point>57.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline8">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>70.000000,0.000000</point>
<point>70.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline9">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>36.000000,0.000000</point>
<point>36.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline10">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>31.000000,0.000000</point>
<point>31.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline11">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>153.000000,0.000000</point>
<point>153.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline12">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>24.000000,0.000000</point>
<point>24.000000,50.000000</point>
<point>0.000000,50.000000</point>
</outline>
<outline id="outline13">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>50.000000,0.000000</point>
<point>50.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
<outline id="outline2">
<corner-radius>1.000000</corner-radius>
<point>0.000000,0.000000</point>
<point>51.000000,0.000000</point>
<point>51.000000,24.000000</point>
<point>0.000000,24.000000</point>
</outline>
</keyboard>

View File

@ -35,6 +35,7 @@ libeek_public_headers = \
$(srcdir)/eek-key.h \ $(srcdir)/eek-key.h \
$(srcdir)/eek-symbol.h \ $(srcdir)/eek-symbol.h \
$(srcdir)/eek-keysym.h \ $(srcdir)/eek-keysym.h \
$(srcdir)/eek-symbol-matrix.h \
$(srcdir)/eek-types.h \ $(srcdir)/eek-types.h \
$(srcdir)/eek-xml.h \ $(srcdir)/eek-xml.h \
$(srcdir)/eek-xml-layout.h \ $(srcdir)/eek-xml-layout.h \
@ -59,6 +60,7 @@ libeek_sources = \
$(srcdir)/eek-keyboard.c \ $(srcdir)/eek-keyboard.c \
$(srcdir)/eek-section.c \ $(srcdir)/eek-section.c \
$(srcdir)/eek-key.c \ $(srcdir)/eek-key.c \
$(srcdir)/eek-symbol-matrix.c \
$(srcdir)/eek-symbol.c \ $(srcdir)/eek-symbol.c \
$(srcdir)/eek-keysym.c \ $(srcdir)/eek-keysym.c \
$(srcdir)/eek-types.c \ $(srcdir)/eek-types.c \

View File

@ -20,9 +20,8 @@
#ifndef EEK_KEY_H #ifndef EEK_KEY_H
#define EEK_KEY_H 1 #define EEK_KEY_H 1
#include <glib-object.h>
#include "eek-element.h" #include "eek-element.h"
#include "eek-types.h" #include "eek-symbol-matrix.h"
G_BEGIN_DECLS G_BEGIN_DECLS

View File

@ -147,6 +147,7 @@ eek_keyboard_real_serialize (EekSerializable *self,
} }
g_variant_builder_add (builder, "v", g_variant_builder_end (&array)); g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
g_variant_builder_add (builder, "u", priv->num_lock_mask); g_variant_builder_add (builder, "u", priv->num_lock_mask);
g_variant_builder_add (builder, "u", priv->alt_gr_mask);
} }
static gsize static gsize
@ -172,6 +173,7 @@ eek_keyboard_real_deserialize (EekSerializable *self,
g_slice_free (EekOutline, _outline); g_slice_free (EekOutline, _outline);
} }
g_variant_get_child (variant, index++, "u", &priv->num_lock_mask); g_variant_get_child (variant, index++, "u", &priv->num_lock_mask);
g_variant_get_child (variant, index++, "u", &priv->alt_gr_mask);
return index; return index;
} }
@ -359,7 +361,10 @@ eek_keyboard_real_key_released (EekKeyboard *self,
priv->modifiers ^= modifier; priv->modifiers ^= modifier;
break; break;
case EEK_MODIFIER_BEHAVIOR_LATCH: case EEK_MODIFIER_BEHAVIOR_LATCH:
priv->modifiers = (priv->modifiers ^ modifier) & modifier; if (modifier == priv->alt_gr_mask || modifier == EEK_SHIFT_MASK)
priv->modifiers ^= modifier;
else
priv->modifiers = (priv->modifiers ^ modifier) & modifier;
break; break;
} }
set_level_from_modifiers (self); set_level_from_modifiers (self);

View File

@ -53,6 +53,7 @@ struct _EekRendererPrivate
gdouble allocation_height; gdouble allocation_height;
gdouble scale; gdouble scale;
PangoFontDescription *ascii_font;
PangoFontDescription *font; PangoFontDescription *font;
GHashTable *outline_surface_cache; GHashTable *outline_surface_cache;
GHashTable *active_outline_surface_cache; GHashTable *active_outline_surface_cache;
@ -65,14 +66,13 @@ struct _EekRendererPrivate
static const EekColor DEFAULT_FOREGROUND_COLOR = {0.3, 0.3, 0.3, 1.0}; static const EekColor DEFAULT_FOREGROUND_COLOR = {0.3, 0.3, 0.3, 1.0};
static const EekColor DEFAULT_BACKGROUND_COLOR = {1.0, 1.0, 1.0, 1.0}; static const EekColor DEFAULT_BACKGROUND_COLOR = {1.0, 1.0, 1.0, 1.0};
struct { struct _TextProperty {
gint category; gint category;
gboolean ascii;
gdouble scale; gdouble scale;
} symbol_category_scale_factors[EEK_SYMBOL_CATEGORY_LAST] = { gboolean ellipses;
{ EEK_SYMBOL_CATEGORY_LETTER, 1.0 },
{ EEK_SYMBOL_CATEGORY_FUNCTION, 0.5 },
{ EEK_SYMBOL_CATEGORY_KEYNAME, 0.5 }
}; };
typedef struct _TextProperty TextProperty;
/* eek-keyboard-drawing.c */ /* eek-keyboard-drawing.c */
extern void _eek_rounded_polygon (cairo_t *cr, extern void _eek_rounded_polygon (cairo_t *cr,
@ -342,7 +342,7 @@ render_key_outline (EekRenderer *renderer,
struct _CalculateFontSizeCallbackData { struct _CalculateFontSizeCallbackData {
gdouble size; gdouble size;
gdouble em_size; gboolean ascii;
EekRenderer *renderer; EekRenderer *renderer;
const PangoFontDescription *base_font; const PangoFontDescription *base_font;
}; };
@ -358,16 +358,21 @@ calculate_font_size_key_callback (EekElement *element, gpointer user_data)
PangoRectangle extents = { 0, }; PangoRectangle extents = { 0, };
PangoLayout *layout; PangoLayout *layout;
gdouble size; gdouble size;
EekSymbol *symbol;
EekBounds bounds; EekBounds bounds;
const gchar *label = NULL; const gchar *label = NULL;
symbol = eek_key_get_symbol (EEK_KEY(element)); if (data->ascii)
if (symbol &&
eek_symbol_get_category (symbol) == EEK_SYMBOL_CATEGORY_LETTER)
label = eek_symbol_get_label (symbol);
if (!label)
label = "M"; label = "M";
else {
EekSymbol *symbol;
symbol = eek_key_get_symbol (EEK_KEY(element));
if (symbol &&
eek_symbol_get_category (symbol) == EEK_SYMBOL_CATEGORY_LETTER)
label = eek_symbol_get_label (symbol);
if (!label)
label = "M";
}
font = pango_font_description_copy (data->base_font); font = pango_font_description_copy (data->base_font);
@ -390,12 +395,8 @@ calculate_font_size_key_callback (EekElement *element, gpointer user_data)
sy = bounds.height * PANGO_SCALE / extents.height; sy = bounds.height * PANGO_SCALE / extents.height;
size *= MIN(sx, sy); size *= MIN(sx, sy);
if (size >= pango_font_description_get_size (data->base_font)) { if (size < data->size)
if (size < data->size) data->size = size;
data->size = size;
if (size < data->em_size)
data->em_size = size;
}
} }
static void static void
@ -407,19 +408,21 @@ calculate_font_size_section_callback (EekElement *element, gpointer user_data)
} }
static gdouble static gdouble
calculate_font_size (EekRenderer *renderer, const PangoFontDescription *base_font) calculate_font_size (EekRenderer *renderer,
const PangoFontDescription *base_font,
gboolean ascii)
{ {
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(renderer); EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(renderer);
CalculateFontSizeCallbackData data; CalculateFontSizeCallbackData data;
data.size = G_MAXDOUBLE; data.size = G_MAXDOUBLE;
data.em_size = G_MAXDOUBLE; data.ascii = ascii;
data.renderer = renderer; data.renderer = renderer;
data.base_font = base_font; data.base_font = base_font;
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard), eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
calculate_font_size_section_callback, calculate_font_size_section_callback,
&data); &data);
return data.size > 0 ? data.size : data.em_size; return data.size;
} }
static void static void
@ -538,6 +541,23 @@ eek_renderer_apply_transformation_for_key (EekRenderer *self,
} }
} }
static const TextProperty *
get_text_property_for_category (EekSymbolCategory category)
{
static const TextProperty props[EEK_SYMBOL_CATEGORY_LAST] = {
{ EEK_SYMBOL_CATEGORY_LETTER, FALSE, 1.0, FALSE },
{ EEK_SYMBOL_CATEGORY_FUNCTION, TRUE, 0.5, FALSE },
{ EEK_SYMBOL_CATEGORY_KEYNAME, TRUE, 0.5, TRUE }
};
gint i;
for (i = 0; i < G_N_ELEMENTS(props); i++)
if (props[i].category == category)
return &props[i];
g_return_val_if_reached (NULL);
}
static void static void
eek_renderer_real_render_key_label (EekRenderer *self, eek_renderer_real_render_key_label (EekRenderer *self,
PangoLayout *layout, PangoLayout *layout,
@ -548,9 +568,9 @@ eek_renderer_real_render_key_label (EekRenderer *self,
EekSymbolCategory category; EekSymbolCategory category;
const gchar *label; const gchar *label;
EekBounds bounds; EekBounds bounds;
const TextProperty *prop;
PangoFontDescription *font; PangoFontDescription *font;
gdouble size, scale; gdouble size, scale;
gint i;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0); symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol) if (!symbol)
@ -562,7 +582,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
if (!priv->font) { if (!priv->font) {
const PangoFontDescription *base_font; const PangoFontDescription *base_font;
gdouble size; gdouble ascii_size, size;
EekThemeNode *theme_node; EekThemeNode *theme_node;
theme_node = g_object_get_data (G_OBJECT(key), "theme-node"); theme_node = g_object_get_data (G_OBJECT(key), "theme-node");
@ -570,7 +590,11 @@ eek_renderer_real_render_key_label (EekRenderer *self,
base_font = eek_theme_node_get_font (theme_node); base_font = eek_theme_node_get_font (theme_node);
else else
base_font = pango_context_get_font_description (priv->pcontext); base_font = pango_context_get_font_description (priv->pcontext);
size = calculate_font_size (self, base_font); ascii_size = calculate_font_size (self, base_font, TRUE);
priv->ascii_font = pango_font_description_copy (base_font);
pango_font_description_set_size (priv->ascii_font, ascii_size);
size = calculate_font_size (self, base_font, FALSE);
priv->font = pango_font_description_copy (base_font); priv->font = pango_font_description_copy (base_font);
pango_font_description_set_size (priv->font, size); pango_font_description_set_size (priv->font, size);
} }
@ -579,21 +603,23 @@ eek_renderer_real_render_key_label (EekRenderer *self,
scale = MIN((bounds.width - priv->border_width) / bounds.width, scale = MIN((bounds.width - priv->border_width) / bounds.width,
(bounds.height - priv->border_width) / bounds.height); (bounds.height - priv->border_width) / bounds.height);
font = pango_font_description_copy (priv->font);
size = pango_font_description_get_size (font);
category = eek_symbol_get_category (symbol); category = eek_symbol_get_category (symbol);
for (i = 0; i < G_N_ELEMENTS(symbol_category_scale_factors); i++) prop = get_text_property_for_category (category);
if (symbol_category_scale_factors[i].category == category) {
size *= symbol_category_scale_factors[i].scale; font = pango_font_description_copy (prop->ascii ?
break; priv->ascii_font :
} priv->font);
pango_font_description_set_size (font, size * priv->scale * scale); pango_font_description_set_size (font,
pango_font_description_get_size (font) *
prop->scale * priv->scale * scale);
pango_layout_set_font_description (layout, font); pango_layout_set_font_description (layout, font);
pango_font_description_free (font); pango_font_description_free (font);
pango_layout_set_text (layout, label, -1); pango_layout_set_text (layout, label, -1);
pango_layout_set_width (layout, pango_layout_set_width (layout,
PANGO_SCALE * bounds.width * priv->scale * scale); PANGO_SCALE * bounds.width * priv->scale * scale);
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); if (prop->ellipses)
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
} }
static void static void
@ -719,6 +745,7 @@ eek_renderer_finalize (GObject *object)
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object); EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
g_hash_table_destroy (priv->outline_surface_cache); g_hash_table_destroy (priv->outline_surface_cache);
g_hash_table_destroy (priv->active_outline_surface_cache); g_hash_table_destroy (priv->active_outline_surface_cache);
pango_font_description_free (priv->ascii_font);
pango_font_description_free (priv->font); pango_font_description_free (priv->font);
G_OBJECT_CLASS (eek_renderer_parent_class)->finalize (object); G_OBJECT_CLASS (eek_renderer_parent_class)->finalize (object);
} }

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];
}

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

@ -0,0 +1,60 @@
/*
* 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
{
gint num_groups;
gint num_levels;
EekSymbol **data;
};
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

@ -20,7 +20,6 @@
#ifndef EEK_SYMBOL_H #ifndef EEK_SYMBOL_H
#define EEK_SYMBOL_H 1 #define EEK_SYMBOL_H 1
#include <glib-object.h>
#include "eek-types.h" #include "eek-types.h"
G_BEGIN_DECLS G_BEGIN_DECLS

View File

@ -32,58 +32,6 @@
#include "eek-types.h" #include "eek-types.h"
/* EekSymbolMatrix */
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;
}
/* EekPoint */ /* EekPoint */
static EekPoint * static EekPoint *
eek_point_copy (const EekPoint *point) eek_point_copy (const EekPoint *point)

View File

@ -146,28 +146,6 @@ typedef struct _EekBounds EekBounds;
typedef struct _EekOutline EekOutline; typedef struct _EekOutline EekOutline;
typedef struct _EekColor EekColor; typedef struct _EekColor EekColor;
/**
* 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
{
gint num_groups;
gint num_levels;
EekSymbol **data;
};
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);
/** /**
* EekPoint: * EekPoint:
* @x: X coordinate of the point * @x: X coordinate of the point

View File

@ -188,6 +188,8 @@ on_context_destroyed (EekboardContext *context,
* @cancellable: a #GCancellable * @cancellable: a #GCancellable
* *
* Create a new input context. * Create a new input context.
*
* Return value: (transfer full): a newly created #EekboardContext.
*/ */
EekboardContext * EekboardContext *
eekboard_eekboard_create_context (EekboardEekboard *eekboard, eekboard_eekboard_create_context (EekboardEekboard *eekboard,

1
examples/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = eekboard-inscript simple-client

View File

@ -0,0 +1,14 @@
bin_SCRIPTS = eekboard-inscript
keyboarddir = $(pkgdatadir)/keyboards
eekboard_inscript_datadir = $(datarootdir)/eekboard-inscript
eekboard_inscript_data_PYTHON = inscript.py main.py
eekboard-inscript: eekboard-inscript.in
$(AM_V_GEN) sed -e 's!@''PYTHON@!'$(PYTHON)'!' \
-e 's!@EEKBOARD_KEYBOARDDIR@!'$(keyboarddir)'!' \
-e 's!@M17N_DIR@!'$(datadir)/m17n'!' \
-e 's!@EEKBOARD_INSCRIPT_DATADIR@!'$(eekboard_inscript_datadir)'!' < $< > $@
CLEANFILES = eekboard-inscript
EXTRA_DIST = eekboard-inscript.in

View File

@ -0,0 +1,23 @@
#!/bin/sh
# 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
export EEKBOARD_KEYBOARDDIR=@EEKBOARD_KEYBOARDDIR@
export M17N_DIR=@M17N_DIR@
exec @PYTHON@ @EEKBOARD_INSCRIPT_DATADIR@/main.py $@

View File

@ -0,0 +1,225 @@
#!/usr/bin/env python
# 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
import gobject, gtk, eekboard, virtkey
import sys, os.path, re
KEYCODE_TABLE = {
'1': 10, '2': 11, '3': 12, '4': 13, '5': 14, '6': 15, '7': 16, '8': 17,
'9': 18, '0': 19, '-': 20, '=': 21, 'q': 24, 'w': 25, 'e': 26, 'r': 27,
't': 28, 'y': 29, 'u': 30, 'i': 31, 'o': 32, 'p': 33, '[': 34, ']': 35,
'a': 38, 's': 39, 'd': 40, 'f': 41, 'g': 42, 'h': 43, 'j': 44, 'k': 45,
'l': 46, ';': 47, '\'': 48, '`': 49, '\\': 51, 'z': 52, 'x': 53, 'c': 54,
'v': 55, 'b': 56, 'n': 57, 'm': 58, ',': 59, '.': 60, '/': 61
}
MARK_UPPER = '~!@#$%^&*()_+{}|:"<>?'
MARK_LOWER = '`1234567890-=[]\\;\',./'
INSCRIPT_MAPS = (
"as-inscript",
"bn-inscript",
"gu-inscript",
"hi-inscript",
"kn-inscript",
"ml-inscript",
"mr-inscript",
"or-inscript",
"pa-inscript",
"sd-inscript",
"ta-inscript",
"te-inscript",
"kn-inscript2",
"kok-inscript2-deva",
"mai-inscript2",
"ml-inscript2",
"mni-inscript2-beng",
"mni-inscript2-mtei",
"mr-inscript2",
"ne-inscript2-deva",
"or-inscript2",
"pa-inscript2-guru",
"sa-inscript2",
"sat-inscript2-deva",
"sat-inscript2-olck",
"sd-inscript2-deva",
"ta-inscript2",
"te-inscript2")
class MapFile(object):
MAPENTRY_PATTERN = re.compile(r'\A\s*\((?:\((.*?)\)|"(.*?)")\s*"(.*?)"\)')
def __init__(self, path):
self.__dict = dict()
with open(path, 'r') as fp:
for line in fp:
match = re.match(self.MAPENTRY_PATTERN, line)
if match:
insert = match.group(3).decode('UTF-8')
if match.group(1):
keyseq = re.sub(r'\\(.)', r'\1', match.group(1))
self.__add_symbol_entry(keyseq, insert)
else:
keyseq = re.sub(r'\\(.)', r'\1', match.group(2))
self.__add_text_entry(keyseq, insert)
def get_entry_for_keycode(self, keycode):
return self.__dict.get(keycode)
def __add_entry(self, letter, level, insert):
if letter.isupper():
level |= 1
letter = letter.lower()
elif letter in MARK_UPPER:
level |= 1
letter = MARK_LOWER[MARK_UPPER.index(letter)]
keycode = KEYCODE_TABLE[letter]
if keycode not in self.__dict:
self.__dict[keycode] = list([None,None,None,None])
self.__dict[keycode][level] = insert
def __add_symbol_entry(self, symbol, insert):
level = 0
if symbol.startswith('G-'):
level |= 2
symbol = symbol[2:]
if not symbol.startswith('KP_'):
self.__add_entry(symbol, level, insert)
def __add_text_entry(self, text, insert):
self.__add_entry(text, 0, insert)
class Keyboard(gobject.GObject):
__gtype_name__ = "PYInscriptKeyboard"
__gsignals__ = {
'quit': (
gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
}
def __init__(self, client_name, map_path, kbd_path):
super(Keyboard, self).__init__()
self.__keyboard = self.__create_keyboard(map_path, kbd_path)
self.__eekboard = eekboard.Eekboard()
self.__context = self.__eekboard.create_context(client_name)
keyboard_id = self.__context.add_keyboard(self.__keyboard)
self.__context.set_keyboard(keyboard_id)
self.__keyboard.connect('key-pressed', self.__key_pressed_cb)
self.__keyboard.connect('key-released', self.__key_released_cb)
self.__virtkey = virtkey.virtkey()
self.__english = False
self.__eekboard.connect('destroyed', self.__destroyed_cb)
self.__context.connect('destroyed', self.__destroyed_cb)
self.__context.connect('notify::keyboard-visible', self.__notify_keyboard_visible_cb)
def __create_keyboard(self, map_path, kbd_path):
def __each_key(element, data):
keycode = element.get_keycode()
# keycode 37 is used to toggle English/Inscript
if keycode == 37:
matrix = eekboard.SymbolMatrix.new(2, 1)
keysym = eekboard.Keysym.new(0)
keysym.set_label("Ind")
keysym.set_category(eekboard.SymbolCategory.FUNCTION)
matrix.set_symbol(0, 0, keysym)
keysym = eekboard.Keysym.new(0)
keysym.set_label("Eng")
keysym.set_category(eekboard.SymbolCategory.FUNCTION)
matrix.set_symbol(1, 0, keysym)
element.set_symbol_matrix(matrix)
return
# group(0) is us keyboard
matrix = eekboard.SymbolMatrix.new(2, 4)
for l in xrange(4):
keysym = element.get_symbol_at_index(0, l, 0, 0)
matrix.set_symbol(0, l, keysym)
# group(1) is inscript keyboard
entry = data.get_entry_for_keycode(keycode)
for l in xrange(4):
if entry and entry[l]:
try:
keyval = gtk.gdk.unicode_to_keyval(ord(entry[l]))
keysym = eekboard.Keysym.new(keyval)
except:
keysym = eekboard.Keysym.new(0)
keysym.set_label(entry[l].encode('UTF-8'))
keysym.set_category(eekboard.SymbolCategory.LETTER)
print >> sys.stderr, "can't convert %s (%d) to keyval" % (entry[l], keycode)
else:
keysym = element.get_symbol_at_index(1, l, 0, 0)
matrix.set_symbol(1, l, keysym)
element.set_symbol_matrix(matrix)
def __each_section(element, data):
element.foreach_child(__each_key, data)
mapfile = MapFile(map_path)
keyboard = eekboard.XmlKeyboard(kbd_path,
eekboard.MODIFIER_BEHAVIOR_LATCH)
keyboard.foreach_child(__each_section, mapfile)
return keyboard
def __destroyed_cb(self, *args):
self.emit('quit')
def __notify_keyboard_visible_cb(self, obj, pspec):
if not obj.get_property(pspec.name):
self.emit('quit')
def enable(self):
self.__eekboard.push_context(self.__context)
def disable(self):
self.__eekboard.pop_context(self.__context)
def show(self):
self.__context.show_keyboard()
def set_group(self, group):
self.__group = group
self.__context.set_group(self.__group)
def __key_pressed_cb(self, keyboard, key):
if key.get_keycode() == 37:
return
symbol = key.get_symbol()
if isinstance(symbol, eekboard.Keysym):
xkeysym = symbol.get_xkeysym()
modifiers = self.__keyboard.get_modifiers()
self.__virtkey.latch_mod(modifiers)
self.__virtkey.press_keysym(xkeysym)
self.__virtkey.unlatch_mod(modifiers)
def __key_released_cb(self, keyboard, key):
if key.get_keycode() == 37:
if self.__english:
self.__context.set_group(self.__group)
self.__english = False
else:
self.__context.set_group(0)
self.__english = True
return
symbol = key.get_symbol()
if isinstance(symbol, eekboard.Keysym):
xkeysym = symbol.get_xkeysym()
self.__virtkey.release_keysym(xkeysym)

View File

@ -0,0 +1,60 @@
# 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
import inscript
import gtk
from optparse import OptionParser
import sys, os, os.path, glob
parser = OptionParser()
parser.add_option("-n", "--name=LANGCODE", dest="langcode",
help="Specify language code to LANGCODE",
metavar="LANGCODE")
parser.add_option("-l", "--list", dest="list", default=False,
action="store_true",
help="List available language codes")
(options, args) = parser.parse_args()
if options.list:
pat = os.path.join(os.getenv("M17N_DIR"), "*.mim")
for fname in sorted(glob.glob(pat)):
mname = os.path.basename(fname[:-4])
if mname in inscript.INSCRIPT_MAPS:
print mname
exit(0)
if options.langcode is None:
print >> sys.stderr, "Specify language code with -n"
exit(1)
map_path = os.path.join(os.getenv("M17N_DIR"), options.langcode + ".mim")
if not os.path.exists(map_path):
print >> sys.stderr, "%s not found" % map_path
exit(1)
kbd_path = os.path.join(os.getenv("EEKBOARD_KEYBOARDDIR"), "us-qwerty.xml")
if not os.path.exists(kbd_path):
print >> sys.stderr, "%s not found" % kbd_path
exit(1)
keyboard = inscript.Keyboard("eekboard-inscript", map_path, kbd_path)
keyboard.connect('quit', lambda *args: gtk.main_quit())
keyboard.set_group(1)
keyboard.enable()
keyboard.show()
gtk.main()

View File

@ -0,0 +1,12 @@
noinst_PROGRAMS = simple-client
simple_client_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS)
simple_client_LDADD = \
$(top_builddir)/eekboard/libeekboard.la \
$(top_builddir)/eek/libeek.la \
$(GIO2_LIBS)
simple_client_SOURCES = main.c

View File

@ -0,0 +1,217 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include <glib/gi18n.h>
#include "eekboard/eekboard.h"
static gboolean opt_system = FALSE;
static gboolean opt_session = FALSE;
static gchar *opt_address = NULL;
static gchar *opt_set_keyboard = NULL;
static gint opt_set_group = -1;
static gboolean opt_show_keyboard = FALSE;
static gboolean opt_hide_keyboard = FALSE;
static gint opt_press_key = -1;
static gint opt_release_key = -1;
static gboolean opt_listen = FALSE;
static const GOptionEntry options[] = {
{"system", 'y', 0, G_OPTION_ARG_NONE, &opt_system,
N_("Connect to the system bus")},
{"session", 'e', 0, G_OPTION_ARG_NONE, &opt_session,
N_("Connect to the session bus")},
{"address", 'a', 0, G_OPTION_ARG_STRING, &opt_address,
N_("Connect to the given D-Bus address")},
{"set-keyboard", '\0', 0, G_OPTION_ARG_STRING, &opt_set_keyboard,
N_("Upload keyboard description from an XML file")},
{"set-group", '\0', 0, G_OPTION_ARG_INT, &opt_set_group,
N_("Set group of the keyboard")},
{"show-keyboard", '\0', 0, G_OPTION_ARG_NONE, &opt_show_keyboard,
N_("Show keyboard")},
{"hide-keyboard", '\0', 0, G_OPTION_ARG_NONE, &opt_hide_keyboard,
N_("Hide keyboard")},
{"press-key", '\0', 0, G_OPTION_ARG_INT, &opt_press_key,
N_("Press key")},
{"release-key", '\0', 0, G_OPTION_ARG_INT, &opt_release_key,
N_("Release key")},
{"listen", '\0', 0, G_OPTION_ARG_NONE, &opt_listen,
N_("Listen events")},
{NULL}
};
static void
on_key_pressed (guint keycode, gpointer user_data)
{
g_print ("KeyPressed %u\n", keycode);
}
static void
on_key_released (guint keycode, gpointer user_data)
{
g_print ("KeyReleased %u\n", keycode);
}
int
main (int argc, char **argv)
{
EekboardEekboard *eekboard = NULL;
EekboardContext *context = NULL;
GBusType bus_type;
GDBusConnection *connection = NULL;
GError *error;
GOptionContext *option_context;
GMainLoop *loop = NULL;
gint retval = 0;
g_type_init ();
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
option_context = g_option_context_new ("eekboard-client");
g_option_context_add_main_entries (option_context, options, NULL);
g_option_context_parse (option_context, &argc, &argv, NULL);
g_option_context_free (option_context);
if (opt_system)
bus_type = G_BUS_TYPE_SYSTEM;
else if (opt_address)
bus_type = G_BUS_TYPE_NONE;
else
bus_type = G_BUS_TYPE_SESSION;
switch (bus_type) {
case G_BUS_TYPE_SYSTEM:
case G_BUS_TYPE_SESSION:
error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (connection == NULL) {
g_printerr ("Can't connect to the bus: %s\n", error->message);
exit (1);
}
break;
case G_BUS_TYPE_NONE:
error = NULL;
connection = g_dbus_connection_new_for_address_sync (opt_address,
0,
NULL,
NULL,
&error);
if (connection == NULL) {
g_printerr ("Can't connect to the bus at %s: %s\n",
opt_address,
error->message);
exit (1);
}
break;
default:
g_assert_not_reached ();
break;
}
eekboard = eekboard_eekboard_new (connection, NULL);
if (eekboard == NULL) {
g_printerr ("Can't create eekboard proxy\n");
retval = 1;
goto out;
}
context = eekboard_eekboard_create_context (eekboard,
"eekboard-client",
NULL);
if (context == NULL) {
g_printerr ("Can't create context\n");
retval = 1;
goto out;
}
eekboard_eekboard_push_context (eekboard, context, NULL);
if (opt_set_keyboard) {
GFile *file;
GFileInputStream *input;
EekLayout *layout;
EekKeyboard *keyboard;
guint keyboard_id;
file = g_file_new_for_path (opt_set_keyboard);
error = NULL;
input = g_file_read (file, NULL, &error);
if (error) {
g_printerr ("Can't read file %s: %s\n",
opt_set_keyboard, error->message);
retval = 1;
goto out;
}
layout = eek_xml_layout_new (G_INPUT_STREAM(input));
g_object_unref (input);
keyboard = eek_keyboard_new (layout, 640, 480);
g_object_unref (layout);
keyboard_id = eekboard_context_add_keyboard (context, keyboard, NULL);
g_object_unref (keyboard);
eekboard_context_set_keyboard (context, keyboard_id, NULL);
}
if (opt_set_group >= 0) {
eekboard_context_set_group (context, opt_set_group, NULL);
}
if (opt_show_keyboard) {
eekboard_context_show_keyboard (context, NULL);
}
if (opt_hide_keyboard) {
eekboard_context_hide_keyboard (context, NULL);
}
if (opt_press_key >= 0) {
eekboard_context_press_key (context, opt_press_key, NULL);
}
if (opt_release_key >= 0) {
eekboard_context_release_key (context, opt_release_key, NULL);
}
if (opt_listen) {
g_signal_connect (context, "key-pressed",
G_CALLBACK(on_key_pressed), NULL);
g_signal_connect (context, "key-released",
G_CALLBACK(on_key_released), NULL);
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
}
out:
if (context)
g_object_unref (context);
if (connection)
g_object_unref (connection);
if (loop)
g_main_loop_unref (loop);
return retval;
}

View File

@ -1,7 +1,7 @@
src/server-server.c src/server-server.c
src/server-context.c src/server-context.c
src/client-main.c
src/desktop-client.c
src/desktop-client-main.c
src/xml-main.c
src/server-main.c src/server-main.c
src/client.c
src/client-main.c
src/xml-main.c
examples/simple-client/main.c

View File

@ -18,14 +18,13 @@
if ENABLE_EEKBOARD if ENABLE_EEKBOARD
bin_PROGRAMS = \ bin_PROGRAMS = \
eekboard-desktop-client \ eekboard \
eekboard-client \
eekboard-server \ eekboard-server \
eekboard-xml eekboard-xml
noinst_LTLIBRARIES = libxklutil.la noinst_LTLIBRARIES = libxklutil.la
eekboard_desktop_client_CFLAGS = \ eekboard_CFLAGS = \
-I$(top_srcdir) \ -I$(top_srcdir) \
$(GIO2_CFLAGS) \ $(GIO2_CFLAGS) \
$(GTK_CFLAGS) \ $(GTK_CFLAGS) \
@ -33,7 +32,7 @@ eekboard_desktop_client_CFLAGS = \
$(XKB_CFLAGS) \ $(XKB_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) $(LIBXKLAVIER_CFLAGS)
eekboard_desktop_client_LDADD = \ eekboard_LDADD = \
$(builddir)/libxklutil.la \ $(builddir)/libxklutil.la \
$(top_builddir)/eekboard/libeekboard.la \ $(top_builddir)/eekboard/libeekboard.la \
$(top_builddir)/eek/libeek.la \ $(top_builddir)/eek/libeek.la \
@ -45,21 +44,21 @@ eekboard_desktop_client_LDADD = \
$(LIBXKLAVIER_LIBS) $(LIBXKLAVIER_LIBS)
if ENABLE_FAKEKEY if ENABLE_FAKEKEY
eekboard_desktop_client_CFLAGS += \ eekboard_CFLAGS += \
$(FAKEKEY_CFLAGS) $(FAKEKEY_CFLAGS)
eekboard_desktop_client_LDADD += \ eekboard_LDADD += \
$(FAKEKEY_LIBS) $(FAKEKEY_LIBS)
endif endif
if ENABLE_CSPI if ENABLE_CSPI
eekboard_desktop_client_CFLAGS += \ eekboard_CFLAGS += \
$(CSPI_CFLAGS) $(CSPI_CFLAGS)
eekboard_desktop_client_LDADD += \ eekboard_LDADD += \
$(CSPI_LIBS) $(CSPI_LIBS)
endif endif
eekboard_desktop_client_headers = desktop-client.h eekboard_headers = client.h
eekboard_desktop_client_SOURCES = desktop-client.c desktop-client-main.c eekboard_SOURCES = client.c client-main.c
eekboard_server_CFLAGS = \ eekboard_server_CFLAGS = \
-I$(top_srcdir) \ -I$(top_srcdir) \
@ -82,17 +81,6 @@ endif
eekboard_server_headers = server-server.h server-context.h eekboard_server_headers = server-server.h server-context.h
eekboard_server_SOURCES = server-server.c server-context.c server-main.c eekboard_server_SOURCES = server-server.c server-context.c server-main.c
eekboard_client_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS)
eekboard_client_LDADD = \
$(top_builddir)/eekboard/libeekboard.la \
$(top_builddir)/eek/libeek.la \
$(GIO2_LIBS)
eekboard_client_SOURCES = client-main.c
eekboard_xml_CFLAGS = \ eekboard_xml_CFLAGS = \
-I$(top_srcdir) \ -I$(top_srcdir) \
$(GIO2_CFLAGS) \ $(GIO2_CFLAGS) \
@ -125,8 +113,7 @@ eekboard_HEADERS = \
$(libeekboard_headers) $(libeekboard_headers)
noinst_HEADERS = \ noinst_HEADERS = \
$(eekboard_desktop_client_headers) \ $(eekboard_headers) \
$(eekboard_client_headers) \
$(eekboard_server_headers) \ $(eekboard_server_headers) \
$(eekboard_xml_headers) \ $(eekboard_xml_headers) \
$(libxklutil_la_headers) $(libxklutil_la_headers)

View File

@ -20,21 +20,29 @@
#endif /* HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include <stdlib.h> #include <stdlib.h>
#include <cspi/spi.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <gconf/gconf-client.h>
#include "eekboard/eekboard.h" #include "eekboard/eekboard.h"
#include "client.h"
static gboolean opt_system = FALSE; static gboolean opt_system = FALSE;
static gboolean opt_session = FALSE; static gboolean opt_session = FALSE;
static gchar *opt_address = NULL; static gchar *opt_address = NULL;
static gchar *opt_set_keyboard = NULL; #ifdef HAVE_CSPI
static gint opt_set_group = -1; static gboolean opt_focus = FALSE;
static gboolean opt_show_keyboard = FALSE; static gboolean opt_keystroke = FALSE;
static gboolean opt_hide_keyboard = FALSE; #endif /* HAVE_CSPI */
static gint opt_press_key = -1;
static gint opt_release_key = -1; static gchar *opt_keyboard = NULL;
static gboolean opt_listen = FALSE;
static gchar *opt_model = NULL;
static gchar *opt_layouts = NULL;
static gchar *opt_options = NULL;
static gboolean opt_fullscreen = FALSE;
static const GOptionEntry options[] = { static const GOptionEntry options[] = {
{"system", 'y', 0, G_OPTION_ARG_NONE, &opt_system, {"system", 'y', 0, G_OPTION_ARG_NONE, &opt_system,
@ -43,51 +51,77 @@ static const GOptionEntry options[] = {
N_("Connect to the session bus")}, N_("Connect to the session bus")},
{"address", 'a', 0, G_OPTION_ARG_STRING, &opt_address, {"address", 'a', 0, G_OPTION_ARG_STRING, &opt_address,
N_("Connect to the given D-Bus address")}, N_("Connect to the given D-Bus address")},
{"set-keyboard", '\0', 0, G_OPTION_ARG_STRING, &opt_set_keyboard, #ifdef HAVE_CSPI
N_("Upload keyboard description from an XML file")}, {"listen-focus", 'f', 0, G_OPTION_ARG_NONE, &opt_focus,
{"set-group", '\0', 0, G_OPTION_ARG_INT, &opt_set_group, N_("Listen focus change events with AT-SPI")},
N_("Set group of the keyboard")}, {"listen-keystroke", 's', 0, G_OPTION_ARG_NONE, &opt_keystroke,
{"show-keyboard", '\0', 0, G_OPTION_ARG_NONE, &opt_show_keyboard, N_("Listen keystroke events with AT-SPI")},
N_("Show keyboard")}, #endif /* HAVE_CSPI */
{"hide-keyboard", '\0', 0, G_OPTION_ARG_NONE, &opt_hide_keyboard, {"keyboard", 'k', 0, G_OPTION_ARG_STRING, &opt_keyboard,
N_("Hide keyboard")}, N_("Specify keyboard file")},
{"press-key", '\0', 0, G_OPTION_ARG_INT, &opt_press_key, {"model", '\0', 0, G_OPTION_ARG_STRING, &opt_model,
N_("Press key")}, N_("Specify model")},
{"release-key", '\0', 0, G_OPTION_ARG_INT, &opt_release_key, {"layouts", '\0', 0, G_OPTION_ARG_STRING, &opt_layouts,
N_("Release key")}, N_("Specify layouts")},
{"listen", '\0', 0, G_OPTION_ARG_NONE, &opt_listen, {"options", '\0', 0, G_OPTION_ARG_STRING, &opt_options,
N_("Listen events")}, N_("Specify options")},
{"fullscreen", 'F', 0, G_OPTION_ARG_NONE, &opt_fullscreen,
N_("Create window in fullscreen mode")},
{NULL} {NULL}
}; };
static void static void
on_key_pressed (guint keycode, gpointer user_data) on_notify_keyboard_visible (GObject *object,
GParamSpec *spec,
gpointer user_data)
{ {
g_print ("KeyPressed %u\n", keycode); GMainLoop *loop = user_data;
gboolean visible;
g_object_get (object, "keyboard-visible", &visible, NULL);
/* user explicitly closed the window */
if (!visible && eekboard_context_is_enabled (EEKBOARD_CONTEXT(object)))
g_main_loop_quit (loop);
} }
static void static void
on_key_released (guint keycode, gpointer user_data) on_context_destroyed (EekboardContext *context,
gpointer user_data)
{ {
g_print ("KeyReleased %u\n", keycode); GMainLoop *loop = user_data;
g_main_loop_quit (loop);
}
static void
on_destroyed (EekboardEekboard *eekboard,
gpointer user_data)
{
GMainLoop *loop = user_data;
g_main_loop_quit (loop);
} }
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
EekboardEekboard *eekboard = NULL; EekboardClient *client;
EekboardContext *context = NULL; EekboardEekboard *eekboard;
EekboardContext *context;
GBusType bus_type; GBusType bus_type;
GDBusConnection *connection = NULL; GDBusConnection *connection;
GError *error; GError *error;
GConfClient *gconfc;
GOptionContext *option_context; GOptionContext *option_context;
GMainLoop *loop = NULL; GMainLoop *loop;
gint retval = 0;
g_type_init (); if (!gtk_init_check (&argc, &argv)) {
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); g_printerr ("Can't init GTK\n");
exit (1);
}
option_context = g_option_context_new ("eekboard-client"); option_context = g_option_context_new ("eekboard-desktop-client");
g_option_context_add_main_entries (option_context, options, NULL); g_option_context_add_main_entries (option_context, options, NULL);
g_option_context_parse (option_context, &argc, &argv, NULL); g_option_context_parse (option_context, &argc, &argv, NULL);
g_option_context_free (option_context); g_option_context_free (option_context);
@ -128,90 +162,98 @@ main (int argc, char **argv)
break; break;
} }
eekboard = eekboard_eekboard_new (connection, NULL); client = eekboard_client_new (connection);
if (eekboard == NULL) { if (client == NULL) {
g_printerr ("Can't create eekboard proxy\n"); g_printerr ("Can't create a client\n");
retval = 1; exit (1);
goto out;
} }
context = eekboard_eekboard_create_context (eekboard, gconfc = gconf_client_get_default ();
"eekboard-client",
NULL);
if (context == NULL) {
g_printerr ("Can't create context\n");
retval = 1;
goto out;
}
eekboard_eekboard_push_context (eekboard, context, NULL); #ifdef HAVE_CSPI
error = NULL;
if (opt_focus || opt_keystroke) {
if (gconf_client_get_bool (gconfc,
"/desktop/gnome/interface/accessibility",
&error) ||
gconf_client_get_bool (gconfc,
"/desktop/gnome/interface/accessibility2",
&error)) {
if (SPI_init () != 0) {
g_printerr ("Can't init CSPI\n");
exit (1);
}
if (opt_set_keyboard) { if (opt_focus &&
GFile *file; !eekboard_client_enable_cspi_focus (client)) {
GFileInputStream *input; g_printerr ("Can't register focus change event listeners\n");
EekLayout *layout; exit (1);
EekKeyboard *keyboard; }
guint keyboard_id;
file = g_file_new_for_path (opt_set_keyboard); if (opt_keystroke &&
!eekboard_client_enable_cspi_keystroke (client)) {
error = NULL; g_printerr ("Can't register keystroke event listeners\n");
input = g_file_read (file, NULL, &error); exit (1);
if (error) { }
g_printerr ("Can't read file %s: %s\n", } else {
opt_set_keyboard, error->message); g_printerr ("Desktop accessibility support is disabled\n");
retval = 1; exit (1);
goto out;
} }
}
#endif /* HAVE_CSPI */
layout = eek_xml_layout_new (G_INPUT_STREAM(input)); if (opt_keyboard && (opt_model || opt_layouts || opt_options)) {
g_object_unref (input); g_printerr ("Can't use --keyboard option with xklavier options\n");
keyboard = eek_keyboard_new (layout, 640, 480); exit (1);
g_object_unref (layout);
keyboard_id = eekboard_context_add_keyboard (context, keyboard, NULL);
g_object_unref (keyboard);
eekboard_context_set_keyboard (context, keyboard_id, NULL);
} }
if (opt_set_group >= 0) { if (opt_keyboard) {
eekboard_context_set_group (context, opt_set_group, NULL); if (!eekboard_client_load_keyboard_from_file (client, opt_keyboard)) {
g_printerr ("Can't load keyboard\n");
exit (1);
}
} else if (opt_model || opt_layouts || opt_options) {
if (!eekboard_client_set_xkl_config (client,
opt_model,
opt_layouts,
opt_options)) {
g_printerr ("Can't set xklavier config\n");
exit (1);
}
} else if (!eekboard_client_enable_xkl (client)) {
g_printerr ("Can't register xklavier event listeners\n");
exit (1);
} }
if (opt_show_keyboard) { #ifdef HAVE_FAKEKEY
eekboard_context_show_keyboard (context, NULL); if (!eekboard_client_enable_fakekey (client)) {
g_printerr ("Can't init fakekey\n");
exit (1);
} }
#endif /* HAVE_FAKEKEY */
if (opt_hide_keyboard) { loop = g_main_loop_new (NULL, FALSE);
eekboard_context_hide_keyboard (context, NULL); if (!opt_focus) {
} g_object_get (client, "context", &context, NULL);
g_signal_connect (context, "notify::keyboard-visible",
if (opt_press_key >= 0) { G_CALLBACK(on_notify_keyboard_visible), loop);
eekboard_context_press_key (context, opt_press_key, NULL); g_signal_connect (context, "destroyed",
} G_CALLBACK(on_context_destroyed), loop);
if (opt_release_key >= 0) {
eekboard_context_release_key (context, opt_release_key, NULL);
}
if (opt_listen) {
g_signal_connect (context, "key-pressed",
G_CALLBACK(on_key_pressed), NULL);
g_signal_connect (context, "key-released",
G_CALLBACK(on_key_released), NULL);
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
}
out:
if (context)
g_object_unref (context); g_object_unref (context);
if (connection) }
g_object_unref (connection);
if (loop)
g_main_loop_unref (loop);
return retval; if (opt_fullscreen) {
g_object_get (client, "context", &context, NULL);
eekboard_context_set_fullscreen (context, TRUE, NULL);
g_object_unref (context);
}
g_object_get (client, "eekboard", &eekboard, NULL);
g_signal_connect (eekboard, "destroyed",
G_CALLBACK(on_destroyed), loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
return 0;
} }

View File

@ -34,7 +34,7 @@
#include "eek/eek.h" #include "eek/eek.h"
#include "eek/eek-xkl.h" #include "eek/eek-xkl.h"
#include "eekboard/eekboard.h" #include "eekboard/eekboard.h"
#include "desktop-client.h" #include "client.h"
#include "xklutil.h" #include "xklutil.h"
#define CSW 640 #define CSW 640
@ -48,9 +48,9 @@ enum {
PROP_LAST PROP_LAST
}; };
typedef struct _EekboardDesktopClientClass EekboardDesktopClientClass; typedef struct _EekboardClientClass EekboardClientClass;
struct _EekboardDesktopClient { struct _EekboardClient {
GObject parent; GObject parent;
EekboardEekboard *eekboard; EekboardEekboard *eekboard;
@ -78,11 +78,11 @@ struct _EekboardDesktopClient {
#endif /* HAVE_FAKEKEY */ #endif /* HAVE_FAKEKEY */
}; };
struct _EekboardDesktopClientClass { struct _EekboardClientClass {
GObjectClass parent_class; GObjectClass parent_class;
}; };
G_DEFINE_TYPE (EekboardDesktopClient, eekboard_desktop_client, G_TYPE_OBJECT); G_DEFINE_TYPE (EekboardClient, eekboard_client, G_TYPE_OBJECT);
static GdkFilterReturn filter_xkl_event (GdkXEvent *xev, static GdkFilterReturn filter_xkl_event (GdkXEvent *xev,
GdkEvent *event, GdkEvent *event,
@ -106,19 +106,22 @@ static SPIBoolean keystroke_listener_cb
(const AccessibleKeystroke *stroke, (const AccessibleKeystroke *stroke,
void *user_data); void *user_data);
#endif /* HAVE_CSPI */ #endif /* HAVE_CSPI */
static gboolean set_keyboard (EekboardDesktopClient *client, static gboolean set_keyboard (EekboardClient *client,
gboolean show,
EekLayout *layout);
static gboolean set_xkl_keyboard (EekboardClient *client,
gboolean show, gboolean show,
const gchar *model, const gchar *model,
const gchar *layouts, const gchar *layouts,
const gchar *options); const gchar *options);
static void static void
eekboard_desktop_client_set_property (GObject *object, eekboard_client_set_property (GObject *object,
guint prop_id, guint prop_id,
const GValue *value, const GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
EekboardDesktopClient *client = EEKBOARD_DESKTOP_CLIENT(object); EekboardClient *client = EEKBOARD_CLIENT(object);
GDBusConnection *connection; GDBusConnection *connection;
switch (prop_id) { switch (prop_id) {
@ -129,7 +132,7 @@ eekboard_desktop_client_set_property (GObject *object,
if (client->eekboard != NULL) { if (client->eekboard != NULL) {
client->context = client->context =
eekboard_eekboard_create_context (client->eekboard, eekboard_eekboard_create_context (client->eekboard,
"eekboard-desktop-client", "eekboard",
NULL); NULL);
if (client->context == NULL) { if (client->context == NULL) {
g_object_unref (client->eekboard); g_object_unref (client->eekboard);
@ -149,12 +152,12 @@ eekboard_desktop_client_set_property (GObject *object,
} }
static void static void
eekboard_desktop_client_get_property (GObject *object, eekboard_client_get_property (GObject *object,
guint prop_id, guint prop_id,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
EekboardDesktopClient *client = EEKBOARD_DESKTOP_CLIENT(object); EekboardClient *client = EEKBOARD_CLIENT(object);
switch (prop_id) { switch (prop_id) {
case PROP_EEKBOARD: case PROP_EEKBOARD:
@ -172,19 +175,19 @@ eekboard_desktop_client_get_property (GObject *object,
} }
static void static void
eekboard_desktop_client_dispose (GObject *object) eekboard_client_dispose (GObject *object)
{ {
EekboardDesktopClient *client = EEKBOARD_DESKTOP_CLIENT(object); EekboardClient *client = EEKBOARD_CLIENT(object);
eekboard_desktop_client_disable_xkl (client); eekboard_client_disable_xkl (client);
#ifdef HAVE_CSPI #ifdef HAVE_CSPI
eekboard_desktop_client_disable_cspi_focus (client); eekboard_client_disable_cspi_focus (client);
eekboard_desktop_client_disable_cspi_keystroke (client); eekboard_client_disable_cspi_keystroke (client);
#endif /* HAVE_CSPI */ #endif /* HAVE_CSPI */
#ifdef HAVE_FAKEKEY #ifdef HAVE_FAKEKEY
eekboard_desktop_client_disable_fakekey (client); eekboard_client_disable_fakekey (client);
#endif /* HAVE_FAKEKEY */ #endif /* HAVE_FAKEKEY */
if (client->context) { if (client->context) {
@ -217,18 +220,18 @@ eekboard_desktop_client_dispose (GObject *object)
client->display = NULL; client->display = NULL;
} }
G_OBJECT_CLASS (eekboard_desktop_client_parent_class)->dispose (object); G_OBJECT_CLASS (eekboard_client_parent_class)->dispose (object);
} }
static void static void
eekboard_desktop_client_class_init (EekboardDesktopClientClass *klass) eekboard_client_class_init (EekboardClientClass *klass)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec; GParamSpec *pspec;
gobject_class->set_property = eekboard_desktop_client_set_property; gobject_class->set_property = eekboard_client_set_property;
gobject_class->get_property = eekboard_desktop_client_get_property; gobject_class->get_property = eekboard_client_get_property;
gobject_class->dispose = eekboard_desktop_client_dispose; gobject_class->dispose = eekboard_client_dispose;
pspec = g_param_spec_object ("connection", pspec = g_param_spec_object ("connection",
"Connection", "Connection",
@ -259,7 +262,7 @@ eekboard_desktop_client_class_init (EekboardDesktopClientClass *klass)
} }
static void static void
eekboard_desktop_client_init (EekboardDesktopClient *client) eekboard_client_init (EekboardClient *client)
{ {
client->eekboard = NULL; client->eekboard = NULL;
client->context = NULL; client->context = NULL;
@ -281,28 +284,28 @@ eekboard_desktop_client_init (EekboardDesktopClient *client)
} }
gboolean gboolean
eekboard_desktop_client_set_xkl_config (EekboardDesktopClient *client, eekboard_client_set_xkl_config (EekboardClient *client,
const gchar *model, const gchar *model,
const gchar *layouts, const gchar *layouts,
const gchar *options) const gchar *options)
{ {
#ifdef HAVE_CSPI #ifdef HAVE_CSPI
return set_keyboard (client, return set_xkl_keyboard (client,
client->focus_listener ? FALSE : TRUE, client->focus_listener ? FALSE : TRUE,
model, model,
layouts, layouts,
options); options);
#else #else
return set_keyboard (client, return set_xkl_keyboard (client,
TRUE, TRUE,
model, model,
layouts, layouts,
options); options);
#endif #endif
} }
gboolean gboolean
eekboard_desktop_client_enable_xkl (EekboardDesktopClient *client) eekboard_client_enable_xkl (EekboardClient *client)
{ {
if (!client->display) { if (!client->display) {
client->display = gdk_display_get_default (); client->display = gdk_display_get_default ();
@ -338,15 +341,18 @@ eekboard_desktop_client_enable_xkl (EekboardDesktopClient *client)
xkl_engine_start_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE); xkl_engine_start_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
#ifdef HAVE_CSPI #ifdef HAVE_CSPI
return set_keyboard (client, client->focus_listener ? FALSE : TRUE, return set_xkl_keyboard (client,
NULL, NULL, NULL); client->focus_listener ? FALSE : TRUE,
NULL,
NULL,
NULL);
#else #else
return set_keyboard (client, TRUE, NULL, NULL, NULL); return set_xkl_keyboard (client, TRUE, NULL, NULL, NULL);
#endif #endif
} }
void void
eekboard_desktop_client_disable_xkl (EekboardDesktopClient *client) eekboard_client_disable_xkl (EekboardClient *client)
{ {
if (client->xkl_engine) if (client->xkl_engine)
xkl_engine_stop_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE); xkl_engine_stop_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
@ -362,7 +368,7 @@ eekboard_desktop_client_disable_xkl (EekboardDesktopClient *client)
#ifdef HAVE_CSPI #ifdef HAVE_CSPI
gboolean gboolean
eekboard_desktop_client_enable_cspi_focus (EekboardDesktopClient *client) eekboard_client_enable_cspi_focus (EekboardClient *client)
{ {
client->focus_listener = SPI_createAccessibleEventListener client->focus_listener = SPI_createAccessibleEventListener
((AccessibleEventListenerCB)focus_listener_cb, ((AccessibleEventListenerCB)focus_listener_cb,
@ -380,7 +386,7 @@ eekboard_desktop_client_enable_cspi_focus (EekboardDesktopClient *client)
} }
void void
eekboard_desktop_client_disable_cspi_focus (EekboardDesktopClient *client) eekboard_client_disable_cspi_focus (EekboardClient *client)
{ {
if (client->focus_listener) { if (client->focus_listener) {
SPI_deregisterGlobalEventListenerAll (client->focus_listener); SPI_deregisterGlobalEventListenerAll (client->focus_listener);
@ -390,7 +396,7 @@ eekboard_desktop_client_disable_cspi_focus (EekboardDesktopClient *client)
} }
gboolean gboolean
eekboard_desktop_client_enable_cspi_keystroke (EekboardDesktopClient *client) eekboard_client_enable_cspi_keystroke (EekboardClient *client)
{ {
client->keystroke_listener = client->keystroke_listener =
SPI_createAccessibleKeystrokeListener (keystroke_listener_cb, SPI_createAccessibleKeystrokeListener (keystroke_listener_cb,
@ -408,7 +414,7 @@ eekboard_desktop_client_enable_cspi_keystroke (EekboardDesktopClient *client)
} }
void void
eekboard_desktop_client_disable_cspi_keystroke (EekboardDesktopClient *client) eekboard_client_disable_cspi_keystroke (EekboardClient *client)
{ {
if (client->keystroke_listener) { if (client->keystroke_listener) {
SPI_deregisterAccessibleKeystrokeListener (client->keystroke_listener, SPI_deregisterAccessibleKeystrokeListener (client->keystroke_listener,
@ -422,7 +428,7 @@ static SPIBoolean
focus_listener_cb (const AccessibleEvent *event, focus_listener_cb (const AccessibleEvent *event,
void *user_data) void *user_data)
{ {
EekboardDesktopClient *client = user_data; EekboardClient *client = user_data;
Accessible *accessible = event->source; Accessible *accessible = event->source;
AccessibleStateSet *state_set = Accessible_getStateSet (accessible); AccessibleStateSet *state_set = Accessible_getStateSet (accessible);
AccessibleRole role = Accessible_getRole (accessible); AccessibleRole role = Accessible_getRole (accessible);
@ -466,7 +472,7 @@ static SPIBoolean
keystroke_listener_cb (const AccessibleKeystroke *stroke, keystroke_listener_cb (const AccessibleKeystroke *stroke,
void *user_data) void *user_data)
{ {
EekboardDesktopClient *client = user_data; EekboardClient *client = user_data;
EekKey *key; EekKey *key;
/* Ignore modifiers since the keystroke listener does not called /* Ignore modifiers since the keystroke listener does not called
@ -489,10 +495,10 @@ keystroke_listener_cb (const AccessibleKeystroke *stroke,
} }
#endif /* HAVE_CSPI */ #endif /* HAVE_CSPI */
EekboardDesktopClient * EekboardClient *
eekboard_desktop_client_new (GDBusConnection *connection) eekboard_client_new (GDBusConnection *connection)
{ {
EekboardDesktopClient *client = g_object_new (EEKBOARD_TYPE_DESKTOP_CLIENT, EekboardClient *client = g_object_new (EEKBOARD_TYPE_CLIENT,
"connection", connection, "connection", connection,
NULL); NULL);
if (client->context) if (client->context)
@ -505,7 +511,7 @@ filter_xkl_event (GdkXEvent *xev,
GdkEvent *event, GdkEvent *event,
gpointer user_data) gpointer user_data)
{ {
EekboardDesktopClient *client = user_data; EekboardClient *client = user_data;
XEvent *xevent = (XEvent *)xev; XEvent *xevent = (XEvent *)xev;
xkl_engine_filter_events (client->xkl_engine, xevent); xkl_engine_filter_events (client->xkl_engine, xevent);
@ -516,10 +522,10 @@ static void
on_xkl_config_changed (XklEngine *xklengine, on_xkl_config_changed (XklEngine *xklengine,
gpointer user_data) gpointer user_data)
{ {
EekboardDesktopClient *client = user_data; EekboardClient *client = user_data;
gboolean retval; gboolean retval;
retval = set_keyboard (client, FALSE, NULL, NULL, NULL); retval = set_xkl_keyboard (client, FALSE, NULL, NULL, NULL);
g_return_if_fail (retval); g_return_if_fail (retval);
#ifdef HAVE_FAKEKEY #ifdef HAVE_FAKEKEY
@ -529,17 +535,41 @@ on_xkl_config_changed (XklEngine *xklengine,
} }
static gboolean static gboolean
set_keyboard (EekboardDesktopClient *client, set_keyboard (EekboardClient *client,
gboolean show, gboolean show,
const gchar *model, EekLayout *layout)
const gchar *layouts,
const gchar *options)
{ {
EekLayout *layout;
gchar *keyboard_name; gchar *keyboard_name;
static gint keyboard_serial = 0; static gint keyboard_serial = 0;
guint keyboard_id; guint keyboard_id;
client->keyboard = eek_keyboard_new (layout, CSW, CSH);
eek_keyboard_set_modifier_behavior (client->keyboard,
EEK_MODIFIER_BEHAVIOR_LATCH);
keyboard_name = g_strdup_printf ("keyboard%d", keyboard_serial++);
eek_element_set_name (EEK_ELEMENT(client->keyboard), keyboard_name);
g_free (keyboard_name);
keyboard_id = eekboard_context_add_keyboard (client->context,
client->keyboard,
NULL);
eekboard_context_set_keyboard (client->context, keyboard_id, NULL);
if (show)
eekboard_context_show_keyboard (client->context, NULL);
return TRUE;
}
static gboolean
set_xkl_keyboard (EekboardClient *client,
gboolean show,
const gchar *model,
const gchar *layouts,
const gchar *options)
{
EekLayout *layout;
gboolean retval;
if (client->keyboard) if (client->keyboard)
g_object_unref (client->keyboard); g_object_unref (client->keyboard);
layout = eek_xkl_layout_new (); layout = eek_xkl_layout_new ();
@ -583,22 +613,9 @@ set_keyboard (EekboardDesktopClient *client,
} }
} }
client->keyboard = eek_keyboard_new (layout, CSW, CSH); retval = set_keyboard (client, show, layout);
eek_keyboard_set_modifier_behavior (client->keyboard, g_object_unref (layout);
EEK_MODIFIER_BEHAVIOR_LATCH); return retval;
keyboard_name = g_strdup_printf ("keyboard%d", keyboard_serial++);
eek_element_set_name (EEK_ELEMENT(client->keyboard), keyboard_name);
g_free (keyboard_name);
keyboard_id = eekboard_context_add_keyboard (client->context,
client->keyboard,
NULL);
eekboard_context_set_keyboard (client->context, keyboard_id, NULL);
if (show)
eekboard_context_show_keyboard (client->context, NULL);
return TRUE;
} }
static void static void
@ -608,7 +625,7 @@ on_xkl_state_changed (XklEngine *xklengine,
gboolean restore, gboolean restore,
gpointer user_data) gpointer user_data)
{ {
EekboardDesktopClient *client = user_data; EekboardClient *client = user_data;
if (type == GROUP_CHANGED && client->keyboard) { if (type == GROUP_CHANGED && client->keyboard) {
gint group = eek_element_get_group (EEK_ELEMENT(client->keyboard)); gint group = eek_element_get_group (EEK_ELEMENT(client->keyboard));
@ -641,7 +658,7 @@ on_key_pressed (EekKeyboard *keyboard,
EekKey *key, EekKey *key,
gpointer user_data) gpointer user_data)
{ {
EekboardDesktopClient *client = user_data; EekboardClient *client = user_data;
EekSymbol *symbol; EekSymbol *symbol;
g_assert (client->fakekey); g_assert (client->fakekey);
@ -671,14 +688,14 @@ on_key_released (EekKeyboard *keyboard,
EekKey *key, EekKey *key,
gpointer user_data) gpointer user_data)
{ {
EekboardDesktopClient *client = user_data; EekboardClient *client = user_data;
g_assert (client->fakekey); g_assert (client->fakekey);
fakekey_release (client->fakekey); fakekey_release (client->fakekey);
} }
gboolean gboolean
eekboard_desktop_client_enable_fakekey (EekboardDesktopClient *client) eekboard_client_enable_fakekey (EekboardClient *client)
{ {
if (!client->display) { if (!client->display) {
client->display = gdk_display_get_default (); client->display = gdk_display_get_default ();
@ -701,7 +718,7 @@ eekboard_desktop_client_enable_fakekey (EekboardDesktopClient *client)
} }
void void
eekboard_desktop_client_disable_fakekey (EekboardDesktopClient *client) eekboard_client_disable_fakekey (EekboardClient *client)
{ {
if (client->fakekey) if (client->fakekey)
fakekey_release (client->fakekey); fakekey_release (client->fakekey);
@ -715,4 +732,31 @@ eekboard_desktop_client_disable_fakekey (EekboardDesktopClient *client)
g_signal_handler_disconnect (client->keyboard, g_signal_handler_disconnect (client->keyboard,
client->key_released_handler); client->key_released_handler);
} }
gboolean
eekboard_client_load_keyboard_from_file (EekboardClient *client,
const gchar *keyboard_file)
{
GFile *file;
GFileInputStream *input;
GError *error;
EekLayout *layout;
EekKeyboard *keyboard;
guint keyboard_id;
gboolean retval;
file = g_file_new_for_path (keyboard_file);
error = NULL;
input = g_file_read (file, NULL, &error);
if (input == NULL)
return FALSE;
layout = eek_xml_layout_new (G_INPUT_STREAM(input));
g_object_unref (input);
retval = set_keyboard (client, TRUE, layout);
g_object_unref (layout);
return retval;
}
#endif /* HAVE_FAKEKEY */ #endif /* HAVE_FAKEKEY */

61
src/client.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 program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EEKBOARD_CLIENT_H
#define EEKBOARD_CLIENT_H 1
#include <gio/gio.h>
G_BEGIN_DECLS
#define EEKBOARD_TYPE_CLIENT (eekboard_client_get_type())
#define EEKBOARD_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_CLIENT, EekboardClient))
#define EEKBOARD_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_CLIENT, EekboardClientClass))
#define EEKBOARD_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_CLIENT))
#define EEKBOARD_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_CLIENT))
#define EEKBOARD_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_CLIENT, EekboardClientClass))
typedef struct _EekboardClient EekboardClient;
EekboardClient * eekboard_client_new (GDBusConnection *connection);
gboolean eekboard_client_load_keyboard_from_file
(EekboardClient *client,
const gchar *file);
gboolean eekboard_client_set_xkl_config (EekboardClient *client,
const gchar *model,
const gchar *layouts,
const gchar *options);
gboolean eekboard_client_enable_xkl (EekboardClient *client);
void eekboard_client_disable_xkl (EekboardClient *client);
gboolean eekboard_client_enable_cspi_focus
(EekboardClient *client);
void eekboard_client_disable_cspi_focus
(EekboardClient *client);
gboolean eekboard_client_enable_cspi_keystroke
(EekboardClient *client);
void eekboard_client_disable_cspi_keystroke
(EekboardClient *client);
gboolean eekboard_client_enable_fakekey (EekboardClient *client);
void eekboard_client_disable_fakekey (EekboardClient *client);
G_END_DECLS
#endif /* EEKBOARD_CLIENT_H */

View File

@ -1,245 +0,0 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include <cspi/spi.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gconf/gconf-client.h>
#include "eekboard/eekboard.h"
#include "desktop-client.h"
static gboolean opt_system = FALSE;
static gboolean opt_session = FALSE;
static gchar *opt_address = NULL;
#ifdef HAVE_CSPI
static gboolean opt_focus = FALSE;
static gboolean opt_keystroke = FALSE;
#endif /* HAVE_CSPI */
static gchar *opt_model = NULL;
static gchar *opt_layouts = NULL;
static gchar *opt_options = NULL;
static gboolean opt_fullscreen = FALSE;
static const GOptionEntry options[] = {
{"system", 'y', 0, G_OPTION_ARG_NONE, &opt_system,
N_("Connect to the system bus")},
{"session", 'e', 0, G_OPTION_ARG_NONE, &opt_session,
N_("Connect to the session bus")},
{"address", 'a', 0, G_OPTION_ARG_STRING, &opt_address,
N_("Connect to the given D-Bus address")},
#ifdef HAVE_CSPI
{"listen-focus", 'f', 0, G_OPTION_ARG_NONE, &opt_focus,
N_("Listen focus change events with AT-SPI")},
{"listen-keystroke", 's', 0, G_OPTION_ARG_NONE, &opt_keystroke,
N_("Listen keystroke events with AT-SPI")},
#endif /* HAVE_CSPI */
{"model", '\0', 0, G_OPTION_ARG_STRING, &opt_model,
N_("Specify model")},
{"layouts", '\0', 0, G_OPTION_ARG_STRING, &opt_layouts,
N_("Specify layouts")},
{"options", '\0', 0, G_OPTION_ARG_STRING, &opt_options,
N_("Specify options")},
{"fullscreen", 'F', 0, G_OPTION_ARG_NONE, &opt_fullscreen,
N_("Create window in fullscreen mode")},
{NULL}
};
static void
on_notify_keyboard_visible (GObject *object,
GParamSpec *spec,
gpointer user_data)
{
GMainLoop *loop = user_data;
gboolean visible;
g_object_get (object, "keyboard-visible", &visible, NULL);
/* user explicitly closed the window */
if (!visible && eekboard_context_is_enabled (EEKBOARD_CONTEXT(object)))
g_main_loop_quit (loop);
}
static void
on_context_destroyed (EekboardContext *context,
gpointer user_data)
{
GMainLoop *loop = user_data;
g_main_loop_quit (loop);
}
static void
on_destroyed (EekboardEekboard *eekboard,
gpointer user_data)
{
GMainLoop *loop = user_data;
g_main_loop_quit (loop);
}
int
main (int argc, char **argv)
{
EekboardDesktopClient *client;
EekboardEekboard *eekboard;
EekboardContext *context;
GBusType bus_type;
GDBusConnection *connection;
GError *error;
GConfClient *gconfc;
GOptionContext *option_context;
GMainLoop *loop;
if (!gtk_init_check (&argc, &argv)) {
g_printerr ("Can't init GTK\n");
exit (1);
}
option_context = g_option_context_new ("eekboard-desktop-client");
g_option_context_add_main_entries (option_context, options, NULL);
g_option_context_parse (option_context, &argc, &argv, NULL);
g_option_context_free (option_context);
if (opt_system)
bus_type = G_BUS_TYPE_SYSTEM;
else if (opt_address)
bus_type = G_BUS_TYPE_NONE;
else
bus_type = G_BUS_TYPE_SESSION;
switch (bus_type) {
case G_BUS_TYPE_SYSTEM:
case G_BUS_TYPE_SESSION:
error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (connection == NULL) {
g_printerr ("Can't connect to the bus: %s\n", error->message);
exit (1);
}
break;
case G_BUS_TYPE_NONE:
error = NULL;
connection = g_dbus_connection_new_for_address_sync (opt_address,
0,
NULL,
NULL,
&error);
if (connection == NULL) {
g_printerr ("Can't connect to the bus at %s: %s\n",
opt_address,
error->message);
exit (1);
}
break;
default:
g_assert_not_reached ();
break;
}
client = eekboard_desktop_client_new (connection);
if (client == NULL) {
g_printerr ("Can't create a client\n");
exit (1);
}
gconfc = gconf_client_get_default ();
#ifdef HAVE_CSPI
error = NULL;
if (opt_focus || opt_keystroke) {
if (gconf_client_get_bool (gconfc,
"/desktop/gnome/interface/accessibility",
&error) ||
gconf_client_get_bool (gconfc,
"/desktop/gnome/interface/accessibility2",
&error)) {
if (SPI_init () != 0) {
g_printerr ("Can't init CSPI\n");
exit (1);
}
if (opt_focus &&
!eekboard_desktop_client_enable_cspi_focus (client)) {
g_printerr ("Can't register focus change event listeners\n");
exit (1);
}
if (opt_keystroke &&
!eekboard_desktop_client_enable_cspi_keystroke (client)) {
g_printerr ("Can't register keystroke event listeners\n");
exit (1);
}
} else {
g_printerr ("Desktop accessibility support is disabled\n");
exit (1);
}
}
#endif /* HAVE_CSPI */
if (opt_model || opt_layouts || opt_options) {
if (!eekboard_desktop_client_set_xkl_config (client,
opt_model,
opt_layouts,
opt_options)) {
g_printerr ("Can't set xklavier config\n");
exit (1);
}
} else if (!eekboard_desktop_client_enable_xkl (client)) {
g_printerr ("Can't register xklavier event listeners\n");
exit (1);
}
#ifdef HAVE_FAKEKEY
if (!eekboard_desktop_client_enable_fakekey (client)) {
g_printerr ("Can't init fakekey\n");
exit (1);
}
#endif /* HAVE_FAKEKEY */
loop = g_main_loop_new (NULL, FALSE);
if (!opt_focus) {
g_object_get (client, "context", &context, NULL);
g_signal_connect (context, "notify::keyboard-visible",
G_CALLBACK(on_notify_keyboard_visible), loop);
g_signal_connect (context, "destroyed",
G_CALLBACK(on_context_destroyed), loop);
g_object_unref (context);
}
if (opt_fullscreen) {
g_object_get (client, "context", &context, NULL);
eekboard_context_set_fullscreen (context, TRUE, NULL);
g_object_unref (context);
}
g_object_get (client, "eekboard", &eekboard, NULL);
g_signal_connect (eekboard, "destroyed",
G_CALLBACK(on_destroyed), loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
return 0;
}

View File

@ -1,64 +0,0 @@
/*
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2010-2011 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EEKBOARD_DESKTOP_CLIENT_H
#define EEKBOARD_DESKTOP_CLIENT_H 1
#include <gio/gio.h>
G_BEGIN_DECLS
#define EEKBOARD_TYPE_DESKTOP_CLIENT (eekboard_desktop_client_get_type())
#define EEKBOARD_DESKTOP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_DESKTOP_CLIENT, EekboardDesktopClient))
#define EEKBOARD_DESKTOP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_DESKTOP_CLIENT, EekboardDesktopClientClass))
#define EEKBOARD_IS_DESKTOP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_DESKTOP_CLIENT))
#define EEKBOARD_IS_DESKTOP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_DESKTOP_CLIENT))
#define EEKBOARD_DESKTOP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_DESKTOP_CLIENT, EekboardDesktopClientClass))
typedef struct _EekboardDesktopClient EekboardDesktopClient;
EekboardDesktopClient * eekboard_desktop_client_new
(GDBusConnection *connection);
gboolean eekboard_desktop_client_set_xkl_config
(EekboardDesktopClient *client,
const gchar *model,
const gchar *layouts,
const gchar *options);
gboolean eekboard_desktop_client_enable_xkl
(EekboardDesktopClient *client);
void eekboard_desktop_client_disable_xkl
(EekboardDesktopClient *client);
gboolean eekboard_desktop_client_enable_cspi_focus
(EekboardDesktopClient *client);
void eekboard_desktop_client_disable_cspi_focus
(EekboardDesktopClient *client);
gboolean eekboard_desktop_client_enable_cspi_keystroke
(EekboardDesktopClient *client);
void eekboard_desktop_client_disable_cspi_keystroke
(EekboardDesktopClient *client);
gboolean eekboard_desktop_client_enable_fakekey
(EekboardDesktopClient *client);
void eekboard_desktop_client_disable_fakekey
(EekboardDesktopClient *client);
G_END_DECLS
#endif /* EEKBOARD_DESKTOP_CLIENT_H */

View File

@ -94,6 +94,7 @@ struct _ServerContext {
guint registration_id; guint registration_id;
char *object_path; char *object_path;
char *client_connection; char *client_connection;
char *client_name;
gboolean enabled; gboolean enabled;
gboolean last_keyboard_visible; gboolean last_keyboard_visible;
@ -285,7 +286,10 @@ update_widget (ServerContext *context)
gtk_widget_set_can_focus (context->window, FALSE); gtk_widget_set_can_focus (context->window, FALSE);
g_object_set (G_OBJECT(context->window), "accept_focus", FALSE, NULL); g_object_set (G_OBJECT(context->window), "accept_focus", FALSE, NULL);
gtk_window_set_title (GTK_WINDOW(context->window), _("Keyboard")); gtk_window_set_title (GTK_WINDOW(context->window),
context->client_name ?
context->client_name :
_("Keyboard"));
gtk_window_set_icon_name (GTK_WINDOW(context->window), "eekboard"); gtk_window_set_icon_name (GTK_WINDOW(context->window), "eekboard");
gtk_window_set_keep_above (GTK_WINDOW(context->window), TRUE); gtk_window_set_keep_above (GTK_WINDOW(context->window), TRUE);
@ -372,6 +376,7 @@ server_context_finalize (GObject *object)
g_free (context->object_path); g_free (context->object_path);
g_free (context->client_connection); g_free (context->client_connection);
g_free (context->client_name);
G_OBJECT_CLASS (server_context_parent_class)->finalize (object); G_OBJECT_CLASS (server_context_parent_class)->finalize (object);
} }
@ -797,6 +802,7 @@ void
server_context_set_client_connection (ServerContext *context, server_context_set_client_connection (ServerContext *context,
const gchar *client_connection) const gchar *client_connection)
{ {
g_free (context->client_connection);
context->client_connection = g_strdup (client_connection); context->client_connection = g_strdup (client_connection);
} }
@ -805,3 +811,11 @@ server_context_get_client_connection (ServerContext *context)
{ {
return context->client_connection; return context->client_connection;
} }
void
server_context_set_client_name (ServerContext *context,
const gchar *client_name)
{
g_free (context->client_name);
context->client_name = g_strdup (client_name);
}

View File

@ -43,6 +43,9 @@ void server_context_set_client_connection
const gchar *client_connection); const gchar *client_connection);
const gchar *server_context_get_client_connection const gchar *server_context_get_client_connection
(ServerContext *context); (ServerContext *context);
void server_context_set_client_name
(ServerContext *context,
const gchar *client_name);
G_END_DECLS G_END_DECLS
#endif /* SERVER_CONTEXT_H */ #endif /* SERVER_CONTEXT_H */

View File

@ -321,6 +321,7 @@ handle_method_call (GDBusConnection *connection,
object_path = g_strdup_printf (SERVER_CONTEXT_PATH, context_id++); object_path = g_strdup_printf (SERVER_CONTEXT_PATH, context_id++);
context = server_context_new (object_path, server->connection); context = server_context_new (object_path, server->connection);
server_context_set_client_connection (context, sender); server_context_set_client_connection (context, sender);
server_context_set_client_name (context, client_name);
g_hash_table_insert (server->context_hash, g_hash_table_insert (server->context_hash,
object_path, object_path,
context); context);
@ -367,6 +368,17 @@ handle_method_call (GDBusConnection *connection,
if (server->context_stack) { if (server->context_stack) {
ServerContext *context = server->context_stack->data; ServerContext *context = server->context_stack->data;
if (g_strcmp0 (server_context_get_client_connection (context),
sender) != 0) {
g_dbus_method_invocation_return_error
(invocation,
G_IO_ERROR,
G_IO_ERROR_FAILED_HANDLED,
"the current context not owned by %s",
sender);
return;
}
server_context_set_enabled (context, FALSE); server_context_set_enabled (context, FALSE);
server->context_stack = g_slist_next (server->context_stack); server->context_stack = g_slist_next (server->context_stack);
g_object_unref (context); g_object_unref (context);