mirror of
https://github.com/libretro/RetroArch
synced 2025-02-28 12:40:23 +00:00
Merge pull request #11892 from jdgleaver/x11-mouse-grab-fix
(X11) Fix mouse input when mouse is grabbed
This commit is contained in:
commit
40b3e4c00f
@ -37,11 +37,15 @@ typedef struct x11_input
|
||||
Display *display;
|
||||
Window win;
|
||||
|
||||
int mouse_x, mouse_y;
|
||||
int mouse_last_x, mouse_last_y;
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
int mouse_delta_x;
|
||||
int mouse_delta_y;
|
||||
bool mouse_grabbed;
|
||||
char state[32];
|
||||
bool mouse_l, mouse_r, mouse_m;
|
||||
bool mouse_l;
|
||||
bool mouse_r;
|
||||
bool mouse_m;
|
||||
} x11_input_t;
|
||||
|
||||
/* Public global variable */
|
||||
@ -222,11 +226,11 @@ static int16_t x_input_state(
|
||||
case RETRO_DEVICE_ID_MOUSE_X:
|
||||
if (device == RARCH_DEVICE_MOUSE_SCREEN)
|
||||
return x11->mouse_x;
|
||||
return x11->mouse_x - x11->mouse_last_x;
|
||||
return x11->mouse_delta_x;
|
||||
case RETRO_DEVICE_ID_MOUSE_Y:
|
||||
if (device == RARCH_DEVICE_MOUSE_SCREEN)
|
||||
return x11->mouse_y;
|
||||
return x11->mouse_y - x11->mouse_last_y;
|
||||
return x11->mouse_delta_y;
|
||||
case RETRO_DEVICE_ID_MOUSE_LEFT:
|
||||
return x11->mouse_l;
|
||||
case RETRO_DEVICE_ID_MOUSE_RIGHT:
|
||||
@ -592,9 +596,9 @@ static int16_t x_input_state(
|
||||
break;
|
||||
/*deprecated*/
|
||||
case RETRO_DEVICE_ID_LIGHTGUN_X:
|
||||
return x11->mouse_x - x11->mouse_last_x;
|
||||
return x11->mouse_delta_x;
|
||||
case RETRO_DEVICE_ID_LIGHTGUN_Y:
|
||||
return x11->mouse_y - x11->mouse_last_y;
|
||||
return x11->mouse_delta_y;
|
||||
case RETRO_DEVICE_ID_LIGHTGUN_PAUSE:
|
||||
{
|
||||
unsigned new_id = RARCH_LIGHTGUN_START;
|
||||
@ -637,71 +641,140 @@ static void x_input_free(void *data)
|
||||
|
||||
static void x_input_poll(void *data)
|
||||
{
|
||||
unsigned mask;
|
||||
int root_x, root_y, win_x, win_y;
|
||||
Window root_win, child_win;
|
||||
Window root_win;
|
||||
Window child_win;
|
||||
x11_input_t *x11 = (x11_input_t*)data;
|
||||
bool video_has_focus = video_driver_has_focus();
|
||||
int root_x = 0;
|
||||
int root_y = 0;
|
||||
int win_x = 0;
|
||||
int win_y = 0;
|
||||
unsigned mask = 0;
|
||||
|
||||
if (video_has_focus)
|
||||
XQueryKeymap(x11->display, x11->state);
|
||||
else
|
||||
memset(x11->state, 0, sizeof(x11->state));
|
||||
|
||||
x11->mouse_last_x = x11->mouse_x;
|
||||
x11->mouse_last_y = x11->mouse_y;
|
||||
|
||||
XQueryPointer(x11->display,
|
||||
x11->win,
|
||||
&root_win, &child_win,
|
||||
&root_x, &root_y,
|
||||
&win_x, &win_y,
|
||||
&mask);
|
||||
|
||||
if (g_x11_entered)
|
||||
/* If window loses focus, 'reset' keyboard
|
||||
* and ignore mouse input */
|
||||
if (!video_has_focus)
|
||||
{
|
||||
x11->mouse_x = win_x;
|
||||
x11->mouse_y = win_y;
|
||||
x11->mouse_l = mask & Button1Mask;
|
||||
x11->mouse_m = mask & Button2Mask;
|
||||
x11->mouse_r = mask & Button3Mask;
|
||||
memset(x11->state, 0, sizeof(x11->state));
|
||||
x11->mouse_delta_x = 0;
|
||||
x11->mouse_delta_y = 0;
|
||||
x11->mouse_l = 0;
|
||||
x11->mouse_m = 0;
|
||||
x11->mouse_r = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Major grab kludge required to circumvent
|
||||
* absolute pointer area limitation
|
||||
* AND to be able to use mouse in menu
|
||||
*/
|
||||
if (x11->mouse_grabbed && video_has_focus)
|
||||
/* If pointer is not inside the application
|
||||
* window, ignore mouse input */
|
||||
if (!g_x11_entered)
|
||||
{
|
||||
x11->mouse_delta_x = 0;
|
||||
x11->mouse_delta_y = 0;
|
||||
x11->mouse_l = 0;
|
||||
x11->mouse_m = 0;
|
||||
x11->mouse_r = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process keyboard */
|
||||
XQueryKeymap(x11->display, x11->state);
|
||||
|
||||
/* Process mouse */
|
||||
if (!XQueryPointer(x11->display,
|
||||
x11->win,
|
||||
&root_win, &child_win,
|
||||
&root_x, &root_y,
|
||||
&win_x, &win_y,
|
||||
&mask))
|
||||
return;
|
||||
|
||||
/* > Mouse buttons */
|
||||
x11->mouse_l = mask & Button1Mask;
|
||||
x11->mouse_m = mask & Button2Mask;
|
||||
x11->mouse_r = mask & Button3Mask;
|
||||
|
||||
/* > Mouse pointer */
|
||||
if (!x11->mouse_grabbed)
|
||||
{
|
||||
/* Mouse is not grabbed - this corresponds
|
||||
* to 'conventional' pointer input, using
|
||||
* absolute screen coordinates */
|
||||
int mouse_last_x = x11->mouse_x;
|
||||
int mouse_last_y = x11->mouse_y;
|
||||
|
||||
x11->mouse_x = win_x;
|
||||
x11->mouse_y = win_y;
|
||||
|
||||
x11->mouse_delta_x = x11->mouse_x - mouse_last_x;
|
||||
x11->mouse_delta_y = x11->mouse_y - mouse_last_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mouse is grabbed - all pointer movement
|
||||
* must be considered 'relative' */
|
||||
XWindowAttributes win_attr;
|
||||
int centre_x;
|
||||
int centre_y;
|
||||
int warp_x = win_x;
|
||||
int warp_y = win_y;
|
||||
bool do_warp = false;
|
||||
|
||||
/* Get dimensions/centre coordinates of
|
||||
* application window */
|
||||
if (!XGetWindowAttributes(x11->display, x11->win, &win_attr))
|
||||
{
|
||||
int new_x = win_x, new_y = win_y;
|
||||
int margin = 0;
|
||||
float margin_pct = 0.05f;
|
||||
struct video_viewport vp;
|
||||
x11->mouse_delta_x = 0;
|
||||
x11->mouse_delta_y = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
video_driver_get_viewport_info(&vp);
|
||||
centre_x = win_attr.width >> 1;
|
||||
centre_y = win_attr.height >> 1;
|
||||
|
||||
margin = ((vp.full_height < vp.full_width) ? vp.full_height : vp.full_width) * margin_pct;
|
||||
/* Get relative movement delta since last
|
||||
* poll event */
|
||||
x11->mouse_delta_x = win_x - centre_x;
|
||||
x11->mouse_delta_y = win_y - centre_y;
|
||||
|
||||
if (win_x + 1 > vp.full_width - margin)
|
||||
new_x = vp.full_width - margin;
|
||||
else if (win_x + 1 < margin)
|
||||
new_x = margin;
|
||||
/* Get effective 'absolute' pointer location
|
||||
* (last position + delta, bounded by current
|
||||
* application window dimensions) */
|
||||
x11->mouse_x += x11->mouse_delta_x;
|
||||
x11->mouse_x = (x11->mouse_x < 0) ? 0 : x11->mouse_x;
|
||||
x11->mouse_x = (x11->mouse_x >= win_attr.width) ? (win_attr.width - 1) : x11->mouse_x;
|
||||
|
||||
if (win_y + 1 > vp.full_height - margin)
|
||||
new_y = vp.full_height - margin;
|
||||
else if (win_y + 1 < margin)
|
||||
new_y = margin;
|
||||
x11->mouse_y += x11->mouse_delta_y;
|
||||
x11->mouse_y = (x11->mouse_y < 0) ? 0 : x11->mouse_y;
|
||||
x11->mouse_y = (x11->mouse_y >= win_attr.height) ? (win_attr.height - 1) : x11->mouse_y;
|
||||
|
||||
if (new_x != win_x || new_y != win_y)
|
||||
{
|
||||
XWarpPointer(x11->display, None, x11->win,
|
||||
0, 0, 0 ,0,
|
||||
new_x, new_y);
|
||||
/* Hack/workaround:
|
||||
* - X11 gives absolute pointer coordinates
|
||||
* - Once the pointer reaches a screen edge
|
||||
* it cannot go any further
|
||||
* - To achieve 'relative' motion, we therefore
|
||||
* have to reset the hardware cursor to the
|
||||
* centre of the screen after polling each
|
||||
* movement delta, such that it is always
|
||||
* free to move in all directions during the
|
||||
* time interval until the next poll event */
|
||||
if (win_x != centre_x)
|
||||
{
|
||||
warp_x = centre_x;
|
||||
do_warp = true;
|
||||
}
|
||||
|
||||
XSync(x11->display, False);
|
||||
}
|
||||
if (win_y != centre_y)
|
||||
{
|
||||
warp_y = centre_y;
|
||||
do_warp = true;
|
||||
}
|
||||
|
||||
x11->mouse_last_x = new_x + x11->mouse_last_x - x11->mouse_x;
|
||||
x11->mouse_last_y = new_y + x11->mouse_last_y - x11->mouse_y;
|
||||
if (do_warp)
|
||||
{
|
||||
XWarpPointer(x11->display, None,
|
||||
x11->win, 0, 0, 0, 0,
|
||||
warp_x, warp_y);
|
||||
XSync(x11->display, False);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6606,6 +6606,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
unsigned
|
||||
materialui_color_theme = video_info->materialui_color_theme;
|
||||
bool video_fullscreen = video_info->fullscreen;
|
||||
bool mouse_grabbed = video_info->input_driver_grab_mouse_state;
|
||||
bool menu_mouse_enable = video_info->menu_mouse_enable;
|
||||
gfx_animation_t *p_anim = anim_get_ptr();
|
||||
|
||||
@ -6791,14 +6792,14 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
/* Draw mouse cursor */
|
||||
if (mui->mouse_show && (mui->pointer.type != MENU_POINTER_DISABLED))
|
||||
{
|
||||
float color_white[16] = {
|
||||
float color_white[16] = {
|
||||
1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f
|
||||
};
|
||||
bool cursor_visible = video_fullscreen
|
||||
&& menu_mouse_enable;
|
||||
bool cursor_visible = (video_fullscreen || mouse_grabbed) &&
|
||||
menu_mouse_enable;
|
||||
|
||||
if (cursor_visible)
|
||||
gfx_display_draw_cursor(
|
||||
|
@ -2780,6 +2780,7 @@ static void ozone_frame(void *data, video_frame_info_t *video_info)
|
||||
float menu_framebuffer_opacity = video_info->menu_framebuffer_opacity;
|
||||
bool libretro_running = video_info->libretro_running;
|
||||
bool video_fullscreen = video_info->fullscreen;
|
||||
bool mouse_grabbed = video_info->input_driver_grab_mouse_state;
|
||||
bool menu_mouse_enable = video_info->menu_mouse_enable;
|
||||
bool input_menu_swap_ok_cancel_buttons = video_info->input_menu_swap_ok_cancel_buttons;
|
||||
bool battery_level_enable = video_info->battery_level_enable;
|
||||
@ -3032,7 +3033,8 @@ static void ozone_frame(void *data, video_frame_info_t *video_info)
|
||||
/* Cursor */
|
||||
if (ozone->show_cursor && (ozone->pointer.type != MENU_POINTER_DISABLED))
|
||||
{
|
||||
bool cursor_visible = video_fullscreen && menu_mouse_enable;
|
||||
bool cursor_visible = (video_fullscreen || mouse_grabbed) &&
|
||||
menu_mouse_enable;
|
||||
|
||||
gfx_display_set_alpha(ozone->pure_white, 1.0f);
|
||||
if (cursor_visible)
|
||||
|
@ -2791,6 +2791,7 @@ static void stripes_frame(void *data, video_frame_info_t *video_info)
|
||||
float xmb_alpha_factor = video_info->xmb_alpha_factor;
|
||||
bool xmb_shadows_enable = video_info->xmb_shadows_enable;
|
||||
bool video_fullscreen = video_info->fullscreen;
|
||||
bool mouse_grabbed = video_info->input_driver_grab_mouse_state;
|
||||
bool menu_mouse_enable = video_info->menu_mouse_enable;
|
||||
const float under_thumb_margin = 0.96;
|
||||
float scale_factor = 0.0f;
|
||||
@ -3029,8 +3030,8 @@ static void stripes_frame(void *data, video_frame_info_t *video_info)
|
||||
if (stripes->mouse_show)
|
||||
{
|
||||
menu_input_pointer_t pointer;
|
||||
bool cursor_visible = video_fullscreen
|
||||
&& menu_mouse_enable;
|
||||
bool cursor_visible = (video_fullscreen || mouse_grabbed) &&
|
||||
menu_mouse_enable;
|
||||
|
||||
menu_input_get_pointer_state(&pointer);
|
||||
|
||||
|
@ -4653,6 +4653,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
|
||||
bool timedate_enable = video_info->timedate_enable;
|
||||
bool battery_level_enable = video_info->battery_level_enable;
|
||||
bool video_fullscreen = video_info->fullscreen;
|
||||
bool mouse_grabbed = video_info->input_driver_grab_mouse_state;
|
||||
bool menu_mouse_enable = video_info->menu_mouse_enable;
|
||||
unsigned xmb_color_theme = video_info->xmb_color_theme;
|
||||
bool libretro_running = video_info->libretro_running;
|
||||
@ -5286,8 +5287,8 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
|
||||
/* Cursor image */
|
||||
if (xmb->mouse_show)
|
||||
{
|
||||
bool cursor_visible = video_fullscreen
|
||||
&& menu_mouse_enable;
|
||||
bool cursor_visible = (video_fullscreen || mouse_grabbed) &&
|
||||
menu_mouse_enable;
|
||||
|
||||
gfx_display_set_alpha(coord_white, MIN(xmb->alpha, 1.00f));
|
||||
if (cursor_visible)
|
||||
|
24
retroarch.c
24
retroarch.c
@ -14389,8 +14389,10 @@ bool command_event(enum event_command cmd, void *data)
|
||||
break;
|
||||
case CMD_EVENT_GRAB_MOUSE_TOGGLE:
|
||||
{
|
||||
bool ret = false;
|
||||
bool ret = false;
|
||||
bool grab_mouse_state = p_rarch->input_driver_grab_mouse_state;
|
||||
bool video_fullscreen =
|
||||
settings->bools.video_fullscreen || p_rarch->rarch_force_fullscreen;
|
||||
|
||||
grab_mouse_state = !grab_mouse_state;
|
||||
|
||||
@ -14408,7 +14410,7 @@ bool command_event(enum event_command cmd, void *data)
|
||||
|
||||
if (grab_mouse_state)
|
||||
video_driver_hide_mouse();
|
||||
else
|
||||
else if (!video_fullscreen)
|
||||
video_driver_show_mouse();
|
||||
}
|
||||
break;
|
||||
@ -24762,6 +24764,12 @@ bool input_key_pressed(int key, bool keyboard_pressed)
|
||||
key);
|
||||
}
|
||||
|
||||
bool input_mouse_grabbed(void)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
return p_rarch->input_driver_grab_mouse_state;
|
||||
}
|
||||
|
||||
int16_t button_is_pressed(
|
||||
const input_device_driver_t *joypad,
|
||||
rarch_joypad_info_t *joypad_info,
|
||||
@ -29880,7 +29888,15 @@ static bool video_driver_init_internal(bool *video_is_threaded)
|
||||
if ((enum rotation)settings->uints.screen_orientation != ORIENTATION_NORMAL)
|
||||
video_display_server_set_screen_orientation((enum rotation)settings->uints.screen_orientation);
|
||||
|
||||
if (video.fullscreen)
|
||||
/* Ensure that we preserve the 'grab mouse'
|
||||
* state if it was enabled prior to driver
|
||||
* (re-)initialisation */
|
||||
if (p_rarch->input_driver_grab_mouse_state)
|
||||
{
|
||||
video_driver_hide_mouse();
|
||||
input_driver_grab_mouse(p_rarch);
|
||||
}
|
||||
else if (video.fullscreen)
|
||||
{
|
||||
video_driver_hide_mouse();
|
||||
if (!settings->bools.video_windowed_fullscreen)
|
||||
@ -31514,6 +31530,8 @@ void video_driver_build_info(video_frame_info_t *video_info)
|
||||
video_info->runloop_is_slowmotion = p_rarch->runloop_slowmotion;
|
||||
|
||||
video_info->input_driver_nonblock_state = p_rarch->input_driver_nonblock_state;
|
||||
video_info->input_driver_grab_mouse_state = p_rarch->input_driver_grab_mouse_state;
|
||||
|
||||
video_info->userdata = VIDEO_DRIVER_GET_PTR_INTERNAL(false);
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
|
@ -1182,6 +1182,7 @@ typedef struct video_frame_info
|
||||
bool widgets_is_rewinding;
|
||||
bool input_menu_swap_ok_cancel_buttons;
|
||||
bool input_driver_nonblock_state;
|
||||
bool input_driver_grab_mouse_state;
|
||||
bool hard_sync;
|
||||
bool fps_show;
|
||||
bool memory_show;
|
||||
@ -1981,6 +1982,8 @@ void retroarch_init_task_queue(void);
|
||||
|
||||
bool input_key_pressed(int key, bool keyboard_pressed);
|
||||
|
||||
bool input_mouse_grabbed(void);
|
||||
|
||||
const char *joypad_driver_name(unsigned i);
|
||||
void joypad_driver_reinit(void *data, const char *joypad_driver_name);
|
||||
|
||||
|
@ -656,6 +656,7 @@ static void ui_companion_qt_toggle(void *data, bool force)
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool ui_companion_toggle = settings->bools.ui_companion_toggle;
|
||||
bool video_fullscreen = settings->bools.video_fullscreen;
|
||||
bool mouse_grabbed = input_mouse_grabbed();
|
||||
|
||||
if (ui_companion_toggle || force)
|
||||
{
|
||||
@ -664,7 +665,11 @@ static void ui_companion_qt_toggle(void *data, bool force)
|
||||
|
||||
win_handle->qtWindow->activateWindow();
|
||||
win_handle->qtWindow->raise();
|
||||
|
||||
if (mouse_grabbed)
|
||||
command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL);
|
||||
video_driver_show_mouse();
|
||||
|
||||
win_handle->qtWindow->show();
|
||||
|
||||
if (video_driver_started_fullscreen())
|
||||
|
Loading…
x
Reference in New Issue
Block a user