Use input context in xvideo and xegl.

This commit is contained in:
Themaister 2013-12-08 14:42:03 +01:00
parent 205f8ce90d
commit 07e3c7f7fa
3 changed files with 75 additions and 65 deletions

View File

@ -354,8 +354,6 @@ void x11_handle_key_event(XEvent *event, XIC ic, bool filter)
unsigned key = input_translate_keysym_to_rk(XLookupKeysym(&event->xkey, 0));
int num = 0;
fprintf(stderr, "Key: %u\n", key);
if (down && !filter)
{
KeySym keysym = 0;
@ -365,28 +363,18 @@ void x11_handle_key_event(XEvent *event, XIC ic, bool filter)
// XwcLookupString doesn't seem to work.
num = Xutf8LookupString(ic, &event->xkey, keybuf, ARRAY_SIZE(keybuf), &keysym, &status);
fprintf(stderr, "Status: %d\n", status);
for (i = 0; i < num; i++)
fprintf(stderr, "Char: 0x%x\n", (uint8_t)keybuf[i]);
// libc functions need UTF-8 locale to work properly, which makes mbrtowc a bit impractical.
// Use custom utf8 -> UTF-32 conversion.
num = conv_utf8_utf32(chars, ARRAY_SIZE(chars), keybuf, num);
for (i = 0; i < num; i++)
fprintf(stderr, "UTF32: 0x%u\n", chars[i]);
#else
(void)ic;
num = XLookupString(&event->xkey, keybuf, sizeof(keybuf), &keysym, NULL); // ASCII only.
for (i = 0; i < num; i++)
chars[i] = keybuf[i] & 0x7f;
#endif
fprintf(stderr, "KeySym: %u\n", (unsigned)keysym);
}
fprintf(stderr, "Xwc*: %d\n", num);
unsigned state = event->xkey.state;
uint16_t mod = 0;
mod |= (state & ShiftMask) ? RETROKMOD_SHIFT : 0;
@ -395,8 +383,8 @@ void x11_handle_key_event(XEvent *event, XIC ic, bool filter)
mod |= (state & Mod1Mask) ? RETROKMOD_ALT : 0;
mod |= (state & Mod4Mask) ? RETROKMOD_META : 0;
g_extern.system.key_event(down, key, keybuf[0] == -1u ? 0 : keybuf[0], mod);
g_extern.system.key_event(down, key, chars[0], mod);
for (i = 1; i < num; i++)
g_extern.system.key_event(down, RETROK_UNKNOWN, keybuf[i] == -1u ? 0 : keybuf[i], mod);
g_extern.system.key_event(down, RETROK_UNKNOWN, chars[i], mod);
}

View File

@ -38,6 +38,9 @@ static bool g_has_focus;
static bool g_true_full;
static unsigned g_screen;
static XIM g_xim;
static XIC g_xic;
static EGLContext g_egl_ctx;
static EGLSurface g_egl_surf;
static EGLDisplay g_egl_dpy;
@ -137,6 +140,8 @@ static void gfx_ctx_check_window(bool *quit,
while (XPending(g_dpy))
{
XNextEvent(g_dpy, &event);
bool filter = XFilterEvent(&event, g_win);
switch (event.type)
{
case ClientMessage:
@ -158,7 +163,7 @@ static void gfx_ctx_check_window(bool *quit,
case KeyPress:
case KeyRelease:
x11_handle_key_event(&event, NULL, false);
x11_handle_key_event(&event, g_xic, filter);
break;
}
}
@ -456,6 +461,9 @@ static bool gfx_ctx_set_video_mode(
g_has_focus = true;
g_inited = true;
if (!x11_create_input_context(g_dpy, g_win, &g_xim, &g_xic))
goto error;
driver.display_type = RARCH_DISPLAY_X11;
driver.video_display = (uintptr_t)g_dpy;
driver.video_window = (uintptr_t)g_win;
@ -473,6 +481,7 @@ error:
static void gfx_ctx_destroy(void)
{
x11_destroy_input_context(&g_xim, &g_xic);
if (g_egl_dpy)
{
if (g_egl_ctx)

View File

@ -42,6 +42,8 @@ typedef struct xv
Window window;
Colormap colormap;
XShmSegmentInfo shminfo;
XIM xim;
XIC xic;
Atom quit_atom;
bool focus;
@ -331,6 +333,53 @@ static bool adaptor_set_format(xv_t *xv, Display *dpy, XvPortID port, const vide
return false;
}
static void calc_out_rect(bool keep_aspect, struct rarch_viewport *vp, unsigned vp_width, unsigned vp_height)
{
vp->full_width = vp_width;
vp->full_height = vp_height;
if (g_settings.video.scale_integer)
{
gfx_scale_integer(vp, vp_width, vp_height, g_extern.system.aspect_ratio, keep_aspect);
}
else if (!keep_aspect)
{
vp->x = 0; vp->y = 0;
vp->width = vp_width;
vp->height = vp_height;
}
else
{
float desired_aspect = g_extern.system.aspect_ratio;
float device_aspect = (float)vp_width / vp_height;
// If the aspect ratios of screen and desired aspect ratio are sufficiently equal (floating point stuff),
// assume they are actually equal.
if (fabs(device_aspect - desired_aspect) < 0.0001)
{
vp->x = 0; vp->y = 0;
vp->width = vp_width;
vp->height = vp_height;
}
else if (device_aspect > desired_aspect)
{
float delta = (desired_aspect / device_aspect - 1.0) / 2.0 + 0.5;
vp->x = vp_width * (0.5 - delta);
vp->y = 0;
vp->width = 2.0 * vp_width * delta;
vp->height = vp_height;
}
else
{
float delta = (device_aspect / desired_aspect - 1.0) / 2.0 + 0.5;
vp->x = 0;
vp->y = vp_height * (0.5 - delta);
vp->width = vp_width;
vp->height = 2.0 * vp_height * delta;
}
}
}
static void *xv_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
xv_t *xv = (xv_t*)calloc(1, sizeof(*xv));
@ -489,6 +538,15 @@ static void *xv_init(const video_info_t *video, const input_driver_t **input, vo
init_yuv_tables(xv);
xv_init_font(xv, g_settings.video.font_path, g_settings.video.font_size);
if (!x11_create_input_context(xv->display, xv->window, &xv->xim, &xv->xic))
goto error;
XWindowAttributes target;
XGetWindowAttributes(xv->display, xv->window, &target);
calc_out_rect(xv->keep_aspect, &xv->vp, target.width, target.height);
xv->vp.full_width = target.width;
xv->vp.full_height = target.height;
return xv;
error:
@ -541,53 +599,6 @@ static bool check_resize(xv_t *xv, unsigned width, unsigned height)
return true;
}
static void calc_out_rect(bool keep_aspect, struct rarch_viewport *vp, unsigned vp_width, unsigned vp_height)
{
vp->full_width = vp_width;
vp->full_height = vp_height;
if (g_settings.video.scale_integer)
{
gfx_scale_integer(vp, vp_width, vp_height, g_extern.system.aspect_ratio, keep_aspect);
}
else if (!keep_aspect)
{
vp->x = 0; vp->y = 0;
vp->width = vp_width;
vp->height = vp_height;
}
else
{
float desired_aspect = g_extern.system.aspect_ratio;
float device_aspect = (float)vp_width / vp_height;
// If the aspect ratios of screen and desired aspect ratio are sufficiently equal (floating point stuff),
// assume they are actually equal.
if (fabs(device_aspect - desired_aspect) < 0.0001)
{
vp->x = 0; vp->y = 0;
vp->width = vp_width;
vp->height = vp_height;
}
else if (device_aspect > desired_aspect)
{
float delta = (desired_aspect / device_aspect - 1.0) / 2.0 + 0.5;
vp->x = vp_width * (0.5 - delta);
vp->y = 0;
vp->width = 2.0 * vp_width * delta;
vp->height = vp_height;
}
else
{
float delta = (device_aspect / desired_aspect - 1.0) / 2.0 + 0.5;
vp->x = 0;
vp->y = vp_height * (0.5 - delta);
vp->width = vp_width;
vp->height = 2.0 * vp_height * delta;
}
}
}
// TODO: Is there some way to render directly like GL? :(
// Hacky C code is hacky :D Yay.
static void xv_render_msg(xv_t *xv, const char *msg, unsigned width, unsigned height)
@ -699,7 +710,7 @@ static bool xv_frame(void *data, const void *frame, unsigned width, unsigned hei
calc_out_rect(xv->keep_aspect, &xv->vp, target.width, target.height);
xv->vp.full_width = target.width;
xv->vp.full_height = target.width;
xv->vp.full_height = target.height;
if (msg)
xv_render_msg(xv, msg, width << 1, height << 1);
@ -726,6 +737,8 @@ static bool xv_alive(void *data)
while (XPending(xv->display))
{
XNextEvent(xv->display, &event);
bool filter = XFilterEvent(&event, xv->window);
switch (event.type)
{
case ClientMessage:
@ -743,7 +756,7 @@ static bool xv_alive(void *data)
case KeyPress:
case KeyRelease:
x11_handle_key_event(&event, NULL, false);
x11_handle_key_event(&event, xv->xic, filter);
break;
default:
@ -760,10 +773,10 @@ static bool xv_focus(void *data)
return xv->focus;
}
static void xv_free(void *data)
{
xv_t *xv = (xv_t*)data;
x11_destroy_input_context(&xv->xim, &xv->xic);
XShmDetach(xv->display, &xv->shminfo);
shmdt(xv->shminfo.shmaddr);
shmctl(xv->shminfo.shmid, IPC_RMID, NULL);