present_event.c (7943B)
1 /* 2 * Copyright © 2013 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23 #include "present_priv.h" 24 25 static RESTYPE present_event_type; 26 27 static int 28 present_free_event(void *data, XID id) 29 { 30 present_event_ptr present_event = (present_event_ptr) data; 31 present_window_priv_ptr window_priv = present_window_priv(present_event->window); 32 present_event_ptr *previous, current; 33 34 for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { 35 if (current == present_event) { 36 *previous = present_event->next; 37 break; 38 } 39 } 40 free((void *) present_event); 41 return 1; 42 43 } 44 45 void 46 present_free_events(WindowPtr window) 47 { 48 present_window_priv_ptr window_priv = present_window_priv(window); 49 present_event_ptr event; 50 51 if (!window_priv) 52 return; 53 54 while ((event = window_priv->events)) 55 FreeResource(event->id, RT_NONE); 56 } 57 58 static void 59 present_event_swap(xGenericEvent *from, xGenericEvent *to) 60 { 61 *to = *from; 62 swaps(&to->sequenceNumber); 63 swapl(&to->length); 64 swaps(&to->evtype); 65 switch (from->evtype) { 66 case PresentConfigureNotify: { 67 xPresentConfigureNotify *c = (xPresentConfigureNotify *) to; 68 69 swapl(&c->eid); 70 swapl(&c->window); 71 swaps(&c->x); 72 swaps(&c->y); 73 swaps(&c->width); 74 swaps(&c->height); 75 swaps(&c->off_x); 76 swaps(&c->off_y); 77 swaps(&c->pixmap_width); 78 swaps(&c->pixmap_height); 79 swapl(&c->pixmap_flags); 80 break; 81 } 82 case PresentCompleteNotify: 83 { 84 xPresentCompleteNotify *c = (xPresentCompleteNotify *) to; 85 swapl(&c->eid); 86 swapl(&c->window); 87 swapl(&c->serial); 88 swapll(&c->ust); 89 swapll(&c->msc); 90 break; 91 } 92 case PresentIdleNotify: 93 { 94 xPresentIdleNotify *c = (xPresentIdleNotify *) to; 95 swapl(&c->eid); 96 swapl(&c->window); 97 swapl(&c->serial); 98 swapl(&c->idle_fence); 99 break; 100 } 101 } 102 } 103 104 void 105 present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) 106 { 107 present_window_priv_ptr window_priv = present_window_priv(window); 108 109 if (window_priv) { 110 xPresentConfigureNotify cn = { 111 .type = GenericEvent, 112 .extension = present_request, 113 .length = (sizeof(xPresentConfigureNotify) - 32) >> 2, 114 .evtype = PresentConfigureNotify, 115 .eid = 0, 116 .window = window->drawable.id, 117 .x = x, 118 .y = y, 119 .width = w, 120 .height = h, 121 .off_x = 0, 122 .off_y = 0, 123 .pixmap_width = w, 124 .pixmap_height = h, 125 .pixmap_flags = 0 126 }; 127 present_event_ptr event; 128 129 for (event = window_priv->events; event; event = event->next) { 130 if (event->mask & (1 << PresentConfigureNotify)) { 131 cn.eid = event->id; 132 WriteEventsToClient(event->client, 1, (xEvent *) &cn); 133 } 134 } 135 } 136 } 137 138 static present_complete_notify_proc complete_notify; 139 140 void 141 present_register_complete_notify(present_complete_notify_proc proc) 142 { 143 complete_notify = proc; 144 } 145 146 void 147 present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) 148 { 149 present_window_priv_ptr window_priv = present_window_priv(window); 150 151 if (window_priv) { 152 xPresentCompleteNotify cn = { 153 .type = GenericEvent, 154 .extension = present_request, 155 .length = (sizeof(xPresentCompleteNotify) - 32) >> 2, 156 .evtype = PresentCompleteNotify, 157 .kind = kind, 158 .mode = mode, 159 .eid = 0, 160 .window = window->drawable.id, 161 .serial = serial, 162 .ust = ust, 163 .msc = msc, 164 }; 165 present_event_ptr event; 166 167 for (event = window_priv->events; event; event = event->next) { 168 if (event->mask & PresentCompleteNotifyMask) { 169 cn.eid = event->id; 170 WriteEventsToClient(event->client, 1, (xEvent *) &cn); 171 } 172 } 173 } 174 if (complete_notify) 175 (*complete_notify)(window, kind, mode, serial, ust, msc); 176 } 177 178 void 179 present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence) 180 { 181 present_window_priv_ptr window_priv = present_window_priv(window); 182 183 if (window_priv) { 184 xPresentIdleNotify in = { 185 .type = GenericEvent, 186 .extension = present_request, 187 .length = (sizeof(xPresentIdleNotify) - 32) >> 2, 188 .evtype = PresentIdleNotify, 189 .eid = 0, 190 .window = window->drawable.id, 191 .serial = serial, 192 .pixmap = pixmap->drawable.id, 193 .idle_fence = present_fence_id(idle_fence) 194 }; 195 present_event_ptr event; 196 197 for (event = window_priv->events; event; event = event->next) { 198 if (event->mask & PresentIdleNotifyMask) { 199 in.eid = event->id; 200 WriteEventsToClient(event->client, 1, (xEvent *) &in); 201 } 202 } 203 } 204 } 205 206 int 207 present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) 208 { 209 present_window_priv_ptr window_priv; 210 present_event_ptr event; 211 int ret; 212 213 /* Check to see if we're modifying an existing event selection */ 214 ret = dixLookupResourceByType((void **) &event, eid, present_event_type, 215 client, DixWriteAccess); 216 if (ret == Success) { 217 /* Match error for the wrong window; also don't modify some other 218 * client's event selection 219 */ 220 if (event->window != window || event->client != client) 221 return BadMatch; 222 223 if (mask) 224 event->mask = mask; 225 else 226 FreeResource(eid, RT_NONE); 227 return Success; 228 } 229 if (ret != BadValue) 230 return ret; 231 232 if (mask == 0) 233 return Success; 234 235 LEGAL_NEW_RESOURCE(eid, client); 236 237 window_priv = present_get_window_priv(window, TRUE); 238 if (!window_priv) 239 return BadAlloc; 240 241 event = calloc (1, sizeof (present_event_rec)); 242 if (!event) 243 return BadAlloc; 244 245 event->client = client; 246 event->window = window; 247 event->id = eid; 248 event->mask = mask; 249 250 event->next = window_priv->events; 251 window_priv->events = event; 252 253 if (!AddResource(event->id, present_event_type, (void *) event)) 254 return BadAlloc; 255 256 return Success; 257 } 258 259 Bool 260 present_event_init(void) 261 { 262 present_event_type = CreateNewResourceType(present_free_event, "PresentEvent"); 263 if (!present_event_type) 264 return FALSE; 265 266 GERegisterExtension(present_request, present_event_swap); 267 return TRUE; 268 }