Android: Rotation issues and Soft keys
alehbeer

Two questions:

I am running now on a real Nexus7 rather than an emulator, and I am now seeing two issues I had not yet seen.

1) How do you work with the softkeys? Can I treat them as keys being pressed, with an event que? I ask because pressing back can lock up the device for a moment, after which I am asked if the program should be shutdown for not responding or not - and if no is pressed, the demo becomes a background behind all the icons.

2) What ever orientation the device starts in is fine, but after rotating the device the aspect becomes very warped. Rotating the device into the orientation it was when the program started makes everything right again.

What code or condition checks am I missing? I am running the allegro example. Any ideas?

Thomas Fjellstrom

All keys should come through as keyboard events. Some work should probably be done to make sure the keyboard event handling doesn't lock up the java thread.

That backgrounding issue has been brought up before. Not sure what is causing that, other than the device supporting multiple GL contexts, and the user thread continuing to run in the background drawing under the main ui.. At least thats my guess.

I'll have to do some testing on my Nexus 7.

alehbeer

I just updated from 4.0 4.1 to 4.1.1

The background bug persists, and can now be repeated via:
click back a bunch real fast. select wait. click home.

The rotation bug seems fixed.

Let me know if you can replicate either - if so I will add it to the bug tracker.

Thomas Fjellstrom

Ah, you were using 4.0? That isn't even possible. There was no Android port in 4.0 afaik.

But please try the latest 4.1 release, and Git if possible. Git especially, that's probably the most important.

AMCerasoli

Isn't he talking about Android? Android 4.1, Jelly Bean?

alehbeer

I meant android 4.1 to 4.1.1

Thomas Fjellstrom

OH. Heh. My bad. What version of Allegro are you trying?

alehbeer

Allegro 5.1.3

Thomas Fjellstrom

Would it be possible to try the version from the git repo? That may have some fixes for what you're seeing. (I can't remember for sure)

Trent Gamblin

You MUST handle ALLEGRO_EVENT_DISPLAY_HALT/RESUME_DRAWING and should handle ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/IN also. Take a look at the Allegro demo for Android to see what you need to do: http://www.nooskewl.com/content/open-source/.

EDIT:

I'll try to break it down as best I can remember (in the way I prefer to do it).

1) When you get a HALT_DRAWING, you should set up a condition variable and start a thread with al_run_detached_thread. The code in this thread is pretty simple:

#SelectExpand
1// Some "global" data, or in some way accessible to both threads 2ALLEGRO_COND *cond; 3ALLEGRO_MUTEX *mutex; 4// This is the event queue your display is registered to 5ALLEGRO_EVENT_QUEUE *queue; 6 7// Here's the thread function 8void *thread_proc(void *data) 9{ 10 (void)data; 11 12 while (true) { 13 ALLEGRO_EVENT e; 14 al_wait_for_event(queue, &e); 15 if (e.type == ALLEGRO_EVENT_RESUME_DRAWING) { 16 al_broadcast_cond(cond); 17 break; 18 } 19 } 20 21 return NULL; 22} 23 24// Got HALT_DRAWING here 25cond = al_create_cond(); 26mutex = al_create_mutex(); 27al_run_detached_thread(...); 28al_acknowledge_drawing_halt(...); 29al_wait_cond(cond, mutex); 30al_acknowledge_drawing_resume(...); 31al_destroy_cond(cond); 32al_destroy_mutex(mutex); 33// ... Back to your regularly scheduled programming

Thomas Fjellstrom

I'm wondering why that is required. Can't the main thread just not run things when it knows it can't draw?

Trent Gamblin

Yes, but then you mess up your main loop. Like I said, way I prefer to do it.

EDIT:

And it's impossible to wait on a condition in the main thread, because you have to wait on events, so you'll be spinning cycles needlessly.

Thomas Fjellstrom

Ah. I personally wouldn't find it would mess up the main loop. I'd probably just stop my timer and call it a day. That way no updates at all should happen till the resume drawing event, where you'd start the timer back up.

Trent Gamblin

You can't. Read my edit. Well you can but it's better my way.

Thomas Fjellstrom

I wouldn't wait on a condition. Just wait for the resume event to come back, and set things back up. Basically with the timer[s] stopped, no more events should be able to come back, other than the resume drawing event. so you wait on that, rather than a condition.

Trent Gamblin

Whatever. Won't argue with you. You're "The Android Guy" after all. ;D.

Thomas Fjellstrom

Whatever. Won't argue with you. You're "The Android Guy" after all. .

:P

I have to say you've done at least as much work, so you're like a partner in crime.

I could be missing something. Some quirk of android or allegro's interaction with it that needs something that fancy.

alehbeer

I am a little confused how you would add that code into this. I tried, but now I can't get graphics and it doesn't open immediately like it used to - which I believe is possibly caused by my new and not quite clear understanding of ALLEGRO_EVENTS. Here is the example main.c from the allegro5 git.

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_image.h> 3#include <allegro5/allegro_primitives.h> 4#include <allegro5/allegro_android.h> /* al_android_set_apk_file_interface */ 5 6ALLEGRO_DEBUG_CHANNEL("main") 7 8#define MAX_TOUCH 10 9 10struct touch { 11 bool down; 12 double x, y; 13} touch[MAX_TOUCH]; 14 15/* debugging */ 16#define print_standard_path(std) \ 17 do { \ 18 ALLEGRO_PATH *path = al_get_standard_path(std); \ 19 ALLEGRO_DEBUG(#std ": %s", al_path_cstr(path, '/')); \ 20 } while (0) 21 22static void print_standard_paths(void) 23{ 24 print_standard_path(ALLEGRO_RESOURCES_PATH); 25 print_standard_path(ALLEGRO_TEMP_PATH); 26 print_standard_path(ALLEGRO_USER_DATA_PATH); 27 print_standard_path(ALLEGRO_USER_HOME_PATH); 28 print_standard_path(ALLEGRO_USER_SETTINGS_PATH); 29 print_standard_path(ALLEGRO_USER_DOCUMENTS_PATH); 30 print_standard_path(ALLEGRO_EXENAME_PATH); 31} 32 33static void set_transform(ALLEGRO_DISPLAY *dpy) 34{ 35 ALLEGRO_TRANSFORM t; 36 int w = al_get_display_width(dpy); 37 int h = al_get_display_height(dpy); 38 39 // XXX we shouldn't need this in user code 40 // glViewport(0, 0, w, h); 41 42 al_identity_transform(&t); 43 al_ortho_transform(&t, 0, w, h, 0, -1, 1); 44 al_set_projection_transform(dpy, &t); 45} 46 47static void draw_touches(void) 48{ 49 int i; 50 51 for (i = 0; i < MAX_TOUCH; i++) { 52 if (touch[i].down) { 53 al_draw_filled_rectangle( 54 touch[i].x-40, touch[i].y-40, 55 touch[i].x+40, touch[i].y+40, 56 al_map_rgb(100+i*20, 40+i*20, 40+i*20)); 57 } 58 } 59} 60 61int main(int argc, char **argv) 62{ 63 ALLEGRO_DISPLAY *dpy; 64 ALLEGRO_EVENT_QUEUE *queue; 65 ALLEGRO_EVENT event; 66 ALLEGRO_TIMER *timer; 67 ALLEGRO_BITMAP *image; 68 69 (void) argc; 70 (void) argv; 71 72 ALLEGRO_DEBUG("init allegro!"); 73 if (!al_init()) { 74 return 1; 75 } 76 77 ALLEGRO_DEBUG("init primitives"); 78 al_init_primitives_addon(); 79 80 ALLEGRO_DEBUG("init image addon"); 81 al_init_image_addon(); 82 83 ALLEGRO_DEBUG("init touch input"); 84 al_install_touch_input(); 85 86 ALLEGRO_DEBUG("init keyboard"); 87 al_install_keyboard(); 88 89 ALLEGRO_DEBUG("creating display"); 90 dpy = al_create_display(800, 480); 91 if (!dpy) { 92 ALLEGRO_ERROR("failed to create display!"); 93 return 1; 94 } 95 96 print_standard_paths(); 97 98 /* This is loaded from assets in the apk. */ 99 al_android_set_apk_file_interface(); 100 image = al_load_bitmap("alexlogo.png"); 101 if (!image) { 102 ALLEGRO_DEBUG("failed to load alexlogo.png"); 103 return 1; 104 } 105 al_set_standard_file_interface(); 106 107 al_convert_mask_to_alpha(image, al_map_rgb(255,0,255)); 108 109 queue = al_create_event_queue(); 110 al_register_event_source(queue, al_get_display_event_source(dpy)); 111 al_register_event_source(queue, al_get_touch_input_event_source()); 112 al_register_event_source(queue, al_get_keyboard_event_source()); 113 114 timer = al_create_timer(1/60.0); 115 al_register_event_source(queue, al_get_timer_event_source(timer)); 116 al_start_timer(timer); 117 118 bool draw = true; 119 bool running = true; 120 bool paused = false; 121 int count = 0; 122 123 while (running) { 124 al_wait_for_event(queue, &event); 125 126 switch (event.type) { 127 case ALLEGRO_EVENT_TOUCH_BEGIN: 128 //ALLEGRO_DEBUG("touch %i begin", event.touch.id); 129 touch[event.touch.id].down = true; 130 touch[event.touch.id].x = event.touch.x; 131 touch[event.touch.id].y = event.touch.y; 132 break; 133 134 case ALLEGRO_EVENT_TOUCH_END: 135 //ALLEGRO_DEBUG("touch %i end", event.touch.id); 136 touch[event.touch.id].down = false; 137 touch[event.touch.id].x = 0.0; 138 touch[event.touch.id].y = 0.0; 139 break; 140 141 case ALLEGRO_EVENT_TOUCH_MOVE: 142 //ALLEGRO_DEBUG("touch %i move: %fx%f", event.touch.id, event.touch.x, event.touch.y); 143 touch[event.touch.id].x = event.touch.x; 144 touch[event.touch.id].y = event.touch.y; 145 break; 146 147 case ALLEGRO_EVENT_TOUCH_CANCEL: 148 //ALLEGRO_DEBUG("touch %i canceled", event.touch.id); 149 break; 150 151 case ALLEGRO_EVENT_KEY_UP: 152 if (event.keyboard.keycode == ALLEGRO_KEY_BACK) { 153 ALLEGRO_DEBUG("back key pressed, exit!"); 154 running = false; 155 } 156 else { 157 ALLEGRO_DEBUG("%i key pressed", event.keyboard.keycode); 158 } 159 break; 160 161 case ALLEGRO_EVENT_TIMER: 162 draw = true; 163 if (count == 60) { 164 ALLEGRO_DEBUG("tick"); 165 count = 0; 166 } 167 count++; 168 break; 169 170 case ALLEGRO_EVENT_DISPLAY_CLOSE: 171 ALLEGRO_DEBUG("display close"); 172 running = false; 173 break; 174 175 case ALLEGRO_EVENT_DISPLAY_HALT_DRAWING: 176 ALLEGRO_DEBUG("halt drawing"); 177 // Stop the timer so we don't run at all while our display isn't 178 // active. 179 al_stop_timer(timer); 180 //al_set_target_backbuffer(0); 181 ALLEGRO_DEBUG("after set target"); 182 paused = true; 183 draw = false; 184 al_acknowledge_drawing_halt(dpy); 185 break; 186 187 case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING: 188 ALLEGRO_DEBUG("resume drawing"); 189 190 al_acknowledge_drawing_resume(dpy, NULL); 191 ALLEGRO_DEBUG("done waiting for surface recreated"); 192 193 al_start_timer(timer); 194 //al_set_target_backbuffer(dpy); 195 //_al_android_setup_opengl_view(dpy); 196 paused = false; 197 break; 198 199 case ALLEGRO_EVENT_DISPLAY_RESIZE: 200 ALLEGRO_DEBUG("display resize"); 201 al_acknowledge_resize(dpy); 202 ALLEGRO_DEBUG("done resize"); 203 set_transform(dpy); 204 break; 205 206 case ALLEGRO_EVENT_DISPLAY_ORIENTATION: 207 set_transform(dpy); 208 break; 209 } 210 211 if (draw && al_event_queue_is_empty(queue)) { 212 draw = false; 213 al_clear_to_color(al_map_rgb(255, 255, 255)); 214 if (image) { 215 al_draw_bitmap(image, 216 al_get_display_width(dpy)/2 - al_get_bitmap_width(image)/2, 217 al_get_display_height(dpy)/2 - al_get_bitmap_height(image)/2, 218 0); 219 } 220 draw_touches(); 221 al_flip_display(); 222 } 223 } 224 225 ALLEGRO_DEBUG("done"); 226 return 0; 227} 228 229/* vim: set sts=3 sw=3 et: */

Thread #610921. Printed from Allegro.cc