present_event.c revision 35c4bbdf
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#ifdef HAVE_XORG_CONFIG_H 24#include <xorg-config.h> 25#endif 26 27#include "present_priv.h" 28 29static RESTYPE present_event_type; 30 31static int 32present_free_event(void *data, XID id) 33{ 34 present_event_ptr present_event = (present_event_ptr) data; 35 present_window_priv_ptr window_priv = present_window_priv(present_event->window); 36 present_event_ptr *previous, current; 37 38 for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { 39 if (current == present_event) { 40 *previous = present_event->next; 41 break; 42 } 43 } 44 free((void *) present_event); 45 return 1; 46 47} 48 49void 50present_free_events(WindowPtr window) 51{ 52 present_window_priv_ptr window_priv = present_window_priv(window); 53 present_event_ptr event; 54 55 if (!window_priv) 56 return; 57 58 while ((event = window_priv->events)) 59 FreeResource(event->id, RT_NONE); 60} 61 62static void 63present_event_swap(xGenericEvent *from, xGenericEvent *to) 64{ 65 *to = *from; 66 swaps(&to->sequenceNumber); 67 swapl(&to->length); 68 swaps(&to->evtype); 69 switch (from->evtype) { 70 case PresentConfigureNotify: { 71 xPresentConfigureNotify *c = (xPresentConfigureNotify *) to; 72 73 swapl(&c->eid); 74 swapl(&c->window); 75 swaps(&c->x); 76 swaps(&c->y); 77 swaps(&c->width); 78 swaps(&c->height); 79 swaps(&c->off_x); 80 swaps(&c->off_y); 81 swaps(&c->pixmap_width); 82 swaps(&c->pixmap_height); 83 swapl(&c->pixmap_flags); 84 break; 85 } 86 case PresentCompleteNotify: 87 { 88 xPresentCompleteNotify *c = (xPresentCompleteNotify *) to; 89 swapl(&c->eid); 90 swapl(&c->window); 91 swapl(&c->serial); 92 swapll(&c->ust); 93 swapll(&c->msc); 94 } 95 case PresentIdleNotify: 96 { 97 xPresentIdleNotify *c = (xPresentIdleNotify *) to; 98 swapl(&c->eid); 99 swapl(&c->window); 100 swapl(&c->serial); 101 swapl(&c->idle_fence); 102 } 103 } 104} 105 106void 107present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) 108{ 109 present_window_priv_ptr window_priv = present_window_priv(window); 110 111 if (window_priv) { 112 xPresentConfigureNotify cn = { 113 .type = GenericEvent, 114 .extension = present_request, 115 .length = (sizeof(xPresentConfigureNotify) - 32) >> 2, 116 .evtype = PresentConfigureNotify, 117 .eid = 0, 118 .window = window->drawable.id, 119 .x = x, 120 .y = y, 121 .width = w, 122 .height = h, 123 .off_x = 0, 124 .off_y = 0, 125 .pixmap_width = w, 126 .pixmap_height = h, 127 .pixmap_flags = 0 128 }; 129 present_event_ptr event; 130 131 for (event = window_priv->events; event; event = event->next) { 132 if (event->mask & (1 << PresentConfigureNotify)) { 133 cn.eid = event->id; 134 WriteEventsToClient(event->client, 1, (xEvent *) &cn); 135 } 136 } 137 } 138} 139 140static present_complete_notify_proc complete_notify; 141 142void 143present_register_complete_notify(present_complete_notify_proc proc) 144{ 145 complete_notify = proc; 146} 147 148void 149present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) 150{ 151 present_window_priv_ptr window_priv = present_window_priv(window); 152 153 if (window_priv) { 154 xPresentCompleteNotify cn = { 155 .type = GenericEvent, 156 .extension = present_request, 157 .length = (sizeof(xPresentCompleteNotify) - 32) >> 2, 158 .evtype = PresentCompleteNotify, 159 .kind = kind, 160 .mode = mode, 161 .eid = 0, 162 .window = window->drawable.id, 163 .serial = serial, 164 .ust = ust, 165 .msc = msc, 166 }; 167 present_event_ptr event; 168 169 for (event = window_priv->events; event; event = event->next) { 170 if (event->mask & PresentCompleteNotifyMask) { 171 cn.eid = event->id; 172 WriteEventsToClient(event->client, 1, (xEvent *) &cn); 173 } 174 } 175 } 176 if (complete_notify) 177 (*complete_notify)(window, kind, mode, serial, ust, msc); 178} 179 180void 181present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence) 182{ 183 present_window_priv_ptr window_priv = present_window_priv(window); 184 185 if (window_priv) { 186 xPresentIdleNotify in = { 187 .type = GenericEvent, 188 .extension = present_request, 189 .length = (sizeof(xPresentIdleNotify) - 32) >> 2, 190 .evtype = PresentIdleNotify, 191 .eid = 0, 192 .window = window->drawable.id, 193 .serial = serial, 194 .pixmap = pixmap->drawable.id, 195 .idle_fence = present_fence_id(idle_fence) 196 }; 197 present_event_ptr event; 198 199 for (event = window_priv->events; event; event = event->next) { 200 if (event->mask & PresentIdleNotifyMask) { 201 in.eid = event->id; 202 WriteEventsToClient(event->client, 1, (xEvent *) &in); 203 } 204 } 205 } 206} 207 208int 209present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) 210{ 211 present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0); 212 present_event_ptr event; 213 214 if (!window_priv) { 215 if (mask) 216 return BadAlloc; 217 return Success; 218 } 219 220 event = calloc (1, sizeof (present_event_rec)); 221 if (!event) 222 return BadAlloc; 223 224 event->client = client; 225 event->window = window; 226 event->id = eid; 227 event->mask = mask; 228 229 event->next = window_priv->events; 230 window_priv->events = event; 231 232 if (!AddResource(event->id, present_event_type, (void *) event)) 233 return BadAlloc; 234 235 return Success; 236} 237 238Bool 239present_event_init(void) 240{ 241 present_event_type = CreateNewResourceType(present_free_event, "PresentEvent"); 242 if (!present_event_type) 243 return FALSE; 244 245 GERegisterExtension(present_request, present_event_swap); 246 return TRUE; 247} 248