Two buffer-activated notifications instead of just one
-
Consider the following short PythonScript:
from Npp import * def bufferactivated_callback(args): print(notepad.getCurrentFilename(), args) notepad.callback(bufferactivated_callback, [NOTIFICATION.BUFFERACTIVATED])
With this installed, set up the following scenario:
- have 2 tabs open in each view
- in the inactive view, click on the inactive tab
Notice that there are two indications in the PythonScript console that documents have been activated, not just one.
It seems that if you activate a tab other than the active one in the view that is not active (wow, say THAT 3 times fast!), first the existing active tab in that view produces a notify, then the tab that you are intending to activate produces a notify.
What’s the feeling here, is the first notify a bug?
-
@Alan-Kilborn said in Two buffer-activated notifications instead of just one:
first the existing active tab in that view produces a notify, then the tab that you are intending to activate produces a notify.
What’s the feeling here, is the first notify a bug?
Confusing? Definitely. A bug? I’m not sure.
My guess is that the way that Notepad++ has implemented view-change-plus-tab-change is internally as two separate events, where the view gets activated first (and thus the currently-active tab from that view), then changing to the new tab. So, from that perspective, it makes a certain sense to send a notification for each step of the process, since Notepad++ is technically taking each of those steps.
But from the script/plugin-writer’s perspective, I can definitely see that the desire would be to just be notified for the “actual” (second) tab activation.
-
Thanks for your thoughts, Peter.
But from the script/plugin-writer’s perspective…
Right; the normal N++ user doesn’t notice that this happens.
But if the user is using e.g. a plugin that does a not-insignificant operation on buff-activated, and that operation is time-related to the size of the file, and the currently-active tab in the inactive view is absolutely huge and the above happens, the user can notice.
Maybe I’ll open an issue about this, as an “advisory” rather than a “bug”…
-
@Alan-Kilborn said in Two buffer-activated notifications instead of just one:
But if the user is using e.g. a plugin that does a not-insignificant operation on buff-activated, and that operation is time-related to the size of the file, and the currently-active tab in the inactive view is absolutely huge and the above happens, the user can notice.
I can confirm from implementing Columns++ Elastic tabstops that this is an annoying problem. (I’ve worked around most of it, but there is a specific case I cannot mitigate.)
I think Notepad++ sends NPPN_BUFFERACTIVATED whenever it loads a Scintilla document into a view; but there are times when it does that only temporarily. It could be that the path through Notepad++ is such that it doesn’t “know” at the time it sends the message whether it will be temporary.
The best way I have found to work around it is to try to write NPPN_BUFFERACTIVATED processing such that doing it repeatedly on a file that hasn’t changed does nothing, and does it quickly. That usually means tracking changes with SCN_MODIFIED and keeping a map that associates Scintilla document IDs, Notepad++ buffer IDs, and status information. It’s ugly.
Edit to add: It is possible that one could wait for an SCN_UPDATEUI notification. Now that I think of it, I don’t believe I tried deferring the slow operation I can’t escape to that message; but it’s rare enough, now — and I have a progress box with a cancel button that shows up when it happens — that I don’t want to make things even more complicated than they already are.
-
I have also ‘stumbled’ upon that behavior when working on Compare plugins.
@Coises said in Two buffer-activated notifications instead of just one:
The best way I have found to work around it is to try to write NPPN_BUFFERACTIVATED processing such that doing it repeatedly on a file that hasn’t changed does nothing, and does it quickly. That usually means tracking changes with SCN_MODIFIED and keeping a map that associates Scintilla document IDs, Notepad++ buffer IDs, and status information. It’s ugly.
@Coises , I would just add that back in the time when I analyzed that behavior I noticed that NPPN_BUFFERACTIVATED is send for the same file that hasn’t changed also when it is changed outside Notepad++ and it is reloaded in the editor. I actually currently use that to detect that the current file is changed outside and reloaded in Notepad++ to refresh the compare.
I agree with what Alan wrote:
@Alan-Kilborn said in Two buffer-activated notifications instead of just one:
But if the user is using e.g. a plugin that does a not-insignificant operation on buff-activated, and that operation is time-related to the size of the file, and the currently-active tab in the inactive view is absolutely huge and the above happens, the user can notice.
I would also add that it is not only the plugins processing of NPPN_BUFFERACTIVATED involved here but unfortunately also some Notepad++ internal functions.
For example let’s suppose we have opened two files in the first (main) view and one file in the second (sub) view. Now let’s assume one of the files in the first view is small and loads quickly and the second file is large xml for example and it is the currently active file in the view. Now if we switch to the second view and activate the Notepad++'s function list and then click on the small file’s tab in the first view then it seems the large file is first ‘activated’ in the view and the function list seems to be processing it before immediately switching to the small file. And that delay is noticeable by the user in that case even though plugins are not involved -
I made an official issue out of this: https://github.com/notepad-plus-plus/notepad-plus-plus/issues/16493
-
I noticed a workaround; consider the following script:
# -*- coding: utf-8 -*- from __future__ import print_function # Python2 vestige! # see https://community.notepad-plus-plus.org/topic/26799 "Two buffer-activated notifications instead of just one" from Npp import notepad, NOTIFICATION last_known_doc_index_by_view = [ notepad.getCurrentDocIndex(0), notepad.getCurrentDocIndex(1) ] def find_docindex_from_buffer_id_via_enumeration(test_buffer_id, must_be_in_this_view): for (pathname, buffer_id, index, view) in notepad.getFiles(): if view != must_be_in_this_view: continue # needed to find the right doc in case of cloned doc if buffer_id == test_buffer_id: return index return -1 # never happens def bufferactivated_callback(args): cfn = notepad.getCurrentFilename().rsplit('\\', 1)[-1] # only the filename, no directory print('BUFFERACTIVATED:', cfn, 'args=', args) current_view = notepad.getCurrentView() current_doc_index = notepad.getCurrentDocIndex(current_view) curr_doc_index_via_enumerating = find_docindex_from_buffer_id_via_enumeration(args['bufferID'], current_view) if current_doc_index != curr_doc_index_via_enumerating: print(' NOT A NEEDED ACTIVATION NOTIFICATION!!!!!!') return print(' HANDLING A REAL ACTIVATION NOTIFICATION!') if last_known_doc_index_by_view[current_view] == current_doc_index: print(' note: THIS DOC WAS ALREADY ACTIVE IN THE ITS VIEW -- so was an activation notify really necessary?') else: last_known_doc_index_by_view[current_view] = current_doc_index notepad.callback(bufferactivated_callback, [NOTIFICATION.BUFFERACTIVATED])
This workaround works because the “index” reported with the bogus notification is also bogus, and the correct index can be found by looking through the entire tab list for the right buffer id.
A subtle point of the script is that it can also detect when the active tab in the inactive view is activated by the user.
-
A Alan Kilborn referenced this topic on