Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Keyboard Modifiers flag on Windows?

Credits go to Mark Oates for helping out!
This thread is locked; no one can reply to it. rss feed Print
Keyboard Modifiers flag on Windows?
Aksel Huff
Member #16,201
February 2016

I have just managed to get an app I am working on to compile and run on Windows from Linux, and I've noticed my code for handling shift/ctrl/alt+key presses has broken.

It appears that the ev.keyboard.modifiers flag is always zero on Windows. Unless I am doing something wrong, which is always a possibility.

Line 69 is where I am testing the ev.keyboard.modifiers flag.

This is my input logic:

#SelectExpand
1#include "input.hpp" 2 3#include <iostream> // For std::cerr 4 5InputHandler::InputHandler() : mods(0) 6{ 7 if (!al_is_system_installed()) 8 { 9 std::cerr << "input - Allegro has not been installed!" << std::endl; 10 abort(); 11 } 12 13 al_install_keyboard(); 14 al_install_mouse(); 15 16 memset(keys_pressed, false, sizeof(bool) * CUSTOM_ALLEGRO_KEY_MAX); 17 memset(keys_held, false, sizeof(bool) * CUSTOM_ALLEGRO_KEY_MAX); 18 memset(keys_released, false, sizeof(bool) * CUSTOM_ALLEGRO_KEY_MAX); 19} 20 21InputHandler::~InputHandler() 22{ 23 al_uninstall_keyboard(); 24 al_uninstall_mouse(); 25} 26 27void InputHandler::getInput(const ALLEGRO_EVENT &ev) 28{ 29 memset(keys_pressed, false, sizeof(bool) * CUSTOM_ALLEGRO_KEY_MAX); 30 memset(keys_released, false, sizeof(bool) * CUSTOM_ALLEGRO_KEY_MAX); 31 32 mouse_wheel_down = false; 33 mouse_wheel_up = false; 34 35 switch (ev.type) 36 { 37 case ALLEGRO_EVENT_MOUSE_AXES: 38 if (ev.mouse.dz > 0) 39 { 40 callKeybind(MOUSE::WHEELUP, true); 41 mouse_wheel_up = true; 42 } 43 else if (ev.mouse.dz < 0) 44 { 45 callKeybind(MOUSE::WHEELDOWN, true); 46 mouse_wheel_down = true; 47 } 48 49 mouse_position = { ev.mouse.x, ev.mouse.y }; 50 break; 51 52 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: 53 callKeybind(ALLEGRO_KEY_MAX + ev.mouse.button, true); 54 keys_pressed[ALLEGRO_KEY_MAX + ev.mouse.button] = true; 55 keys_held[ALLEGRO_KEY_MAX + ev.mouse.button] = true; 56 break; 57 58 case ALLEGRO_EVENT_MOUSE_BUTTON_UP: 59 callKeybind(ALLEGRO_KEY_MAX + ev.mouse.button, false); 60 keys_released[ALLEGRO_KEY_MAX + ev.mouse.button] = true; 61 keys_held[ALLEGRO_KEY_MAX + ev.mouse.button] = false; 62 break; 63 64 case ALLEGRO_EVENT_KEY_DOWN: 65 mods = ev.keyboard.modifiers; 66 callKeybind(ev.keyboard.keycode, true); 67 keys_pressed[ev.keyboard.keycode] = true; 68 keys_held[ev.keyboard.keycode] = true; 69 std::cout << "Shift Pressed: " << (ev.keyboard.modifiers & ALLEGRO_KEYMOD_SHIFT ? "true" : "false") << "\n" 70 << "\tKeymods Bitfield " << std::hex << ev.keyboard.modifiers << "\n"; 71 break; 72 73 case ALLEGRO_EVENT_KEY_UP: 74 mods = ev.keyboard.modifiers; 75 callKeybind(ev.keyboard.keycode, false); 76 keys_released[ev.keyboard.keycode] = true; 77 keys_held[ev.keyboard.keycode] = false; 78 break; 79 80 default: 81 break; 82 }; 83} 84 85bool InputHandler::isKeyPressed(const int key, const int mod) const 86{ 87 return keys_pressed[key] && (mod == -1 || mod & mods); 88} 89bool InputHandler::isKeyReleased(const int key, const int mod) const 90{ 91 return keys_released[key] && (mod == -1 || mod & mods); 92} 93bool InputHandler::isKeyDown(const int key, const int mod) const 94{ 95 return keys_held[key] && (mod == -1 || mod & mods); 96} 97 98bool InputHandler::isMousePressed(int button, const int mod) const 99{ 100 return isKeyPressed(button, mod); 101} 102bool InputHandler::isMouseReleased(int button, const int mod) const 103{ 104 return isKeyReleased(button, mod); 105} 106bool InputHandler::isMouseDown(int button, const int mod) const 107{ 108 return isKeyDown(button, mod); 109} 110 111bool InputHandler::isMouseWheelDown(const int mod) const 112{ 113 return mouse_wheel_down && (mod == -1 || mod & mods); 114} 115bool InputHandler::isMouseWheelUp(const int mod) const 116{ 117 return mouse_wheel_up && (mod == -1 || mod & mods); 118} 119 120vec2i InputHandler::getMousePos(void) const 121{ 122 return mouse_position; 123} 124 125bool InputHandler::isModifierDown(const int mod) 126{ 127 return mod & mods; 128} 129 130void InputHandler::setKeybind(int key, std::function<void(void)> callback, bool pressed) 131{ 132 if (pressed) keybinds_p[key] = callback; 133 else keybinds_r[key] = callback; 134} 135 136void InputHandler::clearKeybind(int key) 137{ 138 //TODO Untested 139 auto it = keybinds_p.find(key); 140 if (it != keybinds_p.end()) 141 { 142 keybinds_p.erase(it); 143 return; 144 } 145 146 it = keybinds_r.find(key); 147 148 if (it != keybinds_r.end()) keybinds_r.erase(it); 149} 150 151void InputHandler::callKeybind(int key, bool pressed) 152{ 153 if (pressed && keybinds_p.find(key) != keybinds_p.end()) 154 { 155 keybinds_p[key](); 156 return; 157 } 158 159 if (keybinds_r.find(key) != keybinds_r.end()) keybinds_r[key](); 160}

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

The modifier field is only valid for KEY_CHAR events. It hasn't been added to key press and releases yet. I think I remember seeing something on the mailing list about adding them but I can't remember right.

You already know the state of the SHIFT, CTRL, and ALT keys anyway.

Mark Oates
Member #1,146
March 2001
avatar

This works for me on Mac and Windows.

#SelectExpand
1#include <iostream> 2#include <sstream> 3#include <allegro5/allegro.h> 4 5std::string build_readable_keypress_string(int keycode, bool shift, bool alt, bool ctrl, bool command); 6 7int main(int argc, char **argv) 8{ 9 al_init(); 10 al_install_keyboard(); 11 12 ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue(); 13 al_register_event_source(event_queue, al_get_keyboard_event_source()); 14 15 ALLEGRO_DISPLAY *display = al_create_display(1280, 720); 16 17 ALLEGRO_EVENT event; 18 bool shutdown_program = false; 19 while (!shutdown_program) 20 { 21 al_wait_for_event(event_queue, &event); 22 switch(event.type) 23 { 24 case ALLEGRO_EVENT_KEY_DOWN: 25 { 26 int allegro_keycode = event.keyboard.keycode; 27 bool shift = event.keyboard.modifiers & ALLEGRO_KEYMOD_SHIFT; 28 bool alt = event.keyboard.modifiers & ALLEGRO_KEYMOD_ALT; 29 bool ctrl = event.keyboard.modifiers & ALLEGRO_KEYMOD_CTRL; 30 bool command = event.keyboard.modifiers & ALLEGRO_KEYMOD_COMMAND; 31 32 std::cout << build_readable_keypress_string(allegro_keycode, shift, alt, ctrl, command); 33 std::cout << std::flush; 34 } 35 break; 36 case ALLEGRO_EVENT_KEY_CHAR: 37 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) shutdown_program = true; 38 break; 39 } 40 } 41 42 al_destroy_display(display); 43 al_destroy_event_queue(event_queue); 44 al_uninstall_keyboard(); 45 al_uninstall_system(); 46 47 return 0; 48} 49 50std::string build_readable_keypress_string(int keycode, bool shift, bool alt, bool ctrl, bool command) 51{ 52 std::stringstream ss; 53 ss << "shift: " << shift 54 << ", alt: " << alt 55 << ", ctrl: " << ctrl 56 << ", command: " << command 57 << ", key: " << al_keycode_to_name(keycode) 58 << std::endl; 59 return ss.str(); 60}

Just skimming over your code I don't immediately see anything, but here are some thoughts:

  • Could you be re-initializing the keyboard a second time causing an issue?

  • I recall reading there is some connection between the display and keyboard. Do you have a display created?

Aksel Huff
Member #16,201
February 2016

The ev.keyboard.modifiers flag seems to be updated in the ALLEGRO_EVENT_KEY_DOWN event on Linux, at least. Looking through the Allegro source (and I'm definitely not experienced enough to know for sure) it looks like the modifiers variable is being updated in the key press function. https://github.com/liballeg/allegro5/blob/f41f49d65c89fdb214b4dd49172b5adfbf16c4ec/src/win/wkeyboard.c#L358

Thanks for the help all, I'll let you know how it goes.

UDPATE:

I have just compiled and ran the above code sample, and it does not work on my system. A snippet of the output:

shift: 0, alt: 0, ctrl: 0, command: 0, key: S
shift: 0, alt: 0, ctrl: 0, command: 0, key: D
shift: 0, alt: 0, ctrl: 0, command: 0, key: C
shift: 0, alt: 0, ctrl: 0, command: 0, key: LSHIFT
shift: 0, alt: 0, ctrl: 0, command: 0, key: C

The modifiers never change.

I may just do this manually and keep track of which modifier keys are held down myself.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Like I said, I think this was recently added. That may be why it works for Mark Oates and not for you.

The changes may be in the latest Git. If you want, you can try compiling allegro and see if the changes are there.

Aksel Huff
Member #16,201
February 2016

Just looked at the changes from 5.2.6 to 7 and yes you are absolutely correct:

https://liballeg.org/changes-5.2.html

I believe the Allegro5 libraries I got through pacman in msys were 5.2.6 so that makes sense for why it isn't working on Windows.

Thanks

Mark Oates
Member #1,146
March 2001
avatar

Sweet.

I like the way you indent your case blocks by the way:

{"name":"613137","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/1\/9122597f3a589c446742c0ea32d0eca2.png","w":1214,"h":679,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/1\/9122597f3a589c446742c0ea32d0eca2"}613137

I've never seen it like that, it's very easy to read. I might actually adopt it. :)

Aksel Huff
Member #16,201
February 2016

Thanks Mark, I appreciate that.

Is there anyway to modify who I've given credit to for helping out? I mistakenly only gave credit to you Mark, and not Edgar, if it even means anything to you guys, hah.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Go to: