GTK3 regressions from a GTK2 perspective

@devs, is there really no less painful way to restore that than adding it back in to every single affected app?!

Correct. Patching GTK is not sustainable and would break between distros, also breaks GNOME compatibility.

The functionality was removed from GTK for reasons that I don't agree with, and adding it to a more central lib within MATE was considered, but would have still required as many changes as the current approach. This way at least the code is consistent across apps and leaves the possibility of modifying any behavior on a specific app if necessary.

It was a trade off. Filing bugs for each instance is just a way of tracking what's done and what's not.

2 Likes

I keep thinking of MATE's GTK interaction as being something where you could reasonably just rebase against upstream periodically, and in that scenario a trivial change to GtkNotebook wouldn't be likely to hit a conflict in years. Clearly that's not the case though.

If devs don't know about it then it wouldn't get fixed

Sure - in case it wasn't obvious already, I've been a developer myself for decades - but it's not like it was a subtle bug, and between the massive libinput changes that were also going on at the time, and the Qt bugs with mousewheel adding the possibility of it being a VirtualBox issue, it made more sense for me to just let all that settle down first, especially since GTK3 meant I wasn't going to switch to 18.04 any time soon anyway.
I'll try a LIVECD over the weekend just to rule out VBox, and go from there. Thanks.

Rebasing upstream is actually the problem, unless you control the distro (Ubuntu, Fedora, etc), you wouldn't be allowed to do that.

Also, plenty of people run multiple DEs on the same machine, and most use GTK, so they could break too

1 Like

Ah, right - only Canonical / Red Hat / etc get to do that.

I'd have thought at this stage in GTK3's life - other technical issues aside, and IDK what those would be - that it would be fine to maintain a fork and just static link the MATE apps against that. But that's also because I'd rather have some apps work well rather than all of them be worse, regardless of the inconsistency, which isn't a position a maintainer can really have. (Though it hasn't stopped Firefox etc from doing exactly that, making what for most people is the most used app they have acting differently to the rest of the system!)

I think "plenty of" people using multiple DEs is probably biased by the circles you move in and the MATE / Mint relationship, but in the abstract I don't think it really matters: nobody expects e.g. KDE and GNOME to offer the same functionality or behavior as each other, and users are realistically learning the DE itself, not Qt or GTK. But it also doesn't matter how true my comment is, because unless there's a good way to run multiple versions of GTK3 on a machine on a per-DE basis, it's all academic. :slight_smile:

unless there's a good way to run multiple versions of GTK3 on a machine on a per-DE basis, it's all academic

True that :slight_smile:

Also a maintenance nightmare. The GNOME/GTK teams are well staffed and have great incentive to keep the entire thing running well, so as much as I disagree with some (many?) of their decisions, they do an amazing job, and I'm more than happy just backporting some things and fixing others on our side.

The MATE team is just a handful of devs doing this for love and beer; the GNOME/GTK teams are a well funded group of paid professionals (and many volunteers) doing this, in part, to maintain profitable enterprise contracts.

4 Likes

Yeah, though a maintenance nightmare is much less of one when you don't have people wilfully causing breakage in the first place. :stuck_out_tongue:

The problem is that when a team abdicates their responsibility to fix bugs, or makes statements like "It doesn't matter what users want: our branding is more important than their choices" (though to their credit they at least came out and said that clearly, rather than going with lines like "We'll do that, we just couldn't make it for this release" etc), then when they're effectively the only group allowed to make ANY version of something, regardless of how nominally open-source it may be, there's no option but to live with it.

I don't want to come off as ungrateful to the people who've contributed to GNOME over the years (though I'm sure I do), and certainly not to the MATE team, because even with GTK's bugs and the user-hostility of the current GNOME team, I'd still rather not switch to KDE / XFCE / etc. But man, they make it hard to actually like them much, when the software becomes less capable and more buggy as time goes by rather than the other way around. Maybe I'm just getting too old for this treadmill. :slight_smile:

Anyway, I think I've pulled this thread off-topic enough - sorry about that. If someone with mod privs wants to split these last few posts off, please do.

3 Likes

@lah7

Regarding gtk3-mashrooms, perhaps it is better to talk with Canonical devs to carry those as patches. Specially no_csd patch. It can be done for specific sessions (like mate, xfce) may be tied to a gsettings key. Or may be you can reach even debian. They already carry few patches.

Scrolling on notebook would be a nice addition too. Since gtk3 is stable now, it can be maintained easily.

Alternate way is to use gtk3-nocsd which is not maintained anymore or perhaps packaging it as a gtk-module (note, gtk-module was removed from gtk4).

I would create a PPA, but I ran into problems compiling the package (regardless of patches) nor did I see the patches in action on Ubuntu MATE 19.04. I put it aside for now, but it works great on Manjaro for the GTK apps I use on KDE.

I have doubts Canonical would take these patches as main Ubuntu intends to create an experience around GNOME 3, in which these patches would break GNOME and other Ubuntu flavours/derivatives. Someone could create an alternate package (or PPA), which is how Manjaro handles it with gtk3 and gtk3-classic.

I've created a separate topic to continue the discussion of gtk3-mushrooms:

1 Like

I have doubts Canonical would take these patches as main Ubuntu intends to create an experience around GNOME 3, in which these patches would break GNOME and other Ubuntu flavours/derivatives.

Not really. Patchee needs to be applied under as if (in_desktop != gnome) . That's how unity patches work on Ubuntu. But they won't accept all the patches.

1 Like

Treeviews: No alternate rows colours

I see that bug/FR has been handled in classic RedHat fashion...

Last time I worked with GTK(2) there was a typical CosmicObject/Trainwreck attempt at OOP to it. I doubt that's gone away (or gotten any better :P) in GTK3, so it's potentially viable to just (fake-)subclass GtkTreeView and use that subclass in the few apps that really benefit from that feature.
It would also be an opportunity to fix the metrics bugs that reduced the content density by ~15% compared to GTK2.
But I haven't even looked at GTK3, so it could also be impractical; or Wimpy et al may prefer not to for other reasons - someone more familiar with it than me would need to weigh in.

2 Likes

What concerns me right now about GTK3 is symbolic icons because it seems to be a special class of icons. They break all older icon themes. They don't render properly in the notification area. Yeah, some people don't think the notification area is important. Heck, some people (Gnome and Elementary) don't even think indicators are important. So they are going to kill them too and replace them with what?

I used to be a Gnome 2/MATE user but became a Xfce user for GTK2 reasons. GTK2 just felt better and more polished. Both the GTK3 port of MATE and Xfce are pretty stable I guess, but when toolkit breakages happen faster than they can be fixed the future for desktop Linux doesn't look good.

There is a reason that the word "good" is part of "good old days". After reading your post and attitude contained with in it, I think my ubuntu mate experiment just ended.

Iah7 Actually it's possible to have a text inside the progress bar in gtk3 but with another widget.
This is what I managed to hack today with the GtkEntry widget. :slight_smile:
Peek 2020-06-04 21-06

I did not set it to run anything it's just a proof of concept.
Will probably use it on xfce.

gcc -Wall -g timer.c -o timer $(pkg-config --libs --cflags gtk+-3.0)

#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>

GtkWidget *switch_a;
GtkWidget *switch_b;

/* Determines to continue the timer or not */
static gboolean continue_timer = FALSE;

/* Determines if the timer has started */
static gboolean start_timer = TRUE;

/* Display seconds expired */
static int sec_expired = 30;

static void
_quit_cb (GtkWidget *button, gpointer data)
{
    (void)button; (void)data; /* Avoid compiler warnings */
    printf("Canceled\n");
    gtk_main_quit();
    return;
}

static void
_check_switch ()
{
    if (gtk_switch_get_active (GTK_SWITCH(switch_a)) == 1)
        printf("no_save=on\n");
    else
        printf("no_save=off\n");
    if (gtk_switch_get_active (GTK_SWITCH(switch_b)) == 1)
        printf("reboot=on\n");
    else
        printf("reboot=off\n");
}

static void
_shutdown (GtkWidget *button, gpointer data)
{
    (void)button; (void)data; /* Avoid compiler warnings */
     _check_switch();
    gtk_main_quit();
}

static gboolean
_label_update(gpointer data)
{
    GtkEntry *label = (GtkEntry*)data;
    char buf[256];
    memset(&buf, 0x0, 256);
    snprintf(buf, 255, "Turning off computer in  %d seconds.", --sec_expired);
    if (sec_expired == 0)
        {
        _check_switch();
        gtk_main_quit();
        }

    gtk_entry_set_text(GTK_ENTRY(label), buf);
    gtk_entry_set_progress_fraction(GTK_ENTRY(label), (double)sec_expired / 30.0);
    return continue_timer;
}

int main(void)
{
    GtkWidget *window;
    GtkWidget *box;
    GtkWidget *box_a;
    GtkWidget *box_b;
    GtkWidget *boxl;
    GtkWidget *shutdown_button;
    GtkWidget *cancel_button;
    GtkWidget *label;
    GtkWidget *question;
    GtkWidget *no_save;
    GtkWidget *reboot;

    gtk_init(NULL, NULL);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_size_request(window, 250, 120);
    gtk_window_set_resizable (GTK_WINDOW(window), FALSE);
    gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
    gtk_window_stick (GTK_WINDOW (window));
    gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
    gtk_window_set_title (GTK_WINDOW (window), "Shutdown");
    g_signal_connect (G_OBJECT (window), "destroy", 
                    G_CALLBACK (gtk_main_quit),
                    NULL);
    box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
    box_a = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
    box_b = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
    boxl = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);

    gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
    gtk_container_add(GTK_CONTAINER(window),boxl);

    question = gtk_label_new ("\nAre you sure you want to shutdown?");
    label = gtk_entry_new ();
    gtk_entry_set_text (GTK_ENTRY(label),
                       "Turning off computer in  30 seconds.");
    gtk_entry_set_progress_fraction(GTK_ENTRY(label), 1.0);
    gtk_entry_set_has_frame (GTK_ENTRY(label), FALSE);
    gtk_entry_set_activates_default (GTK_ENTRY(label),
                                     FALSE);
    gtk_entry_set_overwrite_mode (GTK_ENTRY(label),
                                    FALSE);
    gtk_editable_set_editable (GTK_EDITABLE(label), FALSE);
    gtk_widget_set_can_focus (GTK_WIDGET(label), FALSE);
    gtk_widget_set_state_flags (GTK_WIDGET(label),
                                GTK_SELECTION_NONE, FALSE);

    no_save = gtk_label_new ("No save");
    reboot = gtk_label_new ("Reboot ");
    switch_a = gtk_switch_new ();
    switch_b = gtk_switch_new ();
    gtk_box_pack_start (GTK_BOX(box_a), no_save, FALSE, FALSE, 10);
    gtk_box_pack_start (GTK_BOX(box_a), switch_a, FALSE, FALSE, 10);
    gtk_box_pack_start (GTK_BOX(box_b), reboot, FALSE, FALSE, 10);
    gtk_box_pack_start (GTK_BOX(box_b), switch_b, FALSE, FALSE, 10);

    shutdown_button = gtk_button_new_with_label("Shutdown");
    g_signal_connect(G_OBJECT(shutdown_button), "clicked", G_CALLBACK(_shutdown), shutdown_button);

    cancel_button = gtk_button_new_with_label("Cancel");
    g_signal_connect(G_OBJECT(cancel_button), "clicked", G_CALLBACK(_quit_cb), NULL);

    gtk_box_pack_start (GTK_BOX(boxl), question, TRUE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX(boxl), label, TRUE, TRUE, 0);

    gtk_box_pack_start (GTK_BOX(boxl), box_a, TRUE, TRUE, 10);
    gtk_box_pack_start (GTK_BOX(boxl), box_b, TRUE, TRUE, 10);
    gtk_box_pack_start (GTK_BOX (box), cancel_button, TRUE, TRUE, 10);
    gtk_box_pack_start (GTK_BOX(box), shutdown_button, TRUE, TRUE, 10);
    gtk_box_pack_start (GTK_BOX(boxl), box, TRUE, TRUE, 10);

    gtk_widget_show_all(window);

    g_timeout_add_seconds(1, _label_update, label);
    continue_timer = TRUE;
    start_timer = TRUE;

    gtk_main();
    return 0;
}

Perhaps @vkareh has an idea about how to prevent text selection inside GtkEntry. :slight_smile:

Is anybody still interested in the classic-style Log Out and Shut Down dialogs?

I ask this because I actually whipped up a solution which looks almost identical to the GTK+ 2 dialogs, but the solution is kind of messy, at least on the progress bar front. To wit, I had to pack a GtkLabel and a GtkProgressBar into an overlay container (GtkOverlay) so that the label text would be drawn over the top of the progress bar. To make things messier, I used a size group to ensure the progress bar did not cut the text off (the text should dictate the size of the progress bar, not vice versa). Furthermore, I also had to connect to the label's size-allocate signal so that whenever the label was resized (e.g., the text size was increased), the progress bar trough and progress "gadgets" would increase in height. Without the last step, the result was a big gap at the top of the progress bar, meaning roughly half the text may be drawn over the progress bar and half is drawn above the progress bar. Annoying!

Anyway, I personally use my version exclusively now. Here's the fruits of my labors:
new-log-out

new-shut-down

In short, I want to know if anyone else thinks it's a good idea for me to start a pull request for this. I can only imagine it'll first make light in MATE 1.26.

4 Likes

Good idea Gordon.
I think you covered all of the cases, the text size/font and theme switching.

1 Like

I just started a pull request for this at: https://github.com/mate-desktop/mate-session-manager/pull/261.

My fingers are crossed and we shall see how it works out.

3 Likes

Your knowledge of Gtk is impressive.
Do you know if GtkPopovers can be used to create mate-panel plugin menus?
I like how they look and how other widgets can be inside them.

Edit:
Let's forget that I asked. It looks too tricky.
Especially the arrows. Popover is not designed to work as a standalone widget, it has no own window.
It needs a window and a few dummy widgets (1x1 transparent png) to set arrows pointing to.
It would need a lot of them for all the corners. :slight_smile:
I've tried to emulate a standalone menu-like behavior which closes popover if it is unfocused.

#include <gtk/gtk.h> 
  
/*   save this file as standalone-popover.c
     create a 1x1 pixel transparent png image in the same folder
     and name it dummy.png
     compile with:
          gcc standalone-popover.c -o standalone-popover  `pkg-config --cflags --libs gtk+-3.0`
*/

#define DUMMY_PNG "dummy.png"

void destroy(GtkWidget* widget, gpointer data) 
{ 
    gtk_main_quit(); 
} 
  
int main(int argc, char* argv[]) 
{ 
  
    GtkWidget  *window; 
    GtkWidget  *popover;
    GtkWidget  *dummy_png_top_left;
    GtkWidget  *dummy_png_top_center;
    GtkWidget  *dummy_png_top_right;
    GtkWidget  *box;
    GtkWidget  *dummy_box_top;
    GtkWidget  *label;
    GtkWidget  *button;
    gtk_init(&argc, &argv); 
  
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_type_hint (GTK_WINDOW(window),
                              GDK_WINDOW_TYPE_HINT_POPUP_MENU);
    gtk_widget_set_size_request(window, 250, 220);
    gtk_window_set_resizable (GTK_WINDOW(window), TRUE);
    gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
    gtk_window_stick (GTK_WINDOW (window));
    gtk_window_set_decorated (GTK_WINDOW(window), FALSE);
    gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);

    gtk_widget_set_events (window, GDK_FOCUS_CHANGE_MASK);

    g_signal_connect(window, "destroy", 
                     G_CALLBACK(destroy), NULL);
    g_signal_connect (G_OBJECT (GTK_WINDOW (window)),
                    "focus-out-event",
                    G_CALLBACK (destroy),
                    NULL);
    gtk_window_present (GTK_WINDOW(window));
    gtk_container_set_border_width(GTK_CONTAINER(window), 20); 
  

    dummy_png_top_left   =  gtk_image_new_from_file (DUMMY_PNG);
    dummy_png_top_center =  gtk_image_new_from_file (DUMMY_PNG);
    dummy_png_top_right  =  gtk_image_new_from_file (DUMMY_PNG);

    dummy_box_top = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_box_set_homogeneous (GTK_BOX (dummy_box_top), TRUE);
    gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_left, TRUE, FALSE, 0);
    gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_center, TRUE, FALSE, 0);
    gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_right, TRUE, FALSE, 0);

    box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
    gtk_box_set_homogeneous (GTK_BOX (box), TRUE);

    gtk_widget_show(dummy_png_top_left);
    gtk_widget_show(dummy_png_top_center);
    gtk_widget_show(dummy_png_top_right);

    label = gtk_label_new ("Standalone GtkPopover");
    button = gtk_button_new_with_label("OK");
    gtk_box_pack_start (GTK_BOX(box), dummy_box_top, TRUE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX(box), label, TRUE, FALSE, 10);
    gtk_box_pack_start (GTK_BOX(box), button, TRUE, FALSE, 10);

    /* here we use the dummy widget to position the popover arrows */
    popover = gtk_popover_new(dummy_png_top_center);

    gtk_container_add(GTK_CONTAINER(window), popover); 
    gtk_container_add(GTK_CONTAINER(popover), box); 
    gtk_popover_set_modal(GTK_POPOVER(popover), FALSE);

    g_signal_connect(G_OBJECT(button),
                     "clicked",
                     G_CALLBACK(destroy),
                     window);
    gtk_widget_show_all(window);

    /* need this to focus a window */
    gtk_window_present_with_time(GTK_WINDOW(window),GDK_CURRENT_TIME);
    gtk_window_activate_focus (GTK_WINDOW (window));
    gtk_widget_grab_focus(GTK_WIDGET(window));
    gtk_main(); 
  
    return 0; 
} 

So far the PR has gotten mixed responses. Some of us here really disliked the "spreading" of the dialog buttons; turns out @raveit65 likes the spreading and says no to the lack of spreading I (unintentionally) whipped up. I wrote back a response which details the advantages and disadvantages of both methods, and strongly urged @raveit65 to not include the expanding buttons.

We'll have to see what happens. Personally I don't care about the buttons, but enabling the expanded buttons also means using a deprecated function in GTK+ 3. As far as I can tell, there's no way around the use of the deprecated feature -- @raveit65 claims applying a style class would do the trick, but the result still doesn't look right.

I defended our position by showing that in MATE, the old-style button layout is more common than the new-style layout. I hope we can come to an agreement on this issue.

Spread buttons require a deprecated function!? I thought this was a new GTK misfeature. How is it deprecated?

Good question, but it requires a little background.

When a feature is "deprecated" in GTK, that only means that the feature is deprecated for use by applications; the feature may be used within the GTK library itself for as long as the feature exists. Heck, the use of the feature in the GTK does not even throw up a warning under most circumstances.

The old style of logout dialog used a GtkMessageDialog, which is derived from a more generic GtkDialog. Since GtkMessageDialog is implemented inside of GTK, the usage of the deprecated function in question does not throw up a warning; if there even was a warning, it was when GTK was compiled. GtkDialog actually has more conservative button layouts than GtkMessageDialog, apparently. (An oversight on the part of the GTK team, perhaps?) My proposed logout dialog uses the generic GtkDialog instead of GtkMessageDialog so that I can insert an image on the left and stuff. In other words, I did it for extra flexibility -- not really for the buttons, but that was a side benefit.

Honestly, I don't see what anyone's complaining about. The majority of dialogs in MATE use the old style, and the GTK+ 2 version of MATE had a log out dialog which looked practically identical to this one. But it looks like I'm going to have to partly concede here if I want to push this patch through. Oh well.