diff --git a/allegro5.cfg b/allegro5.cfg index beec7f8939..f87bd92f1a 100644 --- a/allegro5.cfg +++ b/allegro5.cfg @@ -231,6 +231,15 @@ max_page_size = 0 # Uncomment if you want only the characters in the cache_text entry to ever be drawn # skip_cache_misses = true +[osx] + +# If set to false, then Allegro will send ALLEGRO_EVENT_DISPLAY_HALT_DRAWING +# and ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING events when the user resizes a +# window. Drawing while resizing ("live resizing") has historically been buggy, +# so setting this to false allows you to opt out of this behavior and detect +# when the resize happens. +allow_live_resize = true + [compatibility] # Prior to 5.2.4 on Windows you had to manually resize the display when diff --git a/demos/skater/src/framework.c b/demos/skater/src/framework.c index 43b4f5a75a..1a01c8c65b 100644 --- a/demos/skater/src/framework.c +++ b/demos/skater/src/framework.c @@ -336,6 +336,7 @@ void run_framework(void) case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING: background_mode = false; + al_acknowledge_drawing_resume(screen); break; case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT: diff --git a/examples/ex_camera.c b/examples/ex_camera.c index 2aaf262844..cd28df4b0d 100644 --- a/examples/ex_camera.c +++ b/examples/ex_camera.c @@ -474,6 +474,7 @@ int main(int argc, char **argv) ALLEGRO_TIMER *timer; ALLEGRO_EVENT_QUEUE *queue; int redraw = 0; + bool halt_drawing = false; char const *skybox_name = NULL; if (argc > 1) { @@ -489,6 +490,7 @@ int main(int argc, char **argv) al_install_keyboard(); al_install_mouse(); + al_set_config_value(al_get_system_config(), "osx", "allow_live_resize", "false"); al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST); al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST); @@ -566,12 +568,20 @@ int main(int argc, char **argv) else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { ex.button[event.mouse.button] = 0; } + else if (event.type == ALLEGRO_EVENT_DISPLAY_HALT_DRAWING) { + halt_drawing = true; + al_acknowledge_drawing_halt(display); + } + else if (event.type == ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING) { + halt_drawing = false; + al_acknowledge_drawing_resume(display); + } else if (event.type == ALLEGRO_EVENT_MOUSE_AXES) { ex.mouse_dx += event.mouse.dx; ex.mouse_dy += event.mouse.dy; } - if (redraw && al_is_event_queue_empty(queue)) { + if (!halt_drawing && redraw && al_is_event_queue_empty(queue)) { draw_scene(); al_flip_display(); diff --git a/examples/ex_resize2.c b/examples/ex_resize2.c index 7257d195ab..f5ec01d465 100644 --- a/examples/ex_resize2.c +++ b/examples/ex_resize2.c @@ -20,6 +20,7 @@ int main(int argc, char **argv) ALLEGRO_EVENT event; ALLEGRO_FONT *font; bool redraw; + bool halt_drawing; (void)argc; (void)argv; @@ -31,6 +32,7 @@ int main(int argc, char **argv) al_init_image_addon(); al_init_font_addon(); + al_set_config_value(al_get_system_config(), "osx", "allow_live_resize", "false"); al_set_new_display_flags(ALLEGRO_RESIZABLE | ALLEGRO_GENERATE_EXPOSE_EVENTS); display = al_create_display(640, 480); @@ -51,8 +53,9 @@ int main(int argc, char **argv) al_register_event_source(queue, al_get_keyboard_event_source()); redraw = true; + halt_drawing = false; while (true) { - if (redraw && al_is_event_queue_empty(queue)) { + if (!halt_drawing && redraw && al_is_event_queue_empty(queue)) { al_clear_to_color(al_map_rgb(255, 0, 0)); al_draw_scaled_bitmap(bmp, 0, 0, al_get_bitmap_width(bmp), al_get_bitmap_height(bmp), @@ -81,6 +84,14 @@ int main(int argc, char **argv) if (event.type == ALLEGRO_EVENT_DISPLAY_EXPOSE) { redraw = true; } + if (event.type == ALLEGRO_EVENT_DISPLAY_HALT_DRAWING) { + halt_drawing = true; + al_acknowledge_drawing_halt(display); + } + if (event.type == ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING) { + halt_drawing = false; + al_acknowledge_drawing_resume(display); + } if (event.type == ALLEGRO_EVENT_KEY_DOWN && event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { break; diff --git a/src/macosx/osxgl.h b/src/macosx/osxgl.h index 19883641fa..c460df701f 100644 --- a/src/macosx/osxgl.h +++ b/src/macosx/osxgl.h @@ -35,6 +35,10 @@ typedef struct ALLEGRO_DISPLAY_OSX_WIN { BOOL in_fullscreen; BOOL single_buffer; CGDisplayModeRef original_mode; + BOOL send_halt_events; + ALLEGRO_MUTEX *halt_mutex; + ALLEGRO_COND *halt_cond; + BOOL halt_event_acknowledged; /* For new (10.14+) vsyncing. */ CVDisplayLinkRef display_link; ALLEGRO_MUTEX *flip_mutex; diff --git a/src/macosx/osxgl.m b/src/macosx/osxgl.m index 2663dca81e..3938aa84ab 100644 --- a/src/macosx/osxgl.m +++ b/src/macosx/osxgl.m @@ -235,6 +235,7 @@ -(void) viewDidMoveToWindow; -(void) viewWillMoveToWindow: (NSWindow*) newWindow; -(void) mouseEntered: (NSEvent*) evt; -(void) mouseExited: (NSEvent*) evt; +-(void) viewWillStartLiveResize; -(void) viewDidEndLiveResize; /* Window delegate methods */ -(void) windowDidBecomeMain:(NSNotification*) notification; @@ -519,6 +520,33 @@ -(void) viewDidChangeBackingProperties } #endif +-(void) viewWillStartLiveResize +{ + ALLEGRO_DISPLAY_OSX_WIN* dpy = (ALLEGRO_DISPLAY_OSX_WIN*) dpy_ptr; + ALLEGRO_EVENT_SOURCE *es = &dpy->parent.es; + + if (dpy->send_halt_events) { + al_lock_mutex(dpy->halt_mutex); + dpy->halt_event_acknowledged = false; + al_unlock_mutex(dpy->halt_mutex); + + _al_event_source_lock(es); + if (_al_event_source_needs_to_generate_event(es)) { + ALLEGRO_EVENT event; + event.display.type = ALLEGRO_EVENT_DISPLAY_HALT_DRAWING; + event.display.timestamp = al_get_time(); + _al_event_source_emit_event(es, &event); + } + _al_event_source_unlock(es); + + al_lock_mutex(dpy->halt_mutex); + while (!dpy->halt_event_acknowledged) { + al_wait_cond(dpy->halt_cond, dpy->halt_mutex); + } + al_unlock_mutex(dpy->halt_mutex); + } +} + -(void) viewDidEndLiveResize { [super viewDidEndLiveResize]; @@ -541,6 +569,11 @@ -(void) viewDidEndLiveResize event.display.height = NSHeight(content); _al_event_source_emit_event(es, &event); ALLEGRO_INFO("Window finished resizing %d x %d\n", event.display.width, event.display.height); + + if (dpy->send_halt_events) { + event.display.type = ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING; + _al_event_source_emit_event(es, &event); + } } _al_event_source_unlock(es); dpy->old_w = NSWidth(content); @@ -1104,6 +1137,19 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) CVDisplayLinkStart(dpy->display_link); } +static void init_halt_events(ALLEGRO_DISPLAY_OSX_WIN *dpy) +{ + const char* value = al_get_config_value(al_get_system_config(), "osx", "allow_live_resize"); + if (value && strcmp(value, "false") == 0) { + dpy->send_halt_events = true; + } + else { + dpy->send_halt_events = false; + } + dpy->halt_mutex = al_create_mutex(); + dpy->halt_cond = al_create_cond(); +} + /* create_display_fs: * Create a fullscreen display - capture the display */ @@ -1141,6 +1187,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) _al_event_source_init(&display->es); dpy->cursor = [[NSCursor arrowCursor] retain]; dpy->display_id = CGMainDisplayID(); + init_halt_events(dpy); /* Get display ID for the requested display */ if (al_get_new_display_adapter() > 0) { @@ -1338,6 +1385,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) _al_event_source_init(&dpy->parent.es); osx_change_cursor(dpy, [NSCursor arrowCursor]); dpy->show_cursor = YES; + init_halt_events(dpy); // Set up a pixel format to describe the mode we want. osx_set_opengl_pixelformat_attributes(dpy); @@ -1519,6 +1567,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) _al_event_source_init(&display->es); _al_osx_change_cursor(dpy, [NSCursor arrowCursor]); dpy->show_cursor = YES; + init_halt_events(dpy); // Set up a pixel format to describe the mode we want. osx_set_opengl_pixelformat_attributes(dpy); @@ -1807,6 +1856,8 @@ static void destroy_display(ALLEGRO_DISPLAY* d) _al_set_current_display_only(NULL); } + al_destroy_cond(dpy->halt_cond); + al_destroy_mutex(dpy->halt_mutex); if (dpy->flip_mutex) { al_destroy_mutex(dpy->flip_mutex); al_destroy_cond(dpy->flip_cond); @@ -2497,6 +2548,15 @@ static bool set_display_flag(ALLEGRO_DISPLAY *display, int flag, bool onoff) #endif } +static void acknowledge_drawing_halt(ALLEGRO_DISPLAY *display) +{ + ALLEGRO_DISPLAY_OSX_WIN *dpy = (ALLEGRO_DISPLAY_OSX_WIN *)display; + al_lock_mutex(dpy->halt_mutex); + dpy->halt_event_acknowledged = true; + al_signal_cond(dpy->halt_cond); + al_unlock_mutex(dpy->halt_mutex); +} + ALLEGRO_DISPLAY_INTERFACE* _al_osx_get_display_driver_win(void) { static ALLEGRO_DISPLAY_INTERFACE* vt = NULL; @@ -2527,6 +2587,7 @@ static bool set_display_flag(ALLEGRO_DISPLAY *display, int flag, bool onoff) vt->set_display_flag = set_display_flag; vt->set_icons = set_icons; vt->update_render_state = _al_ogl_update_render_state; + vt->acknowledge_drawing_halt = acknowledge_drawing_halt; _al_ogl_add_drawing_functions(vt); _al_osx_add_clipboard_functions(vt); }