sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_x11keyboard.c (17358B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
      4 
      5   This software is provided 'as-is', without any express or implied
      6   warranty.  In no event will the authors be held liable for any damages
      7   arising from the use of this software.
      8 
      9   Permission is granted to anyone to use this software for any purpose,
     10   including commercial applications, and to alter it and redistribute it
     11   freely, subject to the following restrictions:
     12 
     13   1. The origin of this software must not be misrepresented; you must not
     14      claim that you wrote the original software. If you use this software
     15      in a product, an acknowledgment in the product documentation would be
     16      appreciated but is not required.
     17   2. Altered source versions must be plainly marked as such, and must not be
     18      misrepresented as being the original software.
     19   3. This notice may not be removed or altered from any source distribution.
     20 */
     21 #include "../../SDL_internal.h"
     22 
     23 #if SDL_VIDEO_DRIVER_X11
     24 
     25 #include "SDL_x11video.h"
     26 
     27 #include "../../events/SDL_keyboard_c.h"
     28 #include "../../events/scancodes_darwin.h"
     29 #include "../../events/scancodes_xfree86.h"
     30 
     31 #include <X11/keysym.h>
     32 #include <X11/XKBlib.h>
     33 
     34 #include "imKStoUCS.h"
     35 
     36 #ifdef X_HAVE_UTF8_STRING
     37 #include <locale.h>
     38 #endif
     39 
     40 /* *INDENT-OFF* */
     41 static const struct {
     42     KeySym keysym;
     43     SDL_Scancode scancode;
     44 } KeySymToSDLScancode[] = {
     45     { XK_Return, SDL_SCANCODE_RETURN },
     46     { XK_Escape, SDL_SCANCODE_ESCAPE },
     47     { XK_BackSpace, SDL_SCANCODE_BACKSPACE },
     48     { XK_Tab, SDL_SCANCODE_TAB },
     49     { XK_Caps_Lock, SDL_SCANCODE_CAPSLOCK },
     50     { XK_F1, SDL_SCANCODE_F1 },
     51     { XK_F2, SDL_SCANCODE_F2 },
     52     { XK_F3, SDL_SCANCODE_F3 },
     53     { XK_F4, SDL_SCANCODE_F4 },
     54     { XK_F5, SDL_SCANCODE_F5 },
     55     { XK_F6, SDL_SCANCODE_F6 },
     56     { XK_F7, SDL_SCANCODE_F7 },
     57     { XK_F8, SDL_SCANCODE_F8 },
     58     { XK_F9, SDL_SCANCODE_F9 },
     59     { XK_F10, SDL_SCANCODE_F10 },
     60     { XK_F11, SDL_SCANCODE_F11 },
     61     { XK_F12, SDL_SCANCODE_F12 },
     62     { XK_Print, SDL_SCANCODE_PRINTSCREEN },
     63     { XK_Scroll_Lock, SDL_SCANCODE_SCROLLLOCK },
     64     { XK_Pause, SDL_SCANCODE_PAUSE },
     65     { XK_Insert, SDL_SCANCODE_INSERT },
     66     { XK_Home, SDL_SCANCODE_HOME },
     67     { XK_Prior, SDL_SCANCODE_PAGEUP },
     68     { XK_Delete, SDL_SCANCODE_DELETE },
     69     { XK_End, SDL_SCANCODE_END },
     70     { XK_Next, SDL_SCANCODE_PAGEDOWN },
     71     { XK_Right, SDL_SCANCODE_RIGHT },
     72     { XK_Left, SDL_SCANCODE_LEFT },
     73     { XK_Down, SDL_SCANCODE_DOWN },
     74     { XK_Up, SDL_SCANCODE_UP },
     75     { XK_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR },
     76     { XK_KP_Divide, SDL_SCANCODE_KP_DIVIDE },
     77     { XK_KP_Multiply, SDL_SCANCODE_KP_MULTIPLY },
     78     { XK_KP_Subtract, SDL_SCANCODE_KP_MINUS },
     79     { XK_KP_Add, SDL_SCANCODE_KP_PLUS },
     80     { XK_KP_Enter, SDL_SCANCODE_KP_ENTER },
     81     { XK_KP_Delete, SDL_SCANCODE_KP_PERIOD },
     82     { XK_KP_End, SDL_SCANCODE_KP_1 },
     83     { XK_KP_Down, SDL_SCANCODE_KP_2 },
     84     { XK_KP_Next, SDL_SCANCODE_KP_3 },
     85     { XK_KP_Left, SDL_SCANCODE_KP_4 },
     86     { XK_KP_Begin, SDL_SCANCODE_KP_5 },
     87     { XK_KP_Right, SDL_SCANCODE_KP_6 },
     88     { XK_KP_Home, SDL_SCANCODE_KP_7 },
     89     { XK_KP_Up, SDL_SCANCODE_KP_8 },
     90     { XK_KP_Prior, SDL_SCANCODE_KP_9 },
     91     { XK_KP_Insert, SDL_SCANCODE_KP_0 },
     92     { XK_KP_Decimal, SDL_SCANCODE_KP_PERIOD },
     93     { XK_KP_1, SDL_SCANCODE_KP_1 },
     94     { XK_KP_2, SDL_SCANCODE_KP_2 },
     95     { XK_KP_3, SDL_SCANCODE_KP_3 },
     96     { XK_KP_4, SDL_SCANCODE_KP_4 },
     97     { XK_KP_5, SDL_SCANCODE_KP_5 },
     98     { XK_KP_6, SDL_SCANCODE_KP_6 },
     99     { XK_KP_7, SDL_SCANCODE_KP_7 },
    100     { XK_KP_8, SDL_SCANCODE_KP_8 },
    101     { XK_KP_9, SDL_SCANCODE_KP_9 },
    102     { XK_KP_0, SDL_SCANCODE_KP_0 },
    103     { XK_KP_Decimal, SDL_SCANCODE_KP_PERIOD },
    104     { XK_Hyper_R, SDL_SCANCODE_APPLICATION },
    105     { XK_KP_Equal, SDL_SCANCODE_KP_EQUALS },
    106     { XK_F13, SDL_SCANCODE_F13 },
    107     { XK_F14, SDL_SCANCODE_F14 },
    108     { XK_F15, SDL_SCANCODE_F15 },
    109     { XK_F16, SDL_SCANCODE_F16 },
    110     { XK_F17, SDL_SCANCODE_F17 },
    111     { XK_F18, SDL_SCANCODE_F18 },
    112     { XK_F19, SDL_SCANCODE_F19 },
    113     { XK_F20, SDL_SCANCODE_F20 },
    114     { XK_F21, SDL_SCANCODE_F21 },
    115     { XK_F22, SDL_SCANCODE_F22 },
    116     { XK_F23, SDL_SCANCODE_F23 },
    117     { XK_F24, SDL_SCANCODE_F24 },
    118     { XK_Execute, SDL_SCANCODE_EXECUTE },
    119     { XK_Help, SDL_SCANCODE_HELP },
    120     { XK_Menu, SDL_SCANCODE_MENU },
    121     { XK_Select, SDL_SCANCODE_SELECT },
    122     { XK_Cancel, SDL_SCANCODE_STOP },
    123     { XK_Redo, SDL_SCANCODE_AGAIN },
    124     { XK_Undo, SDL_SCANCODE_UNDO },
    125     { XK_Find, SDL_SCANCODE_FIND },
    126     { XK_KP_Separator, SDL_SCANCODE_KP_COMMA },
    127     { XK_Sys_Req, SDL_SCANCODE_SYSREQ },
    128     { XK_Control_L, SDL_SCANCODE_LCTRL },
    129     { XK_Shift_L, SDL_SCANCODE_LSHIFT },
    130     { XK_Alt_L, SDL_SCANCODE_LALT },
    131     { XK_Meta_L, SDL_SCANCODE_LGUI },
    132     { XK_Super_L, SDL_SCANCODE_LGUI },
    133     { XK_Control_R, SDL_SCANCODE_RCTRL },
    134     { XK_Shift_R, SDL_SCANCODE_RSHIFT },
    135     { XK_Alt_R, SDL_SCANCODE_RALT },
    136     { XK_ISO_Level3_Shift, SDL_SCANCODE_RALT },
    137     { XK_Meta_R, SDL_SCANCODE_RGUI },
    138     { XK_Super_R, SDL_SCANCODE_RGUI },
    139     { XK_Mode_switch, SDL_SCANCODE_MODE },
    140     { XK_period, SDL_SCANCODE_PERIOD },
    141     { XK_comma, SDL_SCANCODE_COMMA },
    142     { XK_slash, SDL_SCANCODE_SLASH },
    143     { XK_backslash, SDL_SCANCODE_BACKSLASH },
    144     { XK_minus, SDL_SCANCODE_MINUS },
    145     { XK_equal, SDL_SCANCODE_EQUALS },
    146     { XK_space, SDL_SCANCODE_SPACE },
    147     { XK_grave, SDL_SCANCODE_GRAVE },
    148     { XK_apostrophe, SDL_SCANCODE_APOSTROPHE },
    149     { XK_bracketleft, SDL_SCANCODE_LEFTBRACKET },
    150     { XK_bracketright, SDL_SCANCODE_RIGHTBRACKET },
    151 };
    152 
    153 static const struct
    154 {
    155     SDL_Scancode const *table;
    156     int table_size;
    157 } scancode_set[] = {
    158     { darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
    159     { xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
    160     { xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
    161     { xvnc_scancode_table, SDL_arraysize(xvnc_scancode_table) },
    162 };
    163 /* *INDENT-OFF* */
    164 
    165 /* This function only works for keyboards in US QWERTY layout */
    166 static SDL_Scancode
    167 X11_KeyCodeToSDLScancode(_THIS, KeyCode keycode)
    168 {
    169     KeySym keysym;
    170     int i;
    171 
    172     keysym = X11_KeyCodeToSym(_this, keycode, 0);
    173     if (keysym == NoSymbol) {
    174         return SDL_SCANCODE_UNKNOWN;
    175     }
    176 
    177     if (keysym >= XK_a && keysym <= XK_z) {
    178         return SDL_SCANCODE_A + (keysym - XK_a);
    179     }
    180     if (keysym >= XK_A && keysym <= XK_Z) {
    181         return SDL_SCANCODE_A + (keysym - XK_A);
    182     }
    183 
    184     if (keysym == XK_0) {
    185         return SDL_SCANCODE_0;
    186     }
    187     if (keysym >= XK_1 && keysym <= XK_9) {
    188         return SDL_SCANCODE_1 + (keysym - XK_1);
    189     }
    190 
    191     for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) {
    192         if (keysym == KeySymToSDLScancode[i].keysym) {
    193             return KeySymToSDLScancode[i].scancode;
    194         }
    195     }
    196     return SDL_SCANCODE_UNKNOWN;
    197 }
    198 
    199 static Uint32
    200 X11_KeyCodeToUcs4(_THIS, KeyCode keycode, unsigned char group)
    201 {
    202     KeySym keysym = X11_KeyCodeToSym(_this, keycode, group);
    203 
    204     if (keysym == NoSymbol) {
    205         return 0;
    206     }
    207 
    208     return X11_KeySymToUcs4(keysym);
    209 }
    210 
    211 KeySym
    212 X11_KeyCodeToSym(_THIS, KeyCode keycode, unsigned char group)
    213 {
    214     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    215     KeySym keysym;
    216 
    217 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    218     if (data->xkb) {
    219         int num_groups     = XkbKeyNumGroups(data->xkb, keycode);
    220         unsigned char info = XkbKeyGroupInfo(data->xkb, keycode);
    221         
    222         if (num_groups && group >= num_groups) {
    223         
    224             int action = XkbOutOfRangeGroupAction(info);
    225             
    226             if (action == XkbRedirectIntoRange) {
    227                 if ((group = XkbOutOfRangeGroupNumber(info)) >= num_groups) {
    228                     group = 0;
    229                 }
    230             } else if (action == XkbClampIntoRange) {
    231                 group = num_groups - 1;
    232             } else {
    233                 group %= num_groups;
    234             }
    235         }
    236         keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
    237     } else {
    238         keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
    239     }
    240 #else
    241     keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
    242 #endif
    243 
    244     return keysym;
    245 }
    246 
    247 int
    248 X11_InitKeyboard(_THIS)
    249 {
    250     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    251     int i = 0;
    252     int j = 0;
    253     int min_keycode, max_keycode;
    254     struct {
    255         SDL_Scancode scancode;
    256         KeySym keysym;
    257         int value;
    258     } fingerprint[] = {
    259         { SDL_SCANCODE_HOME, XK_Home, 0 },
    260         { SDL_SCANCODE_PAGEUP, XK_Prior, 0 },
    261         { SDL_SCANCODE_UP, XK_Up, 0 },
    262         { SDL_SCANCODE_LEFT, XK_Left, 0 },
    263         { SDL_SCANCODE_DELETE, XK_Delete, 0 },
    264         { SDL_SCANCODE_KP_ENTER, XK_KP_Enter, 0 },
    265     };
    266     int best_distance;
    267     int best_index;
    268     int distance;
    269     Bool xkb_repeat = 0;
    270     XKeyboardState values = { .global_auto_repeat = AutoRepeatModeOff };
    271     
    272     X11_XGetKeyboardControl(data->display, &values);
    273     if (values.global_auto_repeat != AutoRepeatModeOn)
    274         X11_XAutoRepeatOn(data->display);
    275 
    276 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    277     {
    278         int xkb_major = XkbMajorVersion;
    279         int xkb_minor = XkbMinorVersion;
    280 
    281         if (X11_XkbQueryExtension(data->display, NULL, NULL, NULL, &xkb_major, &xkb_minor)) {
    282             data->xkb = X11_XkbGetMap(data->display, XkbAllClientInfoMask, XkbUseCoreKbd);
    283         }
    284 
    285         /* This will remove KeyRelease events for held keys */
    286         X11_XkbSetDetectableAutoRepeat(data->display, True, &xkb_repeat);
    287     }
    288 #endif
    289     
    290     /* Open a connection to the X input manager */
    291 #ifdef X_HAVE_UTF8_STRING
    292     if (SDL_X11_HAVE_UTF8) {
    293         /* Set the locale, and call XSetLocaleModifiers before XOpenIM so that 
    294            Compose keys will work correctly. */
    295         char *prev_locale = setlocale(LC_ALL, NULL);
    296         char *prev_xmods  = X11_XSetLocaleModifiers(NULL);
    297         const char *new_xmods = "";
    298         const char *env_xmods = SDL_getenv("XMODIFIERS");
    299         SDL_bool has_dbus_ime_support = SDL_FALSE;
    300 
    301         if (prev_locale) {
    302             prev_locale = SDL_strdup(prev_locale);
    303         }
    304 
    305         if (prev_xmods) {
    306             prev_xmods = SDL_strdup(prev_xmods);
    307         }
    308 
    309         /* IBus resends some key events that were filtered by XFilterEvents
    310            when it is used via XIM which causes issues. Prevent this by forcing
    311            @im=none if XMODIFIERS contains @im=ibus. IBus can still be used via 
    312            the DBus implementation, which also has support for pre-editing. */
    313         if (env_xmods && SDL_strstr(env_xmods, "@im=ibus") != NULL) {
    314             has_dbus_ime_support = SDL_TRUE;
    315         }
    316         if (env_xmods && SDL_strstr(env_xmods, "@im=fcitx") != NULL) {
    317             has_dbus_ime_support = SDL_TRUE;
    318         }
    319         if (has_dbus_ime_support || !xkb_repeat) {
    320             new_xmods = "@im=none";
    321         }
    322 
    323         setlocale(LC_ALL, "");
    324         X11_XSetLocaleModifiers(new_xmods);
    325 
    326         data->im = X11_XOpenIM(data->display, NULL, data->classname, data->classname);
    327 
    328         /* Reset the locale + X locale modifiers back to how they were,
    329            locale first because the X locale modifiers depend on it. */
    330         setlocale(LC_ALL, prev_locale);
    331         X11_XSetLocaleModifiers(prev_xmods);
    332 
    333         if (prev_locale) {
    334             SDL_free(prev_locale);
    335         }
    336 
    337         if (prev_xmods) {
    338             SDL_free(prev_xmods);
    339         }
    340     }
    341 #endif
    342     /* Try to determine which scancodes are being used based on fingerprint */
    343     best_distance = SDL_arraysize(fingerprint) + 1;
    344     best_index = -1;
    345     X11_XDisplayKeycodes(data->display, &min_keycode, &max_keycode);
    346     for (i = 0; i < SDL_arraysize(fingerprint); ++i) {
    347         fingerprint[i].value =
    348             X11_XKeysymToKeycode(data->display, fingerprint[i].keysym) -
    349             min_keycode;
    350     }
    351     for (i = 0; i < SDL_arraysize(scancode_set); ++i) {
    352         /* Make sure the scancode set isn't too big */
    353         if ((max_keycode - min_keycode + 1) <= scancode_set[i].table_size) {
    354             continue;
    355         }
    356         distance = 0;
    357         for (j = 0; j < SDL_arraysize(fingerprint); ++j) {
    358             if (fingerprint[j].value < 0
    359                 || fingerprint[j].value >= scancode_set[i].table_size) {
    360                 distance += 1;
    361             } else if (scancode_set[i].table[fingerprint[j].value] != fingerprint[j].scancode) {
    362                 distance += 1;
    363             }
    364         }
    365         if (distance < best_distance) {
    366             best_distance = distance;
    367             best_index = i;
    368         }
    369     }
    370     if (best_index >= 0 && best_distance <= 2) {
    371 #ifdef DEBUG_KEYBOARD
    372         printf("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d\n", best_index, min_keycode, max_keycode, scancode_set[best_index].table_size);
    373 #endif
    374         SDL_memcpy(&data->key_layout[min_keycode], scancode_set[best_index].table,
    375                    sizeof(SDL_Scancode) * scancode_set[best_index].table_size);
    376     } else {
    377         SDL_Keycode keymap[SDL_NUM_SCANCODES];
    378 
    379         printf
    380             ("Keyboard layout unknown, please report the following to the SDL forums/mailing list (https://discourse.libsdl.org/):\n");
    381 
    382         /* Determine key_layout - only works on US QWERTY layout */
    383         SDL_GetDefaultKeymap(keymap);
    384         for (i = min_keycode; i <= max_keycode; ++i) {
    385             KeySym sym;
    386             sym = X11_KeyCodeToSym(_this, (KeyCode) i, 0);
    387             if (sym != NoSymbol) {
    388                 SDL_Scancode scancode;
    389                 printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
    390                        (unsigned int) sym, X11_XKeysymToString(sym));
    391                 scancode = X11_KeyCodeToSDLScancode(_this, i);
    392                 data->key_layout[i] = scancode;
    393                 if (scancode == SDL_SCANCODE_UNKNOWN) {
    394                     printf("scancode not found\n");
    395                 } else {
    396                     printf("scancode = %d (%s)\n", scancode, SDL_GetScancodeName(scancode));
    397                 }
    398             }
    399         }
    400     }
    401 
    402     X11_UpdateKeymap(_this);
    403 
    404     SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");
    405 
    406 #ifdef SDL_USE_IME
    407     SDL_IME_Init();
    408 #endif
    409 
    410     return 0;
    411 }
    412 
    413 void
    414 X11_UpdateKeymap(_THIS)
    415 {
    416     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    417     int i;
    418     SDL_Scancode scancode;
    419     SDL_Keycode keymap[SDL_NUM_SCANCODES];
    420     unsigned char group = 0;
    421 
    422     SDL_GetDefaultKeymap(keymap);
    423 
    424 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    425     if (data->xkb) {
    426         XkbStateRec state;
    427         X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
    428 
    429         if (X11_XkbGetState(data->display, XkbUseCoreKbd, &state) == Success) {
    430             group = state.group;
    431         }
    432     }
    433 #endif
    434 
    435 
    436     for (i = 0; i < SDL_arraysize(data->key_layout); i++) {
    437         Uint32 key;
    438 
    439         /* Make sure this is a valid scancode */
    440         scancode = data->key_layout[i];
    441         if (scancode == SDL_SCANCODE_UNKNOWN) {
    442             continue;
    443         }
    444 
    445         /* See if there is a UCS keycode for this scancode */
    446         key = X11_KeyCodeToUcs4(_this, (KeyCode)i, group);
    447         if (key) {
    448             keymap[scancode] = key;
    449         } else {
    450             SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(_this, (KeyCode)i);
    451 
    452             switch (keyScancode) {
    453                 case SDL_SCANCODE_RETURN:
    454                     keymap[scancode] = SDLK_RETURN;
    455                     break;
    456                 case SDL_SCANCODE_ESCAPE:
    457                     keymap[scancode] = SDLK_ESCAPE;
    458                     break;
    459                 case SDL_SCANCODE_BACKSPACE:
    460                     keymap[scancode] = SDLK_BACKSPACE;
    461                     break;
    462                 case SDL_SCANCODE_TAB:
    463                     keymap[scancode] = SDLK_TAB;
    464                     break;
    465                 case SDL_SCANCODE_DELETE:
    466                     keymap[scancode] = SDLK_DELETE;
    467                     break;
    468                 default:
    469                     keymap[scancode] = SDL_SCANCODE_TO_KEYCODE(keyScancode);
    470                     break;
    471             }
    472         }
    473     }
    474     SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
    475 }
    476 
    477 void
    478 X11_QuitKeyboard(_THIS)
    479 {
    480     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    481 
    482 #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
    483     if (data->xkb) {
    484         X11_XkbFreeKeyboard(data->xkb, 0, True);
    485         data->xkb = NULL;
    486     }
    487 #endif
    488 
    489 #ifdef SDL_USE_IME
    490     SDL_IME_Quit();
    491 #endif
    492 }
    493 
    494 static void
    495 X11_ResetXIM(_THIS)
    496 {
    497 #ifdef X_HAVE_UTF8_STRING
    498     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    499     int i;
    500 
    501     if (videodata && videodata->windowlist) {
    502         for (i = 0; i < videodata->numwindows; ++i) {
    503             SDL_WindowData *data = videodata->windowlist[i];
    504             if (data && data->ic) {
    505                 /* Clear any partially entered dead keys */
    506                 char *contents = X11_Xutf8ResetIC(data->ic);
    507                 if (contents) {
    508                     X11_XFree(contents);
    509                 }
    510             }
    511         }
    512     }
    513 #endif
    514 }
    515 
    516 void
    517 X11_StartTextInput(_THIS)
    518 {
    519     X11_ResetXIM(_this);
    520 }
    521 
    522 void
    523 X11_StopTextInput(_THIS)
    524 {
    525     X11_ResetXIM(_this);
    526 #ifdef SDL_USE_IME
    527     SDL_IME_Reset();
    528 #endif
    529 }
    530 
    531 void
    532 X11_SetTextInputRect(_THIS, SDL_Rect *rect)
    533 {
    534     if (!rect) {
    535         SDL_InvalidParamError("rect");
    536         return;
    537     }
    538        
    539 #ifdef SDL_USE_IME
    540     SDL_IME_UpdateTextRect(rect);
    541 #endif
    542 }
    543 
    544 #endif /* SDL_VIDEO_DRIVER_X11 */
    545 
    546 /* vi: set ts=4 sw=4 expandtab: */