|
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: 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
|
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. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Mark Oates
Member #1,146
March 2001
|
This works for me on Mac and Windows. 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:
-- |
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
|
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. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
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
|
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"} 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
|
, I don't need credit. It's just a way of saying thank you anyway. No real rewards for getting credit. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|