-
Notifications
You must be signed in to change notification settings - Fork 177
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: Implement the session lock protocol
This sort of handles basic locking and unlocking. BUGS: - The swaylock indicator isn't displayed. Perhaps this is because swaylock uses a subsurface to draw it, and wlr-surface-node doesn't support child surfaces? TODO: - Deal with outputs being resized - Use keyboard grabs (fail to lock if grabbed?) - Blank the screen instead of just relying on the lock app to display the surface. Or at least wait for the surface to be committed before saying the lock succeeded.
- Loading branch information
Showing
6 changed files
with
205 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
#include "wayfire/core.hpp" | ||
|
||
#include "wayfire/seat.hpp" | ||
#include "wayfire/scene-input.hpp" | ||
#include "wayfire/scene-operations.hpp" | ||
#include "wayfire/unstable/wlr-surface-node.hpp" | ||
#include "wayfire/output.hpp" | ||
#include "wayfire/output-layout.hpp" | ||
|
||
#include <wayfire/plugin.hpp> | ||
#include <wayfire/nonstd/wlroots-full.hpp> | ||
#include <wayfire/util/log.hpp> | ||
|
||
class wf_session_lock_impl : public wf::plugin_interface_t | ||
{ | ||
class lock_surface_node_t : public wf::scene::wlr_surface_node_t | ||
{ | ||
public: | ||
lock_surface_node_t(wlr_surface *surface, bool autocommit) : | ||
wf::scene::wlr_surface_node_t(surface, autocommit) | ||
{ | ||
interaction = new lock_surface_keyboard_interaction(surface); | ||
} | ||
|
||
wf::keyboard_focus_node_t keyboard_refocus(wf::output_t *output) override | ||
{ | ||
wf::keyboard_focus_node_t node = { | ||
.node = this, | ||
.importance = wf::focus_importance::HIGH, | ||
.allow_focus_below = false, | ||
}; | ||
return node; | ||
} | ||
|
||
class lock_surface_keyboard_interaction : public wf::keyboard_interaction_t | ||
{ | ||
public: | ||
lock_surface_keyboard_interaction(wlr_surface *surface) : surface(surface) | ||
{} | ||
|
||
void handle_keyboard_enter(wf::seat_t *seat) | ||
{ | ||
// TODO: use a keyboard grab instead? | ||
wlr_seat_keyboard_enter(seat->seat, surface, nullptr, 0, nullptr); | ||
} | ||
|
||
void handle_keyboard_leave(wf::seat_t *seat) | ||
{ | ||
// TODO: refocus? | ||
wlr_seat_keyboard_clear_focus(seat->seat); | ||
} | ||
|
||
void handle_keyboard_key(wf::seat_t *seat, wlr_keyboard_key_event event) | ||
{ | ||
wlr_seat_keyboard_notify_key(seat->seat, event.time_msec, event.keycode, event.state); | ||
} | ||
|
||
private: | ||
wlr_surface *surface; | ||
}; | ||
|
||
wf::keyboard_interaction_t& keyboard_interaction() | ||
{ | ||
return *interaction; | ||
} | ||
|
||
private: | ||
wf::keyboard_interaction_t *interaction; | ||
}; | ||
|
||
class wayfire_session_lock | ||
{ | ||
public: | ||
wayfire_session_lock(wf_session_lock_impl *parent, wlr_session_lock_v1 *data) | ||
{ | ||
plugin = parent; | ||
lock = data; | ||
|
||
new_surface.set_callback([this] (void *data) | ||
{ | ||
wlr_session_lock_surface_v1 *lock_surface = (wlr_session_lock_surface_v1*)data; | ||
uint32_t serial = wlr_session_lock_surface_v1_configure(lock_surface, | ||
lock_surface->output->width, | ||
lock_surface->output->height); | ||
LOGI("surface_configure output=", lock_surface->output->name, " ", | ||
lock_surface->output->width, "x", | ||
lock_surface->output->height, | ||
" serial=", serial); | ||
|
||
surfaces.push_back(lock_surface); | ||
|
||
auto node = new std::shared_ptr<wf::scene::wlr_surface_node_t>( | ||
new lock_surface_node_t(lock_surface->surface, true)); | ||
|
||
lock_surface->data = node; | ||
auto target_layer = wf::scene::layer::TOP; | ||
auto wo = wf::get_core().output_layout->find_output(lock_surface->output); | ||
auto layer_node = wo->node_for_layer(target_layer); | ||
|
||
(*node)->set_enabled(true); | ||
wf::scene::add_front(layer_node, *node); | ||
wf::get_core().seat->set_active_node(*node); | ||
|
||
lock_surface_destroy.set_callback([lock_surface, this] (void *data) | ||
{ | ||
auto node = (std::shared_ptr<wf::scene::wlr_surface_node_t>*)lock_surface->data; | ||
if (node != nullptr) | ||
{ | ||
wf::scene::remove_child(*node); | ||
} | ||
|
||
lock_surface_destroy.disconnect(); | ||
}); | ||
lock_surface_destroy.connect(&lock_surface->events.destroy); | ||
}); | ||
new_surface.connect(&lock->events.new_surface); | ||
|
||
unlock.set_callback([this] (void *data) | ||
{ | ||
LOGI("unlock"); | ||
}); | ||
unlock.connect(&lock->events.unlock); | ||
|
||
destroy.set_callback([this] (void *data) | ||
{ | ||
new_surface.disconnect(); | ||
unlock.disconnect(); | ||
destroy.disconnect(); | ||
LOGI("destroy"); | ||
plugin->unlock(); | ||
}); | ||
destroy.connect(&lock->events.destroy); | ||
} | ||
|
||
private: | ||
wf_session_lock_impl *plugin; | ||
wlr_session_lock_v1 *lock; | ||
std::vector<wlr_session_lock_surface_v1*> surfaces; | ||
wf::wl_listener_wrapper new_surface; | ||
wf::wl_listener_wrapper unlock; | ||
wf::wl_listener_wrapper destroy; | ||
wf::wl_listener_wrapper lock_surface_destroy; | ||
}; | ||
|
||
public: | ||
void init() override | ||
{ | ||
auto display = wf::get_core().display; | ||
manager = wlr_session_lock_manager_v1_create(display); | ||
|
||
new_lock.set_callback([this] (void *data) | ||
{ | ||
wlr_session_lock_v1 *wlr_lock = (wlr_session_lock_v1*)data; | ||
if (cur_lock.get() == nullptr) | ||
{ | ||
cur_lock.reset(new wayfire_session_lock(this, wlr_lock)); | ||
// TODO: blank the screen, or set a timeout for the lock app to commit a surface. | ||
wlr_session_lock_v1_send_locked(wlr_lock); | ||
LOGI("new_lock"); | ||
} else | ||
{ | ||
LOGI("new_lock: already locked"); | ||
wlr_session_lock_v1_destroy(wlr_lock); | ||
} | ||
}); | ||
new_lock.connect(&manager->events.new_lock); | ||
|
||
destroyed.set_callback([this] (void *data) | ||
{ | ||
LOGI("session_lock destroyed"); | ||
}); | ||
destroyed.connect(&manager->events.destroy); | ||
} | ||
|
||
void fini() override | ||
{ | ||
// TODO: unlock everything? | ||
} | ||
|
||
bool is_unloadable() override | ||
{ | ||
return false; | ||
} | ||
|
||
void unlock() | ||
{ | ||
cur_lock.reset(); | ||
} | ||
|
||
private: | ||
wlr_session_lock_manager_v1 *manager; | ||
wf::wl_listener_wrapper new_lock; | ||
wf::wl_listener_wrapper destroyed; | ||
|
||
std::shared_ptr<wayfire_session_lock> cur_lock; | ||
}; | ||
|
||
DECLARE_WAYFIRE_PLUGIN(wf_session_lock_impl); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters