Files
cproof/PR_plugin_post_display.md
jabber.developer2 3b84d5c4ee
All checks were successful
CI Code / Check spelling (pull_request) Successful in 17s
CI Code / Check coding style (pull_request) Successful in 32s
CI Code / Code Coverage (pull_request) Successful in 3m14s
CI Code / Linux (debian) (pull_request) Successful in 4m45s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m58s
CI Code / Linux (arch) (pull_request) Successful in 7m1s
docs: PR description for chatwin trigger fix
2026-06-01 16:33:32 +03:00

2.7 KiB

fix(chatwin): only fire plugins_post_chat_message_display on incoming

Base: masterfix/plugin-post-display-incoming-only

Create PR: https://git.jabber.space/devs/cproof/pulls/new/fix/plugin-post-display-incoming-only

Problem

Plugins listening on plugins_post_chat_message_display (e.g. sounds.py — plays a notification sound on a new incoming chat message) were firing in places that are not "a remote party sent a chat message and it was displayed":

  • Opening a chat — every message loaded from history triggered the hook, so the user heard the notification sound once per historical message.
  • Sending a chat message — the outgoing-message path triggered the hook, so sending played the incoming sound.
  • Receiving a carbon copy of your own outgoing message from another device — same, played the incoming sound.

Net effect for sounds.py (and any plugin that treats the hook as "a new message arrived"): notification sound on every open / send / carbon, which is essentially constant nuisance.

Root cause

The post-display hook was invoked from four sites in src/ui/chatwin.c:

Function Path
chatwin_incoming_msg remote → us (true incoming)
chatwin_outgoing_msg us → remote
chatwin_outgoing_carbon us → remote, mirrored back via XEP-0280 carbons
_chatwin_history history scroll-back
chatwin_db_history DB-backed history load

Only the first matches the hook's semantic. The other four were spurious — they treated "display happened" as the trigger condition instead of "an incoming message was displayed".

Fix

Remove the plugins_post_chat_message_display(...) call from the four spurious sites. Keep it only in chatwin_incoming_msg. The corresponding pre-display hook (plugins_pre_chat_message_display) and the msg->plain = old_plain swap that bracket it stay in place — those affect how the message is rendered, independent of the post hook.

One file, five deletions.

Verify

  • Open a chat that has stored history → expect zero notification sounds from sounds.py during the history render.
  • Send a message → expect zero notification sound for your own outgoing.
  • Receive an outgoing carbon (send from another XMPP client logged into the same account) → expect zero notification sound.
  • Receive an actual incoming message from the remote contact → expect the notification sound exactly once.

Note for plugin authors

Plugins relying on the previous (broader) trigger semantics will see the hook only on true incoming displays. If a plugin needs to observe outgoing or history events, it should hook into the corresponding paths instead (plugins_post_chat_message_send for outgoing; no current hook for history — could be added separately).