xlib - print event name - c

So I have a standard window created with xlib that handles events:
while (keep_running){
XNextEvent (display, &event);
printf("event\n");
}
Now it doesn't seem to be calling the expose event, so I'm not able to draw in the window. I can see by the print statement that there are some events being fired, and I'd like to know what events they are.
So basically my question is, how can I get the event name to print it?
I'm still learning C, so any help is appriciated!

so I don't totally agree with their design decision, but it was probably made 30 years ago, so now isn't the time for monday morning quarterbacking...
the type is a crazy union:
typedef union _XEvent {
int type; /* must not be changed */
XAnyEvent xany;
XKeyEvent xkey;
XButtonEvent xbutton;
XMotionEvent xmotion;
XCrossingEvent xcrossing;
XFocusChangeEvent xfocus;
XExposeEvent xexpose;
XGraphicsExposeEvent xgraphicsexpose;
XNoExposeEvent xnoexpose;
XVisibilityEvent xvisibility;
XCreateWindowEvent xcreatewindow;
XDestroyWindowEvent xdestroywindow;
XUnmapEvent xunmap;
XMapEvent xmap;
XMapRequestEvent xmaprequest;
XReparentEvent xreparent;
XConfigureEvent xconfigure;
XGravityEvent xgravity;
XResizeRequestEvent xresizerequest;
XConfigureRequestEvent xconfigurerequest;
XCirculateEvent xcirculate;
XCirculateRequestEvent xcirculaterequest;
XPropertyEvent xproperty;
XSelectionClearEvent xselectionclear;
XSelectionRequestEvent xselectionrequest;
XSelectionEvent xselection;
XColormapEvent xcolormap;
XClientMessageEvent xclient;
XMappingEvent xmapping;
XErrorEvent xerror;
XKeymapEvent xkeymap;
long pad[24];
} Event;
so you must first use the type to determine which event is being used:
if(event.type == KeyPress)
{
printf("keypress\n");
// now you know the type you can use the specific fields from `XKeyEvent xkey`...
}
or you could just log the type
printf("event type = (%d)\n",event.type);
the union works because each of the other possible elements also has type as the first element, so they all line up on the same address...

Related

macOS: Override Modifier Key with CGEventTap

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}]}'

Monitor flashing when running a Windows SendInput API

Well, I certainly should go to python since I did several functions of this type, keyboard event and mouse event, but decide to try to learn the windows api.
My goal is to know when button 1 of the mouse is pressed.
I created this file in a very beginner way, it returns in mouseData only 0.
The curious thing is that whenever I run it, it flashes my monitor at short intervals in blinks, but between 1 second with it off. Very strange that, execution is not viable.
Could someone help me understand and try to execute to see if it is only here.
Code:
int main()
{
DWORD mouseData = 0;
MOUSEINPUT tagMouse;
tagMouse.dx = 0;
tagMouse.dy = 0;
tagMouse.mouseData = mouseData;
tagMouse.dwFlags = MOUSEEVENTF_XDOWN;
tagMouse.dwExtraInfo = 0;
INPUT tagInput;
tagInput.type = INPUT_MOUSE;
tagInput.mi = tagMouse;
while (true) {
if (GetAsyncKeyState(VK_DELETE)) break;
SendInput(1, &tagInput, sizeof(INPUT));
printf("KEYWORD: %d\n", mouseData);
Sleep(500);
}
system("pause");
return 0;
}
I can reproduce your reported 'symptoms' - and the effect is really brutal!
Now, while I cannot offer a full explanation, I can offer a fix! You have an uninitialized field in your tagMouse structure (the time member, which is a time-stamp used by the system). Setting this to zero (which tells the system to generate its own time-stamp) fixes the problem. So, just add this line to your other initializer statements:
//...
tagMouse.dwExtraInfo = 0;
tagMouse.time = 0; // Adding this line fixes it!
//...
Note: I, too, would appreciate a fuller explanation; however, an uninitialized field, to me, smells like undefined behaviour! I have tried a variety of other values (i.e. not zero) for the time field but haven't yet found one that works.
The discussion here on devblogs may help. This quote seems relevant:
And who knows what sort of havoc that will create if a program checks
the timestamps and notices that they are either from the future or
have traveled back in time.

Send struct pointers to WndProc for multiple dialog instances

I'm stuck. I have a vector of structs, one of its members is HWND. I use these HWNDs to process messages, and the other members are for instance-specific parameters. I pass a pointer to each newly created struct instance to the WndProc using lpParam. Sounds about right.
Inside the Proc I'm trying to get the passed pointer and tie all the instance-specific variables to the struct pointed by it. It seems the standard way for that is this:
HexParams Hex;
if (uMsg == WM_NCCREATE) {
SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR) ((CREATESTRUCT *)lParam)->lpCreateParams);
return TRUE;
} else {
LONG_PTR lpUserData = GetWindowLongPtr(hDlg, GWLP_USERDATA);
Hex = *(HexParams *)lpUserData;
}
switch (uMsg) {
case WM_CREATE: {
// use "Hex.Member"
It happens so that I'm sizing the dialog in a certain way, and I'm handling WM_GETMINMAXINFO for that. And inside it, I already use a Hex struct member called Running.
case WM_GETMINMAXINFO: {
MINMAXINFO *pInfo = (MINMAXINFO *) lParam;
// Manual adjust to account for cell parameters
pInfo->ptMinTrackSize.y = Hex.CellHeight * 2 + ClientTopGap;
if (Hex.Running) {
pInfo->ptMinTrackSize.x = TextArea.left + ClientXGap;
pInfo->ptMaxTrackSize.x = TextArea.right + ClientXGap;
}
return 0;
break;
}
Which is then used in WM_CREATE too, to figure out how to size it and when.
I'm in a vicious circle: I can't get the proper struct pointer out of lpParam until WM_NCCREATE arrives, but it's not the first message to arrive! And in the one that in fact arrives first I already need the scruct. And in that first message it's not possible to get it!
You can safely ignore those early messages, returning DefWindowProc() values for those. Those aren't going to be the important ones; you'll get more messages later down the line. (Remember that GWLP_USERDATA is initially zero.)
See also this and this (note the date this was posted). (Yes, this annoyed me at first, but I'm not fond of a window hook-based solution, and in practice it works fine, and if Raymond Chen does it...)

Need for XEventsQueued(display, QueuedAfterReading) in XCB

I am migrating some code of CYBOI from Xlib to XCB.
CYBOI uses a couple of threads for different communication channels like:
serial_port, terminal, socket, x_window_system.
However, it uses these threads only for signal/event/data detection;
the actual receiving and sending is done in the main thread,
in order to avoid any multi-threading conflicts of address space.
For the x_window_system channel, I previously detected events in a thread:
int n = XEventsQueued(display, QueuedAfterReading);
Upon detection of an event, an "interrupt flag" was set.
Afterwards, the main thread was reading the actual event using:
XNextEvent(display, &event);
When no more events were available, the main thread stopped receiving events
and the x_window_system channel thread started listening with XEventsQueued again.
Now, I am migrating the code to X C Binding (XCB).
There is a blocking function "xcb_wait_for_event" which is fine for reading an event.
What I miss is some function "peeking ahead" if there are events pending,
WITHOUT actually returning/removing the event from the queue.
I was reading the web for a couple of hours now, but am not able to find such a function.
The "xcb_poll_for_event" does not help. Blocking is fine for me,
since my event detection runs in its own thread.
The "xcb_request_check" as third input function does not seem to be what I want.
Could somebody help me out?
Thanks,
Christian
Are you looking for xcb_poll_for_queued_event(xcb_connection_t *c) which returns the next event without reading from the connection?
First, thanks to Julien for his reply.
I have studied the XCB 1.9 sources and found out that the
"xcb_poll_for_queued_event" function is not what I need.
The functions "xcb_poll_for_event" and "xcb_poll_for_queued_event"
both call "poll_for_next_event".
The functions "poll_for_next_event" and "xcb_wait_for_event"
both call "get_event".
If "get_event" finds an event, it changes the internal
linked list to point to the next event. However, I would
prefer NOT to change the event queue AT ALL, independent
from whether or not events are available.
I therefore propose to add a function like the following to XCB:
void* NULL_POINTER = (void*) 0;
int xcb_test_for_event(xcb_connection_t* c) {
int r = 0;
if (c != NULL_POINTER) {
struct _xcb_in in = c->in;
struct event_list* l = in.events;
if (l != NULL_POINTER) {
xcb_generic_event_t* e = l->event;
if (e != NULL_POINTER) {
r = 1;
}
}
}
return r;
}
This would allow me to write an endless loop like:
while (!xcb_test_for_event(connection)) {
sleep(t);
}
This is comparable to the old Xlib function:
int n = XEventsQueued(d, QueuedAfterReading);
which just checked the number of events in the event queue.
The "XEventsQueued" function always returns immediately WITHOUT
input/output, if there are events already in the queue.
Thanks
Christian

Dynamically Sized Input Buffer for Console Game in C

Hey, I'm trying rewrite code in C++ to work in C. I'm basically just trying to find an equivalent for new and delete in C but it's not quite working, here is my code:
Here's the code in C++:
// Gets the number of events
ReadConsoleInput(rHnd, eventBuffer, numEvents, &numEventsRead);
// Sizes the eventbuffer based on the number of events
INPUT_RECORD *eventBuffer = new INPUT_RECORD[numEvents];
// Removes from memory:
delete[] eventBuffer;
Here's what I have so far in C:
// Event buffer
INPUT_RECORD *eventBuffer;
// Gets the number of events
ReadConsoleInput(rHnd, eventBuffer, numEvents, &numEventsRead);
// Sizes the event buffer based on the number of events.
eventBuffer = malloc(numOfEvents * sizeof(*eventBuffer));
// Removes from memory:
free(eventBuffer);
The code above almost works with one error:
Error: a value of type "void *" cannot be assigned to an entity of type "INPUT_RECORD *"
You just have to cast it --
eventBuffer = (INPUT_RECORD*) malloc(numOfEvents * sizeof(*eventBuffer));
Of course, someone is going to come along and say that the standard says you don't have to cast the result of "malloc". Obviously, in this case, the standard is irrelevant :)
Your C++ code doesn't work. You pass eventBuffer to ReadConsoleInput() but it's only later that you declare it:
// Gets the number of events
ReadConsoleInput(rHnd, eventBuffer, numEvents, &numEventsRead);
// Sizes the eventbuffer based on the number of events
INPUT_RECORD *eventBuffer = new INPUT_RECORD[numEvents];
If ReadConsoleInput() needs eventBuffer for something, you'll need to declare it before calling the function.
Anyway, the equivalent C code would be:
INPUT_RECORD* eventBuffer;
ReadConsoleInput(rHnd, eventBuffer, numEvents, &numEventsRead);
eventBuffer = (INPUT_RECORD*) malloc(numOfEvents * sizeof(INPUT_RECORD));

Resources