From 6acebf9e1298939593b942ec91ae9ec9e74faa19 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 1 Dec 2011 13:35:50 +1000 Subject: [PATCH 01/22] include: add list_append() The existing list_add() prepends to the list, but in some cases we need the list ordered in the way we append the elements. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/list.h | 22 ++++++++++++++++++++++ test/list.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/list.h b/include/list.h index 4706e178b..f8659f04e 100644 --- a/include/list.h +++ b/include/list.h @@ -159,6 +159,28 @@ list_add(struct list *entry, struct list *head) __list_add(entry, head, head->next); } +/** + * Append a new element to the end of the list given with this list head. + * + * The list changes from: + * head → some element → ... → lastelement + * to + * head → some element → ... → lastelement → new element + * + * Example: + * struct foo *newfoo = malloc(...); + * list_append(&newfoo->mylist, &foo->mylist); + * + * @param entry The new element to prepend to the list. + * @param head The existing list. + */ +static inline void +list_append(struct list *entry, struct list *head) +{ + __list_add(entry, head->prev, head); +} + + static inline void __list_del(struct list *prev, struct list *next) { diff --git a/test/list.c b/test/list.c index f7d7bffce..b96182e03 100644 --- a/test/list.c +++ b/test/list.c @@ -88,6 +88,36 @@ test_list_add(void) assert(memcmp(c, &child[2], sizeof(struct child)) == 0); }; +static void +test_list_append(void) +{ + struct parent parent = {0}; + struct child child[3]; + struct child *c; + int i; + + list_init(&parent.children); + + list_append(&child[0].node, &parent.children); + assert(!list_is_empty(&parent.children)); + + c = list_first_entry(&parent.children, struct child, node); + assert(memcmp(c, &child[0], sizeof(struct child)) == 0); + + list_append(&child[1].node, &parent.children); + c = list_first_entry(&parent.children, struct child, node); + assert(memcmp(c, &child[0], sizeof(struct child)) == 0); + + list_append(&child[2].node, &parent.children); + c = list_first_entry(&parent.children, struct child, node); + assert(memcmp(c, &child[0], sizeof(struct child)) == 0); + + i = 0; + list_for_each_entry(c, &parent.children, node) { + assert(memcmp(c, &child[i++], sizeof(struct child)) == 0); + } +}; + static void test_list_del(void) { @@ -325,6 +355,7 @@ int main(int argc, char** argv) { test_list_init(); test_list_add(); + test_list_append(); test_list_del(); test_list_for_each(); From c8e451a8e719ba432bcfa8976774c07307087809 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 1 Dec 2011 14:12:11 +1000 Subject: [PATCH 02/22] include: add list_last_entry to get the tail of a list Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/list.h | 15 +++++++++++++++ test/list.c | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/include/list.h b/include/list.h index f8659f04e..73ff0bee9 100644 --- a/include/list.h +++ b/include/list.h @@ -262,6 +262,21 @@ list_is_empty(struct list *head) #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) +/** + * Retrieve the last list entry for the given listpointer. + * + * Example: + * struct foo *first; + * first = list_last_entry(&foo->mylist, struct foo, mylist); + * + * @param ptr The list head + * @param type Data type of the list element to retrieve + * @param member Member name of the struct list field in the list element. + * @return A pointer to the last list element. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + #define __container_of(ptr, sample, member) \ (void *)((char *)(ptr) \ - ((char *)&(sample)->member - (char *)(sample))) diff --git a/test/list.c b/test/list.c index b96182e03..ffb85efd0 100644 --- a/test/list.c +++ b/test/list.c @@ -103,14 +103,20 @@ test_list_append(void) c = list_first_entry(&parent.children, struct child, node); assert(memcmp(c, &child[0], sizeof(struct child)) == 0); + c = list_last_entry(&parent.children, struct child, node); + assert(memcmp(c, &child[0], sizeof(struct child)) == 0); list_append(&child[1].node, &parent.children); c = list_first_entry(&parent.children, struct child, node); assert(memcmp(c, &child[0], sizeof(struct child)) == 0); + c = list_last_entry(&parent.children, struct child, node); + assert(memcmp(c, &child[1], sizeof(struct child)) == 0); list_append(&child[2].node, &parent.children); c = list_first_entry(&parent.children, struct child, node); assert(memcmp(c, &child[0], sizeof(struct child)) == 0); + c = list_last_entry(&parent.children, struct child, node); + assert(memcmp(c, &child[2], sizeof(struct child)) == 0); i = 0; list_for_each_entry(c, &parent.children, node) { From 58dc73314b6508121ca094bbcf00612fe19ed69f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 2 Dec 2011 08:43:45 +1000 Subject: [PATCH 03/22] include: point to the tests in list.c as examples Even with the documentation, the list.c tests are the best examples. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/list.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/list.h b/include/list.h index 73ff0bee9..733a579c0 100644 --- a/include/list.h +++ b/include/list.h @@ -28,6 +28,7 @@ /** * @file Classic doubly-link circular list implementation. + * For real usage examples of the linked list, see the file test/list.c * * Example: * We need to keep a list of struct foo in the parent struct bar, i.e. what From 18539c89eca8f6e272ead2b631365da530065ae7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 2 Dec 2011 08:51:04 +1000 Subject: [PATCH 04/22] include: a new list element does not need initialization, state so Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/list.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/list.h b/include/list.h index 733a579c0..677fd9232 100644 --- a/include/list.h +++ b/include/list.h @@ -141,7 +141,8 @@ __list_add(struct list *entry, } /** - * Insert a new element after the given list head. + * Insert a new element after the given list head. The new element does not + * need to be initialised as empty list. * The list changes from: * head → some element → ... * to From 7dfe8c32a96d3f96c8aaeb2802f5b122e381a1e4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 2 Dec 2011 08:51:24 +1000 Subject: [PATCH 05/22] include: update struct list documentation to use one set of structs only The example at the top of the file used a struct bar and a list of struct foos. Use those two throughout instead of a different struct foo for the examples and for the API documentation. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/list.h | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/include/list.h b/include/list.h index 677fd9232..77cc5f9b4 100644 --- a/include/list.h +++ b/include/list.h @@ -97,14 +97,8 @@ /** * The linkage struct for list nodes. This struct must be part of your - * to-be-linked struct. - * - * Example: - * struct foo { - * int a; - * void *b; - * struct list *mylist; - * } + * to-be-linked struct. struct list is required for both the head of the + * list and for each list node. * * Position and name of the struct list field is irrelevant. * There are no requirements that elements of a list are of the same type. @@ -119,7 +113,7 @@ struct list { * Initialize the list as an empty list. * * Example: - * list_init(&foo->mylist); + * list_init(&bar->foos); * * @param The list to initialized. */ @@ -150,7 +144,7 @@ __list_add(struct list *entry, * * Example: * struct foo *newfoo = malloc(...); - * list_add(&newfoo->mylist, &foo->mylist); + * list_add(&newfoo->entry, &bar->foos); * * @param entry The new element to prepend to the list. * @param head The existing list. @@ -171,7 +165,7 @@ list_add(struct list *entry, struct list *head) * * Example: * struct foo *newfoo = malloc(...); - * list_append(&newfoo->mylist, &foo->mylist); + * list_append(&newfoo->entry, &bar->foos); * * @param entry The new element to prepend to the list. * @param head The existing list. @@ -200,7 +194,7 @@ __list_del(struct list *prev, struct list *next) * the list but rather reset the list as empty list. * * Example: - * list_del(&newfoo->mylist); + * list_del(&foo->entry); * * @param entry The element to remove. */ @@ -215,7 +209,7 @@ list_del(struct list *entry) * Check if the list is empty. * * Example: - * list_is_empty(&foo->mylist); + * list_is_empty(&bar->foos); * * @return True if the list contains one or more elements or False otherwise. */ @@ -230,7 +224,7 @@ list_is_empty(struct list *head) * * Example: * struct foo* f; - * f = container_of(&foo->mylist, struct foo, mylist); + * f = container_of(&foo->entry, struct foo, entry); * assert(f == foo); * * @param ptr Pointer to the struct list. @@ -254,7 +248,7 @@ list_is_empty(struct list *head) * * Example: * struct foo *first; - * first = list_first_entry(&foo->mylist, struct foo, mylist); + * first = list_first_entry(&bar->foos, struct foo, foos); * * @param ptr The list head * @param type Data type of the list element to retrieve @@ -269,7 +263,7 @@ list_is_empty(struct list *head) * * Example: * struct foo *first; - * first = list_last_entry(&foo->mylist, struct foo, mylist); + * first = list_last_entry(&bar->foos, struct foo, foos); * * @param ptr The list head * @param type Data type of the list element to retrieve @@ -287,7 +281,7 @@ list_is_empty(struct list *head) * * Example: * struct foo *iterator; - * list_for_each_entry(iterator, &foo->mylist, mylist) { + * list_for_each_entry(iterator, &bar->foos, entry) { * [modify iterator] * } * From fac464e310b82fadcedf790798d1016c4805640b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 2 Dec 2011 08:52:53 +1000 Subject: [PATCH 06/22] include: rename "foos" to "list_of_foos" in the struct list documentation Makes things a little easier to read. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/list.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/list.h b/include/list.h index 77cc5f9b4..6ec2bac53 100644 --- a/include/list.h +++ b/include/list.h @@ -36,16 +36,16 @@ * * struct bar { * ... - * struct foo *foos; -----> struct foo {}, struct foo {}, struct foo{} + * struct foo *list_of_foos; -----> struct foo {}, struct foo {}, struct foo{} * ... * } * - * We need one list head in bar and a list element in all foos (both are of + * We need one list head in bar and a list element in all list_of_foos (both are of * data type 'struct list'). * * struct bar { * ... - * struct list foos; + * struct list list_of_foos; * ... * } * @@ -59,27 +59,27 @@ * * struct bar bar; * ... - * list_init(&bar.foos); + * list_init(&bar.list_of_foos); * * Then we create the first element and add it to this list: * * struct foo *foo = malloc(...); * .... - * list_add(&foo->entry, &bar.foos); + * list_add(&foo->entry, &bar.list_of_foos); * * Repeat the above for each element you want to add to the list. Deleting * works with the element itself. * list_del(&foo->entry); * free(foo); * - * Note: calling list_del(&bar.foos) will set bar.foos to an empty + * Note: calling list_del(&bar.list_of_foos) will set bar.list_of_foos to an empty * list again. * * Looping through the list requires a 'struct foo' as iterator and the * name of the field the subnodes use. * * struct foo *iterator; - * list_for_each_entry(iterator, &bar.foos, entry) { + * list_for_each_entry(iterator, &bar.list_of_foos, entry) { * if (iterator->something == ...) * ... * } @@ -88,7 +88,7 @@ * loop. You need to run the safe for-each loop instead: * * struct foo *iterator, *next; - * list_for_each_entry_safe(iterator, next, &bar.foos, entry) { + * list_for_each_entry_safe(iterator, next, &bar.list_of_foos, entry) { * if (...) * list_del(&iterator->entry); * } @@ -113,7 +113,7 @@ struct list { * Initialize the list as an empty list. * * Example: - * list_init(&bar->foos); + * list_init(&bar->list_of_foos); * * @param The list to initialized. */ @@ -144,7 +144,7 @@ __list_add(struct list *entry, * * Example: * struct foo *newfoo = malloc(...); - * list_add(&newfoo->entry, &bar->foos); + * list_add(&newfoo->entry, &bar->list_of_foos); * * @param entry The new element to prepend to the list. * @param head The existing list. @@ -165,7 +165,7 @@ list_add(struct list *entry, struct list *head) * * Example: * struct foo *newfoo = malloc(...); - * list_append(&newfoo->entry, &bar->foos); + * list_append(&newfoo->entry, &bar->list_of_foos); * * @param entry The new element to prepend to the list. * @param head The existing list. @@ -209,7 +209,7 @@ list_del(struct list *entry) * Check if the list is empty. * * Example: - * list_is_empty(&bar->foos); + * list_is_empty(&bar->list_of_foos); * * @return True if the list contains one or more elements or False otherwise. */ @@ -248,7 +248,7 @@ list_is_empty(struct list *head) * * Example: * struct foo *first; - * first = list_first_entry(&bar->foos, struct foo, foos); + * first = list_first_entry(&bar->list_of_foos, struct foo, list_of_foos); * * @param ptr The list head * @param type Data type of the list element to retrieve @@ -263,7 +263,7 @@ list_is_empty(struct list *head) * * Example: * struct foo *first; - * first = list_last_entry(&bar->foos, struct foo, foos); + * first = list_last_entry(&bar->list_of_foos, struct foo, list_of_foos); * * @param ptr The list head * @param type Data type of the list element to retrieve @@ -281,7 +281,7 @@ list_is_empty(struct list *head) * * Example: * struct foo *iterator; - * list_for_each_entry(iterator, &bar->foos, entry) { + * list_for_each_entry(iterator, &bar->list_of_foos, entry) { * [modify iterator] * } * From 7af23259d88f4c28ed21140f82cc03b3724c06bb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 21 Nov 2011 11:41:12 -0800 Subject: [PATCH 07/22] dix: switch the syncEvent queue to a struct list No effective functionality change, just cleanup to make this code slightly more sane. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/events.c | 46 +++++++++++++++---------------- include/dix.h | 1 + include/inputstr.h | 6 ++--- test/input.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 28 deletions(-) diff --git a/dix/events.c b/dix/events.c index 4847db005..3c21a964c 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1132,12 +1132,14 @@ NoticeEventTime(InternalEvent *ev) void EnqueueEvent(InternalEvent *ev, DeviceIntPtr device) { - QdEventPtr tail = *syncEvents.pendtail; + QdEventPtr tail; QdEventPtr qe; SpritePtr pSprite = device->spriteInfo->sprite; int eventlen; DeviceEvent *event = &ev->device_event; + tail = list_last_entry(&syncEvents.pending, QdEventRec, next); + NoticeTime((InternalEvent*)event); /* Fix for key repeating bug. */ @@ -1196,15 +1198,13 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device) qe = malloc(sizeof(QdEventRec) + eventlen); if (!qe) return; - qe->next = (QdEventPtr)NULL; + list_init(&qe->next); qe->device = device; qe->pScreen = pSprite->hotPhys.pScreen; qe->months = currentTime.months; qe->event = (InternalEvent *)(qe + 1); memcpy(qe->event, event, eventlen); - if (tail) - syncEvents.pendtail = &tail->next; - *syncEvents.pendtail = qe; + list_append(&qe->next, &syncEvents.pending); } /** @@ -1216,22 +1216,20 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device) * If there is none, we're done. If there is at least one device that is not * frozen, then re-run from the beginning of the event queue. */ -static void +void PlayReleasedEvents(void) { - QdEventPtr *prev, qe; + QdEventPtr tmp; + QdEventPtr qe; DeviceIntPtr dev; DeviceIntPtr pDev; - prev = &syncEvents.pending; - while ( (qe = *prev) ) - { +restart: + list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) { if (!qe->device->deviceGrab.sync.frozen) { - *prev = qe->next; - pDev = qe->device; - if (*syncEvents.pendtail == *prev) - syncEvents.pendtail = prev; + list_del(&qe->next); + pDev = qe->device; if (qe->event->any.type == ET_Motion) CheckVirtualMotion(pDev, qe, NullWindow); syncEvents.time.months = qe->months; @@ -1268,12 +1266,11 @@ PlayReleasedEvents(void) ; if (!dev) break; + /* Playing the event may have unfrozen another device. */ /* So to play it safe, restart at the head of the queue */ - prev = &syncEvents.pending; + goto restart; } - else - prev = &qe->next; } } @@ -1314,7 +1311,8 @@ ComputeFreezes(void) for (dev = inputInfo.devices; dev; dev = dev->next) FreezeThaw(dev, dev->deviceGrab.sync.other || (dev->deviceGrab.sync.state >= FROZEN)); - if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + if (syncEvents.playingEvents || + (!replayDev && list_is_empty(&syncEvents.pending))) return; syncEvents.playingEvents = TRUE; if (replayDev) @@ -5258,6 +5256,7 @@ void InitEvents(void) { int i; + QdEventPtr qe, tmp; inputInfo.numDevices = 0; inputInfo.devices = (DeviceIntPtr)NULL; @@ -5271,13 +5270,10 @@ InitEvents(void) syncEvents.replayDev = (DeviceIntPtr)NULL; syncEvents.replayWin = NullWindow; - while (syncEvents.pending) - { - QdEventPtr next = syncEvents.pending->next; - free(syncEvents.pending); - syncEvents.pending = next; - } - syncEvents.pendtail = &syncEvents.pending; + if (syncEvents.pending.next) + list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) + free(qe); + list_init(&syncEvents.pending); syncEvents.playingEvents = FALSE; syncEvents.time.months = 0; syncEvents.time.milliseconds = 0; /* hardly matters */ diff --git a/include/dix.h b/include/dix.h index 34661f3b6..8e35d2cf5 100644 --- a/include/dix.h +++ b/include/dix.h @@ -339,6 +339,7 @@ extern _X_EXPORT void NoticeEventTime(InternalEvent *ev); extern void EnqueueEvent( InternalEvent * /* ev */, DeviceIntPtr /* device */); +extern void PlayReleasedEvents(void); extern void ActivatePointerGrab( DeviceIntPtr /* mouse */, diff --git a/include/inputstr.h b/include/inputstr.h index f482a2294..0568e0c9d 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -575,7 +575,7 @@ extern _X_EXPORT InputInfo inputInfo; /* for keeping the events for devices grabbed synchronously */ typedef struct _QdEvent *QdEventPtr; typedef struct _QdEvent { - QdEventPtr next; + struct list next; DeviceIntPtr device; ScreenPtr pScreen; /* what screen the pointer was on */ unsigned long months; /* milliseconds is in the event */ @@ -591,8 +591,8 @@ typedef struct _QdEvent { * replayed and processed as if they would come from the device directly. */ typedef struct _EventSyncInfo { - QdEventPtr pending, /**< list of queued events */ - *pendtail; /**< last event in list */ + struct list pending; + /** The device to replay events for. Only set in AllowEvents(), in which * case it is set to the device specified in the request. */ DeviceIntPtr replayDev; /* kludgy rock to put flag for */ diff --git a/test/input.c b/test/input.c index 5b4c8c193..c44e5f613 100644 --- a/test/input.c +++ b/test/input.c @@ -1674,8 +1674,75 @@ mieq_test(void) { mieqFini(); } +/* Simple check that we're replaying events in-order */ +static void +process_input_proc(InternalEvent *ev, DeviceIntPtr device) +{ + static int last_evtype = -1; + + if (ev->any.header == 0xac) + last_evtype = -1; + + assert(ev->any.type == ++last_evtype); +} + +static void +dix_enqueue_events(void) { +#define NEVENTS 5 + DeviceIntRec dev; + InternalEvent ev[NEVENTS]; + SpriteInfoRec spriteInfo; + SpriteRec sprite; + QdEventPtr qe; + int i; + + memset(&dev, 0, sizeof(dev)); + dev.public.processInputProc = process_input_proc; + + memset(&spriteInfo, 0, sizeof(spriteInfo)); + memset(&sprite, 0, sizeof(sprite)); + dev.spriteInfo = &spriteInfo; + spriteInfo.sprite = &sprite; + + InitEvents(); + assert(list_is_empty(&syncEvents.pending)); + + /* this way PlayReleasedEvents really runs through all events in the + * queue */ + inputInfo.devices = &dev; + + /* to reset process_input_proc */ + ev[0].any.header = 0xac; + + for (i = 0; i < NEVENTS; i++) + { + ev[i].any.length = sizeof(*ev); + ev[i].any.type = i; + EnqueueEvent(&ev[i], &dev); + assert(!list_is_empty(&syncEvents.pending)); + qe = list_last_entry(&syncEvents.pending, QdEventRec, next); + assert(memcmp(qe->event, &ev[i], ev[i].any.length) == 0); + qe = list_first_entry(&syncEvents.pending, QdEventRec, next); + assert(memcmp(qe->event, &ev[0], ev[i].any.length) == 0); + } + + /* calls process_input_proc */ + dev.deviceGrab.sync.frozen = 1; + PlayReleasedEvents(); + assert(!list_is_empty(&syncEvents.pending)); + + + dev.deviceGrab.sync.frozen = 0; + PlayReleasedEvents(); + assert(list_is_empty(&syncEvents.pending)); + + inputInfo.devices = NULL; +} + + int main(int argc, char** argv) { + dix_enqueue_events(); dix_double_fp_conversion(); dix_input_valuator_masks(); dix_input_attributes(); From 347f377f3b3f8c9d230d6309ec8ae92aa86d78b7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 3 Nov 2011 16:12:09 +1000 Subject: [PATCH 08/22] dix: add AllocGrab helper function Not needed since the GrabRec is a self-contained struct but will be needed for the xi2 input mask rework. FreeGrab already exists, make it available to other callers. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/grabs.c | 12 ++++++++++-- include/dixgrabs.h | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/dix/grabs.c b/dix/grabs.c index c28356d9b..3b07186ea 100644 --- a/dix/grabs.c +++ b/dix/grabs.c @@ -180,6 +180,14 @@ UngrabAllDevices(Bool kill_client) ErrorF("End list of ungrabbed devices\n"); } +GrabPtr +AllocGrab(void) +{ + GrabPtr grab = calloc(1, sizeof(GrabRec)); + + return grab; +} + GrabPtr CreateGrab( int client, @@ -196,7 +204,7 @@ CreateGrab( { GrabPtr grab; - grab = calloc(1, sizeof(GrabRec)); + grab = AllocGrab(); if (!grab) return (GrabPtr)NULL; grab->resource = FakeClientID(client); @@ -226,7 +234,7 @@ CreateGrab( } -static void +void FreeGrab(GrabPtr pGrab) { free(pGrab->modifiersDetail.pMask); diff --git a/include/dixgrabs.h b/include/dixgrabs.h index 229c8bb53..2ed8a54b4 100644 --- a/include/dixgrabs.h +++ b/include/dixgrabs.h @@ -31,6 +31,9 @@ struct _GrabParameters; extern void PrintDeviceGrabInfo(DeviceIntPtr dev); extern void UngrabAllDevices(Bool kill_client); +extern GrabPtr AllocGrab(void); +extern void FreeGrab(GrabPtr grab); + extern GrabPtr CreateGrab( int /* client */, DeviceIntPtr /* device */, From b0e9e2e32616d09c30a02b9d0ae9db0b13e150d1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 4 Nov 2011 10:44:31 +1000 Subject: [PATCH 09/22] dix: add CopyGrab() function Not really needed at this point, but will be once touch support is added. Since grabs are now expected to be allocated/freed with AllocGrab and FreeGrab, CopyGrab must increase the refcount and duplicate the modifier masks. Until the callers are switched to use FreeGrab, this introduces memleaks. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/events.c | 4 ++-- dix/grabs.c | 34 ++++++++++++++++++++++++++++++++++ include/dixgrabs.h | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/dix/events.c b/dix/events.c index 3c21a964c..c1c296d22 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1509,7 +1509,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, grabinfo->grabTime = time; if (grab->cursor) grab->cursor->refcnt++; - grabinfo->activeGrab = *grab; + CopyGrab(&grabinfo->activeGrab, grab); grabinfo->grab = &grabinfo->activeGrab; grabinfo->fromPassiveGrab = isPassive; grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; @@ -1586,7 +1586,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass grabinfo->grabTime = syncEvents.time; else grabinfo->grabTime = time; - grabinfo->activeGrab = *grab; + CopyGrab(&grabinfo->activeGrab, grab); grabinfo->grab = &grabinfo->activeGrab; grabinfo->fromPassiveGrab = passive; grabinfo->implicitGrab = passive & ImplicitGrabMask; diff --git a/dix/grabs.c b/dix/grabs.c index 3b07186ea..a1d56c5ed 100644 --- a/dix/grabs.c +++ b/dix/grabs.c @@ -246,6 +246,40 @@ FreeGrab(GrabPtr pGrab) free(pGrab); } +Bool +CopyGrab(GrabPtr dst, const GrabPtr src) +{ + Mask *mdetails_mask = NULL; + Mask *details_mask = NULL; + + if (src->cursor) + src->cursor->refcnt++; + + if (src->modifiersDetail.pMask) { + int len = MasksPerDetailMask * sizeof(Mask); + mdetails_mask = malloc(len); + if (!mdetails_mask) + return FALSE; + memcpy(mdetails_mask, src->modifiersDetail.pMask, len); + } + + if (src->detail.pMask) { + int len = MasksPerDetailMask * sizeof(Mask); + details_mask = malloc(len); + if (!details_mask) { + free(mdetails_mask); + return FALSE; + } + memcpy(details_mask, src->detail.pMask, len); + } + + *dst = *src; + dst->modifiersDetail.pMask = mdetails_mask; + dst->detail.pMask = details_mask; + + return TRUE; +} + int DeletePassiveGrab(pointer value, XID id) { diff --git a/include/dixgrabs.h b/include/dixgrabs.h index 2ed8a54b4..65ff45d1d 100644 --- a/include/dixgrabs.h +++ b/include/dixgrabs.h @@ -33,6 +33,7 @@ extern void UngrabAllDevices(Bool kill_client); extern GrabPtr AllocGrab(void); extern void FreeGrab(GrabPtr grab); +extern Bool CopyGrab(GrabPtr dst, const GrabPtr src); extern GrabPtr CreateGrab( int /* client */, From b601ea769f1b8a4d7f19e9d4a13541c78e865fe5 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 4 Nov 2011 10:47:27 +1000 Subject: [PATCH 10/22] dix: allocate temporary grabs on the heap Once grabs start having nested memory locations, we can't just use the GrabRec on the stack anymore, we need to alloc/copy/free the grabs. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- Xi/exevents.c | 29 ++++--- Xi/ungrdevb.c | 30 ++++--- Xi/ungrdevk.c | 29 ++++--- Xi/xipassivegrab.c | 37 +++++---- dix/events.c | 193 +++++++++++++++++++++++++-------------------- 5 files changed, 180 insertions(+), 138 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 20495e74d..8ef974609 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -2024,20 +2024,25 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, dev->valuator->motionHintWindow = pWin; else if ((type == DeviceButtonPress) && (!grab) && (deliveryMask & DeviceButtonGrabMask)) { - GrabRec tempGrab; + GrabPtr tempGrab; - tempGrab.device = dev; - tempGrab.resource = client->clientAsMask; - tempGrab.window = pWin; - tempGrab.ownerEvents = + tempGrab = AllocGrab(); + if (!tempGrab) + return; + + tempGrab->device = dev; + tempGrab->resource = client->clientAsMask; + tempGrab->window = pWin; + tempGrab->ownerEvents = (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE; - tempGrab.eventMask = deliveryMask; - tempGrab.keyboardMode = GrabModeAsync; - tempGrab.pointerMode = GrabModeAsync; - tempGrab.confineTo = NullWindow; - tempGrab.cursor = NullCursor; - tempGrab.next = NULL; - (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE); + tempGrab->eventMask = deliveryMask; + tempGrab->keyboardMode = GrabModeAsync; + tempGrab->pointerMode = GrabModeAsync; + tempGrab->confineTo = NullWindow; + tempGrab->cursor = NullCursor; + tempGrab->next = NULL; + (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE); + FreeGrab(tempGrab); } } diff --git a/Xi/ungrdevb.c b/Xi/ungrdevb.c index 9e9ece47a..628024870 100644 --- a/Xi/ungrdevb.c +++ b/Xi/ungrdevb.c @@ -96,7 +96,7 @@ ProcXUngrabDeviceButton(ClientPtr client) DeviceIntPtr dev; DeviceIntPtr mdev; WindowPtr pWin; - GrabRec temporaryGrab; + GrabPtr temporaryGrab; int rc; REQUEST(xUngrabDeviceButtonReq); @@ -126,17 +126,23 @@ ProcXUngrabDeviceButton(ClientPtr client) (stuff->modifiers & ~AllModifiersMask)) return BadValue; - temporaryGrab.resource = client->clientAsMask; - temporaryGrab.device = dev; - temporaryGrab.window = pWin; - temporaryGrab.type = DeviceButtonPress; - temporaryGrab.grabtype = GRABTYPE_XI; - temporaryGrab.modifierDevice = mdev; - temporaryGrab.modifiersDetail.exact = stuff->modifiers; - temporaryGrab.modifiersDetail.pMask = NULL; - temporaryGrab.detail.exact = stuff->button; - temporaryGrab.detail.pMask = NULL; + temporaryGrab = AllocGrab(); + if (!temporaryGrab) + return BadAlloc; - DeletePassiveGrabFromList(&temporaryGrab); + temporaryGrab->resource = client->clientAsMask; + temporaryGrab->device = dev; + temporaryGrab->window = pWin; + temporaryGrab->type = DeviceButtonPress; + temporaryGrab->grabtype = GRABTYPE_XI; + temporaryGrab->modifierDevice = mdev; + temporaryGrab->modifiersDetail.exact = stuff->modifiers; + temporaryGrab->modifiersDetail.pMask = NULL; + temporaryGrab->detail.exact = stuff->button; + temporaryGrab->detail.pMask = NULL; + + DeletePassiveGrabFromList(temporaryGrab); + + FreeGrab(temporaryGrab); return Success; } diff --git a/Xi/ungrdevk.c b/Xi/ungrdevk.c index 526347db4..b0d83cbbc 100644 --- a/Xi/ungrdevk.c +++ b/Xi/ungrdevk.c @@ -98,7 +98,7 @@ ProcXUngrabDeviceKey(ClientPtr client) DeviceIntPtr dev; DeviceIntPtr mdev; WindowPtr pWin; - GrabRec temporaryGrab; + GrabPtr temporaryGrab; int rc; REQUEST(xUngrabDeviceKeyReq); @@ -133,17 +133,22 @@ ProcXUngrabDeviceKey(ClientPtr client) (stuff->modifiers & ~AllModifiersMask)) return BadValue; - temporaryGrab.resource = client->clientAsMask; - temporaryGrab.device = dev; - temporaryGrab.window = pWin; - temporaryGrab.type = DeviceKeyPress; - temporaryGrab.grabtype = GRABTYPE_XI; - temporaryGrab.modifierDevice = mdev; - temporaryGrab.modifiersDetail.exact = stuff->modifiers; - temporaryGrab.modifiersDetail.pMask = NULL; - temporaryGrab.detail.exact = stuff->key; - temporaryGrab.detail.pMask = NULL; + temporaryGrab = AllocGrab(); + if (!temporaryGrab) + return BadAlloc; - DeletePassiveGrabFromList(&temporaryGrab); + temporaryGrab->resource = client->clientAsMask; + temporaryGrab->device = dev; + temporaryGrab->window = pWin; + temporaryGrab->type = DeviceKeyPress; + temporaryGrab->grabtype = GRABTYPE_XI; + temporaryGrab->modifierDevice = mdev; + temporaryGrab->modifiersDetail.exact = stuff->modifiers; + temporaryGrab->modifiersDetail.pMask = NULL; + temporaryGrab->detail.exact = stuff->key; + temporaryGrab->detail.pMask = NULL; + + DeletePassiveGrabFromList(temporaryGrab); + FreeGrab(temporaryGrab); return Success; } diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c index 2f13a95e8..4fa887a42 100644 --- a/Xi/xipassivegrab.c +++ b/Xi/xipassivegrab.c @@ -253,7 +253,7 @@ ProcXIPassiveUngrabDevice(ClientPtr client) { DeviceIntPtr dev, mod_dev; WindowPtr win; - GrabRec tempGrab; + GrabPtr tempGrab; uint32_t* modifiers; int i, rc; @@ -293,29 +293,36 @@ ProcXIPassiveUngrabDevice(ClientPtr client) mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); - tempGrab.resource = client->clientAsMask; - tempGrab.device = dev; - tempGrab.window = win; + + tempGrab = AllocGrab(); + if (!tempGrab) + return BadAlloc; + + tempGrab->resource = client->clientAsMask; + tempGrab->device = dev; + tempGrab->window = win; switch(stuff->grab_type) { - case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break; - case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break; - case XIGrabtypeEnter: tempGrab.type = XI_Enter; break; - case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break; + case XIGrabtypeButton: tempGrab->type = XI_ButtonPress; break; + case XIGrabtypeKeycode: tempGrab->type = XI_KeyPress; break; + case XIGrabtypeEnter: tempGrab->type = XI_Enter; break; + case XIGrabtypeFocusIn: tempGrab->type = XI_FocusIn; break; } - tempGrab.grabtype = GRABTYPE_XI2; - tempGrab.modifierDevice = mod_dev; - tempGrab.modifiersDetail.pMask = NULL; - tempGrab.detail.exact = stuff->detail; - tempGrab.detail.pMask = NULL; + tempGrab->grabtype = GRABTYPE_XI2; + tempGrab->modifierDevice = mod_dev; + tempGrab->modifiersDetail.pMask = NULL; + tempGrab->detail.exact = stuff->detail; + tempGrab->detail.pMask = NULL; modifiers = (uint32_t*)&stuff[1]; for (i = 0; i < stuff->num_modifiers; i++, modifiers++) { - tempGrab.modifiersDetail.exact = *modifiers; - DeletePassiveGrabFromList(&tempGrab); + tempGrab->modifiersDetail.exact = *modifiers; + DeletePassiveGrabFromList(tempGrab); } + FreeGrab(tempGrab); + return Success; } diff --git a/dix/events.c b/dix/events.c index c1c296d22..bd7e93b6c 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1976,7 +1976,7 @@ static BOOL ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, xEvent *event, Mask deliveryMask) { - GrabRec tempGrab; + GrabPtr tempGrab; OtherInputMasks *inputMasks; CARD8 type = event->u.u.type; GrabType grabtype; @@ -1990,30 +1990,33 @@ ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, else return FALSE; - memset(&tempGrab, 0, sizeof(GrabRec)); - tempGrab.next = NULL; - tempGrab.device = dev; - tempGrab.resource = client->clientAsMask; - tempGrab.window = win; - tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; - tempGrab.eventMask = deliveryMask; - tempGrab.keyboardMode = GrabModeAsync; - tempGrab.pointerMode = GrabModeAsync; - tempGrab.confineTo = NullWindow; - tempGrab.cursor = NullCursor; - tempGrab.type = type; - tempGrab.grabtype = grabtype; + tempGrab = AllocGrab(); + if (!tempGrab) + return FALSE; + tempGrab->next = NULL; + tempGrab->device = dev; + tempGrab->resource = client->clientAsMask; + tempGrab->window = win; + tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab->eventMask = deliveryMask; + tempGrab->keyboardMode = GrabModeAsync; + tempGrab->pointerMode = GrabModeAsync; + tempGrab->confineTo = NullWindow; + tempGrab->cursor = NullCursor; + tempGrab->type = type; + tempGrab->grabtype = grabtype; /* get the XI and XI2 device mask */ inputMasks = wOtherInputMasks(win); - tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0; + tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0; if (inputMasks) - memcpy(tempGrab.xi2mask, inputMasks->xi2mask, - sizeof(tempGrab.xi2mask)); + memcpy(tempGrab->xi2mask, inputMasks->xi2mask, + sizeof(tempGrab->xi2mask)); - (*dev->deviceGrab.ActivateGrab)(dev, &tempGrab, + (*dev->deviceGrab.ActivateGrab)(dev, tempGrab, currentTime, TRUE | ImplicitGrabMask); + FreeGrab(tempGrab); return TRUE; } @@ -3657,7 +3660,7 @@ CheckPassiveGrabsOnWindow( { SpritePtr pSprite = device->spriteInfo->sprite; GrabPtr grab = wPassiveGrabs(pWin); - GrabRec tempGrab; + GrabPtr tempGrab; GrabInfoPtr grabinfo; #define CORE_MATCH 0x1 #define XI_MATCH 0x2 @@ -3666,27 +3669,30 @@ CheckPassiveGrabsOnWindow( if (!grab) return NULL; + + tempGrab = AllocGrab(); + /* Fill out the grab details, but leave the type for later before * comparing */ switch (event->any.type) { case ET_KeyPress: case ET_KeyRelease: - tempGrab.detail.exact = event->device_event.detail.key; + tempGrab->detail.exact = event->device_event.detail.key; break; case ET_ButtonPress: case ET_ButtonRelease: - tempGrab.detail.exact = event->device_event.detail.button; + tempGrab->detail.exact = event->device_event.detail.button; break; default: - tempGrab.detail.exact = 0; + tempGrab->detail.exact = 0; break; } - tempGrab.window = pWin; - tempGrab.device = device; - tempGrab.detail.pMask = NULL; - tempGrab.modifiersDetail.pMask = NULL; - tempGrab.next = NULL; + tempGrab->window = pWin; + tempGrab->device = device; + tempGrab->detail.pMask = NULL; + tempGrab->modifiersDetail.pMask = NULL; + tempGrab->next = NULL; for (; grab; grab = grab->next) { DeviceIntPtr gdev; @@ -3711,29 +3717,29 @@ CheckPassiveGrabsOnWindow( if (gdev && gdev->key) xkbi= gdev->key->xkbInfo; - tempGrab.modifierDevice = grab->modifierDevice; - tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; + tempGrab->modifierDevice = grab->modifierDevice; + tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; /* Check for XI2 and XI grabs first */ - tempGrab.type = GetXI2Type(event); - tempGrab.grabtype = GRABTYPE_XI2; - if (GrabMatchesSecond(&tempGrab, grab, FALSE)) + tempGrab->type = GetXI2Type(event); + tempGrab->grabtype = GRABTYPE_XI2; + if (GrabMatchesSecond(tempGrab, grab, FALSE)) match = XI2_MATCH; if (!match) { - tempGrab.grabtype = GRABTYPE_XI; - if ((tempGrab.type = GetXIType(event)) && - (GrabMatchesSecond(&tempGrab, grab, FALSE))) + tempGrab->grabtype = GRABTYPE_XI; + if ((tempGrab->type = GetXIType(event)) && + (GrabMatchesSecond(tempGrab, grab, FALSE))) match = XI_MATCH; } /* Check for a core grab (ignore the device when comparing) */ if (!match && checkCore) { - tempGrab.grabtype = GRABTYPE_CORE; - if ((tempGrab.type = GetCoreType(event)) && - (GrabMatchesSecond(&tempGrab, grab, TRUE))) + tempGrab->grabtype = GRABTYPE_CORE; + if ((tempGrab->type = GetCoreType(event)) && + (GrabMatchesSecond(tempGrab, grab, TRUE))) match = CORE_MATCH; } @@ -3761,7 +3767,7 @@ CheckPassiveGrabsOnWindow( Since XGrabDeviceButton requires to specify the modifierDevice explicitly, we don't override this choice. */ - if (tempGrab.type < GenericEvent) + if (tempGrab->type < GenericEvent) { grab->device = device; grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD); @@ -3800,7 +3806,7 @@ CheckPassiveGrabsOnWindow( if (match & (XI_MATCH | CORE_MATCH)) { event->device_event.corestate &= 0x1f00; - event->device_event.corestate |= tempGrab.modifiersDetail.exact & + event->device_event.corestate |= tempGrab->modifiersDetail.exact & (~0x1f00); } @@ -3861,6 +3867,7 @@ CheckPassiveGrabsOnWindow( break; } + FreeGrab(tempGrab); return grab; #undef CORE_MATCH #undef XI_MATCH @@ -5078,29 +5085,30 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, *status = GrabFrozen; else { - GrabRec tempGrab; + GrabPtr tempGrab; - /* Otherwise segfaults happen on grabbed MPX devices */ - memset(&tempGrab, 0, sizeof(GrabRec)); + tempGrab = AllocGrab(); - tempGrab.next = NULL; - tempGrab.window = pWin; - tempGrab.resource = client->clientAsMask; - tempGrab.ownerEvents = ownerEvents; - tempGrab.keyboardMode = keyboard_mode; - tempGrab.pointerMode = pointer_mode; + tempGrab->next = NULL; + tempGrab->window = pWin; + tempGrab->resource = client->clientAsMask; + tempGrab->ownerEvents = ownerEvents; + tempGrab->keyboardMode = keyboard_mode; + tempGrab->pointerMode = pointer_mode; if (grabtype == GRABTYPE_CORE) - tempGrab.eventMask = mask->core; + tempGrab->eventMask = mask->core; else if (grabtype == GRABTYPE_XI) - tempGrab.eventMask = mask->xi; + tempGrab->eventMask = mask->xi; else - memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask)); - tempGrab.device = dev; - tempGrab.cursor = cursor; - tempGrab.confineTo = confineTo; - tempGrab.grabtype = grabtype; - (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE); + memcpy(tempGrab->xi2mask, mask->xi2mask, sizeof(tempGrab->xi2mask)); + tempGrab->device = dev; + tempGrab->cursor = cursor; + tempGrab->confineTo = confineTo; + tempGrab->grabtype = grabtype; + (*grabInfo->ActivateGrab)(dev, tempGrab, time, FALSE); *status = GrabSuccess; + + FreeGrab(tempGrab); } return Success; } @@ -5419,7 +5427,7 @@ ProcUngrabKey(ClientPtr client) { REQUEST(xUngrabKeyReq); WindowPtr pWin; - GrabRec tempGrab; + GrabPtr tempGrab; DeviceIntPtr keybd = PickKeyboard(client); int rc; @@ -5441,21 +5449,27 @@ ProcUngrabKey(ClientPtr client) client->errorValue = stuff->modifiers; return BadValue; } - tempGrab.resource = client->clientAsMask; - tempGrab.device = keybd; - tempGrab.window = pWin; - tempGrab.modifiersDetail.exact = stuff->modifiers; - tempGrab.modifiersDetail.pMask = NULL; - tempGrab.modifierDevice = keybd; - tempGrab.type = KeyPress; - tempGrab.grabtype = GRABTYPE_CORE; - tempGrab.detail.exact = stuff->key; - tempGrab.detail.pMask = NULL; - tempGrab.next = NULL; + tempGrab = AllocGrab(); + if (!tempGrab) + return BadAlloc; + tempGrab->resource = client->clientAsMask; + tempGrab->device = keybd; + tempGrab->window = pWin; + tempGrab->modifiersDetail.exact = stuff->modifiers; + tempGrab->modifiersDetail.pMask = NULL; + tempGrab->modifierDevice = keybd; + tempGrab->type = KeyPress; + tempGrab->grabtype = GRABTYPE_CORE; + tempGrab->detail.exact = stuff->key; + tempGrab->detail.pMask = NULL; + tempGrab->next = NULL; - if (!DeletePassiveGrabFromList(&tempGrab)) - return BadAlloc; - return Success; + if (!DeletePassiveGrabFromList(tempGrab)) + rc = BadAlloc; + + FreeGrab(tempGrab); + + return rc; } /** @@ -5619,7 +5633,7 @@ ProcUngrabButton(ClientPtr client) { REQUEST(xUngrabButtonReq); WindowPtr pWin; - GrabRec tempGrab; + GrabPtr tempGrab; int rc; DeviceIntPtr ptr; @@ -5636,21 +5650,26 @@ ProcUngrabButton(ClientPtr client) ptr = PickPointer(client); - tempGrab.resource = client->clientAsMask; - tempGrab.device = ptr; - tempGrab.window = pWin; - tempGrab.modifiersDetail.exact = stuff->modifiers; - tempGrab.modifiersDetail.pMask = NULL; - tempGrab.modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); - tempGrab.type = ButtonPress; - tempGrab.detail.exact = stuff->button; - tempGrab.grabtype = GRABTYPE_CORE; - tempGrab.detail.pMask = NULL; - tempGrab.next = NULL; + tempGrab = AllocGrab(); + if (!tempGrab) + return BadAlloc; + tempGrab->resource = client->clientAsMask; + tempGrab->device = ptr; + tempGrab->window = pWin; + tempGrab->modifiersDetail.exact = stuff->modifiers; + tempGrab->modifiersDetail.pMask = NULL; + tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); + tempGrab->type = ButtonPress; + tempGrab->detail.exact = stuff->button; + tempGrab->grabtype = GRABTYPE_CORE; + tempGrab->detail.pMask = NULL; + tempGrab->next = NULL; - if (!DeletePassiveGrabFromList(&tempGrab)) - return BadAlloc; - return Success; + if (!DeletePassiveGrabFromList(tempGrab)) + rc = BadAlloc; + + FreeGrab(tempGrab); + return rc; } /** From 4bc2761ad5ec2d0668aec639780ffb136605fbc8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 4 Nov 2011 14:16:37 +1000 Subject: [PATCH 11/22] dix: switch the dev->deviceGrab.activeGrab from GrabRec to GrabPtr This breaks the input ABI. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/devices.c | 3 +++ dix/events.c | 8 ++++---- include/inputstr.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dix/devices.c b/dix/devices.c index 37cbcdb78..e448eab62 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -73,6 +73,7 @@ SOFTWARE. #include "dixevents.h" #include "mipointer.h" #include "eventstr.h" +#include "dixgrabs.h" #include #include @@ -273,6 +274,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) dev->deviceGrab.grabTime = currentTime; dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + dev->deviceGrab.activeGrab = AllocGrab(); XkbSetExtension(dev, ProcessKeyboardEvent); @@ -941,6 +943,7 @@ CloseDevice(DeviceIntPtr dev) } } + FreeGrab(dev->deviceGrab.activeGrab); free(dev->deviceGrab.sync.event); free(dev->config_info); /* Allocated in xf86ActivateDevice. */ free(dev->last.scroll); diff --git a/dix/events.c b/dix/events.c index bd7e93b6c..8f8531cf1 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1509,8 +1509,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, grabinfo->grabTime = time; if (grab->cursor) grab->cursor->refcnt++; - CopyGrab(&grabinfo->activeGrab, grab); - grabinfo->grab = &grabinfo->activeGrab; + CopyGrab(grabinfo->activeGrab, grab); + grabinfo->grab = grabinfo->activeGrab; grabinfo->fromPassiveGrab = isPassive; grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; PostNewCursor(mouse); @@ -1586,8 +1586,8 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass grabinfo->grabTime = syncEvents.time; else grabinfo->grabTime = time; - CopyGrab(&grabinfo->activeGrab, grab); - grabinfo->grab = &grabinfo->activeGrab; + CopyGrab(grabinfo->activeGrab, grab); + grabinfo->grab = grabinfo->activeGrab; grabinfo->fromPassiveGrab = passive; grabinfo->implicitGrab = passive & ImplicitGrabMask; CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); diff --git a/include/inputstr.h b/include/inputstr.h index 0568e0c9d..f9cb8fe0f 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -451,7 +451,7 @@ typedef struct _GrabInfoRec { TimeStamp grabTime; Bool fromPassiveGrab; /* true if from passive grab */ Bool implicitGrab; /* implicit from ButtonPress */ - GrabRec activeGrab; + GrabPtr activeGrab; GrabPtr grab; CARD8 activatingKey; void (*ActivateGrab) ( From b8b90cd1610331ff12fa3f70bf372670af7795ec Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 3 Nov 2011 13:39:59 +1000 Subject: [PATCH 12/22] Add a new XI2Mask struct and a few helper functions. The current XI2 mask handling is handy for copying (fixed size arrays) but a pain to deal with otherwise. Add a struct for XI2 masks and the required accessors. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/inpututils.c | 180 +++++++++++++++++++++++++++++++++++++++++++ include/input.h | 1 + include/inputstr.h | 6 ++ include/inpututils.h | 12 +++ test/xi2/Makefile.am | 5 +- test/xi2/xi2.c | 129 +++++++++++++++++++++++++++++++ 6 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 test/xi2/xi2.c diff --git a/dix/inpututils.c b/dix/inpututils.c index c152b2d8b..05d4c7ce1 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -892,3 +892,183 @@ double_to_fp3232(double in) ret.frac = frac_d; return ret; } + +/** + * DO NOT USE THIS FUNCTION. It only exists for the test cases. Use + * xi2mask_new() instead to get the standard sized masks. + * + * @param nmasks The number of masks (== number of devices) + * @param size The size of the masks in bytes + * @return The new mask or NULL on allocation error. + */ +XI2Mask* +xi2mask_new_with_size(size_t nmasks, size_t size) +{ + int i; + + XI2Mask *mask = calloc(1, sizeof(*mask)); + if (!mask) + return NULL; + + + mask->nmasks = nmasks; + mask->mask_size = size; + + mask->masks = calloc(mask->nmasks, sizeof(*mask->masks)); + if (!mask->masks) + goto unwind; + + for (i = 0; i < mask->nmasks; i++) { + mask->masks[i] = calloc(1, mask->mask_size); + if (!mask->masks[i]) + goto unwind; + } + return mask; + +unwind: + xi2mask_free(&mask); + return NULL; +} + + +/** + * Create a new XI2 mask of the standard size, i.e. for all devices + fake + * devices and for the highest supported XI2 event type. + * + * @return The new mask or NULL on allocation error. + */ +XI2Mask* +xi2mask_new(void) +{ + return xi2mask_new_with_size(EMASKSIZE, XI2MASKSIZE); +} + +/** + * Frees memory associated with mask and resets mask to NULL. + */ +void +xi2mask_free(XI2Mask** mask) +{ + int i; + + if (!(*mask)) + return; + + for (i = 0; (*mask)->masks && i < (*mask)->nmasks; i++) + free((*mask)->masks[i]); + free((*mask)->masks); + free((*mask)); + *mask = NULL; +} + +/** + * Test if the bit for event type is set for this device, or the + * XIAllDevices/XIAllMasterDevices (if applicable) is set. + * + * @return TRUE if the bit is set, FALSE otherwise + */ +Bool +xi2mask_isset(XI2Mask* mask, const DeviceIntPtr dev, int event_type) +{ + int set = 0; + + if (dev->id < 0 || dev->id >= mask->nmasks || event_type >= mask->mask_size) + return 0; + + set = !!BitIsOn(mask->masks[XIAllDevices], event_type); + if (!set) + set = !!BitIsOn(mask->masks[dev->id], event_type); + if (!set && IsMaster(dev)) + set = !!BitIsOn(mask->masks[XIAllMasterDevices], event_type); + + return set; +} + +/** + * Set the mask bit for this event type for this device. + */ +void +xi2mask_set(XI2Mask *mask, int deviceid, int event_type) +{ + if (deviceid < 0 || deviceid >= mask->nmasks || event_type >= mask->mask_size) + return; + + SetBit(mask->masks[deviceid], event_type); +} + +/** + * Zero out the xi2mask, for the deviceid given. If the deviceid is < 0, all + * masks are zeroed. + */ +void +xi2mask_zero(XI2Mask *mask, int deviceid) +{ + int i; + + if (deviceid > 0 && deviceid >= mask->nmasks) + return; + + if (deviceid >= 0) + memset(mask->masks[deviceid], 0, mask->mask_size); + else + for (i = 0; i < mask->nmasks; i++) + memset(mask->masks[i], 0, mask->mask_size); +} + +/** + * Merge source into dest, i.e. dest |= source. + * If the masks are of different size, only the overlapping section is merged. + */ +void +xi2mask_merge(XI2Mask *dest, const XI2Mask *source) +{ + int i, j; + + for (i = 0; i < min(dest->nmasks, source->nmasks); i++) + for (j = 0; j < min(dest->mask_size, source->mask_size); j++) + dest->masks[i][j] |= source->masks[i][j]; +} + +/** + * @return The number of masks in mask + */ +size_t +xi2mask_num_masks(const XI2Mask *mask) +{ + return mask->nmasks; +} + +/** + * @return The size of each mask in bytes + */ +size_t +xi2mask_mask_size(const XI2Mask *mask) +{ + return mask->mask_size; +} + +/** + * Set the mask for the given deviceid to the source mask. + * If the mask given is larger than the target memory, only the overlapping + * parts are copied. + */ +void +xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, size_t mask_size) +{ + if (deviceid < 0 || deviceid >= xi2mask->nmasks) + return; + + memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size)); +} + +/** + * Get a reference to the XI2mask for this particular device. + */ +const unsigned char* +xi2mask_get_one_mask(const XI2Mask *mask, int deviceid) +{ + if (deviceid < 0 || deviceid >= mask->nmasks) + return NULL; + + return mask->masks[deviceid]; +} diff --git a/include/input.h b/include/input.h index 8e7b47a4c..8b0c18e70 100644 --- a/include/input.h +++ b/include/input.h @@ -205,6 +205,7 @@ extern _X_EXPORT KeybdCtrl defaultKeyboardControl; extern _X_EXPORT PtrCtrl defaultPointerControl; typedef struct _InputOption InputOption; +typedef struct _XI2Mask XI2Mask; typedef struct _InputAttributes { char *product; diff --git a/include/inputstr.h b/include/inputstr.h index f9cb8fe0f..a73ace830 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -622,4 +622,10 @@ static inline WindowPtr DeepestSpriteWin(SpritePtr sprite) return sprite->spriteTrace[sprite->spriteTraceGood - 1]; } +struct _XI2Mask { + unsigned char **masks; /* event mask in masks[deviceid][event type byte] */ + size_t nmasks; /* number of masks */ + size_t mask_size; /* size of each mask in bytes */ +}; + #endif /* INPUTSTRUCT_H */ diff --git a/include/inpututils.h b/include/inpututils.h index 2832ed5b1..5f9dfecc3 100644 --- a/include/inpututils.h +++ b/include/inpututils.h @@ -46,4 +46,16 @@ FP1616 double_to_fp1616(double in); double fp1616_to_double(FP1616 in); double fp3232_to_double(FP3232 in); + +XI2Mask* xi2mask_new(void); +XI2Mask* xi2mask_new_with_size(size_t, size_t); /* don't use it */ +void xi2mask_free(XI2Mask** mask); +Bool xi2mask_isset(XI2Mask* mask, const DeviceIntPtr dev, int event_type); +void xi2mask_set(XI2Mask *mask, int deviceid, int event_type); +void xi2mask_zero(XI2Mask *mask, int deviceid); +void xi2mask_merge(XI2Mask *dest, const XI2Mask *source); +size_t xi2mask_num_masks(const XI2Mask *mask); +size_t xi2mask_mask_size(const XI2Mask *mask); +void xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, size_t mask_size); +const unsigned char* xi2mask_get_one_mask(const XI2Mask *xi2mask, int deviceid); #endif diff --git a/test/xi2/Makefile.am b/test/xi2/Makefile.am index c6e93e78f..913ba0f8b 100644 --- a/test/xi2/Makefile.am +++ b/test/xi2/Makefile.am @@ -10,7 +10,8 @@ noinst_PROGRAMS = \ protocol-xipassivegrabdevice \ protocol-xiquerypointer \ protocol-xiwarppointer \ - protocol-eventconvert + protocol-eventconvert \ + xi2 TESTS=$(noinst_PROGRAMS) TESTS_ENVIRONMENT = $(XORG_MALLOC_DEBUG_ENV) @@ -34,6 +35,7 @@ protocol_xiquerypointer_LDADD=$(TEST_LDADD) protocol_xipassivegrabdevice_LDADD=$(TEST_LDADD) protocol_xiwarppointer_LDADD=$(TEST_LDADD) protocol_eventconvert_LDADD=$(TEST_LDADD) +xi2_LDADD=$(TEST_LDADD) protocol_xiqueryversion_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient protocol_xiquerydevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient @@ -44,6 +46,7 @@ protocol_xigetclientpointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-w protocol_xipassivegrabdevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,GrabButton -Wl,-wrap,dixLookupWindow -Wl,-wrap,WriteToClient protocol_xiquerypointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow protocol_xiwarppointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow +xi2_LDFLAGS=$(AM_LDFLAGS) protocol_xiqueryversion_SOURCES=$(COMMON_SOURCES) protocol-xiqueryversion.c protocol_xiquerydevice_SOURCES=$(COMMON_SOURCES) protocol-xiquerydevice.c diff --git a/test/xi2/xi2.c b/test/xi2/xi2.c new file mode 100644 index 000000000..5143caff8 --- /dev/null +++ b/test/xi2/xi2.c @@ -0,0 +1,129 @@ +/** + * Copyright © 2011 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "inpututils.h" +#include "inputstr.h" +#include "assert.h" + +static void xi2mask_test(void) +{ + XI2Mask *xi2mask = NULL, + *mergemask = NULL; + unsigned char *mask; + DeviceIntRec dev; + int i; + + /* size >= nmasks * 2 for the test cases below */ + xi2mask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2); + assert(xi2mask); + assert(xi2mask->nmasks > 0); + assert(xi2mask->mask_size > 0); + + assert(xi2mask_mask_size(xi2mask) == xi2mask->mask_size); + assert(xi2mask_num_masks(xi2mask) == xi2mask->nmasks); + + mask = calloc(1, xi2mask_mask_size(xi2mask)); + /* ensure zeros */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + } + + /* set various bits */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m; + xi2mask_set(xi2mask, i, i); + + dev.id = i; + assert(xi2mask_isset(xi2mask, &dev, i)); + + m = xi2mask_get_one_mask(xi2mask, i); + SetBit(mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + ClearBit(mask, i); + } + + /* ensure zeros one-by-one */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) != 0); + xi2mask_zero(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + } + + /* re-set, zero all */ + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) + xi2mask_set(xi2mask, i, i); + xi2mask_zero(xi2mask, -1); + + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + } + + for (i = 0; i < xi2mask_num_masks(xi2mask); i++) { + const unsigned char *m; + SetBit(mask, i); + xi2mask_set_one_mask(xi2mask, i, mask, xi2mask_mask_size(xi2mask)); + m = xi2mask_get_one_mask(xi2mask, i); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + ClearBit(mask, i); + } + + mergemask = xi2mask_new_with_size(MAXDEVICES + 2, (MAXDEVICES + 2) * 2); + for (i = 0; i < xi2mask_num_masks(mergemask); i++) { + dev.id = i; + xi2mask_set(mergemask, i, i * 2); + } + + /* xi2mask still has all i bits set, should now also have all i * 2 bits */ + xi2mask_merge(xi2mask, mergemask); + for (i = 0; i < xi2mask_num_masks(mergemask); i++) { + const unsigned char *m = xi2mask_get_one_mask(xi2mask, i); + SetBit(mask, i); + SetBit(mask, i * 2); + assert(memcmp(mask, m, xi2mask_mask_size(xi2mask)) == 0); + ClearBit(mask, i); + ClearBit(mask, i * 2); + } + + xi2mask_free(&xi2mask); + assert(xi2mask == NULL); + + xi2mask_free(&mergemask); + assert(mergemask == NULL); + free(mask); +} + + +int main(int argc, char** argv) +{ + xi2mask_test(); + + return 0; +} From 86bb3781b336c09e4279136ed81974de5acdba7f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 4 Nov 2011 11:29:01 +1000 Subject: [PATCH 13/22] input: swap the server over to use the XI2mask struct Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- Xi/exevents.c | 35 ++++++++++++++++++++++------------- Xi/xigrabdev.c | 15 +++++++++++---- Xi/xipassivegrab.c | 13 +++++++++---- Xi/xiselectev.c | 5 +++-- dix/events.c | 43 ++++++++++++++++--------------------------- dix/grabs.c | 38 +++++++++++++++++++++++++++++++++----- include/inputstr.h | 8 ++++---- 7 files changed, 98 insertions(+), 59 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 8ef974609..7a84c6b3d 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1631,6 +1631,7 @@ SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, static void FreeInputClient(InputClientsPtr *other) { + xi2mask_free(&(*other)->xi2mask); free(*other); *other = NULL; } @@ -1653,6 +1654,9 @@ AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx) return BadAlloc; if (!pWin->optional->inputMasks && !MakeInputMasks(pWin)) goto bail; + others->xi2mask = xi2mask_new(); + if (!others->xi2mask) + goto bail; others->mask[mskidx] = mask; others->resource = FakeClientID(client->index); others->next = pWin->optional->inputMasks->inputClients; @@ -1674,6 +1678,12 @@ MakeInputMasks(WindowPtr pWin) imasks = calloc(1, sizeof(struct _OtherInputMasks)); if (!imasks) return FALSE; + imasks->xi2mask = xi2mask_new(); + if (!imasks->xi2mask) + { + free(imasks); + return FALSE; + } pWin->optional->inputMasks = imasks; return TRUE; } @@ -1681,6 +1691,7 @@ MakeInputMasks(WindowPtr pWin) static void FreeInputMask(OtherInputMasks **imask) { + xi2mask_free(&(*imask)->xi2mask); free(*imask); *imask = NULL; } @@ -1691,20 +1702,17 @@ RecalculateDeviceDeliverableEvents(WindowPtr pWin) InputClientsPtr others; struct _OtherInputMasks *inputMasks; /* default: NULL */ WindowPtr pChild, tmp; - int i, j; + int i; pChild = pWin; while (1) { if ((inputMasks = wOtherInputMasks(pChild)) != 0) { - for (i = 0; i < EMASKSIZE; i++) - memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i])); + xi2mask_zero(inputMasks->xi2mask, -1); for (others = inputMasks->inputClients; others; others = others->next) { for (i = 0; i < EMASKSIZE; i++) inputMasks->inputEvents[i] |= others->mask[i]; - for (i = 0; i < EMASKSIZE; i++) - for (j = 0; j < XI2MASKSIZE; j++) - inputMasks->xi2mask[i][j] |= others->xi2mask[i][j]; + xi2mask_merge(inputMasks->xi2mask, others->xi2mask); } for (i = 0; i < EMASKSIZE; i++) inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i]; @@ -2188,14 +2196,12 @@ XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, for (others = wOtherInputMasks(win)->inputClients; others; others = others->next) { if (SameClient(others, client)) { - memset(others->xi2mask[dev->id], 0, - sizeof(others->xi2mask[dev->id])); + xi2mask_zero(others->xi2mask, dev->id); break; } } } - len = min(len, sizeof(others->xi2mask[dev->id])); if (len && !others) { @@ -2204,11 +2210,14 @@ XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client, others= wOtherInputMasks(win)->inputClients; } - if (others) - memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id])); + if (others) { + xi2mask_zero(others->xi2mask, dev->id); + len = min(len, xi2mask_mask_size(others->xi2mask)); + } - if (len) - memcpy(others->xi2mask[dev->id], mask, len); + if (len) { + xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len); + } RecalculateDeviceDeliverableEvents(win); diff --git a/Xi/xigrabdev.c b/Xi/xigrabdev.c index a9b655c0e..1cfbf243b 100644 --- a/Xi/xigrabdev.c +++ b/Xi/xigrabdev.c @@ -41,6 +41,7 @@ #include "exglobals.h" /* BadDevice */ #include "exevents.h" #include "xigrabdev.h" +#include "inpututils.h" int SProcXIGrabDevice(ClientPtr client) @@ -64,7 +65,7 @@ ProcXIGrabDevice(ClientPtr client) xXIGrabDeviceReply rep; int ret = Success; uint8_t status; - GrabMask mask; + GrabMask mask = { 0 }; int mask_len; REQUEST(xXIGrabDeviceReq); @@ -81,9 +82,13 @@ ProcXIGrabDevice(ClientPtr client) stuff->mask_len * 4) != Success) return BadValue; - mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); - memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); - memcpy(mask.xi2mask, (char*)&stuff[1], mask_len); + mask.xi2mask = xi2mask_new(); + if (!mask.xi2mask) + return BadAlloc; + + mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4); + /* FIXME: I think the old code was broken here */ + xi2mask_set_one_mask(mask.xi2mask, dev->id, (unsigned char*)&stuff[1], mask_len); ret = GrabDevice(client, dev, stuff->grab_mode, stuff->paired_device_mode, @@ -96,6 +101,8 @@ ProcXIGrabDevice(ClientPtr client) None /* confineTo */, &status); + xi2mask_free(&mask.xi2mask); + if (ret != Success) return ret; diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c index 4fa887a42..4860757fc 100644 --- a/Xi/xipassivegrab.c +++ b/Xi/xipassivegrab.c @@ -44,6 +44,7 @@ #include "xipassivegrab.h" #include "dixgrabs.h" #include "misc.h" +#include "inpututils.h" int SProcXIPassiveGrabDevice(ClientPtr client) @@ -82,7 +83,7 @@ ProcXIPassiveGrabDevice(ClientPtr client) int i, ret = Success; uint32_t *modifiers; xXIGrabModifierInfo *modifiers_failed; - GrabMask mask; + GrabMask mask = { 0 }; GrabParameters param; void *tmp; int mask_len; @@ -124,9 +125,12 @@ ProcXIPassiveGrabDevice(ClientPtr client) stuff->mask_len * 4) != Success) return BadValue; - mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); - memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); - memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4); + mask.xi2mask = xi2mask_new(); + if (!mask.xi2mask) + return BadAlloc; + + mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4); + xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid, (unsigned char*)&stuff[1], mask_len * 4); rep.repType = X_Reply; rep.RepType = X_XIPassiveGrabDevice; @@ -212,6 +216,7 @@ ProcXIPassiveGrabDevice(ClientPtr client) free(modifiers_failed); out: + xi2mask_free(&mask.xi2mask); return ret; } diff --git a/Xi/xiselectev.c b/Xi/xiselectev.c index 3af4f1fb9..ee14edb6d 100644 --- a/Xi/xiselectev.c +++ b/Xi/xiselectev.c @@ -33,6 +33,7 @@ #include "exglobals.h" #include "exevents.h" #include +#include "inpututils.h" #include "xiselectev.h" @@ -249,7 +250,7 @@ ProcXIGetSelectedEvents(ClientPtr client) for (i = 0; i < MAXDEVICES; i++) { int j; - unsigned char *devmask = others->xi2mask[i]; + const unsigned char *devmask = xi2mask_get_one_mask(others->xi2mask, i); if (i > 2) { @@ -259,7 +260,7 @@ ProcXIGetSelectedEvents(ClientPtr client) } - for (j = XI2MASKSIZE - 1; j >= 0; j--) + for (j = xi2mask_mask_size(others->xi2mask) - 1; j >= 0; j--) { if (devmask[j] != 0) { diff --git a/dix/events.c b/dix/events.c index 8f8531cf1..59caa918f 100644 --- a/dix/events.c +++ b/dix/events.c @@ -420,12 +420,6 @@ GetXI2EventFilterMask(int evtype) return (1 << (evtype % 8)); } -static inline int -GetXI2EventFilterOffset(int evtype) -{ - return (evtype / 8); -} - /** * For the given event, return the matching event filter. This filter may then * be AND'ed with the selected event mask. @@ -459,12 +453,15 @@ GetEventFilter(DeviceIntPtr dev, xEvent *event) * for the event_type. */ static int -GetXI2MaskByte(unsigned char xi2mask[][XI2MASKSIZE], DeviceIntPtr dev, int event_type) +GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type) { - int byte = GetXI2EventFilterOffset(event_type); - return xi2mask[dev->id][byte] | - xi2mask[XIAllDevices][byte] | - (IsMaster(dev) ? xi2mask[XIAllMasterDevices][byte] : 0); + /* we just return the matching filter because that's the only use + * for this mask anyway. + */ + if (xi2mask_isset(mask, dev, event_type)) + return GetXI2EventFilterMask(event_type); + else + return 0; } @@ -476,16 +473,14 @@ Bool WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent* ev) { OtherInputMasks *inputMasks = wOtherInputMasks(win); - int filter; int evtype; if (!inputMasks || xi2_get_type(ev) == 0) return 0; evtype = ((xGenericEvent*)ev)->evtype; - filter = GetEventFilter(dev, ev); - return !!(GetXI2MaskByte(inputMasks->xi2mask, dev, evtype) & filter); + return xi2mask_isset(inputMasks->xi2mask, dev, evtype); } Mask @@ -2011,8 +2006,7 @@ ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0; if (inputMasks) - memcpy(tempGrab->xi2mask, inputMasks->xi2mask, - sizeof(tempGrab->xi2mask)); + xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask); (*dev->deviceGrab.ActivateGrab)(dev, tempGrab, currentTime, TRUE | ImplicitGrabMask); @@ -2561,10 +2555,7 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win) if ((type = GetXI2Type(event)) != 0) { - filter = GetXI2EventFilterMask(type); - - if (inputMasks && - (GetXI2MaskByte(inputMasks->xi2mask, dev, type) & filter)) + if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type)) rc |= EVENT_XI2_MASK; } @@ -4155,12 +4146,11 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, if (rc == Success) { int evtype = xi2_get_type(xi2); - mask = GetXI2MaskByte(grab->xi2mask, thisDev, evtype); + mask = xi2mask_isset(grab->xi2mask, thisDev, evtype); /* try XI2 event */ FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE); /* XXX: XACE */ - deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, - GetEventFilter(thisDev, xi2), grab); + deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, 1, grab); } else if (rc != BadMatch) ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n", thisDev->name, event->any.type, rc); @@ -4634,9 +4624,8 @@ DeviceEnterLeaveEvent( if (grab) { Mask mask; - mask = GetXI2MaskByte(grab->xi2mask, mouse, type); - TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, - filter, grab); + mask = xi2mask_isset(grab->xi2mask, mouse, type); + TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, 1, grab); } else { if (!WindowXI2MaskIsset(mouse, pWin, (xEvent*)event)) goto out; @@ -5100,7 +5089,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, else if (grabtype == GRABTYPE_XI) tempGrab->eventMask = mask->xi; else - memcpy(tempGrab->xi2mask, mask->xi2mask, sizeof(tempGrab->xi2mask)); + xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); tempGrab->device = dev; tempGrab->cursor = cursor; tempGrab->confineTo = confineTo; diff --git a/dix/grabs.c b/dix/grabs.c index a1d56c5ed..aced130a7 100644 --- a/dix/grabs.c +++ b/dix/grabs.c @@ -60,6 +60,7 @@ SOFTWARE. #include "dixgrabs.h" #include "xace.h" #include "exevents.h" +#include "inpututils.h" #define BITMASK(i) (((Mask)1) << ((i) & 31)) #define MASKIDX(i) ((i) >> 5) @@ -122,13 +123,15 @@ PrintDeviceGrabInfo(DeviceIntPtr dev) } else if (grab->grabtype == GRABTYPE_XI2) { - for (i = 0; i < EMASKSIZE; i++) + for (i = 0; i < xi2mask_num_masks(grab->xi2mask); i++) { + const unsigned char *mask; int print; print = 0; for (j = 0; j < XI2MASKSIZE; j++) { - if (grab->xi2mask[i][j]) + mask = xi2mask_get_one_mask(grab->xi2mask, i); + if (mask[j]) { print = 1; break; @@ -137,8 +140,8 @@ PrintDeviceGrabInfo(DeviceIntPtr dev) if (!print) continue; ErrorF(" xi2 event mask for device %d: 0x", dev->id); - for (j = 0; j < XI2MASKSIZE; j++) - ErrorF("%x", grab->xi2mask[i][j]); + for (j = 0; j < xi2mask_mask_size(grab->xi2mask); j++) + ErrorF("%x", mask[j]); ErrorF("\n"); } } @@ -185,6 +188,14 @@ AllocGrab(void) { GrabPtr grab = calloc(1, sizeof(GrabRec)); + if (grab) { + grab->xi2mask = xi2mask_new(); + if (!grab->xi2mask) { + free(grab); + grab = NULL; + } + } + return grab; } @@ -227,7 +238,7 @@ CreateGrab( grab->next = NULL; if (grabtype == GRABTYPE_XI2) - memcpy(grab->xi2mask, mask->xi2mask, sizeof(mask->xi2mask)); + xi2mask_merge(grab->xi2mask, mask->xi2mask); if (cursor) cursor->refcnt++; return grab; @@ -243,6 +254,7 @@ FreeGrab(GrabPtr pGrab) if (pGrab->cursor) FreeCursor(pGrab->cursor, (Cursor)0); + xi2mask_free(&pGrab->xi2mask); free(pGrab); } @@ -251,6 +263,7 @@ CopyGrab(GrabPtr dst, const GrabPtr src) { Mask *mdetails_mask = NULL; Mask *details_mask = NULL; + XI2Mask *xi2mask; if (src->cursor) src->cursor->refcnt++; @@ -273,9 +286,24 @@ CopyGrab(GrabPtr dst, const GrabPtr src) memcpy(details_mask, src->detail.pMask, len); } + if (!dst->xi2mask) { + xi2mask = xi2mask_new(); + if (!xi2mask) { + free(mdetails_mask); + free(details_mask); + return FALSE; + } + } else { + xi2mask = dst->xi2mask; + xi2mask_zero(xi2mask, -1); + } + *dst = *src; dst->modifiersDetail.pMask = mdetails_mask; dst->detail.pMask = details_mask; + dst->xi2mask = xi2mask; + + xi2mask_merge(dst->xi2mask, src->xi2mask); return TRUE; } diff --git a/include/inputstr.h b/include/inputstr.h index a73ace830..5634f3cfc 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -118,7 +118,7 @@ typedef struct _InputClients { XID resource; /**< id for putting into resource manager */ Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */ /** XI2 event masks. One per device, each bit is a mask of (1 << type) */ - unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; + struct _XI2Mask *xi2mask; } InputClients; /** @@ -148,7 +148,7 @@ typedef struct _OtherInputMasks { /** The clients that selected for events */ InputClientsPtr inputClients; /* XI2 event masks. One per device, each bit is a mask of (1 << type) */ - unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; + struct _XI2Mask *xi2mask; } OtherInputMasks; /* @@ -176,7 +176,7 @@ typedef enum { union _GrabMask { Mask core; Mask xi; - char xi2mask[EMASKSIZE][XI2MASKSIZE]; + struct _XI2Mask *xi2mask; }; /** @@ -210,7 +210,7 @@ typedef struct _GrabRec { Mask eventMask; Mask deviceMask; /* XI2 event masks. One per device, each bit is a mask of (1 << type) */ - unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE]; + struct _XI2Mask *xi2mask; } GrabRec; /** From 9b570ecbda954227c89938ee6f94b9efd192d3c6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 9 Dec 2011 10:48:05 +1000 Subject: [PATCH 14/22] xfree86: bump the input ABI The last few patches broke the ABI, bump it for convenience. Signed-off-by: Peter Hutterer --- hw/xfree86/common/xf86Module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h index a9645e77b..d35464351 100644 --- a/hw/xfree86/common/xf86Module.h +++ b/hw/xfree86/common/xf86Module.h @@ -83,7 +83,7 @@ typedef enum { */ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) #define ABI_VIDEODRV_VERSION SET_ABI_VERSION(12, 0) -#define ABI_XINPUT_VERSION SET_ABI_VERSION(14, 0) +#define ABI_XINPUT_VERSION SET_ABI_VERSION(15, 0) #define ABI_EXTENSION_VERSION SET_ABI_VERSION(6, 0) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) From 27425f07b29e0ddaa782345c1899273ca742891e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 9 Nov 2011 14:45:02 +1000 Subject: [PATCH 15/22] dix: use BUG_WARN for input mask size issues Yes, we're likely corrupting memory here but really this is unlikely to be triggered other than a real bug in the server. In which case a stacktrace is going to be more useful than any silent error handling. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/inpututils.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/dix/inpututils.c b/dix/inpututils.c index 05d4c7ce1..60f9fa0a8 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -972,8 +972,9 @@ xi2mask_isset(XI2Mask* mask, const DeviceIntPtr dev, int event_type) { int set = 0; - if (dev->id < 0 || dev->id >= mask->nmasks || event_type >= mask->mask_size) - return 0; + BUG_WARN(dev->id < 0); + BUG_WARN(dev->id >= mask->nmasks); + BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size); set = !!BitIsOn(mask->masks[XIAllDevices], event_type); if (!set) @@ -990,8 +991,9 @@ xi2mask_isset(XI2Mask* mask, const DeviceIntPtr dev, int event_type) void xi2mask_set(XI2Mask *mask, int deviceid, int event_type) { - if (deviceid < 0 || deviceid >= mask->nmasks || event_type >= mask->mask_size) - return; + BUG_WARN(deviceid < 0); + BUG_WARN(deviceid >= mask->nmasks); + BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size); SetBit(mask->masks[deviceid], event_type); } @@ -1005,8 +1007,7 @@ xi2mask_zero(XI2Mask *mask, int deviceid) { int i; - if (deviceid > 0 && deviceid >= mask->nmasks) - return; + BUG_WARN(deviceid > 0 && deviceid >= mask->nmasks); if (deviceid >= 0) memset(mask->masks[deviceid], 0, mask->mask_size); @@ -1055,8 +1056,8 @@ xi2mask_mask_size(const XI2Mask *mask) void xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, size_t mask_size) { - if (deviceid < 0 || deviceid >= xi2mask->nmasks) - return; + BUG_WARN(deviceid < 0); + BUG_WARN(deviceid >= xi2mask->nmasks); memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size)); } @@ -1067,8 +1068,8 @@ xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, const unsigned char* xi2mask_get_one_mask(const XI2Mask *mask, int deviceid) { - if (deviceid < 0 || deviceid >= mask->nmasks) - return NULL; + BUG_WARN(deviceid < 0); + BUG_WARN(deviceid >= mask->nmasks); return mask->masks[deviceid]; } From d2ebbcdaf6b13d70eee704b1764ff349e1be22a0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 29 Nov 2011 16:15:37 +1000 Subject: [PATCH 16/22] Xi: when removing a device, reset ClientPointers where needed if a client had the to-be-removed device as ClientPointer, reset to NULL. Fixes #43165 Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston --- Xi/xichangehierarchy.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c index 614d23116..a8bc761d3 100644 --- a/Xi/xichangehierarchy.c +++ b/Xi/xichangehierarchy.c @@ -200,6 +200,19 @@ unwind: return rc; } +static int +disable_clientpointer(DeviceIntPtr dev) +{ + int i; + + for (i = 0; i < currentMaxClients; i++) + { + ClientPtr client = clients[i]; + if (client && client->clientPtr == dev) + client->clientPtr = NULL; + } +} + static int remove_master(ClientPtr client, xXIRemoveMasterInfo *r, int flags[MAXDEVICES]) @@ -250,6 +263,8 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo *r, if (rc != Success) goto unwind; + disable_clientpointer(ptr); + /* Disabling sends the devices floating, reattach them if * desired. */ if (r->return_mode == XIAttachToMaster) From 1ab50be938524dcd4a9e56d27e3b96a27c2db2c0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 30 Nov 2011 09:06:06 +1000 Subject: [PATCH 17/22] xfixes: don't dereference a NULL cursor If the new cursor is the NULL cursor, don't dereference it and use zeros instead. Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston --- xfixes/cursor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xfixes/cursor.c b/xfixes/cursor.c index 2950e4579..53f9f202a 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -179,9 +179,9 @@ CursorDisplayCursor (DeviceIntPtr pDev, ev.type = XFixesEventBase + XFixesCursorNotify; ev.subtype = XFixesDisplayCursorNotify; ev.window = e->pWindow->drawable.id; - ev.cursorSerial = pCursor->serialNumber; + ev.cursorSerial = pCursor ? pCursor->serialNumber : 0; ev.timestamp = currentTime.milliseconds; - ev.name = pCursor->name; + ev.name = pCursor ? pCursor->name : None; WriteEventsToClient (e->pClient, 1, (xEvent *) &ev); } } From a1304d6cb69301899c3c8450d6bf3e68573599df Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 5 Dec 2011 11:26:30 +1000 Subject: [PATCH 18/22] Xi: skip superfluous cast Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- Xi/exevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 7a84c6b3d..5e446ec4a 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1033,7 +1033,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) if (grab) DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab); - else if (device->focus && !IsPointerEvent((InternalEvent*)ev)) + else if (device->focus && !IsPointerEvent(ev)) DeliverFocusedEvent(device, (InternalEvent*)event, GetSpriteWindow(device)); else From 631516a4aa9858874ee197444cd93d91b97a1089 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 2 Dec 2011 15:47:58 +1000 Subject: [PATCH 19/22] Xi: check button mapping value _before_ assigning it Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- Xi/exevents.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 5e446ec4a..532f04e42 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1002,11 +1002,9 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) deactivateDeviceGrab = TRUE; break; case ET_ButtonPress: - event->detail.button = b->map[key]; - if (!event->detail.button) { /* there's no button 0 */ - event->detail.button = key; + if (b->map[key] == 0) /* there's no button 0 */ return; - } + event->detail.button = b->map[key]; if (!grab && CheckDeviceGrabs(device, event, 0)) { /* if a passive grab was activated, the event has been sent @@ -1015,11 +1013,9 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) } break; case ET_ButtonRelease: - event->detail.button = b->map[key]; - if (!event->detail.button) { /* there's no button 0 */ - event->detail.button = key; + if (b->map[key] == 0) /* there's no button 0 */ return; - } + event->detail.button = b->map[key]; if (grab && !b->buttonsDown && device->deviceGrab.fromPassiveGrab && (device->deviceGrab.grab->type == ButtonPress || From 8c9589c71d47f287588314d77ddbfcc22cd04c8a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 5 Dec 2011 11:55:58 +1000 Subject: [PATCH 20/22] Xi: rename "state" to "corestate" in ProcessDeviceEvents 'state' is shadowed by the XKB 'state' as well (which feeds into the event too), so rename this one to clarify that this is the core event state only. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- Xi/exevents.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 532f04e42..b2e82ec06 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -885,7 +885,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) int key = 0, rootX, rootY; ButtonClassPtr b; int ret = 0; - int state, i; + int corestate, i; DeviceIntPtr mouse = NULL, kbd = NULL; DeviceEvent *event = &ev->device_event; @@ -915,9 +915,9 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) mouse = NULL; } - /* State needs to be assembled BEFORE the device is updated. */ - state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0; - state |= (mouse && mouse->button) ? (mouse->button->state) : 0; + /* core state needs to be assembled BEFORE the device is updated. */ + corestate = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0; + corestate |= (mouse && mouse->button) ? (mouse->button->state) : 0; for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) if (BitIsOn(mouse->button->down, i)) @@ -965,7 +965,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) event->root_x = rootX; event->root_y = rootY; NoticeEventTime((InternalEvent*)event); - event->corestate = state; + event->corestate = corestate; key = event->detail.key; break; default: From 4fc797f3756611a97767f407e1af0b6a7cf2f1d9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 11 Nov 2011 16:25:30 +1000 Subject: [PATCH 21/22] xfree86: include xorg-config.h from xaalocal.h Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith --- hw/xfree86/xaa/xaalocal.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/xfree86/xaa/xaalocal.h b/hw/xfree86/xaa/xaalocal.h index a9a70da08..0780fb133 100644 --- a/hw/xfree86/xaa/xaalocal.h +++ b/hw/xfree86/xaa/xaalocal.h @@ -2,6 +2,10 @@ #ifndef _XAALOCAL_H #define _XAALOCAL_H +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + /* This file is very unorganized ! */ From 2abe83df686ed64c4f4df711ac3c1fd12131c2e4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 5 Dec 2011 14:02:51 +1000 Subject: [PATCH 22/22] include: add BUG_WARN_MSG for custom error message on bug condition __BUG_WARN_MSG is a simple helper to enable call with and without varargs. I couldn't find a way to otherwise do this without getting gcc warnings. Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- include/misc.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/misc.h b/include/misc.h index ef86fa539..d9811ca60 100644 --- a/include/misc.h +++ b/include/misc.h @@ -359,11 +359,18 @@ typedef struct _CharInfo *CharInfoPtr; /* also in fonts/include/font.h */ extern _X_EXPORT unsigned long globalSerialNumber; extern _X_EXPORT unsigned long serverGeneration; -#define BUG_WARN(cond) \ +/* Don't use this directly, use BUG_WARN or BUG_WARN_MSG instead */ +#define __BUG_WARN_MSG(cond, with_msg, ...) \ do { if (cond) { \ ErrorF("BUG: triggered 'if (" #cond ")'\nBUG: %s:%d in %s()\n", \ __FILE__, __LINE__, __func__); \ + if (with_msg) ErrorF(__VA_ARGS__); \ xorg_backtrace(); \ } } while(0) +#define BUG_WARN_MSG(cond, msg, ...) \ + __BUG_WARN_MSG(cond, 1, msg, __VA_ARGS__) + +#define BUG_WARN(cond) __BUG_WARN_MSG(cond, 0, NULL) + #endif /* MISC_H */