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