Either I'm doing something wrong, or it's an LGS bug.
I want to check through a simple script where I press Mouse button 1 and get a message on the keyboard lcd screen
but LGS only responds to the Mouse button 4 and above.
function OnEvent(event, arg)
OutputLogMessage("event = %s, arg = %s\n", event, arg)
EnablePrimaryMouseButtonEvents(true)
if event == "MOUSE_BUTTON_PRESSED" and arg == 1 then
ClearLCD ()
OutputLCDMessage("Hello world1")
OutputLCDMessage("Hello world2")
end
end
Related
So I have this piece of code which works well
while(1) {
XNextEvent(dpy,&e);
paint(cs,g);
if(e.xbutton.button == 1) {
evolue(g,gc,cycleG);
paint(cs,g);
printf("test");
}else if(e.xbutton.button==3) break ;
}
here xbutton.button == 1 is the left click.
I want to change the code so that it does the function with a keyboard press by changing it to
while(1) {
XNextEvent(dpy,&e);
paint(cs,g);
if(e.xkey.keycode == 54) {
evolue(g,gc,cycleG);
paint(cs,g);
printf("test");
}else if(e.xbutton.button==3) break ;
}
I got the keycode 54 by running xev on the terminal
so anyways logically the second piece of code should work but it just doesn't run the code inside the if statement unlike when it took mouse input. So..what gives? And how to fix it taking keyboard input?
Edit:
for further testing I wrote this code
while(1) {
XNextEvent(dpy,&e);
if(e.type == KeyPress){
paint(cs,g);
evolue(g,gc,cycleG);
}
if(e.type == ButtonPress){
paint(cs,g);
evolue(g,gc,cycleG);
}
}
so that it executes the program no matter what mouse button is pressed and no matter what keyboard key is pressed, but again, only mouse buttons execute the program while keyboard keys dont.
The problem was in a function above that chooses the input type it was this
XSelectInput(dpy, win, ExposureMask|ButtonPressMask);
I changed it to this
XSelectInput(dpy, win, ExposureMask|ButtonPressMask|KeyPressMask);
and this fixed it.
So I recently spilled some water on my macbook pro keyboard, and my left command and option keys no longer function. Apple wants me to mail it in for repairs, which I don't have time for right now. So I thought I'd override the right command key to serve as left control seeing as the left command key still works.
I adapted the following from a keylogger gist I found:
#include <stdio.h>
#import <Carbon/Carbon.h>
#import <ApplicationServices/ApplicationServices.h>
CGEventRef loggerCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* context)
{
if (type == kCGEventFlagsChanged && CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == 54 /* right cmd key */) {
printf(
"TEST: %d %llu\n",
type,
CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode)
);
CGKeyCode virtualKey = 0x3B; // kVK_Control (left control);
CGEventRef override = CGEventCreateCopy(event);
CGEventSetIntegerValueField(override, kCGKeyboardEventKeycode, virtualKey);
return override;
}
return event;
}
int main(int argc, const char * argv[])
{
CFMachPortRef tap;
if ((tap = CGEventTapCreate(kCGHIDEventTap,
kCGHeadInsertEventTap,
0, kCGEventMaskForAllEvents,
loggerCallback, NULL)) == NULL) {
printf("Failed ot create event tap\n");
exit(1);
}
CFRunLoopSourceRef runLoopSource;
if ((runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0)) == NULL) {
printf("Failed to create run loop source\n");
exit(1);
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CGEventTapEnable(tap, true);
CFRunLoopRun();
return 0;
}
Now the event tap works correctly, and it does intercept keyboard events ( I can see TEST 12 54 printed to the console), but the key is still behaving as command and not control. According to the documentation for CGEventTapCallback, the callback may return:
A newly-constructed event. After the new event has been passed back to the event system, the new event will be released along with the original event.
Passing in kCGHeadInsertEventTap as the tap location should ensure my event tap is inserted at the head of the handler list. Am I doing something wrong here or is it just not possible to modify events like this?
#Willeke was correct in their comment. Although I was correctly overriding the event, what I really needed to do was use the keydown/keyup events to keep track of when the right command key is pressed. I could then use that flag to intercept other keypress events, remove the command modifier, and insert the control modifier flag use bitwise operators. However, the simple solution here to this problem comes from the documentation link they provided:
hidutil property --set '{"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc":0x7000000E7,"HIDKeyboardModifierMappingDst":0x7000000E0}]}'
I'm writing Conways game of life in C with SDL. The game logic and everything works fine but I want to have it when you press p for example that the game automatically updates until p is pressed again and the loop stops. Somehow it only repeats once and doesn't even register the second time p is pressed.
else if (e.key.keysym.sym == SDLK_p){
bool stop = false;
while (!stop){
nextEpoch();
updateGame(window, renderer, r);
msleep(500);
if (e.type == SDL_KEYDOWN){
if (e.key.keysym.sym == SDLK_p){
stop = true;
printf("s\n");
}
}
}
}
It doesn't register that p is pressed when it in the while-loop.
Here's the full code: https://gist.github.com/PhilippRados/2df8760cc55822c2eac62addafb24403
As already pointed out by someone else in the comments section, you are not updating e in the inner loop. If you want to update e with a new event, you must call SDL_PollEvent( &e ) again to fill it with a new event.
In your linked code, you seem to be attempting to implement a new state of your program outside the main event loop, which represents the running state of the program, whereas the main event loop represents the paused state of the program. That way, you effectively have two separate event loops, one for each state of the program. While it is possible to make your program work this way, I don't recommend it.
For example, the way you have designed your program, your program won't respond to SDL_QUIT events in the running state. It will only do so in the paused state.
Therefore, it would make more sense to have a single event loop for both the running and the paused states of your program.
I don't recommend that you call usleep or SDL_Delay for waiting until it is time to render the next frame, as your program will not be responding to user input during this time. Especially since you have a very low frame rate of 2 frames per second, this means that it will take up to half a second for your program to respond to user input (for example if the user resizes the window or attempts to close it). Instead, I recommend that you set up a timer using SDL_AddTimer. You can program the timer callback function to give you a SDL_USEREVENT event twice per second. That way, when you receive this event, you will know that it is time to update the game and render the next frame. While waiting for this event, your program will still be able to respond to other events.
Note that in order to use SDL timers, you must initialize the corresponding subsystem using the SDL_INIT_TIMER flag when calling SDL_Init. Strangely, your linked code does not seem to call SDL_Init at all, so I am surprised that your code works at all. According to the documentation, you should call SDL_Init like this:
SDL_Init( SDL_INIT_TIMER | SDL_INIT_VIDEO );
Also, calling SDL_PollEvent in a loop seems like a big waste of CPU resources, as your CPU usage will likely be 100% although you are effectively doing nothing most of the time. I recommend that you call SDL_WaitEvent instead, so that the thread will sleep until it receives a new event to respond to.
Another thing worth noting is that when handling an SDL_MOUSEBUTTONDOWN event, it does not seem appropriate to use the result of SDL_GetMouseState to determine the coordinates of the mouse click, as that function will return the current mouse coordinates and not the coordinates at the time of the click. Therefore, it would be more appropriate to read these coordinates from the SDL_MouseButtonEvent structure.
Here is an example of how you could rewrite your event loop to use SDL_WaitEvent instead of SDL_PollEvent and to support both a running and a paused state in the main event loop.
Uint32 my_callbackfunc( Uint32 interval, void *param )
{
SDL_Event e;
e.user.type = SDL_USEREVENT;
e.user.code = 0;
e.user.data1 = NULL;
e.user.data2 = NULL;
SDL_PushEvent( &e );
return interval;
}
int main (int argc, char** argv)
{
[...]
//set timer to trigger twice per second
SDL_TimerID timer = SDL_AddTimer( 500, my_callbackfunc, NULL );
if ( timer == 0 ) {
//TODO: handle error
return EXIT_FAILURE;
}
//start game in a paused state
bool paused = true;
while ( SDL_WaitEvent( &e ) ) {
switch ( e.type ) {
case SDL_QUIT:
goto quit_game;
case SDL_WINDOWEVENT:
//rerender in case of window state change
updateGame( window, renderer, r );
break;
case SDL_USEREVENT:
if ( !paused ) {
nextEpoch();
updateGame(window, renderer, r);
}
break;
case SDL_MOUSEBUTTONDOWN:
mouseX = getNearestMultiple( e.button.x ) / RECT_SIZE;
mouseY = getNearestMultiple( e.button.y) / RECT_SIZE;
if ( Field[mouseX][mouseY] ) {
//Deactivate cell
Field[mouseX][mouseY] = false;
updateGame(window,renderer,r);
}
else {
//activate cell at position x,y
Field[mouseX][mouseY] = true;
updateGame(window,renderer,r);
}
break;
case SDL_KEYDOWN:
switch ( e.key.keysym.sym ) {
case SDLK_SPACE:
if ( paused ) {
nextEpoch();
updateGame(window, renderer, r);
}
break;
case SDLK_r:
memset(Field,0,sizeof(Field[0][0]) * WIDTH * HEIGHT);
memset(nextState,0,sizeof(nextState[0][0]) * WIDTH * HEIGHT);
updateGame(window,renderer, r);
break;
case SDLK_p:
paused = !paused;
}
}
}
quit_game:
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
When I use the function system(), I cannot catch any mouse event.
I have already know system() function is a shell command, but why using this command will block catching mouse event?
#include <windows.h>
#include <stdio.h>
int main()
{
HANDLE ConsoleWin;
INPUT_RECORD eventMsg;
DWORD Pointer;
//system("mode con cols=140 lines=40"); //after using this function,I cannot catch any mouse event
while (1)
{
ConsoleWin = GetStdHandle(STD_INPUT_HANDLE);//Get the console window
ReadConsoleInput(ConsoleWin, &eventMsg, 1, &Pointer);//Read input msg
if (eventMsg.EventType == MOUSE_EVENT && eventMsg.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) {
printf("Left button clicked.");
}
else if (eventMsg.EventType == MOUSE_EVENT && eventMsg.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED) {
printf("Right button clicked.");
}
}
return 0;
}
system() executes a new cmd.exe which resets many console flags. After each "system" you should restore console options this way:
DWORD mode;
GetConsoleMode(ConsoleWin, &mode);
system("...your command...");
SetConsoleMode(ConsoleWin, mode);
By the way, your program may have the same problem even without executing any system(). It relies on default console settings, which in turn depend on system settings and user preferences. I suggest you to add this code at the beginning of your program:
DWORD mode;
GetConsoleMode(ConsoleWin, &mode);
mode |= ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS;
SetConsoleMode(ConsoleWin, mode);
I'm working on a project where I took a Super Nintendo controller, driving it with an Arduino. The Arduino reads the button presses on the controller, and sends it over a serial connection.
I'm working on a receiver program, which will read from the serial port, and then simulate key presses in Windows, so I can use the controller in other programs.
The thing is, I got pretty much everything down. Except there is one issue.
My simulated keypresses aren't actually being held down.
Here is the code for the A button (buttons are active low, so they are 'false' when being pressed)
if(!(buttonState.state_word & B_A))
{
/* If previous state is not pressed, and current is pressed, simulate a keypress */
if(prevState.state_word & B_A)
keybd_event(0x41, 0x41,KEYEVENTF_EXTENDEDKEY | 0,0);
}
else if(buttonState.state_word & B_A)
{
/* If previous state is pressed, and current is not pressed, simulate a key release */
if(!(prevState.state_word & B_A))
keybd_event(0x41, 0x41,KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,0);
}
When I press A on the SNES controller, an A will appear in notepad, for example.
And when I hold the A button on the SNES controller, a single A will appear in notepad, but the terminal will print that the key is being held, like I programmed it to do.
When the button is first pressed from being unpressed, it simulates the keypress. When it's held down, no more calls to simulate a keypress are made. And then when the SNES button is released, the keypress is also released.
Since there is this time between the keydown and the keyup, why is there only a single letter being printed, and not as if the keyboard was being held down and printing repeatedly?
Thanks to all who responded.
I ended up taking a different approach, using SendInput instead this time, and now it works like a charm.
As for the reason while I keep state, the way I saw it was if the button is being held down, I don't want to simulate another keypress each time the controller is polled. So I keep state, such that, if the button is pressed, and next time it is polled it is still being pressed, I won't generate another keypress. It will only be generated when the last state of the controller showed it wasn't pressed.
while(1)
{
prevState = buttonState;
ReadFile( hCOM,
&buttonState.state_word,
2,
&bytesRead,
NULL);
for(i = 0; i < 12; i++)
{
if(!(buttonState.state_word & (1 << i)))
{
/* If previous state is not pressed, and current is pressed, simulate a keypress */
if(prevState.state_word & (1 << i))
{
in[i].ki.dwFlags = KEYEVENTF_SCANCODE;
SendInput(1,&in[i],sizeof(INPUT));
}
}
else if(buttonState.state_word & (1 << i))
{
/* If previous state is pressed, and current is not pressed, simulate a key release */
if(!(prevState.state_word & (1 << i)))
{
in[i].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1,&in[i],sizeof(INPUT));
}
}
}
}