LINUX.ORG.RU

История изменений

Исправление Darth_Revan, (текущая версия) :

Я совершенно забыл, что GdkWindow не обязан быть квадратным.
Реализовал – может, кому-нибудь пригодится:

#include <gtkmm.h>

static bool
on_widget_draw(Gtk::Widget                  &widget,
               Cairo::RefPtr<Cairo::Context> cr)
{
    const int w = widget.get_allocated_width();
    const int h = widget.get_allocated_height();

    auto surface = widget.get_window()->create_similar_surface(
        Cairo::CONTENT_COLOR_ALPHA,
        w,
        h
    );

    auto cr2 = Cairo::Context::create(surface);
    cr2->set_operator(Cairo::OPERATOR_SOURCE);

    cr2->set_source_rgba(0.0, 0.0, 0.0, 0.0);
    cr2->paint();

    const double radius = 30;
    cr2->rectangle(0, 0, w, h - radius);
    cr2->set_source_rgb(1.0, 0.0, 0.0);
    cr2->fill();

    cr2->arc(w - radius, h - radius, radius, 0.0,        M_PI * 0.5);
    cr2->arc(radius,     h - radius, radius, M_PI * 0.5, M_PI);
    cr2->set_source_rgb(1.0, 0.0, 0.0);
    cr2->fill();

    cr2->set_source_rgb(0.0, 0.0, 0.0);
    cr2->set_line_width(1.0);
    cr2->stroke();

    if (cr) {
        cr->set_operator(Cairo::OPERATOR_SOURCE);
        cr->set_source(surface, 0.0, 0.0);
        cr->paint();
    }

    const auto region = Gdk::Cairo::create_region_from_surface(surface);
    widget.shape_combine_region(region);
    widget.input_shape_combine_region(region);

    return false;
}

static void
on_widget_realize(Gtk::Widget &widget)
{
    on_widget_draw(widget, Cairo::RefPtr<Cairo::Context>());
}

int
main(int   argc,
     char *argv[])
{
    auto app = Gtk::Application::create("", Gio::APPLICATION_NON_UNIQUE);

    Gtk::Window window;
    window.set_default_size(200, 200);

    window.signal_draw().connect(
        [&](const Cairo::RefPtr<Cairo::Context> &cr) {
            return on_widget_draw(window, cr);
        }
    );
    window.signal_realize().connect([&] { on_widget_realize(window); });

    app->signal_activate().connect([&] {
        app->add_window(window);
        window.present();
    });
    return app->run(argc, argv);
}

Исходная версия Darth_Revan, :

Я совершенно забыл, что GdkWindow не обязан быть квадратным.
Реализовал – может, кому-нибудь пригодится:

#include <gtkmm.h>

static bool
on_widget_draw(Gtk::Widget                  &widget,
               Cairo::RefPtr<Cairo::Context> cr)
{
    const int w = widget.get_allocated_width();
    const int h = widget.get_allocated_height();

    auto surface = widget.get_window()->create_similar_surface(
        Cairo::CONTENT_COLOR_ALPHA,
        w,
        h
    );

    auto cr2 = Cairo::Context::create(surface);
    cr2->set_operator(Cairo::OPERATOR_SOURCE);

    cr2->set_source_rgba(0.0, 0.0, 0.0, 0.0);
    cr2->paint();

    const double radius = 30;
    cr2->rectangle(0, 0, w, h - radius);
    cr2->set_source_rgb(1.0, 0.0, 0.0);
    cr2->fill();

    cr2->arc(w - radius, h - radius, radius, 0.0,        M_PI * 0.5);
    cr2->arc(radius,     h - radius, radius, M_PI * 0.5, M_PI);
    cr2->set_source_rgb(1.0, 0.0, 0.0);
    cr2->fill();

    cr2->set_source_rgb(0.0, 0.0, 0.0);
    cr2->set_line_width(1.0);
    cr2->stroke();

    if (cr) {
        cr->set_operator(Cairo::OPERATOR_SOURCE);
        cr->set_source(surface, 0.0, 0.0);
        cr->paint();
    }

    const auto region = Gdk::Cairo::create_region_from_surface(surface);
    widget.shape_combine_region(region);

    return false;
}

static void
on_widget_realize(Gtk::Widget &widget)
{
    on_widget_draw(widget, Cairo::RefPtr<Cairo::Context>());
}

int
main(int   argc,
     char *argv[])
{
    auto app = Gtk::Application::create("", Gio::APPLICATION_NON_UNIQUE);

    Gtk::Window window;
    window.set_default_size(200, 200);

    window.signal_draw().connect(
        [&](const Cairo::RefPtr<Cairo::Context> &cr) {
            return on_widget_draw(window, cr);
        }
    );
    window.signal_realize().connect([&] { on_widget_realize(window); });

    app->signal_activate().connect([&] {
        app->add_window(window);
        window.present();
    });
    return app->run(argc, argv);
}