/* _al_run_destructors: * Run all the destructors on the list in reverse order. */ void _al_run_destructors(_AL_DTOR_LIST *dtors) { if (!dtors) { return; } /* call the destructors in reverse order */ _al_mutex_lock(&dtors->mutex); { while (!_al_vector_is_empty(&dtors->dtors)) { DTOR *dtor = _al_vector_ref_back(&dtors->dtors); void *object = dtor->object; void (*func)(void *) = dtor->func; ALLEGRO_DEBUG("calling dtor for %s %p, func %p\n", dtor->name, object, func); _al_mutex_unlock(&dtors->mutex); { (*func)(object); } _al_mutex_lock(&dtors->mutex); } } _al_mutex_unlock(&dtors->mutex); }
static void _al_xsys_xinerama_init(ALLEGRO_SYSTEM_XGLX *s) { int event_base = 0; int error_base = 0; /* init xinerama info to defaults */ s->xinerama_available = 0; s->xinerama_screen_count = 0; s->xinerama_screen_info = NULL; _al_mutex_lock(&s->lock); if (XineramaQueryExtension(s->x11display, &event_base, &error_base)) { int minor_version = 0, major_version = 0; int status = XineramaQueryVersion(s->x11display, &major_version, &minor_version); ALLEGRO_INFO("Xinerama version: %i.%i\n", major_version, minor_version); if (status && !XineramaIsActive(s->x11display)) { ALLEGRO_WARN("Xinerama is not active\n"); } else { ALLEGRO_INFO("Xinerama is active\n"); s->xinerama_available = 1; } } else { ALLEGRO_WARN("Xinerama extension is not available.\n"); } _al_mutex_unlock(&s->lock); }
static bool xfvm_get_monitor_info(ALLEGRO_SYSTEM_XGLX *s, int adapter, ALLEGRO_MONITOR_INFO *mi) { #ifdef ALLEGRO_XWINDOWS_WITH_XINERAMA if (s->xinerama_available) { return xinerama_get_monitor_info(s, adapter, mi); } #endif if (adapter < 0 || adapter > s->xfvm_screen_count) return false; XWindowAttributes xwa; Window root; _al_mutex_lock(&s->lock); root = RootWindow(s->x11display, adapter); XGetWindowAttributes(s->x11display, root, &xwa); _al_mutex_unlock(&s->lock); /* under plain X, each screen has its own origin, and theres no way to figure out orientation or relative position */ mi->x1 = 0; mi->y1 = 0; mi->x2 = xwa.width; mi->y2 = xwa.height; return true; }
static int xglx_get_num_video_adapters(void) { #ifdef ALLEGRO_XWINDOWS_WITH_XINERAMA ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); if (!system->xinerama_available) { return 1; } if (system->xinerama_screen_info) { XFree(system->xinerama_screen_info); system->xinerama_screen_info = NULL; system->xinerama_screen_count = 0; } _al_mutex_lock(&system->lock); system->xinerama_screen_info = XineramaQueryScreens(system->x11display, &(system->xinerama_screen_count)); _al_mutex_unlock(&system->lock); if (!system->xinerama_screen_info) { system->xinerama_available = 0; system->xinerama_screen_count = 0; return 1; } return system->xinerama_screen_count; #else /* !ALLEGRO_XWINDOWS_WITH_XINERAMA */ return 1; #endif /* !ALLEGRO_XWINDOWS_WITH_XINERAMA */ }
/* Function: al_start_thread */ void al_start_thread(ALLEGRO_THREAD *thread) { ASSERT(thread); switch (thread->thread_state) { case THREAD_STATE_CREATED: _al_mutex_lock(&thread->mutex); thread->thread_state = THREAD_STATE_STARTING; _al_cond_broadcast(&thread->cond); _al_mutex_unlock(&thread->mutex); break; case THREAD_STATE_STARTING: break; case THREAD_STATE_STARTED: break; /* invalid cases */ case THREAD_STATE_JOINING: ASSERT(thread->thread_state != THREAD_STATE_JOINING); break; case THREAD_STATE_JOINED: ASSERT(thread->thread_state != THREAD_STATE_JOINED); break; case THREAD_STATE_DESTROYED: ASSERT(thread->thread_state != THREAD_STATE_DESTROYED); break; case THREAD_STATE_DETACHED: ASSERT(thread->thread_state != THREAD_STATE_DETACHED); break; } }
void _al_xwin_destroy_mouse_cursor(ALLEGRO_MOUSE_CURSOR *cursor) { ALLEGRO_MOUSE_CURSOR_XGLX *xcursor = (ALLEGRO_MOUSE_CURSOR_XGLX *)cursor; ALLEGRO_SYSTEM *sys = al_get_system_driver(); ALLEGRO_SYSTEM_XGLX *sysx = (ALLEGRO_SYSTEM_XGLX *)sys; unsigned i; _al_mutex_lock(&sysx->lock); for (i = 0; i < _al_vector_size(&sys->displays); i++) { ALLEGRO_DISPLAY_XGLX **slot = _al_vector_ref(&sys->displays, i); ALLEGRO_DISPLAY_XGLX *glx = *slot; if (glx->current_cursor == xcursor->cursor) { if (!glx->cursor_hidden) XUndefineCursor(sysx->x11display, glx->window); glx->current_cursor = None; } } XFreeCursor(sysx->x11display, xcursor->cursor); al_free(xcursor); _al_mutex_unlock(&sysx->lock); }
static void thread_func_trampoline(_AL_THREAD *inner, void *_outer) { ALLEGRO_THREAD *outer = (ALLEGRO_THREAD *) _outer; ALLEGRO_SYSTEM *system = al_get_system_driver(); (void)inner; if (system && system->vt && system->vt->thread_init) { system->vt->thread_init(outer); } /* Wait to start the actual user thread function. The thread could also be * destroyed before ever running the user function. */ _al_mutex_lock(&outer->mutex); while (outer->thread_state == THREAD_STATE_CREATED) { _al_cond_wait(&outer->cond, &outer->mutex); } _al_mutex_unlock(&outer->mutex); if (outer->thread_state == THREAD_STATE_STARTING) { outer->thread_state = THREAD_STATE_STARTED; outer->retval = ((void *(*)(ALLEGRO_THREAD *, void *))outer->proc)(outer, outer->arg); } if (system && system->vt && system->vt->thread_exit) { system->vt->thread_exit(outer); } }
/* [user thread] */ static void xgtk_set_fullscreen_window(ALLEGRO_DISPLAY *display, bool onoff) { ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *d = (ALLEGRO_DISPLAY_XGLX *)display; if (onoff == (display->flags & ALLEGRO_FULLSCREEN_WINDOW)) { return; } _al_mutex_lock(&system->lock); { int old_resize_count; ARGS_FULLSCREEN_WINDOW args; display->flags ^= ALLEGRO_FULLSCREEN_WINDOW; old_resize_count = d->resize_count; d->programmatic_resize = true; if (_al_gtk_init_args(&args, sizeof(args))) { args.display = d; args.fullscreen = onoff; _al_gtk_wait_for_args(do_set_fullscreen_window, &args); _al_display_xglx_await_resize(display, old_resize_count, (display->flags & ALLEGRO_FULLSCREEN)); } d->programmatic_resize = false; } _al_mutex_unlock(&system->lock); }
static void xdpy_set_window_position(ALLEGRO_DISPLAY *display, int x, int y) { ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)display; Window root, parent, child, *children; unsigned int n; _al_mutex_lock(&system->lock); /* To account for the window border, we have to find the parent window which * draws the border. If the parent is the root though, then we should not * translate. */ XQueryTree(system->x11display, glx->window, &root, &parent, &children, &n); if (parent != root) { XTranslateCoordinates(system->x11display, parent, glx->window, x, y, &x, &y, &child); } XMoveWindow(system->x11display, glx->window, x, y); XFlush(system->x11display); /* We have to store these immediately, as we will ignore the XConfigureEvent * that we receive in response. _al_display_xglx_configure() knows why. */ glx->x = x; glx->y = y; _al_mutex_unlock(&system->lock); }
/* xmouse_get_mouse_num_buttons: * Return the number of buttons on the mouse. */ static unsigned int xmouse_get_mouse_num_buttons(void) { int num_buttons; unsigned char map[32]; ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); ASSERT(xmouse_installed); _al_mutex_lock(&system->lock); num_buttons = XGetPointerMapping(system->x11display, map, sizeof(map)); _al_mutex_unlock(&system->lock); if (num_buttons > (int)sizeof(map)) num_buttons = sizeof(map); #ifdef DEBUGMODE char debug[num_buttons * 4 + 1]; debug[0] = 0; int i; for (i = 0; i < num_buttons; i++) { sprintf(debug + strlen(debug), "%2d,", map[i]); } ALLEGRO_DEBUG("XGetPointerMapping: %s\n", debug); #endif if (num_buttons < 1) num_buttons = 1; return num_buttons; }
ALLEGRO_MOUSE_CURSOR *_al_xwin_create_mouse_cursor(ALLEGRO_BITMAP *bmp, int x_focus, int y_focus) { ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver(); Display *xdisplay = system->x11display; int bmp_w; int bmp_h; ALLEGRO_MOUSE_CURSOR_XGLX *xcursor; XcursorImage *image; int c, ix, iy; bool was_locked; bmp_w = al_get_bitmap_width(bmp); bmp_h = al_get_bitmap_height(bmp); xcursor = al_malloc(sizeof *xcursor); if (!xcursor) { return NULL; } image = XcursorImageCreate(bmp->w, bmp->h); if (image == None) { al_free(xcursor); return NULL; } was_locked = al_is_bitmap_locked(bmp); if (!was_locked) { al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY); } c = 0; for (iy = 0; iy < bmp_h; iy++) { for (ix = 0; ix < bmp_w; ix++) { ALLEGRO_COLOR col; unsigned char r, g, b, a; col = al_get_pixel(bmp, ix, iy); al_unmap_rgba(col, &r, &g, &b, &a); image->pixels[c++] = (a<<24) | (r<<16) | (g<<8) | (b); } } if (!was_locked) { al_unlock_bitmap(bmp); } image->xhot = x_focus; image->yhot = y_focus; _al_mutex_lock(&system->lock); xcursor->cursor = XcursorImageLoadCursor(xdisplay, image); _al_mutex_unlock(&system->lock); XcursorImageDestroy(image); return (ALLEGRO_MOUSE_CURSOR *)xcursor; }
/* Function: al_pause_event_queue */ void al_pause_event_queue(ALLEGRO_EVENT_QUEUE *queue, bool pause) { ASSERT(queue); _al_mutex_lock(&queue->mutex); queue->paused = pause; _al_mutex_unlock(&queue->mutex); }
/* returns -1 on timeout */ static int cond_wait(_AL_COND *cond, _AL_MUTEX *mtxExternal, DWORD timeout) { int nSignalsWasLeft; bool bTimedOut; DWORD dwWaitResult; EnterCriticalSection(&cond->semBlockLock); ++cond->nWaitersBlocked; LeaveCriticalSection(&cond->semBlockLock); _al_mutex_unlock(mtxExternal); dwWaitResult = WaitForSingleObject(cond->semBlockQueue, timeout); if (dwWaitResult == WAIT_TIMEOUT) bTimedOut = true; else if (dwWaitResult == WAIT_OBJECT_0) bTimedOut = false; else { /* bad! what to do? */ _al_mutex_lock(mtxExternal); ASSERT(false); return 0; } EnterCriticalSection(&cond->mtxUnblockLock); if (0 != (nSignalsWasLeft = cond->nWaitersToUnblock)) { --(cond->nWaitersToUnblock); } else if (INT_MAX/2 == ++(cond->nWaitersGone)) { /* timeout/canceled or spurious semaphore :-) */ EnterCriticalSection(&cond->semBlockLock); cond->nWaitersBlocked -= cond->nWaitersGone; /* something is going on here - test of timeouts? :-) */ LeaveCriticalSection(&cond->semBlockLock); cond->nWaitersGone = 0; } LeaveCriticalSection(&cond->mtxUnblockLock); if (1 == nSignalsWasLeft) { LeaveCriticalSection(&cond->semBlockLock); /* open the gate */ } _al_mutex_lock(mtxExternal); return bTimedOut ? -1 : 0; }
static void xdpy_set_window_title(ALLEGRO_DISPLAY *display, const char *title) { ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)display; _al_mutex_lock(&system->lock); glx->overridable_vt->set_window_title(display, title); _al_mutex_unlock(&system->lock); }
bool _al_xwin_ungrab_mouse(void) { ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); _al_mutex_lock(&system->lock); XUngrabPointer(system->x11display, CurrentTime); system->mouse_grab_display = NULL; _al_mutex_unlock(&system->lock); return true; }
static void xglx_get_smonitor_info(ALLEGRO_SYSTEM_XGLX *system, ALLEGRO_MONITOR_INFO *info) { XWindowAttributes xwa; Window root = RootWindow(system->x11display, 0); _al_mutex_lock(&system->lock); XGetWindowAttributes(system->x11display, root, &xwa); _al_mutex_unlock(&system->lock); info->x1 = 0; info->y1 = 0; info->x2 = xwa.width; info->y2 = xwa.height; }
/* Function: al_unregister_event_source */ void al_unregister_event_source(ALLEGRO_EVENT_QUEUE *queue, ALLEGRO_EVENT_SOURCE *source) { bool found; ASSERT(queue); ASSERT(source); /* Remove source from our list. */ _al_mutex_lock(&queue->mutex); found = _al_vector_find_and_delete(&queue->sources, &source); _al_mutex_unlock(&queue->mutex); if (found) { /* Tell the event source that it was unregistered. */ _al_event_source_on_unregistration_from_queue(source, queue); /* Drop all the events in the queue that belonged to the source. */ _al_mutex_lock(&queue->mutex); discard_events_of_source(queue, source); _al_mutex_unlock(&queue->mutex); } }
static bool xglx_get_cursor_position(int *ret_x, int *ret_y) { ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); Window root = RootWindow(system->x11display, 0); Window child; int wx, wy; unsigned int mask; _al_mutex_lock(&system->lock); XQueryPointer(system->x11display, root, &root, &child, ret_x, ret_y, &wx, &wy, &mask); _al_mutex_unlock(&system->lock); return true; }
static void xdpy_destroy_display(ALLEGRO_DISPLAY *d) { ALLEGRO_SYSTEM_XGLX *s = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d; ALLEGRO_OGL_EXTRAS *ogl = d->ogl_extras; bool is_last; ALLEGRO_DEBUG("destroying display.\n"); /* If we're the last display, convert all bitmaps to display independent * (memory) bitmaps. Otherwise, pass all bitmaps to any other living * display. We assume all displays are compatible.) */ is_last = (s->system.displays._size == 1); if (is_last) convert_display_bitmaps_to_memory_bitmap(d); else transfer_display_bitmaps_to_any_other_display(s, d); _al_ogl_unmanage_extensions(d); ALLEGRO_DEBUG("unmanaged extensions.\n"); _al_mutex_lock(&s->lock); _al_vector_find_and_delete(&s->system.displays, &d); if (ogl->backbuffer) { _al_ogl_destroy_backbuffer(ogl->backbuffer); ogl->backbuffer = NULL; ALLEGRO_DEBUG("destroy backbuffer.\n"); } if (glx->overridable_vt) { glx->overridable_vt->destroy_display_hook(d, is_last); } if (s->mouse_grab_display == d) { s->mouse_grab_display = NULL; } _al_vector_free(&d->bitmaps); _al_event_source_free(&d->es); al_free(d->ogl_extras); al_free(d->vertex_cache); al_free(d); _al_mutex_unlock(&s->lock); ALLEGRO_DEBUG("destroy display finished.\n"); }
/* Internal function: _al_foreach_destructor * Call the callback for each registered object. * [thread-safe] */ void _al_foreach_destructor(_AL_DTOR_LIST *dtors, void (*callback)(void *object, void (*func)(void *), void *udata), void *userdata) { _al_mutex_lock(&dtors->mutex); { unsigned int i; for (i = 0; i < _al_vector_size(&dtors->dtors); i++) { DTOR *dtor = _al_vector_ref(&dtors->dtors, i); callback(dtor->object, dtor->func, userdata); } } _al_mutex_unlock(&dtors->mutex); }
/* Function: al_register_event_source */ void al_register_event_source(ALLEGRO_EVENT_QUEUE *queue, ALLEGRO_EVENT_SOURCE *source) { ALLEGRO_EVENT_SOURCE **slot; ASSERT(queue); ASSERT(source); if (!_al_vector_contains(&queue->sources, &source)) { _al_event_source_on_registration_to_queue(source, queue); _al_mutex_lock(&queue->mutex); slot = _al_vector_alloc_back(&queue->sources); *slot = source; _al_mutex_unlock(&queue->mutex); } }
/* Show the system mouse cursor. */ static bool xdpy_show_mouse_cursor(ALLEGRO_DISPLAY *display) { ALLEGRO_DISPLAY_XGLX *glx = (void *)display; ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); Display *xdisplay = system->x11display; Window xwindow = glx->window; if (!glx->cursor_hidden) return true; _al_mutex_lock(&system->lock); XDefineCursor(xdisplay, xwindow, glx->current_cursor); glx->cursor_hidden = false; _al_mutex_unlock(&system->lock); return true; }
static void xdpy_set_fullscreen_window(ALLEGRO_DISPLAY *display, bool onoff) { ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); if (onoff == !(display->flags & ALLEGRO_FULLSCREEN_WINDOW)) { _al_mutex_lock(&system->lock); _al_xwin_reset_size_hints(display); _al_xwin_set_fullscreen_window(display, 2); /* XXX Technically, the user may fiddle with the _NET_WM_STATE_FULLSCREEN * property outside of Allegro so this flag may not be in sync with * reality. */ display->flags ^= ALLEGRO_FULLSCREEN_WINDOW; _al_xwin_set_size_hints(display, INT_MAX, INT_MAX); _al_mutex_unlock(&system->lock); } }
bool _al_xglx_get_monitor_info(ALLEGRO_SYSTEM_XGLX *s, int adapter, ALLEGRO_MONITOR_INFO *info) { if (!init_mmon_interface(s)) return false; if (!_al_xglx_mmon_interface.get_monitor_info) { _al_mutex_lock(&s->lock); info->x1 = 0; info->y1 = 0; info->x2 = DisplayWidth(s->x11display, DefaultScreen(s->x11display)); info->y2 = DisplayHeight(s->x11display, DefaultScreen(s->x11display)); _al_mutex_unlock(&s->lock); return true; } return _al_xglx_mmon_interface.get_monitor_info(s, adapter, info); }
/* Function: al_join_thread */ void al_join_thread(ALLEGRO_THREAD *thread, void **ret_value) { ASSERT(thread); /* If al_join_thread() is called soon after al_start_thread(), the thread * function may not yet have noticed the STARTING state and executed the * user's thread function. Hence we must wait until the thread enters the * STARTED state. */ while (thread->thread_state == THREAD_STATE_STARTING) { al_rest(0.001); } switch (thread->thread_state) { case THREAD_STATE_CREATED: /* fall through */ case THREAD_STATE_STARTED: _al_mutex_lock(&thread->mutex); thread->thread_state = THREAD_STATE_JOINING; _al_cond_broadcast(&thread->cond); _al_mutex_unlock(&thread->mutex); _al_cond_destroy(&thread->cond); _al_mutex_destroy(&thread->mutex); _al_thread_join(&thread->thread); thread->thread_state = THREAD_STATE_JOINED; break; case THREAD_STATE_STARTING: ASSERT(thread->thread_state != THREAD_STATE_STARTING); break; case THREAD_STATE_JOINING: ASSERT(thread->thread_state != THREAD_STATE_JOINING); break; case THREAD_STATE_JOINED: ASSERT(thread->thread_state != THREAD_STATE_JOINED); break; case THREAD_STATE_DESTROYED: ASSERT(thread->thread_state != THREAD_STATE_DESTROYED); break; case THREAD_STATE_DETACHED: ASSERT(thread->thread_state != THREAD_STATE_DETACHED); break; } if (ret_value) { *ret_value = thread->retval; } }
/* used for xinerama and pure xrandr modes */ void _al_xsys_get_active_window_center(ALLEGRO_SYSTEM_XGLX *s, int *x, int *y) { Window focus; int revert_to = 0; _al_mutex_lock(&s->lock); if (!XGetInputFocus(s->x11display, &focus, &revert_to)) { ALLEGRO_ERROR("XGetInputFocus failed!\n"); _al_mutex_unlock(&s->lock); return; } if (focus == None || focus == PointerRoot) { ALLEGRO_DEBUG("XGetInputFocus returned special window, selecting default root!\n"); focus = DefaultRootWindow(s->x11display); } else { /* this horribleness is due to toolkits like GTK (and probably Qt) creating * a 1x1 window under the window you're looking at that actually accepts * all input, so we need to grab the top level parent window rather than * whatever happens to have focus */ focus = get_toplevel_parent(s, focus); } ALLEGRO_DEBUG("XGetInputFocus returned %i\n", (int)focus); XWindowAttributes attr; if (XGetWindowAttributes(s->x11display, focus, &attr) == 0) { ALLEGRO_ERROR("XGetWindowAttributes failed :(\n"); _al_mutex_unlock(&s->lock); return; } _al_mutex_unlock(&s->lock); /* check the center of the window with focus * might be a bit more useful than just checking the top left */ ALLEGRO_DEBUG("focus geom: %ix%i %ix%i\n", attr.x, attr.y, attr.width, attr.height); *x = (attr.x + (attr.x + attr.width)) / 2; *y = (attr.y + (attr.y + attr.height)) / 2; }
static bool xdpy_set_mouse_cursor(ALLEGRO_DISPLAY *display, ALLEGRO_MOUSE_CURSOR *cursor) { ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)display; ALLEGRO_MOUSE_CURSOR_XGLX *xcursor = (ALLEGRO_MOUSE_CURSOR_XGLX *)cursor; ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver(); Display *xdisplay = system->x11display; Window xwindow = glx->window; glx->current_cursor = xcursor->cursor; if (!glx->cursor_hidden) { _al_mutex_lock(&system->lock); XDefineCursor(xdisplay, xwindow, glx->current_cursor); _al_mutex_unlock(&system->lock); } return true; }
static void xdpy_set_icons(ALLEGRO_DISPLAY *d, int num_icons, ALLEGRO_BITMAP *bitmaps[]) { ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d; int prop_mode = PropModeReplace; int i; _al_mutex_lock(&system->lock); for (i = 0; i < num_icons; i++) { if (xdpy_set_icon_inner(system->x11display, glx->window, bitmaps[i], prop_mode)) { prop_mode = PropModeAppend; } } _al_mutex_unlock(&system->lock); }
/* Internal function: _al_register_destructor * Register OBJECT to be destroyed by FUNC during Allegro shutdown. * This would be done in the object's constructor function. * * [thread-safe] */ void _al_register_destructor(_AL_DTOR_LIST *dtors, char const *name, void *object, void (*func)(void*)) { int *dtor_owner_count; ASSERT(object); ASSERT(func); dtor_owner_count = _al_tls_get_dtor_owner_count(); if (*dtor_owner_count > 0) return; _al_mutex_lock(&dtors->mutex); { #ifdef DEBUGMODE /* make sure the object is not registered twice */ { unsigned int i; for (i = 0; i < _al_vector_size(&dtors->dtors); i++) { DTOR *dtor = _al_vector_ref(&dtors->dtors, i); ASSERT(dtor->object != object); } } #endif /* DEBUGMODE */ /* add the destructor to the list */ { DTOR *new_dtor = _al_vector_alloc_back(&dtors->dtors); if (new_dtor) { new_dtor->object = object; new_dtor->func = func; new_dtor->name = name; ALLEGRO_DEBUG("added dtor for %s %p, func %p\n", name, object, func); } else { ALLEGRO_WARN("failed to add dtor for %s %p\n", name, object); } } } _al_mutex_unlock(&dtors->mutex); }
/* Hide the system mouse cursor. */ static bool xdpy_hide_mouse_cursor(ALLEGRO_DISPLAY *display) { ALLEGRO_DISPLAY_XGLX *glx = (void *)display; ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); Display *xdisplay = system->x11display; Window xwindow = glx->window; if (glx->cursor_hidden) return true; _al_mutex_lock(&system->lock); if (glx->invisible_cursor == None) { unsigned long gcmask; XGCValues gcvalues; Pixmap pixmap = XCreatePixmap(xdisplay, xwindow, 1, 1, 1); GC temp_gc; XColor color; gcmask = GCFunction | GCForeground | GCBackground; gcvalues.function = GXcopy; gcvalues.foreground = 0; gcvalues.background = 0; temp_gc = XCreateGC(xdisplay, pixmap, gcmask, &gcvalues); XDrawPoint(xdisplay, pixmap, temp_gc, 0, 0); XFreeGC(xdisplay, temp_gc); color.pixel = 0; color.red = color.green = color.blue = 0; color.flags = DoRed | DoGreen | DoBlue; glx->invisible_cursor = XCreatePixmapCursor(xdisplay, pixmap, pixmap, &color, &color, 0, 0); XFreePixmap(xdisplay, pixmap); } XDefineCursor(xdisplay, xwindow, glx->invisible_cursor); glx->cursor_hidden = true; _al_mutex_unlock(&system->lock); return true; }