[digesting_libdecor] fully eliminate the libdecor context struct merging with my context

main
Allen Webster 2026-02-25 18:24:10 -08:00
parent 8e7ab3b49b
commit cddaa2962f
1 changed files with 126 additions and 297 deletions

View File

@ -68,26 +68,6 @@ struct libdecor_frame;
struct libdecor_configuration; struct libdecor_configuration;
struct libdecor_state; struct libdecor_state;
struct libdecor {
int ref_count;
void *user_data;
struct libdecor_plugin *plugin;
bool plugin_ready;
struct wl_display *wl_display;
struct wl_registry *wl_registry;
struct xdg_wm_base *xdg_wm_base;
struct zxdg_decoration_manager_v1 *decoration_manager;
struct wl_callback *init_callback;
bool init_done;
bool has_error;
struct wl_list frames;
};
enum libdecor_error { enum libdecor_error {
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION, LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
@ -137,38 +117,6 @@ enum libdecor_wm_capabilities {
LIBDECOR_WM_CAPABILITIES_MINIMIZE = 1 << 3 LIBDECOR_WM_CAPABILITIES_MINIMIZE = 1 << 3
}; };
/**
* Remove a reference to the libdecor instance. When the reference count
* reaches zero, it is freed.
*/
void
libdecor_unref(struct libdecor *context);
/**
* Dispatch events. This function should be called when data is available on
* the file descriptor returned by libdecor_get_fd(). If timeout is zero, this
* function will never block.
*/
int
libdecor_dispatch(struct libdecor *context,
int timeout);
/**
* Decorate the given content wl_surface.
*
* This will create an xdg_surface and an xdg_toplevel, and integrate it
* properly with the windowing system, including creating appropriate
* decorations when needed, as well as handle windowing integration events such
* as resizing, moving, maximizing, etc.
*
* The passed wl_surface should only contain actual application content,
* without any window decoration.
*/
struct libdecor_frame *
libdecor_decorate(struct libdecor *context,
struct wl_surface *surface,
void *user_data);
/** /**
* Add a reference to the frame object. * Add a reference to the frame object.
*/ */
@ -463,14 +411,6 @@ libdecor_frame_get_xdg_toplevel(struct libdecor_frame *frame);
enum libdecor_wm_capabilities enum libdecor_wm_capabilities
libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame); libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame);
/**
* Tell libdecor to set the default pointer cursor when the pointer is over an
* application surface. The default false.
*/
void
libdecor_set_handle_application_cursor(struct libdecor *context,
bool handle_cursor);
/** /**
* Create a new content surface state. * Create a new content surface state.
*/ */
@ -526,6 +466,14 @@ typedef struct Ctx{
struct wl_registry *wl_registry; struct wl_registry *wl_registry;
struct wl_compositor *wl_compositor; struct wl_compositor *wl_compositor;
struct xdg_wm_base *xdg_wm_base; struct xdg_wm_base *xdg_wm_base;
struct zxdg_decoration_manager_v1 *decoration_manager;
struct wl_list frames;
struct wl_callback *init_callback;
struct libdecor_plugin *plugin;
bool plugin_ready;
bool init_done;
bool has_error;
/* window */ /* window */
struct wl_surface *wl_surface; struct wl_surface *wl_surface;
@ -541,15 +489,12 @@ typedef struct Ctx{
EGLDisplay egl_display; EGLDisplay egl_display;
EGLContext egl_context; EGLContext egl_context;
EGLSurface egl_surface; EGLSurface egl_surface;
/* libdecor digestion */
struct libdecor *libdecor;
} Ctx; } Ctx;
static Ctx ctx = {0}; static Ctx ctx = {0};
typedef struct libdecor_plugin * (* libdecor_plugin_constructor)(struct libdecor *context); typedef struct libdecor_plugin * (* libdecor_plugin_constructor)(void);
enum libdecor_plugin_capabilities { enum libdecor_plugin_capabilities {
LIBDECOR_PLUGIN_CAPABILITY_BASE = 1 << 0, LIBDECOR_PLUGIN_CAPABILITY_BASE = 1 << 0,
@ -592,9 +537,7 @@ const struct libdecor_plugin_description libdecor_plugin_description;
** name is now available " ** name is now available "
*/ */
static void static void
init_xdg_wm_base(struct libdecor *context, init_xdg_wm_base(uint32_t id, uint32_t version);
uint32_t id,
uint32_t version);
static void static void
wlevent__wl_registry_global(void *data, struct wl_registry *registry, wlevent__wl_registry_global(void *data, struct wl_registry *registry,
@ -608,6 +551,18 @@ wlevent__wl_registry_global(void *data, struct wl_registry *registry,
ctx.wl_compositor = (struct wl_compositor*) ctx.wl_compositor = (struct wl_compositor*)
wl_registry_bind(registry, name, &wl_compositor_interface, 1); wl_registry_bind(registry, name, &wl_compositor_interface, 1);
} }
else if (!strcmp(interface, xdg_wm_base_interface.name)){
init_xdg_wm_base(name, version);
}
else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)){
const char *force_csd = getenv("LIBDECOR_FORCE_CSD");
if (!(force_csd && atoi(force_csd))){
ctx.decoration_manager = wl_registry_bind(ctx.wl_registry, name,
&zxdg_decoration_manager_v1_interface,
MIN(version,2));
}
}
} }
/* (1) Appendix A: wl_registry::global_remove */ /* (1) Appendix A: wl_registry::global_remove */
@ -620,11 +575,9 @@ const struct wl_registry_listener wl_registry_listener = {
wlevent__wl_registry_global_remove, wlevent__wl_registry_global_remove,
}; };
/* (libdecor.h) libdecor_interface::error " An error event " */ /* (libdecor.h) libdecor_interface::error " An error event " */
static void static void
libdecorevent__error(struct libdecor *libdecor, enum libdecor_error error, libdecorevent__error(enum libdecor_error error, const char *msg){}
const char *msg){}
/* (libdecor.h) libdecor_frame_interface::configure /* (libdecor.h) libdecor_frame_interface::configure
@ -697,6 +650,9 @@ libdecorevent__frame_bounds(struct libdecor_frame *frame,
void *user_data){ void *user_data){
} }
struct libdecor_frame* libdecor_decorate(struct wl_surface *wl_surface, void *user_data);
int libdecor_dispatch(int timeout);
int main(){ int main(){
/*~ NOTE: /*~ NOTE:
**~ initialize Wayland, Libdecor, & EGL **~ initialize Wayland, Libdecor, & EGL
@ -742,25 +698,16 @@ int main(){
} }
} }
/* (libdecor.h) " Create a new libdecor context for the given wl_display " */
if (ctx.wl_display != 0 && ctx.wl_compositor != 0){ if (ctx.wl_display != 0 && ctx.wl_compositor != 0){
ctx.libdecor = calloc(1, sizeof *ctx.libdecor); ctx.init_callback = wl_display_sync(ctx.wl_display);
wl_callback_add_listener(ctx.init_callback,
ctx.libdecor->ref_count = 1;
ctx.libdecor->wl_display = ctx.wl_display;
ctx.libdecor->wl_registry = wl_display_get_registry(ctx.wl_display);
wl_registry_add_listener(ctx.libdecor->wl_registry,
&scrap__registry_listener,
ctx.libdecor);
ctx.libdecor->init_callback = wl_display_sync(ctx.wl_display);
wl_callback_add_listener(ctx.libdecor->init_callback,
&init_wl_display_callback_listener, &init_wl_display_callback_listener,
ctx.libdecor); 0);
wl_list_init(&ctx.libdecor->frames); wl_list_init(&ctx.frames);
ctx.libdecor->plugin = libdecor_plugin_description.constructor(ctx.libdecor); ctx.plugin = libdecor_plugin_description.constructor();
if (ctx.libdecor->plugin == 0){ if (ctx.plugin == 0){
fprintf(stderr, "Failed to load static plugin: failed to init\n"); fprintf(stderr, "Failed to load static plugin: failed to init\n");
exit(1); exit(1);
} }
@ -769,7 +716,7 @@ int main(){
} }
int opengl_load_success = 0; int opengl_load_success = 0;
if (ctx.libdecor != 0){ if (ctx.plugin != 0){
/* (egl) eglGetDisplay /* (egl) eglGetDisplay
** " obtains the EGL display connection for the native display " ** " obtains the EGL display connection for the native display "
*/ */
@ -869,7 +816,7 @@ int main(){
if (ctx.wl_surface != 0){ if (ctx.wl_surface != 0){
/* (libdecor.h) " Decorate the given content wl_surface. " */ /* (libdecor.h) " Decorate the given content wl_surface. " */
ctx.libdecor_frame = libdecor_decorate(ctx.libdecor, ctx.wl_surface, 0); ctx.libdecor_frame = libdecor_decorate(ctx.wl_surface, 0);
} }
if (ctx.libdecor_frame != 0){ if (ctx.libdecor_frame != 0){
@ -968,7 +915,7 @@ int main(){
** the file descriptor returned by libdecor_get_fd(). If timeout is zero, this ** the file descriptor returned by libdecor_get_fd(). If timeout is zero, this
** function will never block. " ** function will never block. "
*/ */
libdecor_dispatch(ctx.libdecor, 0); libdecor_dispatch(0);
if (ctx.close_signal){ if (ctx.close_signal){
exit_loop = 1; exit_loop = 1;
@ -1060,7 +1007,7 @@ int main(){
#define LIBDECOR_FALLBACK_H #define LIBDECOR_FALLBACK_H
struct libdecor_plugin * struct libdecor_plugin *
libdecor_fallback_plugin_new(struct libdecor *context); libdecor_fallback_plugin_new(void);
#endif /* LIBDECOR_FALLBACK_H */ #endif /* LIBDECOR_FALLBACK_H */
@ -1160,15 +1107,11 @@ libdecor_frame_dismiss_popup(struct libdecor_frame *frame,
void void
libdecor_frame_toplevel_commit(struct libdecor_frame *frame); libdecor_frame_toplevel_commit(struct libdecor_frame *frame);
struct wl_display * void
libdecor_get_wl_display(struct libdecor *context); libdecor_notify_plugin_ready(void);
void void
libdecor_notify_plugin_ready(struct libdecor *context); libdecor_notify_plugin_error(enum libdecor_error error,
void
libdecor_notify_plugin_error(struct libdecor *context,
enum libdecor_error error,
const char *__restrict fmt, const char *__restrict fmt,
...); ...);
@ -1182,9 +1125,7 @@ enum libdecor_window_state
libdecor_state_get_window_state(struct libdecor_state *state); libdecor_state_get_window_state(struct libdecor_state *state);
int int
libdecor_plugin_init(struct libdecor_plugin *plugin, libdecor_plugin_init(struct libdecor_plugin *plugin, struct libdecor_plugin_interface *iface);
struct libdecor *context,
struct libdecor_plugin_interface *iface);
void void
libdecor_plugin_release(struct libdecor_plugin *plugin); libdecor_plugin_release(struct libdecor_plugin *plugin);
@ -1238,8 +1179,6 @@ struct libdecor_configuration {
struct libdecor_frame_private { struct libdecor_frame_private {
int ref_count; int ref_count;
struct libdecor *context;
struct wl_surface *wl_surface; struct wl_surface *wl_surface;
void *user_data; void *user_data;
@ -1393,8 +1332,7 @@ frame_get_window_size_for(struct libdecor_frame *frame,
int *window_height) int *window_height)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
*window_width = state->content_width; *window_width = state->content_width;
*window_height = state->content_height; *window_height = state->content_height;
@ -1416,7 +1354,7 @@ static void
frame_set_window_geometry(struct libdecor_frame *frame, frame_set_window_geometry(struct libdecor_frame *frame,
int32_t content_width, int32_t content_height) int32_t content_width, int32_t content_height)
{ {
struct libdecor_plugin *plugin = frame->priv->context->plugin; struct libdecor_plugin *plugin = ctx.plugin;
int x, y, width, height; int x, y, width, height;
int left, right, top, bottom; int left, right, top, bottom;
@ -1445,7 +1383,7 @@ libdecor_configuration_get_content_size(struct libdecor_configuration *configura
int *width, int *width,
int *height) int *height)
{ {
struct libdecor_plugin *plugin = frame->priv->context->plugin; struct libdecor_plugin *plugin = ctx.plugin;
/* get configured toplevel dimensions */ /* get configured toplevel dimensions */
if (!configuration->has_size) if (!configuration->has_size)
@ -1620,8 +1558,7 @@ xdg_toplevel_configure_bounds(void *user_data,
{ {
struct libdecor_frame *frame = user_data; struct libdecor_frame *frame = user_data;
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
int left = 0, top = 0, right = 0, bottom = 0; int left = 0, top = 0, right = 0, bottom = 0;
if (frame_has_visible_client_side_decoration(frame) && if (frame_has_visible_client_side_decoration(frame) &&
@ -1703,16 +1640,14 @@ xdg_toplevel_decoration_listener = {
void void
libdecor_frame_create_xdg_decoration(struct libdecor_frame_private *frame_priv) libdecor_frame_create_xdg_decoration(struct libdecor_frame_private *frame_priv)
{ {
if (!frame_priv->context->decoration_manager) if (!ctx.decoration_manager)
return; return;
frame_priv->toplevel_decoration = frame_priv->toplevel_decoration =
zxdg_decoration_manager_v1_get_toplevel_decoration( zxdg_decoration_manager_v1_get_toplevel_decoration(ctx.decoration_manager,
frame_priv->context->decoration_manager,
frame_priv->xdg_toplevel); frame_priv->xdg_toplevel);
zxdg_toplevel_decoration_v1_add_listener( zxdg_toplevel_decoration_v1_add_listener(frame_priv->toplevel_decoration,
frame_priv->toplevel_decoration,
&xdg_toplevel_decoration_listener, &xdg_toplevel_decoration_listener,
frame_priv); frame_priv);
} }
@ -1721,14 +1656,12 @@ static void
init_shell_surface(struct libdecor_frame *frame) init_shell_surface(struct libdecor_frame *frame)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context;
if (frame_priv->xdg_surface) if (frame_priv->xdg_surface)
return; return;
frame_priv->xdg_surface = frame_priv->xdg_surface =
xdg_wm_base_get_xdg_surface(context->xdg_wm_base, xdg_wm_base_get_xdg_surface(ctx.xdg_wm_base, frame_priv->wl_surface);
frame_priv->wl_surface);
xdg_surface_add_listener(frame_priv->xdg_surface, xdg_surface_add_listener(frame_priv->xdg_surface,
&xdg_surface_listener, &xdg_surface_listener,
frame); frame);
@ -1762,15 +1695,12 @@ init_shell_surface(struct libdecor_frame *frame)
} }
struct libdecor_frame * struct libdecor_frame *
libdecor_decorate(struct libdecor *context, libdecor_decorate(struct wl_surface *wl_surface, void *user_data){
struct wl_surface *wl_surface, struct libdecor_plugin *plugin = ctx.plugin;
void *user_data)
{
struct libdecor_plugin *plugin = context->plugin;
struct libdecor_frame *frame; struct libdecor_frame *frame;
struct libdecor_frame_private *frame_priv; struct libdecor_frame_private *frame_priv;
if (context->has_error) if (ctx.has_error)
return NULL; return NULL;
frame = plugin->priv->iface->frame_new(plugin); frame = plugin->priv->iface->frame_new(plugin);
@ -1781,7 +1711,6 @@ libdecor_decorate(struct libdecor *context,
frame->priv = frame_priv; frame->priv = frame_priv;
frame_priv->ref_count = 1; frame_priv->ref_count = 1;
frame_priv->context = context;
frame_priv->wl_surface = wl_surface; frame_priv->wl_surface = wl_surface;
frame_priv->user_data = user_data; frame_priv->user_data = user_data;
@ -1790,7 +1719,7 @@ libdecor_decorate(struct libdecor *context,
LIBDECOR_WM_CAPABILITIES_FULLSCREEN | LIBDECOR_WM_CAPABILITIES_FULLSCREEN |
LIBDECOR_WM_CAPABILITIES_MINIMIZE; LIBDECOR_WM_CAPABILITIES_MINIMIZE;
wl_list_insert(&context->frames, &frame->link); wl_list_insert(&ctx.frames, &frame->link);
libdecor_frame_set_capabilities(frame, libdecor_frame_set_capabilities(frame,
LIBDECOR_ACTION_MOVE | LIBDECOR_ACTION_MOVE |
@ -1801,7 +1730,7 @@ libdecor_decorate(struct libdecor *context,
frame_priv->visible = true; frame_priv->visible = true;
if (context->init_done) if (ctx.init_done)
init_shell_surface(frame); init_shell_surface(frame);
return frame; return frame;
@ -1822,10 +1751,9 @@ libdecor_frame_unref(struct libdecor_frame *frame)
frame_priv->ref_count--; frame_priv->ref_count--;
if (frame_priv->ref_count == 0) { if (frame_priv->ref_count == 0) {
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
if (context->decoration_manager && frame_priv->toplevel_decoration) { if (ctx.decoration_manager && frame_priv->toplevel_decoration) {
zxdg_toplevel_decoration_v1_destroy(frame_priv->toplevel_decoration); zxdg_toplevel_decoration_v1_destroy(frame_priv->toplevel_decoration);
frame_priv->toplevel_decoration = NULL; frame_priv->toplevel_decoration = NULL;
} }
@ -1865,8 +1793,7 @@ libdecor_frame_set_visibility(struct libdecor_frame *frame,
bool visible) bool visible)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
frame_priv->visible = visible; frame_priv->visible = visible;
@ -1877,7 +1804,7 @@ libdecor_frame_set_visibility(struct libdecor_frame *frame,
* *
* See also: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/17 * See also: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/17
*/ */
if (context->decoration_manager && if (ctx.decoration_manager &&
frame_priv->toplevel_decoration && frame_priv->toplevel_decoration &&
frame_priv->has_decoration_mode && frame_priv->has_decoration_mode &&
frame_priv->decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) { frame_priv->decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) {
@ -1933,7 +1860,7 @@ libdecor_frame_set_title(struct libdecor_frame *frame,
const char *title) const char *title)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor_plugin *plugin = frame_priv->context->plugin; struct libdecor_plugin *plugin = ctx.plugin;
if (!streql(frame_priv->state.title, title)) { if (!streql(frame_priv->state.title, title)) {
free(frame_priv->state.title); free(frame_priv->state.title);
@ -1973,7 +1900,7 @@ static void
notify_on_capability_change(struct libdecor_frame *frame, notify_on_capability_change(struct libdecor_frame *frame,
const enum libdecor_capabilities old_capabilities) const enum libdecor_capabilities old_capabilities)
{ {
struct libdecor_plugin *plugin = frame->priv->context->plugin; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_state *state; struct libdecor_state *state;
if (frame->priv->capabilities == old_capabilities) if (frame->priv->capabilities == old_capabilities)
@ -2043,8 +1970,7 @@ libdecor_frame_popup_grab(struct libdecor_frame *frame,
const char *seat_name) const char *seat_name)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
plugin->priv->iface->frame_popup_grab(plugin, frame, seat_name); plugin->priv->iface->frame_popup_grab(plugin, frame, seat_name);
} }
@ -2054,8 +1980,7 @@ libdecor_frame_popup_ungrab(struct libdecor_frame *frame,
const char *seat_name) const char *seat_name)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
plugin->priv->iface->frame_popup_ungrab(plugin, frame, seat_name); plugin->priv->iface->frame_popup_ungrab(plugin, frame, seat_name);
} }
@ -2096,8 +2021,7 @@ libdecor_frame_translate_coordinate(struct libdecor_frame *frame,
int *frame_y) int *frame_y)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
*frame_x = content_x; *frame_x = content_x;
*frame_y = content_y; *frame_y = content_y;
@ -2281,9 +2205,7 @@ libdecor_frame_apply_limits(struct libdecor_frame *frame,
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
if (!valid_limits(frame_priv)) { if (!valid_limits(frame_priv)) {
libdecor_notify_plugin_error( libdecor_notify_plugin_error(LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
frame_priv->context,
LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
"minimum size (%i,%i) must be smaller than maximum size (%i,%i)", "minimum size (%i,%i) must be smaller than maximum size (%i,%i)",
frame_priv->state.content_limits.min_width, frame_priv->state.content_limits.min_width,
frame_priv->state.content_limits.min_height, frame_priv->state.content_limits.min_height,
@ -2367,8 +2289,7 @@ libdecor_frame_commit(struct libdecor_frame *frame,
struct libdecor_configuration *configuration) struct libdecor_configuration *configuration)
{ {
struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_frame_private *frame_priv = frame->priv;
struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = ctx.plugin;
struct libdecor_plugin *plugin = context->plugin;
if (configuration && configuration->has_window_state) { if (configuration && configuration->has_window_state) {
frame_priv->window_state = configuration->window_state; frame_priv->window_state = configuration->window_state;
@ -2441,16 +2362,6 @@ libdecor_frame_get_xdg_toplevel(struct libdecor_frame *frame)
return frame->priv->xdg_toplevel; return frame->priv->xdg_toplevel;
} }
void
libdecor_set_handle_application_cursor(struct libdecor *context,
bool handle_cursor)
{
struct libdecor_plugin *plugin = context->plugin;
plugin->priv->iface->set_handle_application_cursor(plugin,
handle_cursor);
}
int int
libdecor_frame_get_content_width(struct libdecor_frame *frame) libdecor_frame_get_content_width(struct libdecor_frame *frame)
{ {
@ -2485,7 +2396,6 @@ libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame)
int int
libdecor_plugin_init(struct libdecor_plugin *plugin, libdecor_plugin_init(struct libdecor_plugin *plugin,
struct libdecor *context,
struct libdecor_plugin_interface *iface) struct libdecor_plugin_interface *iface)
{ {
plugin->priv = calloc(1, sizeof (struct libdecor_plugin_private)); plugin->priv = calloc(1, sizeof (struct libdecor_plugin_private));
@ -2516,9 +2426,7 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = {
}; };
static void static void
init_xdg_wm_base(struct libdecor *context, init_xdg_wm_base(uint32_t id, uint32_t version)
uint32_t id,
uint32_t version)
{ {
uint32_t desired_version = 2; uint32_t desired_version = 2;
@ -2536,78 +2444,29 @@ init_xdg_wm_base(struct libdecor *context,
desired_version = MAX(desired_version, XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION); desired_version = MAX(desired_version, XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION);
#endif #endif
context->xdg_wm_base = wl_registry_bind(context->wl_registry, ctx.xdg_wm_base = wl_registry_bind(ctx.wl_registry,
id, id,
&xdg_wm_base_interface, &xdg_wm_base_interface,
MIN(version, desired_version)); MIN(version, desired_version));
xdg_wm_base_add_listener(context->xdg_wm_base, xdg_wm_base_add_listener(ctx.xdg_wm_base,
&xdg_wm_base_listener, &xdg_wm_base_listener,
context); 0);
} }
static void static void
scrap__registry_handle_global(void *user_data, notify_error(enum libdecor_error error, const char *message)
struct wl_registry *wl_registry,
uint32_t id,
const char *interface,
uint32_t version)
{ {
struct libdecor *context = user_data; ctx.has_error = true;
libdecorevent__error(error, message);
if (!strcmp(interface, xdg_wm_base_interface.name)) { ctx.plugin->priv->iface->destroy(ctx.plugin);
init_xdg_wm_base(context, id, version);
} else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)) {
const char *force_csd = getenv("LIBDECOR_FORCE_CSD");
if (force_csd && atoi(force_csd)) {
return;
}
context->decoration_manager = wl_registry_bind(
context->wl_registry, id,
&zxdg_decoration_manager_v1_interface,
MIN(version,2));
}
} }
static void static void
scrap__registry_handle_global_remove(void *user_data, finish_init(void){
struct wl_registry *wl_registry,
uint32_t name)
{
}
const struct wl_registry_listener scrap__registry_listener = {
scrap__registry_handle_global,
scrap__registry_handle_global_remove
};
static bool
is_compositor_compatible(struct libdecor *context)
{
if (!context->xdg_wm_base)
return false;
return true;
}
static void
notify_error(struct libdecor *context,
enum libdecor_error error,
const char *message)
{
context->has_error = true;
libdecorevent__error(context, error, message);
context->plugin->priv->iface->destroy(context->plugin);
}
static void
finish_init(struct libdecor *context)
{
struct libdecor_frame *frame; struct libdecor_frame *frame;
wl_list_for_each(frame, &ctx.frames, link){
wl_list_for_each(frame, &context->frames, link)
init_shell_surface(frame); init_shell_surface(frame);
}
} }
static void static void
@ -2617,19 +2476,18 @@ init_wl_display_callback(void *user_data,
{ {
struct libdecor *context = user_data; struct libdecor *context = user_data;
context->init_done = true; ctx.init_done = true;
wl_callback_destroy(callback); wl_callback_destroy(callback);
context->init_callback = NULL; ctx.init_callback = NULL;
if (!is_compositor_compatible(context)) { if (ctx.xdg_wm_base == 0){
notify_error(context, notify_error(LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
"Compositor is missing required interfaces"); "Compositor is missing required interfaces");
} }
if (context->plugin_ready) { if (ctx.plugin_ready) {
finish_init(context); finish_init();
} }
} }
@ -2638,32 +2496,23 @@ const struct wl_callback_listener init_wl_display_callback_listener = {
}; };
int int
libdecor_dispatch(struct libdecor *context, libdecor_dispatch(int timeout)
int timeout)
{ {
struct libdecor_plugin *plugin = context->plugin; struct libdecor_plugin *plugin = ctx.plugin;
return plugin->priv->iface->dispatch(plugin, timeout); return plugin->priv->iface->dispatch(plugin, timeout);
} }
struct wl_display *
libdecor_get_wl_display(struct libdecor *context)
{
return context->wl_display;
}
void void
libdecor_notify_plugin_ready(struct libdecor *context) libdecor_notify_plugin_ready(void){
{ ctx.plugin_ready = true;
context->plugin_ready = true;
if (context->init_done) if (ctx.init_done){
finish_init(context); finish_init();
}
} }
void void
libdecor_notify_plugin_error(struct libdecor *context, libdecor_notify_plugin_error(enum libdecor_error error,
enum libdecor_error error,
const char *__restrict fmt, const char *__restrict fmt,
...) ...)
{ {
@ -2671,36 +2520,34 @@ libdecor_notify_plugin_error(struct libdecor *context,
int nbytes = 0; int nbytes = 0;
va_list argp; va_list argp;
if (context->has_error) if (ctx.has_error)
return; return;
va_start(argp, fmt); va_start(argp, fmt);
nbytes = vasprintf(&msg, fmt, argp); nbytes = vasprintf(&msg, fmt, argp);
va_end(argp); va_end(argp);
if (nbytes>0) if (nbytes > 0){
notify_error(context, error, msg); notify_error(error, msg);
}
if (msg) if (msg)
free(msg); free(msg);
} }
void void
libdecor_unref(struct libdecor *context) cleanup(void){
{ if (ctx.plugin != 0){
context->ref_count--; ctx.plugin->priv->iface->destroy(ctx.plugin);
if (context->ref_count == 0) { }
if (context->plugin) if (ctx.init_callback != 0){
context->plugin->priv->iface->destroy(context->plugin); wl_callback_destroy(ctx.init_callback);
if (context->init_callback) }
wl_callback_destroy(context->init_callback); if (ctx.xdg_wm_base != 0){
wl_registry_destroy(context->wl_registry); xdg_wm_base_destroy(ctx.xdg_wm_base);
if (context->xdg_wm_base) }
xdg_wm_base_destroy(context->xdg_wm_base); if (ctx.decoration_manager != 0){
if (context->decoration_manager) zxdg_decoration_manager_v1_destroy(ctx.decoration_manager);
zxdg_decoration_manager_v1_destroy(
context->decoration_manager);
free(context);
} }
} }
@ -2722,10 +2569,8 @@ libdecor_plugin_fallback_get_fd(struct libdecor_plugin *plugin)
{ {
struct libdecor_plugin_fallback *plugin_fallback = struct libdecor_plugin_fallback *plugin_fallback =
(struct libdecor_plugin_fallback *) plugin; (struct libdecor_plugin_fallback *) plugin;
struct wl_display *wl_display =
libdecor_get_wl_display(plugin_fallback->context);
return wl_display_get_fd(wl_display); return wl_display_get_fd(ctx.wl_display);
} }
static int static int
@ -2734,8 +2579,7 @@ libdecor_plugin_fallback_dispatch(struct libdecor_plugin *plugin,
{ {
struct libdecor_plugin_fallback *plugin_fallback = struct libdecor_plugin_fallback *plugin_fallback =
(struct libdecor_plugin_fallback *) plugin; (struct libdecor_plugin_fallback *) plugin;
struct wl_display *wl_display = struct wl_display *wl_display = ctx.wl_display;
libdecor_get_wl_display(plugin_fallback->context);
struct pollfd fds[1]; struct pollfd fds[1];
int ret; int ret;
int dispatch_count = 0; int dispatch_count = 0;
@ -2858,15 +2702,14 @@ static struct libdecor_plugin_interface fallback_plugin_iface = {
}; };
struct libdecor_plugin * struct libdecor_plugin *
libdecor_fallback_plugin_new(struct libdecor *context) libdecor_fallback_plugin_new(void){
{
struct libdecor_plugin_fallback *plugin; struct libdecor_plugin_fallback *plugin;
plugin = calloc(1, sizeof *plugin); plugin = calloc(1, sizeof *plugin);
libdecor_plugin_init(&plugin->plugin, context, &fallback_plugin_iface); libdecor_plugin_init(&plugin->plugin, &fallback_plugin_iface);
plugin->context = context; plugin->context = 0;
libdecor_notify_plugin_ready(context); libdecor_notify_plugin_ready();
return &plugin->plugin; return &plugin->plugin;
} }
@ -3750,8 +3593,7 @@ libdecor_plugin_gtk_get_fd(struct libdecor_plugin *plugin)
{ {
struct libdecor_plugin_gtk *plugin_gtk = struct libdecor_plugin_gtk *plugin_gtk =
(struct libdecor_plugin_gtk *) plugin; (struct libdecor_plugin_gtk *) plugin;
struct wl_display *wl_display = struct wl_display *wl_display = ctx.wl_display;
libdecor_get_wl_display(plugin_gtk->context);
return wl_display_get_fd(wl_display); return wl_display_get_fd(wl_display);
} }
@ -3762,8 +3604,7 @@ libdecor_plugin_gtk_dispatch(struct libdecor_plugin *plugin,
{ {
struct libdecor_plugin_gtk *plugin_gtk = struct libdecor_plugin_gtk *plugin_gtk =
(struct libdecor_plugin_gtk *) plugin; (struct libdecor_plugin_gtk *) plugin;
struct wl_display *wl_display = struct wl_display *wl_display = ctx.wl_display;
libdecor_get_wl_display(plugin_gtk->context);
struct pollfd fds[1]; struct pollfd fds[1];
int ret; int ret;
int dispatch_count = 0; int dispatch_count = 0;
@ -5104,10 +4945,7 @@ struct wl_shm_listener shm_listener = {
}; };
static void static void
shm_callback(void *user_data, shm_callback(void *user_data, struct wl_callback *callback, uint32_t time){
struct wl_callback *callback,
uint32_t time)
{
struct libdecor_plugin_gtk *plugin_gtk = user_data; struct libdecor_plugin_gtk *plugin_gtk = user_data;
struct libdecor *context = plugin_gtk->context; struct libdecor *context = plugin_gtk->context;
@ -5115,14 +4953,12 @@ shm_callback(void *user_data,
plugin_gtk->globals_callback_shm = NULL; plugin_gtk->globals_callback_shm = NULL;
if (!plugin_gtk->has_argb) { if (!plugin_gtk->has_argb) {
libdecor_notify_plugin_error( libdecor_notify_plugin_error(LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
context,
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
"Compositor is missing required shm format"); "Compositor is missing required shm format");
return; return;
} }
libdecor_notify_plugin_ready(context); libdecor_notify_plugin_ready();
} }
static const struct wl_callback_listener shm_callback_listener = { static const struct wl_callback_listener shm_callback_listener = {
@ -5135,7 +4971,7 @@ init_wl_shm(struct libdecor_plugin_gtk *plugin_gtk,
uint32_t version) uint32_t version)
{ {
struct libdecor *context = plugin_gtk->context; struct libdecor *context = plugin_gtk->context;
struct wl_display *wl_display = libdecor_get_wl_display(context); struct wl_display *wl_display = ctx.wl_display;
plugin_gtk->wl_shm = plugin_gtk->wl_shm =
wl_registry_bind(plugin_gtk->wl_registry, wl_registry_bind(plugin_gtk->wl_registry,
@ -5966,9 +5802,7 @@ init_wl_seat(struct libdecor_plugin_gtk *plugin_gtk,
struct seat *seat; struct seat *seat;
if (version < 3) { if (version < 3) {
libdecor_notify_plugin_error( libdecor_notify_plugin_error(LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
plugin_gtk->context,
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
"%s version 3 required but only version %i is available\n", "%s version 3 required but only version %i is available\n",
wl_seat_interface.name, wl_seat_interface.name,
version); version);
@ -6055,9 +5889,7 @@ init_wl_output(struct libdecor_plugin_gtk *plugin_gtk,
struct output *output; struct output *output;
if (version < 2) { if (version < 2) {
libdecor_notify_plugin_error( libdecor_notify_plugin_error(LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
plugin_gtk->context,
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
"%s version 2 required but only version %i is available\n", "%s version 2 required but only version %i is available\n",
wl_output_interface.name, wl_output_interface.name,
version); version);
@ -6185,8 +6017,7 @@ static const struct wl_callback_listener globals_callback_listener = {
}; };
static struct libdecor_plugin * static struct libdecor_plugin *
libdecor_plugin_new(struct libdecor *context) libdecor_plugin_new(void){
{
struct libdecor_plugin_gtk *plugin_gtk; struct libdecor_plugin_gtk *plugin_gtk;
struct wl_display *wl_display; struct wl_display *wl_display;
@ -6197,10 +6028,8 @@ libdecor_plugin_new(struct libdecor *context)
#endif #endif
plugin_gtk = calloc(1, sizeof *plugin_gtk); plugin_gtk = calloc(1, sizeof *plugin_gtk);
libdecor_plugin_init(&plugin_gtk->plugin, libdecor_plugin_init(&plugin_gtk->plugin, &gtk_plugin_iface);
context, plugin_gtk->context = 0;
&gtk_plugin_iface);
plugin_gtk->context = context;
wl_list_init(&plugin_gtk->visible_frame_list); wl_list_init(&plugin_gtk->visible_frame_list);
wl_list_init(&plugin_gtk->seat_list); wl_list_init(&plugin_gtk->seat_list);
@ -6215,7 +6044,7 @@ libdecor_plugin_new(struct libdecor *context)
plugin_gtk->color_scheme_setting = libdecor_get_color_scheme(); plugin_gtk->color_scheme_setting = libdecor_get_color_scheme();
wl_display = libdecor_get_wl_display(context); wl_display = ctx.wl_display;
plugin_gtk->wl_registry = wl_display_get_registry(wl_display); plugin_gtk->wl_registry = wl_display_get_registry(wl_display);
wl_registry_add_listener(plugin_gtk->wl_registry, wl_registry_add_listener(plugin_gtk->wl_registry,
&registry_listener, &registry_listener,