microsoft / wslg

Enabling the Windows Subsystem for Linux to include support for Wayland and X server related scenarios
MIT License
10.06k stars 302 forks source link

gtk_window_get_position returns always (0, 0) in X11 mode #355

Open MikeYeager opened 3 years ago

MikeYeager commented 3 years ago

Environment

Microsoft Windows [Version 10.0.22000.65]
Release:        20.04

image

Steps to reproduce

Calls to gtk_window_get_position(GTK_WINDOW(_window), x, y); always return 0, 0 in WSLg, but return proper values on a Linux machine. I'm not sure if this is by design, not working properly or if there is a different method for retrieving this info in WSLg.

Expected behavior

I would expect x and y coordinates appropriate for the display to be returned.

Actual behavior

Always return 0, 0.

spronovo commented 3 years ago

Hi @MikeYeager, do you have a code sample demonstrating this? Are you running your application in X11 or Wayland mode?

In X11 mode i would expect your application to be able to read and set the position of its windows under WSLg the same as you can under any other X11 server.

In Wayland mode, the compositor owns windows positioning and an application can't change it, so getting 0,0 would make sense there.

WSLg is one of the first Linux environment which enables Wayland by default. My suspicion is that you are running your application on a Linux system which default to X11 mode (most do)... but running the same application in Wayland mode under WSLg and thus why you are seeing a difference. I also suspect you would see the same behavior running on a native Linux environment which default to Wayland. For example, Ubuntu is in the process of switching to Wayland by default for Hippo/21.04, but not all system default to Wayland yet (https://askubuntu.com/questions/1338874/ubuntu-21-04-how-to-enable-wayland).

To test out that theory, could you try the following to force X11 mode for your application under WSLg. Before launching your application, unset WAYLAND_DISPLAY... that will force GTK to go into X11 mode. Alternatively you can use export GDK_BACKEND=x11 to select the backend for your application and setting it to x11 before running it.

MikeYeager commented 3 years ago

@spronovo Thank you for the reply. I tried unset WAYLAND_DISPLAY, but still no luck. echo $XDG_SESSION_TYPE doesn't display anything. Is there anything else I can try? I'm still pretty new to X11 and Wayland.

hideyukn88 commented 3 years ago

@MikeYeager, I confirmed the issue, it does return 0, 0 in X11 mode, and in Wayland mode, it returns offset of window decoration. Thanks for reporting the issue.

image

hideyukn88 commented 3 years ago

For reference, here is the test program I used. It creates application window with size of 500x500 and placed it at center of screen. @MikeYeager , is this close enough to what you are doing?

In X11 mode,

In Wayland mode,

How to compile below test code.

gcc -Wall -O -o gtk_window_test gtk_window_test.c `pkg-config --cflags --libs gtk+-3.0`

gtk_window_test.c

#include <gtk/gtk.h>

GtkWidget *window = NULL;

static void app_activate(GtkApplication* app, gpointer user_data)
{
    window = gtk_application_window_new(app);

    gtk_window_set_title(GTK_WINDOW(window), "Test Window");
    gtk_window_set_default_size(GTK_WINDOW(window), 500, 500);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_widget_show_all(window);
}

static void app_activate_after(GtkApplication* app, gpointer user_data)
{
    gint x = 0, y = 0, w = 0, h = 0;

    gtk_window_get_position(GTK_WINDOW(window), &x, &y);
    gtk_window_get_size(GTK_WINDOW(window), &w, &h);
    fprintf(stderr, "window is at (%d,%d) - (%dx%d)\n", x, y, w, h);
}

int main(int argc, char **argv)
{
    GtkApplication *app;
    int status;

    app = gtk_application_new("com.gtk.window", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(app_activate), NULL);
    g_signal_connect_after(app, "activate", G_CALLBACK(app_activate_after), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);

    return status;
}
MikeYeager commented 3 years ago

Yes, that’s very close to our code.