Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

how to get GUI.Window focus?

Discussion in 'Immediate Mode GUI (IMGUI)' started by Abe, Feb 18, 2009.

  1. Abe

    Abe

    Joined:
    Feb 14, 2008
    Posts:
    35
    Hi,
    I have two GUI.Window.WindowID are 1, 2.
    How do I know which Window is focusing?

    Thanks.
     
  2. Abe

    Abe

    Joined:
    Feb 14, 2008
    Posts:
    35
    Anybody please to help me this!
     
  3. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
  4. Abe

    Abe

    Joined:
    Feb 14, 2008
    Posts:
    35
    Hi Quietus,
    When I draw two Windows then both callback functions are called, but the focusing is the last called.

    My situation: I have two GameObjects, each will draw one GUI.Window with different WindowID. When I click Delete Key on keyboard, I want to know which Window is focusing in order to process with different task.

    At your link, I don't see it can help me with this stuff. It is different from my situation.

    Thanks.
     
  5. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    There was a recent thread on how to trick Unity to get some kind of mousehover

    you could attempt the same solution for this.

    But above that, there is no functionality like that.

    At simplest you just do it differently and much simpler:
    Ensure each window is in its own script / class.
    Put a bool variable in there.
    Draw the window only if that variable is true
    and then add close functionality where it is meant to be: into the window code
    and close functionality just sets the bool to false

    or another alternative
    A global variable in some globally accessable context that holds a "last window" reference. whenever a gui element is used in some way you update that reference to hold the current window handle
     
  6. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Ok so you're not actually driving focus by clicking on an element within the window.

    If you look at the bottom of the documentation it states that one cannot count on the window functions to be called in any particular order. If they overlap, the front most window will be called last and that callback should be the one that has focus.

    So if you're not clicking in the window and they don't overlap I'm not sure how you would go about determining focus, or that it can be done at all.
     
  7. Abe

    Abe

    Joined:
    Feb 14, 2008
    Posts:
    35
    Thank Quietus and dreamora.

    I found the way can resolve this.

    As dreamora wrote, I use a *global* variable as focusing WindowID (for example: m_focusingID). Then each window function callback, I just only write:

    Code (csharp):
    1. if ((Event.current.button == 0)  (Event.current.type == EventType.MouseDown)) {
    2.      m_focusingID = windowID;
    3. }
    And it works!!!. At first, I think this code ALWAYS set m_focusingID = windowID. But I am suprised, it only run when you click on Window zone(window area), and position that Mouse returns is position in Window zone.

    Thanks!
     
  8. DerWoDaSo

    DerWoDaSo

    Joined:
    May 25, 2009
    Posts:
    131
    Thanks guys for sharing your solution! :)
     
  9. twoopy

    twoopy

    Joined:
    Dec 3, 2010
    Posts:
    2
    There is another (simpler) way. You will find that if you use "MouseUp" unity will automatically know which Window you are in..

    For example, if you have:
    Code (csharp):
    1. void SomeWindow(int id){
    2.    ...
    3.    if ((Event.current.button == 0)  (Event.current.type == EventType.MouseUP)) {
    4.      //some stuff
    5.    }
    6. }
    inside your SomeWindow(int id) function you can handle coding specific to that window. You could also set a flag to remember the last window to be accessed. The key here is the MouseUp as MouseDown will not work (you can't have it all)..
     
  10. outofinspiration

    outofinspiration

    Joined:
    Oct 3, 2011
    Posts:
    3
    But how can you know if no window is selected? Cause now the last window will stay registered as active. And will not be setted to null.
    any ideas?
     
  11. PaulAsh

    PaulAsh

    Joined:
    Nov 29, 2010
    Posts:
    108
    Heres out I determine the focused window, it is dark magic of reflection because GUI does have an internal static member for the current focusedWindow.

    Be careful with this code if you use it if they change the static fields name it will break;

     
  12. outofinspiration

    outofinspiration

    Joined:
    Oct 3, 2011
    Posts:
    3
    Wow PaulAsh tanks soo much! This works perfectly and saves me so much time! I like the black voodoo, me want more!
     
  13. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    177
    Awesome work :)
     
  14. garkin

    garkin

    Joined:
    Jun 16, 2012
    Posts:
    3
    Wrote same hack-fu reflection code day ago. And do u know what? It does not works in webplayer, due security restrictions of private and internal variables acces.
    Why are 'focusedWindow' not public? I see absolutely no particular reason fo that. IMGUI sucks all way ahead, but Unity realization of it sucks even more. I hope NEWGUI™ will be OOP, and done completely not in Unity's best traditions.
     
  15. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    I wrote a ton of reflections myself and it all works in the browser.

    I'm not sure about this particular example, since it tries to reflect something from 'Unity class'.

    btw I'm interested if the reflection above works on iOS?

    Thanks...
     
  16. mkgnzlz

    mkgnzlz

    Joined:
    Aug 13, 2010
    Posts:
    2
    Very Awsome Indeed!!! Works Great!!!
     
  17. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    177
    Sadly this is now broken in 4.x - anyone resolved this for 4.x?
     
  18. amw157

    amw157

    Joined:
    Jun 11, 2012
    Posts:
    6
    Bump? Any solutions for Unity 4?
     
  19. Deleted User

    Deleted User

    Guest

    also interested ff anyone resolved rhis for 4.x
     
  20. yoyo

    yoyo

    Joined:
    Apr 16, 2010
    Posts:
    112
    I don't have Unity 4 installed, but if you open your Unity 4 project in MonoDevelop you can right click on the GUI class (anywhere you use it, for example the GUI.Window(...) call) and "Go to declaration" to open the GUI class in the Assembly Browser. This will show you all the public and private fields, properties and methods, so you can see if there is a new field along the lines of the old "focusedWindow".

    Note that for the Assembly Browser to find the Unity DLL's you need to add the right path (e.g. "C:/Program Files(x86)/Unity/Editor/Data/Managed") to your MonoDevelop > Options > Preferences > Build >Assembly Folders setting.
     
  21. im

    im

    Joined:
    Jan 17, 2013
    Posts:
    1,408
    i tried this with latest unity 4.3.x

    u can use something like this in each window called in OnGUI

    Code (csharp):
    1.  
    2.     void UpdateFocus()
    3.     {
    4.         if ((Event.current.button == 0)  (Event.current.type == EventType.mouseUp))
    5.         {
    6.             hudController.windowWithFocus= this;
    7.         }
    8.     }
    9.  

    you must define this in HudController

    Code (csharp):
    1.  
    2.         MonoBehavior windowWithFocus
    3.  
    still its not 100% bullet proof since i need to find way to set it to lets say null when none of the windows have focus like when someone does not click on a window but lets say clicks on nothing outside of gui. i mean if they click on an object u can always do an OnMouse in a component attached to the object. but sometimes they can click on nothing...

    and the only way i could think of is to do something like this that Update in HudController would call

    Code (csharp):
    1.  
    2.     void UpdateFocus()
    3.     {
    4.         if(Input.GetMouseButtonUp(0))
    5.         {
    6.             if(menubar.window.Contains(Input.mousePosition))
    7.             {
    8.                 return;
    9.             }
    10. .... do above check for each control ...
    11.             else
    12.             {
    13.                 hudElementWithFocus = null;
    14.             }
    15.         }
    16.     }
    17.  
    but that is messy clunky slow way of doing thing since obviously unity knows who has focus and could tell us...

    and yeah we need some api to find out during runtime which gui control has focus, also would be nice to have api for which gui window has focus

    right now all we have is OnMouseDown which is not fired for all controls and SetNameOfFocusedControl/GetNameOfFocusedControl which does not work with all controls

    so if i have a bunch of windows and one of the windows has just a label i really never know when it has focus since on OnMouseDown nor SetNameOfFocusedControl/GetNameOfFocusedControl work...

    since we r getting a new gui w 4.6 hopefully we will get better apis...
     
    Last edited: Apr 1, 2014
  22. ARTsev

    ARTsev

    Joined:
    Jul 23, 2014
    Posts:
    4
    Tested on Unity 5

    Code (CSharp):
    1.     void OnGUI()
    2.     {
    3.         _window1 = GUI.Window(1, _window1, DrawWindow, "Window 1");
    4.         _window2 = GUI.Window(2, _window2, DrawWindow, "Window 2");
    5.     }
    6.  
    7.     void DrawWindow(int id)
    8.     {
    9.         GUI.DragWindow();
    10.         if (Event.current.GetTypeForControl(id) == EventType.Used)      
    11.            _focusedWindowId = id;          
    12.     }
    variable _focusedWindowId contains focused window id ;)
     
    Corum, BennyKokMusic and samana1407 like this.
  23. BennyKokMusic

    BennyKokMusic

    Joined:
    Dec 22, 2016
    Posts:
    33
    This work perfectly but is there any way to know if no window was focused, maybe use the id to get the state of the window, is there any api for that?
     
  24. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    Why not use EditorWindow.focusedWindow ?
     
  25. BennyKokMusic

    BennyKokMusic

    Joined:
    Dec 22, 2016
    Posts:
    33
    Thx for replying, I thought it doesn't include the windows created by the gui method.
     
  26. JHobsie

    JHobsie

    Joined:
    Aug 3, 2015
    Posts:
    9
    I came across this issue for myself and I may be wrong in my assumption but I think input events (MouseDown/Up/Drag) etc only fire for the window that is currently in focus. (I haven't tried for keyboard or the dragdrop event)

    So similar to ARTsev's implementation, I just store the window ID of the last window to recieve an input event, regardless of if it gets used or not (it may not be a draggable window).

    This won't help if you want to know if no window has focus though as it'll just maintain the last window to have focus.

    Code (CSharp):
    1. static int focusedWindowID;
    2.  
    3. int windowID;
    4.  
    5. bool hasFocus { get { return windowID == focusedWindowID; } }
    6.  
    7. void  OnWindowGUI(int id)
    8. {
    9.     Event e = Event.current;
    10.     if(e.type == EventType.MouseDown ||
    11.     e.type == EventType.MouseUp ||
    12.     e.type == EventType.MouseDrag ||
    13.     e.type == EventType.MouseMove)
    14.     {
    15.         focusedWindowID = id;
    16.     }
    17.      
    18.     // do other gui stuff
    19. }
     
  27. sbsmith

    sbsmith

    Joined:
    Feb 7, 2013
    Posts:
    126
    I'm just starting to poke at this too and JHobsie's trick does work. If you want to see if nothing is selected, you just need to put an additional event check on the Window itself.

    This would all be inside some EditorWindow and DrawWindows is called from inside OnGUI.

    Code (CSharp):
    1.  
    2. private int m_focusedWindow = -1;
    3.  
    4. private void DrawWindows()
    5. {
    6.     BeginWindows();
    7.  
    8.     for( int iNode = 0; iNode < fakeListOfWindows.Count; ++iNode )
    9.     {
    10.         FakeNode node = fakeListOfWindows[ iNode ];
    11.  
    12.         Rect rect = FakeGetNodeWindowRect( node );
    13.         Rect movedRect = GUILayout.Window(
    14.             iNode,
    15.             rect,
    16.             delegate ( int id )
    17.             {
    18.                 Event windowEvent = Event.current;
    19.                 if( EventType.MouseDown == windowEvent.type ||
    20.                     EventType.MouseUp == windowEvent.type ||
    21.                     EventType.MouseDrag == windowEvent.type ||
    22.                     EventType.MouseMove == windowEvent.type )
    23.                 {
    24.                     m_focusedWindow = id;
    25.                 }
    26.  
    27.                 node.DrawNode();
    28.                 GUI.DragWindow();
    29.             },
    30.             node.GetType().ToString() );
    31.     }
    32.    
    33.     EndWindows();
    34.  
    35.     Event canvasEvent = Event.current;
    36.     if( EventType.MouseDown == canvasEvent.type ||
    37.         EventType.MouseUp == canvasEvent.type ||
    38.         EventType.MouseDrag == canvasEvent.type ||
    39.         EventType.MouseMove == canvasEvent.type )
    40.     {
    41.         m_focusedWindow = -1;
    42.     }
    43.  
    44.     Debug.Log( string.Format( "Focused window: {0}", m_focusedWindow ) );
    45. }
    46.  
     
    Igorexa likes this.
  28. mara_art

    mara_art

    Joined:
    Sep 23, 2020
    Posts:
    1
    The actually working condition is
    Code (CSharp):
    1.  
    2.             if ((E.type == EventType.MouseDown ||
    3.                 E.type == EventType.MouseUp ||
    4.                 E.type == EventType.MouseDrag ||
    5.                 E.type == EventType.MouseMove) || E.GetTypeForControl(ID) == EventType.Used)
    6.             {
    7.                 FocusedID = ID;
    8.             }
    9.  
    Which combines the two from this thread. First part checks for clicks where there are no controls (just the window body), second detects if any controls were clicked (otherwise the buttons clicked in a window STILL consume the event or something, im not sure but this is the only way it works).