present: Handle event mask updates as specified v2

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 <michel.daenzer@amd.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Michel Dänzer 2016-07-29 18:41:06 +09:00 committed by Keith Packard
parent 0924ac014d
commit c833c0866f
2 changed files with 26 additions and 5 deletions

View File

@ -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)

View File

@ -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;