I am trying to drag an undecorated window in GLFW but am encountering some event lag, even though I am using glfwWaitEvents()
I have a cursor position callback, and a simple loop:
// register a cursor position callback
glfwSetCursorPosCallback(win, cursor_pos_callback);
// then loop..
while(!glfwWindowShouldClose(win)) {
glfwWaitEvents();
... some rendering...
glfwSwapBuffers(win);
}
My cursor callback does some simple tracking of the deltas and updates window position.
cursor_pos_callback(GLFWwindow *win, double xpos, double ypos) {
// figure out delta_x and delta_y based on cursor previous position
int delta_x, delta_y;
// update window position
if (window_drag_active) {
int x,y;
glfwGetWindowPos(window, &x, &y);
glfwSetWindowPos(window, x + delta_x, y + delta_y);
}
}
Here is what the deltas look like when I'm dragging in a straight line
delta_x: 10 delta_y: 0 | xpos: 649 ypos: 55
delta_x: 5 delta_y: -1 | xpos: 654 ypos: 54
delta_x: 5 delta_y: 3 | xpos: 659 ypos: 57
delta_x: 5 delta_y: 2 | xpos: 664 ypos: 59
delta_x: -5 delta_y: -2 | xpos: 659 ypos: 57
delta_x: 4 delta_y: 0 | xpos: 663 ypos: 57
delta_x: 2 delta_y: 0 | xpos: 665 ypos: 57
delta_x: -3 delta_y: -3 | xpos: 662 ypos: 54
delta_x: 2 delta_y: 1 | xpos: 664 ypos: 55
delta_x: 2 delta_y: 0 | xpos: 666 ypos: 55
delta_x: 3 delta_y: 2 | xpos: 669 ypos: 57
delta_x: 1 delta_y: -1 | xpos: 670 ypos: 56
delta_x: 2 delta_y: -1 | xpos: 672 ypos: 55
delta_x: 7 delta_y: 3 | xpos: 679 ypos: 58
delta_x: 2 delta_y: -1 | xpos: 681 ypos: 57
delta_x: -2 delta_y: -3 | xpos: 679 ypos: 54
delta_x: 0 delta_y: -2 | xpos: 679 ypos: 52
delta_x: 3 delta_y: 3 | xpos: 682 ypos: 55
delta_x: -5 delta_y: -3 | xpos: 677 ypos: 52
The xpos
increments as it should, then every so often it goes backwards (stale event?)
Maybe my window movement is not synced up with the cursor?
The result is the when I drag the window, it shakes violently and I can barely move it anywhere...
Update: I have also tried moving the glfwSetWindowPos
logic into the main loop as well with no success—I still get the same shaking and stuttering.
Update: When I comment out the glfwSetWindowPos()
the window no longer moves (of course) but the event stream is now consistent.
This leads me to think that the moving of the window, when done quickly is causing the jerking motion (ie. 2 steps forward, 1 step backwards).
I suspect your problem is that the
cursor_pos_callback
receives the cursor position relative to the window and moving the window has an immediate effect on that position.Suppose you are moving the cursor diagonally at a constant rate. If, over one tick, the cursor moves from relative position (100,100) to (105,105), you calculate
delta_x=5
anddelta_y=5
. You then move the window. The process of moving the window then instantaneously changes the relative coordinates from (105,105) back to (100,100), and on the next tick, even though you've moved to position (110,110) relative to the original window location, you are only at relative position (105,105) with respect to the new window location, so you calculatedelta_x=0
anddelta_y=0
from your previous position (plus some random jittery noise) even though you've actually moved an addition 5 units along each axis.Instead, modify your algorithm to maintain a constant relative cursor position. On the drag start, store the relative cursor position (say (100,100)). Now, at each tick, calculate where you need to position the window to move the cursor back to that fixed, relative position. So, if the cursor has moved to (112,108), move the window by (+12,+8) to put the cursor back at (100,100). At a later tick, if the cursor has moved to (108,106), don't try to calculate a delta from (112,108); instead, compare it to the original (100,100) starting point and move the window by (+8,+6). It would be something like the following: