How to make child widgets' corners rounded to match the outlines of the main GTK window?

Hello!
I’m trying to make a frameless GTK window with a Qt widget embedded inside it, but the widget ends up not matching the outline of the main GTK window. Is there any way to fix this?

Here’s a complete example of the code I’m using:

GtkMainWindow.pro

QT += core gui widgets
CONFIG += c++11
CONFIG += app_bundle
TEMPLATE = app
TARGET = gtkmainwindow

CONFIG  += link_pkgconfig
PKGCONFIG += gtk+-3.0

SOURCES += main.cpp gtkmainwindow.cpp
HEADERS += gtkmainwindow.h

gtkmainwindow.h

#ifndef GTKMAINWINDOW_H
#define GTKMAINWINDOW_H

#include <QWidget>
    
class GtkMainWindow
{
public:
    GtkMainWindow();
    ~GtkMainWindow();
    void setCentralWidget(QWidget *w);
    void show();

private:
    class GtkMainWindowPrivate;
    GtkMainWindowPrivate *pimpl;
};

#endif // GTKMAINWINDOW_H

gtkmainwindow.cpp

#include <gtk/gtk.h>
#include "gtkmainwindow.h"
#include <QVBoxLayout>
#include <gtk/gtkx.h>

gboolean on_configure_event(GtkWidget *wgt, GdkEvent *ev, gpointer data)
{
    if (QWidget *w = (QWidget*)data) {
        gint x = 0, y = 0;
        gtk_window_get_size(GTK_WINDOW(wgt), &x, &y);
        w->resize(x, y);
    }
    return FALSE;
}
   
class GtkMainWindow::GtkMainWindowPrivate
{
public:
    GtkMainWindowPrivate() {}
    ~GtkMainWindowPrivate() {}
    GtkWidget *window = nullptr;
    QWidget *w = nullptr;
};

GtkMainWindow::GtkMainWindow() :
    pimpl(new GtkMainWindowPrivate)
{
    gtk_init(NULL, NULL);
    pimpl->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(pimpl->window), "GtkMainWindow");
    gtk_window_set_default_size(GTK_WINDOW(pimpl->window), 600, 400);
    gtk_window_set_position(GTK_WINDOW(pimpl->window), GtkWindowPosition::GTK_WIN_POS_CENTER);
    g_signal_connect(G_OBJECT(pimpl->window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    GtkCssProvider *provider = gtk_css_provider_new();
    gtk_css_provider_load_from_data(provider, "decoration {border: 0px solid #ff0000; border-radius: 8px 8px 0px 0px;}", -1, NULL);
    gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

    GtkWidget *header = gtk_header_bar_new();
    gtk_window_set_titlebar(GTK_WINDOW(pimpl->window), header);
    gtk_widget_destroy(header); // remove header
    
    GtkWidget *socket = gtk_socket_new();
    gtk_widget_show(socket);
    gtk_container_add(GTK_CONTAINER(pimpl->window), socket);

    pimpl->w = new QWidget(nullptr, Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
    g_signal_connect(G_OBJECT(pimpl->window), "configure-event", G_CALLBACK(on_configure_event), pimpl->w);
    QVBoxLayout *lut = new QVBoxLayout;
    lut->setContentsMargins(0,0,0,0);
    pimpl->w->setLayout(lut);
    pimpl->w->createWinId();
    gtk_socket_add_id(GTK_SOCKET(socket), (Window)pimpl->w->winId());
}

GtkMainWindow::~GtkMainWindow()
{
    delete pimpl;
}

void GtkMainWindow::setCentralWidget(QWidget *w)
{
    pimpl->w->layout()->addWidget(w);
}

void GtkMainWindow::show()
{
    gtk_widget_show_all(pimpl->window);
    pimpl->w->show();
}

main.cpp

#include <QApplication>
#include <QWidget>
#include <QGridLayout>
#include <QPushButton>
#include <QSpacerItem>
#include "gtkmainwindow.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    GtkMainWindow wnd;
    QWidget *w = new QWidget;
    w->setStyleSheet("QWidget{background: #555555;} QPushButton{min-height: 24px; background: #888888; border: 0px solid #00ffff;}");
    QGridLayout *gl = new QGridLayout;
    w->setLayout(gl);
    gl->setContentsMargins(0,0,0,0);
    QPushButton *btn = new QPushButton("Button");
    gl->addWidget(btn, 0, 0, 1, 1);
    gl->addItem(new QSpacerItem(5, 5, QSizePolicy::Expanding, QSizePolicy::Expanding), 1, 0, 1, 1);
    gl->addWidget(new QPushButton("Button"), 2, 0, 1, 1);
    wnd.setCentralWidget(w);
    wnd.show();
    return app.exec();
}

There was an idea to use gdk_window_shape_combine_region() but it is not clear how exactly to do this and whether it would help.

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