src/video/android/SDL_androidvideo.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 03 Oct 2012 20:49:16 -0700
changeset 6555 f2c03c06d987
parent 6464 ab55284b389f
child 6654 2ecfb25be1e2
permissions -rw-r--r--
Fixed bug 1614 - SDL for Android does not implement TextInput API

Andrey Isakov 2012-10-03 08:30:25 PDT

I've found out in the process of porting one OS project to Android/SDL2 that
there is no support for TextInput events/APIs on Android.
So I implemented some kind of initial support of that feature, and at the very
least it seems to work fine with latin chars input with soft and hardware
keyboards on my Moto Milestone2. I've also tried playing around with more
complex IMEs, like japanese, logging the process and it seemed to work too. I'm
not sure since the app itself I am working on does not have support for
non-latin input.

The main point of the patch is to place a fake input view in the region
specified by SDL_SetTextInputRect and create a custom InputConnection for it.
The reason to make it a separate view is to support Android's pan&scan on input
feature properly. For details please refer to
http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html
Even though the manual states that SetTextInputRect is used to determine the
IME variants position, I thought this would be a proper use for this too.
paul@4701
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
paul@4701
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
paul@4701
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
paul@4701
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
paul@4701
    20
*/
paul@4701
    21
#include "SDL_config.h"
paul@4701
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_ANDROID
slouken@6044
    24
paul@4701
    25
/* Android SDL video driver implementation
paul@4701
    26
*/
paul@4701
    27
paul@4701
    28
#include "SDL_video.h"
paul@4701
    29
#include "SDL_mouse.h"
paul@4701
    30
#include "../SDL_sysvideo.h"
paul@4701
    31
#include "../SDL_pixels_c.h"
paul@4701
    32
#include "../../events/SDL_events_c.h"
slouken@5001
    33
#include "../../events/SDL_windowevents_c.h"
paul@4701
    34
paul@4701
    35
#include "SDL_androidvideo.h"
slouken@6464
    36
#include "SDL_androidclipboard.h"
paul@4703
    37
#include "SDL_androidevents.h"
slouken@4980
    38
#include "SDL_androidkeyboard.h"
slouken@4998
    39
#include "SDL_androidwindow.h"
paul@4701
    40
paul@4701
    41
#define ANDROID_VID_DRIVER_NAME "Android"
paul@4701
    42
paul@4701
    43
/* Initialization/Query functions */
paul@4701
    44
static int Android_VideoInit(_THIS);
paul@4701
    45
static void Android_VideoQuit(_THIS);
paul@4701
    46
paul@4701
    47
/* GL functions (SDL_androidgl.c) */
paul@4701
    48
extern int Android_GL_LoadLibrary(_THIS, const char *path);
paul@4701
    49
extern void *Android_GL_GetProcAddress(_THIS, const char *proc);
paul@4701
    50
extern void Android_GL_UnloadLibrary(_THIS);
paul@4701
    51
//extern int *Android_GL_GetVisual(_THIS, Display * display, int screen);
paul@4701
    52
extern SDL_GLContext Android_GL_CreateContext(_THIS, SDL_Window * window);
paul@4701
    53
extern int Android_GL_MakeCurrent(_THIS, SDL_Window * window,
paul@4701
    54
                              SDL_GLContext context);
paul@4701
    55
extern int Android_GL_SetSwapInterval(_THIS, int interval);
paul@4701
    56
extern int Android_GL_GetSwapInterval(_THIS);
paul@4701
    57
extern void Android_GL_SwapWindow(_THIS, SDL_Window * window);
paul@4701
    58
extern void Android_GL_DeleteContext(_THIS, SDL_GLContext context);
paul@4701
    59
paul@4701
    60
/* Android driver bootstrap functions */
paul@4701
    61
paul@4701
    62
slouken@4981
    63
// These are filled in with real values in Android_SetScreenResolution on 
slouken@4981
    64
// init (before SDL_main())
slouken@4998
    65
int Android_ScreenWidth = 0;
slouken@4998
    66
int Android_ScreenHeight = 0;
slouken@4998
    67
Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_UNKNOWN;
gabomdq@6330
    68
SDL_sem *Android_PauseSem = NULL, *Android_ResumeSem = NULL;
paul@4716
    69
slouken@5001
    70
/* Currently only one window */
slouken@5001
    71
SDL_Window *Android_Window = NULL;
paul@4716
    72
paul@4701
    73
static int
paul@4701
    74
Android_Available(void)
paul@4701
    75
{
paul@4701
    76
    return 1;
paul@4701
    77
}
paul@4701
    78
paul@4701
    79
static void
paul@4701
    80
Android_DeleteDevice(SDL_VideoDevice * device)
paul@4701
    81
{
paul@4701
    82
    SDL_free(device);
paul@4701
    83
}
paul@4701
    84
paul@4701
    85
static SDL_VideoDevice *
paul@4701
    86
Android_CreateDevice(int devindex)
paul@4701
    87
{
paul@4701
    88
    printf("Creating video device\n");
paul@4701
    89
    SDL_VideoDevice *device;
slouken@6555
    90
    SDL_VideoData *data;
paul@4701
    91
paul@4701
    92
    /* Initialize all variables that we clean on shutdown */
paul@4701
    93
    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
paul@4701
    94
    if (!device) {
paul@4701
    95
        SDL_OutOfMemory();
slouken@6555
    96
        return NULL;
paul@4701
    97
    }
paul@4701
    98
slouken@6555
    99
    data = (SDL_VideoData*) SDL_calloc(1, sizeof(SDL_VideoData));
slouken@6555
   100
    if (!data) {
slouken@6555
   101
        SDL_OutOfMemory();
slouken@6555
   102
        SDL_free(device);
slouken@6555
   103
        return NULL;
slouken@6555
   104
    }
slouken@6555
   105
slouken@6555
   106
    device->driverdata = data;
slouken@6555
   107
paul@4701
   108
    /* Set the function pointers */
paul@4701
   109
    device->VideoInit = Android_VideoInit;
paul@4701
   110
    device->VideoQuit = Android_VideoQuit;
paul@4701
   111
    device->PumpEvents = Android_PumpEvents;
slouken@4980
   112
slouken@4998
   113
    device->CreateWindow = Android_CreateWindow;
slouken@4998
   114
    device->SetWindowTitle = Android_SetWindowTitle;
slouken@4998
   115
    device->DestroyWindow = Android_DestroyWindow;
slouken@4998
   116
paul@4701
   117
    device->free = Android_DeleteDevice;
paul@4701
   118
paul@4701
   119
    /* GL pointers */
paul@4701
   120
    device->GL_LoadLibrary = Android_GL_LoadLibrary;
paul@4701
   121
    device->GL_GetProcAddress = Android_GL_GetProcAddress;
paul@4701
   122
    device->GL_UnloadLibrary = Android_GL_UnloadLibrary;
paul@4701
   123
    device->GL_CreateContext = Android_GL_CreateContext;
paul@4701
   124
    device->GL_MakeCurrent = Android_GL_MakeCurrent;
paul@4701
   125
    device->GL_SetSwapInterval = Android_GL_SetSwapInterval;
paul@4701
   126
    device->GL_GetSwapInterval = Android_GL_GetSwapInterval;
paul@4701
   127
    device->GL_SwapWindow = Android_GL_SwapWindow;
paul@4701
   128
    device->GL_DeleteContext = Android_GL_DeleteContext;
paul@4701
   129
slouken@6392
   130
    /* Screen keyboard */
slouken@6392
   131
    device->SDL_HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport;
slouken@6392
   132
    device->SDL_ShowScreenKeyboard = Android_ShowScreenKeyboard;
slouken@6392
   133
    device->SDL_HideScreenKeyboard = Android_HideScreenKeyboard;
slouken@6392
   134
    device->SDL_ToggleScreenKeyboard = Android_ToggleScreenKeyboard;
slouken@6392
   135
    device->SDL_IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
slouken@6392
   136
slouken@6464
   137
    /* Clipboard */
slouken@6464
   138
    device->SetClipboardText = Android_SetClipboardText;
slouken@6464
   139
    device->GetClipboardText = Android_GetClipboardText;
slouken@6464
   140
    device->HasClipboardText = Android_HasClipboardText;
slouken@6464
   141
slouken@6555
   142
    /* Text input */
slouken@6555
   143
    device->StartTextInput = Android_StartTextInput;
slouken@6555
   144
    device->StopTextInput = Android_StopTextInput;
slouken@6555
   145
    device->SetTextInputRect = Android_SetTextInputRect;
slouken@6555
   146
paul@4701
   147
    return device;
paul@4701
   148
}
paul@4701
   149
paul@4701
   150
VideoBootStrap Android_bootstrap = {
paul@4701
   151
    ANDROID_VID_DRIVER_NAME, "SDL Android video driver",
paul@4701
   152
    Android_Available, Android_CreateDevice
paul@4701
   153
};
paul@4701
   154
paul@4701
   155
paul@4701
   156
int
paul@4701
   157
Android_VideoInit(_THIS)
paul@4701
   158
{
paul@4701
   159
    SDL_DisplayMode mode;
paul@4701
   160
slouken@4998
   161
    mode.format = Android_ScreenFormat;
slouken@4998
   162
    mode.w = Android_ScreenWidth;
slouken@4998
   163
    mode.h = Android_ScreenHeight;
paul@4701
   164
    mode.refresh_rate = 0;
paul@4701
   165
    mode.driverdata = NULL;
paul@4701
   166
    if (SDL_AddBasicVideoDisplay(&mode) < 0) {
paul@4701
   167
        return -1;
paul@4701
   168
    }
paul@4701
   169
paul@4701
   170
    SDL_zero(mode);
paul@4701
   171
    SDL_AddDisplayMode(&_this->displays[0], &mode);
paul@4701
   172
slouken@4980
   173
    Android_InitKeyboard();
paul@4713
   174
paul@4701
   175
    /* We're done! */
paul@4701
   176
    return 0;
paul@4701
   177
}
paul@4701
   178
paul@4701
   179
void
paul@4701
   180
Android_VideoQuit(_THIS)
paul@4701
   181
{
paul@4701
   182
}
paul@4701
   183
slouken@4998
   184
/* This function gets called before VideoInit() */
slouken@4981
   185
void
slouken@4981
   186
Android_SetScreenResolution(int width, int height, Uint32 format)
slouken@4981
   187
{
slouken@4998
   188
    Android_ScreenWidth = width;
slouken@4998
   189
    Android_ScreenHeight = height;   
slouken@4998
   190
    Android_ScreenFormat = format;
slouken@5001
   191
slouken@5001
   192
    if (Android_Window) {
slouken@5001
   193
        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESIZED, width, height);
slouken@5001
   194
    }
paul@4716
   195
}
paul@4716
   196
slouken@6044
   197
#endif /* SDL_VIDEO_DRIVER_ANDROID */
slouken@6044
   198
paul@4701
   199
/* vi: set ts=4 sw=4 expandtab: */