Detecting MouseUp Outside EditorWindow without "hotControl"

First, some foundation for the question. In my EditorWindow I have a Scroll View created with EditorGUILayout.BeginScrollView/EndScrollView. I then use the Rect created there to similarly position a Group, created with GUI.BeginGroup. Inside of that I do a whole bunch of custom drawing including some standard GUI fields, passing them custom Rects.

I have my own system of selection, which includes drawing a selection box when the mouse is dragged over that content Group. Everything works like a charm except detecting MouseUp events when outside of the editor window.

The main Unity Scene does precisely this so I know that it’s possible. The only question is how is it done?

This does appear to be a fairly common question, and only one viable solution appears to exist as I understand it. That solution does not work for me, however.

The solution linked above appears to require the use of GUI.hotControl to be set to something that receives mouseUp events (with the correct FocusType set?). But I do not have a control to focus anyway: Groups/Scroll Views appear to never take “focus”. When I detect the right situation in my GUI, I clear the focus entirely using GUI.FocusControl(""). This leaves me to handle the mouse events as I see fit.

When the mouse is over the EditorWindow, this works flawlessly. When I drag to a position outside of the window, however, I continue to get events with type EventType.MouseDrag until I release the mouse button. (I get events by calling Repaint() in Update() when I have an active selection box). When I release the button, I stop getting updates entirely.

This means that I never get the MouseUp event and I only start getting MouseMove events again once the mouse is actually over the EditorWindow. This happens even when I force a Repaint() for every call to Update().

According to everything I’ve seen and my own personal tests with Unity-provided controls (TextFields, for instance), I simply never get those events (e.g. when dragging a selection over some text in a test TextField, the event flow is identical to what I described above).

For the time being, I now have the selection disappearing when an active selection exists and MouseMove event is encountered. This clears the selection once the user hovers over the window again. Far less than ideal, but workable.

How do I make sure these events reach my EditorWindow?

The main Scene View appears to be able to handle these events and certain documentation makes it seem viable. What is the magic sauce?

Edit: I’m running Unity 4.5.4f1 on Mac OSX.

1 Like

The aforementioned viable solution does work. I created a really simple test window that merely output the current event into the Debug console. I suddenly started seeing EvenType.Ignore types along with the EventType.MouseUp events in the rawType report.

It turns out I’d surrounded my debug output in my main codebase with the following:

if (Event.current.isMouse)
{
    HandleMouseInput();
}

The problem is that EventType.Ignore isn’t considered a mouse event even if the underlying rawType is.

Good to know. Hopefully this will help someone else in the future, too!

1 Like

Hey, sorry to dig up a dusty old thread. But I’m unable to get any mouse up events outside my editor window either.
No idea how you got it working SonicBloomEric or this viable solution

I just have a simple window:

public class WindowTest : EditorWindow {

    [MenuItem("Window/WindowTest")]
    static void Open() {

        GetWindow<WindowTest>();
    }

    private void OnGUI() {

        //OnGUI never called when mouse is outside EditorWindow :(

        Debug.Log(Event.current.type + " - " + Event.current.rawType);
    }

    private void Update() {

        //Update never receives an event!

        if (Event.current != null) {

            Debug.Log(Event.current.type + " - " + Event.current.rawType);
        }
    }
}

Where should I be capturing mouse events when mouse is outside Editor Window?
This is driving me insane :hushed:

Nevermind, you DO need to set the hotControl

public class WindowTest : EditorWindow {

    [MenuItem("Window/WindowTest")]
    static void Open() {

        GetWindow<WindowTest>();
    }

    private void OnGUI() {

        int controlId = GUIUtility.GetControlID(FocusType.Passive);

        Event evt = Event.current;

        switch (evt.GetTypeForControl(controlId)) {

            case EventType.MouseDown:

                //Important, must set hotControl to receive MouseUp outside window!

                GUIUtility.hotControl = controlId;
                evt.Use();
                break;

            case EventType.MouseUp:

                Debug.Log("Mouse Up, Hoorah!");
                evt.Use();
                break;
        }
    }
}

Interesting that if you set “keyboardControl” instead, you need to handle using “rawType”

4 Likes

@CDF Thank you!

// Important, must set hotControl to receive MouseUp outside window!
int controlId = GUIUtility.GetControlID(FocusType.Passive);
if (Event.current.GetTypeForControl(controlId) == EventType.MouseDown)
    GUIUtility.hotControl = controlId;