UBKeyboardPalette_linux.cpp 7.77 KB
Newer Older
Claudio Valerio's avatar
Claudio Valerio committed
1 2 3
/*
 * 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
Claudio Valerio's avatar
Claudio Valerio committed
4
 * the Free Software Foundation, either version 2 of the License, or
Claudio Valerio's avatar
Claudio Valerio committed
5 6 7 8 9 10 11 12 13 14
 * (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/>.
 */
15 16 17 18 19 20 21 22 23 24 25 26 27 28 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
#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);
73

74 75
}

76
/*
77
void traceKeyCodes()
78
{
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
    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);
}
106
*/
107

108

109 110
void UBKeyboardButton::sendUnicodeSymbol(KEYCODE keycode)
{
111 112 113 114 115
    // Obtain the X11 display.
    Display *display = XOpenDisplay(0);
    if(display == NULL)
       return;

116
    if (!keycode.empty())
117
    {
118 119 120 121 122 123 124 125 126 127
        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);
128 129 130 131 132 133 134 135 136 137 138 139
    }

    XCloseDisplay(display);
}

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

140

141 142 143 144 145 146 147 148 149 150 151 152
    KeyCode keyCode = XKeysymToKeycode(display, nSymbol);

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

    XCloseDisplay(display);
}

void UBKeyboardPalette::createCtrlButtons()
{
153 154 155 156 157 158 159 160 161 162 163
        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);
164 165 166 167 168 169 170
}


void UBKeyboardPalette::onActivated(bool activated)
{
    if (activated)
    {
171 172 173 174 175 176
        if (storage)
        {
            qDebug() << "Keybard already activated....";
            return;
        }

177 178 179 180 181 182
        Display *display = XOpenDisplay(0);
        if(display == NULL)
           return;

        XDisplayKeycodes(display, &this->min_keycodes, &this->max_keycodes);
        KeySym* keySyms = XGetKeyboardMapping(display, min_keycodes,
183
                           max_keycodes - min_keycodes, &byte_per_code);
184 185 186 187 188 189

        storage = keySyms;

        XCloseDisplay(display);

        onLocaleChanged(locales[nCurrentLocale]);
190

191 192 193 194 195
    }
    else
    {
        Display *display = XOpenDisplay(0);
        if(display == NULL)
196 197 198 199
        {
            qDebug() << "Keybard not activated....";
            return;
        }
200 201 202 203

        KeySym* keySyms = (KeySym*)storage;
        if (keySyms!=NULL)
        {
204
            qDebug() << "Default key table restored.....";
205 206 207 208

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

209
            XFree(keySyms);
210 211
            storage = NULL;
        }
212 213 214 215

        XCloseDisplay(display);
    }
}
216 217

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

221 222 223
    Display *display = XOpenDisplay(0);
    if(display == NULL)
       return;
224

225 226 227
    int byte_per_code;
    KeySym* keySyms = XGetKeyboardMapping(display, min_keycodes,
                       max_keycodes - min_keycodes, &byte_per_code);
228

229
    for(int i=0; i<SYMBOL_KEYS_COUNT; i++)
230
    {
231 232 233 234 235 236
        // loop by keybt
        for(int j=0; j<8; j++)
        {
            KEYCODE& kc = (*locale)[i]->codes[j];
            if (!kc.empty())
            {
237
                if (kc.modifier <= maxMapOffset)
238 239 240 241
                    keySyms[kc.code * byte_per_code + kc.modifier] = kc.symbol;

            }
        }
242 243
    }

244 245 246 247 248 249 250 251 252
    //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())
            {
253
                if (kc.modifier > maxMapOffset)
254 255
                {
                    for(int i1=0; i1<SYMBOL_KEYS_COUNT; i1++)
256
                        for(int j1=0; j1<=maxMapOffset; j1++)
257 258 259 260 261 262 263 264 265 266 267 268
                            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;
            }
        }
    }
269 270


271 272
    XChangeKeyboardMapping(display, min_keycodes, byte_per_code, keySyms, max_keycodes - min_keycodes);
    XFree(keySyms);
273 274 275

    XCloseDisplay(display);
}