Merge pull request #5126 from akallabeth/x11_button_mapping
X11 extended button remapping support.
This commit is contained in:
commit
6f6c8473a1
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user