I made a mistake in my previous post :
for (int i = XPending(display); i > 0; --i)
With >= 0 the program was waiting for a new event to be queued and thus blocked the program execution for several ms (due to the behavior of XNextEvent).
Now I have a decent frame rate !
Though there is still one 103 event present in the queue for each tick ...
What happens if you make that int i = std::min(XPending(display, 10)? Nothing, because most of the time there is less than 10 events in the queue per tick.
The problem was the behavior of the loop that will always consume new events posted during the current tick, making it last forever when spammed.
Moreover the standard behavior of XPending may be to wait for a new event when the queue is empty... (not so clear in the man about that
http://www.manpagez.com/man/3/XPending/).
Anyway, nice work on Gosu, after that little fix everything went ok :)