From c833c0866f2f8f829185667efe3d6dfa5979a9e8 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 29 Jul 2016 18:41:06 +0900 Subject: present: Handle event mask updates as specified v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the Present extension specification: An event context is associated with a specific window; using an existing event context with a different window generates a Match error. If eventContext specifies an existing event context, then if eventMask is empty, PresentSelectInput deletes the specified context, otherwise the specified event context is changed to select a different set of events. If eventContext is an unused XID, then if eventMask is empty no operation is performed. Otherwise, a new event context is created selecting the specified events. Without this change, there's no way for a client to explicitly change or destroy an existing event mask entry. Trying to do so as specified above would just result in a protocol error. v2: (Keith Packard) * Use dixLookupResourceByType instead of walking window_priv->events * Return BadMatch if the existing event context is associated with a different window or client * Call LEGAL_NEW_RESOURCE again when creating a new event context * Drop invalid "leak fix" Signed-off-by: Michel Dänzer Signed-off-by: Keith Packard Reviewed-by: Keith Packard Reviewed-by: Kenneth Graunke --- present/present_event.c | 29 ++++++++++++++++++++++++++--- present/present_request.c | 2 -- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'present') diff --git a/present/present_event.c b/present/present_event.c index c586c9a60..c222dd5ff 100644 --- a/present/present_event.c +++ b/present/present_event.c @@ -208,14 +208,37 @@ present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, stru int present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) { - present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0); + present_window_priv_ptr window_priv; present_event_ptr event; + int ret; + + /* Check to see if we're modifying an existing event selection */ + ret = dixLookupResourceByType((void **) &event, eid, present_event_type, + client, DixWriteAccess); + if (ret == Success) { + /* Match error for the wrong window; also don't modify some other + * client's event selection + */ + if (event->window != window || event->client != client) + return BadMatch; - if (!window_priv) { if (mask) - return BadAlloc; + event->mask = mask; + else + FreeResource(eid, RT_NONE); return Success; } + if (ret != BadValue) + return ret; + + if (mask == 0) + return Success; + + LEGAL_NEW_RESOURCE(eid, client); + + window_priv = present_get_window_priv(window, TRUE); + if (!window_priv) + return BadAlloc; event = calloc (1, sizeof (present_event_rec)); if (!event) diff --git a/present/present_request.c b/present/present_request.c index 35320b64e..c7663fcc8 100644 --- a/present/present_request.c +++ b/present/present_request.c @@ -184,8 +184,6 @@ proc_present_select_input (ClientPtr client) REQUEST_SIZE_MATCH(xPresentSelectInputReq); - LEGAL_NEW_RESOURCE(stuff->eid, client); - rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); if (rc != Success) return rc; -- cgit v1.2.3