Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several ViewEventListener handlers do not work for duplicate view via Goto Anything #2411

Closed
ehuss opened this issue Sep 2, 2018 · 13 comments

Comments

@ehuss
Copy link

ehuss commented Sep 2, 2018

Summary

on_activated in ViewEventListener will not trigger for a view that is opened in a separate layout group via Goto Anything.

Expected behavior

on_activated should trigger whenever activating the view regardless of how it is opened.

Actual behavior

on_activated is not called.

Steps to reproduce

  1. Create demo plugin:
import sublime
import sublime_plugin


class Example(sublime_plugin.ViewEventListener):
    def on_activated(self):
        print('on_activated id=%r buffer_id=%r' % (self.view.id(), self.view.buffer_id()))
  1. Open a window and add a folder to it.
  2. Create a two-column layout.
  3. Open a file in the left column.
  4. Set focus into right column.
  5. Goto Anything and select the file opened in step 4 to create a duplicate view.
  6. Notice that on_activated is not printed. Switching between views, on_activated is never printed for the new view.

Notes

  • Also does not work with on_activated_async.
  • Does work with regular EventListener.
  • applies_to_primary_view_only does not affect it.
  • Works correctly if the duplicate view is opened through other means (like "New View Into File").

Environment

  • Operating system and version: Tested on Windows and Mac.
  • Sublime Text: Build 3176
@ehuss
Copy link
Author

ehuss commented Sep 2, 2018

I did some more digging, and clones created with Goto Anything have problems with several ViewEventListener handlers:

  • Does not work:
    • on_pre_close, on_close
    • on_activated, on_deactivated
    • on_hover
    • on_query_context
    • on_query_completions
    • on_text_command, on_post_text_command
  • Does work (although with wrong view ID, see Multiple event hooks don't work with clones #289):
    • on_pre_save, on_post_save
    • on_modified, on_selection_modified

Also on_clone is not called in EventListener (even though Sublime correctly opens a view into the same buffer).

@ehuss ehuss changed the title on_activated not registered in ViewEventListener for duplicate view via Goto Anything Several ViewEventListener handlers do not work for duplicate view via Goto Anything Sep 3, 2018
@deathaxe
Copy link
Collaborator

deathaxe commented Sep 9, 2018

This is default behavior of a ViewEventListener.

The following should register it for all views of a file.

import sublime
import sublime_plugin


class Example(sublime_plugin.ViewEventListener):

    @classmethod
    def applies_to_primary_view_only(cls):
        return False

    def on_activated(self):
        print('on_activated id=%r buffer_id=%r' % (self.view.id(), self.view.buffer_id()))

@ehuss
Copy link
Author

ehuss commented Sep 9, 2018

@deathaxe I mentioned in the report that, at least for me, setting applies_to_primary_view_only does not affect the behavior. Were you able to get it to work by creating duplicate views with Goto Anything?

@FichteFoll
Copy link
Collaborator

FichteFoll commented Sep 9, 2018

I'd consider this to be a duplicate of #289 (comment) (and #1253).

@ehuss
Copy link
Author

ehuss commented Sep 9, 2018

@FichteFoll Very similar, but this is a very specific issue where the new ViewEventListener does not work with GotoAnything — it does work with EventListener or regular clones. They can be merged if you'd like, but hopefully details about what doesn't work doesn't get lost (since that issue was created before ViewEventListener even existed).

@deathaxe
Copy link
Collaborator

deathaxe commented Sep 9, 2018

Sorry, didn't read carefully enough.

A closer look reveals ST does simply not create any ViewEventListener for a secondary view in that situation. sublime_plugin.event_listeners_for_view(view) returns [].

Once sublime_plugin.check_view_event_listeners(view) is called from console with the secondary view focused all listeners whose applies_to_primary_view_only returns False are created.

Neither on_load nor on_clone is received by a normal EventListener as well, if a secondary file is opened via Goto Anything. I guess one of them is needed to trigger the ViewEventListener´s to be created for that view.

@FichteFoll
Copy link
Collaborator

I'll consider it a sibling of #289, then. It's a related issue but with different symptoms and cause(s). Hopefully the devs find a way to clear this inconsistency.

@deathaxe
Copy link
Collaborator

@ehuss: I am able to reproduce the issue.
@FichteFoll: It's not a duplicate.
@wbond: This ViewEventListener related issue still exists in ST 4068.

Here are some information I found so far:

If a file is opened a second time via "Goto Anything" quick panel, the on_activated() event handler of ViewEventListeners is not called for that view at any time. As the normal EventListener.on_activated() is called with the correct view, it seems to be an issue of the ViewEventListener (creation) implementation.

The ViewEventListener.on_pre_save() is called once with the primary view object being passed, while the EventListener.on_pre_save() is called for each view with the correct view object being passed as expected.

As soon as the plugin, which implements the ViewEventListener is reloaded all event handlers are called as expected.

Running "Create new View into File" from Command Palette works correctly.


By adding some prints to the sublime_plugin.py I found the following:

Opening a clone via "Goto Anything" doesn't cause sublime_plugin.check_view_event_listeners() to be called for the cloned view - maybe because it is in transient state when being opened as a preview? As a result no ViewEventListener gets registered to the view.

sublime_plugin.check_view_event_listeners() is called for any other open view if the selection in the "Goto Anything" panel changes.


class EventListener(sublime_plugin.EventListener):

    def on_reload(self, view):
        print(f"on_reload View {view.id()} : {view.file_name()}.")

    def on_activated(self, view):
        print(f"raw on_activated View({view.id()}) Buffer({view.buffer_id()}) File({view.file_name()})")

    def on_pre_save(self, view):
        print(f"raw on_pre_save View({view.id()}) Buffer({view.buffer_id()}) File({view.file_name()})")


class ViewEventListener(sublime_plugin.ViewEventListener):

    @classmethod
    def applies_to_primary_view_only(cls):
        return False

    def on_activated(self):
        print(f"on_activated View({self.view.id()}) Buffer({self.view.buffer_id()}) File({self.view.file_name()})")

    def on_pre_save(self):
        print(f"on_pre_save View({self.view.id()}) Buffer({self.view.buffer_id()}) File({self.view.file_name()})")

    def on_selection_modified(self):
        print(f"on_selection_modified View({self.view.id()}) Buffer({self.view.buffer_id()}) File({self.view.file_name()})")

Here's the console output. Each time a new file is selected in the Goto Anything panel, check_all_view_event_listeners() is called, which runs check_view_event_listeners for all normal views, which are open at that time - except the new transient view which contains the preview of the selected file in the Goto Anything panel.

Once enter key is hit, the Goto Anything panel closes, which causes the normal on_activate event to be triggered. But no more calls to check_view_event_listeners are performed.

check_all_view_event_listeners()
check_view_event_listeners(View(14))
check_view_event_listeners(View(15))
check_view_event_listeners(View(16))
check_view_event_listeners(View(17))
check_view_event_listeners(View(18))
raw on_activated View(24) Buffer(29) File(Packages\Java\syntax_test_java.java)

@BenjaminSchaaf
Copy link
Member

Seems this isn't fixed? I'll remove the milestone.

@rchl
Copy link

rchl commented Jun 28, 2022

This also causes a problem for LSP.

LSP relies on sublime.ViewEventListener being initialized for the view to be able to attach LSP server to the view. Without it it gets no notifications and can't do anything.

@BenjaminSchaaf
Copy link
Member

I can't reproduce this in build 4183.

@rchl
Copy link

rchl commented Nov 18, 2024

It does seem like it works. Also when testing with the plugin from sublimelsp/LSP#2251 (comment)

@BenjaminSchaaf
Copy link
Member

Going to close this then, given no one else has reproduces this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants