Can you remove a GtkPopoverMenu's rounded corners?

,

In my program, I have a GtkPopoverMenu:
styled_GtkPopoverMenu

I understand that these are derived GtkPopovers and can be styled with CSS.

However, I can’t figure out how to make the corners not rounded, as indicated in yellow in the screenshot there. Note that the actual corners of the menu are gray and rounded. The black, sharp corners actually represent what would normally be a transparent area around the menu (which is black because my compositor is disabled, so transparency falls back to solid black).

Ideally, I’d like the menu’s gray body to completely extend over this normally-transparent area, such that there’s no black border. (This would make the menu look the same to those on a desktop environment with no compositor or who turn their compositor off and those with a compositor enabled.)

The CSS I’m using is:

/* Style... everything */
* {
    border-radius: 0 0 0 0;
}

/* Style menu entries */
.menu * {
    color: white;
    background-color: red;
}

I’m discouraged and puzzled by the fact that the * rule – which should remove everything’s border radius – isn’t doing anything to those corners.

I’m applying that CSS like this:

// Apply CSS stylesheet.
GdkDisplay* display = gdk_display_get_default();
GtkCssProvider* css_provider = gtk_css_provider_new();
GFile* css_stylesheet = g_file_new_for_path("./prototype-gtk.css");

gtk_css_provider_load_from_file(css_provider,
                                css_stylesheet);
gtk_style_context_add_provider_for_display(display,
                                           GTK_STYLE_PROVIDER(css_provider),
                                           GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);

g_object_unref(css_stylesheet);
g_object_unref(css_provider);

And, if it helps or if anyone’s curious, the code to add that menu is:

static void create_menus(GtkApplication* app, GtkWidget* window)
{
    GMenu* menubar = g_menu_new();

    // Make File menu.
    GMenu* file_menu = g_menu_new();

    // Make quit menu item.
    GMenuItem* quit_item = g_menu_item_new("Quit",
                                        "app.quit");

    // Add `Ctrl+Q` shortcut accelerator to quit menu item.
    // First, configure the item to respond to the shortcut (aka "accelerator").
    gtk_application_set_accels_for_action(app,
                                        "app.quit",
                                        (const char *[]) {
                                            "<Ctrl>q",
                                            NULL,
                                        });
    // Second, make the item display the key combo.
    g_menu_item_set_attribute(quit_item, "accel", "s", "<Control>q", NULL);

    // Add quit menu item to File menu.
    g_menu_append_item(file_menu, quit_item);

    g_object_unref(quit_item);

    // Add File menu to menubar.
    g_menu_append_submenu(menubar,
                        "File",
                        G_MENU_MODEL(file_menu));

    g_object_unref(file_menu);

    // (Unrelated lines of code abridged...)

    // Set and show menubar.
    gtk_application_set_menubar(app, G_MENU_MODEL(menubar));
    gtk_application_window_set_show_menubar(GTK_APPLICATION_WINDOW(window), TRUE);

    g_object_unref(menubar);
}

Hi! I don’t think it’s possible, the shape of a popover is hardcoded: https://gitlab.gnome.org/GNOME/gtk/-/blob/4.7.2/gtk/gtkpopover.c#L1324

1 Like

I’d try GTK_STYLE_PROVIDER_PRIORITY_APPLICATION instead of GTK_STYLE_PROVIDER_PRIORITY_FALLBACK, otherwise the theme will take precedence. The black part is probably the shadow.

1 Like

Please, use a compositor under X11. There’s no reason whatsoever to not use one in 2022; the whole uncomposited X11 case is barely tested, and it’s broken by definition.

1 Like

Yaaas, you’re my hero! :trophy: :partying_face:
It seems like you’re correct on both counts!
GtkPopoverMenu_no_rounded_corners

Removing the rounded corners

@lb90 I saw that menacing GskRoundedRect in your link, and I felt all hope drain away. But, per @skeller’s suggestion, changing the last argument in

gtk_style_context_add_provider_for_display(display,
                                           GTK_STYLE_PROVIDER(css_provider),
                                           GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);

to

gtk_style_context_add_provider_for_display(display,
                                           GTK_STYLE_PROVIDER(css_provider),
                                           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

made my CSS rules apply!

It must have indeed been that my system’s GTK theme was overriding my CSS rules due to GTK_STYLE_PROVIDER_PRIORITY_FALLBACK, which the docs describe as the “priority used for default style information that is used in the absence of themes”. (The reason I used that to begin with was because I carelessly cargo-cult-copied-and-pasted it from the web.)

NOTE: I’ll be referring to figures I uploaded to :framed_picture: :film_strip: this Imgur album :film_strip: :framed_picture: (due to Discourse’s limit on how much media and links new users can use in a post).

It seems like corner styling can be achieved by targeting everything under a menu, rather than the menu itself. This CSS

.menu * {
    border-radius: 0 0 0 0;
    color: white;
    background-color: red;
}

(and no other CSS) produces :framed_picture: Fig 1.
To reiterate, that thick black border around the menu is due to my compositor being off; with my compositor on, it looks like :framed_picture: Fig 2.

Something possible via targeting the menu itself is that

.menu {
    background-color: red;
}

colors in the black area/transparency/shadow:
:framed_picture: Fig 3
(With composition on, this looks identical; the normally-transparent perimeter is suddenly red.)

That thin black border (and… unfortunately, all borders) can be removed by adding border: none; to

.menu * {
    border: none;
    border-radius: 0 0 0 0;
    color: white;
    background-color: red;
}

which produces :framed_picture: Fig 4.
(With composition on, this also looks identical.)

…But note that there’s still a subtle shadow border there.

A better approach to deal with this it not to try to color the black area/transparency/shadow but to remove it entirely. See below.

Removing the black borders (a.k.a. transparency/shadow) when you’re not running a compositor

Transparency or shadow?

The black part is probably the shadow.

Indeed, it seems like the big black borders are the menu shadow, since they’re toggled with the box-shadow property!

On KDE with the compositor enabled, I see :film_strip: Fig 5.

The menu’s got rounded corners and there’s a region of transparency around its perimeter. (It also has a fade in/out animation when activated/dismissed.)

With the compositor disabled, it appears like :film_strip: Fig 6.

This is why I assumed the fat black border was transparency-, not shadow-, related. I also know that disabling composition disables blur/transparency in other programs. (On the plus side, the menu appears/disappears instantly, which feels a lot snappier than the fade animation.)

So, about removing it…

First, this CSS rule from above

.menu {
    background-color: red;
}

is not actually needed; it merely colors the shadow, and the shadow is about to be removed.

The shadow is removed by adding box-shadow: none; to

.menu * {
    box-shadow: none;
    border: none;
    border-radius: 0 0 0 0;
    color: white;
    background-color: red;
}

which finally produces a no-frills :framed_picture: Fig 7!
:red_square: :partying_face:

My only remaining problem

.menu * styles everything under a menu. I like that menu entries now have no border-radius, but I don’t necessarily want the radio buttons in the screenshot above to have no border-radius (or, in fact, no border at all).

Might someone be able to point me to some… list of CSS class selectors for things under a menu so I can target things specifically, rather than targeting everything with *?

2 Likes

Please, use a compositor under X11. There’s no reason whatsoever to not use one in 2022

:rofl:
Allow me to gently push back on this. There’s at least one reason: responsiveness.

I don’t know how much this applies to a 60 Hz or lower monitor, but, if you have a higher refresh rate monitor (~120 Hz and above), try the following experiment:

  • Drag a window around on your screen with the mouse with the compositor on
  • Do the same thing with the compositor off

When I do this, the movement is WAY smoother (more responsive) with composition off.

It’s easy to test this in KDE, where you can toggle the compositor via System Settings > Display and Monitor > Compositor > Enable on startup and rebooting.

Alternatively, you can boot in with LXDE, which I believe doesn’t use a compositor at all.

More alternatively, boot into Windows 10 and try it there – the Windows 10 desktop has the same, high level of responsiveness. (My pet theory is that they achieved that by disabling the transparency effects in Windows 10 that Aero used to provide in Windows 7. I mean, disabling composition in Linux kills transparency but makes stuff more responsive. They disabled window transparency in Windows 10, and Windows 10 feels more responsive. Coincidence? Maybe.)

This actually also seems to apply to games, where it’s easiest to detect when prominent things are rapidly passing by, like stars streaming past the sides of your cockpit in Elite Dangerous. (That said: games may block compositing when they run, but I’m not sure whether all games do that or under what condition in various desktop environments.)

It’s something you don’t notice you’re missing until you feel it. :sob:

That’s why I disable my compositor.

There’s also a bonus which I mentioned in the post before this one: animations that add latency to GUI feedback get disabled. Compare these these menu fade animations with the compositor turned on…

…with the snappy menus had with the compositor turned off:

This also applies to close-window animations, etc. All of that can probably be negotiated by fiddling with system settings, but still. :yum:

And I don’t think the responsiveness difference I cited is because I have weak hardware, for the record. I’ve tested this with an AMD 3900X CPU + an Nvidia GTX 1080 Ti and, more recently, an AMD RX 5700 XT. This includes dual booting Windows 10 to notice how much more responsive its desktop environment feels than any Linux desktop environment with the compositor enabled, and how equally responsive Linux desktop environments feel with the compositor disabled. (I guess it’s possible that, if I got an RX 3090 Ti or something, I might cease to notice any responsiveness difference whether the compositor is enabled or not, but I have yet to test that out and also doubt it.)

the whole uncomposited X11 case is barely tested, and it’s broken by definition.

I’m curious what you mean by this.

1 Like

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