I am attempting to re-parent a child window Gtk::Window so that I can emulate the deprecated GTKMM 4 call to position the window in the centre of the parent (which was present in GTKMM 3). I have searched for XReparentWindow posts and the only relevant one advised to use XSetTransientForHint this which did not work for me. The code that I have written is:
void MyGtk::Window_Centre_Child_On_Parent(
Gtk::Window *parent,
Gtk::Window *child
)
{
int child_height;
int child_width;
int parent_height;
int parent_width;
int position_x;
int position_y;
//
//First we must validate all parameters and terminate if any fail.
//
assert(parent);
assert(child);
//
//Now we need to fetch the size of the child window so that we can then
//re-parent the window at the centre of the parent window thus emulating
//the GTKMM 3 set position call. This has been deprecated in GTKMM 4.
//
Widget_Get_Size(
child,
child_width,
child_height
);
//
//Now we need to ensure that the above returned sensible values and we
//terminate if not.
//
assert(child_height > 0);
assert(child_width > 0);
//
//Now we need to fetch the size of the parent window so that we can then
//re-parent the window at the centre of the parent window thus emulating
//the GTKMM 3 set position call. This has been deprecated in GTKMM 4.
//
Widget_Get_Size(
parent,
parent_width,
parent_height
);
//
//Now we need to ensure that the above returned sensible values and we
//terminate if not.
//
assert(parent_height > 0);
assert(parent_width > 0);
//
//Now we need to fetch the X windows ID for the child window. This ID
//is what is used to refer to windows within the X windows library.
//
auto child_window = Window_Get_X_Windows_ID(child);
assert(child_window > 0);
//
//Now we need to fetch the X windows ID for the parent window. This ID
//is what is used to refer to windows within the X windows library.
//
auto parent_window = Window_Get_X_Windows_ID(parent);
assert(parent_window > 0);
//
//Now we need to open the X windows display for the X server instance
//that is running. We could also use the DISPLAY environment variable
//but the below is faster as it does not have to fetch the environment.
//
auto display = XOpenDisplay(XDisplayName(nullptr));
assert(display);
//
//Now we need to calculate where to place the child window within the
//parent window. This depends on the size of the child as using the
//centre of the parent can mean that the child window does not fit on
//the display.
//
position_x = abs(
std::min(
parent_width / 2,
(parent_width - child_width) / 2
)
);
position_y = abs(
std::min(
parent_height / 2,
(parent_height - child_height) / 2
)
);
//
//Now we need to ensure that the child window will be transient for the
//parent window.
//
XSetTransientForHint(
display,
child_window,
parent_window
);
//
//Now we need to re-parent the child window to the parent window and we
//set the (X, Y) co-ordinate such that the top left corner of the child
//window will be in the centre of the parent window.
//
XReparentWindow(
display,
child_window,
parent_window,
position_x,
position_y
);
//
//Now we need to flush any changes made to the display.
//
XFlush(display);
//
//Finally, we need to close the display and thus release any resources
//associated with it.
//
XCloseDisplay(display);
}
What I see is that all of the decorations for the child window are removed but if I do not use the above code and simply display the dialog the decorations are rendered correctly. I would very much appreciate any hints on how to solve this problem.
Searched for XReparentWindow within stack overflow and found a possible solution (see link) that did not work for me.
From further research it appears that the reparent and set transient for hint routines will always remove the decorations. So to solve the problem I changed the above code to the below.
So first you obtain your x window coordinates with respect to the root window, perform some calculations to centre the window on the parent and then move the window. Not exactly what I wanted as there is a flicker before the child window centres (due to the realising of the window in gtkmm) but at least I can emulate the obsolete call.