mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-13 08:22:16 -04:00
Merge branch 'responsiveness' into 'master'
foreign-toplevel-management: Allow to emit toplevels responsiveness state See merge request wlroots/wlroots!4924
This commit is contained in:
commit
4366ed1655
4 changed files with 143 additions and 3 deletions
|
|
@ -36,6 +36,11 @@ enum wlr_foreign_toplevel_handle_v1_state {
|
|||
WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN = (1 << 3),
|
||||
};
|
||||
|
||||
enum wlr_foreign_toplevel_handle_v1_responsiveness {
|
||||
WLR_FOREIGN_TOPLEVEL_HANDLE_V1_RESPONSIVENESS_RESPONSIVE = (0 << 0),
|
||||
WLR_FOREIGN_TOPLEVEL_HANDLE_V1_RESPONSIVENESS_UNRESPONSIVE = (1 << 0),
|
||||
};
|
||||
|
||||
struct wlr_foreign_toplevel_handle_v1_output {
|
||||
struct wl_list link; // wlr_foreign_toplevel_handle_v1.outputs
|
||||
struct wlr_output *output;
|
||||
|
|
@ -57,6 +62,7 @@ struct wlr_foreign_toplevel_handle_v1 {
|
|||
char *app_id;
|
||||
struct wlr_foreign_toplevel_handle_v1 *parent;
|
||||
struct wl_list outputs; // wlr_foreign_toplevel_v1_output.link
|
||||
uint32_t responsiveness; // enum wlr_foreign_toplevel_v1_responsiveness
|
||||
uint32_t state; // enum wlr_foreign_toplevel_v1_state
|
||||
|
||||
struct {
|
||||
|
|
@ -151,5 +157,7 @@ void wlr_foreign_toplevel_handle_v1_set_parent(
|
|||
struct wlr_foreign_toplevel_handle_v1 *toplevel,
|
||||
struct wlr_foreign_toplevel_handle_v1 *parent);
|
||||
|
||||
void wlr_foreign_toplevel_handle_v1_set_responsive(
|
||||
struct wlr_foreign_toplevel_handle_v1 *toplevel, bool responsive);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwlr_foreign_toplevel_manager_v1" version="3">
|
||||
<interface name="zwlr_foreign_toplevel_manager_v1" version="4">
|
||||
<description summary="list and control opened apps">
|
||||
The purpose of this protocol is to enable the creation of taskbars
|
||||
and docks by providing them with a list of opened applications and
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_foreign_toplevel_handle_v1" version="3">
|
||||
<interface name="zwlr_foreign_toplevel_handle_v1" version="4">
|
||||
<description summary="an opened toplevel">
|
||||
A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
|
||||
window. Each app may have multiple opened toplevels.
|
||||
|
|
@ -266,5 +266,27 @@
|
|||
</description>
|
||||
<arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
|
||||
<enum name="responsiveness" since="4">
|
||||
<description summary="types of responsiveness states">
|
||||
The different responsiveness states that a toplevel can have. If the client didn't receive
|
||||
any event from the compositor it should assume the client is responsive.
|
||||
</description>
|
||||
|
||||
<entry name="responsive" value="0" summary="the compositor deems the toplevel reponsive"/>
|
||||
<entry name="unresponsive" value="1" summary="the compositor deems the toplevel is unresponsive"/>
|
||||
</enum>
|
||||
|
||||
<event name="responsiveness" since="4">
|
||||
<description summary="responsiveness">
|
||||
This event is emitted when the compositor detects a change in the toplevels responsiveness.
|
||||
An unresponsive toplevel usually doesn't respond to ping requests send by the compositor
|
||||
while a responsive one does but a compositor might use more elaborate means to detect if a
|
||||
toplevel is still usable by the user.
|
||||
</description>
|
||||
<arg name="responsive" type="uint" enum="responsiveness"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
|
@ -68,6 +69,8 @@ struct tinywl_server {
|
|||
struct wlr_output_layout *output_layout;
|
||||
struct wl_list outputs;
|
||||
struct wl_listener new_output;
|
||||
|
||||
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
||||
};
|
||||
|
||||
struct tinywl_output {
|
||||
|
|
@ -83,15 +86,20 @@ struct tinywl_toplevel {
|
|||
struct wl_list link;
|
||||
struct tinywl_server *server;
|
||||
struct wlr_xdg_toplevel *xdg_toplevel;
|
||||
struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel;
|
||||
struct wlr_scene_tree *scene_tree;
|
||||
struct wl_listener map;
|
||||
struct wl_listener unmap;
|
||||
struct wl_listener commit;
|
||||
struct wl_listener set_app_id;
|
||||
struct wl_listener set_title;
|
||||
struct wl_listener set_parent;
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener request_move;
|
||||
struct wl_listener request_resize;
|
||||
struct wl_listener request_maximize;
|
||||
struct wl_listener request_fullscreen;
|
||||
struct wl_listener ping_timeout;
|
||||
};
|
||||
|
||||
struct tinywl_popup {
|
||||
|
|
@ -151,6 +159,8 @@ static void focus_toplevel(struct tinywl_toplevel *toplevel) {
|
|||
wlr_seat_keyboard_notify_enter(seat, surface,
|
||||
keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
|
||||
}
|
||||
wlr_log(WLR_DEBUG, "Pinging toplevel %s", toplevel->xdg_toplevel->title);
|
||||
wlr_xdg_surface_ping(toplevel->xdg_toplevel->base);
|
||||
}
|
||||
|
||||
static void keyboard_handle_modifiers(
|
||||
|
|
@ -704,18 +714,54 @@ static void xdg_toplevel_commit(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
}
|
||||
|
||||
static void xdg_toplevel_set_app_id(struct wl_listener *listener, void *data) {
|
||||
/* Called when the toplevel wants to set its app ID. */
|
||||
struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, set_app_id);
|
||||
const char *app_id = toplevel->xdg_toplevel->app_id;
|
||||
wlr_foreign_toplevel_handle_v1_set_app_id(toplevel->foreign_toplevel, app_id);
|
||||
}
|
||||
|
||||
static void xdg_toplevel_set_title(struct wl_listener *listener, void *data) {
|
||||
/* Called when the toplevel wants to set its title. */
|
||||
struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, set_title);
|
||||
const char *title = toplevel->xdg_toplevel->title;
|
||||
wlr_foreign_toplevel_handle_v1_set_title(toplevel->foreign_toplevel, title);
|
||||
}
|
||||
|
||||
static void xdg_toplevel_set_parent(struct wl_listener *listener, void *data) {
|
||||
/* Called when the toplevel wants to set its parent. */
|
||||
struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, set_parent);
|
||||
|
||||
/* Iterate through list of toplevels and find the tinywl_toplevel whose xdg_toplevel is the
|
||||
* current toplevel's parent. */
|
||||
struct wlr_foreign_toplevel_handle_v1 *foreign_parent_toplevel = NULL;
|
||||
struct tinywl_toplevel *parent_toplevel;
|
||||
wl_list_for_each(parent_toplevel, &toplevel->server->toplevels, link) {
|
||||
if (parent_toplevel->xdg_toplevel == toplevel->xdg_toplevel->parent) {
|
||||
foreign_parent_toplevel = parent_toplevel->foreign_toplevel;
|
||||
}
|
||||
}
|
||||
wlr_foreign_toplevel_handle_v1_set_parent(toplevel->foreign_toplevel, foreign_parent_toplevel);
|
||||
}
|
||||
|
||||
static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
|
||||
/* Called when the xdg_toplevel is destroyed. */
|
||||
struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, destroy);
|
||||
|
||||
wlr_foreign_toplevel_handle_v1_destroy(toplevel->foreign_toplevel);
|
||||
|
||||
wl_list_remove(&toplevel->map.link);
|
||||
wl_list_remove(&toplevel->unmap.link);
|
||||
wl_list_remove(&toplevel->commit.link);
|
||||
wl_list_remove(&toplevel->set_app_id.link);
|
||||
wl_list_remove(&toplevel->set_title.link);
|
||||
wl_list_remove(&toplevel->set_parent.link);
|
||||
wl_list_remove(&toplevel->destroy.link);
|
||||
wl_list_remove(&toplevel->request_move.link);
|
||||
wl_list_remove(&toplevel->request_resize.link);
|
||||
wl_list_remove(&toplevel->request_maximize.link);
|
||||
wl_list_remove(&toplevel->request_fullscreen.link);
|
||||
wl_list_remove(&toplevel->ping_timeout.link);
|
||||
|
||||
free(toplevel);
|
||||
}
|
||||
|
|
@ -800,6 +846,14 @@ static void xdg_toplevel_request_fullscreen(
|
|||
}
|
||||
}
|
||||
|
||||
static void xdg_toplevel_ping_timeout(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct tinywl_toplevel *toplevel =
|
||||
wl_container_of(listener, toplevel, ping_timeout);
|
||||
wlr_log(WLR_DEBUG, "Ping timeout for toplevel %s", toplevel->xdg_toplevel->title);
|
||||
wlr_foreign_toplevel_handle_v1_set_responsive(toplevel->foreign_toplevel, false);
|
||||
}
|
||||
|
||||
static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
|
||||
/* This event is raised when a client creates a new toplevel (application window). */
|
||||
struct tinywl_server *server = wl_container_of(listener, server, new_xdg_toplevel);
|
||||
|
|
@ -814,6 +868,11 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
|
|||
toplevel->scene_tree->node.data = toplevel;
|
||||
xdg_toplevel->base->data = toplevel->scene_tree;
|
||||
|
||||
/* Setup foreign_toplevel_handle */
|
||||
struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel =
|
||||
wlr_foreign_toplevel_handle_v1_create(server->foreign_toplevel_manager);
|
||||
toplevel->foreign_toplevel = foreign_toplevel;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
toplevel->map.notify = xdg_toplevel_map;
|
||||
wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map);
|
||||
|
|
@ -821,6 +880,12 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
|
|||
wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap);
|
||||
toplevel->commit.notify = xdg_toplevel_commit;
|
||||
wl_signal_add(&xdg_toplevel->base->surface->events.commit, &toplevel->commit);
|
||||
toplevel->set_app_id.notify = xdg_toplevel_set_app_id;
|
||||
wl_signal_add(&xdg_toplevel->events.set_app_id, &toplevel->set_app_id);
|
||||
toplevel->set_title.notify = xdg_toplevel_set_title;
|
||||
wl_signal_add(&xdg_toplevel->events.set_title, &toplevel->set_title);
|
||||
toplevel->set_parent.notify = xdg_toplevel_set_parent;
|
||||
wl_signal_add(&xdg_toplevel->events.set_parent, &toplevel->set_parent);
|
||||
|
||||
toplevel->destroy.notify = xdg_toplevel_destroy;
|
||||
wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy);
|
||||
|
|
@ -834,6 +899,10 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
|
|||
wl_signal_add(&xdg_toplevel->events.request_maximize, &toplevel->request_maximize);
|
||||
toplevel->request_fullscreen.notify = xdg_toplevel_request_fullscreen;
|
||||
wl_signal_add(&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen);
|
||||
|
||||
/* Check for responsiveness */
|
||||
toplevel->ping_timeout.notify = xdg_toplevel_ping_timeout;
|
||||
wl_signal_add(&xdg_toplevel->base->events.ping_timeout, &toplevel->ping_timeout);
|
||||
}
|
||||
|
||||
static void xdg_popup_commit(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -1038,6 +1107,14 @@ int main(int argc, char *argv[]) {
|
|||
wl_signal_add(&server.seat->events.request_set_selection,
|
||||
&server.request_set_selection);
|
||||
|
||||
/* Setup foreign_toplevel_management. This protocol allows creation of taskbars, docks etc.
|
||||
* which can manage the windows (like maximize, minimize etc.). The current code of tinywl does
|
||||
* not process these requests. However, this protocol has been added to demonstrate the usage of
|
||||
* responsiveness event. This event allows tinywl to inform foreign_toplevel_management clients
|
||||
* of unresponsive apps.
|
||||
*/
|
||||
server.foreign_toplevel_manager = wlr_foreign_toplevel_manager_v1_create(server.wl_display);
|
||||
|
||||
/* Add a Unix socket to the Wayland display. */
|
||||
const char *socket = wl_display_add_socket_auto(server.wl_display);
|
||||
if (!socket) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <wlr/util/log.h>
|
||||
#include "wlr-foreign-toplevel-management-unstable-v1-protocol.h"
|
||||
|
||||
#define FOREIGN_TOPLEVEL_MANAGEMENT_V1_VERSION 3
|
||||
#define FOREIGN_TOPLEVEL_MANAGEMENT_V1_VERSION 4
|
||||
|
||||
#define FOREIGN_TOPLEVEL_HANDLE_V1_STATE_COUNT 32
|
||||
|
||||
|
|
@ -445,6 +445,32 @@ void wlr_foreign_toplevel_handle_v1_set_parent(
|
|||
toplevel_update_idle_source(toplevel);
|
||||
}
|
||||
|
||||
void wlr_foreign_toplevel_handle_v1_set_responsive(
|
||||
struct wlr_foreign_toplevel_handle_v1 *toplevel, bool responsive) {
|
||||
enum wlr_foreign_toplevel_handle_v1_responsiveness responsiveness;
|
||||
if (responsive) {
|
||||
responsiveness = WLR_FOREIGN_TOPLEVEL_HANDLE_V1_RESPONSIVENESS_RESPONSIVE;
|
||||
} else {
|
||||
responsiveness = WLR_FOREIGN_TOPLEVEL_HANDLE_V1_RESPONSIVENESS_UNRESPONSIVE;
|
||||
}
|
||||
|
||||
if (toplevel->responsiveness == responsiveness) {
|
||||
// Only inform clients if the state changed
|
||||
return;
|
||||
}
|
||||
|
||||
struct wl_resource *resource;
|
||||
wl_resource_for_each(resource, &toplevel->resources) {
|
||||
if (wl_resource_get_version(resource) <
|
||||
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_RESPONSIVENESS_SINCE_VERSION) {
|
||||
continue;
|
||||
}
|
||||
zwlr_foreign_toplevel_handle_v1_send_responsiveness(resource, responsiveness);
|
||||
}
|
||||
toplevel->responsiveness = responsiveness;
|
||||
toplevel_update_idle_source(toplevel);
|
||||
}
|
||||
|
||||
void wlr_foreign_toplevel_handle_v1_destroy(
|
||||
struct wlr_foreign_toplevel_handle_v1 *toplevel) {
|
||||
if (!toplevel) {
|
||||
|
|
@ -536,6 +562,8 @@ wlr_foreign_toplevel_handle_v1_create(
|
|||
wl_list_init(&toplevel->resources);
|
||||
wl_list_init(&toplevel->outputs);
|
||||
|
||||
toplevel->responsiveness = WLR_FOREIGN_TOPLEVEL_HANDLE_V1_RESPONSIVENESS_RESPONSIVE;
|
||||
|
||||
wl_signal_init(&toplevel->events.request_maximize);
|
||||
wl_signal_init(&toplevel->events.request_minimize);
|
||||
wl_signal_init(&toplevel->events.request_activate);
|
||||
|
|
@ -598,6 +626,11 @@ static void toplevel_send_details_to_toplevel_resource(
|
|||
|
||||
toplevel_resource_send_parent(resource, toplevel->parent);
|
||||
|
||||
if (wl_resource_get_version(resource) >=
|
||||
ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_RESPONSIVENESS_SINCE_VERSION) {
|
||||
zwlr_foreign_toplevel_handle_v1_send_responsiveness(resource, toplevel->responsiveness);
|
||||
}
|
||||
|
||||
zwlr_foreign_toplevel_handle_v1_send_done(resource);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue