#14823 closed defect (fixed)

Menu not disabled when showing modal dialogs in wxGTK under Unity

Reported by: raananc Owned by:
Priority: normal Milestone: 2.9.5
Component: wxGTK Version: 2.9.4
Keywords: wxDialog modal gtk ubuntu unity Cc: dghart@…
Blocked By: Blocking:
Patch: yes

Description

Using 2.9.4 with GTK+2 on Ubuntu 12.04, with GCC.

A wxFrame has a menu and the menu item displays a dialog using ShowModal() (see below)

The problem is that the menu is not disabled while the dialog is displayed: each subsequent click on the menu item displays a new dialog window.

void mainframe::OnMenuitemClick( wxCommandEvent& event )
{
  DialogPage* dp = new DialogPage(this);
  
  dp->ShowModal();
}

class DialogPage: public wxDialog
{
....
};

Attachments (1)

messagedialog.diff download (824 bytes) - added by dghart 20 months ago.

Download all attachments as: .zip

Change History (21)

comment:1 Changed 22 months ago by raananc

The problem existed with 2.8.12, and is present with SVN of today.

comment:2 Changed 22 months ago by vadz

  • Keywords ubuntu unity added
  • Priority changed from critical to normal
  • Summary changed from 2.9.4 on GTK+2 wxDialog ShowModal is not modal to Menu not disabled when showing modal dialogs in wxGTK under Unity

Is this reproducible in the dialogs sample? Also, I guess this is with the default Unity desktop?

$DEITY knows I'm fed up with Ubuntu...

comment:3 Changed 22 months ago by raananc

This is reproduced with the dialogs sample.

Your intuition about Unity is confirmed, inasmuch as the behaviour with Ubuntu 10.04 (Gnome desktop) is as expected, with Modal disabling underlying window.

I'll post a bug with Ubuntu.

comment:4 Changed 22 months ago by vadz

  • Milestone set to 2.9.5

I won't hold my breath about this being fixed in Ubuntu, even they clearly did break GTK+ promise to make the dialog modal with just gtk_window_set_modal() that we do call. My guess would be that they hacked gtk_dialog_run() to allow their stuff to work with the standard modal dialogs but we don't use those, hence the problem. We probably will need to ignore any menu events while wxOpenModalDialogsCount != 0, e.g. do something like this:

  • src/gtk/menu.cpp

    diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp
    index 54856e2..548a441 100644
    a b  
    3030#include "wx/gtk/private/gtk2-compat.h" 
    3131#include "wx/gtk/private/mnemonics.h" 
    3232 
     33// this is defined in src/gtk/toplevel.cpp 
     34extern int wxOpenModalDialogsCount; 
     35 
    3336// we use normal item but with a special id for the menu title 
    3437static const int wxGTK_TITLE_ID = -3; 
    3538 
     
    4548 
    4649static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event) 
    4750{ 
     51    if ( wxOpenModalDialogsCount ) 
     52        return; 
     53 
    4854    event.SetEventObject( menu ); 
    4955 
    5056    wxEvtHandler* handler = menu->GetEventHandler(); 

Does this fix the problem for you?

P.S. Could you please also give your Ubuntu bug URL just in case they do decide to do something about this?

comment:5 follow-up: Changed 22 months ago by pcor

I think it is time to implement the fix described in http://trac.wxwidgets.org/ticket/14302#comment:6, namely setting the environment variable UBUNTU_MENUPROXY to 0 to disable this stupid "feature". I'm tired of polluting our code to try and deal with this broken system.

comment:6 Changed 22 months ago by raananc

The suggested patch does not solve the problem: it only disables the menu entry which launched the dialog. All other menu entries are enabled.

I posted a question on https://answers.launchpad.net/ubuntu/+question/214155, which will evolve into a bug later on.

comment:8 in reply to: ↑ 5 Changed 22 months ago by vadz

Replying to pcor:

I think it is time to implement the fix described in http://trac.wxwidgets.org/ticket/14302#comment:6, namely setting the environment variable UBUNTU_MENUPROXY to 0 to disable this stupid "feature". I'm tired of polluting our code to try and deal with this broken system.

The trouble with this is that it makes wx applications look non-native under Ubuntu and also that I'm far from sure about how long is this going to be continued to be supported by Ubuntu.

Replying to raananc

The suggested patch does not solve the problem: it only disables the menu entry which launched the dialog. All other menu entries are enabled.

I don't understand this... Could you please put a breakpoint in your menu handler and see where does it get called from? I must have missed some other place where we process menu events.

comment:9 Changed 22 months ago by raananc

An error in an app produced an error in my post. The patch has no effect at all: a clicked entry can be reclicked any number of times, displaying a new dialog each time. A second menu item launches a wxMessageBox, which can also be repeated indefinitely.

Debugging shows that line 51 of menu.cpp is only executed when line 417 of wxWidgets-2.9.4/include/wx/app.h 'static wxAppConsole *GetInstance() { return ms_appInstance; }' is executed after '/common/init.cpp is exited at line 472. When a menu item is clicked, line 51 of menu.cpp is not invoked. This explains why the patch has no effect.

I have no idea how to find where the menu handler gets called from. I am ready to look, but I need some indication on where to look.

comment:10 Changed 22 months ago by raananc

I posted to Ubuntu launchpad another bug regarding menus under Unity: Unity does not respect the order of menu items (https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1081006)

With the two bugs about menus under Unity (compiz), I have the impression that there is a lack of communication between the wxWidgets application and compiz: apparently, Ubuntu copies the application menu generated with wxWidgets to the Unity menu bar (top line of the screen) and hides the menu on the application window. With that, when a dialog is displayed with ShowModal(), the original application menu is probably disabled, but since it is hidden this has no effect. The copy of the menu at the top of the screen is not informed of the ShowModal() and reamins active.

comment:11 Changed 22 months ago by vadz

The patch of comment:4 indeed doesn't work, we need to do this in menuitem_activate() (too) to really fix this.

This is still not ideal as the menu items don't work now but still look enabled. It would be better if we could disable the menu before showing the first modal dialog in wxDialog::ShowModal() and reenable it before its return. But I don't know how to do it, using wxMenuBar::EnableTop() doesn't seem to do anything...

comment:12 Changed 22 months ago by VZ

  • Resolution set to fixed
  • Status changed from new to closed

(In [73007]) Ignore menu events while modal dialogs are shown in wxGTK.

Normally menus are disabled in this case but not when running under Ubuntu
Unity, so add an explicit test for this to avoid breaking the program expected
flow of control by allowing the user to show the same modal dialog twice, for
example.

This is not ideal, it would be better to visually disable the menu while the
modal dialogs are shown but is better than nothing.

Closes #14823.

comment:13 Changed 20 months ago by VZ

(In [73365]) Relax Unity menu interdiction hack to allow popup menus in modal dialogs.

The changes of r73007 fixed the problem with menus remaining active while a
modal dialog was shown (see #14823) but also disabled processing of the events
from any popup menus shown by the dialog itself. Reallow the latter while
still forbidding the former now by checking whether the window associated with
the menu is the dialog itself.

Closes #14961.

comment:14 Changed 20 months ago by dghart

  • Cc dghart@… added
  • Patch set
  • Resolution fixed deleted
  • Status changed from closed to reopened

While running 'dialogs' to check r73365 I made the mistake of testing at first using wxMessageBox, discovering that this doesn't disable unity's global menu anyway as it's not derived from wxDialog. messagedialog.diff remedies this.

wxMessageBox/wxMessageDialog are used often enough to be worth fixing. I expect there'll probably be other similar but less common exceptions e.g. wxProgressDialog, should anyone be sufficiently motivated to check.

Changed 20 months ago by dghart

comment:15 follow-up: Changed 20 months ago by vadz

  • Status changed from reopened to confirmed

That's really weird. I thought the problem with not disabling the menu was due to our own implementation of modal dialogs but if even the standard gtk_dialog_run() is still affected, this is even worse. Can Unity be really so broken?? Can anybody test whether message boxes don't disable the menus in other, pure GTK+, applications?

Anyhow, if we don't find anything, we definitely should apply this. The only change I'd like to do would be to add a small RAII helper class that would increment wxOpenModalDialogsCount in ctor and decrement it in dtor to avoid disabling the menus permanently by an accidental early return (I also think that we might have a problem even right now if an exception is thrown from inside the dialog event loop).

comment:16 in reply to: ↑ 15 Changed 20 months ago by pcor

Replying to vadz:

Can anybody test whether message boxes don't disable the menus in other, pure GTK+, applications?

I ran the following program on 12.04 and the menus are not disabled.

#include <gtk/gtk.h>

static void activate_test(GtkMenuItem*, GtkWindow* window)
{
    GtkWidget* dialog = gtk_message_dialog_new(window, GTK_DIALOG_MODAL,
        GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "a message", NULL);
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
}

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);
    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    GtkWidget* menu = gtk_menu_new();
    GtkWidget* mi = gtk_menu_item_new_with_mnemonic("_Test");
    g_signal_connect(mi, "activate", G_CALLBACK(activate_test), window);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);

    mi = gtk_menu_item_new_with_mnemonic("E_xit");
    g_signal_connect(mi, "activate", G_CALLBACK (gtk_main_quit), NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
    mi = gtk_menu_item_new_with_mnemonic("_File");
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), menu);

    GtkWidget* menubar = gtk_menu_bar_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar), mi);
    gtk_widget_show_all(menubar);
    gtk_container_add(GTK_CONTAINER(window), menubar);

    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show(window);
    gtk_main();
    return 0;
}

comment:17 Changed 20 months ago by vadz

Thanks Paul!

Should we report this as a bug to Ubuntu? To be honest, it doesn't look like reporting bugs to them ever does anything good but this really seems like something too gross to just be ignored... or am I underestimating them.

comment:18 Changed 20 months ago by vadz

There is already a Ubuntu bug for this.

comment:19 Changed 18 months ago by VZ

(In [73689]) Create a small helper class for Unity global menu bug workaround.

Encapsulate the code temporarily incrementing wxOpenModalDialogsCount in a
small helper class to make it easier to reuse it elsewhere.

See #14823.

comment:20 Changed 18 months ago by VZ

  • Resolution set to fixed
  • Status changed from confirmed to closed

(In [73690]) Disable Unity global menu while native modal dialogs are shown in wxGTK.

We need to use wxOpenModalDialogLocker even with native GTK+ dialogs to
prevent the menu commands from being available while they're shown, so do it
in wxMessageDialog and wxColourDialog which call gtk_dialog_run().

Closes #14823.

Note: See TracTickets for help on using tickets.