未验证 提交 ce89ae10 编写于 作者: J Jim 提交者: GitHub

Merge pull request #1181 from admshao/linux-mouse-extra-buttons

XInput Support
......@@ -21,6 +21,7 @@
# XCB_GLX_FOUND XCB_GLX_INCLUDE_DIR XCB_GLX_LIBRARY
# XCB_SHM_FOUND XCB_SHM_INCLUDE_DIR XCB_SHM_LIBRARY
# XCB_XV_FOUND XCB_XV_INCLUDE_DIR XCB_XV_LIBRARY
# XCB_XINPUT_FOUND XCB_XINPUT_INCLUDE_DIR XCB_XINPUT_LIBRARY
# XCB_SYNC_FOUND XCB_SYNC_INCLUDE_DIR XCB_SYNC_LIBRARY
# XCB_XTEST_FOUND XCB_XTEST_INCLUDE_DIR XCB_XTEST_LIBRARY
# XCB_ICCCM_FOUND XCB_ICCCM_INCLUDE_DIR XCB_ICCCM_LIBRARY
......@@ -54,6 +55,7 @@ set(knownComponents XCB
XFIXES
XTEST
XV
XINPUT
XINERAMA)
unset(unknownComponents)
......@@ -112,6 +114,8 @@ foreach(comp ${comps})
list(APPEND pkgConfigModules "xcb-xtest")
elseif("${comp}" STREQUAL "XV")
list(APPEND pkgConfigModules "xcb-xv")
elseif("${comp}" STREQUAL "XINPUT")
list(APPEND pkgConfigModules "xcb-xinput")
elseif("${comp}" STREQUAL "XINERAMA")
list(APPEND pkgConfigModules "xcb-xinerama")
endif()
......@@ -190,6 +194,9 @@ macro(_XCB_HANDLE_COMPONENT _comp)
elseif("${_comp}" STREQUAL "XV")
set(_header "xcb/xv.h")
set(_lib "xcb-xv")
elseif("${_comp}" STREQUAL "XINPUT")
set(_header "xcb/xinput.h")
set(_lib "xcb-xinput")
elseif("${_comp}" STREQUAL "XINERAMA")
set(_header "xcb/xinerama.h")
set(_lib "xcb-xinerama")
......
......@@ -13,6 +13,13 @@ endif()
if(UNIX)
if (NOT APPLE)
find_package(X11_XCB REQUIRED)
find_package(XCB OPTIONAL_COMPONENTS XINPUT)
if (XCB_XINPUT_FOUND)
set(USE_XINPUT "1")
else()
set(USE_XINPUT "0")
endif()
find_package(PulseAudio)
if (NOT "${PULSEAUDIO_LIBRARY}" STREQUAL "")
message(STATUS "Found PulseAudio - Audio Monitor enabled")
......@@ -22,14 +29,13 @@ if(UNIX)
endif()
else()
set(HAVE_PULSEAUDIO "0")
set(USE_XINPUT "0")
endif()
find_package(DBus QUIET)
if (NOT APPLE)
find_package(X11_XCB REQUIRED)
endif()
else()
set(HAVE_DBUS "0")
set(HAVE_PULSEAUDIO "0")
set(USE_XINPUT "0")
endif()
find_package(ImageMagick QUIET COMPONENTS MagickCore)
......@@ -199,6 +205,16 @@ elseif(UNIX)
${libobs_PLATFORM_DEPS}
${X11_XCB_LIBRARIES})
if(USE_XINPUT)
include_directories(
${XCB_XINPUT_INCLUDE_DIR})
add_definitions(
${XCB_DEFINITIONS})
set(libobs_PLATFORM_DEPS
${XCB_XINPUT_LIBRARY}
${libobs_PLATFORM_DEPS})
endif()
if(HAVE_PULSEAUDIO)
set(libobs_PLATFORM_DEPS
${libobs_PLATFORM_DEPS}
......
......@@ -32,6 +32,8 @@ const size_t OBS_INVALID_HOTKEY_ID = (size_t)-1;
const size_t OBS_INVALID_HOTKEY_PAIR_ID = (size_t)-1;
#endif
#define XINPUT_MOUSE_LEN 33
enum obs_key {
#define OBS_HOTKEY(x) x,
#include "obs-hotkeys.h"
......
......@@ -16,6 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include "obs-internal.h"
#if defined(__FreeBSD__)
#define _GNU_SOURCE
#endif
......@@ -28,13 +29,13 @@
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#include <xcb/xcb.h>
#if USE_XINPUT
#include <xcb/xinput.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlib-xcb.h>
#include <X11/keysym.h>
#include <inttypes.h>
#include "util/dstr.h"
#include "obs-internal.h"
const char *get_module_extension(void)
{
......@@ -356,6 +357,12 @@ struct obs_hotkeys_platform {
xcb_keysym_t *keysyms;
int num_keysyms;
int syms_per_code;
#if USE_XINPUT
bool pressed[XINPUT_MOUSE_LEN];
bool update[XINPUT_MOUSE_LEN];
bool button_pressed[XINPUT_MOUSE_LEN];
#endif
};
#define MOUSE_1 (1<<16)
......@@ -736,6 +743,54 @@ error1:
return error != NULL || reply == NULL;
}
static xcb_screen_t *default_screen(obs_hotkeys_platform_t *context,
xcb_connection_t *connection)
{
int def_screen_idx = XDefaultScreen(context->display);
xcb_screen_iterator_t iter;
iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
while (iter.rem) {
if (def_screen_idx-- == 0)
return iter.data;
xcb_screen_next(&iter);
}
return NULL;
}
static inline xcb_window_t root_window(obs_hotkeys_platform_t *context,
xcb_connection_t *connection)
{
xcb_screen_t *screen = default_screen(context, connection);
if (screen)
return screen->root;
return 0;
}
#if USE_XINPUT
static inline void registerMouseEvents(struct obs_core_hotkeys *hotkeys)
{
obs_hotkeys_platform_t *context = hotkeys->platform_context;
xcb_connection_t *connection = XGetXCBConnection(
context->display);
xcb_window_t window = root_window(context, connection);
struct {
xcb_input_event_mask_t head;
xcb_input_xi_event_mask_t mask;
} mask;
mask.head.deviceid = XCB_INPUT_DEVICE_ALL_MASTER;
mask.head.mask_len = sizeof(mask.mask) / sizeof(uint32_t);
mask.mask = XCB_INPUT_XI_EVENT_MASK_RAW_BUTTON_PRESS |
XCB_INPUT_XI_EVENT_MASK_RAW_BUTTON_RELEASE;
xcb_input_xi_select_events(connection, window, 1, &mask.head);
xcb_flush(connection);
}
#endif
bool obs_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys)
{
Display *display = XOpenDisplay(NULL);
......@@ -745,6 +800,9 @@ bool obs_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys)
hotkeys->platform_context = bzalloc(sizeof(obs_hotkeys_platform_t));
hotkeys->platform_context->display = display;
#if USE_XINPUT
registerMouseEvents(hotkeys);
#endif
fill_base_keysyms(hotkeys);
fill_keycodes(hotkeys);
return true;
......@@ -764,41 +822,147 @@ void obs_hotkeys_platform_free(struct obs_core_hotkeys *hotkeys)
hotkeys->platform_context = NULL;
}
static xcb_screen_t *default_screen(obs_hotkeys_platform_t *context,
xcb_connection_t *connection)
static bool mouse_button_pressed(xcb_connection_t *connection,
obs_hotkeys_platform_t *context, obs_key_t key)
{
int def_screen_idx = XDefaultScreen(context->display);
xcb_screen_iterator_t iter;
bool ret = false;
iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
while (iter.rem) {
if (def_screen_idx-- == 0) {
return iter.data;
break;
#if USE_XINPUT
memset(context->pressed, 0, XINPUT_MOUSE_LEN);
memset(context->update, 0, XINPUT_MOUSE_LEN);
xcb_generic_event_t *ev;
while ((ev = xcb_poll_for_event(connection))) {
if ((ev->response_type & ~80) == XCB_GE_GENERIC) {
switch (((xcb_ge_event_t *) ev)->event_type) {
case XCB_INPUT_RAW_BUTTON_PRESS: {
xcb_input_raw_button_press_event_t *mot;
mot = (xcb_input_raw_button_press_event_t *) ev;
if (mot->detail < XINPUT_MOUSE_LEN) {
context->pressed[mot->detail-1] = true;
context->update[mot->detail-1] = true;
} else {
blog(LOG_WARNING, "Unsupported button");
}
break;
}
case XCB_INPUT_RAW_BUTTON_RELEASE: {
xcb_input_raw_button_release_event_t *mot;
mot = (xcb_input_raw_button_release_event_t *) ev;
if (mot->detail < XINPUT_MOUSE_LEN)
context->update[mot->detail-1] = true;
else
blog(LOG_WARNING, "Unsupported button");
break;
}
default:
break;
}
}
xcb_screen_next(&iter);
free(ev);
}
return NULL;
}
static inline xcb_window_t root_window(obs_hotkeys_platform_t *context,
xcb_connection_t *connection)
{
xcb_screen_t *screen = default_screen(context, connection);
if (screen)
return screen->root;
return 0;
}
// Mouse 2 for OBS is Right Click and Mouse 3 is Wheel Click.
// Mouse Wheel axis clicks (xinput mot->detail 4 5 6 7) are ignored.
switch (key) {
case OBS_KEY_MOUSE1:
ret = context->pressed[0] || context->button_pressed[0];
break;
case OBS_KEY_MOUSE2:
ret = context->pressed[2] || context->button_pressed[2];
break;
case OBS_KEY_MOUSE3:
ret = context->pressed[1] || context->button_pressed[1];
break;
case OBS_KEY_MOUSE4:
ret = context->pressed[7] || context->button_pressed[7];
break;
case OBS_KEY_MOUSE5:
ret = context->pressed[8] || context->button_pressed[8];
break;
case OBS_KEY_MOUSE6:
ret = context->pressed[9] || context->button_pressed[9];
break;
case OBS_KEY_MOUSE7:
ret = context->pressed[10] || context->button_pressed[10];
break;
case OBS_KEY_MOUSE8:
ret = context->pressed[11] || context->button_pressed[11];
break;
case OBS_KEY_MOUSE9:
ret = context->pressed[12] || context->button_pressed[12];
break;
case OBS_KEY_MOUSE10:
ret = context->pressed[13] || context->button_pressed[13];
break;
case OBS_KEY_MOUSE11:
ret = context->pressed[14] || context->button_pressed[14];
break;
case OBS_KEY_MOUSE12:
ret = context->pressed[15] || context->button_pressed[15];
break;
case OBS_KEY_MOUSE13:
ret = context->pressed[16] || context->button_pressed[16];
break;
case OBS_KEY_MOUSE14:
ret = context->pressed[17] || context->button_pressed[17];
break;
case OBS_KEY_MOUSE15:
ret = context->pressed[18] || context->button_pressed[18];
break;
case OBS_KEY_MOUSE16:
ret = context->pressed[19] || context->button_pressed[19];
break;
case OBS_KEY_MOUSE17:
ret = context->pressed[20] || context->button_pressed[20];
break;
case OBS_KEY_MOUSE18:
ret = context->pressed[21] || context->button_pressed[21];
break;
case OBS_KEY_MOUSE19:
ret = context->pressed[22] || context->button_pressed[22];
break;
case OBS_KEY_MOUSE20:
ret = context->pressed[23] || context->button_pressed[23];
break;
case OBS_KEY_MOUSE21:
ret = context->pressed[24] || context->button_pressed[24];
break;
case OBS_KEY_MOUSE22:
ret = context->pressed[25] || context->button_pressed[25];
break;
case OBS_KEY_MOUSE23:
ret = context->pressed[26] || context->button_pressed[26];
break;
case OBS_KEY_MOUSE24:
ret = context->pressed[27] || context->button_pressed[27];
break;
case OBS_KEY_MOUSE25:
ret = context->pressed[28] || context->button_pressed[28];
break;
case OBS_KEY_MOUSE26:
ret = context->pressed[29] || context->button_pressed[29];
break;
case OBS_KEY_MOUSE27:
ret = context->pressed[30] || context->button_pressed[30];
break;
case OBS_KEY_MOUSE28:
ret = context->pressed[31] || context->button_pressed[31];
break;
case OBS_KEY_MOUSE29:
ret = context->pressed[32] || context->button_pressed[32];
break;
default:
break;
}
static bool mouse_button_pressed(xcb_connection_t *connection,
obs_hotkeys_platform_t *context, obs_key_t key)
{
for (int i = 0; i != XINPUT_MOUSE_LEN; i++)
if (context->update[i])
context->button_pressed[i] = context->pressed[i];
#else
xcb_generic_error_t *error = NULL;
xcb_query_pointer_cookie_t qpc;
xcb_query_pointer_reply_t *reply;
bool ret = false;
qpc = xcb_query_pointer(connection, root_window(context, connection));
reply = xcb_query_pointer_reply(connection, qpc, &error);
......@@ -818,6 +982,7 @@ static bool mouse_button_pressed(xcb_connection_t *connection,
free(reply);
free(error);
#endif
return ret;
}
......
......@@ -18,6 +18,7 @@
#define BUILD_CAPTIONS @BUILD_CAPTIONS@
#define HAVE_DBUS @HAVE_DBUS@
#define HAVE_PULSEAUDIO @HAVE_PULSEAUDIO@
#define USE_XINPUT @USE_XINPUT@
#define LIBOBS_IMAGEMAGICK_DIR_STYLE_6L 6
#define LIBOBS_IMAGEMAGICK_DIR_STYLE_7GE 7
#define LIBOBS_IMAGEMAGICK_DIR_STYLE @LIBOBS_IMAGEMAGICK_DIR_STYLE@
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册