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

Session lock plugin fixes #2304

Merged
merged 3 commits into from
Apr 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 55 additions & 19 deletions plugins/protocols/session-lock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ class lock_surface_node : public lock_base_node<wf::scene::wlr_surface_node_t>
interaction(std::make_unique<lock_surface_keyboard_interaction>(lock_surface->surface))
{}

void configure(wf::dimensions_t size)
{
wlr_session_lock_surface_v1_configure(lock_surface, size.width, size.height);
LOGC(LSHELL, "surface_configure on ", lock_surface->output->name, " ", size);
}

void display()
{
auto layer_node = output->node_for_layer(wf::scene::layer::LOCK);
Expand Down Expand Up @@ -137,6 +143,8 @@ class lock_crashed_node : public lock_base_node<simple_text_node_t>
set_text_params(params);
// TODO: make the text smaller and display a useful message instead of a big explosion.
set_text("💥");
auto layer_node = output->node_for_layer(wf::scene::layer::LOCK);
wf::scene::add_back(layer_node, shared_from_this());
wf::get_core().seat->set_active_node(shared_from_this());
}

Expand All @@ -161,13 +169,18 @@ class wf_session_lock_plugin : public wf::plugin_interface_t
ZOMBIE,
};


struct output_state
{
std::shared_ptr<lock_surface_node> surface_node;
wf::wl_listener_wrapper surface_destroy;
std::shared_ptr<lock_crashed_node> crashed_node;

output_state(wf::output_t *output)
{
crashed_node = std::make_shared<lock_crashed_node>(output);
crashed_node->set_text("");
}

~output_state()
{
surface_destroy.disconnect();
Expand Down Expand Up @@ -195,6 +208,21 @@ class wf_session_lock_plugin : public wf::plugin_interface_t
});
ol->connect(&output_removed);

output_changed.set_callback([this] (wf::output_configuration_changed_signal *ev)
{
auto output_state = output_states[ev->output];
auto size = ev->output->get_screen_size();
if (output_state->surface_node)
{
output_state->surface_node->configure(size);
}

if (output_state->crashed_node)
{
output_state->crashed_node->set_size(size);
}
});

for (auto output : ol->get_outputs())
{
handle_output_added(output);
Expand All @@ -212,13 +240,9 @@ class wf_session_lock_plugin : public wf::plugin_interface_t
return;
}

auto size = output->get_screen_size();
wlr_session_lock_surface_v1_configure(lock_surface, size.width, size.height);
LOGC(LSHELL, "surface_configure on ", wo->name, " ", size.width, "x", size.height);

// TODO: hook into output size changes and reconfigure.

auto surface_node = std::make_shared<lock_surface_node>(lock_surface, output);
surface_node->configure(output->get_screen_size());

output_states[output]->surface_destroy.set_callback(
[this, surface_node, output] (void*)
{
Expand Down Expand Up @@ -276,21 +300,33 @@ class wf_session_lock_plugin : public wf::plugin_interface_t
~wayfire_session_lock()
{
disconnect_signals();
output_changed.disconnect();
output_added.disconnect();
output_removed.disconnect();
remove_crashed_nodes();
}

private:
void handle_output_added(wf::output_t *output)
{
output_states[output] = std::make_shared<output_state>();
output_states[output] = std::make_shared<output_state>(output);
if (state == LOCKED)
{
lock_output(output, output_states[output]);
}

if (state == ZOMBIE)
{
output->set_inhibited(true);
output_states[output]->crashed_node->display();
}

output->connect(&output_changed);
}

void handle_output_removed(wf::output_t *output)
{
output->disconnect(&output_changed);
output_states.erase(output);
}

Expand All @@ -315,10 +351,7 @@ class wf_session_lock_plugin : public wf::plugin_interface_t
output_state->surface_node->display();
}

output_state->crashed_node = std::make_shared<lock_crashed_node>(output);
output_state->crashed_node->set_text("");
auto layer_node = output->node_for_layer(wf::scene::layer::LOCK);
wf::scene::add_back(layer_node, output_state->crashed_node);
// TODO: if the surface node has not yet been displayed, display... something?
}

void lock_all()
Expand Down Expand Up @@ -368,8 +401,10 @@ class wf_session_lock_plugin : public wf::plugin_interface_t

void disconnect_signals()
{
output_added.disconnect();
output_removed.disconnect();
// Disconnect lock_session protocol signals and lock timer because the client has gone.
// Leave output monitoring signals connected: if the client crashed and this lock is
// in ZOMBIE state, it must keep monitoring output changes to add/remove/resize
// lock_crashed_nodes.
new_surface.disconnect();
unlock.disconnect();
destroy.disconnect();
Expand All @@ -386,6 +421,7 @@ class wf_session_lock_plugin : public wf::plugin_interface_t
wf::wl_listener_wrapper destroy;

wf::signal::connection_t<wf::output_added_signal> output_added;
wf::signal::connection_t<wf::output_configuration_changed_signal> output_changed;
wf::signal::connection_t<wf::output_removed_signal> output_removed;

lock_state state = UNLOCKED;
Expand Down Expand Up @@ -424,14 +460,14 @@ class wf_session_lock_plugin : public wf::plugin_interface_t
{
switch (state)
{
case UNLOCKED:
case LOCKING:
case LOCKED:
break;

case UNLOCKED:
// Screen unlocked.
// If a session lock client had previously crashed, destroy it to un-inhibit outputs,
// remove lock_crashed_nodes, etc.
case LOCKED:
// Screen locked.
// If a previous lock is in zombie state, delete it, so it stops listening for output
// changes, removes lock_crashed_nodes, etc.
prev_lock.reset();
break;

Expand Down
Loading