static void xdpy_destroy_display_hook_default(ALLEGRO_DISPLAY *d, bool is_last) { ALLEGRO_SYSTEM_XGLX *s = (ALLEGRO_SYSTEM_XGLX *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d; (void)is_last; if (glx->context) { glXDestroyContext(s->gfxdisplay, glx->context); glx->context = NULL; ALLEGRO_DEBUG("destroy context.\n"); } if (glx->fbc) { al_free(glx->fbc); glx->fbc = NULL; XFree(glx->xvinfo); glx->xvinfo = NULL; } else if (glx->xvinfo) { al_free(glx->xvinfo); glx->xvinfo = NULL; } if ((glx->glxwindow) && (glx->glxwindow != glx->window)) { glXDestroyWindow(s->x11display, glx->glxwindow); glx->glxwindow = 0; ALLEGRO_DEBUG("destroy glx window\n"); } _al_cond_destroy(&glx->mapped); _al_cond_destroy(&glx->selectioned); ALLEGRO_DEBUG("destroy window.\n"); XDestroyWindow(s->x11display, glx->window); _al_xglx_unuse_adapter(s, glx->adapter); if (d->flags & ALLEGRO_FULLSCREEN) { restore_mode_if_last_fullscreen_display(s, glx); } }
void _al_xglx_display_configure(ALLEGRO_DISPLAY *d, int x, int y, int width, int height, bool setglxy) { ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d; ALLEGRO_EVENT_SOURCE *es = &glx->display.es; _al_event_source_lock(es); /* Generate a resize event if the size has changed non-programmtically. * We cannot asynchronously change the display size here yet, since the user * will only know about a changed size after receiving the resize event. * Here we merely add the event to the queue. */ if (!glx->programmatic_resize && (d->w != width || d->h != height)) { if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_RESIZE; event.display.timestamp = al_get_time(); event.display.x = x; event.display.y = y; event.display.width = width; event.display.height = height; _al_event_source_emit_event(es, &event); } } /* We receive two configure events when toggling the window frame. * We ignore the first one as it has bogus coordinates. * The only way to tell them apart seems to be the send_event field. * Unfortunately, we also end up ignoring the only event we receive in * response to a XMoveWindow request so we have to compensate for that. */ if (setglxy) { glx->x = x; glx->y = y; } ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX*)al_get_system_driver(); ALLEGRO_MONITOR_INFO mi; int center_x = (glx->x + (glx->x + width)) / 2; int center_y = (glx->y + (glx->y + height)) / 2; _al_xglx_get_monitor_info(system, glx->adapter, &mi); ALLEGRO_DEBUG("xconfigure event! %ix%i\n", x, y); /* check if we're no longer inside the stored adapter */ if ((center_x < mi.x1 && center_x > mi.x2) || (center_y < mi.y1 && center_y > mi.x2)) { int new_adapter = _al_xglx_get_adapter(system, glx, true); if (new_adapter != glx->adapter) { ALLEGRO_DEBUG("xdpy: adapter change!\n"); _al_xglx_unuse_adapter(system, glx->adapter); if (d->flags & ALLEGRO_FULLSCREEN) _al_xglx_restore_video_mode(system, glx->adapter); glx->adapter = new_adapter; _al_xglx_use_adapter(system, glx->adapter); } } _al_event_source_unlock(es); }
static void xdpy_destroy_display(ALLEGRO_DISPLAY *d) { ALLEGRO_SYSTEM_XGLX *s = (void *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *glx = (void *)d; ALLEGRO_OGL_EXTRAS *ogl = d->ogl_extras; ALLEGRO_DEBUG("destroy display.\n"); /* If we're the last display, convert all bitmpas to display independent * (memory) bitmaps. */ if (s->system.displays._size == 1) { while (d->bitmaps._size > 0) { ALLEGRO_BITMAP **bptr = _al_vector_ref_back(&d->bitmaps); ALLEGRO_BITMAP *b = *bptr; _al_convert_to_memory_bitmap(b); } } else { /* Pass all bitmaps to any other living display. (We assume all displays * are compatible.) */ size_t i; ALLEGRO_DISPLAY **living = NULL; ASSERT(s->system.displays._size > 1); for (i = 0; i < s->system.displays._size; i++) { living = _al_vector_ref(&s->system.displays, i); if (*living != d) break; } for (i = 0; i < d->bitmaps._size; i++) { ALLEGRO_BITMAP **add = _al_vector_alloc_back(&(*living)->bitmaps); ALLEGRO_BITMAP **ref = _al_vector_ref(&d->bitmaps, i); *add = *ref; (*add)->display = *living; } } _al_xglx_unuse_adapter(s, glx->adapter); _al_ogl_unmanage_extensions(d); ALLEGRO_DEBUG("unmanaged extensions.\n"); _al_mutex_lock(&s->lock); _al_vector_find_and_delete(&s->system.displays, &d); XDestroyWindow(s->x11display, glx->window); if (s->mouse_grab_display == d) { s->mouse_grab_display = NULL; } ALLEGRO_DEBUG("destroy window.\n"); if (d->flags & ALLEGRO_FULLSCREEN) { size_t i; ALLEGRO_DISPLAY **living = NULL; bool last_fullscreen = true; /* If any other fullscreen display is still active on the same adapter, * we must not touch the video mode. */ for (i = 0; i < s->system.displays._size; i++) { living = _al_vector_ref(&s->system.displays, i); ALLEGRO_DISPLAY_XGLX *living_glx = (void*)*living; if (*living == d) continue; /* check for fullscreen displays on the same adapter */ if (living_glx->adapter == glx->adapter && al_get_display_flags(*living) & ALLEGRO_FULLSCREEN) { last_fullscreen = false; } } if (last_fullscreen) { ALLEGRO_DEBUG("restore modes.\n"); _al_xglx_restore_video_mode(s, glx->adapter); } else { ALLEGRO_DEBUG("*not* restoring modes.\n"); } } if (ogl->backbuffer) { _al_ogl_destroy_backbuffer(ogl->backbuffer); ogl->backbuffer = NULL; ALLEGRO_DEBUG("destroy backbuffer.\n"); } if (glx->context) { glXDestroyContext(s->gfxdisplay, glx->context); glx->context = NULL; ALLEGRO_DEBUG("destroy context.\n"); } /* XXX quick pre-release hack */ /* In multi-window programs these result in a double-free bugs. */ #if 0 if (glx->fbc) { al_free(glx->fbc); glx->fbc = NULL; XFree(glx->xvinfo); glx->xvinfo = NULL; } else if (glx->xvinfo) { al_free(glx->xvinfo); glx->xvinfo = NULL; } #endif _al_cond_destroy(&glx->mapped); _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"); }
void _al_xglx_display_configure(ALLEGRO_DISPLAY *d, int x, int y, int width, int height, bool setglxy) { ALLEGRO_DISPLAY_XGLX *glx = (ALLEGRO_DISPLAY_XGLX *)d; ALLEGRO_EVENT_SOURCE *es = &glx->display.es; _al_event_source_lock(es); /* Generate a resize event if the size has changed non-programmatically. * We cannot asynchronously change the display size here yet, since the user * will only know about a changed size after receiving the resize event. * Here we merely add the event to the queue. */ if (!glx->programmatic_resize && (d->w != width || d->h != height)) { if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_RESIZE; event.display.timestamp = al_get_time(); event.display.x = x; event.display.y = y; event.display.width = width; event.display.height = height; _al_event_source_emit_event(es, &event); } } if (setglxy) { glx->x = x; glx->y = y; } ALLEGRO_SYSTEM_XGLX *system = (ALLEGRO_SYSTEM_XGLX*)al_get_system_driver(); ALLEGRO_MONITOR_INFO mi; int center_x = (glx->x + (glx->x + width)) / 2; int center_y = (glx->y + (glx->y + height)) / 2; _al_xglx_get_monitor_info(system, glx->adapter, &mi); ALLEGRO_DEBUG("xconfigure event! %ix%i\n", x, y); /* check if we're no longer inside the stored adapter */ if ((center_x < mi.x1 && center_x > mi.x2) || (center_y < mi.y1 && center_y > mi.x2)) { int new_adapter = _al_xglx_get_adapter(system, glx, true); if (new_adapter != glx->adapter) { ALLEGRO_DEBUG("xdpy: adapter change!\n"); _al_xglx_unuse_adapter(system, glx->adapter); if (d->flags & ALLEGRO_FULLSCREEN) _al_xglx_restore_video_mode(system, glx->adapter); glx->adapter = new_adapter; _al_xglx_use_adapter(system, glx->adapter); } } _al_xwin_check_maximized(d); _al_event_source_unlock(es); }