How to run and log KWin plugin example?

I have stumbled upon EventListener plugin that is available on the Kwin repository as an example under directory examples/plugin (can’t post links, sorry).

After downloading, building and installing it, it seems like the plugin is loaded properly. Here is my output from qdbus-qt6 org.kde.KWin /KWin supportInformation:

Loaded Plugins:
---------------
BounceKeysPlugin
StickyKeysPlugin
buttonsrebind
eis
eventlistener
krunnerintegration
nightlight
screencast

Available Plugins:
------------------
BounceKeysPlugin
StickyKeysPlugin
buttonsrebind
eis
eventlistener
krunnerintegration
nightlight
screencast

Full command output:
KWin Support Information:
The following information should be used when requesting support on e.g. https://discuss.kde.org.
It provides information about the currently running instance, which options are used,
what OpenGL driver and which effects are running.
Please post the information provided underneath this introductory text to a paste bin service
like https://paste.kde.org instead of pasting into support threads.
 
==========================
 
Version
=======
KWin version: 6.1.4
Qt Version: 6.7.2
Qt compile version: 6.7.2
XCB compile version: 1.17.0
 
Operation Mode: Xwayland
 
Build Options
=============
KWIN_BUILD_DECORATIONS: yes
KWIN_BUILD_TABBOX: yes
KWIN_BUILD_ACTIVITIES: yes
HAVE_X11_XCB: yes
HAVE_GLX: yes
 
X11
===
Vendor: The X.Org Foundation
Vendor Release: 12401002
Protocol Version/Revision: 11/0
SHAPE: yes; Version: 0x11
RANDR: yes; Version: 0x14
DAMAGE: yes; Version: 0x11
Composite: yes; Version: 0x4
RENDER: yes; Version: 0xb
XFIXES: yes; Version: 0x50
SYNC: yes; Version: 0x31
GLX: yes; Version: 0x0
 
Decoration
==========
Plugin: org.kde.breeze
Theme: 
Plugin recommends border size: None
onAllDesktopsAvailable: false
alphaChannelSupported: true
closeOnDoubleClickOnMenu: false
decorationButtonsLeft: 0, 2
decorationButtonsRight: 6, 3, 4, 5
borderSize: 0
gridUnit: 10
font: Noto Sans,10,-1,0,400,0,0,0,0,0,0,0,0,0,0,1
smallSpacing: 2
largeSpacing: 10
 
Output backend
==============
Name: DRM
Atomic Mode Setting on GPU 0: true
 
Cursor
======
themeName: breeze_cursors
themeSize: 24
 
Options
=======
focusPolicy: ClickToFocus
xwaylandCrashPolicy: 1
xwaylandMaxCrashCount: 3
nextFocusPrefersMouse: false
clickRaise: true
autoRaise: false
autoRaiseInterval: 0
delayFocusInterval: 0
shadeHover: false
shadeHoverInterval: 250
separateScreenFocus: false
placement: 5
activationDesktopPolicy: SwitchToOtherDesktop
focusPolicyIsReasonable: true
borderSnapZone: 10
windowSnapZone: 10
centerSnapZone: 0
snapOnlyWhenOverlapping: false
edgeBarrier: 100
cornerBarrier: 1
rollOverDesktops: false
focusStealingPreventionLevel: 1
operationTitlebarDblClick: 5000
operationMaxButtonLeftClick: 5000
operationMaxButtonMiddleClick: 5015
operationMaxButtonRightClick: 5014
commandActiveTitlebar1: MouseRaise
commandActiveTitlebar2: MouseNothing
commandActiveTitlebar3: MouseOperationsMenu
commandInactiveTitlebar1: MouseActivateAndRaise
commandInactiveTitlebar2: MouseNothing
commandInactiveTitlebar3: MouseOperationsMenu
commandWindow1: MouseActivateRaiseAndPassClick
commandWindow2: MouseActivateAndPassClick
commandWindow3: MouseActivateAndPassClick
commandWindowWheel: MouseNothing
commandAll1: MouseUnrestrictedMove
commandAll2: MouseToggleRaiseAndLower
commandAll3: MouseUnrestrictedResize
keyCmdAllModKey: 16777250
condensedTitle: false
electricBorderMaximize: true
electricBorderTiling: true
electricBorderCornerRatio: 0.25
borderlessMaximizedWindows: false
killPingTimeout: 5000
hideUtilityWindowsForInactive: true
compositingMode: 1
useCompositing: true
hiddenPreviews: 1
glSmoothScale: 2
glStrictBinding: true
glStrictBindingFollowsDriver: true
glPreferBufferSwap: AutoSwapStrategy
glPlatformInterface: 2
windowsBlockCompositing: true
allowTearing: true
 
Screen Edges
============
desktopSwitching: false
desktopSwitchingMovingClients: false
cursorPushBackDistance: 1x1
timeThreshold: 75
reActivateThreshold: 350
actionTopLeft: 0
actionTop: 0
actionTopRight: 0
actionRight: 0
actionBottomRight: 0
actionBottom: 0
actionBottomLeft: 0
actionLeft: 0
 
Screens
=======
Number of Screens: 2
 
Screen 0:
---------
Name: eDP-1
Enabled: 1
Geometry: 2867,197,1504x1003
Scale: 1.5
Refresh Rate: 59999
Adaptive Sync: incapable
Screen 1:
---------
Name: DP-2
Enabled: 1
Geometry: 0,0,2867x1200
Scale: 1.2
Refresh Rate: 144001
Adaptive Sync: incapable
 
Compositing
===========
Compositing is active
Compositing Type: OpenGL
OpenGL vendor string: AMD
OpenGL renderer string: AMD Radeon 780M (radeonsi, gfx1103_r1, LLVM 18.1.6, DRM 3.57, 6.10.4-200.fc40.x86_64)
OpenGL version string: 4.6 (Core Profile) Mesa 24.1.5
OpenGL platform interface: EGL
OpenGL shading language version string: 4.60
Driver: Unknown
GPU class: Unknown
OpenGL version: 4.6
GLSL version: 4.60
Mesa version: 24.1.5
X server version: 1.24.1
Linux kernel version: 6.10.4
Direct rendering: Requires strict binding: no
Virtual Machine:  no
OpenGL 2 Shaders are used
 
Loaded Effects:
---------------
shakecursor
screenshot
outputlocator
colorpicker
zoom
screenedge
blur
contrast
sessionquit
logout
login
slidingpopups
windowaperture
slide
squash
scale
morphingpopups
maximize
fullscreen
frozenapp
fadingpopups
dialogparent
windowview
tileseditor
overview
highlightwindow
blendchanges
startupfeedback
screentransform
kscreen
 
Currently Active Effects:
-------------------------
blur
contrast
 
Effect Settings:
----------------
shakecursor:
 
screenshot:
 
outputlocator:
 
colorpicker:
 
zoom:
zoomFactor: 1.2
mousePointer: 0
mouseTracking: 0
focusTrackingEnabled: false
textCaretTrackingEnabled: false
focusDelay: 350
moveFactor: 20
targetZoom: 1
 
screenedge:
 
blur:
 
contrast:
 
sessionquit:
pluginId: sessionquit
isActiveFullScreenEffect: false
 
logout:
pluginId: logout
isActiveFullScreenEffect: false
 
login:
pluginId: login
isActiveFullScreenEffect: false
 
slidingpopups:
slideInDuration: 200
slideOutDuration: 200
 
windowaperture:
pluginId: windowaperture
isActiveFullScreenEffect: false
 
slide:
horizontalGap: 45
verticalGap: 20
slideBackground: true
 
squash:
pluginId: squash
isActiveFullScreenEffect: false
 
scale:
pluginId: scale
isActiveFullScreenEffect: false
 
morphingpopups:
pluginId: morphingpopups
isActiveFullScreenEffect: false
 
maximize:
pluginId: maximize
isActiveFullScreenEffect: false
 
fullscreen:
pluginId: fullscreen
isActiveFullScreenEffect: false
 
frozenapp:
pluginId: frozenapp
isActiveFullScreenEffect: false
 
fadingpopups:
pluginId: fadingpopups
isActiveFullScreenEffect: false
 
dialogparent:
pluginId: dialogparent
isActiveFullScreenEffect: false
 
windowview:
activeView: 
delegate: 
animationDuration: 300
ignoreMinimized: false
mode: 
partialActivationFactor: 0
gestureInProgress: false
searchText: 
selectedIds: 
 
tileseditor:
activeView: 
delegate: 
animationDuration: 200
 
overview:
activeView: 
delegate: 
animationDuration: 300
ignoreMinimized: false
filterWindows: true
organizedGrid: true
overviewPartialActivationFactor: 0
overviewGestureInProgress: false
transitionPartialActivationFactor: 0
transitionGestureInProgress: false
gridPartialActivationFactor: 0
gridGestureInProgress: false
desktopOffset: 
searchText: 
 
highlightwindow:
 
blendchanges:
 
startupfeedback:
type: 1
 
screentransform:
 
kscreen:
 
 
Loaded Plugins:
---------------
BounceKeysPlugin
StickyKeysPlugin
buttonsrebind
eis
eventlistener
krunnerintegration
nightlight
screencast
 
Available Plugins:
------------------
BounceKeysPlugin
StickyKeysPlugin
buttonsrebind
eis
eventlistener
krunnerintegration
nightlight
screencast
 
 

However, I’m unable to find any logs regarding this plugin, not even the initial log when the main object is instanced.
Here is what I tried:

  • added export QT_LOGGING_RULES="kwin_*.debug=true" to ~/.bash_profile (according to KWin/Debugging website)
  • tried to check the log file ~/.local/share/sddm/wayland-session.log, but the file does not exist
  • browsed journalctl for log entries, but there are no logs from this plugin

Does anyone have any hints on how this plugin is supposed to work?
Where can I check it’s logs?
Do I need to turn on something extra?
Is there any documentation or README available for this plugin example?

Thanks.

Edit: rebooted multiple times, logs still not showing up.

PC Specs:

Operating System: Fedora Linux 40
KDE Plasma Version: 6.1.4
KDE Frameworks Version: 6.5.0
Qt Version: 6.7.2
Kernel Version: 6.10.4-200.fc40.x86_64 (64-bit)
Graphics Platform: Wayland
Processors: 16 × AMD Ryzen 7 7840U w/ Radeon 780M Graphics
Memory: 58.7 GiB of RAM
Graphics Processor: AMD Radeon 780M
Manufacturer: Framework
Product Name: Laptop 13 (AMD Ryzen 7040Series)
System Version: A7

You to logout/reboot for this this to take effect, I guess you did not.

Documentation should specify it. Needs to be fixed.

Oh, forgot to mention, I have restarted PC after every change, but logs are still not showing up.

The event listener does not use logging categories. So this won’t change anything.

Put in
~/.config/QtProject/qtlogging.ini

[Rules]
*.debug=true
qt.*.debug=false

Then recompile + relog/reboot.

But depending on your distro that may not be necessary.

Source: c++ - qDebug not displaying anything - Stack Overflow

It should populate ~/.local/share/sddm/wayland-session.log.

Developing a KWin plugin is rather advanced be warned.

Awesome, this seems to have done the trick.

Small note: events are displayed on journalctl, not in ~/.local/share/sddm/wayland-session.log (I believe this is configured somewhere else, and modern default is set to log to journalctl not to file).

Thanks for the help and heads up :smiley:

I wasn’t sure.

Good luck

May I ask what do you want to accomplish ?

Thanks.

Of course. I’m trying to develop some kind of OSD for key presses.

Originally, I was trying to make this using Wayland, but I was not aware at the time that Wayland sandboxes key events to the (focused) window.

Later on I learned that these events are handled by the composer and composer is the one passing down events to the window (I think).

And that led me to here. I’m trying to get key input events from the KWin and display them on screen.

The next step would be to display some kind of popup on screen from this plugin when a key is pressed. I need to research if there is a way to do this using some kind of KDE toolkit/framework/lib tool or do I need to use Wayland (I’m not even sure if I can use it from plugin).

Nice, that would be a nice feature for educational purposes.

There is.

Here is an example use:

This was exactly what I was looking for. Thank you!

However, after adding osd header (and adding function call) and reconfiguring and recompiling the project, it seems like linker fails to find reference to osd. It’s weird, since headers are present in /usr/include/kwin, and even more weird is that the two original headers are linked against (input.h and input_event.h). Even KDevelop picked up header files from /usr/include/kwin, for all three headers.

Pardon for my ignorance, I am not that familiar with cmake system, I’m more familiar with Makefiles.

I also tried to find other plugins that are using osd header/lib, but I was unable to find any.

Am I missing something?
Do I need to add some kind of prerequest/dependency to cmake CMakeLists.txt?
I can see that default CMakeLists.txt links whole KWin library, so this is a real head-scratcher for me. If input and input_events are available, and those two are in the same package/directory/library as osd, why does the linker fail to pick up a reference to osd?

I tried to look at Makefile generated by cmake, but I did not find any extra library being linked in build process.

Here is the output of build process:

/usr/bin/ld: CMakeFiles/eventlistener.dir/eventlistener.cpp.o: in function `KWin::EventListener::keyEvent(KWin::KeyEvent*)':
eventlistener.cpp:(.text+0xfe): undefined reference to `KWin::OSD::show(QString const&, int)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/eventlistener.dir/build.make:135: bin/kwin/plugins/eventlistener.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:221: CMakeFiles/eventlistener.dir/all] Error 2
make: *** [Makefile:146: all] Error 

And thanks for all the help that you have provided up until now, means alot that you pointed me to the right direction, since information on this topic seems to be sparse.

Would need to check it is exported, i.e part of the external API available to plugin. But it seems to be.

Make sure you target kwin library (and all your dependencies) for linkage:

target_link_libraries(eventlistener PRIVATE
    kwin
)

We have some documentation for cmake :