mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-28 05:40:11 -04:00
xdg-dialog-v1: add implementation
This commit is contained in:
parent
be555a9a99
commit
90530d43fe
4 changed files with 251 additions and 0 deletions
57
include/wlr/types/wlr_xdg_dialog_v1.h
Normal file
57
include/wlr/types/wlr_xdg_dialog_v1.h
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||||
|
* future consistency of this API.
|
||||||
|
*/
|
||||||
|
#ifndef WLR_USE_UNSTABLE
|
||||||
|
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WLR_TYPES_WLR_XDG_DIALOG_V1_H
|
||||||
|
#define WLR_TYPES_WLR_XDG_DIALOG_V1_H
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/util/addon.h>
|
||||||
|
|
||||||
|
struct wlr_xdg_dialog_v1 {
|
||||||
|
struct wl_resource *resource;
|
||||||
|
struct wlr_xdg_toplevel *xdg_toplevel;
|
||||||
|
|
||||||
|
bool modal;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_signal destroy;
|
||||||
|
// Corresponds to both xdg_dialog_v1.set_modal and xdg_dialog_v1.unset_modal
|
||||||
|
struct wl_signal set_modal;
|
||||||
|
} events;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wlr_addon surface_addon;
|
||||||
|
|
||||||
|
struct wl_listener xdg_toplevel_destroy;
|
||||||
|
} WLR_PRIVATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_xdg_wm_dialog_v1 {
|
||||||
|
struct wl_global *global;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_signal new_dialog; // struct wlr_xdg_dialog_v1
|
||||||
|
} events;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_listener display_destroy;
|
||||||
|
} WLR_PRIVATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_xdg_wm_dialog_v1 *wlr_xdg_wm_dialog_v1_create(struct wl_display *display,
|
||||||
|
uint32_t version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a struct wlr_xdg_dialog_v1 from a struct wlr_xdg_toplevel.
|
||||||
|
*
|
||||||
|
* Returns NULL if there's no xdg_dialog_v1 associated with the xdg toplevel.
|
||||||
|
*/
|
||||||
|
struct wlr_xdg_dialog_v1 *wlr_xdg_dialog_v1_try_from_wlr_xdg_toplevel(
|
||||||
|
struct wlr_xdg_toplevel *xdg_toplevel);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -35,6 +35,7 @@ protocols = {
|
||||||
'security-context-v1': wl_protocol_dir / 'staging/security-context/security-context-v1.xml',
|
'security-context-v1': wl_protocol_dir / 'staging/security-context/security-context-v1.xml',
|
||||||
'single-pixel-buffer-v1': wl_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
|
'single-pixel-buffer-v1': wl_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
|
||||||
'xdg-activation-v1': wl_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
|
'xdg-activation-v1': wl_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
|
||||||
|
'xdg-dialog-v1': wl_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
|
||||||
'xdg-system-bell-v1': wl_protocol_dir / 'staging/xdg-system-bell/xdg-system-bell-v1.xml',
|
'xdg-system-bell-v1': wl_protocol_dir / 'staging/xdg-system-bell/xdg-system-bell-v1.xml',
|
||||||
'xwayland-shell-v1': wl_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
|
'xwayland-shell-v1': wl_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
|
||||||
'tearing-control-v1': wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
'tearing-control-v1': wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ wlr_files += files(
|
||||||
'wlr_xcursor_manager.c',
|
'wlr_xcursor_manager.c',
|
||||||
'wlr_xdg_activation_v1.c',
|
'wlr_xdg_activation_v1.c',
|
||||||
'wlr_xdg_decoration_v1.c',
|
'wlr_xdg_decoration_v1.c',
|
||||||
|
'wlr_xdg_dialog_v1.c',
|
||||||
'wlr_xdg_foreign_v1.c',
|
'wlr_xdg_foreign_v1.c',
|
||||||
'wlr_xdg_foreign_v2.c',
|
'wlr_xdg_foreign_v2.c',
|
||||||
'wlr_xdg_foreign_registry.c',
|
'wlr_xdg_foreign_registry.c',
|
||||||
|
|
|
||||||
192
types/wlr_xdg_dialog_v1.c
Normal file
192
types/wlr_xdg_dialog_v1.c
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_xdg_dialog_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
|
|
||||||
|
#include "xdg-dialog-v1-protocol.h"
|
||||||
|
|
||||||
|
// NOTE: xdg_dialog_v1 becomes inert when the corresponding xdg_toplevel is destroyed
|
||||||
|
|
||||||
|
#define XDG_WM_DIALOG_V1_VERSION 1
|
||||||
|
|
||||||
|
static const struct xdg_dialog_v1_interface dialog_impl;
|
||||||
|
|
||||||
|
static struct wlr_xdg_dialog_v1 *dialog_from_resource(struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource, &xdg_dialog_v1_interface, &dialog_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xdg_wm_dialog_v1_interface wm_impl;
|
||||||
|
|
||||||
|
static struct wlr_xdg_wm_dialog_v1 *wm_from_resource(struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource, &xdg_wm_dialog_v1_interface, &wm_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resource_destroy(struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_addon_destroy(struct wlr_addon *addon) {
|
||||||
|
// As wlr_xdg_toplevel is always destroyed before the surface, this should
|
||||||
|
// never be reached.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_addon_interface surface_addon_impl = {
|
||||||
|
.name = "xdg_wm_dialog_v1",
|
||||||
|
.destroy = surface_addon_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void set_modal(struct wlr_xdg_dialog_v1 *dialog, bool modal) {
|
||||||
|
if (dialog->modal == modal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialog->modal = modal;
|
||||||
|
wl_signal_emit_mutable(&dialog->events.set_modal, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dialog_handle_set_modal(struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
struct wlr_xdg_dialog_v1 *dialog = dialog_from_resource(resource);
|
||||||
|
if (dialog == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_modal(dialog, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dialog_handle_unset_modal(struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
struct wlr_xdg_dialog_v1 *dialog = dialog_from_resource(resource);
|
||||||
|
if (dialog == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_modal(dialog, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct xdg_dialog_v1_interface dialog_impl = {
|
||||||
|
.destroy = resource_destroy,
|
||||||
|
.set_modal = dialog_handle_set_modal,
|
||||||
|
.unset_modal = dialog_handle_unset_modal,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dialog_destroy(struct wlr_xdg_dialog_v1 *dialog) {
|
||||||
|
if (dialog == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_signal_emit_mutable(&dialog->events.destroy, NULL);
|
||||||
|
|
||||||
|
wlr_addon_finish(&dialog->surface_addon);
|
||||||
|
wl_list_remove(&dialog->xdg_toplevel_destroy.link);
|
||||||
|
|
||||||
|
wl_resource_set_user_data(dialog->resource, NULL);
|
||||||
|
free(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct wlr_xdg_dialog_v1 *dialog = wl_container_of(listener, dialog, xdg_toplevel_destroy);
|
||||||
|
dialog_destroy(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_resource_destroy(struct wl_resource *resource) {
|
||||||
|
struct wlr_xdg_dialog_v1 *dialog = dialog_from_resource(resource);
|
||||||
|
dialog_destroy(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_get_xdg_dialog(struct wl_client *client, struct wl_resource *wm_resource,
|
||||||
|
uint32_t id, struct wl_resource *toplevel_resource) {
|
||||||
|
struct wlr_xdg_wm_dialog_v1 *wm = wm_from_resource(wm_resource);
|
||||||
|
struct wlr_xdg_toplevel *xdg_toplevel = wlr_xdg_toplevel_from_resource(toplevel_resource);
|
||||||
|
|
||||||
|
struct wlr_addon_set *addon_set = &xdg_toplevel->base->surface->addons;
|
||||||
|
|
||||||
|
if (wlr_addon_find(addon_set, NULL, &surface_addon_impl) != NULL) {
|
||||||
|
wl_resource_post_error(wm_resource, XDG_WM_DIALOG_V1_ERROR_ALREADY_USED,
|
||||||
|
"the xdg_toplevel object has already been used to create a xdg_dialog_v1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_xdg_dialog_v1 *dialog = calloc(1, sizeof(*dialog));
|
||||||
|
if (dialog == NULL) {
|
||||||
|
wl_resource_post_no_memory(wm_resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog->resource = wl_resource_create(client, &xdg_dialog_v1_interface,
|
||||||
|
wl_resource_get_version(wm_resource), id);
|
||||||
|
if (dialog->resource == NULL) {
|
||||||
|
free(dialog);
|
||||||
|
wl_resource_post_no_memory(wm_resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_resource_set_implementation(dialog->resource, &dialog_impl,
|
||||||
|
dialog, handle_resource_destroy);
|
||||||
|
|
||||||
|
dialog->xdg_toplevel = xdg_toplevel;
|
||||||
|
wlr_addon_init(&dialog->surface_addon, addon_set, NULL, &surface_addon_impl);
|
||||||
|
|
||||||
|
dialog->xdg_toplevel_destroy.notify = handle_xdg_toplevel_destroy;
|
||||||
|
wl_signal_add(&xdg_toplevel->events.destroy, &dialog->xdg_toplevel_destroy);
|
||||||
|
|
||||||
|
wl_signal_init(&dialog->events.destroy);
|
||||||
|
wl_signal_init(&dialog->events.set_modal);
|
||||||
|
|
||||||
|
wl_signal_emit_mutable(&wm->events.new_dialog, dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xdg_wm_dialog_v1_interface wm_impl = {
|
||||||
|
.destroy = resource_destroy,
|
||||||
|
.get_xdg_dialog = wm_get_xdg_dialog,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void wm_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) {
|
||||||
|
struct wlr_xdg_wm_dialog_v1 *wm = data;
|
||||||
|
struct wl_resource *resource =
|
||||||
|
wl_resource_create(client, &xdg_wm_dialog_v1_interface, version, id);
|
||||||
|
if (resource == NULL) {
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_resource_set_implementation(resource, &wm_impl, wm, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xdg_wm_dialog_handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct wlr_xdg_wm_dialog_v1 *wm = wl_container_of(listener, wm, display_destroy);
|
||||||
|
wl_list_remove(&wm->display_destroy.link);
|
||||||
|
wl_global_destroy(wm->global);
|
||||||
|
free(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_xdg_dialog_v1 *wlr_xdg_dialog_v1_try_from_wlr_xdg_toplevel(
|
||||||
|
struct wlr_xdg_toplevel *xdg_toplevel) {
|
||||||
|
struct wlr_addon *addon =
|
||||||
|
wlr_addon_find(&xdg_toplevel->base->surface->addons, NULL, &surface_addon_impl);
|
||||||
|
if (addon == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct wlr_xdg_dialog_v1 *dialog = wl_container_of(addon, dialog, surface_addon);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_xdg_wm_dialog_v1 *wlr_xdg_wm_dialog_v1_create(struct wl_display *display,
|
||||||
|
uint32_t version) {
|
||||||
|
assert(version <= XDG_WM_DIALOG_V1_VERSION);
|
||||||
|
|
||||||
|
struct wlr_xdg_wm_dialog_v1 *wm = calloc(1, sizeof(*wm));
|
||||||
|
if (wm == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm->global = wl_global_create(display, &xdg_wm_dialog_v1_interface, version, wm, wm_bind);
|
||||||
|
if (wm->global == NULL) {
|
||||||
|
free(wm);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm->display_destroy.notify = xdg_wm_dialog_handle_display_destroy;
|
||||||
|
wl_display_add_destroy_listener(display, &wm->display_destroy);
|
||||||
|
|
||||||
|
wl_signal_init(&wm->events.new_dialog);
|
||||||
|
|
||||||
|
return wm;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue