Stored mouse and keyboard after dialog
Auradrummer

Hello Masters,

I'm with a problem that I'm not finding the answer anywhere.
I'm not a newbie in programming, so if have some good technical explanation I'll appreciate.

The question is simple, I made a hotkey to exit my application. If I cancel the exiting confirmation, the prompt is shown again, as the keys is "stored" in the buffer.

Another thing I've noticed, if I call the exit by clicking at the button (and cancel after), the mouse stays "clicking" even if I release the left button. I need to click anywhere to reset the button.

How can I treat this?

SiegeLord

Err... is this Allegro4 or Allegro5?

Edgar Reynaldo

You should post the code you are using for your hotkey detection. Use <code>code goes here...</code> tags in the forum.

It sounds like you are using the key array in Allegro 4 and you need a way to tell your application not to go into the prompt again, so toggle a flag off each time you activate a screen, and only turn the flag on when your key state goes from false to true (ie. once).

Auradrummer

Hi masters,

I forgot to post the version, is Allegro 5.

  if(closeButton->isPressed() || (al_key_down(key, ALLEGRO_KEY_Q) && al_key_down(key, ALLEGRO_KEY_LSHIFT)))
    {
        if(!saved)
        {
            if(al_show_native_message_box(disp, "Close?", "Warning", "Loose unsaved informations?", NULL, ALLEGRO_MESSAGEBOX_OK_CANCEL) == 1)
                return EXIT;
        }
        else
            return EXIT;
    }

As I said before, if I use the keyboard (Shift+Q) or click on the button (closeButton), the prompt is shown. But, the keys and the click remains on the buffer after the dialog is closed. If I use mouse, it remains clicked until I click anywhere again. If I use the keyboard, the message pops over and over again!

pkrcel

How do you poll the key and mouse state?
To me it seems it does not properly reset the polled states....so this might be called over and over with the same state (and that would be why you get the described behaviour).

Seems a problem along the lines Edgar suggested.

I might also add that A5 event system is MUCH better of handling this....or at least I find it more comfortable.

Gideon Weems

If you use events like ALLEGRO_EVENT_DISPLAY_CLOSE and ALLEGRO_EVENT_KEY_DOWN (or even ALLEGRO_EVENT_KEY_CHAR in this case), I suspect the problem will go away.

Edit: I have fallen out of favor with the markup gods.

Auradrummer

Thanks for the replies, but I'm still stuck here. The problem is:

if(ev.type == ALLEGRO_EVENT_TIMER)
    redraw = true;
if(redraw)// && al_is_event_queue_empty(event_queue))
{
    redraw = false;
    ed -> animate(&ev);
}

The problem is that I have to get the commands inside ev->animate(&ev). But the queue must be emptied to redraw, and if the queue is emptied, the event is gone!

I'm thinking in storing the events in a structure before the redraw and pass it to the function, but there are some simpler manner?

---EDIT---
I made that structure. I'll share de code, can be useful to others:

#SelectExpand
1class keyEvent 2{ 3private: 4 std::vector <int> keys; 5 6public: 7 void addKey(int key); 8 bool isKeyDown(int keyCode); 9}; 10 11void keyEvent::addKey(int key) 12{ 13 keys.push_back(key); 14}; 15 16bool keyEvent::isKeyDown(int keyCode) 17{ 18 int pos = -1; 19 for(int i = 0; i < keys.size(); i++) 20 { 21 if(keys[i] == keyCode) 22 pos = i; 23 } 24 25 if(pos != -1) 26 { 27 keys.erase(keys.begin() + pos); 28 return true; 29 } 30 else 31 return false; 32};

Using it is pretty easy.
Instance the class out of the main loop:

keyEvent * kE = new keyEvent();

Then, place the following line in the main loop:

if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
    kE->addKey(ev.keyboard.keycode);

So, you can pass a pointer to the class to anywhere and get the pressed key by invoking

    if(kE->isKeyDown(ALLEGRO_KEYCODE))
        <<action here>>

Is easy to integrate to any application... I like it ;D

Thanks masters!

Gideon Weems

Actually, there's an even easier way to do it. See the second code box.

Auradrummer

Hello guys,

I'm still with problems with that code. The problem, I identified, is that when we open a dialog box by clicking on a button, the MOUSE_UP event happens in that thread so the mouse state not release it. To allow dragging, I improved my interface class.
I'm sure that have another way, but I'll share my solution. This class supports mouse and keyboard.

#SelectExpand
1//PROTOTYPE 2class keyEvent 3{ 4private: 5 std::vector <int> keys; 6 std::vector <int> mouse; 7 8public: 9 void addKey(int key); 10 void addMouseButton(int mouseState); 11 void removeMouseButton(int mouseState); 12 void clearAll(); 13 bool isKeyDown(int keyCode); 14 bool isMouseButtonDown(int mCode); 15};

#SelectExpand
1//IMPLEMENTATION 2void keyEvent::addKey(int key) 3{ 4 keys.push_back(key); 5}; 6 7void keyEvent::addMouseButton(int mouseState) 8{ 9 mouse.push_back(mouseState); 10}; 11 12void keyEvent::removeMouseButton(int mouseState) 13{ 14 int pos = -1; 15 for(int i = 0; i < mouse.size(); i++) 16 { 17 if(mouse[i] & mouseState) 18 pos = i; 19 } 20 if(pos != -1) 21 mouse.erase(mouse.begin() + pos); 22}; 23 24void keyEvent::clearAll() 25{ 26 mouse.clear(); 27 keys.clear(); 28}; 29 30bool keyEvent::isMouseButtonDown(int mCode) 31{ 32 for(int i = 0; i < mouse.size(); i++) 33 { 34 if(mouse[i] & mCode) 35 return true; 36 } 37 return false; 38}; 39 40bool keyEvent::isKeyDown(int keyCode) 41{ 42 int pos = -1; 43 for(int i = 0; i < keys.size(); i++) 44 { 45 if(keys[i] == keyCode) 46 pos = i; 47 } 48 49 if(pos != -1) 50 { 51 keys.erase(keys.begin() + pos); 52 return true; 53 } 54 else 55 return false; 56};

//AT THE MAIN
    keyEvent * kE = new keyEvent();

    while(run)
    {
        if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
            kE->addKey(ev.keyboard.keycode);

        if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
            kE->addMouseButton(ev.mouse.button);

        if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
            kE->removeMouseButton(ev.mouse.button);
    }

//USAGE examples
if(kE->isKeyDown(ALLEGRO_KEY_ESCAPE)) //detecting keyboard
    printf("ESC press");

//DIALOG examples
int resp = 0;
resp = al_show_native_message_box(disp, "Warning", "Text", "Continue?", 0, ALLEGRO_MESSAGEBOX_YES_NO);
if(resp == 1)
   printf("Com caixa \n");
else
   printf("Sem caixa \n");
kE->clearAll();

Helped me a lot here. If you need to watch mouse or keyboard inside a class/ function, just pass a pointer and proceed normally.

Thanks for the great help masters.

Thread #615091. Printed from Allegro.cc