The best or most portable way to check for X11 or Wayland for Window geometry access (on X11)?

I do not want to discuss the previous issues about removing gtk_winget_set/get_size/position here.
Anyhow for some kind of larger applications utilizing many different control windows required in a custom organized way (a scanning probe microscope control) I do make use of the workspace to organize my work flow. And when opening the software every time having to reorganize 10 or more windows is unacceptable.

Thus I depend on my own house keeping here to store and restore the geometry of various windows via gsettings.

As it took me a while to find the hopefully correct way (X11) to access the X window handle and display associated with a gtk window I like to share my solution and also ask if that is an acceptable way as I could not find anything about that in the gtk or gdk documentation. But had to dig into the header files and take some guesses.

This is the way I found to access X Window and Display for a given gtk window and then call the basic X functions to do the job (Move, Resize or Get Geometry), see code below:

Window   xw = GDK_SURFACE_XID (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
Display *xd = GDK_SURFACE_XDISPLAY (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
XMoveWindow (xd, xw, (int)window_geometry[WGEO_XPOS], (int)window_geometry[WGEO_YPOS]);

It turned out been fairly simple to do as you see above. My only issue is how to correctly at run time check for wayland, X11 or anything else? I tried some macros, but did not made this part work yet. The compile time directives I found also not working right. And on Wayland it’s crashing – it should just skip it. Even I wish there would be some way to “talk to” Wayland and tell it to do this.

#include <gtk/gtk.h>

#define ENABLE_GXSM_WINDOW_MANAGEMENT
#ifdef ENABLE_GXSM_WINDOW_MANAGEMENT
# ifdef GDK_WINDOWING_X11
#  include <gdk/x11/gdkx.h>
# endif
# ifdef GDK_WINDOWING_WAYLAND
#  include <gdk/wayland/gdkwayland.h>
# endif
#endi

...


void AppBase::position_auto (){
#ifdef ENABLE_GXSM_WINDOW_MANAGEMENT
        if (window_geometry)
                if (window_geometry[WGEO_FLAG]){
                        // GTK3:
                        // gtk_window_move (GTK_WINDOW (window), window_geometry[WGEO_XPOS], window_geometry[WGEO_YPOS]);
                        // g_message ("SORRY GTK4 can't do it -- Requested Window Position [%s: %d, %d]   -- no gtk_window_move ().", window_key, window_geometry[WGEO_XPOS], window_geometry[WGEO_YPOS]);
                        //g_message ("Requested Window Position [%s] XY %d, %d", window_key, window_geometry[WGEO_XPOS], window_geometry[WGEO_YPOS]);
                        
# ifdef GDK_WINDOWING_X11
                        if (1){ //GDK_IS_X11_DISPLAY (display){
                                Window   xw = GDK_SURFACE_XID (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
                                Display *xd = GDK_SURFACE_XDISPLAY (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
                                XMoveWindow (xd, xw, (int)window_geometry[WGEO_XPOS], (int)window_geometry[WGEO_YPOS]);
                        } else
# endif
# ifdef GDK_WINDOWING_WAYLAND
                                if (1){ // GDK_IS_WAYLAND_DISPLAY (display)){
                                        g_message ("SORRY WAYLAND DOES NOT GIVE ANY ACCESS TO WINDOW GEOMETRY.;");
                                } else
                                        g_error ("Unsupported GDK backend");
                }
# endif
#endif
}

void AppBase::resize_auto (){
#ifdef ENABLE_GXSM_WINDOW_MANAGEMENT
        if (window_geometry)
                if (window_geometry[WGEO_FLAG]){
                        // GTK3:
                        // gtk_window_resize (GTK_WINDOW (window), (int)window_geometry[WGEO_WIDTH], (int)window_geometry[WGEO_HEIGHT]);

                        // trying this... not working
                        // gtk_window_set_default_size (GTK_WINDOW (window), (int)window_geometry[WGEO_WIDTH], (int)window_geometry[WGEO_HEIGHT]);

                        // g_message ("SORRY GTK4 can't do it -- Requested Window Resize [%s: %d, %d]   -- no gtk_window_resize ().", window_key, window_geometry[WGEO_WIDTH], window_geometry[WGEO_HEIGHT]);
                        //g_message ("Requested Window Resize [%s] WH %d, %d", window_key, window_geometry[WGEO_WIDTH], window_geometry[WGEO_HEIGHT]);

# ifdef GDK_WINDOWING_X11
                        if (1){ //GDK_IS_X11_DISPLAY (display){
                                Window   xw = GDK_SURFACE_XID (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
                                Display *xd = GDK_SURFACE_XDISPLAY (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
                                if ((unsigned int)window_geometry[WGEO_WIDTH] > 0 && (unsigned int)window_geometry[WGEO_HEIGHT] > 0)
                                        XResizeWindow (xd, xw,  (unsigned int)window_geometry[WGEO_WIDTH],  (unsigned int)window_geometry[WGEO_HEIGHT]);
                        } else
# endif
# ifdef GDK_WINDOWING_WAYLAND
                        if (1){ //GDK_IS_WAYLAND_DISPLAY (display)){
                                g_message ("SORRY WAYLAND DOES NOT GIVE ANY ACCESS TO WINDOW GEOMETRY.;");
                        } else
# endif
                                g_error ("Unsupported GDK backend");
                }
#endif
}


void AppBase::SaveGeometry(gboolean store_to_settings){
#ifdef ENABLE_GXSM_WINDOW_MANAGEMENT
	XSM_DEBUG (DBG_L2, "** AppBase::SaveGeometry of " << window_key);

        // g_message ("AutoSave Window Geometry: %s", window_key);

        // just in case it was not loaded right
        if (!window_geometry)
                window_geometry = g_new (gint32, WGEO_SIZE);
        
        window_geometry[WGEO_FLAG] = 1;
        window_geometry[WGEO_SHOW] = showstate;
        //g_message ("SORRY GTK4 can't do it -- no gtk_window_get_position (GTK_WINDOW (window), &window_geometry[WGEO_XPOS], &window_geometry[WGEO_YPOS]);");
        //g_message ("SORRY GTK4 can't do it -- no gtk_window_get_size (GTK_WINDOW (window), &window_geometry[WGEO_WIDTH], &window_geometry[WGEO_HEIGHT]);");
        //gtk_window_get_position (GTK_WINDOW (window), &window_geometry[WGEO_XPOS], &window_geometry[WGEO_YPOS]); 

# ifdef GDK_WINDOWING_X11
        if (1){ // GDK_IS_X11_DISPLAY (display){
                Window   xw = GDK_SURFACE_XID (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
                Display *xd = GDK_SURFACE_XDISPLAY (GDK_SURFACE (gtk_native_get_surface(GTK_NATIVE (window))));
                Window root;
                int x, y;
                unsigned int width, height;
                unsigned int border_width;
                unsigned int depth;
                XGetGeometry (xd, xw, &root, &x, &y, &width, &height, &border_width, &depth);
                window_geometry[WGEO_XPOS]=x;
                window_geometry[WGEO_YPOS]=y;
                window_geometry[WGEO_WIDTH]=width;
                window_geometry[WGEO_HEIGHT]=height;
                //g_message ("Window Geometry [%s]: XY %d, %d; WH %d, %d", window_key, x, y, width, height);
                // Status = XGetGeometry (display, d, root_return, x_return, y_return, width_return, height_return, border_width_return, depth_return)
                //        Display *display;
                //        Drawable d;
                //        Window *root_return;
                //        int *x_return, *y_return;
                //        unsigned int *width_return, *height_return;
                //        unsigned int *border_width_return;
                //        unsigned int *depth_return;
        } else
# endif
# ifdef GDK_WINDOWING_WAYLAND
                if (1){ //GDK_IS_WAYLAND_DISPLAY (display)){
                        g_message ("SORRY WAYLAND DOES NOT GIVE ANY ACCESS TO WINDOW GEOMETRY.;");
                } else
# endif
                        g_error ("Unsupported GDK backend");

        if (store_to_settings && window_key){
                GVariant *storage = g_variant_new_fixed_array (g_variant_type_new ("i"), window_geometry, WGEO_SIZE, sizeof (gint32));
                g_settings_set_value (geometry_settings, window_key, storage);
                //g_free (storage); // ??
        }
#endif
}

from the GXSM project and file here:

https://sourceforge.net/p/gxsm/svn/HEAD/tree/trunk/Gxsm4/core-source/gapp_service.C

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.