|
[Allegro5] Native dialog problems |
utz000
Member #16,715
July 2017
|
Hey folks, I'm having some trouble with the native dialogs add-on, namely the al_show_native_message_box function. Below is a minimal example that exhibits the problem: 1#include <iostream>
2#include <allegro5/allegro.h>
3#include <allegro5/allegro_native_dialog.h>
4
5int main(int argc, char **argv){
6
7 if (!al_init()) {
8 std::cout << "Allegro initialization failed.\n";
9 return -1;
10 }
11
12 ALLEGRO_DISPLAY *display;
13 ALLEGRO_TIMER *timer;
14 ALLEGRO_EVENT_QUEUE *queue;
15 ALLEGRO_KEYBOARD_STATE kbd;
16 ALLEGRO_EVENT event;
17
18 if (!al_init_native_dialog_addon()) {
19 std::cout << "Failed to initialize native dialogs.\n";
20 return -1;
21 }
22
23#ifdef ALLEGRO_GTK_TOPLEVEL
24 al_set_new_display_flags(ALLEGRO_GTK_TOPLEVEL);
25#endif
26
27 display = al_create_display(640, 480);
28 if (!display) {
29 std::cout << "Failed to initialize display.\n";
30 al_uninstall_system();
31 return -1;
32 }
33
34 if (!al_install_keyboard()) {
35 std::cout << "Failed to initialize keyboard.\n";
36 al_destroy_display(display);
37 al_uninstall_system();
38 return -1;
39 }
40
41 timer = al_create_timer(1.0f/25.0f);
42 if (!timer) {
43 std::cout << "Failed to initialize timer.\n";
44 al_destroy_display(display);
45 al_uninstall_system();
46 return -1;
47 }
48
49 queue = al_create_event_queue();
50 if(!queue) {
51 std::cout << "Failed to initialize timer.\n";
52 al_destroy_timer(timer);
53 al_destroy_display(display);
54 al_uninstall_system();
55 return -1;
56 }
57 al_register_event_source(queue, al_get_display_event_source(display));
58 al_register_event_source(queue, al_get_timer_event_source(timer));
59 al_start_timer(timer);
60
61 while (true) {
62
63 al_wait_for_event(queue, &event);
64
65 if (event.type == ALLEGRO_EVENT_TIMER) {
66
67 al_get_keyboard_state(&kbd);
68
69 if (al_key_down(&kbd, ALLEGRO_KEY_P)) {
70
71// al_pause_event_queue(queue, true); //nope, doesn't help
72
73 int answer = al_show_native_message_box(display, "Message Box", "", "It'sa me, the dia loco!",
74 nullptr, ALLEGRO_MESSAGEBOX_QUESTION|ALLEGRO_MESSAGEBOX_YES_NO);
75
76 std::cout << "answer: " << answer << "\n";
77
78// al_pause_event_queue(queue, false);
79// al_flush_event_queue(queue); //nope, doesn't help either
80// al_get_keyboard_state(&kbd); //also no use
81 }
82 }
83 else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) break;
84 }
85
86 al_destroy_event_queue(queue);
87 al_destroy_timer(timer);
88 al_destroy_display(display);
89 al_uninstall_system();
90 return 0;
91}
Steps to reproduce the problem: I'm on Debian, using GTK 3.22 and Allegro 5.2.2, and compiling with g++ and clang++, both of which show the same behaviour. So, the obvious question is: What am I doing wrong here? |
Eric Johnson
Member #14,841
January 2013
|
I was able to reproduce the issue in Ubuntu 16.04. One thing that stands out to me is that you're getting the keyboard states manually, rather than registering them via al_register_event_source(). After register keyboard events and checking for said events outside of the timer event, the issue is no longer present. Check it out: 1#include <iostream>
2#include <allegro5/allegro.h>
3#include <allegro5/allegro_native_dialog.h>
4
5int main(int argc, char **argv){
6
7 if (!al_init()) {
8 std::cout << "Allegro initialization failed.\n";
9 return -1;
10 }
11
12 ALLEGRO_DISPLAY *display;
13 ALLEGRO_TIMER *timer;
14 ALLEGRO_EVENT_QUEUE *queue;
15 //ALLEGRO_KEYBOARD_STATE kbd;
16 ALLEGRO_EVENT event;
17
18 if (!al_init_native_dialog_addon()) {
19 std::cout << "Failed to initialize native dialogs.\n";
20 return -1;
21 }
22
23#ifdef ALLEGRO_GTK_TOPLEVEL
24 al_set_new_display_flags(ALLEGRO_GTK_TOPLEVEL);
25#endif
26
27 display = al_create_display(640, 480);
28 if (!display) {
29 std::cout << "Failed to initialize display.\n";
30 al_uninstall_system();
31 return -1;
32 }
33
34 if (!al_install_keyboard()) {
35 std::cout << "Failed to initialize keyboard.\n";
36 al_destroy_display(display);
37 al_uninstall_system();
38 return -1;
39 }
40
41 timer = al_create_timer(1.0f/25.0f);
42 if (!timer) {
43 std::cout << "Failed to initialize timer.\n";
44 al_destroy_display(display);
45 al_uninstall_system();
46 return -1;
47 }
48
49 queue = al_create_event_queue();
50 if(!queue) {
51 std::cout << "Failed to initialize timer.\n";
52 al_destroy_timer(timer);
53 al_destroy_display(display);
54 al_uninstall_system();
55 return -1;
56 }
57 al_register_event_source(queue, al_get_display_event_source(display));
58 al_register_event_source(queue, al_get_timer_event_source(timer));
59 al_register_event_source(queue, al_get_keyboard_event_source());
60 al_start_timer(timer);
61
62 while (true) {
63
64 al_wait_for_event(queue, &event);
65
66 if (event.type == ALLEGRO_EVENT_KEY_DOWN) {
67
68 if (event.keyboard.keycode == ALLEGRO_KEY_P) {
69
70 int answer = al_show_native_message_box(display, "Message Box", "", "It'sa me, the dia loco!",
71 nullptr, ALLEGRO_MESSAGEBOX_QUESTION|ALLEGRO_MESSAGEBOX_YES_NO);
72
73 std::cout << "answer: " << answer << "\n";
74 }
75 }
76 else if (event.type == ALLEGRO_EVENT_TIMER) {
77
78 //
79 }
80 else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) break;
81 }
82
83 al_destroy_event_queue(queue);
84 al_destroy_timer(timer);
85 al_destroy_display(display);
86 al_uninstall_system();
87 return 0;
88}
|
utz000
Member #16,715
July 2017
|
Thanks for your input, Eric. Unfortunately I need precisely timed keyboard input in my project, and I haven't found a viable way of doing that with ALLEGRO_EVENT_KEY_DOWN/UP/CHAR yet. Is there maybe another work-around? That aside, do you think this is a bug? If so, I'll open an issue on github, and perhaps a mod could move this thread to the Development board. |
Eric Johnson
Member #14,841
January 2013
|
It seems to me that the keyboard state is stuck on a key being down upon showing the dialog. When I reproduce the issue with your original code and get to the point where the dialog repeats itself, if I return focus onto the window and press "P" again and then click one of the dialog buttons, the dialog closes properly. So it seems that the keyboard state is getting stuck. I don't know if it's the result of an internal bug or whether or implementation is screwy... Go ahead and open an issue on GitHub and wait to see what others have to say. Edit I found a workaround. Each time you check for a key being down, but before showing the dialog, uninstall and then reinstall the keyboard. Let me know if it works for you: 1#include <iostream>
2#include <allegro5/allegro.h>
3#include <allegro5/allegro_native_dialog.h>
4
5int main(int argc, char **argv){
6
7 if (!al_init()) {
8 std::cout << "Allegro initialization failed.\n";
9 return -1;
10 }
11
12 ALLEGRO_DISPLAY *display;
13 ALLEGRO_TIMER *timer;
14 ALLEGRO_EVENT_QUEUE *queue;
15 ALLEGRO_KEYBOARD_STATE kbd;
16 ALLEGRO_EVENT event;
17
18 if (!al_init_native_dialog_addon()) {
19 std::cout << "Failed to initialize native dialogs.\n";
20 return -1;
21 }
22
23#ifdef ALLEGRO_GTK_TOPLEVEL
24 al_set_new_display_flags(ALLEGRO_GTK_TOPLEVEL);
25#endif
26
27 display = al_create_display(640, 480);
28 if (!display) {
29 std::cout << "Failed to initialize display.\n";
30 al_uninstall_system();
31 return -1;
32 }
33
34 if (!al_install_keyboard()) {
35 std::cout << "Failed to initialize keyboard.\n";
36 al_destroy_display(display);
37 al_uninstall_system();
38 return -1;
39 }
40
41 timer = al_create_timer(1.0f/25.0f);
42 if (!timer) {
43 std::cout << "Failed to initialize timer.\n";
44 al_destroy_display(display);
45 al_uninstall_system();
46 return -1;
47 }
48
49 queue = al_create_event_queue();
50 if(!queue) {
51 std::cout << "Failed to initialize timer.\n";
52 al_destroy_timer(timer);
53 al_destroy_display(display);
54 al_uninstall_system();
55 return -1;
56 }
57 al_register_event_source(queue, al_get_display_event_source(display));
58 al_register_event_source(queue, al_get_timer_event_source(timer));
59 al_start_timer(timer);
60
61 while (true) {
62
63 al_wait_for_event(queue, &event);
64
65 if (event.type == ALLEGRO_EVENT_TIMER) {
66
67 al_get_keyboard_state(&kbd);
68
69 if (al_key_down(&kbd, ALLEGRO_KEY_P)) {
70
71 al_uninstall_keyboard();
72
73 al_install_keyboard();
74
75 int answer = al_show_native_message_box(display, "Message Box", "", "It'sa me, the dia loco!",
76 nullptr, ALLEGRO_MESSAGEBOX_QUESTION|ALLEGRO_MESSAGEBOX_YES_NO);
77
78 std::cout << "answer: " << answer << "\n";
79 }
80 }
81 else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) break;
82 }
83
84 al_destroy_event_queue(queue);
85 al_destroy_timer(timer);
86 al_destroy_display(display);
87 al_uninstall_system();
88 return 0;
89}
Another Edit The above can also be accomplished using al_clear_keyboard_state(), but it's currently a part of the unstable API. You have to define ALLEGRO_UNSTABLE before including the Allegro header files to use the unstable API. 1#define ALLEGRO_UNSTABLE
2
3#include <iostream>
4#include <allegro5/allegro.h>
5#include <allegro5/allegro_native_dialog.h>
6
7int main(int argc, char **argv){
8
9 if (!al_init()) {
10 std::cout << "Allegro initialization failed.\n";
11 return -1;
12 }
13
14 ALLEGRO_DISPLAY *display;
15 ALLEGRO_TIMER *timer;
16 ALLEGRO_EVENT_QUEUE *queue;
17 ALLEGRO_KEYBOARD_STATE kbd;
18 ALLEGRO_EVENT event;
19
20 if (!al_init_native_dialog_addon()) {
21 std::cout << "Failed to initialize native dialogs.\n";
22 return -1;
23 }
24
25#ifdef ALLEGRO_GTK_TOPLEVEL
26 al_set_new_display_flags(ALLEGRO_GTK_TOPLEVEL);
27#endif
28
29 display = al_create_display(640, 480);
30 if (!display) {
31 std::cout << "Failed to initialize display.\n";
32 al_uninstall_system();
33 return -1;
34 }
35
36 if (!al_install_keyboard()) {
37 std::cout << "Failed to initialize keyboard.\n";
38 al_destroy_display(display);
39 al_uninstall_system();
40 return -1;
41 }
42
43 timer = al_create_timer(1.0f/25.0f);
44 if (!timer) {
45 std::cout << "Failed to initialize timer.\n";
46 al_destroy_display(display);
47 al_uninstall_system();
48 return -1;
49 }
50
51 queue = al_create_event_queue();
52 if(!queue) {
53 std::cout << "Failed to initialize timer.\n";
54 al_destroy_timer(timer);
55 al_destroy_display(display);
56 al_uninstall_system();
57 return -1;
58 }
59 al_register_event_source(queue, al_get_display_event_source(display));
60 al_register_event_source(queue, al_get_timer_event_source(timer));
61 al_start_timer(timer);
62
63 while (true) {
64
65 al_wait_for_event(queue, &event);
66
67 if (event.type == ALLEGRO_EVENT_TIMER) {
68
69 al_get_keyboard_state(&kbd);
70
71 if (al_key_down(&kbd, ALLEGRO_KEY_P)) {
72
73 al_clear_keyboard_state(display);
74
75 int answer = al_show_native_message_box(display, "Message Box", "", "It'sa me, the dia loco!",
76 nullptr, ALLEGRO_MESSAGEBOX_QUESTION|ALLEGRO_MESSAGEBOX_YES_NO);
77
78 std::cout << "answer: " << answer << "\n";
79 }
80 }
81 else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) break;
82 }
83
84 al_destroy_event_queue(queue);
85 al_destroy_timer(timer);
86 al_destroy_display(display);
87 al_uninstall_system();
88 return 0;
89}
|
utz000
Member #16,715
July 2017
|
Yes! That does the trick. Thanks a lot! Was just reading up on al_clear_keyboard_state() as well, but it's only been added in 5.2.3. So I'll probably stick with the first version, since it might be a while before the new stuff finds its way into the various distros that have Allegro in their repos. |
Eric Johnson
Member #14,841
January 2013
|
I'm glad it works for you. Also, I wouldn't worry too much about newer versions of Allegro finding their way into various distributions, as it's not difficult to manually build Allegro from source. The gist of it is as follows: sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev cmake build-essential make libxcursor-dev cmake g++ freeglut3-dev libxcursor-dev libpng12-dev libjpeg-dev libfreetype6-dev libgtk2.0-dev libasound2-dev libpulse-dev libopenal-dev libflac-dev libdumb1-dev libvorbis-dev libphysfs-dev git clone https://github.com/liballeg/allegro5
|
|