mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-17 06:46:39 -04:00
[DEBUG] Add dbg-txn protocol
This commit is contained in:
parent
f8030ef5ae
commit
5b41595f4d
7 changed files with 207 additions and 1 deletions
23
include/wlr/types/wlr_dbg_txn.h
Normal file
23
include/wlr/types/wlr_dbg_txn.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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_DBG_TXN_H
|
||||
#define WLR_TYPES_WLR_DBG_TXN_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include "dbg-txn-protocol.h"
|
||||
|
||||
struct wlr_dbg_txn_manager {
|
||||
struct wl_global *global;
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
};
|
||||
|
||||
struct wlr_dbg_txn_manager *wlr_dbg_txn_manager_create(struct wl_display *display);
|
||||
|
||||
#endif
|
||||
17
protocol/dbg-txn.xml
Normal file
17
protocol/dbg-txn.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="dbg_txn">
|
||||
<interface name="dbg_txn_manager" version="1">
|
||||
<request name="get_txn">
|
||||
<arg name="id" type="new_id" interface="dbg_txn"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="dbg_txn" version="1">
|
||||
<request name="add_surface">
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="commit" type="destructor">
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
@ -64,6 +64,8 @@ protocols = {
|
|||
'wlr-output-power-management-unstable-v1': 'wlr-output-power-management-unstable-v1.xml',
|
||||
'wlr-screencopy-unstable-v1': 'wlr-screencopy-unstable-v1.xml',
|
||||
'wlr-virtual-pointer-unstable-v1': 'wlr-virtual-pointer-unstable-v1.xml',
|
||||
|
||||
'dbg-txn': 'dbg-txn.xml',
|
||||
}
|
||||
|
||||
protocols_code = {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
executable(
|
||||
'tinywl',
|
||||
['tinywl.c', protocols_server_header['xdg-shell']],
|
||||
['tinywl.c', protocols_server_header['xdg-shell'],
|
||||
protocols_server_header['dbg-txn'], protocols_server_header['viewporter']],
|
||||
dependencies: wlroots,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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_dbg_txn.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_viewporter.h>
|
||||
#include <wlr/types/wlr_xcursor_manager.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
|
@ -981,6 +983,9 @@ int main(int argc, char *argv[]) {
|
|||
* HiDPI support). */
|
||||
server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
|
||||
|
||||
wlr_viewporter_create(server.wl_display);
|
||||
wlr_dbg_txn_manager_create(server.wl_display);
|
||||
|
||||
/*
|
||||
* wlr_cursor *only* displays an image on screen. It does not move around
|
||||
* when the pointer moves. However, we can attach input devices to it, and
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ wlr_files += files(
|
|||
'wlr_cursor.c',
|
||||
'wlr_damage_ring.c',
|
||||
'wlr_data_control_v1.c',
|
||||
'wlr_dbg_txn.c',
|
||||
'wlr_drm.c',
|
||||
'wlr_export_dmabuf_v1.c',
|
||||
'wlr_foreign_toplevel_management_v1.c',
|
||||
|
|
|
|||
157
types/wlr_dbg_txn.c
Normal file
157
types/wlr_dbg_txn.c
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_dbg_txn.h>
|
||||
|
||||
struct wlr_dbg_txn {
|
||||
struct wl_resource *resource;
|
||||
struct wl_list locks;
|
||||
};
|
||||
|
||||
struct wlr_dbg_txn_lock {
|
||||
struct wlr_addon addon;
|
||||
struct wlr_surface_state_lock lock;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
static const struct dbg_txn_interface txn_impl;
|
||||
|
||||
static struct wlr_dbg_txn *txn_from_resource(struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource, &dbg_txn_interface, &txn_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static void txn_lock_destroy(struct wlr_dbg_txn_lock *lock) {
|
||||
wlr_surface_state_lock_release(&lock->lock);
|
||||
wl_list_remove(&lock->link);
|
||||
wlr_addon_finish(&lock->addon);
|
||||
free(lock);
|
||||
}
|
||||
|
||||
static void addon_handle_destroy(struct wlr_addon *addon) {
|
||||
struct wlr_dbg_txn_lock *lock = wl_container_of(addon, lock, addon);
|
||||
txn_lock_destroy(lock);
|
||||
}
|
||||
|
||||
static struct wlr_addon_interface addon_impl = {
|
||||
.name = "wlr_dbg_txn_lock",
|
||||
.destroy = addon_handle_destroy,
|
||||
};
|
||||
|
||||
static void txn_handle_add_surface(struct wl_client *client, struct wl_resource *resource,
|
||||
struct wl_resource *surface_resource) {
|
||||
struct wlr_surface *surface = wlr_surface_from_resource(surface_resource);
|
||||
if (wlr_addon_find(&surface->addons, NULL, &addon_impl) != NULL) {
|
||||
wl_resource_post_error(resource, -1, "already added");
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_dbg_txn *txn = txn_from_resource(resource);
|
||||
struct wlr_dbg_txn_lock *lock = calloc(1, sizeof(*lock));
|
||||
assert(lock != NULL);
|
||||
wlr_surface_state_lock_acquire(&lock->lock, surface);
|
||||
wl_list_insert(&txn->locks, &lock->link);
|
||||
wlr_addon_init(&lock->addon, &surface->addons, NULL, &addon_impl);
|
||||
}
|
||||
|
||||
static void txn_handle_commit(struct wl_client *client, struct wl_resource *resource) {
|
||||
struct wlr_dbg_txn *txn = txn_from_resource(resource);
|
||||
|
||||
struct wl_array buffer;
|
||||
wl_array_init(&buffer);
|
||||
|
||||
struct wlr_surface_transaction surface_txn;
|
||||
wlr_surface_transaction_init(&surface_txn, &buffer);
|
||||
|
||||
bool ok = true;
|
||||
struct wlr_dbg_txn_lock *lock;
|
||||
wl_list_for_each(lock, &txn->locks, link) {
|
||||
if (!wlr_surface_transaction_add_lock(&surface_txn, &lock->lock)) {
|
||||
wlr_surface_transaction_drop(&surface_txn);
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
ok = wlr_surface_transaction_commit(&surface_txn);
|
||||
}
|
||||
if (!ok) {
|
||||
wl_resource_post_no_memory(resource);
|
||||
}
|
||||
|
||||
wl_array_release(&buffer);
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct dbg_txn_interface txn_impl = {
|
||||
.add_surface = txn_handle_add_surface,
|
||||
.commit = txn_handle_commit,
|
||||
};
|
||||
|
||||
static void txn_handle_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_dbg_txn *txn = txn_from_resource(resource);
|
||||
struct wlr_dbg_txn_lock *lock, *tmp;
|
||||
wl_list_for_each_safe(lock, tmp, &txn->locks, link) {
|
||||
txn_lock_destroy(lock);
|
||||
}
|
||||
free(txn);
|
||||
}
|
||||
|
||||
static void manager_handle_get_txn(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t id) {
|
||||
struct wlr_dbg_txn *txn = calloc(1, sizeof(*txn));
|
||||
if (txn == NULL) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
txn->resource = wl_resource_create(client, &dbg_txn_interface, 1, id);
|
||||
assert(txn->resource != NULL);
|
||||
|
||||
wl_resource_set_implementation(txn->resource, &txn_impl, txn, txn_handle_resource_destroy);
|
||||
|
||||
wl_list_init(&txn->locks);
|
||||
}
|
||||
|
||||
static const struct dbg_txn_manager_interface manager_impl = {
|
||||
.get_txn = manager_handle_get_txn,
|
||||
};
|
||||
|
||||
static void manager_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) {
|
||||
struct wlr_dbg_txn_manager *manager = data;
|
||||
|
||||
struct wl_resource *resource =
|
||||
wl_resource_create(wl_client, &wl_compositor_interface, version, id);
|
||||
if (resource == NULL) {
|
||||
wl_client_post_no_memory(wl_client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(resource, &manager_impl, manager, NULL);
|
||||
}
|
||||
|
||||
static void manager_handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_dbg_txn_manager *manager = wl_container_of(listener, manager, display_destroy);
|
||||
wl_list_remove(&manager->display_destroy.link);
|
||||
wl_global_destroy(manager->global);
|
||||
free(manager);
|
||||
}
|
||||
|
||||
struct wlr_dbg_txn_manager *wlr_dbg_txn_manager_create(struct wl_display *display) {
|
||||
struct wlr_dbg_txn_manager *manager = calloc(1, sizeof(*manager));
|
||||
if (!manager) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->global = wl_global_create(display, &dbg_txn_manager_interface,
|
||||
1, manager, manager_bind);
|
||||
if (!manager->global) {
|
||||
free(manager);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->display_destroy.notify = manager_handle_display_destroy;
|
||||
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
||||
|
||||
return manager;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue