mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 18:01:15 +00:00
[x11] Use barriers to trap the pointer in the window
This should be a much friendlier way of "grabbing" input, though I suspect that using raw keyboard events will result in a keyboard grab, which is part of the reason for wanting a friendly grab. There does seem to be a problem with the mouse sneaking out of the top-right and bottom-left corners. I currently suspect a bug in the X server, but further investigation is needed.
This commit is contained in:
parent
3af078b77a
commit
3ac6d2aa22
6 changed files with 149 additions and 13 deletions
|
@ -53,6 +53,26 @@ if test "x$HAVE_XI2" != xno; then
|
|||
fi
|
||||
AC_SUBST(XI2_LIBS)
|
||||
|
||||
dnl Check for XInput2 support
|
||||
AC_ARG_ENABLE(xfixes,
|
||||
[ --disable-xfixes do not use Xorg Xfixes extension],
|
||||
HAVE_XFIXES=$enable_xfixes, HAVE_XFIXES=auto)
|
||||
if test "x$HAVE_XFIXES" != xno; then
|
||||
save_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$X_CFLAGS $CPPFLAGS"
|
||||
AC_CHECK_HEADER(X11/extensions/Xfixes.h,
|
||||
dnl Make sure the library works
|
||||
[AC_CHECK_LIB(Xi, XIQueryVersion,
|
||||
AC_DEFINE(HAVE_XFIXES, 1, [Define if you have the Xorg Xfixes extension])
|
||||
XFIXES_LIBS="-lXfixes",,
|
||||
[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS]
|
||||
)],,
|
||||
[#include <X11/Xlib.h>]
|
||||
)
|
||||
CPPFLAGS="$save_CPPFLAGS"
|
||||
fi
|
||||
AC_SUBST(XFIXES_LIBS)
|
||||
|
||||
dnl Check for DGA support
|
||||
AC_ARG_ENABLE(dga,
|
||||
[ --disable-dga do not use XFree86 DGA extension],
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#define X11_KEY_MASK (KeyPressMask | KeyReleaseMask)
|
||||
#define X11_MOUSE_MASK (ButtonPressMask | ButtonReleaseMask \
|
||||
| PointerMotionMask)
|
||||
#define X11_FOCUS_MASK (FocusChangeMask | EnterWindowMask)
|
||||
#define X11_FOCUS_MASK (FocusChangeMask | EnterWindowMask | LeaveWindowMask)
|
||||
#define X11_INPUT_MASK (X11_KEY_MASK | X11_MOUSE_MASK | X11_FOCUS_MASK)
|
||||
#define X11_MASK (X11_WINDOW_MASK | X11_FOCUS_MASK | PointerMotionMask)
|
||||
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
#ifdef HAVE_XI2
|
||||
# include <X11/extensions/XInput2.h>
|
||||
#endif
|
||||
#ifdef HAVE_XFIXES
|
||||
# include <X11/extensions/Xfixes.h>
|
||||
#endif
|
||||
|
||||
#include "QF/cdaudio.h"
|
||||
#include "QF/cmd.h"
|
||||
|
@ -140,9 +143,16 @@ static IE_key_event_t x11_key;
|
|||
static int input_grabbed = 0;
|
||||
|
||||
static int xi_opcode;
|
||||
static int xf_opcode;
|
||||
static PointerBarrier x11_left_barrier;
|
||||
static PointerBarrier x11_right_barrier;
|
||||
static PointerBarrier x11_top_barrier;
|
||||
static PointerBarrier x11_bottom_barrier;
|
||||
static int x11_have_xi;
|
||||
static int x11_fd;
|
||||
static int x11_driver_handle = -1;
|
||||
static int x11_event_handler_id;
|
||||
static qboolean x11_have_pointer;
|
||||
|
||||
static void
|
||||
dga_on (void)
|
||||
|
@ -211,6 +221,7 @@ in_paste_buffer_f (void)
|
|||
static void
|
||||
enter_notify (XEvent *event)
|
||||
{
|
||||
x11_have_pointer = true;
|
||||
x_time = event->xcrossing.time;
|
||||
|
||||
x11_mouse.x = event->xmotion.x;
|
||||
|
@ -220,6 +231,12 @@ enter_notify (XEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
leave_notify (XEvent *event)
|
||||
{
|
||||
x11_have_pointer = false;
|
||||
}
|
||||
|
||||
static void
|
||||
XLateKey (XKeyEvent *ev, int *k, int *u)
|
||||
{
|
||||
|
@ -905,6 +922,21 @@ xi_raw_button_resease (void *event)
|
|||
xi_raw_button (event, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
xi_barrier_hit (void *event)
|
||||
{
|
||||
__auto_type be = *(XIBarrierEvent *) event;
|
||||
|
||||
if (!x11_have_pointer || !input_grabbed) {
|
||||
XIBarrierReleasePointer (x_disp, be.deviceid, be.barrier, be.eventid);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xi_barrier_leave (void *event)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
event_generic (XEvent *event)
|
||||
{
|
||||
|
@ -913,6 +945,8 @@ event_generic (XEvent *event)
|
|||
[XI_RawMotion] = xi_raw_motion,
|
||||
[XI_RawButtonPress] = xi_raw_button_press,
|
||||
[XI_RawButtonRelease] = xi_raw_button_resease,
|
||||
[XI_BarrierHit] = xi_barrier_hit,
|
||||
[XI_BarrierLeave] = xi_barrier_leave,
|
||||
};
|
||||
XGenericEventCookie *cookie = &event->xcookie;
|
||||
|
||||
|
@ -957,10 +991,14 @@ grab_error (int code, const char *device)
|
|||
static void
|
||||
in_x11_grab_input (void *data, int grab)
|
||||
{
|
||||
return;//FIXME
|
||||
if (!x_disp || !x_win)
|
||||
return;
|
||||
|
||||
if (xf_opcode) {
|
||||
input_grabbed = grab;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vid_fullscreen)
|
||||
grab = grab || vid_fullscreen->int_val;
|
||||
|
||||
|
@ -1207,17 +1245,36 @@ in_x11_check_xi2 (void)
|
|||
Sys_MaskPrintf (SYS_vid, "in_x11_check_xi2: Xlib return bad: %d\n",
|
||||
ret);
|
||||
}
|
||||
Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d\n", major, minor);
|
||||
Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d, op: %d\n",
|
||||
major, minor, xi_opcode);
|
||||
|
||||
if (!XQueryExtension (x_disp, "XFIXES", &xf_opcode, &event, &error)) {
|
||||
Sys_MaskPrintf (SYS_vid, "X fixes extenions not available.\n");
|
||||
return 0;
|
||||
}
|
||||
major = 5, minor = 0;
|
||||
if (!XFixesQueryVersion (x_disp, &major, &minor)
|
||||
|| (major * 10 + minor) < 50) {
|
||||
Sys_MaskPrintf (SYS_vid, "Need X fixes 5.0.\n");
|
||||
return 0;
|
||||
}
|
||||
Sys_MaskPrintf (SYS_vid, "XFixes supported: version %d.%d, op: %d\n",
|
||||
major, minor, xf_opcode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
in_x11_xi_select_events (void)
|
||||
{
|
||||
//Raw events do not have target windows, so must specify the root
|
||||
//window
|
||||
//XISelectEvents(x_disp, x_root, &evmask, 1);
|
||||
//XFlush (x_disp);
|
||||
byte mask[(XI_LASTEVENT + 7) / 8] = {};
|
||||
XIEventMask evmask = {
|
||||
.deviceid = XIAllMasterDevices,
|
||||
.mask_len = sizeof (mask),
|
||||
.mask = mask,
|
||||
};
|
||||
XISetMask (mask, XI_BarrierHit);
|
||||
XISetMask (mask, XI_BarrierLeave);
|
||||
XISelectEvents (x_disp, x_win, &evmask, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1251,6 +1308,61 @@ in_x11_xi_setup_grabs (void)
|
|||
// 0, &evmask, 1, &modif);
|
||||
}
|
||||
|
||||
static void
|
||||
in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen)
|
||||
{
|
||||
if (x11_left_barrier > 0) {
|
||||
XFixesDestroyPointerBarrier (x_disp, x11_left_barrier);
|
||||
}
|
||||
if (x11_right_barrier > 0) {
|
||||
XFixesDestroyPointerBarrier (x_disp, x11_right_barrier);
|
||||
}
|
||||
if (x11_top_barrier > 0) {
|
||||
XFixesDestroyPointerBarrier (x_disp, x11_top_barrier);
|
||||
}
|
||||
if (x11_bottom_barrier > 0) {
|
||||
XFixesDestroyPointerBarrier (x_disp, x11_bottom_barrier);
|
||||
}
|
||||
|
||||
int lx = xpos;
|
||||
int ty = ypos;
|
||||
int rx = xpos + xlen - 1;
|
||||
int by = ypos + ylen - 1;
|
||||
x11_left_barrier = XFixesCreatePointerBarrier (x_disp, x_win,
|
||||
lx, ty-1, lx, by+1,
|
||||
BarrierPositiveX, 0, 0);
|
||||
x11_right_barrier = XFixesCreatePointerBarrier (x_disp, x_win,
|
||||
rx, ty-1, rx, by+1,
|
||||
BarrierNegativeX, 0, 0);
|
||||
x11_top_barrier = XFixesCreatePointerBarrier (x_disp, x_win,
|
||||
lx-1, ty, rx+1, ty,
|
||||
BarrierPositiveY, 0, 0);
|
||||
x11_bottom_barrier = XFixesCreatePointerBarrier (x_disp, x_win,
|
||||
lx-1, by, rx+1, by,
|
||||
BarrierNegativeY, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
x11_app_window (const IE_event_t *ie_event)
|
||||
{
|
||||
__auto_type aw = ie_event->app_window;
|
||||
in_x11_setup_barriers (aw.xpos, aw.ypos, aw.xlen, aw.ylen);
|
||||
}
|
||||
|
||||
static int
|
||||
x11_event_handler (const IE_event_t *ie_event, void *unused)
|
||||
{
|
||||
static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = {
|
||||
[ie_app_window] = x11_app_window,
|
||||
};
|
||||
if (ie_event->type < 0 || ie_event->type >= ie_event_count
|
||||
|| !handlers[ie_event->type]) {
|
||||
return 0;
|
||||
}
|
||||
handlers[ie_event->type] (ie_event);
|
||||
return 1;
|
||||
}
|
||||
|
||||
long
|
||||
IN_X11_Preinit (void)
|
||||
{
|
||||
|
@ -1259,12 +1371,15 @@ IN_X11_Preinit (void)
|
|||
|
||||
long event_mask = X11_INPUT_MASK;
|
||||
|
||||
x11_event_handler_id = IE_Add_Handler (x11_event_handler, 0);
|
||||
|
||||
X11_AddEvent (KeyPress, &event_key);
|
||||
X11_AddEvent (KeyRelease, &event_key);
|
||||
X11_AddEvent (FocusIn, &event_focusin);
|
||||
X11_AddEvent (FocusOut, &event_focusout);
|
||||
X11_AddEvent (SelectionNotify, &selection_notify);
|
||||
X11_AddEvent (EnterNotify, &enter_notify);
|
||||
X11_AddEvent (LeaveNotify, &leave_notify);
|
||||
|
||||
if (!COM_CheckParm ("-nomouse")) {
|
||||
if ((x11_have_xi = in_x11_check_xi2 ())) {
|
||||
|
|
|
@ -134,8 +134,8 @@ nq_x11_libs= \
|
|||
$(nq_client_LIBS)
|
||||
nq_x11_SOURCES= nq/source/sys_unix.c
|
||||
nq_x11_LDADD= $(nq_x11_libs) \
|
||||
$(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \
|
||||
$(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS)
|
||||
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \
|
||||
-lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS)
|
||||
nq_x11_LDFLAGS= $(common_ldflags)
|
||||
nq_x11_DEPENDENCIES= $(nq_x11_libs)
|
||||
|
||||
|
|
|
@ -161,8 +161,9 @@ qw_client_x11_libs= \
|
|||
$(qw_client_LIBS)
|
||||
qw_client_x11_SOURCES= qw/source/cl_sys_unix.c
|
||||
qw_client_x11_LDADD= $(qw_client_x11_libs) \
|
||||
$(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \
|
||||
$(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) $(DL_LIBS)
|
||||
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \
|
||||
-lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) \
|
||||
$(DL_LIBS)
|
||||
qw_client_x11_LDFLAGS= $(common_ldflags)
|
||||
qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs)
|
||||
|
||||
|
|
|
@ -115,8 +115,8 @@ qwaq_x11_libs= \
|
|||
$(qwaq_client_libs)
|
||||
ruamoko_qwaq_qwaq_x11_SOURCES=ruamoko/qwaq/builtins/qwaq.c ruamoko/qwaq/builtins/qwaq-bi.c
|
||||
ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \
|
||||
$(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \
|
||||
$(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS)
|
||||
$(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \
|
||||
-lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS)
|
||||
ruamoko_qwaq_qwaq_x11_LDFLAGS=
|
||||
ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS)
|
||||
|
||||
|
|
Loading…
Reference in a new issue