Focus problems when using GBUI to launch an external browser window

I'm using GBUI and love it. however I have the following problem:



I use a GBUI button to launch a url in a browser. this works fine. however when the user clicks the game window to go back to the game, the GBUI button retains focus, actuates a click, and relaunches the browser. this goes on forever (or if you click on the chrome of the game window first you can break out of the loop).



I'm including a simple test called FocusBrowserTest that demonstrates the issue. any help would be greatly appreciated.



(note: my platform is Mac OSX; i found the showInBrowser method online somewhere)


package com.jmex.bui.tests;

import java.io.IOException;
import com.jmex.bui.BButton;
import com.jmex.bui.BWindow;
import com.jmex.bui.BuiSystem;
import com.jmex.bui.event.ActionEvent;
import com.jmex.bui.event.ActionListener;
import com.jmex.bui.layout.GroupLayout;

public class FocusBrowserTest extends BaseTest2 {
   String url = "http://www.google.com";
   BButton button;
    protected void createWindows() {
        BWindow window = new BWindow(BuiSystem.getStyle(), GroupLayout.makeVStretch());
        button = new BButton(url);

        button.addListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
               showInBrowser(button.getText());
            }
        });
       
        window.add(button);
        window.setSize(400, 400);
        BuiSystem.addWindow(window);
        window.center();
    }

    public static void main(String[] args) {
        new FocusBrowserTest().start();
    }
   
   public boolean showInBrowser(String url) {
       String os = System.getProperty("os.name").toLowerCase();
       Runtime rt = Runtime.getRuntime();
       try {
               if (os.indexOf( "win" ) >= 0) {
                 String[] cmd = new String[4];
                 cmd[0] = "cmd.exe";
                 cmd[1] = "/C";
                 cmd[2] = "start";
                 cmd[3] = url;
                 rt.exec(cmd);
               } else if (os.indexOf( "mac" ) >= 0) {
                   rt.exec( "open " + url);
               } else {
                 //prioritized 'guess' of users' preference
                 String[] browsers = {"epiphany", "firefox", "mozilla", "konqueror", "netscape","opera","links","lynx"};
   
                 StringBuffer cmd = new StringBuffer();
                 for (int i=0; i<browsers.length; i++)
                   cmd.append( (i==0  ? "" : " || " ) + browsers[i] +" "" + url + "" ");
   
                 rt.exec(new String[] { "sh", "-c", cmd.toString() });
              }
       } catch (IOException e) {
          System.err.println("showInBrowser("+url+") IOException");
           e.printStackTrace();
           return false;
       }
       return true;
   }        
}

Perhaps in your action listener you can remove focus from the button as its clicked. Just throwing out ideas…

does your button have to be focusable?  If not try:


Button.setFocusable( false );


(although that is a pure swing method, so maybe its not in GBUI...)

good idea, but unfortunately i don't think there's anything like a setFocusable method for BComponents in GBUI. i've also tried un-enabling the button and tried other obvious candidates like this:



window.getWindow().getRootNode().requestFocus(somethingElse);



no dice. i'm just not having much luck forcing the focus to change, or "flushing" the button click completely. i also tried wrapping the browser exec call inside a thread. same. 



[EDIT: actually it appears not to be a focus problem at all. button.hasFocus() remains false throughout. so it must be something about fully flushing the click.]

okay it's not a gbui issue at all i don't think. sorry for the confusion :slight_smile:



apparently the mouse x/y coords are cached from the last mouse position, so when you click back on the game window it triggers a mouse event using the old mouse x/y coords.



example: if i click a button at mouse position 200x300, exec the browser window, then click back inside the game window approximately at position 10x10, MouseInput.get().getXAbsolute() and MouseInput.get().getYAbsolute() still show 200x300.



so is there a way for me to flush/nullify/etc the mouse x/y coords?

Not sure, maybe you can figure out a way to consume the first click when returning to the game window preventing it from reaching other listeners. Or, set a boolean on the first click when launching the browser, and when the second (returning click) happens you just reset your boolean and ignore the click. This seems hacky, but it may work for you.

i've found the following hack that seems to work. after launching the external window, you can reset the mouse coords like this:



            MouseInput.get().setCursorPosition(0, 0);



thanks everyone for the suggestions.