From 5b7384a3154a95a805b040e1910e276b52aada96 Mon Sep 17 00:00:00 2001 From: "Alexey Ten (Lynn)" Date: Tue, 23 Oct 2012 12:32:31 +0400 Subject: [PATCH 1/9] Apply partial matches for option (#25873) Rules which match star (*) and option, like one below, should be applied layout[2] option = symbols * misc:typo = +typo(base) This is port of patch from #19563 (https://bugs.freedesktop.org/19563) because here we have own copy of maprules.c X.Org Bug 25873 Signed-off-by: Alexey Ten (Lynn) Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- xkb/maprules.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xkb/maprules.c b/xkb/maprules.c index c6900eccb..5462763d1 100644 --- a/xkb/maprules.c +++ b/xkb/maprules.c @@ -864,6 +864,7 @@ XkbRF_GetComponents(XkbRF_RulesPtr rules, XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append); XkbRF_ApplyPartialMatches(rules, names); XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option); + XkbRF_ApplyPartialMatches(rules, names); if (names->keycodes) names->keycodes = XkbRF_SubstituteVars(names->keycodes, &mdefs); From aad65415bff12c6860c19beac42e4165e598a40f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 11 Oct 2012 13:02:27 +1000 Subject: [PATCH 2/9] dix: don't allow disabling XTest devices Disabling a XTest device followed by an XTest API call crashes the server. This could be fixed elsewhere but disabled devices must not send events anyway. The use-case for disabled XTest devices is somewhat limited, so simply disallow disabling the devices. Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- Xi/chgdctl.c | 5 ++++- dix/devices.c | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c index 7daf58461..31d3a57f3 100644 --- a/Xi/chgdctl.c +++ b/Xi/chgdctl.c @@ -187,7 +187,10 @@ ProcXChangeDeviceControl(ClientPtr client) case DEVICE_ENABLE: e = (xDeviceEnableCtl *) &stuff[1]; - status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e); + if (IsXTestDevice(dev, NULL)) + status = !Success; + else + status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e); if (status == Success) { if (e->enable) diff --git a/dix/devices.c b/dix/devices.c index fd4916a3a..613323fa2 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -145,9 +145,11 @@ DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1) return BadValue; - /* Don't allow disabling of VCP/VCK */ - if ((dev == inputInfo.pointer ||dev == - inputInfo.keyboard) &&!(*(CARD8 *) prop->data)) + /* Don't allow disabling of VCP/VCK or XTest devices */ + if ((dev == inputInfo.pointer || + dev == inputInfo.keyboard || + IsXTestDevice(dev, NULL)) + &&!(*(CARD8 *) prop->data)) return BadAccess; if (!checkonly) { From d74b63f95fc622afe83c53580f1b55346d55fa7a Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 3 Nov 2012 20:23:42 -0400 Subject: [PATCH 3/9] cursor: Fix a minor unused variable warning Signed-off-by: Jasper St. Pierre Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- xfixes/cursor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xfixes/cursor.c b/xfixes/cursor.c index 4eee59246..c45da27a9 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -196,7 +196,7 @@ CursorCloseScreen(ScreenPtr pScreen) Bool ret; _X_UNUSED CloseScreenProcPtr close_proc; _X_UNUSED DisplayCursorProcPtr display_proc; - ConstrainCursorHarderProcPtr constrain_proc; + _X_UNUSED ConstrainCursorHarderProcPtr constrain_proc; Unwrap(cs, pScreen, CloseScreen, close_proc); Unwrap(cs, pScreen, DisplayCursor, display_proc); From 04c885de715a7c989e48fc8cf2e61db2b401de2d Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 3 Nov 2012 20:23:43 -0400 Subject: [PATCH 4/9] cursor: CreatePointerBarrier has a variable request length Support this, and swap the devices in the SProc as well. Don't actually do anything with the devices just yet -- specifying any should still emit a BadImplementation. Based on a patch by Peter Hutterer Signed-off-by: Jasper St. Pierre Signed-off-by: Peter Hutterer --- xfixes/cursor.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/xfixes/cursor.c b/xfixes/cursor.c index c45da27a9..75b03749d 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -1279,7 +1279,7 @@ ProcXFixesCreatePointerBarrier(ClientPtr client) REQUEST(xXFixesCreatePointerBarrierReq); - REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); + REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices)); LEGAL_NEW_RESOURCE(stuff->barrier, client); err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); @@ -1318,9 +1318,13 @@ int SProcXFixesCreatePointerBarrier(ClientPtr client) { REQUEST(xXFixesCreatePointerBarrierReq); + int i; + CARD16 *in_devices = (CARD16 *) &stuff[1]; swaps(&stuff->length); - REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); + swaps(&stuff->num_devices); + REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices)); + swapl(&stuff->barrier); swapl(&stuff->window); swaps(&stuff->x1); @@ -1328,6 +1332,10 @@ SProcXFixesCreatePointerBarrier(ClientPtr client) swaps(&stuff->x2); swaps(&stuff->y2); swapl(&stuff->directions); + for (i = 0; i < stuff->num_devices; i++) { + swaps(in_devices + i); + } + return ProcXFixesVector[stuff->xfixesReqType] (client); } From 1536bc2d213713af45541a15b5e49c552d8d0592 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 3 Nov 2012 20:23:44 -0400 Subject: [PATCH 5/9] cursor: Clean up pointer barrier creation code a tiny bit This will make it much simpler when we add more error paths to the code that constructs pointer barrier clients. Signed-off-by: Jasper St. Pierre Signed-off-by: Peter Hutterer --- xfixes/cursor.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/xfixes/cursor.c b/xfixes/cursor.c index 75b03749d..f66bd68cb 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -1245,28 +1245,34 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, } } -static struct PointerBarrierClient * +static int CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client, - xXFixesCreatePointerBarrierReq * stuff) + xXFixesCreatePointerBarrierReq * stuff, + PointerBarrierClientPtr *client_out) { CursorScreenPtr cs = GetCursorScreen(screen); struct PointerBarrierClient *ret = malloc(sizeof(*ret)); - if (ret) { - ret->screen = screen; - ret->barrier.x1 = min(stuff->x1, stuff->x2); - ret->barrier.x2 = max(stuff->x1, stuff->x2); - ret->barrier.y1 = min(stuff->y1, stuff->y2); - ret->barrier.y2 = max(stuff->y1, stuff->y2); - ret->barrier.directions = stuff->directions & 0x0f; - if (barrier_is_horizontal(&ret->barrier)) - ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX); - if (barrier_is_vertical(&ret->barrier)) - ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY); - xorg_list_add(&ret->entry, &cs->barriers); + *client_out = NULL; + + if (!ret) { + return BadAlloc; } - return ret; + ret->screen = screen; + ret->barrier.x1 = min(stuff->x1, stuff->x2); + ret->barrier.x2 = max(stuff->x1, stuff->x2); + ret->barrier.y1 = min(stuff->y1, stuff->y2); + ret->barrier.y2 = max(stuff->y1, stuff->y2); + ret->barrier.directions = stuff->directions & 0x0f; + if (barrier_is_horizontal(&ret->barrier)) + ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX); + if (barrier_is_vertical(&ret->barrier)) + ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY); + xorg_list_add(&ret->entry, &cs->barriers); + + *client_out = ret; + return Success; } int @@ -1304,9 +1310,9 @@ ProcXFixesCreatePointerBarrier(ClientPtr client) if (barrier_is_horizontal(&b) && barrier_is_vertical(&b)) return BadValue; - if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen, - client, stuff))) - return BadAlloc; + if ((err = CreatePointerBarrierClient(pWin->drawable.pScreen, + client, stuff, &barrier))) + return err; if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier)) return BadAlloc; From 944213bbc7099f1e0238f39973653d459efdc2c9 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 3 Nov 2012 20:23:45 -0400 Subject: [PATCH 6/9] cursor: Clean up barrier finding code a bit The current code manually unrolls the loop, by finding a barrier, clamping it, and then repeaing the code. Since we want to modify both passes of the loop to support device-specific barriers, make it into an actual loop. Signed-off-by: Jasper St. Pierre Signed-off-by: Peter Hutterer --- xfixes/cursor.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xfixes/cursor.c b/xfixes/cursor.c index f66bd68cb..45b07c38a 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -1204,6 +1204,7 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, mode == Relative) { int ox, oy; int dir; + int i; struct PointerBarrier *nearest = NULL; /* where are we coming from */ @@ -1218,8 +1219,12 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, */ dir = barrier_get_direction(ox, oy, *x, *y); - nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); - if (nearest) { +#define MAX_BARRIERS 2 + for (i = 0; i < MAX_BARRIERS; i++) { + nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); + if (!nearest) + break; + barrier_clamp_to_barrier(nearest, dir, x, y); if (barrier_is_vertical(nearest)) { @@ -1230,11 +1235,6 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, dir &= ~(BarrierNegativeY | BarrierPositiveY); oy = *y; } - - nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); - if (nearest) { - barrier_clamp_to_barrier(nearest, dir, x, y); - } } } From 9a536820f6174befb22431bab375ef1af0a1ec29 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 3 Nov 2012 20:23:46 -0400 Subject: [PATCH 7/9] cursor: Fix up implementation for per-device barriers Support multiple mast devices being specified as a parameter to the barrier. This should implement all parts of the XFixes specification, minus the existing non-specification detail where specifying no devices is the same as specifying XIAllDevices. Signed-off-by: Jasper St. Pierre Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- xfixes/cursor.c | 75 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/xfixes/cursor.c b/xfixes/cursor.c index 45b07c38a..7c223ddc5 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -56,6 +56,7 @@ #include "windowstr.h" #include "xace.h" #include "list.h" +#include "exglobals.h" static RESTYPE CursorClientType; static RESTYPE CursorHideCountType; @@ -118,6 +119,8 @@ struct PointerBarrierClient { ScreenPtr screen; struct PointerBarrier barrier; struct xorg_list entry; + int num_devices; + int *device_ids; /* num_devices */ }; /* @@ -1132,6 +1135,31 @@ barrier_is_blocking(const struct PointerBarrier * barrier, return rc; } +static BOOL +barrier_blocks_device(struct PointerBarrierClient *client, + DeviceIntPtr dev) +{ + int i; + int master_id; + + /* Clients with no devices are treated as + * if they specified XIAllDevices. */ + if (client->num_devices == 0) + return TRUE; + + master_id = GetMaster(dev, POINTER_OR_FLOAT)->id; + + for (i = 0; i < client->num_devices; i++) { + int device_id = client->device_ids[i]; + if (device_id == XIAllDevices || + device_id == XIAllMasterDevices || + device_id == master_id) + return TRUE; + } + + return FALSE; +} + /** * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2. * @@ -1143,7 +1171,8 @@ barrier_is_blocking(const struct PointerBarrier * barrier, * @return The barrier nearest to the movement origin that blocks this movement. */ static struct PointerBarrier * -barrier_find_nearest(CursorScreenPtr cs, int dir, +barrier_find_nearest(CursorScreenPtr cs, DeviceIntPtr dev, + int dir, int x1, int y1, int x2, int y2) { struct PointerBarrierClient *c; @@ -1157,6 +1186,9 @@ barrier_find_nearest(CursorScreenPtr cs, int dir, if (!barrier_is_blocking_direction(b, dir)) continue; + if (!barrier_blocks_device(c, dev)) + continue; + if (barrier_is_blocking(b, x1, y1, x2, y2, &distance)) { if (min_distance > distance) { min_distance = distance; @@ -1221,7 +1253,7 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, #define MAX_BARRIERS 2 for (i = 0; i < MAX_BARRIERS; i++) { - nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); + nearest = barrier_find_nearest(cs, dev, dir, ox, oy, *x, *y); if (!nearest) break; @@ -1251,7 +1283,14 @@ CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client, PointerBarrierClientPtr *client_out) { CursorScreenPtr cs = GetCursorScreen(screen); - struct PointerBarrierClient *ret = malloc(sizeof(*ret)); + int err; + int size; + int i; + CARD16 *in_devices; + struct PointerBarrierClient *ret; + + size = sizeof(*ret) + sizeof(int) * stuff->num_devices; + ret = malloc(size); *client_out = NULL; @@ -1260,6 +1299,28 @@ CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client, } ret->screen = screen; + ret->num_devices = stuff->num_devices; + + in_devices = (CARD16 *) &stuff[1]; + for (i = 0; i < stuff->num_devices; i++) { + int device_id = in_devices[i]; + DeviceIntPtr device; + + if ((err = dixLookupDevice (&device, device_id, + client, DixReadAccess))) { + client->errorValue = device_id; + goto error; + } + + if (!IsMaster (device)) { + client->errorValue = device_id; + err = BadDevice; + goto error; + } + + ret->device_ids[i] = device_id; + } + ret->barrier.x1 = min(stuff->x1, stuff->x2); ret->barrier.x2 = max(stuff->x1, stuff->x2); ret->barrier.y1 = min(stuff->y1, stuff->y2); @@ -1273,6 +1334,10 @@ CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client, *client_out = ret; return Success; + + error: + free(ret); + return err; } int @@ -1294,10 +1359,6 @@ ProcXFixesCreatePointerBarrier(ClientPtr client) return err; } - /* This sure does need fixing. */ - if (stuff->num_devices) - return BadImplementation; - b.x1 = stuff->x1; b.x2 = stuff->x2; b.y1 = stuff->y1; From 863f32c930d71073ee5f78452b78bd459d024867 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 31 Oct 2012 19:32:57 +0100 Subject: [PATCH 8/9] Xi: Update the device after delivering the emulated pointer event(#56558) Ensure emulated pointer events contain the state that applies before the event was processed, so the device state must be updated after delivering such emulated events. Co-authored-by: Peter Hutterer Signed-off-by: Carlos Garnacho Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- Xi/exevents.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 4cbeb3796..5cf873c6e 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1568,9 +1568,6 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) else touchid = ev->device_event.touchid; - if (emulate_pointer) - UpdateDeviceState(dev, &ev->device_event); - if (type == ET_TouchBegin) { ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, emulate_pointer); @@ -1617,6 +1614,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) * events which _only_ emulate motion just work normally */ if (emulate_pointer && ev->any.type != ET_TouchUpdate) DeliverEmulatedMotionEvent(dev, ti, ev); + if (emulate_pointer && IsMaster(dev)) CheckMotion(&ev->device_event, dev); @@ -1641,6 +1639,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) if (ev->any.type == ET_TouchEnd) TouchEndTouch(dev, ti); } + + if (emulate_pointer) + UpdateDeviceState(dev, &ev->device_event); } /** From b4e44b285ed0eee1d06514215a4b01d54f40094b Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 31 Oct 2012 19:29:45 +0100 Subject: [PATCH 9/9] Xi: Set modifier mask on touch events Button mask should be out-of-band with the emulated pointer events as touch devices don't truly have "buttons". Even though, it's handy to have the modifier mask from the paired keyboard on touch events. Signed-off-by: Carlos Garnacho Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- Xi/exevents.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Xi/exevents.c b/Xi/exevents.c index 5cf873c6e..106da3a1b 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1559,6 +1559,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) uint32_t touchid; int type = ev->any.type; int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED); + DeviceIntPtr kbd; if (!t) return; @@ -1618,6 +1619,10 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) if (emulate_pointer && IsMaster(dev)) CheckMotion(&ev->device_event, dev); + kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); + event_set_state(NULL, kbd, &ev->device_event); + ev->device_event.corestate = event_get_corestate(NULL, kbd); + /* Make sure we have a valid window trace for event delivery; must be * called after event type mutation. Touch end events are always processed * in order to end touch records. */