How to Monitor Focus Changes

How to monitor focus changes?

One way would be to use the windows UI Automation API. It exposes a global focus changed event. Here is a quick sample I came up with (in C#). Note, you need to add references to UIAutomationClient and UIAutomationTypes.

using System.Windows.Automation;
using System.Diagnostics;

namespace FocusChanged
{
class Program
{
static void Main(string[] args)
{
Automation.AddAutomationFocusChangedEventHandler(OnFocusChangedHandler);
Console.WriteLine("Monitoring... Hit enter to end.");
Console.ReadLine();
}

private static void OnFocusChangedHandler(object src, AutomationFocusChangedEventArgs args)
{
Console.WriteLine("Focus changed!");
AutomationElement element = src as AutomationElement;
if (element != null)
{
string name = element.Current.Name;
string id = element.Current.AutomationId;
int processId = element.Current.ProcessId;
using (Process process = Process.GetProcessById(processId))
{
Console.WriteLine(" Name: {0}, Id: {1}, Process: {2}", name, id, process.ProcessName);
}
}
}
}
}

Detect window focus changes with XCB

The focus events are only sent when the window that you selected these events on receives or loses the focus, see https://www.x.org/releases/X11R7.5/doc/x11proto/proto.html:

FocusIn
FocusOut

[...]

These events are generated when the input focus changes and are reported to clients selecting FocusChange on the window.

To use this, you would have to select this event mask on all windows and also watch for the creation of new windows.


I would suggest a different approach: Watch for PropertyChangeNotify events on the root window to see when the _NET_ACTIVE_WINDOW property changes. This property should be kept up to date by the WM, according to EWMH.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <xcb/xcb.h>

static xcb_atom_t intern_atom(xcb_connection_t *conn, const char *atom)
{
xcb_atom_t result = XCB_NONE;
xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(conn,
xcb_intern_atom(conn, 0, strlen(atom), atom), NULL);
if (r)
result = r->atom;
free(r);
return result;
}

int main (int argc, char **argv)
{
xcb_connection_t* conn = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(conn)) {
printf("Cannot open daemon connection.");
return 0;
}

xcb_atom_t active_window = intern_atom(conn, "_NET_ACTIVE_WINDOW");
xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;

uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
xcb_change_window_attributes(
conn,
screen->root,
XCB_CW_EVENT_MASK,
values);

xcb_flush(conn);

xcb_generic_event_t *ev;
while ((ev = xcb_wait_for_event(conn))) {
printf("IN LOOP\n");
switch (ev->response_type & 0x7F) {
case XCB_PROPERTY_NOTIFY: {
xcb_property_notify_event_t *e = (void *) ev;
if (e->atom == active_window)
puts("active window changed");
break;
}
default:
printf("IN DEFAULT\n");
break;
}
free(ev);
}

return 0;
}

How to monitor active window changes using xcb?

If you set PropertyChange mask on root window you'll start getting PropertyNotify events to your code. See example in my answer here: Linux get notification on focused gui window change

Is there a cross-browser solution for monitoring when the document.activeElement changes?

While @James's answer above is correct. I've added more details to make it a completely working solution along with the use of focus event too.

<html>
<body>
<input type="text" id="Text1" name ="Text1" value=""/>
<input type="text" id="Text2" name ="Text2" value=""/>
<SELECT><OPTION>ASDASD</OPTION><OPTION>A232</OPTION></SELECT>
<INPUT TYPE="CHECKBOX" id="Check1"/>
<INPUT type="TEXT" id="text3"/>
<input type="radio"/>
<div id="console"> </div>
<textarea id="textarea1"> </textarea>
<script>

var lastActiveElement = document.activeElement;

function detectBlur() {
// Do logic related to blur using document.activeElement;
// You can do change detection too using lastActiveElement as a history
}

function isSameActiveElement() {
var currentActiveElement = document.activeElement;
if(lastActiveElement != currentActiveElement) {
lastActiveElement = currentActiveElement;
return false;
}

return true;
}

function detectFocus() {
// Add logic to detect focus and to see if it has changed or not from the lastActiveElement.
}

function attachEvents() {
window.addEventListener ? window.addEventListener('focus', detectFocus, true) : window.attachEvent('onfocusout', detectFocus);

window.addEventListener ? window.addEventListener('blur', detectBlur, true) : window.attachEvent('onblur', detectBlur);
}

attachEvents();

</script>
</body>
</html>


Related Topics



Leave a reply



Submit