icewm
icewm copied to clipboard
GTK tear off menus in menu layer
Tear off menus in Gimp are somehow fixed to the menu layer. It's not possible to change it manually. Obviously it makes them useless.
They appear in correct layer in nedit (that's the only other app I know that uses tearoff menus). Neither Duck nor Google show any meaningful results.
It's 90% a bug in Gimp or GTK, but before I start digging through it - is there a quick way to check it?
man icewm-winoptions gimp.layer: Normal
It doesn't work for me. I'll check tomorrow. Anyway hacking winoptions is a workaround, isn't it.
To be sure it isn't set elsewhere:
matlib@notek:~$ find / -name winoptions -print -exec grep -i gimp {} ';' 2>/dev/null; echo --
/var/home/matlib/Progs/src/icewm/lib/winoptions
/usr/local/icewm/share/icewm/winoptions
--
Ok, Gimp is out. It can be easily reproduced with plain Gtk:
#!/usr/bin/perl
use Gtk2 -init;
my $w = Gtk2::Window -> new ('toplevel');
my $m = Gtk2::MenuBar -> new ();
my $sm = Gtk2::Menu -> new ();
$sm -> append (Gtk2::TearoffMenuItem -> new ());
$sm -> append (Gtk2::MenuItem -> new ("Menu Item"));
my $r = Gtk2::MenuItem -> new ("Menu");
$r -> set_submenu ($sm);
$m -> append ($r);
$w -> add ($m);
$w -> set_size_request (100, 50);
$w -> show_all ();
Gtk2 -> main ();
#include <gtk/gtk.h>
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GtkWidget *m = gtk_menu_bar_new ();
GtkMenu *sm = GTK_MENU (gtk_menu_new ());
gtk_menu_append (sm, gtk_tearoff_menu_item_new ());
gtk_menu_append (sm, gtk_menu_item_new_with_label ("Menu Item"));
GtkWidget *r = gtk_menu_item_new_with_label ("Menu");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (r), GTK_WIDGET (sm));
gtk_menu_bar_append (GTK_MENU_BAR (m), r);
gtk_container_add (GTK_CONTAINER (w), m);
gtk_widget_set_size_request (w, 100, 50);
gtk_widget_show_all (w);
gtk_main ();
}
Please type xprop _NET_WM_WINDOW_TYPE
and click on the torn-off menu and report what it says.
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_MENU
One can change the layer via the layer menu for the main window,
but not for the tear-off menu, because YFrameWindow::updateLayer overrides:
case wtMenu:
newLayer = WinLayerMenu;
break;
Looks like incorrect to me.
So, what's the matter with menus being in the menu layer? Only pinnable toolbars and tear-off menus are in the menu layer...
gijsbers, Thanks for the fix. After commenting that line it behaves correctly, that is it stays on the same layer as parent window but no less than normal.
bbidulock, The behaviour changed around 2015-ish. It had not been like this before. The matter is such permament window covers everything including docks, notifications, its own application and other foreground applications. If that's the case with toolbars then it is also an issue.
That is what they are supposed to do, particularly when they are transients for their main window, whcih they are in the GTK case. This is the old Gnome2/WMH behaviour that used layers. Layers are not used by EWMH/NetWM, which, instead, uses a set of rules to stack windows without layers. Ice does not implement those rules because it was never written to do so. Under EWMH/NetWM rules they would not even be shown if the main window is not active, and when shown would always be above their main window. Ice does not handle transients properly either (because it does not track it properly) and cannot perform application modality either. That said, I don't see how @gijsbers change fixes anything.
To me this whole layer enforcement policy at lines 2479-2517 is wrong. Indeed, I've just commented it out and everything seems to work normally, although I have not tested notifications. I'll check on my corporate laptop on some other day on because there I have XFCE4 panel with all that blinking stuff.
How folks at Opendesktop and Gnome reinvented this wheel is unknown to me, but they've done a lot of bad things in the past trying to mimic OSX and Microsoft game consoles. Which is the reason I use icewm and not their work.
Anyway, I'm glad it's back to normal now. I didn't realise icewm was still developed until discovering this repository.
Which gimp and gtk versions did you use?
Removing that block solves the problem :)
It happens with Debian experimental (gimp 2.8.20-2 libgtk2.0-0:amd64 2.24.32-1) and also Debian stable (icewm 1.3.8 + gimp 2.8.18 + GTK 2.24.31) and probably all other versions of GTK, Qt and some other toolkits where _NET_WM_WINDOW_TYPE_MENU is set.
Motif is not affected as it does not use this property and icewm doesn't try putting permament windows on top of everything.
Now, overriding the layer does not really fix anything, because layers should not be used for any purpose other than determining the window type for old WinWM/WMH or Motif tool kits. Allowing the user to override the layer in a preferences file sets the dangerous precedent that the setting will be observed, when is is incorrect to set "layer" on the basis of window type, when layer should only be use to set window type when it is unspecified by the toolkit.
The proper solution here is to make ice stack windows in accordance with https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html and, in particular, sections "Layered stacking order" and "Stacking order". Under these rules, the GTK tear-off menus would wind up with other "normal" windows, but being a transient, would be placed above the gimp "main" window. They may also be hidden when they, their "main" window, or sibling transients, do not have focus in NextStep style as described in wm-spec under "_NET_WM_WINDOW_TYPE".
Indeed, and this is how it works after removing that block. Remark: tear-offs in Gimp are not transient for the main window (or any other window).
I did some research on this function and it started as a couple of ifs in the original 1.3.8:
if (fTypeDesktop)
newLayer = WinLayerDesktop;
if (fTypeDock)
newLayer = WinLayerDock;
The switch was added in commit b4902d8 "support all Net/WM actions, states, window types".
Yes, gimp violates ICCCM 2.0 and doesn't seem to care.
The point here is that it is not the setting of layer by window type that is the problem, but stacking windows by layer.
Well in my understanding the whole idea of layers is to have them stacked by layer first and then by normal window flow. At least this is how it's always worked.
The removal of transient property is intentional for Gimp. Otherwise its big menus would cover the image windows. GTK tear-offs are transient by default.
Anyway I checked how the switch-less icewm performs with XFCE. The panel and desktop need fixing through winoptions which is, I think, even better because it's configurable and the user can still override. Other than that everything seems to work normally.
Here, xeyes are placed in the OnTop layer, but their favourite is of course Below.
So gimp is at fault here: instead of breaking ICCCM 2.0 compliance by removing WM_TRANSIENT_FOR, it should set the window type to _NET_WM_WINDOW_TYPE_NORMAL to have them treated normally. We could override the incorrect window type, but we can't fix the ICCCM 2.0 violation. Please report to gimp project.