CFRunLoopSourceSignal doesn't work - macos

I'm debugging Qt5.3.1 on Mac, because my program freezes sometimes (intermittent ). I discovered that it is because the QTimer can't work properly.
In Qt code, they use the following two lines to trigger function activateTimersSourceCallback
CFRunLoopSourceSignal(d->activateTimersSourceRef);
CFRunLoopWakeUp(mainRunLoop());
void QCocoaEventDispatcherPrivate::activateTimersSourceCallback(void *info)
{
static int counter = 0;
NSLog(#"finished activeteTimersSourceCallback %d", counter++);
}
but sometimes, these two lines doesn't work, activateTimersSourceCallback won't get called.
I googled, but I couldn't find any solution? is this a known OS bug?
the initialization details:
// keep our sources running when modal loops are running
CFRunLoopAddCommonMode(mainRunLoop(), (CFStringRef) NSModalPanelRunLoopMode);
CFRunLoopSourceContext context;
bzero(&context, sizeof(CFRunLoopSourceContext));
context.info = d;
context.equal = runLoopSourceEqualCallback;
// source used to activate timers
context.perform = QCocoaEventDispatcherPrivate::activateTimersSourceCallback;
d->activateTimersSourceRef = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
Q_ASSERT(d->activateTimersSourceRef);
CFRunLoopAddSource(mainRunLoop(), d->activateTimersSourceRef, kCFRunLoopCommonModes);

Such behavior very likely can occur when UI event loop is overloaded with events or some business logic takes too long time. You should to check your business logic and move it to separate thread or run asynchronous.

Related

XTestFakeKeyEvent calls get swallowed

I'm trying to spoof keystrokes; to be a bit more precise: I'm replaying a number of keystrokes which should all get sent at a certain time - sometimes several at the same time (or at least as close together as reasonably possible).
Implementing this using XTestFakeKeyEvent, I've come across a problem. While what I've written so far mostly works as it is intended and sends the events at the correct time, sometimes a number of them will fail. XTestFakeKeyEvent never returns zero (which would indicate failure), but these events never seem to reach the application I'm trying to send them to. I suspect that this might be due to the frequency of calls being too high (sometimes 100+/second) as it looks like it's more prone to fail when there's a large number of keystrokes/second.
A little program to illustrate what I'm doing, incomplete and without error checks for the sake of conciseness:
// #includes ...
struct action {
int time; // Time where this should be executed.
int down; // Keydown or keyup?
int code; // The VK to simulate the event for.
};
Display *display;
int nactions; // actions array length.
struct action *actions; // Array of actions we'll want to "execute".
int main(void)
{
display = XOpenDisplay(NULL);
nactions = get_actions(&actions);
int cur_time;
int cur_i = 0;
struct action *cur_action;
// While there's still actions to execute.
while (cur_i < nactions) {
cur_time = get_time();
cur_action = actions + cur_i;
// For each action that is (over)due.
while ((cur_action = actions + cur_i)->time <= cur_time) {
cur_i++;
XTestFakeKeyEvent(display, cur_action->code,
cur_action->down, CurrentTime);
XFlush(display);
}
// Sleep for 1ms.
nanosleep((struct timespec[]){{0, 1000000L}}, NULL);
}
}
I realize that the code above is very specific to my case, but I suspect that this is a broader problem - which is also why I'm asking this here.
Is there a limit to how often you can/should flush XEvents? Could the application I'm sending this to be the issue, maybe failing to read them quickly enough?
It's been a little while but after some tinkering, it turned out that my delay between key down and key up was simply too low. After setting it to 15ms the application registered the actions as keystrokes properly and (still) with very high accuracy.
I feel a little silly in retrospect, but I do feel like this might be something others could stumble over as well.

IOHIDManager not triggering callback for keyboard

So I am trying to put together a simple fullscreen OpenGL application using CGL and IOHIDManager in order to learn the lower-level APIs. Currently, I am creating an OpenGL context and starting it fullscreen. I am trying to now add keyboard input so I can quit the app. I've found many similar examples of using IOHIDManager to read keys, but no matter what I do my callback does not fire.
My callback is just a function that prints "here". I'm not sure where I am going wrong -- I've tried both CFRunLoopGetCurrent() and CFRunLoopMain(). My main is simply a while loop. What gives?
CFMutableDictionaryRef CreateMatchingDictionary(UInt32 usage_page, UInt32 usage) {
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFNumberRef page_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page);
CFDictionarySetValue(dictionary, CFSTR(kIOHIDDeviceUsagePageKey), page_number);
CFRelease(page_number);
CFNumberRef usage_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
CFDictionarySetValue(dictionary, CFSTR(kIOHIDDeviceUsageKey), usage_number);
CFRelease(usage_number);
return dictionary;
}
void CreateInputManager() {
IOHIDManagerRef hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
CFMutableDictionaryRef matching_dictionary = CreateMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
IOHIDManagerSetDeviceMatching(hid_manager, matching_dictionary);
IOHIDManagerRegisterInputValueCallback(hid_manager, KeyboardCallback, NULL);
IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
void KeyboardCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) {
puts("CALLBACK!");
}
int main() {
// Commented out CGL context & fullscreen window creation
CreateInputManager();
while(true) {
;
}
}
UPDATE
If I put CFRunLoopRun() at the end of function CreateInputManager, my callback is called but the function never returns. How is this supposed to work in a single-threaded CGL app? Is it a strict requirement that IOHIDManager requires a run loop to function?
IOKit and HID work via Mach messaging, which in turn is deeply integrated with the runloop mechanism, as you've found. If you really do want to busy-poll, you can use the CFRunLoopRunInMode function with a zero timeout to check for events.
You may wish to consider using a CVDisplayLink to invoke your rendering code on every vertical frame refresh instead. The display link's callback will be called from the runloop, so you can leave your main thread running in CFRunLoopRun().
See https://developer.apple.com/library/mac/qa/qa1385/_index.html for how Apple recommends you structure event handling in OpenGL applications.
Turns out I need to create a separate pthread with the CreateInputManager function, specify that the IOHIDManager is to schedule the callback on CFRunLoopGetCurrent() and kick off a run loop on that thread by calling CFRunLoopRun().
I wonder if there is a way to get IOHIDManager to work with plain-old polling instead of these callbacks...

gtk_container_add crush on mac

I create an GtkFixed object and put it into GtkEventBox via gtk_container_add (with destroying previous child, of course). This way works fine on Windows, but on Mac it crashes.
Stack trace showed me that app crashed on gtk_get_parent. I've tried to user set_parent procedure, but it crashes too:
[debug][New Thread 0x1b0f of process 88699]
[debug]Program received signal SIGSEGV, Segmentation fault.
[debug]0x0000000100b3cf3d in gtk_widget_set_parent () from /usr/local/lib/libgtk-3.0.dylib
[debug]>>>>>>cb_gdb:
Program received signal SIGSEGV, Segmentation fault.
In gtk_widget_set_parent () (/usr/local/lib/libgtk-3.0.dylib)
[debug]> bt 30
[debug]#0 0x0000000100b3cf3d in gtk_widget_set_parent () from /usr/local/lib/libgtk-3.0.dylib
Code runned in main thread and in "realize" callback of Window. Same.
The code is:
void main_view_reset_list_view(GtkWidget* list_view, GtkWidget* new_item)
{
GtkEventBox* eb = GTK_EVENT_BOX(list_view);
GtkBin* bin = GTK_BIN(list_view);
GtkContainer* container = GTK_CONTAINER(list_view);
GtkWidget* subview;
subview = gtk_bin_get_child(bin);
if (subview)
{
gtk_container_remove(container, subview);
gtk_widget_unparent (subview);
gtk_widget_destroy(subview);
}
gtk_widget_set_parent(new_item, container); // crash
GtkWidget* parent = gtk_widget_get_parent(container);
GtkWidget* parent2 = gtk_widget_get_parent(new_item); // 0 on windows, crash on mac
if (new_item)
{
gtk_container_add(container, new_item);
gtk_widget_show(new_item);
}
gtk_widget_show(list_view);
}
UPD:
set_parent makes controls dissapeared somehow on windows
I've traced gtk and glib source code and figured that G_IS_OBJECT() fails, which is quite weird. This post have brought me to mind that this issue is pointer-related. I've debugged my code and saw that it is true.
GtkWidget* create_widget()
{
return gtk_fixed_new(); // result points to 0x1018bf830
}
void refresh_widgets()
{
GtkWidget* w = create_widget(); // w points to 0x18bf830
}
I've actually faced with this kind of issue before, so all code which return pointers has been changed:
char* generate_string();
to
void generate_string(char** out);
So in order to fix my problem I have to provide correct pointers in this way. Like:
void create_widget(GtkWidget** out);
UPD: I've noticed difference between pointers. Shortly say, somehow they are trimmed to 32 bit on 64 bit system on return.
UPD2: Finally, I've made all changes and it works that way.

wxTimerEvent does not always call at the expected interval

I am using wxTimerEvent() to call a function at a certain frequency. But it does not always call the function as expected.
For example, it works fine for a random time duration, and then it does not call the function at all for a few seconds. SHere is my block of code. Please help me figure out this issue...
class MyFrame : public wxFrame
{
public:
...
void OnTimer(wxTimerEvent& event);
private:
wxTimer *mTimer
wxDECLARE_EVENT_TABLE();
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_TIMER(TIMER_ID, MyFrame::OnTimer)
wxEND_EVENT_TABLE()
MyFrame::MyFrame()
{
mTimer = new wxTimer(this, TIMER_ID)
m_timer.Start(100); // 100 millisecond interval
}
void MyFrame::OnTimer(wxTimerEvent& event)
{
// my logic -this is working fine... just set a flag.
}
Timers are not guaranteed to fire at exactly the specified interval, but for a 100ms timer to not be called for several seconds is not normal at all. I suspect your code doesn't return to the event loop, preventing it from dispatching the timer events. If you're sure this is not the case, you would really need to produce an example reproducing the problem (ideally the smallest possible change to the wxWidgets minimal sample) and open a bug report about it (please be sure to mention your wxWidgets version and platform if you do this).

GTK+ - How to listen to an event from within a method?

I'm writing an application that runs an algorithm, but allows you to 'step through' the algorithm by pressing a button - displaying what's happening at each step.
How do I listen for events while within a method?
eg, look at the code I've got.
static int proceed;
button1Event(GtkWidget *widget)
{
proceed = 0;
int i = 0;
for (i=0; i<15; i++) //this is our example 'algorithm'
{
while (proceed ==0) continue;
printf("the nunmber is %d\n", i);
proceed = 0;
}
}
button2Event(GtkWidget *widget)
{
proceed = 1;
}
This doesn't work because it's required to exit out of the button1 method before it can listen for button2 (or any other events).
I'm thinking something like in that while loop.
while(proceed == 0)
{
listen_for_button_click();
}
What method is that?
The "real" answer here (the one any experienced GTK+ programmer will give you) isn't one you will like perhaps: don't do this, your code is structured the wrong way.
The options include:
recommended: restructure the app to be event-driven instead; probably you need to keep track of your state (either a state machine or just a boolean flag) and ignore whichever button is not currently applicable.
you can run a recursive main loop, as in the other answer with gtk_main_iteration(); however this is quite dangerous because any UI event can happen in that loop, such as windows closing or other totally unrelated stuff. Not workable in most real apps of any size.
move the blocking logic to another thread and communicate via a GAsyncQueue or something along those lines (caution, this is hard-ish to get right and likely to be overkill).
I think you are going wrong here:
while(proceed == 0)
{
listen_for_button_click();
}
You don't want while loops like this; you just want the GTK+ main loop doing your blocking. When you get the button click, in the callback for it, then write whatever the code after this while loop would have been.
You could check for pending events & handle the events in while loop in the clicked callback. Something on these lines:
button1Event(GtkWidget *widget)
{
proceed = 0;
int i = 0;
for (i=0; i<15; i++) //this is our example 'algorithm'
{
while (proceed ==0)
{
/* Check for all pending events */
while(gtk_events_pending())
{
gtk_main_iteration(); /* Handle the events */
}
continue;
}
printf("the nunmber is %d\n", i);
proceed = 0;
}
}
This way when the events related click on the second button is added to the event queue to be handled, the check will see the events as pending and handle them & then proceed. This way your global value changes can be reflected & stepping should be possible.
Hope this helps!
If you want to do it like this, the only way that comes to my mind is to create a separate thread for your algorithm and use some synchronization methods to notify that thread from within button click handlers.
GTK+ (glib, to be more specific) has its own API for threads and synchronization. As far as I know Condition variables are a standard way to implement wait-notify logic.

Resources