How to get the cursor position on a glfwWindow?

Hi!
I am using Ubuntu 22.04.

This is an OptiX rendered scene, showing in GLFwWindow. I can currently interact with the secne using the left mouse button (pressing and moving around). In addition to that, I also want to get the cursor position while the cursor is on the window.

static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    double xpos, ypos;
    glfwGetCursorPos(window, &xpos, &ypos);
    std::cout << "Position: (" << xpos <<":"  << ypos << ")";
}

... 
int main(){
...
            glfwSetInputMode            (window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
            glfwSetCursorPosCallback    ( window, cursor_position_callback); // doing nothing for now
            glfwMakeContextCurrent(window);
            glfwSwapInterval(1);
...
}

However, I am not getting any output at all. I want to see the cursor positions in the console output. What I am doing wrong?

The cursor position callback should be being called even with GLFW_CURSOR_DISABLED is set.

You’ve not shown your console output, but I’m guessing when you move your mouse you don’t see any output? Have you checked that std::cout works (add some init output), and hasn’t been redirected (I don’t know what the rest of your program does, and I’m not sure if the OptiX framework could cause issues with cout). Have you tried placing a debug breakpoint in the callback? You may also want to check if polling glfwGetCursorPos in your render loop works. SInce it looks like you have text output on the screen perhaps it’s worth adding mouse position data to that.

Note that you don’t need to call glfwGetCursorPos in your callback, this can be:

static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    std::cout << "Position: (" << xpos <<":"  << ypos << ")";
}

If you have further problems check that the events.c test code works on your system, then alter the code to set GLFW_CURSOR_DISABLED (perhaps in the keycallback when pressing a key to toggle it, or just when after window creation). The easiest way to build events.c is with CMake.

Let me know how you get on, along with the OS system you are running on if you are unable to resolve this.

1 Like

Thanks @dougbinks for your advice. Yes, previously I could not see any output in the console. According your advice and the events.c has solved my proble, here is the code snippet that allow both interaction with the scene and coursor output:

//
// BM--------------------------------------------------------------------------------------------------------------
// mouse movement+ and cursor output
typedef struct
{
    GLFWwindow* window;
    int number;
    int closeable;
} Slot;

static unsigned int counter = 0;

static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    // these three lines were default at event.c code
    Slot* slot = static_cast<Slot *>(glfwGetWindowUserPointer(window));
    printf("%08x to %i at %0.3f: Cursor position: %f %f\n",
           counter++, slot->number, glfwGetTime(), xpos, ypos);

    // these code copied from "cursorPosCallback" default optix sample function, commented above
    Params* params = static_cast<Params*>( glfwGetWindowUserPointer( window ) );

    if( mouse_button == GLFW_MOUSE_BUTTON_LEFT )
    {
        trackball.setViewMode( sutil::Trackball::LookAtFixed );
        trackball.updateTracking( static_cast<int>( xpos ), static_cast<int>( ypos ), params->width, params->height );
        camera_changed = true;
    }
    else if( mouse_button == GLFW_MOUSE_BUTTON_RIGHT )
    {
        trackball.setViewMode( sutil::Trackball::EyeFixed );
        trackball.updateTracking( static_cast<int>( xpos ), static_cast<int>( ypos ), params->width, params->height );
        camera_changed = true;
    }
}

...
int main(){
            glfwSetCursorPosCallback(window, cursor_position_callback);
...
}

Hi @bipul-mohanto,

Glad you’ve solved your problem.

You don’t need to cast the user pointer to Slot* as this is specific to the example (so you don’t need the Slot struct declaration). Indeed, the user pointer appears to be set to the Params* type by the OpiX framework, so it can’t be a Slot*.

So your code would be:

static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    printf("Time %0.3f: Cursor position: %f %f\n",
           glfwGetTime(), xpos, ypos);

    // these code copied from "cursorPosCallback" default optix sample function, commented above
    Params* params = static_cast<Params*>( glfwGetWindowUserPointer( window ) );

    if( mouse_button == GLFW_MOUSE_BUTTON_LEFT )
    {
        trackball.setViewMode( sutil::Trackball::LookAtFixed );
        trackball.updateTracking( static_cast<int>( xpos ), static_cast<int>( ypos ), params->width, params->height );
        camera_changed = true;
    }
    else if( mouse_button == GLFW_MOUSE_BUTTON_RIGHT )
    {
        trackball.setViewMode( sutil::Trackball::EyeFixed );
        trackball.updateTracking( static_cast<int>( xpos ), static_cast<int>( ypos ), params->width, params->height );
        camera_changed = true;
    }
}

...
int main(){
            glfwSetCursorPosCallback(window, cursor_position_callback);
...
}

Even better. Thanks again.

If I may ask a very basic question, now I can see the cursor position (x,y) in the console. But if I want to use these values for different purposes inside the main rendering loop, how can I access the data? For example, if I want a dynamic light source where the x and y coordinates will be move according to the cursor:

state.params.light.corner   = make_float3( xpos, ypos, 227.0f );

In more complex scenarios, I actually want to use the cursor position as an alternative of eye tracker to test the foveated rendering algorithms. To access the cursor position do I need to use C++ features like std::pair or std::tuple? Or is there any easier way?

You don’t need to use C++ std:: types, you just need to be able to access the data in your main rendering loop. There are several ways to do this, I’ll outline a few below.

The simplest is to call glfwGetCursorPosition in the function you need access to the position.

The next easiest would be to use global data (either in the main.cpp file along with the callback or in as a static members of a struct in a header):

static double g_xpos, g_ypos;

static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    g_xpos = xpos;
    g_ypos = ypos;
....
}

...
int main(){
    glfwSetCursorPosCallback(window, cursor_position_callback);
...
    state.params.light.corner   = make_float3( g_xpos, g_ypos, 227.0f );
}

The third would be to alter the Params struct to add xpos and ypos data and set that in the callback, or alter the user pointer to be a struct which includes your own data along with a pointer to the Params struct, but I don’t know if this is easy with the framework you are using.

1 Like

Thank you once again, the glfw library is really awesome. I did not learn it before, and now the more I am exploring, the more I am thrilled. Your first suggestion solved my query. Here is my solution:

                    double cposx, cposy;
                    glfwGetCursorPos(window, &cposx, &cposy);
                    std::cout << "INSIDE RENDER LOOP   " << "cursor x value: " <<cposx << "\t cursor y value: " <<cposy  << std::endl;