Related
I'm learning c and messing around with xcb lib (instead of X11) on a raspberry pi4.
The problem is that when implementing the events loop with xcb_poll_for_event instead of xcb_wait_for_event, one core of four is 100% full. What am I doing wrong? And is there any benefit of using wait_for_event (blocking way) instead of xcb_poll_for_event(non blocking)?
The goal is to create a window where the user interact with keyboard/mouse/gamepad on objects, like a game. Can anyone give a hand?
The relevant code is:
int window_loop_test(xcb_connection_t *connection, Display *display){
/* window loop non blocked waiting for events */
int running = 1;
while (running) {
xcb_generic_event_t *event = xcb_poll_for_event(connection);
if (event) {
switch (event->response_type & ~0x80) {
case XCB_EXPOSE: {
// TODO
break;
}
case XCB_KEY_PRESS: {
/* Quit on 'q' key press */
/* write key pressed on console */
const xcb_key_press_event_t *press =
(xcb_key_press_event_t *)event;
XKeyEvent keyev;
keyev.display = display;
keyev.keycode = press->detail;
keyev.state = press->state;
char key[32];
XLookupString(&keyev, key, sizeof(key) - 1, NULL, NULL);
// key[len] = 0;
printf("Key pressed: %s\n", key);
printf("Mod state: %d\n", keyev.state);
if (*key == 'q')
running = 0;
break;
}
}
free(event);
}
}
return 0;
}
Polling and waiting each have their advantages and are good for different situations. Neither is "wrong" per se, but you need to use the correct one for your specific use case.
xcb_wait_for_event(connection) is a blocking call. The call will not return until an event is available, and the return value is is that event (unless an error occurs). It is good for situations where you only want the thread to respond to events, but otherwise not do anything. In that case, there is no need to spend CPU resources when no events are coming in.
xcb_poll_for_event(connection) is a non-blocking call. The call always returns immediately, but the result will be NULL if no event is available. It is good for situations where you want the thread to be able to do useful work even if no events are coming in. As you found out, it's not good if the thread only needs to respond to events, as it can consume CPU resources unnecessarily.
You mention that your goal is to create a game or something similar. Given that there are many ways to architect a game, either function can be suitable. But there are a couple of basic things to keep in mind that will determine which function you want to use. There may be other considerations as well, but this will give you an idea of what to look out for.
First of all, is your input system running on the same thread as other systems (simulation, rendering, etc)? If so, it's probably important to keep that thread available for work other than waiting for input events. In this case, xcb_poll_for_event() is almost required, otherwise your thread will be blocked until an event comes in. However, if your input system is on its own thread that doesn't block your other threads, it may be acceptable to use xcb_wait_for_event() and let that thread sleep when no events are coming in.
The second consideration is how quickly you need to respond to input events. There's often a delay in waking up a thread, so if fast response times are important you'll want to avoid letting the thread sleep in the first place. Again, xcb_poll_for_event() will be your friend in this case. If response times are not critical, xcb_wait_for_events() is an option.
I want to create a realtime sine generator using apples core audio framework. I want do do it low level so I can learn and understand the fundamentals.
I know that using PortAudio or Jack would probably be easier and I will use them at some point but I would like to get this to work first so I can be confident to understand the fundamentals.
I literally searched for days now on this topic but no one seems to have ever created a real time wave generator using core audio trying to optain low latency while using C and not Swift or Objective-C.
For this I use a project I set up a while ago. It was first designed to be a game. So after the Application starts up, it will enter a run loop. I thought this would perfectly fit as I can use the main loop to copy samples into the audio buffer and process rendering and input handling as well.
So far I get sound. Sometimes it works for a while then starts to glitch, sometimes it glitches right away.
This is my code. I tried to simplify if and only present the important parts.
I got multiple questions. They are located in the bottom section of this post.
Applications main run loop. This is where it all starts after the window is created and buffers and memory is initialized:
while (OSXIsGameRunning())
{
OSXProcessPendingMessages(&GameData);
[GlobalGLContext makeCurrentContext];
CGRect WindowFrame = [window frame];
CGRect ContentViewFrame = [[window contentView] frame];
CGPoint MouseLocationInScreen = [NSEvent mouseLocation];
BOOL MouseInWindowFlag = NSPointInRect(MouseLocationInScreen, WindowFrame);
CGPoint MouseLocationInView = {};
if (MouseInWindowFlag)
{
NSRect RectInWindow = [window convertRectFromScreen:NSMakeRect(MouseLocationInScreen.x, MouseLocationInScreen.y, 1, 1)];
NSPoint PointInWindow = RectInWindow.origin;
MouseLocationInView= [[window contentView] convertPoint:PointInWindow fromView:nil];
}
u32 MouseButtonMask = [NSEvent pressedMouseButtons];
OSXProcessFrameAndRunGameLogic(&GameData, ContentViewFrame,
MouseInWindowFlag, MouseLocationInView,
MouseButtonMask);
#if ENGINE_USE_VSYNC
[GlobalGLContext flushBuffer];
#else
glFlush();
#endif
}
Through using VSYNC I can throttle the loop down to 60 FPS. The timing is not super tight but it is quite steady. I also have some code to throttle it manually using mach timing which is even more imprecise. I left it out for readability.
Not using VSYNC or using mach timing to get 60 iterations a second also makes the audio glitch.
Timing log:
CyclesElapsed: 8154360866, TimeElapsed: 0.016624, FPS: 60.155666
CyclesElapsed: 8174382119, TimeElapsed: 0.020021, FPS: 49.946926
CyclesElapsed: 8189041370, TimeElapsed: 0.014659, FPS: 68.216309
CyclesElapsed: 8204363633, TimeElapsed: 0.015322, FPS: 65.264511
CyclesElapsed: 8221230959, TimeElapsed: 0.016867, FPS: 59.286217
CyclesElapsed: 8237971921, TimeElapsed: 0.016741, FPS: 59.733719
CyclesElapsed: 8254861722, TimeElapsed: 0.016890, FPS: 59.207333
CyclesElapsed: 8271667520, TimeElapsed: 0.016806, FPS: 59.503273
CyclesElapsed: 8292434135, TimeElapsed: 0.020767, FPS: 48.154209
What is important here is the function OSXProcessFrameAndRunGameLogic. It is called 60 times a second and it is passed a struct containing basic information like a buffer for rendering, keyboard state and a sound buffer which looks like this:
typedef struct osx_sound_output
{
game_sound_output_buffer SoundBuffer;
u32 SoundBufferSize;
s16* CoreAudioBuffer;
s16* ReadCursor;
s16* WriteCursor;
AudioStreamBasicDescription AudioDescriptor;
AudioUnit AudioUnit;
} osx_sound_output;
Where game_sound_output_buffer is:
typedef struct game_sound_output_buffer
{
real32 tSine;
int SamplesPerSecond;
int SampleCount;
int16 *Samples;
} game_sound_output_buffer;
These get set up before the application enters its run loop.
The size for the SoundBuffer itself is SamplesPerSecond * sizeof(uint16) * 2 where SamplesPerSecond = 48000.
So inside OSXProcessFrameAndRunGameLogic is the sound generation:
void OSXProcessFrameAndRunGameLogic(osx_game_data *GameData, CGRect WindowFrame,
b32 MouseInWindowFlag, CGPoint MouseLocation,
int MouseButtonMask)
{
GameData->SoundOutput.SoundBuffer.SampleCount = GameData->SoundOutput.SoundBuffer.SamplesPerSecond / GameData->TargetFramesPerSecond;
// Oszi 1
OutputTestSineWave(GameData, &GameData->SoundOutput.SoundBuffer, GameData->SynthesizerState.ToneHz);
int16* CurrentSample = GameData->SoundOutput.SoundBuffer.Samples;
for (int i = 0; i < GameData->SoundOutput.SoundBuffer.SampleCount; ++i)
{
*GameData->SoundOutput.WriteCursor++ = *CurrentSample++;
*GameData->SoundOutput.WriteCursor++ = *CurrentSample++;
if ((char*)GameData->SoundOutput.WriteCursor >= ((char*)GameData->SoundOutput.CoreAudioBuffer + GameData->SoundOutput.SoundBufferSize))
{
//printf("Write cursor wrapped!\n");
GameData->SoundOutput.WriteCursor = GameData->SoundOutput.CoreAudioBuffer;
}
}
}
Where OutputTestSineWave is the part where the buffer is actually filled with data:
void OutputTestSineWave(osx_game_data *GameData, game_sound_output_buffer *SoundBuffer, int ToneHz)
{
int16 ToneVolume = 3000;
int WavePeriod = SoundBuffer->SamplesPerSecond/ToneHz;
int16 *SampleOut = SoundBuffer->Samples;
for(int SampleIndex = 0;
SampleIndex < SoundBuffer->SampleCount;
++SampleIndex)
{
real32 SineValue = sinf(SoundBuffer->tSine);
int16 SampleValue = (int16)(SineValue * ToneVolume);
*SampleOut++ = SampleValue;
*SampleOut++ = SampleValue;
SoundBuffer->tSine += Tau32*1.0f/(real32)WavePeriod;
if(SoundBuffer->tSine > Tau32)
{
SoundBuffer->tSine -= Tau32;
}
}
}
So when the Buffers are created at start up also Core audio is initialized which I do like this:
void OSXInitCoreAudio(osx_sound_output* SoundOutput)
{
AudioComponentDescription acd;
acd.componentType = kAudioUnitType_Output;
acd.componentSubType = kAudioUnitSubType_DefaultOutput;
acd.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioComponent outputComponent = AudioComponentFindNext(NULL, &acd);
AudioComponentInstanceNew(outputComponent, &SoundOutput->AudioUnit);
AudioUnitInitialize(SoundOutput->AudioUnit);
// uint16
//AudioStreamBasicDescription asbd;
SoundOutput->AudioDescriptor.mSampleRate = SoundOutput->SoundBuffer.SamplesPerSecond;
SoundOutput->AudioDescriptor.mFormatID = kAudioFormatLinearPCM;
SoundOutput->AudioDescriptor.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsPacked;
SoundOutput->AudioDescriptor.mFramesPerPacket = 1;
SoundOutput->AudioDescriptor.mChannelsPerFrame = 2; // Stereo
SoundOutput->AudioDescriptor.mBitsPerChannel = sizeof(int16) * 8;
SoundOutput->AudioDescriptor.mBytesPerFrame = sizeof(int16); // don't multiply by channel count with non-interleaved!
SoundOutput->AudioDescriptor.mBytesPerPacket = SoundOutput->AudioDescriptor.mFramesPerPacket * SoundOutput->AudioDescriptor.mBytesPerFrame;
AudioUnitSetProperty(SoundOutput->AudioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&SoundOutput->AudioDescriptor,
sizeof(SoundOutput->AudioDescriptor));
AURenderCallbackStruct cb;
cb.inputProc = OSXAudioUnitCallback;
cb.inputProcRefCon = SoundOutput;
AudioUnitSetProperty(SoundOutput->AudioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
0,
&cb,
sizeof(cb));
AudioOutputUnitStart(SoundOutput->AudioUnit);
}
The initialization code for core audio sets the render callback to OSXAudioUnitCallback
OSStatus OSXAudioUnitCallback(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
#pragma unused(ioActionFlags)
#pragma unused(inTimeStamp)
#pragma unused(inBusNumber)
//double currentPhase = *((double*)inRefCon);
osx_sound_output* SoundOutput = ((osx_sound_output*)inRefCon);
if (SoundOutput->ReadCursor == SoundOutput->WriteCursor)
{
SoundOutput->SoundBuffer.SampleCount = 0;
//printf("AudioCallback: No Samples Yet!\n");
}
//printf("AudioCallback: SampleCount = %d\n", SoundOutput->SoundBuffer.SampleCount);
int SampleCount = inNumberFrames;
if (SoundOutput->SoundBuffer.SampleCount < inNumberFrames)
{
SampleCount = SoundOutput->SoundBuffer.SampleCount;
}
int16* outputBufferL = (int16 *)ioData->mBuffers[0].mData;
int16* outputBufferR = (int16 *)ioData->mBuffers[1].mData;
for (UInt32 i = 0; i < SampleCount; ++i)
{
outputBufferL[i] = *SoundOutput->ReadCursor++;
outputBufferR[i] = *SoundOutput->ReadCursor++;
if ((char*)SoundOutput->ReadCursor >= (char*)((char*)SoundOutput->CoreAudioBuffer + SoundOutput->SoundBufferSize))
{
//printf("Callback: Read cursor wrapped!\n");
SoundOutput->ReadCursor = SoundOutput->CoreAudioBuffer;
}
}
for (UInt32 i = SampleCount; i < inNumberFrames; ++i)
{
outputBufferL[i] = 0.0;
outputBufferR[i] = 0.0;
}
return noErr;
}
This is mostly all there is to it. This is quite long but I did not see a way to present all needed information in a more compact way. I wanted to show all because I am by no means a professional programmer. If there is something you feel is missing, pleas tell me.
My feeling tells me that there is something wrong with the timing. I feel the function OSXProcessFrameAndRunGameLogic sometimes needs more time so that the core audio callback is already pulling samples out of the buffer before it is fully written by OutputTestSineWave.
There is actually more stuff going on in OSXProcessFrameAndRunGameLogic which I did not show here. I am "software rendering" very basic stuff into a framebuffer which is then displayed by OpenGL and I also do keypress checks in there because yeah, its the main function of functionality. In the future this is the place where I would like to handle the controls for multiple oscillators, filters and stuff.
Anyway even if I stop the Rendering and Input handling from being called every iteration I still get audio glitches.
I tried pulling all the sound processing in OSXProcessFrameAndRunGameLogic into an own function void* RunSound(void *GameData) and changed it to:
pthread_t soundThread;
pthread_create(&soundThread, NULL, RunSound, GameData);
pthread_join(soundThread, NULL);
However I got mixed results and was not even sure if multithreading is done like that. Creating and destroying threads 60 times a second didn't seem the way to go.
I also had the idea to let sound processing happen on a completely different thread before the application actually runs into the main loop. Something like two simultaneously running while loops where the first processes audio and the latter UI and input.
Questions:
I get glitchy audio. Rendering and input seem to work correctly but audio sometimes glitches, sometimes it doesn't. From the code I provided, can you maybe see me doing something wrong?
Am I using the core audio technology in a wrong way in order to achieve real time low latency signal generation?
Should I do sound processing in a separate thread like I talked about above? How would threading in this context be done correctly? It would make sense to have a thread only dedicated for sound am I right?
Am I right that the basic audio processing should not be done in the render callback of core audio? Is this function only for outputting the provided sound buffer?
And if sound processing should be done right here, how can I access information like the keyboard state from inside the callback?
Are there any resources you could point me to that I maybe missed?
This is the only place I know where I can get help with this project. I would really appreciate your help.
And if something is not clear to you please let me know.
Thank you :)
In general when dealing with low-latency audio you want to achieve the most deterministic behaviour possible.
This, for example, translates to:
Don't hold any locks on the audio thread (priority inversion)
No memory allocation on the audio thread (takes often too much time)
No file/network IO on the audio thread (takes often too much time)
Question 1:
There are indeed some problems with your code for when you want to achieve continuous, realtime, non-glitching audio.
1. Two different clock domains.
You are providing audio data from a (what I call) a different clock domain than the clock domain asking for data. Clock domain 1 in this case is defined by your TargetFramesPerSecond value, clock domain 2 defined by Core Audio. However, due too how scheduling works you have no guarantee that you thread is finishing in time and on time. You try to target your rendering to n frames per second, but what happens when you don't make it time wise? As far as I can see you don't compensate for the deviation a render cycle took compared to the ideal timing.
The way threading works is that ultimately the OS scheduler decides when your thread is active. There are never guarantees and this causes you render cycles to be not very precise (in term of precision you need for audio rendering).
2. There is no synchronisation between the render thread and the Core Audio rendercallback thread.
The thread where the OSXAudioUnitCallback runs is not the same as where your OSXProcessFrameAndRunGameLogic and thus OutputTestSineWave run. You are providing data from your main thread, and data is being read from the Core Audio render thread. Normally you would use some mutexes to protect you data, but in this case that's not possible because you would run into the problem of priority inversion.
A way of dealing with race conditions is to use a buffer which uses atomic variables to store the usage and pointers of the buffer and let only 1 producer and 1 consumer use this buffer.
Good examples of such buffers are:
https://github.com/michaeltyson/TPCircularBuffer
https://github.com/andrewrk/libsoundio/blob/master/src/ring_buffer.h
3. There are a lot of calls in you audio render thread which prevent deterministic behaviour.
As you wrote you are doing a lot more inside the same audio render thread. Changes are quite high that there will be stuff going on (under the hood) which prevents your thread from being on time. Generally, you should avoid calls which take either too much time or are not deterministic. With all the OpenGL/keypres/framebuffer rendering there is no way to be certain you thread will "arrive on time".
Below are some resources worth looking into.
Question 2:
AFAICT generally speaking, you are using the Core Audio technology correctly. The only problem I think you have is on the providing side.
Question 3:
Yes. Definitely! Although, there are multiple ways of doing this.
In your case you have a normal-priority thread running to do the rendering and a high-performance, realtime thread on which the audio render callback is being called. Looking at your code I would suggest putting the generation of the sine wave inside the render callback function (or call OutputTestSineWave from the render callback). This way you have the audio generation running inside a reliable high prio thread, there is no other rendering interfering with the timing precision and there is no need for a ringbuffer.
In other cases where you need to do "non-realtime" processing to get audiodata ready (think of reading from a file, reading from a network or even from another physical audio device) you cannot run this logic inside the Core Audio thread. A way to solve this is to start a separate, dedicated thread to do this processing. To pass the data to the realtime audio thread you would then make use of the earlier mentioned ringbuffer.
It basically boiles down to two simple goals: for the realtime thread it is necessary to have the audio data available at all times (all render calls), if this failes you will end up sending invalid (or better zeroed) audio data.
The main goal for the secondary thread is to fill up the ringbuffer as fast as possible and to keep the ringbuffer as full as possible. So, whenever there is room to put new audio data into the ringbuffer the thread should do just that.
The size of the ringbuffer in this case will dicate how much tolerance there will be for delay. The size of the ringbuffer will be a balance between certainty (bigger buffer) and latency (smaller buffer).
BTW. I'm quite certain Core Audio has all the facilities to do all this for you.
Question 4:
There are multiple ways of achieving you goal, and rendering the stuff inside the render callback from Core Audio is definitely one of them. The one thing you should keep in mind is that you have to make sure the function returns in time.
For changing parameters to manipulate the audio rendering you'll have to find a way of passing messages which enables the reader (audio renderer function) to get messages without locking and waiting. The way I have done this is to create a second ringbuffer which hold messages from which the audio renderer can consume. This can be as simple as a ringbuffer which hold structs with data (or even pointers to data). As long as you stick to the rules of no locking.
Question 5:
I don't know what resources you are aware of but here are some must-reads:
http://atastypixel.com/blog/four-common-mistakes-in-audio-development/
http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing
https://developer.apple.com/library/archive/qa/qa1467/_index.html
You basic problem is that you are trying to push audio from your game loop instead of letting the audio system pull it; e.g. instead of always having (or quickly being able to create *) enough audio samples ready for the amount requested by the audio callback to be pulled by the audio callback. The "always" has to account for enough slop to cover timing jitter (being called late or early or too few times) in your game loop.
(* with no locks, semaphores, memory allocation or Objective C messages)
I'm trying to create a small window manager (just for fun), but I'm having problems in handling windows created by Firefox (only with that application, other apps works fine)
The problem is, after I launch Firefox, and add my decoration, it seems to work fine, but if for example I try to click on the menu button, the (sub)window doesn't appear.
What seems to happen is that after the click, a ClientMessage event is fired with the following values:
Data: (null)
Data: _NET_WM_STATE_HIDDEN
Data: (null)
Data: (null)
Data: (null)
Now the problem is that I don't know how to show the window, which window.
I tried with:
XRaiseWindow
XMapWindow
I tried to get the transient window and show it
But without success. What I don't understand is that if this client message is generated by the menu subwindow or not.
How should I show a window that is in _NET_WM_STATE_HIDDEN?
Another strange problem is that after receiving the ClientMessage, I always receive 2 UnMapNotify Events.
I also have another question, if I want to show the "File, Edit" menù (in Firefox it appears, if I remember correctly, when you press the Alt button.
Maybe Firefox creates a tree of windows?
This is the loop where I handle the events:
while(1){
XNextEvent(display, &local_event);
switch(local_event.type){
case ConfigureNotify:
configure_notify_handler(local_event, display);
break;
case MotionNotify:
motion_handler(local_event, display);
break;
case CreateNotify:
cur_win = local_event.xcreatewindow.window;
char *window_name;
XFetchName(display, cur_win, &window_name);
printf("Window name: %s\n", window_name);
if(window_name!=NULL){
if(!strcmp(window_name, "Parent")){
printf("Adding borders\n");
XSetWindowBorderWidth(display, cur_win, BORDER_WIDTH);
}
XFree(window_name);
}
break;
case MapNotify:
map_notify_handler(local_event,display, infos);
break;
case UnmapNotify:
printf("UnMapNotify\n");
break;
case DestroyNotify:
printf("Destroy Event\n");
destroy_notify_handler(local_event,display);
break;
case ButtonPress:
printf("Event button pressed\n");
button_handler(local_event, display, infos);
break;
case KeyPress:
printf("Keyboard key pressed\n");
keyboard_handler(local_event, display);
break;
case ClientMessage:
printf("------------ClientMessage\n");
printf("\tMessage: %s\n", XGetAtomName(display,local_event.xclient.message_type));
printf("\tFormat: %d\n", local_event.xclient.format);
Atom *atoms = (Atom *)local_event.xclient.data.l;
int i =0;
for(i=0; i<=5; i++){
printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i]));
}
int nchild;
Window *child_windows;
Window parent_window;
Window root_window;
XQueryTree(display, local_event.xclient.window, &root_window, &parent_window, &child_windows, &nchild);
printf("\tNumber of childs: %d\n", nchild);
break;
}
Now in the clientmessage actually I'm just trying to see collect some information to understand what is happening. And what I can see from the code above, is that the window that raised the event contains one child (again: is that the menu? or not?)
The code for the MapNotify event, where I add the decoration is the following:
void map_notify_handler(XEvent local_event, Display* display, ScreenInfos infos){
printf("----------Map Notify\n");
XWindowAttributes win_attr;
char *child_name;
XGetWindowAttributes(display, local_event.xmap.window, &win_attr);
XFetchName(display, local_event.xmap.window, &child_name);
printf("\tAttributes: W: %d - H: %d - Name: %s - ID %lu\n", win_attr.width, win_attr.height, child_name, local_event.xmap.window);
Window trans = None;
XGetTransientForHint(display, local_event.xmap.window, &trans);
printf("\tIs transient: %ld\n", trans);
if(child_name!=NULL){
if(strcmp(child_name, "Parent") && local_event.xmap.override_redirect == False){
Window new_win = draw_window_with_name(display, RootWindow(display, infos.screen_num), "Parent", infos.screen_num,
win_attr.x, win_attr.y, win_attr.width, win_attr.height+DECORATION_HEIGHT, 0,
BlackPixel(display, infos.screen_num));
XMapWindow(display, new_win);
XReparentWindow(display,local_event.xmap.window, new_win,0, DECORATION_HEIGHT);
set_window_item(local_event.xmap.window, new_win);
XSelectInput(display, local_event.xmap.window, StructureNotifyMask);
printf("\tParent window id: %lu\n", new_win);
put_text(display, new_win, child_name, "9x15", 10, 10, BlackPixel(display,infos.screen_num), WhitePixel(display, infos.screen_num));
}
}
XFree(child_name);
}
Now can someone help me with these problems? Unfortunately I already googled many times, but without success.
To sum up, my issues are two:
1. How to show subwindows from Firefox
2. How to show the File, Edit menu.
UPDATE
I noticed something strange testing Firefox with xev to understand what events are fired in order to show an application. I saw that using Firefox in unity, and using Firefox in another window manger, the events fired are completely different. In Unity I have only:
ClientMessage
UnmapNotify
Instead using Firefox, for example with xfce4, the xevents generated are more:
VisiblityNotify (more than one)
Expose event (more than one)
But if I try to enable VisibilityChangeMask in my wm, I receive the following events:
ConfigureNotify
ClientMessage
MapNotify
2 UnMapNotify
UPDATE 2
I tried to read the XWMhints properties in the ClientMessage window (probably the menù window) and the values are:
For the flags 67 = InputHint, StateHint, WIndowGroupHint
For the initial state NormalState
UPDATE 3
I tried to look how another window manager works, and I was looking at the source code of calmwm. What is my understanding is that, when the ClientMessage event arrives, with a _NET_WM_STATE message, it updates these properties, and in the case of _NET_WM_STATE_HIDDEN it clears this property, and the result will be that the property will be deleted. So I tried to update my code to delete that property, but it's still not working. Anyway the relevant updated code in client_message_handler now looks like this:
Atom *atoms = (Atom *)local_event.xclient.data.l;
int i =0;
for(i=0; i<=5; i++){
printf("\t\tData %d: %s\n", i, XGetAtomName(display, atoms[i]));
if(i==1){
printf("\t Deleting Property: _NET_WM_STATE_HIDDEN \n");
XDeleteProperty(display, cur_window, atoms[i]);
}
}
It is only a test, and I'm sure that i=1 in my case is the _NET_WM_STATE_HIDDEN property.
Here a link to calmwm source code: https://github.com/chneukirchen/cwm/blob/linux/xevents.c
So I'm still stuck at that point.
UPDATE 4
Really I don't know if it helps, but I tried to read the window attributes in the MapNotify Event, and the window map_state is IsViewable (2).
UPDATE 5
I found a similar problem here in SO, using xlib with python: Xlib python: cannot map firefox menus
The solution suggests to use XSetInputFocus, i tried that on my XMapNotify handler:
XSetInputFocus(display, local_event.xmap.window, RevertToParent, CurrentTime);
But it still doesn't help, the firefox menu still doesn't appear!!
And i have the same problem with right-click.
UPDATE 6
Playing with xconfigurenotify event and unmap event i found that the:
Xconfigure request has 2 window fields: window and above, and when the
the xconfigurerequest.window value is the same of xunmap.window value.
And also that the xconfigurerequest.above is always changing, but xconfigurerequest.window is always the same in all events.
It seems that the xconfigurerequest.above is related to what menu i'm trying to open. For example:
if right-click on a page i get an id (always the same for every subsequent click)
if i right-clik on a tab, the above value is another one
and the same happen if i left-click the firefox main menu
Still don't know if that helps.
Really don't know
Anyone got any idea?
This question is ancient but for the benefit of anyone who stumbles across it looking for an answer to this, here's an edited (chopped to bits) sample of how I solved this based on the hints above:
while (event = xcb_poll_for_event(connection)) {
uint8_t actual_event = event->response_type & 127;
switch (actual_event) {
case XCB_MAP_NOTIFY: ;
xcb_map_notify_event_t *map_evt = (xcb_map_notify_event_t *)event;
if (map_evt->override_redirect) {
xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for(connection, map_evt->window);
xcb_window_t transient_for = 0;
xcb_icccm_get_wm_transient_for_reply(connection, cookie, &transient_for, NULL);
if (transient_for) {
xcb_set_input_focus(connection, XCB_INPUT_FOCUS_POINTER_ROOT, transient_for, XCB_CURRENT_TIME);
}
xcb_flush(connection);
}
break;
case XCB_CLIENT_MESSAGE: ;
xcb_client_message_event_t *message_evt = (xcb_client_message_event_t *)event;
xcb_get_atom_name_cookie_t name_cookie = xcb_get_atom_name(connection, message_evt->type);
xcb_get_atom_name_reply_t *name_reply = xcb_get_atom_name_reply(connection, name_cookie, NULL);
int length = xcb_get_atom_name_name_length(name_reply);
char *atom_name = malloc(length + 1);
strncpy(atom_name, xcb_get_atom_name_name(name_reply), length);
atom_name[length] = '\0';
free(atom_name);
free(name_reply);
if (message_evt->type == ewmh->_NET_WM_STATE) {
xcb_atom_t atom = message_evt->data.data32[1];
unsigned int action = message_evt->data.data32[0];
xcb_get_atom_name_cookie_t name_cookie = xcb_get_atom_name(connection, atom);
xcb_get_atom_name_reply_t *name_reply = xcb_get_atom_name_reply(connection, name_cookie, NULL);
int length = xcb_get_atom_name_name_length(name_reply);
char *atom_name = malloc(length + 1);
strncpy(atom_name, xcb_get_atom_name_name(name_reply), length);
atom_name[length] = '\0';
if (action == XCB_EWMH_WM_STATE_REMOVE) {
if (atom == ewmh->_NET_WM_STATE_HIDDEN) {
xcb_delete_property(connection, message_evt->window, ewmh->_NET_WM_STATE_HIDDEN);
}
}
free(atom_name);
free(name_reply);
}
break;
}
}
By way of explanation, the important events to handle are MapNotify and ClientMessage because there's two main things that have to be taken care of, the window has to have its hidden state removed on request (the xcb_delete_property call) and the parent window of the transient has to gain input focus (the xcb_set_input_focus call; note that the window that the transient is a transient for gains focus, not the transient itself) or Firefox will immediately hide the transient again.
It also seems to be important for the transients to be stacked above their parent so a WM should respect the ConfigureRequest events.
PS Even if this is the accepted answer, the code of it is for xcb, if you need the code for xlib check my answer below, with the code adapted for xlib, it does cover only the MapNotify event
Use xtruss — an easy-to-use X protocol tracing program
Overview
Any programmer accustomed to writing programs on Linux or System V-type Unixes will have encountered the program variously known as strace or truss, which monitors another program and produces a detailed log of every system call the program makes – in other words, all the program's interactions with the OS kernel. This is often an invaluable debugging tool, and almost as good an educational one.
When it's a GUI program (or rather, the GUI-related behaviour of a program) that you want to understand or debug, though, the level of interaction with the OS kernel is rarely the most useful one. More helpfully, one would like to log all the program's interactions with the X server in the same way.
Programs already exist that will do this. I'm aware of Xmon and Xtrace. But they tend to require a lot of effort to set up: you have to run the program to establish a listening server, then manually arrange for the target program to contact that instead of the real server – including some fiddly work with xauth. Ideally, you'd like tracing a program's X operations to be just as easy as tracing its kernel system calls: you'd like to type a command as simple as strace program-name arguments, and have everything automatically handled for you.
Also, the output of those programs is less easy to read than I'd have liked – by which I largely mean it's less like strace than I'd like it to be. strace has the nice property of putting each system call and its return value on the same line of output, so that you can see at a glance what each response was a response to. X protocol monitors, however, tend to follow the structure of the X protocol faithfully, meaning that each request and response is printed with a sequence number, and you have to match the two up by eye.
So this page presents xtruss, my own contribution to the field of X protocol loggers. It has a command-line syntax similar to strace – in its default mode, you just prefix "xtruss" to the same command line you would have run anyway – and its output format is also more like strace, putting requests and responses on the same line of output where reasonably possible.
strace also supports the feature of attaching to an already-running process and tracing it from the middle of its run – handy when something goes wrong with a long-running process that you didn't know in advance you were going to need to trace. xtruss supports this same feature, by means of the X RECORD extension (provided your X server supports it, which modern X.Org ones do); so in that mode, you can identify a window with the mouse (similarly to standard programs like xwininfo and xkill), and xtruss will attach to the X client program that owns the window you specified, and begin tracing it.
Description
xtruss is a utility which logs everything that passes between the X server and one or more X client programs. In this it is similar to xmon(1), but intended to combine xmon's basic functionality with an interface much more similar to strace(1).
Like xmon, xtruss in its default mode works by setting up a proxy X server, waiting for connections to that, and forwarding them on to the real X server. However, unlike xmon, you don't have to deal with any of that by hand: there's no need to start the trace utility in one terminal and manually attach processes to it from another, unless you really want to (in which case the -P option will do that). The principal mode of use is just to type xtruss followed by the command line of your X program; xtruss will automatically take care of adjusting the new program's environment to point at its proxy server, and (also unlike xmon) it will also take care of X authorisation automatically.
As an alternative mode of use, you can also attach xtruss to an already-running X application, if you didn't realise you were going to want to trace it until it had already been started. This mode requires cooperation from the X server – specifically, it can't work unless the server supports the RECORD protocol extension – but since modern X.Org servers do provide that, it's often useful.
Ok, i'm going to answer my own question after only 4.5 years and half.
I'm going to revise Mr Lightning Bolt answer, and adapt it for XLIB, keeping focused on what he said about the Transient window. The answer probably will not be complete, but at least with that code snippet, now i'm able to open firefox menus.
I will accept his question, since he proposed the correct solution.
As lightning bolt pointed the key is the MapNotify Event,so the window manager should accept that kind of events, and when it is generated it should:
grab any transient window with XGetTransientWindowForHint
if any transient window is found, we need then to set input focus to it using XSetInputFocus.
The complete code, in your MapNotifyHandler, should looks like:
Window trans = None;
XGetTransientForHint(display, local_event.xmap.window, &trans);
if(trans != None){
XSetInputFocus(display, trans, RevertToParent, CurrentTime);
}
I'm trying to acquire data from an MCU, save them to a file and plot them. The code functions properly for some time, then just hangs randomly (sometimes after 1 sec, sometimes after 1 minute ...!). Also the serialport timeouts are not respected, i.e. I'm not receiving any timeout exceptions. I'm using an FTDI232RL chip. The only time I get a timeout exception is when I unplug it while the program is running.
Code:
private: System::Void START_Click(System::Object^ sender, System::EventArgs^ e) {
seconds=0;
minutes=0;
hours=0;
days=0;
t=0;
if((this->comboBox4->Text == String::Empty)||(this->textBox2->Text == String::Empty)||(this->textBox3->Text == String::Empty)){
this->textBox1->Text="please select port, save file directory and logging interval";
timer1->Enabled=false;
}
else{ // start assigning
w=Convert::ToDouble(this->textBox3->Text);
double q=fmod(w*1000,10);
if(q!=0){
MessageBox::Show("The logging interval must be a multiple of 0.01s");
}
else{
period=static_cast<int>(w*1000);
this->interval->Interval = period;
try{ // first make sure port isn't busy/open
if(!this->serialPort1->IsOpen){
// select the port whose name is in comboBox4 (select port)
this->serialPort1->PortName=this->comboBox4->Text;
//open the port
this->serialPort1->Open();
this->serialPort1->ReadTimeout = period+1;
this->serialPort1->WriteTimeout = period+1;
String^ name_ = this->serialPort1->PortName;
START=gcnew String("S");
this->textBox1->Text="Logging started";
timer1->Enabled=true;
interval->Enabled=true;
myStream=new ofstream(directory,ios::out);
*myStream<<"time(ms);ADC1;ADC2;ADC3;ADC4;ADC5;ADC6;ADC7;ADC8;";
*myStream<<endl;
chart1->Series["ADC1"]->Points->Clear();
chart1->Series["ADC2"]->Points->Clear();
chart1->Series["ADC3"]->Points->Clear();
chart1->Series["ADC4"]->Points->Clear();
chart1->Series["ADC5"]->Points->Clear();
chart1->Series["ADC6"]->Points->Clear();
chart1->Series["ADC7"]->Points->Clear();
chart1->Series["ADC8"]->Points->Clear();
backgroundWorker1->RunWorkerAsync();
}
else
{
this->textBox1->Text="Warning: port is busy or isn't open";
timer1->Enabled=false;
interval->Enabled=false;
}
}
catch(UnauthorizedAccessException^)
{
this->textBox1->Text="Unauthorized access";
timer1->Enabled=false;
interval->Enabled=false;
}
}
}
}
private: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
while(!backgroundWorker1->CancellationPending){
if(backgroundWorker1->CancellationPending){
e->Cancel=true;
return;
}
t+=period;
if(t<10*period){
this->chart1->ChartAreas["ChartArea1"]->AxisX->Minimum=0;
this->chart1->ChartAreas["ChartArea1"]->AxisX->Maximum=t+10*period;
}
else {
this->chart1->ChartAreas["ChartArea1"]->AxisX->Minimum=t-10*period;
this->chart1->ChartAreas["ChartArea1"]->AxisX->Maximum=t+10*period;
}
*myStream<<t<<";";
for (int n=0;n<8;n++){
adc_array[n]= this->serialPort1->ReadByte();
}
Array::Copy(adc_array,ADC,8);
for(int f=0; f<8; f++){
*myStream<<ADC[f]<<";";
}
*myStream<<endl;
backgroundWorker1->ReportProgress(t);
}
}
private: System::Void backgroundWorker1_ProgressChanged(System::Object^ sender, System::ComponentModel::ProgressChangedEventArgs^ e) {
chart1->Series["ADC1"]->Points->AddXY(t,ADC[0]);
chart1->Series["ADC2"]->Points->AddXY(t,ADC[1]);
chart1->Series["ADC3"]->Points->AddXY(t,ADC[2]);
chart1->Series["ADC4"]->Points->AddXY(t,ADC[3]);
chart1->Series["ADC5"]->Points->AddXY(t,ADC[4]);
chart1->Series["ADC6"]->Points->AddXY(t,ADC[5]);
chart1->Series["ADC7"]->Points->AddXY(t,ADC[6]);
chart1->Series["ADC8"]->Points->AddXY(t,ADC[7]);
}
the user is allowed to define intervals in seconds for data acquisition (in the code this interval is w after conversion to double). In this case, the program sends a pulse to the MCU requesting a new data transmission. So far, I have been testing this for 1 second intervals (note, during each interval the MCU sends 8 frames, each representing an ADC). However, I need to get this to run for 10ms intervals at some point. Will this be possible? Any idea on how to solve the few problems I mentioned at the beginning?
Thanks in advance
UPDATE
Just to give you an idea of what's happening:
I commented the charting part and ran the program for about 5 minutes, with a reading interval of 1s. So I expected to get around 5x60=300 values in the output file, but I only got 39 (i.e. starting from 1s till 39s). The program was still running, but the data were not getting stored anymore.
Testing was done in release mode and not debug mode. In debug mode, setting a break point under serialport->readbyte(), does not reproduce the problem. My guess is it's a timing issue between program and MCU.
You are making several standard mistakes. First off, do NOT unplug the cable when the port is opened. Many USB emulators don't know how to deal with that, the FTDI driver is particularly notorious about that. They just make the port disappear while it is in use, this invariably gives code that uses the port a severe heart attack. An uncatchable exception is common.
Secondly, you are accessing properties of a class that is not thread-safe in a worker thread. The Chart control was made to be used only in a UI thread, accessing the ChartAreas property in a worker is going to buy you a lot of misery. Getting an InvalidOperationException is pretty typical when you violate threading requirements, it is however not consistently implemented. Nastiness includes random AccessViolationExceptions, corrupted data and deadlock.
Third, you are setting completely unrealistic goals. Pursuing an update every 10 milliseconds is pointless, the human eye cannot perceive that. Anything past 50 milliseconds just turns into a blur. Something that is taken advantage of when you watch a movie in the cinema, it displays at 24 frames per second. The failure mode for that is unpleasant as well, you'll eventually reach a point where you are pummeling the UI thread (or the Chart control) with more updates than it can process. The side effect is that the UI stops painting itself, it is too busy trying to keep up with the deluge of invoke requests. And the amount of memory your program consumes keeps building, the update queue grows without bounds. That does eventually end with an OOM exception, it takes a while to consume 2 jiggabytes however. You will need to prevent this from happening, you need to throttle the rate at which you invoke. A simple thread-safe counter can take care of that.
Forth, you are accessing the data you gather in more than one thread without taking care of thread-safety. The ADC array content is being changed by the worker while the UI thread is reading it. Various amounts of misery from that, bad data at a minimum. A simply workaround is to pass a copy of the data to the ReportProgress method. In general, address these kind of threading problems by using pull instead of push. Get rid of the fire-hose problem by having the UI thread pace the requests instead of trying to have the UI thread keep up.
I want to monitor all the open windows under X11. Currently, I'm doing this as follows:
Initially walking the whole tree by recursively calling XQueryTree from the root window
Listening for substructure changes on the whole desktop: XSelectInput( display, root_window, SubstructureNotifyMask | PropertyChangeMask )
Handling all MapNotify, UnmapNotify and DestroyNotify events, updating my own list of windows in the process
I'm mainly worried about point 1. During the recursion, XQueryTree will be called multiple times. Is there any way to ensure that the tree does not change in the meantime? In other words, to get a 'snapshot' of the whole tree at one point in time?
Also, I've noticed that under some X11 systems, not all events arrive correctly. For example, when opening a new window on the desktop, MapNotify for that window may never arrive at my monitoring application. How can this be? Is it possible that it is thrown away before arriving?
Update:
I've written a small program that will monitor X events on the root window (see below). Now, when I run this program and start and quit xcalc, I get the following output:
Reparented: 0x4a0005b to 0x1001e40
Mapped : 0x1001e40
Destroyed : 0x1001e40
That's it. I'm never notified of the real window (0x4a0005b) being destroyed. Not even of it being mapped! Can anyone tell me why not? Does SubStructureNotifyMask only cause events of direct subwindows to be sent instead of the whole subtree?
By the way, this apparently does not happen when Compiz is running. Then no reparenting is done:
Mapped : 0x4a0005b
Mapped : 0x4e00233
Destroyed : 0x4a0005b
Destroyed : 0x4e00233
Monitoring program source:
#include <X11/Xlib.h>
#include <cstdio>
int main()
{
Display *display;
Window rootwin;
display = XOpenDisplay( NULL );
rootwin = DefaultRootWindow( display );
XSelectInput( display, rootwin, SubstructureNotifyMask );
XEvent event;
while ( 1 ) {
XNextEvent( display, &event );
if ( event.type == MapNotify ) {
XMapEvent *mapevent = (XMapEvent *)&event;
printf( "Mapped : 0x%x\n", (unsigned int)(mapevent->window) );
}
if ( event.type == DestroyNotify ) {
XDestroyWindowEvent *destroywindowevent = (XDestroyWindowEvent *)&event;
printf( "Destroyed : 0x%x\n", (unsigned int)(destroywindowevent->window) );
}
if ( event.type == ReparentNotify ) {
XReparentEvent *reparentevent = (XReparentEvent *)&event;
printf( "Reparented: 0x%x to 0x%x\n", (unsigned int)(reparentevent->window), (unsigned int)(reparentevent->parent) );
}
}
return 0;
}
Have a look at xwininfo.
You might also like xprop and xspy for getting more info.
Update: Yep. Try using xwininfo and -root with either -tree or -children to get all windows involved.
And changes can be tracked with xprop -spy.
I believe that grabbing the X server (XGrabServer(3)) will prevent changes to the window hierarchy. It is a bit heavy handed though, so you should probably only do it if you really need it.
For an example of code that walks the window hierarchy, builds up a tree, uses window events to keep it up to date, and ignores X protocol errors which are unavoidable due to races, see the file src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp in the source code for VirtualBox.
X11 is a remote protocol. This means when you query the X server for any information, you always get your own copy. Your copy never changes when the X server updates its internal data structures.
This means the tree won't suddenly change while you traverse it but when you use the information in it (like examining a window), that information might be stale (someone might have closed the window). That is why you need to do proper error handling.