I recently became interested in isomorphic keyboards (e.g. Wicki-Hayden, Jankó and Harmonic) and after realizing that a normal qwerty typewriter keyboard should do a pretty good job standing in for the hexagonal honeycomb grids used by these, I decided to write a little emulator: https://github.com/mindhog/mawb#isokbd- ... controller
It's currently linux-only since it uses the ALSA libraries to send midi events, but the rest of the code is just python3/tkinter so it should be fairly easy to get it running on other OSes (happy to accept PRs). It's also limited by your keyboard hardware's ability to deal with multiple keys simultaneously (seeing no issues at all on my Das Keyboard .
It emulates the three flavors of iso keyboard mentioned above as well as two others that I thought would be interesting. I'm kind of liking the "alt-thirds" layout myself.
Isomorphic Keyboard Emulator
Moderators: raboof, MattKingUSA, khz
Re: Isomorphic Keyboard Emulator
Hi. This looks interesting.
I tried to build from mawb repo, but got error when building spug. I'm on Fedora 32 with g++ 10.1.1.
Following snippet is the error I got:
Also it might be helpful to put spugxx repository url on `mawb/INSTALL`. I first tried to search "spug" through google and duckduckgo, but spugxx repo didn't hit on result.
I tried to build from mawb repo, but got error when building spug. I'm on Fedora 32 with g++ 10.1.1.
Following snippet is the error I got:
Code: Select all
$ git clone https://github.com/mindhog/spugxx.git
$ cd spugxx/
$ ./bootstrap
$ ./configure
$ make -j
(CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /home/cu/code/install_src/spugxx/missing autoheader)
rm -f stamp-h1
touch config.h.in
cd . && /bin/sh ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make all-am
make[1]: Entering directory '/home/cu/code/install_src/spugxx'
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT tester.o -MD -MP -MF .deps/tester.Tpo -c -o tester.o tester.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT TestMarshaller.o -MD -MP -MF .deps/TestMarshaller.Tpo -c -o TestMarshaller.o TestMarshaller.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Condition.o -MD -MP -MF .deps/Condition.Tpo -c -o Condition.o Condition.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT FileReader.o -MD -MP -MF .deps/FileReader.Tpo -c -o FileReader.o FileReader.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT NativeMarshaller.o -MD -MP -MF .deps/NativeMarshaller.Tpo -c -o NativeMarshaller.o NativeMarshaller.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Marshallable.o -MD -MP -MF .deps/Marshallable.Tpo -c -o Marshallable.o Marshallable.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT InetAddress.o -MD -MP -MF .deps/InetAddress.Tpo -c -o InetAddress.o InetAddress.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Mutex.o -MD -MP -MF .deps/Mutex.Tpo -c -o Mutex.o Mutex.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Reactor.o -MD -MP -MF .deps/Reactor.Tpo -c -o Reactor.o Reactor.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Socket.o -MD -MP -MF .deps/Socket.Tpo -c -o Socket.o Socket.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT SockException.o -MD -MP -MF .deps/SockException.Tpo -c -o SockException.o SockException.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT SystemException.o -MD -MP -MF .deps/SystemException.Tpo -c -o SystemException.o SystemException.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Thread.o -MD -MP -MF .deps/Thread.Tpo -c -o Thread.o Thread.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Time.o -MD -MP -MF .deps/Time.Tpo -c -o Time.o Time.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT Tracer.o -MD -MP -MF .deps/Tracer.Tpo -c -o Tracer.o Tracer.cc
g++ -DHAVE_CONFIG_H -I. -g -O2 -MT OwningByteBuf.o -MD -MP -MF .deps/OwningByteBuf.Tpo -c -o OwningByteBuf.o OwningByteBuf.cc
mv -f .deps/Marshallable.Tpo .deps/Marshallable.Po
mv -f .deps/OwningByteBuf.Tpo .deps/OwningByteBuf.Po
mv -f .deps/TestMarshaller.Tpo .deps/TestMarshaller.Po
Thread.cc: In static member function ‘static void* spug::Thread::outerFunction(void*)’:
Thread.cc:44:1: warning: no return statement in function returning non-void [-Wreturn-type]
44 | }
| ^
mv -f .deps/Thread.Tpo .deps/Thread.Po
mv -f .deps/SockException.Tpo .deps/SockException.Po
mv -f .deps/Mutex.Tpo .deps/Mutex.Po
mv -f .deps/Time.Tpo .deps/Time.Po
mv -f .deps/SystemException.Tpo .deps/SystemException.Po
mv -f .deps/InetAddress.Tpo .deps/InetAddress.Po
mv -f .deps/Condition.Tpo .deps/Condition.Po
mv -f .deps/Socket.Tpo .deps/Socket.Po
mv -f .deps/FileReader.Tpo .deps/FileReader.Po
In file included from /usr/include/c++/10/deque:69,
from Reactor.cc:25:
/usr/include/c++/10/bits/deque.tcc: In instantiation of ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::_M_insert_aux(std::deque<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {{anonymous}::PollReactor::Event}; _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator]’:
/usr/include/c++/10/bits/deque.tcc:203:24: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::emplace(std::deque<_Tp, _Alloc>::const_iterator, _Args&& ...) [with _Args = {{anonymous}::PollReactor::Event}; _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator; std::deque<_Tp, _Alloc>::const_iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::const_iterator]’
/usr/include/c++/10/bits/stl_deque.h:1617:23: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::insert(std::deque<_Tp, _Alloc>::const_iterator, std::deque<_Tp, _Alloc>::value_type&&) [with _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator; std::deque<_Tp, _Alloc>::const_iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::const_iterator; std::deque<_Tp, _Alloc>::value_type = {anonymous}::PollReactor::Event]’
Reactor.cc:114:48: required from here
/usr/include/c++/10/bits/deque.tcc:676:9: error: use of deleted function ‘{anonymous}::PollReactor::Event& {anonymous}::PollReactor::Event::operator=({anonymous}::PollReactor::Event&&)’
676 | *__pos = _GLIBCXX_MOVE(__x_copy);
| ^
Reactor.cc:44:16: note: ‘{anonymous}::PollReactor::Event& {anonymous}::PollReactor::Event::operator=({anonymous}::PollReactor::Event&&)’ is implicitly deleted because the default definition would be ill-formed:
44 | struct Event {
| ^~~~~
Reactor.cc:44:16: error: cannot bind non-const lvalue reference of type ‘spug::LPtr<spug::Runnable>&’ to an rvalue of type ‘spug::RunnableLPtr’ {aka ‘spug::LPtr<spug::Runnable>’}
In file included from Reactor.h:27,
from Reactor.cc:22:
LPtr.h:78:36: note: initializing argument 1 of ‘spug::LPtr<T>& spug::LPtr<T>::operator=(spug::LPtr<T>&) [with T = spug::Runnable]’
78 | LPtr<T> &operator =(LPtr<T> &other) {
| ~~~~~~~~~^~~~~
In file included from /usr/include/c++/10/bits/char_traits.h:39,
from /usr/include/c++/10/ios:40,
from /usr/include/c++/10/ostream:38,
from /usr/include/c++/10/iostream:39,
from LPtr.h:27,
from Reactor.h:27,
from Reactor.cc:22:
/usr/include/c++/10/bits/stl_algobase.h: In instantiation of ‘static _OI std::__copy_move<true, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = {anonymous}::PollReactor::Event*; _OI = {anonymous}::PollReactor::Event*]’:
/usr/include/c++/10/bits/stl_algobase.h:472:30: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = true; _II = {anonymous}::PollReactor::Event*; _OI = {anonymous}::PollReactor::Event*]’
/usr/include/c++/10/bits/stl_algobase.h:506:42: required from ‘_OI std::__copy_move_a1(_II, _II, _OI) [with bool _IsMove = true; _II = {anonymous}::PollReactor::Event*; _OI = {anonymous}::PollReactor::Event*]’
/usr/include/c++/10/bits/deque.tcc:1057:32: required from ‘typename __gnu_cxx::__enable_if<std::__is_random_access_iter<_II>::__value, std::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type std::__copy_move_a1(_II, _II, std::_Deque_iterator<_Tp, _Tp&, _Tp*>) [with bool _IsMove = true; _II = {anonymous}::PollReactor::Event*; _Tp = {anonymous}::PollReactor::Event; typename __gnu_cxx::__enable_if<std::__is_random_access_iter<_II>::__value, std::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type = __gnu_cxx::__enable_if<true, std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*> >::__type]’
/usr/include/c++/10/bits/deque.tcc:1008:36: required from ‘_OI std::__copy_move_dit(std::_Deque_iterator<_Tp, _Ref, _Ptr>, std::_Deque_iterator<_Tp, _Ref, _Ptr>, _OI) [with bool _IsMove = true; _Tp = {anonymous}::PollReactor::Event; _Ref = {anonymous}::PollReactor::Event&; _Ptr = {anonymous}::PollReactor::Event*; _OI = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>]’
/usr/include/c++/10/bits/deque.tcc:1040:38: required from ‘std::_Deque_iterator<_OTp, _OTp&, _OTp*> std::__copy_move_a1(std::_Deque_iterator<_Tp, _Ref, _Ptr>, std::_Deque_iterator<_Tp, _Ref, _Ptr>, std::_Deque_iterator<_OTp, _OTp&, _OTp*>) [with bool _IsMove = true; _ITp = {anonymous}::PollReactor::Event; _IRef = {anonymous}::PollReactor::Event&; _IPtr = {anonymous}::PollReactor::Event*; _OTp = {anonymous}::PollReactor::Event]’
/usr/include/c++/10/bits/stl_algobase.h:514:31: required from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = true; _II = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>; _OI = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>]’
/usr/include/c++/10/bits/stl_algobase.h:601:38: required from ‘_OI std::move(_II, _II, _OI) [with _II = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>; _OI = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>]’
/usr/include/c++/10/bits/deque.tcc:664:6: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::_M_insert_aux(std::deque<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {{anonymous}::PollReactor::Event}; _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator]’
/usr/include/c++/10/bits/deque.tcc:203:24: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::emplace(std::deque<_Tp, _Alloc>::const_iterator, _Args&& ...) [with _Args = {{anonymous}::PollReactor::Event}; _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator; std::deque<_Tp, _Alloc>::const_iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::const_iterator]’
/usr/include/c++/10/bits/stl_deque.h:1617:23: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::insert(std::deque<_Tp, _Alloc>::const_iterator, std::deque<_Tp, _Alloc>::value_type&&) [with _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator; std::deque<_Tp, _Alloc>::const_iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::const_iterator; std::deque<_Tp, _Alloc>::value_type = {anonymous}::PollReactor::Event]’
Reactor.cc:114:48: required from here
/usr/include/c++/10/bits/stl_algobase.h:400:18: error: use of deleted function ‘{anonymous}::PollReactor::Event& {anonymous}::PollReactor::Event::operator=({anonymous}::PollReactor::Event&&)’
400 | *__result = std::move(*__first);
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/10/bits/stl_algobase.h: In instantiation of ‘static _BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = {anonymous}::PollReactor::Event*; _BI2 = {anonymous}::PollReactor::Event*]’:
/usr/include/c++/10/bits/stl_algobase.h:709:37: required from ‘_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true; _BI1 = {anonymous}::PollReactor::Event*; _BI2 = {anonymous}::PollReactor::Event*]’
/usr/include/c++/10/bits/stl_algobase.h:718:51: required from ‘_BI2 std::__copy_move_backward_a1(_BI1, _BI1, _BI2) [with bool _IsMove = true; _BI1 = {anonymous}::PollReactor::Event*; _BI2 = {anonymous}::PollReactor::Event*]’
/usr/include/c++/10/bits/deque.tcc:1135:41: required from ‘typename __gnu_cxx::__enable_if<std::__is_random_access_iter<_II>::__value, std::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type std::__copy_move_backward_a1(_II, _II, std::_Deque_iterator<_Tp, _Tp&, _Tp*>) [with bool _IsMove = true; _II = {anonymous}::PollReactor::Event*; _Tp = {anonymous}::PollReactor::Event; typename __gnu_cxx::__enable_if<std::__is_random_access_iter<_II>::__value, std::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type = __gnu_cxx::__enable_if<true, std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*> >::__type]’
/usr/include/c++/10/bits/deque.tcc:1079:52: required from ‘_OI std::__copy_move_backward_dit(std::_Deque_iterator<_Tp, _Ref, _Ptr>, std::_Deque_iterator<_Tp, _Ref, _Ptr>, _OI) [with bool _IsMove = true; _Tp = {anonymous}::PollReactor::Event; _Ref = {anonymous}::PollReactor::Event&; _Ptr = {anonymous}::PollReactor::Event*; _OI = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>]’
/usr/include/c++/10/bits/deque.tcc:1111:47: required from ‘std::_Deque_iterator<_OTp, _OTp&, _OTp*> std::__copy_move_backward_a1(std::_Deque_iterator<_Tp, _Ref, _Ptr>, std::_Deque_iterator<_Tp, _Ref, _Ptr>, std::_Deque_iterator<_OTp, _OTp&, _OTp*>) [with bool _IsMove = true; _ITp = {anonymous}::PollReactor::Event; _IRef = {anonymous}::PollReactor::Event&; _IPtr = {anonymous}::PollReactor::Event*; _OTp = {anonymous}::PollReactor::Event]’
/usr/include/c++/10/bits/stl_algobase.h:749:5: required from ‘_OI std::__copy_move_backward_a(_II, _II, _OI) [with bool _IsMove = true; _II = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>; _OI = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>]’
/usr/include/c++/10/bits/stl_algobase.h:843:47: required from ‘_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>; _BI2 = std::_Deque_iterator<{anonymous}::PollReactor::Event, {anonymous}::PollReactor::Event&, {anonymous}::PollReactor::Event*>]’
/usr/include/c++/10/bits/deque.tcc:674:6: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::_M_insert_aux(std::deque<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {{anonymous}::PollReactor::Event}; _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator]’
/usr/include/c++/10/bits/deque.tcc:203:24: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::emplace(std::deque<_Tp, _Alloc>::const_iterator, _Args&& ...) [with _Args = {{anonymous}::PollReactor::Event}; _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator; std::deque<_Tp, _Alloc>::const_iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::const_iterator]’
/usr/include/c++/10/bits/stl_deque.h:1617:23: required from ‘std::deque<_Tp, _Alloc>::iterator std::deque<_Tp, _Alloc>::insert(std::deque<_Tp, _Alloc>::const_iterator, std::deque<_Tp, _Alloc>::value_type&&) [with _Tp = {anonymous}::PollReactor::Event; _Alloc = std::allocator<{anonymous}::PollReactor::Event>; std::deque<_Tp, _Alloc>::iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::iterator; std::deque<_Tp, _Alloc>::const_iterator = std::_Deque_base<{anonymous}::PollReactor::Event, std::allocator<{anonymous}::PollReactor::Event> >::const_iterator; std::deque<_Tp, _Alloc>::value_type = {anonymous}::PollReactor::Event]’
Reactor.cc:114:48: required from here
/usr/include/c++/10/bits/stl_algobase.h:668:18: error: use of deleted function ‘{anonymous}::PollReactor::Event& {anonymous}::PollReactor::Event::operator=({anonymous}::PollReactor::Event&&)’
668 | *--__result = std::move(*--__last);
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
make[1]: *** [Makefile:677: Reactor.o] Error 1
make[1]: *** Waiting for unfinished jobs....
mv -f .deps/Tracer.Tpo .deps/Tracer.Po
NativeMarshaller.cc: In function ‘std::ostream& {anonymous}::operator<<(std::ostream&, const {anonymous}::FmtBuf&)’:
NativeMarshaller.cc:68:1: warning: no return statement in function returning non-void [-Wreturn-type]
68 | }
| ^
mv -f .deps/NativeMarshaller.Tpo .deps/NativeMarshaller.Po
tester.cc:236:1: warning: ISO C++ forbids declaration of ‘main’ with no type [-Wreturn-type]
236 | main() {
| ^~~~
tester.cc: In function ‘int main()’:
tester.cc:493:32: warning: placement new constructing an object of type ‘spug::OwningByteBuf’ and size ‘16’ in a region of type ‘char [13]’ and size ‘13’ [-Wplacement-new=]
493 | OwningByteBuf *buf = new(block) OwningByteBuf();
| ^~~~~
mv -f .deps/tester.Tpo .deps/tester.Po
make[1]: Leaving directory '/home/cu/code/install_src/spugxx'
make: *** [Makefile:551: all] Error 2
Re: Isomorphic Keyboard Emulator
Hi ryukau,
You don't have to do the full INSTALL instructions for isokbd, just the instructions from the README:
You don't have to do the full INSTALL instructions for isokbd, just the instructions from the README:
But thank you for the bug report! "mawbd" clearly needs to be updated for the latest C++ goodness.For isokbd.py you should only need swig, tkinter and the alsa libaries and headers ("swig", "python3-tk" and "libasound2-dev" on debian-derivatives) and you can install like so:
python3 setup.py build
sudo python3 setup.py install
Re: Isomorphic Keyboard Emulator
Thanks for the answer, mindhog. It's working now.
I thought missing swig was a error that requires build from source.
I'm using keyboard with Japanese layout (OADG 109A), so key binding configuration would be nice to have. A mention about `rows` variable in isokbd.py might be helpful to have in README.md.
I thought missing swig was a error that requires build from source.
I'm using keyboard with Japanese layout (OADG 109A), so key binding configuration would be nice to have. A mention about `rows` variable in isokbd.py might be helpful to have in README.md.
Re: Isomorphic Keyboard Emulator
Cool, glad it worked out!
Anyway, thanks for taking the time to try it out!
Glad you discovered that I've been thinking a bit about this, @tavasti also had a problem with keyboard layout, it really should just be a config file. The nice thing is that the layout should be really easy to specify (with the exception of characters that show up as keysyms like "backspace" etc.).I'm using keyboard with Japanese layout (OADG 109A), so key binding configuration would be nice to have. A mention about `rows` variable in isokbd.py might be helpful to have in README.md.
Anyway, thanks for taking the time to try it out!