Sys.alert(...) not working, no message dialog

Started by Ciardhubh, March 16, 2009, 12:15:30

Previous topic - Next topic

Ciardhubh

Hi,

I ran into a strange problem. Sys.alert(...) is no longer working. It was working on my computer some time ago. However during tests today, I realised that it does no longer show a message dialog. I only get the default windows error sound "plonk" but no dialog.

import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;

public class SysAlertTest {

    public static void main(String[] args) {
        Sys.alert("Title", "Message!");
        try {
            Display.create();
            Sys.alert("Title", "Message!");
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }
}


I tried both before and after Display.create(...). The above code plays the error sound twice but shows no dialog.

I ran a debugging session and found out that the error sound plays when nAlert(...) in the Windows implementation of Sys gets called.

This is on:
Windows XP SP3
Java 6
LWJGL 2.0.1

Strangely the webstart LWJGL SysTest demo works and shows a dialog. If I download its source and run it without webstart, it no longer works.

Is there something wrong with my code? Am I missing something?

Matzon

Can reproduce that it doesn't show prior to displaying a window. I tried creating a completely new native function and regardless of what I do it doesn't show (GetDesktopWindow, NULL, etc)... not sure why.
Any takers?

Ciardhubh

Quote from: Matzon on March 16, 2009, 20:35:18
Can reproduce that it doesn't show prior to displaying a window.

Ah thanks, that's a good hint. Looks like the necessary (AWT?) libraries do not get loaded by Sys.alert(). This would explain why it works with web start, which shows a splash screen before the actual application gets launched.

First, I tried to create a simple frame (java.awt.Frame frame = new java.awt.Frame();) prior to Sys.alert() and it worked. So I checked constructors and static parts of Frame/Window. They load certain native libraries in their static {} constructor via Toolkit. Since all they use is private or package-only, I tried Toolkit.getDefaultToolkit(); and it worked:
    public static void main(String[] args) {
        Toolkit.getDefaultToolkit();
        Sys.alert("Title", "Message!"); // Works
    }


During the construction of java.awt.Toolkit libraries get loaded. Issueing this load call prior to using Sys.alert() also fixes it:
    public static void main(String[] args) {
        java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("awt"));
        Sys.alert("Title", "Message!"); // Works too
    }


I don't really know what the side effects of both calls are. Is it a problem to instantiate a default Toolkit in some cases? Do libraries get loaded twice with the second? Are libraries unloaded at some point?

At least it's a workaround :)

Elviz

This is still reproducible in 2.2.1 on Windows XP.

Without the Toolkit.getDefaultToolkit(); workaround, there's no visible alert.

Matzon

I have not been working on fixing this - so yes still there. Absolutely clueless as to why its happening.

Elviz

Found a comment in the NSIS source that at least sounds like it's referring to a similar problem:

  // workaround for bug #1400995
  //
  // for an unexplained reason, MessageBox with MB_TOPMOST
  // will fail, if no other messages were sent from this
  // thread to the GUI thread before it.
  //
  // the source of the problem couldn't be found, so a
  // WM_NULL is sent to work around it.

Matzon

hmm, not able to reproduce it anymore using 2.2.1 and Vista

Matzon

I can only reproduce it on windows xp - and I have a fix for it. Will commit tonight.

MessageBox is part of the Windows Common Controls - so we need to call: http://msdn.microsoft.com/en-us/library/bb775697%28VS.85%29.aspx prior to calling MessageBox. This is done behind the scenes (apparently) when creating a display.

aldacron

Quote from: Matzon on December 02, 2009, 08:43:29
MessageBox is part of the Windows Common Controls - so we need to call: http://msdn.microsoft.com/en-us/library/bb775697%28VS.85%29.aspx prior to calling MessageBox. This is done behind the scenes (apparently) when creating a display.

That doesn't sound right to me. This C code works just fine without initing the common controls or creating any windows:

int main(int argc, char **argv)
{
    MessageBox(0, "Blah", "Bleh", MB_OK);
}


Also, MessageBoxA/W are in User32.dll, not Comctl32.dll. And I'm quite sure that InitCommonControlsEX is not called behind the scenes when creating a normal window, otherwise there'd be no reason to call it in apps that use common controls.