icewm icon indicating copy to clipboard operation
icewm copied to clipboard

GTK tear off menus in menu layer

Open Matlib opened this issue 6 years ago • 18 comments

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?

Matlib avatar Mar 11 '18 21:03 Matlib

man icewm-winoptions gimp.layer: Normal

gijsbers avatar Mar 12 '18 00:03 gijsbers

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
--

Matlib avatar Mar 12 '18 00:03 Matlib

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 ();
}

Matlib avatar Mar 13 '18 06:03 Matlib

Please type xprop _NET_WM_WINDOW_TYPE and click on the torn-off menu and report what it says.

bbidulock avatar Mar 13 '18 10:03 bbidulock

_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.

gijsbers avatar Mar 13 '18 12:03 gijsbers

So, what's the matter with menus being in the menu layer? Only pinnable toolbars and tear-off menus are in the menu layer...

bbidulock avatar Mar 13 '18 16:03 bbidulock

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.

Matlib avatar Mar 13 '18 22:03 Matlib

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.

bbidulock avatar Mar 14 '18 01:03 bbidulock

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.

ice_gimp

Matlib avatar Mar 14 '18 06:03 Matlib

Which gimp and gtk versions did you use?

gijsbers avatar Mar 14 '18 14:03 gijsbers

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.

Matlib avatar Mar 14 '18 22:03 Matlib

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.

bbidulock avatar Mar 17 '18 23:03 bbidulock

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".

bbidulock avatar Mar 17 '18 23:03 bbidulock

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).

tearoff

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".

Matlib avatar Mar 18 '18 06:03 Matlib

Yes, gimp violates ICCCM 2.0 and doesn't seem to care.

bbidulock avatar Mar 18 '18 07:03 bbidulock

The point here is that it is not the setting of layer by window type that is the problem, but stacking windows by layer.

bbidulock avatar Mar 18 '18 10:03 bbidulock

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.

icexfce

Here, xeyes are placed in the OnTop layer, but their favourite is of course Below.

Matlib avatar Mar 18 '18 18:03 Matlib

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.

bbidulock avatar Mar 18 '18 21:03 bbidulock