UBKeyboardPalette_linux.cpp 8.2 KB
Newer Older
Claudio Valerio's avatar
Claudio Valerio committed
1
/*
2
 * Copyright (C) 2015-2018 Département de l'Instruction Publique (DIP-SEM)
Craig Watson's avatar
Craig Watson committed
3
 *
Claudio Valerio's avatar
Claudio Valerio committed
4
 * Copyright (C) 2013 Open Education Foundation
Claudio Valerio's avatar
Claudio Valerio committed
5
 *
Claudio Valerio's avatar
Claudio Valerio committed
6 7
 * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour
 * l'Education Numérique en Afrique (GIP ENA)
8
 *
Claudio Valerio's avatar
Claudio Valerio committed
9 10 11
 * This file is part of OpenBoard.
 *
 * OpenBoard is free software: you can redistribute it and/or modify
Claudio Valerio's avatar
Claudio Valerio committed
12 13
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License,
14 15 16 17
 * 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).
 *
Claudio Valerio's avatar
Claudio Valerio committed
18
 * OpenBoard is distributed in the hope that it will be useful,
Claudio Valerio's avatar
Claudio Valerio committed
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Claudio Valerio's avatar
Claudio Valerio committed
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Claudio Valerio's avatar
Claudio Valerio committed
21
 * GNU General Public License for more details.
Claudio Valerio's avatar
Claudio Valerio committed
22
 *
Claudio Valerio's avatar
Claudio Valerio committed
23
 * You should have received a copy of the GNU General Public License
Claudio Valerio's avatar
Claudio Valerio committed
24
 * along with OpenBoard. If not, see <http://www.gnu.org/licenses/>.
Claudio Valerio's avatar
Claudio Valerio committed
25
 */
26 27


Claudio Valerio's avatar
Claudio Valerio committed
28

Claudio Valerio's avatar
Claudio Valerio committed
29

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
#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);
88

89 90
}

91
/*
92
void traceKeyCodes()
93
{
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    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);
}
121
*/
122

123

124 125
void UBKeyboardButton::sendUnicodeSymbol(KEYCODE keycode)
{
126 127 128 129 130
    // Obtain the X11 display.
    Display *display = XOpenDisplay(0);
    if(display == NULL)
       return;

131
    if (!keycode.empty())
132
    {
133 134 135 136 137 138 139 140 141 142
        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);
143 144 145 146 147 148 149 150 151 152 153 154
    }

    XCloseDisplay(display);
}

void UBKeyboardButton::sendControlSymbol(int nSymbol)
{
    // Obtain the X11 display.
    Display *display = XOpenDisplay(0);
    if(display == NULL)
       return;

155

156 157 158 159 160 161 162 163 164 165 166 167
    KeyCode keyCode = XKeysymToKeycode(display, nSymbol);

    if (keyCode != NoSymbol)
    {
        x11SendKey(display, keyCode, 0);
    }

    XCloseDisplay(display);
}

void UBKeyboardPalette::createCtrlButtons()
{
168 169 170 171 172 173 174 175 176 177 178
        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);
179 180 181
}


Anatoly Mihalchenko's avatar
Anatoly Mihalchenko committed
182 183 184
void UBKeyboardPalette::checkLayout()
{}

185 186 187 188
void UBKeyboardPalette::onActivated(bool activated)
{
    if (activated)
    {
189 190 191 192 193 194
        if (storage)
        {
            qDebug() << "Keybard already activated....";
            return;
        }

195 196 197 198 199 200
        Display *display = XOpenDisplay(0);
        if(display == NULL)
           return;

        XDisplayKeycodes(display, &this->min_keycodes, &this->max_keycodes);
        KeySym* keySyms = XGetKeyboardMapping(display, min_keycodes,
201
                           max_keycodes - min_keycodes, &byte_per_code);
202 203 204 205 206 207

        storage = keySyms;

        XCloseDisplay(display);

        onLocaleChanged(locales[nCurrentLocale]);
208

209 210 211 212 213
    }
    else
    {
        Display *display = XOpenDisplay(0);
        if(display == NULL)
214 215 216 217
        {
            qDebug() << "Keybard not activated....";
            return;
        }
218 219 220 221

        KeySym* keySyms = (KeySym*)storage;
        if (keySyms!=NULL)
        {
222
            qDebug() << "Default key table restored.....";
223 224 225 226

            XChangeKeyboardMapping(display, min_keycodes, byte_per_code,
                                   keySyms, max_keycodes - min_keycodes);

227
            XFree(keySyms);
228 229
            storage = NULL;
        }
230 231 232 233

        XCloseDisplay(display);
    }
}
234 235

void UBKeyboardPalette::onLocaleChanged(UBKeyboardLocale* locale)
236
{
237 238
    const int maxMapOffset = 3; //Suppose to have at least 2 keysym groups due to X11 xlib specification

239 240 241
    Display *display = XOpenDisplay(0);
    if(display == NULL)
       return;
242

243 244 245
    int byte_per_code;
    KeySym* keySyms = XGetKeyboardMapping(display, min_keycodes,
                       max_keycodes - min_keycodes, &byte_per_code);
246

247
    for(int i=0; i<SYMBOL_KEYS_COUNT; i++)
248
    {
249 250 251 252 253 254
        // loop by keybt
        for(int j=0; j<8; j++)
        {
            KEYCODE& kc = (*locale)[i]->codes[j];
            if (!kc.empty())
            {
255
                if (kc.modifier <= maxMapOffset)
256 257 258 259
                    keySyms[kc.code * byte_per_code + kc.modifier] = kc.symbol;

            }
        }
260 261
    }

262 263 264 265 266 267 268 269 270
    //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())
            {
271
                if (kc.modifier > maxMapOffset)
272 273
                {
                    for(int i1=0; i1<SYMBOL_KEYS_COUNT; i1++)
274
                        for(int j1=0; j1<=maxMapOffset; j1++)
275 276 277 278 279 280 281 282 283 284 285 286
                            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;
            }
        }
    }
287 288


289 290
    XChangeKeyboardMapping(display, min_keycodes, byte_per_code, keySyms, max_keycodes - min_keycodes);
    XFree(keySyms);
291 292 293

    XCloseDisplay(display);
}