Jump to content

[SOLVED] InterfaceWindow focus problem


photo

Recommended Posts

It seems in certain situations it is possible to click widgets in the main gui while there is an interface window before it. The mouse event seems to go right through the interface window to the main window that is behind it, making it possible to accidentally click on a button that isn't visible, as seen below (I made the interface window partially overlap in this case so you can see the button being hit):

post-999-0-16667900-1406879651_thumb.png

 

It can be reproduced with the following world script with the 2014-07-07 Sim SDK:

WidgetGroupBox wgb;
WidgetButton wb;
InterfaceWindow iw;
WidgetGroupBox iwg;
int init() {
    iw = new InterfaceWindow( INTERFACE_WINDOW_TITLE );
    iw.setWidth( 500 );
    iw.setHeight( 500 );
    iw.setPosition( 200, 200 );
    iw.setHidden( false );
    iwg = new WidgetGroupBox( iw.getGui() );
    iwg.setBackground( true );
    Gui( iw.getGui() ).addChild( iwg, GUI_ALIGN_EXPAND );

    wgb = new WidgetGroupBox( engine.getGui() );
    wgb.setWidth( 300 );
    wgb.setHeight( 100 );
    wgb.setBackground( true );
    wb = new WidgetButton( engine.getGui(), "Button" );
    wgb.addChild( wb, GUI_ALIGN_CENTER );
    Gui( engine.getGui() ).addChild( wgb, GUI_ALIGN_EXPAND );
    
    return 1;
}

After starting it, position the interface window to overlap the button, then click anywhere on the background of the main window and try to click the button that is behind the interface window, and it will be hit. Now click anywhere in the background of the interface window that is not in front of the button and try to hit the button again, now it will not be hit. Hit the background of the main window again and the click-though problem will reappear. Right now it seems you need to click anywhere on the interface window that does not overlap any input elements (buttons or listboxes) in order to give the interface window focus, otherwise the main window will keep having focus when it comes to intercepting mouse events.

Link to comment
  • 1 month later...
  • 4 weeks later...
  • 3 weeks later...

I'm afraid the problem just got a lot worse with the new version. Instead of being able to click through the interface window, you now cannot click on the interface window at all anymore after you click on the background of the main window. In the same test case, move the button to the interface window (replace wgb.addChild( wb, GUI_ALIGN_CENTER ) with iwg.addChild( wb, GUI_ALIGN_CENTER )) and click somewhere on the background of the main window and you will not be able to click on the interface window button anymore. Only once you click on some interactive widget on the main window (like a button or listbox), the interface window becomes responsive again.

Link to comment

Hi Bemined,

We've added this issue to our bug tracker.

For now you can use the following code as a workaround:

#include <core/unigine.h>
WidgetGroupBox wgb;
WidgetButton wb;
InterfaceWindow iw;
WidgetGroupBox iwg;

/*
 */
int init() {
	iw = new InterfaceWindow(INTERFACE_WINDOW_TITLE);
	iw.setWidth(500);
	iw.setHeight(500);
	iw.setPosition(200, 200);
	iw.setHidden(false);
	iwg = new WidgetGroupBox(iw.getGui());
	iwg.setBackground(true);
	iwg.setWidth(500);
	iwg.setHeight(500);
	
	//iw.setWidget(iwg); // Works fine
	Gui(iw.getGui()).addChild(iwg, GUI_ALIGN_EXPAND); // Doesn't work

	wgb = new WidgetGroupBox(engine.getGui());
	wgb.setWidth(300);
	wgb.setHeight(100);
	wgb.setBackground(true);
	wb = new WidgetButton(engine.getGui(), "Button");
	wb.setCallback(GUI_CLICKED,functionid(click));
	iwg.addChild(wb, GUI_ALIGN_CENTER );
	Gui(engine.getGui()).addChild(wgb, GUI_ALIGN_EXPAND);
	
	return 1;
}

Link to comment
  • 2 weeks later...

Thanks, I finally got around to test it, and with setWidget the focus works correctly. But it gives us again another problem when we do this with a WidgetWindow with an interface window without border or native titlebar. With the following code, it shows a nice WidgetWindow in an InterfaceWindow that can be moved around and resized. However if you try to resize from the top or left side, the window will start jumping up and down, it does get bigger, but only to about halfway where the cursor is, and as long as you drag the mouse it keeps jumping between halfway the cursor and the original position.

InterfaceWindow iw;
WidgetWindow ww;
int init() {
    iw = new InterfaceWindow( 0 );
    iw.setHidden( false );
    ww = new WidgetWindow( iw.getGui() );
    ww.setWidth( 500 );
    ww.setHeight( 500 );
    ww.setSizeable( 1 );
    ww.setMoveable( 1 );
    iw.setWidget( ww );
}

In the Unigine editor the windows do resize correctly, is some additional code required for this? I remember for the old way (before setWidget was introduced) some special code was needed for resizing, does this new method require some manual syncing as well of the widget window and interface window?

Link to comment

Hi there!

 

Why don't you use widgets from core/systems/widgets? They're compatible both with interface and non-interface version of the engine. Inside the editor we're relying heavily on them and more or less happy with the results. :)

 

There's nothing special inside core/systems/widgets/widget_window.h, it just uses InterfaceWindow as usual.

 

I'll dig into your sample and report back.

Link to comment

Thanks for your help again, using engine.getGui() indeed fixes the resize problem. Unfortunately it seems to be a never ending story, there is one very specific case in which the interface window is still blocked. Took me some time to reproduce it (internally we are using .ui files, so there are many widgets involved), but I found a way to reproduce it. It turns out that when you have a WidgetSprite below your interface window, which has the ALIGN_OVERLAP flag, and has at least one mouse callback specified, you cannot click on the interface window before the sprite when the sprite has focus:

WidgetSprite sprite = new WidgetSprite( engine.getGui() );
sprite.setWidth( 500 );
sprite.setHeight( 500 );
sprite.setCallback( GUI_PRESSED, "foo" );
engine.gui.addChild( sprite, GUI_ALIGN_OVERLAP );

The callback is needed because only a WidgetSprite with a callback seems to be able to take focus. Why it only happens with overlap and not with expand I did not figure out, it just does. To reproduce, first position an interface window partially over the sprite, then click on the sprite to give it focus, and you cannot click the button anymore until you click somewhere outside the sprite on the main window first.

Link to comment

Hi there!

 

I did a few tests and looks like I have a solution for you yet I believe focus handling should be definitely improved inside the GUI system. So in your callback just call removeFocus on that sprite.

 

Here's my code:

/*
 */
InterfaceWindow iw;
WidgetWindow ww;
WidgetSprite sprite;

void foo() {
	engine.message("hi there!\n");
	sprite.removeFocus();
}

/*
 */
int init() {
	
	iw = new InterfaceWindow( 0 );
	iw.setHidden( false );
	ww = new WidgetWindow( engine.getGui() );
	ww.setWidth( 500 );
	ww.setHeight( 500 );
	ww.setSizeable( 1 );
	ww.setMoveable( 1 );
	iw.setWidget( ww );
	
	sprite = new WidgetSprite( engine.getGui() );
	sprite.setWidth( 500 );
	sprite.setHeight( 500 );
	sprite.setCallback( GUI_PRESSED, "foo" );
	engine.gui.addChild( sprite, GUI_ALIGN_OVERLAP );
        
        return 1;
}
Link to comment

Thanks, it seems to be working now. I did had to move to code to GUI_RELEASED callback since we are relying on mouse move events, but it seems to do the trick as well. I do still seems to get dragging mouse events through the interface window (if I click the interface window to move it, the sprite below also gets the event) but this is a minor issue for now us at the moment.

Link to comment
×
×
  • Create New...