Merge pull request #5126 from akallabeth/x11_button_mapping

X11 extended button remapping support.
This commit is contained in:
Bernhard Miklautz 2018-12-11 08:53:39 +00:00 committed by GitHub
commit 6f6c8473a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 154 deletions

View File

@ -1036,26 +1036,55 @@ static void xf_get_x11_button_map(xfContext* xfc, unsigned char* x11_map)
/* Assignment of physical (not logical) mouse buttons to wire flags. */
/* Notice that the middle button is 2 in X11, but 3 in RDP. */
static const int xf_button_flags[NUM_BUTTONS_MAPPED] =
static const button_map xf_button_flags[NUM_BUTTONS_MAPPED] =
{
PTR_FLAGS_BUTTON1,
PTR_FLAGS_BUTTON3,
PTR_FLAGS_BUTTON2
{Button1, PTR_FLAGS_BUTTON1},
{Button2, PTR_FLAGS_BUTTON3},
{Button3, PTR_FLAGS_BUTTON2},
{Button4, PTR_FLAGS_WHEEL | 0x78},
{Button5, PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x78},
{6, PTR_FLAGS_HWHEEL | 0x78},
{7, PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x78},
{8, PTR_XFLAGS_BUTTON1},
{9, PTR_XFLAGS_BUTTON2},
{97, PTR_XFLAGS_BUTTON1},
{112, PTR_XFLAGS_BUTTON2}
};
static UINT16 get_flags_for_button(int button)
{
size_t x;
for (x = 0; x < ARRAYSIZE(xf_button_flags); x++)
{
const button_map* map = &xf_button_flags[x];
if (map->button == button)
return map->flags;
}
return 0;
}
static void xf_button_map_init(xfContext* xfc)
{
size_t pos = 0;
/* loop counter for array initialization */
int physical;
int logical;
size_t physical;
/* logical mouse button which is used for each physical mouse */
/* button (indexed from zero). This is the default map. */
unsigned char x11_map[NUM_BUTTONS_MAPPED] =
{
Button1,
Button2,
Button3
};
unsigned char x11_map[112] = { 0 };
x11_map[0] = Button1;
x11_map[1] = Button2;
x11_map[2] = Button3;
x11_map[3] = Button4;
x11_map[4] = Button5;
x11_map[5] = 6;
x11_map[6] = 7;
x11_map[7] = 8;
x11_map[8] = 9;
x11_map[96] = 97;
x11_map[111] = 112;
/* query system for actual remapping */
if (!xfc->context.settings->UnmapButtons)
@ -1066,18 +1095,23 @@ static void xf_button_map_init(xfContext* xfc)
/* iterate over all (mapped) physical buttons; for each of them */
/* find the logical button in X11, and assign to this the */
/* appropriate value to send over the RDP wire. */
for (physical = 0; physical < NUM_BUTTONS_MAPPED; ++physical)
for (physical = 0; physical < ARRAYSIZE(x11_map); ++physical)
{
logical = x11_map[physical];
const unsigned char logical = x11_map[physical];
const UINT16 flags = get_flags_for_button(logical);
if (Button1 <= logical && logical <= Button3)
if ((logical != 0) && (flags != 0))
{
xfc->button_map[logical - BUTTON_BASE] = xf_button_flags[physical];
}
else
{
WLog_ERR(TAG, "Mouse physical button %d is mapped to logical button %d",
physical, logical);
if (pos >= NUM_BUTTONS_MAPPED)
{
WLog_ERR(TAG, "Failed to map mouse button to RDP button, no space");
}
else
{
button_map* map = &xfc->button_map[pos++];
map->button = physical + Button1;
map->flags = get_flags_for_button(logical);
}
}
}
}

View File

@ -373,73 +373,52 @@ static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app)
return xf_generic_MotionNotify(xfc, event->xmotion.x, event->xmotion.y,
event->xmotion.state, event->xmotion.window, app);
}
BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button,
Window window, BOOL app)
BOOL xf_generic_ButtonEvent(xfContext* xfc, int x, int y, int button,
Window window, BOOL app, BOOL down)
{
int flags;
BOOL wheel;
BOOL extended;
UINT16 flags = 0;
rdpInput* input;
Window childWindow;
wheel = FALSE;
extended = FALSE;
input = xfc->context.input;
size_t i;
switch (button)
for (i = 0; i < ARRAYSIZE(xfc->button_map); i++)
{
case Button1:
case Button2:
case Button3:
flags = PTR_FLAGS_DOWN | xfc->button_map[button - BUTTON_BASE];
break;
const button_map* cur = &xfc->button_map[i];
case 4:
wheel = TRUE;
flags = PTR_FLAGS_WHEEL | 0x0078;
break;
case 5:
wheel = TRUE;
flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0078;
break;
case 8: /* back */
case 97: /* Xming */
extended = TRUE;
flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
break;
case 9: /* forward */
case 112: /* Xming */
extended = TRUE;
flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
break;
case 6: /* wheel left */
wheel = TRUE;
flags = PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0078;
break;
case 7: /* wheel right */
wheel = TRUE;
flags = PTR_FLAGS_HWHEEL | 0x0078;
break;
default:
x = 0;
y = 0;
flags = 0;
if (cur->button == button)
{
flags = cur->flags;
break;
}
}
input = xfc->context.input;
if (flags != 0)
{
if (wheel)
if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
{
freerdp_input_send_mouse_event(input, flags, 0, 0);
if (down)
freerdp_input_send_mouse_event(input, flags, 0, 0);
}
else
{
BOOL extended = FALSE;
if (flags & (PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_BUTTON2))
{
extended = TRUE;
if (down)
flags |= PTR_XFLAGS_DOWN;
}
else if (flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3))
{
if (down)
flags |= PTR_FLAGS_DOWN;
}
if (app)
{
/* make sure window exists */
@ -468,80 +447,17 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app)
if (xfc->use_xinput)
return TRUE;
return xf_generic_ButtonPress(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
return xf_generic_ButtonEvent(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app, TRUE);
}
BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button,
Window window, BOOL app)
{
int flags = 0;
BOOL extended = FALSE;
rdpInput* input;
Window childWindow;
if (!xfc || !xfc->context.input)
return FALSE;
input = xfc->context.input;
switch (button)
{
case Button1:
case Button2:
case Button3:
flags = xfc->button_map[button - BUTTON_BASE];
break;
case 6:
case 8:
case 97:
extended = TRUE;
flags = PTR_XFLAGS_BUTTON1;
break;
case 7:
case 9:
case 112:
extended = TRUE;
flags = PTR_XFLAGS_BUTTON2;
break;
default:
flags = 0;
break;
}
if (flags != 0)
{
if (app)
{
/* make sure window exists */
if (!xf_AppWindowFromX11Window(xfc, window))
return TRUE;
/* Translate to desktop coordinates */
XTranslateCoordinates(xfc->display, window,
RootWindowOfScreen(xfc->screen),
x, y, &x, &y, &childWindow);
}
xf_event_adjust_coordinates(xfc, &x, &y);
if (extended)
freerdp_input_send_extended_mouse_event(input, flags, x, y);
else
freerdp_input_send_mouse_event(input, flags, x, y);
}
return TRUE;
}
static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app)
{
if (xfc->use_xinput)
return TRUE;
return xf_generic_ButtonRelease(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
return xf_generic_ButtonEvent(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app, FALSE);
}
static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app)
{

View File

@ -29,12 +29,14 @@ BOOL xf_event_action_script_init(xfContext* xfc);
void xf_event_action_script_free(xfContext* xfc);
BOOL xf_event_process(freerdp* instance, XEvent* event);
void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...);
void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs,
...);
void xf_event_adjust_coordinates(xfContext* xfc, int* x, int *y);
void xf_event_adjust_coordinates(xfContext* xfc, int* x, int* y);
BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app);
BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window window, BOOL app);
BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window window, BOOL app);
BOOL xf_generic_ButtonEvent(xfContext* xfc, int x, int y, int button, Window window, BOOL app,
BOOL down);
#endif /* FREERDP_CLIENT_X11_EVENT_H */

View File

@ -581,13 +581,13 @@ static int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype)
switch (evtype)
{
case XI_ButtonPress:
xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
xf_generic_ButtonEvent(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app, TRUE);
break;
case XI_ButtonRelease:
xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
xf_generic_ButtonEvent(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app, FALSE);
break;
case XI_Motion:

View File

@ -85,13 +85,14 @@ typedef struct _xfDispContext xfDispContext;
typedef struct _xfVideoContext xfVideoContext;
typedef struct xf_rail_icon_cache xfRailIconCache;
/* Value of the first logical button number in X11 which must be */
/* subtracted to go from a button number in X11 to an index into */
/* a per-button array. */
#define BUTTON_BASE Button1
/* Number of buttons that are mapped from X11 to RDP button events. */
#define NUM_BUTTONS_MAPPED 3
#define NUM_BUTTONS_MAPPED 11
typedef struct
{
int button;
UINT16 flags;
} button_map;
struct xf_context
{
@ -231,7 +232,7 @@ struct xf_context
BOOL xrenderAvailable;
/* value to be sent over wire for each logical client mouse button */
int button_map[NUM_BUTTONS_MAPPED];
button_map button_map[NUM_BUTTONS_MAPPED];
BYTE savedMaximizedState;
};