IntelliJ Platform Plugin SDK Help

Listeners

Listeners allow plugins to subscribe to events delivered through the message bus (see Messaging infrastructure for details).

Listeners are defined at application (global) or project level.

Listener implementations must be stateless and may not implement life-cycle (e.g., Disposable). Use inspection Plugin DevKit | Code | Listener implementation implements 'Disposable' to verify (2023.3).

Declarative registration of listeners (2019.3 and later) allows achieving better performance than registering listeners from code. The advantage is because listener instances get created lazily — the first time an event is sent to the topic — and not during application startup or project opening.

Defining Application-Level Listeners

To define an application-level listener, add the <applicationListeners> section to plugin.xml:

<idea-plugin> <applicationListeners> <listener class="myPlugin.MyListenerClass" topic="BaseListenerInterface"/> </applicationListeners> </idea-plugin>

The topic attribute specifies the listener interface corresponding to the type of events to receive. Usually, this is the interface used as the type parameter of the Topic instance for the type of events. The class attribute specifies the class in the plugin that implements the listener interface and receives the events.

As a specific example, to receive events about all Virtual File System changes, implement the BulkFileListener interface, corresponding to the topic VirtualFileManager.VFS_CHANGES. To subscribe to this topic from code, use something like the following snippet:

messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { @Override public void after(@NotNull List<? extends VFileEvent> events) { // handle the events } });

To use declarative registration, it's no longer required to reference the Topic instance. Instead, refer directly to the listener interface class:

<applicationListeners> <listener class="myPlugin.MyVfsListener" topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/> </applicationListeners>

Then provide the listener implementation:

package myPlugin; final class MyVfsListener implements BulkFileListener { @Override public void after(@NotNull List<? extends VFileEvent> events) { // handle the events } }

Defining Project-Level Listeners

Project-level listeners are registered in the same way, except that the top-level tag is <projectListeners>. They can be used to listen to project-level events, for example, tool window operations:

<idea-plugin> <projectListeners> <listener class="myPlugin.MyToolWindowListener" topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener"/> </projectListeners> </idea-plugin>

The class implementing the listener interface can define a one-argument constructor accepting a Project, and it will receive the instance of the project for which the listener is created:

package myPlugin; final class MyToolWindowListener implements ToolWindowManagerListener { private final Project project; MyToolWindowListener(Project project) { this.project = project; } @Override public void stateChanged(@NotNull ToolWindowManager toolWindowManager) { // handle the state change } }

Additional Attributes

Registration of listeners can be restricted using the following attributes.

os

Allows restricting listener to given OS, e.g., os="windows" for Windows only (2020.1 and later)

activeInTestMode

Set to false to disable listener if Application.isUnitTestMode() returns true

activeInHeadlessMode

Set to false to disable listener if Application.isHeadlessEnvironment() returns true. Also covers activeInTestMode as test mode implies headless mode.

Last modified: 15 April 2024