Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 159 additions & 1 deletion BetterMouseYoke/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* replaces it with a more sane system for those who, for whatever reason,
* want to or have to use the mouse for flying.
*
* Copyright 2019 Torben K�nke.
* Copyright 2019 Torben Könke.
*/
#include "plugin.h"

Expand Down Expand Up @@ -45,6 +45,15 @@ static HCURSOR yoke_cursor;
static HCURSOR rudder_cursor;
static HCURSOR arrow_cursor;
static HCURSOR(WINAPI *true_set_cursor) (HCURSOR cursor) = SetCursor;
#elif LIN
Display *dpy;
XEvent ev;
XIEvent *xi_event;
XIRawEvent *xev;
Cursor cross;
Cursor arrows;
Cursor def;
Window window;
#endif

/**
Expand Down Expand Up @@ -118,6 +127,28 @@ PLUGIN_API int XPluginStart(char *name, char *sig, char *desc) {
_log("could not load arrow_cursor");
return 0;
}
#elif LIN
int xi_opcode, event, error;

dpy = XOpenDisplay(NULL);
if (!dpy) {
_log("Failed to open display.\n");
return 0;
}

window = XDefaultRootWindow(dpy);
if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) {
_log("X Input extension not available.\n");
return 0;
}

if (!has_xi2(dpy))
return 0;

def = XcursorLibraryLoadCursor(dpy, "left_ptr");
cross = XcursorLibraryLoadCursor(dpy, "cross");
arrows = XcursorLibraryLoadCursor(dpy, "sb_h_double_arrow");

#endif
return 1;
}
Expand All @@ -132,6 +163,13 @@ PLUGIN_API void XPluginStop(void) {
if (!hook_set_cursor(0)) {
_log("could not unhook SetCursor function");
}
#elif LIN
XDefineCursor(dpy, window, def);
XFreeCursor(dpy, cross);
XFreeCursor(dpy, arrows);
XFreeCursor(dpy, def);
XFlush(dpy);
XCloseDisplay(dpy);
#endif
}

Expand Down Expand Up @@ -169,6 +207,10 @@ PLUGIN_API void XPluginDisable(void) {
XPLMDestroyFlightLoop(loop_id);
loop_id = NULL;
menu_deinit();
#ifdef LIN
XDefineCursor(dpy, window, def);
XFlush(dpy);
#endif // LIN
}

/**
Expand Down Expand Up @@ -209,7 +251,13 @@ int toggle_yoke_control_cb(XPLMCommandRef cmd, XPLMCommandPhase phase, void *ref
set_cursor_bmp(CURSOR_ARROW);
yoke_control_enabled = 0;
rudder_control = 0;
#ifdef LIN
deselect_events(dpy, window);
#endif // LIN
} else {
#ifdef LIN
select_events(dpy, window);
#endif // LIN
/* Fetch screen dimensions here because doing it from XPluginEnable
give unrealiable results. Also the screen size may be changed by
the user at any time. */
Expand Down Expand Up @@ -298,6 +346,35 @@ int left_mouse_down() {
/* Apparently you can use this also outside of the context of an event. */
return CGEventSourceButtonState(
kCGEventSourceStateCombinedSessionState, kCGMouseButtonLeft);
#elif LIN

static int mouse_but = 0;

XGenericEventCookie *cookie = &ev.xcookie;

XCheckTypedEvent(dpy, GenericEvent ,&ev);

if (cookie->type != GenericEvent ||
!XGetEventData(dpy, cookie))
return mouse_but;

xi_event = (XIEvent *) cookie->data;
xev = (XIRawEvent *) xi_event;

if(xev->detail == 1)
{
switch (cookie->evtype) {
case XI_RawButtonPress:
mouse_but = 1;
break;
case XI_RawButtonRelease:
mouse_but = 0;
break;
}

XFreeEventData(dpy, cookie);
}
return mouse_but;
#endif
}

Expand Down Expand Up @@ -372,6 +449,9 @@ void set_cursor_pos(int x, int y) {
CGEventRef ev = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, pt, 0);
CGEventPost(kCGHIDEventTap, ev);
CFRelease(ev);
#elif LIN
XWarpPointer(dpy, None, window, 0, 0, 0, 0, x, screen_height - y);
XFlush(dpy);
#endif
}

Expand All @@ -391,6 +471,23 @@ void set_cursor_bmp(cursor_t cursor) {
/* TODO */
/* Can probably use NSCursor::set for this but not sure we can hook
that under OSX to prevent XP from constantly overriding our cursor...*/
#elif LIN
/*TODO*/
/*Use custom png cursors*/
Cursor c = def;
switch (cursor) {
case CURSOR_YOKE:
c = cross;
break;
case CURSOR_RUDDER:
c = arrows;
break;
case CURSOR_ARROW:
c = def;
break;
}
XDefineCursor(dpy, window, c);
XFlush(dpy);
#endif
}

Expand Down Expand Up @@ -428,4 +525,65 @@ int hook_set_cursor(int attach) {
}
return 1;
}
#elif LIN

static int has_xi2(Display *dpy)
{
int major, minor;
int rc;

/* We support XI 2.2 */
major = 2;
minor = 2;

rc = XIQueryVersion(dpy, &major, &minor);
if (rc == BadRequest) {
_log("No XI2 support.\n");
return 0;
} else if (rc != Success) {
_log("Internal Error! This is a bug in Xlib.\n");
}

_log("XI2 supported.\n");

return 1;
}

static void select_events(Display *dpy, Window win)
{
XIEventMask evmasks[1];
unsigned char mask1[(XI_LASTEVENT + 7)/8];

memset(mask1, 0, sizeof(mask1));

/* select for button and key events from all master devices */
XISetMask(mask1, XI_RawButtonPress);
XISetMask(mask1, XI_RawButtonRelease);

evmasks[0].deviceid = XIAllMasterDevices;
evmasks[0].mask_len = sizeof(mask1);
evmasks[0].mask = mask1;

XISelectEvents(dpy, win, evmasks, 1);
XFlush(dpy);
}

static void deselect_events(Display *dpy, Window win)
{
XIEventMask evmasks[1];
unsigned char mask1[(XI_LASTEVENT + 7)/8];

memset(mask1, 0, sizeof(mask1));

/* select for button and key events from all master devices */
XISetMask(mask1, 0);

evmasks[0].deviceid = XIAllMasterDevices;
evmasks[0].mask_len = sizeof(mask1);
evmasks[0].mask = mask1;

XISelectEvents(dpy, win, evmasks, 1);
XFlush(dpy);
}

#endif
15 changes: 14 additions & 1 deletion BetterMouseYoke/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* replaces it with a more sane system for those who, for whatever reason,
* want to or have to use the mouse for flying.
*
* Copyright 2019 Torben K�nke.
* Copyright 2019 Torben Könke.
*/
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
Expand All @@ -21,8 +21,13 @@
#pragma comment(lib, "detours.lib")
#include "detours.h"
int hook_set_cursor(int attach);
#elif LIN
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/Xcursor/Xcursor.h>
#endif


typedef enum {
CURSOR_ARROW,
CURSOR_YOKE,
Expand All @@ -38,4 +43,12 @@ void set_cursor_from_yoke();
void set_cursor_pos(int x, int y);
void set_cursor_bmp(cursor_t cursor);
int controlling_rudder(int *x, int *y);

#ifdef LIN
static int has_xi2(Display *dpy);
static void select_events(Display *dpy, Window win);
static void deselect_events(Display *dpy, Window win);
#endif // LIN


#endif /* _PLUGIN_H_ */