From 07e3c7f7fa7d169e209fa4d174d8c82c92772d48 Mon Sep 17 00:00:00 2001 From: Themaister Date: Sun, 8 Dec 2013 14:42:03 +0100 Subject: [PATCH] Use input context in xvideo and xegl. --- gfx/context/x11_common.c | 16 +----- gfx/context/xegl_ctx.c | 11 +++- gfx/xvideo.c | 113 ++++++++++++++++++++++----------------- 3 files changed, 75 insertions(+), 65 deletions(-) diff --git a/gfx/context/x11_common.c b/gfx/context/x11_common.c index 12fbce7766..10dcf086fb 100644 --- a/gfx/context/x11_common.c +++ b/gfx/context/x11_common.c @@ -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); } diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index 1acb042a36..b1a414c6a4 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -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) diff --git a/gfx/xvideo.c b/gfx/xvideo.c index 975d4bd859..86df929751 100644 --- a/gfx/xvideo.c +++ b/gfx/xvideo.c @@ -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);