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

Fix cursor events on screen lock/unlock #8374

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

OkamiW
Copy link

@OkamiW OkamiW commented Oct 6, 2024

After the scene graph refactor, node_at_coords no longer return the lock surface after the screen is locked, thereby cursor_rebase_all in handle_surface_map won't work.

This commit make node_at_coords return lock surface when locked.

I also found that the cursor would disappear after screen is unlocked, thereby adding a cursor_rebase_all in handle_unlock.

@@ -63,6 +63,11 @@ struct sway_node *node_at_coords(
}
}

if (server.session_lock.lock) {
*surface = server.session_lock.lock->focused;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

focused represents the keyboard focus, but this codepath is about the pointer. Moreover, the surface-local coordinates sx/sy are left unset.

The session lock surfaces are added to output->layers.session_lock, so I wonder why this doesn't work?

cc @Nefsen402

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last time I checked, when screen is just locked(without any cursor movement), node_at_coords would get a WLR_SCENE_NODE_RECT instead of a WLR_SCENE_NODE_BUFFER, which is probably the red surface created to show when session lock crashed.

Copy link
Author

@OkamiW OkamiW Oct 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related: #8343
Maybe wlr_scene_node_at can only get the lock surface after it's committed(not mapped)?

@OkamiW
Copy link
Author

OkamiW commented Oct 8, 2024

      ┗━tree 0,0 
          ┗━tree 0,0 
              ┗━tree 0,0 
                  ┣━rect 0,0 1280x720 
                  ┗━tree 0,0 
                      ┣━buffer 0,0 0x0 
                      ┗━tree 0,0  disabled
                          ┗━buffer 0,0 0x0 
      ┗━tree 0,0 
          ┗━tree 0,0 
              ┗━tree 0,0 
                  ┣━rect 0,0 1280x720 
                  ┗━tree 0,0 
                      ┣━buffer 0,0 1280x720 
                      ┗━tree 582,300 
                          ┗━buffer 582,300 121x121 

It seems that during handle_surface_map, the lock surface scene buffer size is 0x0. Thereby wlr_scene_node_at won't return it.
After cursor movement, the lock surface scene buffer size is normal.
@emersion

@kennylevinsen
Copy link
Member

Hmm, this is a bit of an event ordering issue with wlr_scene.

The order of events here is:

  1. Surface is committed
  2. Surface role commit implementations are called
  3. Surface role commit handlers call wlr_surface_map
  4. Surface role map implementations are called
  5. Map event fires
  6. Commit event fires
  7. Scene surface helper attaches new buffer to the surface

Dealing with this would require an "initial commit" sort of commit handler... :/

@OkamiW OkamiW force-pushed the fix-cursor-events branch from 8ae2b1b to a394522 Compare October 8, 2024 08:39
@OkamiW
Copy link
Author

OkamiW commented Oct 8, 2024

@kennylevinsen
I added commit event emitting in lock_surface_role_commit, that seems to fix the issue.

--- a/types/wlr_session_lock_v1.c
+++ b/types/wlr_session_lock_v1.c
@@ -185,6 +185,8 @@ static void lock_surface_role_commit(struct wlr_surface *surface) {
 		return;
 	}
 
+	wl_signal_emit_mutable(&lock_surface->surface->events.commit, lock_surface);
+
 	wlr_surface_map(surface);
 }

Though we still need cursor_rebase_all in handle_unlock.

@Nefsen402
Copy link
Member

I've been pondering for a while if we should get rid of all the cursor rebase stuff and add some sort of callback or just go through with wlr_scene_cursor finally. Scene could implement cursor rebasing on its own and all these problems would go away similar to how we handled xwayland restacking.

@kennylevinsen
Copy link
Member

It could be useful, but there are some caveats.

One is that the effect of cursor_rebase is currently conditional on the ongoing seatop, with only the default seatop performing focus updates. It could also be argued that it's a bug that cursor_rebase doesn't also update keyboard focus when focus_follows_mouse always is set.

Another is that, even if scene have a helper, there should preferably still be a way for compositors to do things on their own.

@OkamiW
Copy link
Author

OkamiW commented Nov 13, 2024

It seems that Labwc has a fix for the same problem: labwc/labwc#1858
wl_event_loop_add_idle can be used here to delay the actual operations after the buffer has been attached.
This should be a proper fix for the issue.

@OkamiW
Copy link
Author

OkamiW commented Nov 16, 2024

Just fixed another edge case. I think this PR is ready.
Is it OK to merge this? @emersion

@OkamiW OkamiW requested a review from emersion November 17, 2024 17:54
@OkamiW
Copy link
Author

OkamiW commented Nov 17, 2024

Gentle ping.

See labwc/labwc#1858

Delay refocus operations because only the role-specific surface
commit/map handler has been processed in wlroots at this moment and
node_at_coords returns the WLR_SCENE_NODE_RECT as a buffer has not
been actually attached to the surface.
@OkamiW
Copy link
Author

OkamiW commented Nov 22, 2024

Any update on this? @emersion @kennylevinsen @Nefsen402

sway/lock.c Outdated Show resolved Hide resolved
@emersion
Copy link
Member

In general the approach of delaying the focus updates are more of a workaround than a proper fix. However it's not clear what the proper fix could look like.

@OkamiW
Copy link
Author

OkamiW commented Nov 22, 2024

In general the approach of delaying the focus updates are more of a workaround than a proper fix. However it's not clear what the proper fix could look like.

How about: #8374 (comment)
That requires changing wlroots though.

Before this commit, if the cursor is at screen center, and the lock is
swaylock, the cursor would be at swaylock's subsurface(the indicator).

Since it's not the lock surface, `handle_rebase` would refuse to
rebase the cursor to there. Thereby the cursor enter event won't be
sent to swaylock.

This commit fix the issue.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants