Selective Auto-Raise for Windows

Motivation

2015-08-04 All of you guys who think focus-follows-mouse is the natural way to interact with a windowing GUI, possibly combined with auto-raise (which is the variant I prefer), will know that MS-Windows has for a long time now offered the "XMouse" option first through its TweakUI add-on tool – which goes back all the way to PowerToys for Windows 95 –, then from Windows 7 on through the Accessibility Settings in Control Panel.

History lesson: TweakUI 1.33 (German version shown here) running on Windows 2000 Server, offering the focus-follows-mouse and auto-raise options:

Windows 7 Accessibility Center, offering the auto-raise option:

There is also the very recommendable command-line utility XMouse.exe which is easy to compile with every normal .NET Framework installation, which is actually needed on Windows 7 to achieve pure focus-follows-mouse, as that setting is not offered by A11Y options.

The xmouse.exe utility running in a Command Prompt window:

Now the problem starts with IE 9 and newer (even 8 in some cases). While focus-follows-mouse still works fine, auto-raise does not. Only if the pointer touches window chrome before entering the IE content window, the top-level window is raised. When the pointer enters the IE content area directly from another window it was formerly obscured by, without crossing IE's window border first, the auto-raise will not happen. I filed a bug for that actually a couple of years ago, which was set to resolved by Microsoft but in reality isn't. (I thought I had entered the appropriate feedback then with Microsoft Connect but now I cannot find that comment. God knows what happened to it. *sigh*)

So for all you guys using pure focus-follows-mouse – you can move on, nothing interesting for you here. Auto-raise enthusiasts, stay put.

A Selective Auto-Raise Implementation

The goal is to complement the MS-Windows auto-raise implementation with an add-on tool that handles the case of the pointer entering an Internet Explorer window in some way. (Well actually, it's not entirely unlikely that some people would want to run the tool without Microsoft's auto-raise to only augment certain windows with auto-raise functionality.)

Ideally, the tool would be some minimal C# hack which compiles on every machine where the .NET Framework is available, just like XMouse.exe does.

After researching the appropriate MSDN Win32 API documentation, I came up with a tool – pretty much mashed up out of example code from MSDN – that does exactly what I want:

  1. Sets a low-level hook on the mouse pointer to be notified of pointer movement.
  2. On movement, checks the window under the pointer with WindowFromPoint, combined with GetAncestor to find out about the corresponding top-level window.
  3. In case the top-level window under the pointer matches a preconfigured class name, starts a configurable delay counter.
  4. Once the delay counter hits its target and the pointer has since not left the window, raises the window with a configurable API call (default is SetForegroundWindow).

So all in all it's really pretty simple – see the main form source file (this is not the full program; see the ZIP download below). The tool has a small dialog window which hides itself after a few seconds, which was created with the Visual Studio 2013 GUI designer so to build with msbuild.exe a recent SDK is necessary. However, if the generated .cs files are available (which is the case in the linked ZIP file) the program can simply be compiled with csc, without the SDK. It's programmed against the .NET Framework 2.0 and compiles perfectly on legacy W2K systems. (IE 9 being unavailable on such systems, this is probably more of a theoretical excercise though.)

The tool, WindowFocusHook.exe started without arguments, showing its command-line syntax:

The -debug argument makes the form stay visible and display class names of the windows under the mouse cursor, so start the tool once with that argument and some bogus values for -raisedelay and -classpattern to find out about the class name pattern you need to invoke the tool with. You can also use utilities like Window Detective to get that name.

Download the program source code here. (License: Beerware)

In absence of a Visual Studio 2013 or appropriate SDK installation, compile it with:

csc /out:WindowFocusHook.exe /target:winexe Form1.cs Form1.Designer.cs Program.cs

To compile the program with console trace output enabled, use:

csc /out:WindowFocusHook.exe /d:TRACE Form1.cs Form1.Designer.cs Program.cs

You can also download the binary: WindowFocusHook-0.0.5-bin.zip

Once the executable is in place, you can use the following invocation to enable proper auto-raise for IE windows:

windowfocushook -raisedelay 4 -classpattern IEFrame

Since the form hides after startup when not in debug mode, the program cannot be closed through the user interface. Either close it with the Task Manager, or send a Close message with taskkill.exe (included in Windows):

taskkill /im:windowfocushook.exe

This is in particular necessary if you want to change the settings of the program or otherwise need to restart it. It is generally not recommendable to run multiple instances of it in parallel. While they won't necessarily get in each other's way, it's just a waste of resources.


Last change 2016-06-05