event_loop: cover every output with a session-lock surface, with the app's backdrop on the secondary ones
ext-session-lock-v1 obliges the compositor to blank any output that has no lock surface, and the runtime only ever created one, on the first output — so on a multi-monitor session the extended screens went black the moment the lock engaged. The lock grant now creates one lock surface per advertised output: the first keeps hosting the app's main surface exactly as before, and each remaining output gets its own surface tracked in `lock_extras`, paired with its `WlOutput` so configure, scale and teardown can be routed per surface. What those extra surfaces show is up to the app: a new `App::lock_secondary_view( width, height )` returns the content for a secondary output of that physical size, and the default `None` paints the surface with `background_color()`. The draw pass renders them without requesting frame callbacks — their content is static between invalidations, and a callback that is never re-requested would leave `frame_pending` stuck — and invalidations that touch the main surface also mark the extras, so a backdrop that follows main-surface state (wallpaper swaps, theme changes) stays in sync. The per-surface plumbing that only ever knew about the main surface learns to route: `SessionLockHandler::configure` matches the surface against main and the extras instead of assuming main (an extra's configure used to resize the main surface's target), and the scale-change resize moves into an `apply_surface_scale` helper shared by main, overlays and the lock extras, so a HiDPI secondary gets a correctly scaled buffer instead of staying at factor 1. `new_output` creates a lock surface for an output hotplugged while locked — the compositor would blank it otherwise — and `output_destroyed` drops the matching extra. Input on the extras is deliberately inert, with one asymmetry: pointer and touch events landing on them are discarded rather than falling back to `Main`, because their coordinates would hit-test the main surface's widgets and a click on a secondary screen could press whatever sits at those coordinates on the form — the power button included. Keyboard keeps its existing fall-through to `Main`, so typing works wherever the compositor decides to put the lock focus.
This commit is contained in:
+13
@@ -794,6 +794,19 @@ pub trait App: 'static
|
||||
/// returning `true` from [`requested_exit`](Self::requested_exit).
|
||||
fn shell_mode( &self ) -> ShellMode { ShellMode::Window }
|
||||
|
||||
/// Content for the lock surfaces the runtime creates on every output
|
||||
/// beyond the first while in [`ShellMode::SessionLock`]. The compositor
|
||||
/// blanks any output without a lock surface, so the runtime covers each
|
||||
/// one; this view is what gets painted there (typically the same
|
||||
/// wallpaper as the main surface, without the interactive form).
|
||||
/// `width` / `height` are that output's surface size in physical pixels.
|
||||
/// Default `None`: the surface is filled with
|
||||
/// [`background_color`](Self::background_color).
|
||||
fn lock_secondary_view( &self, _width: u32, _height: u32 ) -> Option<Element<Self::Message>>
|
||||
{
|
||||
None
|
||||
}
|
||||
|
||||
/// Return `true` to tear the surface down and exit the event loop. For a
|
||||
/// [`ShellMode::SessionLock`] surface the runtime calls `unlock` first, so
|
||||
/// the compositor lifts the lock instead of leaving the outputs blanked.
|
||||
|
||||
Reference in New Issue
Block a user