Skip to content

Load menu icons only when "menus-have-icons" is set#820

Merged
lukefromdc merged 1 commit into
masterfrom
icon-prefs
Jun 25, 2018
Merged

Load menu icons only when "menus-have-icons" is set#820
lukefromdc merged 1 commit into
masterfrom
icon-prefs

Conversation

@lukefromdc
Copy link
Copy Markdown
Member

Most panel menus excluding main menus. Duplicate behavior of now-deprecated code replaced by github.com/mate-desktop/mate-panel/commit/86701517e7d7cb3d2c08a40d76af97308f18902c

@lukefromdc lukefromdc requested review from a team and sc0w June 20, 2018 17:09
lukefromdc referenced this pull request Jun 20, 2018
avoid deprecated:

gtk_image_menu_item_new_with_mnemonic
gtk_image_menu_item_set_image
@TomaszGasior
Copy link
Copy Markdown

There are three problems with this merge request.

  1. This code should be part of MATE's shared library, not part of panel or any MATE application. But this is only my private opinion.
  2. It does not work dynamically like GtkImageMenuItem was. When I un-check menu icons in MATE apeearance settings I have to re-login or killall mate-panel to see effect.
  3. See ss:
    zrzut ekranu z 2018-06-20 21-36-23. No, fixing this should not be part of theme.

Comment thread mate-panel/libpanel-util/panel-gtk.c Outdated
gtk_container_add (GTK_CONTAINER (box), icon);

/*Load the icon unless the user has icons in menus turned off*/
icon_settings = g_settings_new ("org.mate.interface");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you allocate memory, you should also free it.

@lukefromdc
Copy link
Copy Markdown
Member Author

I'm seeking to get the panel to respect icon preferences here. Thus I am modifying a function already existing in mate-panel, not refactoring mate-panel, caja, and everything else to move a function to mate-desktop. That kind of combined PR is time-consuming to test and we are a small team. I for one will not be writing such a PR. If we want this to work at all, we need to keep it simple. We also have apps like Pluma that are deliberately designed NOT to depend on mate-desktop.

@lukefromdc
Copy link
Copy Markdown
Member Author

@muktupavels, I don't know offhand how to free a gsettings object, and I don't see anything being done to free them in other functions in MATE. I am wondering if this is why changes to this setting are not being immediately applied. I tried g_object_unref() but got no change in behavior.

@lukefromdc
Copy link
Copy Markdown
Member Author

OK, I see g_object_unref being used in some places in MATE for gsettings objects, but left out in a LOT of others. Didn't cause any problems and might be one less memory leak, but still looking at the delayed application issue.

We've got another PR hung up behind the panel not detecting window manager changes, BTW.

@lukefromdc
Copy link
Copy Markdown
Member Author

I found the dynamic application issue: panel_image_menu_item_new_from_icon is only run the FIRST time the panel context menu is opened, and thus any change in the gsettings value cannot be applied after the menu is first created, because it is never remade. We have had problems in many other places created by this kind of problem.

@lukefromdc lukefromdc force-pushed the icon-prefs branch 3 times, most recently from 2ab93a0 to ffb0d49 Compare June 21, 2018 03:43
@lukefromdc
Copy link
Copy Markdown
Member Author

lukefromdc commented Jun 21, 2018

The dynamic application problems are now fixed, and it should now cover every menuitem icon loaded by mate-panel except those in the main menu button or main menu bar. I assume we want to load those unconditionally.

This ended up being four commits affecting three files. I reordered them a bit and squashed it into two commits, one to apply the gsettings preference and the other to rebuild the affected menus each time they are shown.

Note that building menus anew when shown is slightly heavier code, but these menus are small and if this is not done issues arise. Not only does reusing menus prevent applying any gsettings preference that changes the menus until the panel is restarted, in another place I am all but certain it plays a role in #817 , which I will now take another crack at. EDIT: that issue may be in libwnck and thus out of our scope for patching.

@lukefromdc
Copy link
Copy Markdown
Member Author

@TomaszGasior , would you please retest this? I don't know what you were referrring to concerning themes, but you should not find icon show/hide prefs applied dynamically

Copy link
Copy Markdown
Contributor

@muktupavels muktupavels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also why do you create icon_settings for each menu item?

Why do you need to rebuild menus? You should not comment out assert, but should make sure that old menu is properly destroyed.

HINT: you can bind icon visibility to GSettings setting!

Comment thread mate-panel/panel.c
static GtkWidget *
panel_menu_get (PanelWidget *panel, PanelData *pd)
{
if (!pd->menu) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time when panel_menu_get is called you re-create menu now... What happens with menu or menus that was created previously?

@lukefromdc
Copy link
Copy Markdown
Member Author

Keep in mind, I am NOT a university-trained programmer but am self-taught by experimenting with this stuff. The menus are rebuilt each time because otherwise the changes are not applied. To apply a change in the icon settings requires repacking the box that is in turn packed into the menu item. As for the fate of previously created menus" NO idea but no observed adverse effect. Variables involved are simply overwritten with new values in at least some cases though.

As for why icon settings is created and destroyed for each menu item, it works that way because that's where the code is that needs to read it.

"bind icon visibility to GSetting" I have exactly no idea how to do or even what you mean.

@lukefromdc
Copy link
Copy Markdown
Member Author

Note that I have never found any other way to make a menu change its appearance other than to re-create it. Do you know a good way to destroy a menu when it is closed (popped down) which would presumably have the same effect? As for the assert, it caused the panel to exit and could not be used. With it commented out the panel worked fine, not sure why it was there in the first place since I did not get a segfault or similar issue with it gone.

@lukefromdc
Copy link
Copy Markdown
Member Author

We have another option here if we don't want to remake menus: ditch the attempt to make this work dynamically, and document in mate-appearance-properties that mate-panel may need to be restarted after enabling or disabling icons in menus. That is lighter code as the menus are made only once, at the price of being a little less functional. Is that a significant difference on something like a Raspberry Pi? If so I would vote for not attempting to apply it dynamically at all here.

The origjnal report on this issue came from someone who really wants icons in menus gone, not user selectable, which at least two of us are absolutely refusing to consider for MATE. None the less, if the preference for icons or no icons in menus exists it should be made to work, so users can choose for themselves.

@muktupavels
Copy link
Copy Markdown
Contributor

muktupavels commented Jun 21, 2018 via email

@muktupavels
Copy link
Copy Markdown
Contributor

muktupavels commented Jun 21, 2018 via email

@lukefromdc
Copy link
Copy Markdown
Member Author

Are you saying that overwriting a menu with another menu leaks the old menu and leaves mutliple copies storied in RAM? I could start the process by resetting to NULL if so

@lukefromdc
Copy link
Copy Markdown
Member Author

As for the origjnal author and assert, when I found nothing broke if the assert was removed, I assumed he ran into trouble with this on GTK2 and the original problem was now long gone

@muktupavels
Copy link
Copy Markdown
Contributor

Check pd->menu = g_object_ref_sink (panel_context_menu_create (panel)); line! Really, read this:
https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#g-object-ref-sink

You can not simply set it to NULL... You need free allocated memory first and only then set it to NULL. Of course if you free old menu before creating new one you don't need to set it to NULL, just free and assign new value. In this case free is gtk_widget_destroy, don't remember, but you might use also g_object_unref...

I put asserts to make sure my expectations are met. For example if I know or expect that variable must be NULL when function is called I put assert. If I would expect that function could be called more then once then I would make sure that old value is freed first.

@TomaszGasior
Copy link
Copy Markdown

In my honest opinion… you can avoid problem by dropping menu items icons. As I wrote to you, maintaining good reimplementation of GtkImageMenuItem will be hard task…

@lukefromdc
Copy link
Copy Markdown
Member Author

NO, NO, and HELL NO! @TomaszGasior, we are absolutely REFUSING to remove icons from menus. I have put a lot of work into making this user selectable but repeated demands to remove icons with no user ability to bring them back are tempting me to stop work.

I would revert a removal of icons locally, and if I was unable to do that I would refuse to install the "updated" version. I have trouble even using the menus without the icons, noticed that in testing.

We are not going to remove icons from menus, we are not going to remove icons from the desktop, any further discusion of such things is a waste of time and energy. Case closed.

@sc0w
Copy link
Copy Markdown
Member

sc0w commented Jun 21, 2018

to make sure we have spaces in the left (the expected in all the gtk applications) you need to do the changes here with something like this:

if ((icon_name) && (g_settings_get_boolean (icon_settings, "menus-have-icons")))
        icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
else
        icon = gtk_image_new ();

and...

if ((gicon) && (g_settings_get_boolean (icon_settings, "menus-have-icons")))
        icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
else
        icon = gtk_image_new ();

and I think no more changes are needed, if the user needs to restart the panel to apply the changes in the gsettings key, that is the expected behavior for me

and other question, I am not sure if we will have problems with dbus with several clicks (remember mate-desktop/mate-terminal#233)

@lukefromdc
Copy link
Copy Markdown
Member Author

Icons are staying in menus, its just a question of keeping deprecated code (and permanently swearing off GTK4) or reimplementing the deprecated items to use them to the best of our ability. There is no condition under which they are going to be removed. Just because GNOME doesn't use them does not me we are obilgated to drop them too. The user experience is just as important as code quality, and some of us find menus without icons much harder to use

@TomaszGasior
Copy link
Copy Markdown

TomaszGasior commented Jun 21, 2018

@lukefromdc You are misunderstanding my words. You are think I am against MATE, GNOME-like friend. I wanted to say that lack of menu items icons is better than ugly and weak reimplementation of deprecated GTK component. And maybe insetad of wasting time to small 16x16 pxs icons you can move your energy to something more important in MATE, Wayland support for example.
My (small) participation in this discussion and whole MATE desktop now is closed too. Sorry, if someone was hurt by my words.

My last word in this topic: keep in mind that users of other environments may not have MATE"s gsettings schema installed. You should check existence of it when you are reading directly from MATE's gsettings, otherwise errors will be printed in logs. Maybe this problem is not related to mate-panel but it is for pluma, atril and other MATE apps, where you probably copy&paste this poor reimplementation of GtkImageMenuItem.

@muktupavels
Copy link
Copy Markdown
Contributor

gtk_image_clear should work without rebuilding menu... And GTK3 will not remove deprecated things... And going to GTK4 probably will have bigger problems then icons in menus... :P

@lukefromdc
Copy link
Copy Markdown
Member Author

I will try gtk_image_clear if I can find a way to run it from the places this function is called. The orignal problem in getting a response to changing the gsettings value is that the entire code to build the menu was run only once, so if gtk_image_clear is in that code it won't be run until the panel is restarted.

@lukefromdc
Copy link
Copy Markdown
Member Author

As for the need for icons in menus, they are so important to me that I cannot accept removing them no matter what the benefits. Keep in mind, we have been blocking all replacements for deprecated code that remove icons anywhere unless the icon loading is reimplemented. GTK3 won't remove these items, and we can choose never to support GTK4 if necessary.

Thus this becomes a choice between keeping deprecated code and reimplementing deprecated code. Meanwhile I am wasting time reminding you that icons are not coming out of menus when I could be trying better reimplementation ideas.

@muktupavels
Copy link
Copy Markdown
Contributor

Well you can just hide all images, no? By using simple g_settings_bind call when menu item is created. You can even provide your own binding function and do whatever you want:
https://developer.gnome.org/gio/stable/GSettings.html#g-settings-bind-with-mapping

@lukefromdc
Copy link
Copy Markdown
Member Author

right now I am experimenting with two different options. In both cases the rebuilding of menus is scrapped and those files reverted to master. If I use Albert's suggestion to bind visibility to gsettings, the result is good dynamic application of the gsettings preference(no need to restart the panel) but when the icons are not shown the space for them is removed, as the allocated space of a non-visible GtkWidget is zero. Alternately, I can use the same code as I've used in Caja where either an empty image or the icon is loaded. That gives a consistant space with or without icons being loaded, but a change is not applied until the panel is restarted. Got a bit more space when empty by packing the icon into a box, trying to set a minimum size on the box without having to resort to cssproviders, as one would then be loaded on every menuitem and that is heavy.

Trying to find a way to preserve the space and apply changes immediately

@raveit65
Copy link
Copy Markdown
Member

@TomaszGasior
Please stop to post your personal opinions about using icons or not here.
This is a technical topic, feel free to discuss this in you own report.

@TomaszGasior
Copy link
Copy Markdown

@raveit65 You didn't understand what I said.

@lukefromdc
Copy link
Copy Markdown
Member Author

Finally found a way to make it work and force-pushed.

First bind the icon's visiblity to "menus-have-icons" though that sets a width and height of zero when the widget(the icon) is not visible. Because of that, pack the icon into a box of its own, and set a 16px min-width on that with css added to the existing global mate-panel.css file and a style class on the icons.

This applies changes in "menus-have-icons" immediately, and so long as the menus are are showing 16px icons will keep the same spacing between the label and the left edge as with or without the icons. The space would grow for a larger icon but will never shrink below this.

Results this time around consistant with what I got in Caja with mate-desktop/caja@76c2a2a but code was more complex due to these menus not being remade each time they are popped up. The point here is to make the gsettings preference behave as users expect, and to render the menus the way they are supposed to be rendered when the icons are not shown by user choice.

Copy link
Copy Markdown
Member

@raveit65 raveit65 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works well.

@sc0w
Copy link
Copy Markdown
Member

sc0w commented Jun 23, 2018

for some reason, there is no space in the left here: (hardware, internet and network ...)

screenshot at 2018-06-23 22-37-38

EDIT: it works fine with mate-panel 1.20.1

EDIT2: culprit commit 8670151

@lukefromdc
Copy link
Copy Markdown
Member Author

The issue with the "preferences" item occurs both with this PR and also with mate-panel 1.21.1 as released. Thus, in between those was another menitem deprecation fix, affecting main menus which this PR did not touch. Also link to the control center in the "system" menu still gets its icon, I will have to find that one.

@muktupavels
Copy link
Copy Markdown
Contributor

I still don't get why you need to create multiple GSettings objects. If you have 100 menu items then you create 100 GSettings objects... Why? You need only one, no?

These extra / uneeded objects will cause more memory usage, also menu creation time will be slower for no reason. Just because computers these days are fast and has huge memories does not mean that you should ignore these things.

If you don't want pass extra parameter to your helper functions you could do something like this (untested ofcourse):

static GSettings icon_settings = NULL;

static void
ensure_icon_settings (void)
{
  if (icon_settings != NULL)
    return;

  icon_settings = g_settings_new ("org.mate.interface");

  panel_cleanup_register (panel_cleanup_unref_and_nullify,
&icon_settings);
}

Then in helper functions call ensure_icon_settings before using g_settings_bind. Now GSettings object should be created once and destroyed when panel will exit.

@lukefromdc
Copy link
Copy Markdown
Member Author

lukefromdc commented Jun 24, 2018

@muktupavels , your change works. I had to do a little tuning on it but once I changed the initial declaration of icon_prefs from gsettings to *gsettings like in the previous code and added panel-cleanup.h to the includes it worked.

I then matched the indents to the rest of the file, gave you credit for the basic code, and pushed it. I figure you probably don't have a mate build environment set up so you know what works on gnome-panel but can't directly test on mate-panel.

Anyway, these hints are quite helpful. Out of curiosity, how much RAM does a typical boolean gsettings object take? The boolean variable itself would need only one byte (can't use just one bit), but there's the rest of the object to consider. Multiply by the worst case for maximum number of menuitems and that's the RAM savings.

Many guides to programming promote limiting the scope of variables and avoiding globals, but in this case that advice seems to be wrong.

EDIT: I would think that as the menu items are created with the previous code, the multiple gsettings objects would be created, used, and then destroyed one at a time unless the g_object_unref didn't end up actually freeing them. More code to run and CPU usage on opening a menu but at least not all of them in RAM at once.

@muktupavels
Copy link
Copy Markdown
Contributor

@muktupavels , your change works. I had to do a little tuning on it but once I changed the initial declaration of icon_prefs from gsettings to *gsettings like in the previous code and added panel-cleanup.h to the includes it worked.

I did not expect that it will work by simple copy&paste, I just gave idea...

I then matched the indents to the rest of the file, gave you credit for the basic code, and pushed it. I figure you probably don't have a mate build environment set up so you know what works on gnome-panel but can't directly test on mate-panel.

Not only I don't have MATE build environment, I also don't have any MATE package/module installed... :P I don't know if this works in gnome-panel... We don't have icons in normal/standard menus and in menu-bar / main-menu applets icons are always visible. Also in gnome-panel I don't use GtkBox to replace GtkImageMenuItem, it simply does not give you same result... I have GpImageMenuItem that is supposed to give same/similar result.

Anyway, these hints are quite helpful. Out of curiosity, how much RAM does a typical boolean gsettings object take? The boolean variable itself would need only one byte (can't use just one bit), but there's the rest of the object to consider. Multiply by the worst case for maximum number of menuitems and that's the RAM savings.

I don't know, but clearly 100 objects require more memory than 1 object. If you are interested, then just measure memory usage and/or time needed to create new objects.

Many guides to programming promote limiting the scope of variables and avoiding globals, but in this case that advice seems to be wrong.

I prefer to not use globals and in this case it is limited only to this file. If you would want then you could avoid this... This is not only option. :)

EDIT: I would think that as the menu items are created with the previous code, the multiple gsettings objects would be created, used, and then destroyed one at a time unless the g_object_unref didn't end up actually freeing them. More code to run and CPU usage on opening a menu but at least not all of them in RAM at once.

And how bindings works? If that object would have been destroyed then how would you get notifications that setting has changed? Yes, you dropped your own reference, but in this case it is not destroyed because there is extra reference added creating binding. From documentation:

Note that the lifecycle of the binding is tied to object

In this case it means that there is extra ref added:
https://gitlab.gnome.org/GNOME/glib/blob/master/gio/gsettings.c#L2862

Most panel menus excluding main menus. Bind gsettings preference "menus have icons" to visibility of icon. Pack the icon into a box with a 16px min-width set in panel.css to hold the space when the icons are not shown Duplicate as much as possible behavior of now-deprecated GtkImageMenuItem replaced by github.com/mate-desktop/mate-panel/commit/86701517e7d7cb3d2c08a40d76af97308f18902c Use only one icon-settings gsettings object to control this in all menuitems controlled by panel-gtk.c The use of a single gsettings object is based on code by Albert Muktupavels https://github.com/muktupavels
@lukefromdc lukefromdc merged commit 5ca1fb1 into master Jun 25, 2018
@lukefromdc lukefromdc deleted the icon-prefs branch June 25, 2018 23:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants