/*
* Copyright ( C ) 2012 Webdoc SA
*
* This file is part of Open - Sankoré .
*
* Open - Sankoré 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 , version 3 of the License ,
* with a specific linking exception for the OpenSSL project ' s
* " OpenSSL " library ( or with modified versions of it that use the
* same license as the " OpenSSL " library ) .
*
* Open - Sankoré 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 Open - Sankoré . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "UBKeyboardPalette.h"
# include <X11/Xlib.h>
# include <X11/keysym.h>
// The key code to be sent.
// A full list of available codes can be found in /usr/include/X11/keysymdef.h
//#define KEYCODE XK_Down
// Function to create a keyboard event
XKeyEvent createKeyEvent ( Display * display , Window & win ,
Window & winRoot , bool press ,
int keycode , int modifiers )
{
XKeyEvent event ;
event . display = display ;
event . window = win ;
event . root = winRoot ;
event . subwindow = None ;
event . time = CurrentTime ;
event . x = 1 ;
event . y = 1 ;
event . x_root = 1 ;
event . y_root = 1 ;
event . same_screen = True ;
event . keycode = keycode ;
event . state = modifiers ;
if ( press )
event . type = KeyPress ;
else
event . type = KeyRelease ;
return event ;
}
void x11SendKey ( Display * display , int keyCode , int modifiers )
{
// Get the root window for the current display.
Window winRoot = XDefaultRootWindow ( display ) ;
if ( winRoot = = 0 )
return ;
// Find the window which has the current keyboard focus.
Window winFocus ;
int revert ;
XGetInputFocus ( display , & winFocus , & revert ) ;
// Send a fake key press event to the window.
XKeyEvent event = createKeyEvent ( display , winFocus , winRoot , true , keyCode , modifiers ) ;
XSendEvent ( event . display , event . window , True , KeyPressMask , ( XEvent * ) & event ) ;
// Send a fake key release event to the window.
event = createKeyEvent ( display , winFocus , winRoot , false , keyCode , modifiers ) ;
XSendEvent ( event . display , event . window , True , KeyPressMask , ( XEvent * ) & event ) ;
}
/*
void traceKeyCodes ( )
{
Display * display = XOpenDisplay ( 0 ) ;
if ( display = = NULL )
return ;
int min_keycodes , max_keycodes , byte_per_code ;
XDisplayKeycodes ( display , & min_keycodes , & max_keycodes ) ;
KeySym * keySyms = XGetKeyboardMapping ( display , min_keycodes ,
max_keycodes - min_keycodes , & byte_per_code ) ;
qDebug ( ) < < " Codes table, min_keycodes: " < < min_keycodes < < " , max_keycodes: "
< < max_keycodes < < " , bytes_per_code: " < < byte_per_code ;
for ( int i = 0 ; i < max_keycodes - min_keycodes ; i + + )
{
QString str ;
for ( int j = 0 ; j < byte_per_code ; j + + )
{
str + = QString : : number ( keySyms [ i * byte_per_code + j ] , 16 ) ;
str + = " : " ;
}
qDebug ( ) < < i < < " : " < < str ;
}
XFree ( keySyms ) ;
XCloseDisplay ( display ) ;
}
*/
void UBKeyboardButton : : sendUnicodeSymbol ( KEYCODE keycode )
{
// Obtain the X11 display.
Display * display = XOpenDisplay ( 0 ) ;
if ( display = = NULL )
return ;
if ( ! keycode . empty ( ) )
{
int modifier = keycode . modifier ;
if ( keycode . modifier = = 2 ) modifier = 0x2000 ;
if ( keycode . modifier = = 3 ) modifier = 0x2001 ;
if ( keycode . modifier = = 4 ) modifier = 0x4000 ;
if ( keycode . modifier = = 5 ) modifier = 0x4001 ;
//modifiers 6 and 7 seems are not available.... They are reassigned in layout creationtime
//if (keycode.modifier==6) modifier = 0x6000;
//if (keycode.modifier==7) modifier = 0x6001;
x11SendKey ( display , keycode . code + keyboard - > min_keycodes , modifier ) ;
}
XCloseDisplay ( display ) ;
}
void UBKeyboardButton : : sendControlSymbol ( int nSymbol )
{
// Obtain the X11 display.
Display * display = XOpenDisplay ( 0 ) ;
if ( display = = NULL )
return ;
KeyCode keyCode = XKeysymToKeycode ( display , nSymbol ) ;
if ( keyCode ! = NoSymbol )
{
x11SendKey ( display , keyCode , 0 ) ;
}
XCloseDisplay ( display ) ;
}
void UBKeyboardPalette : : createCtrlButtons ( )
{
ctrlButtons = new UBKeyboardButton * [ 9 ] ;
ctrlButtons [ 0 ] = new UBCntrlButton ( this , XK_BackSpace , " backspace " ) ;
ctrlButtons [ 1 ] = new UBCntrlButton ( this , XK_Tab , " tab " ) ;
ctrlButtons [ 2 ] = new UBCapsLockButton ( this , " capslock " ) ;
ctrlButtons [ 3 ] = new UBCntrlButton ( this , tr ( " Enter " ) , XK_Return ) ;
ctrlButtons [ 4 ] = new UBShiftButton ( this , " shift " ) ;
ctrlButtons [ 5 ] = new UBShiftButton ( this , " shift " ) ;
ctrlButtons [ 6 ] = new UBLocaleButton ( this ) ;
ctrlButtons [ 7 ] = new UBCntrlButton ( this , " " , XK_space ) ;
ctrlButtons [ 8 ] = new UBLocaleButton ( this ) ;
}
void UBKeyboardPalette : : checkLayout ( )
{ }
void UBKeyboardPalette : : onActivated ( bool activated )
{
if ( activated )
{
if ( storage )
{
qDebug ( ) < < " Keybard already activated.... " ;
return ;
}
Display * display = XOpenDisplay ( 0 ) ;
if ( display = = NULL )
return ;
XDisplayKeycodes ( display , & this - > min_keycodes , & this - > max_keycodes ) ;
KeySym * keySyms = XGetKeyboardMapping ( display , min_keycodes ,
max_keycodes - min_keycodes , & byte_per_code ) ;
storage = keySyms ;
XCloseDisplay ( display ) ;
onLocaleChanged ( locales [ nCurrentLocale ] ) ;
}
else
{
Display * display = XOpenDisplay ( 0 ) ;
if ( display = = NULL )
{
qDebug ( ) < < " Keybard not activated.... " ;
return ;
}
KeySym * keySyms = ( KeySym * ) storage ;
if ( keySyms ! = NULL )
{
qDebug ( ) < < " Default key table restored..... " ;
XChangeKeyboardMapping ( display , min_keycodes , byte_per_code ,
keySyms , max_keycodes - min_keycodes ) ;
XFree ( keySyms ) ;
storage = NULL ;
}
XCloseDisplay ( display ) ;
}
}
void UBKeyboardPalette : : onLocaleChanged ( UBKeyboardLocale * locale )
{
const int maxMapOffset = 3 ; //Suppose to have at least 2 keysym groups due to X11 xlib specification
Display * display = XOpenDisplay ( 0 ) ;
if ( display = = NULL )
return ;
int byte_per_code ;
KeySym * keySyms = XGetKeyboardMapping ( display , min_keycodes ,
max_keycodes - min_keycodes , & byte_per_code ) ;
for ( int i = 0 ; i < SYMBOL_KEYS_COUNT ; i + + )
{
// loop by keybt
for ( int j = 0 ; j < 8 ; j + + )
{
KEYCODE & kc = ( * locale ) [ i ] - > codes [ j ] ;
if ( ! kc . empty ( ) )
{
if ( kc . modifier < = maxMapOffset )
keySyms [ kc . code * byte_per_code + kc . modifier ] = kc . symbol ;
}
}
}
//Now look for modifiers > 5 and reassign them to free places
for ( int i = 0 ; i < SYMBOL_KEYS_COUNT ; i + + )
{
// loop by keybt
for ( int j = 0 ; j < 8 ; j + + )
{
KEYCODE & kc = ( * locale ) [ i ] - > codes [ j ] ;
if ( ! kc . empty ( ) )
{
if ( kc . modifier > maxMapOffset )
{
for ( int i1 = 0 ; i1 < SYMBOL_KEYS_COUNT ; i1 + + )
for ( int j1 = 0 ; j1 < = maxMapOffset ; j1 + + )
if ( keySyms [ i1 * byte_per_code + j1 ] = = NoSymbol )
{
kc . code = i1 ;
kc . modifier = j1 ;
break ;
}
}
keySyms [ kc . code * byte_per_code + kc . modifier ] = kc . symbol ;
}
}
}
XChangeKeyboardMapping ( display , min_keycodes , byte_per_code , keySyms , max_keycodes - min_keycodes ) ;
XFree ( keySyms ) ;
XCloseDisplay ( display ) ;
}