WinEvent Object

class WinEvent extends Object

Subscribes to active-window, appearance, disappearance, movement, minimize, restore, title-change and caret-movement events.

This class is exported by the KS module and is modeled on the AutoHotkey WinEvent library.

#Import "Ks" { WinEvent }

Subscriptions

Hook := WinEvent.Active(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)
Hook := WinEvent.Exist(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)
Hook := WinEvent.NotExist(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)
Hook := WinEvent.Move(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)
Hook := WinEvent.Minimize(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)
Hook := WinEvent.Restore(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)
Hook := WinEvent.TitleChange(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)
Hook := WinEvent.CaretMove(Callback , WinTitle, Count := -1, WinText, ExcludeTitle, ExcludeText)

Callback receives (Hook, Hwnd, EventTime). Count limits how many callbacks are delivered; -1 is unlimited. Window criteria use ordinary WinTitle matching.

Event-specific data arrives in A_EventInfo rather than as an extra parameter. Move and CaretMove put a rectangle there as an object with x, y, w and h; every other event type leaves the event time in A_EventInfo. The rectangle is built only if the callback reads it.

MethodEvent
ActiveThe foreground window changed, or the active window's title changed.
ExistA matching window was created, shown or changed title to match. Fires once per window and forces hidden-window detection.
NotExistA matching window was destroyed, hidden/cloaked when hidden detection is off, or changed title so it no longer matches.
MoveA window moved or resized. Events are not coalesced.
MinimizeA window was minimized.
RestoreA window was restored.
TitleChangeA window title changed.
CaretMoveThe text caret (insertion point) moved: typing, clicking into text, arrow keys, scrolling a text view, or focus moving to another text field. Hwnd is the caret owner's top-level window, not the focused edit control, so ordinary window criteria apply. Consecutive events reporting an unchanged rectangle are suppressed, and an event whose caret position cannot be resolved is dropped.

Note: CaretMove reads the caret through the same accessibility APIs as CaretGetPos and has the same coverage. An application which draws its own caret without exposing it to accessibility — common in browser-based and Electron editors, and in some game and terminal interfaces — reports nothing on any platform. The caret rectangle is always in screen coordinates, regardless of CoordMode, which affects only CaretGetPos.

The values of DetectHiddenWindows, DetectHiddenText and title-match mode are captured when the subscription is created.

Global Control

NewState := WinEvent.Pause(NewState := 1)
IsPaused := WinEvent.IsPaused
WinEvent.IsPaused := NewState

Pause (1), resume (0) or toggle (-1) every subscription. Pause returns the resulting state.

Subscription Members

MemberDescription
Stop()Cancels the subscription.
Pause([NewState := 1])Pauses, resumes or toggles this subscription and returns its new state.
IsPausedGets or sets whether this subscription is paused.
IsActiveWhether it is still registered to receive events.
EventTypeThe event name.
CountRemaining callback count, or -1 for unlimited.

The subscription stops during __Delete, but garbage collection is non-deterministic. Call Stop() when the subscription is no longer needed.

Platform Remarks

Every event type is available on every platform. What differs is the source each one is read from, and the permissions or helpers that source needs.

Windows

Window events come from SetWinEventHook. CaretMove uses the MSAA caret, and its rectangle is read from the same GUITHREADINFO source as CaretGetPos, so the two always agree.

Linux

X11/XWayland: Window events come from a GDK/X11 filter running on the UI thread.

Wayland: Window events come from the compositor, through the GNOME Shell, KWin, Cinnamon or wlroots foreign-toplevel source available in the session.

CaretMove is not a display-server event on either backend: it comes from the AT-SPI object:text-caret-moved signal, which is why a caret subscription works the same way under X11 and Wayland. It requires accessibility to be enabled for the session; with no AT-SPI bridge running, no caret events arrive.

macOS

Window events come from per-application Accessibility AXObserver streams and require Accessibility permission; without it the stream stays empty. CaretMove uses the AXSelectedTextChanged notification, which is registered only while a caret subscription exists because it fires on every keystroke. The event is reported against the edited element's containing window.