forked from 12to11/12to11
Implement support for XDG window decoration
* 12to11.c (XLMain): Initialize window decoration. * Imakefile (SRCS, OBJS): Add decoration.c and decoration.o. * README: Document support for zdg_decoration_manager_v1. * compositor.h: Update prototypes. * xdg_toplevel.c (XdgDecoration, DecorationMode): New types. (enum _DecorationMode): New structures. (struct _XdgToplevel): New fields `decor' and `decoration'. (struct _XdgDecoration): New struct. (SendDecorationConfigure): New function. (Commit): Apply decoration should it be dirty. (HandleResourceDestroy): Detach decoration object. (Destroy): Post error if decoration object would be orphaned. (DestroyDecoration, SetMode, UnsetMode) (HandleDecorationResourceDestroy, XLXdgToplevelGetDecoration): New functions.
This commit is contained in:
parent
e09fe5f5b5
commit
a5f2c99939
5 changed files with 239 additions and 8 deletions
1
12to11.c
1
12to11.c
|
@ -123,6 +123,7 @@ XLMain (int argc, char **argv)
|
||||||
XLInitPrimarySelection ();
|
XLInitPrimarySelection ();
|
||||||
XLInitExplicitSynchronization ();
|
XLInitExplicitSynchronization ();
|
||||||
XLInitWpViewporter ();
|
XLInitWpViewporter ();
|
||||||
|
XLInitDecoration ();
|
||||||
/* This has to come after the rest of the initialization. */
|
/* This has to come after the rest of the initialization. */
|
||||||
DetermineServerTime ();
|
DetermineServerTime ();
|
||||||
XLRunCompositor ();
|
XLRunCompositor ();
|
||||||
|
|
|
@ -21,7 +21,7 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \
|
||||||
dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c \
|
dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c \
|
||||||
icon_surface.c primary_selection.c renderer.c \
|
icon_surface.c primary_selection.c renderer.c \
|
||||||
picture_renderer.c explicit_synchronization.c transform.c \
|
picture_renderer.c explicit_synchronization.c transform.c \
|
||||||
wp_viewporter.c
|
wp_viewporter.c decoration.c
|
||||||
|
|
||||||
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
||||||
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
|
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
|
||||||
|
@ -30,7 +30,7 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
||||||
dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o \
|
dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o \
|
||||||
icon_surface.o primary_selection.o renderer.o \
|
icon_surface.o primary_selection.o renderer.o \
|
||||||
picture_renderer.o explicit_synchronization.o transform.o \
|
picture_renderer.o explicit_synchronization.o transform.o \
|
||||||
wp_viewporter.o
|
wp_viewporter.o decoration.o
|
||||||
|
|
||||||
GENHEADERS = transfer_atoms.h
|
GENHEADERS = transfer_atoms.h
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ ScannerTarget(xdg-shell)
|
||||||
ScannerTarget(primary-selection-unstable-v1)
|
ScannerTarget(primary-selection-unstable-v1)
|
||||||
ScannerTarget(linux-explicit-synchronization-unstable-v1)
|
ScannerTarget(linux-explicit-synchronization-unstable-v1)
|
||||||
ScannerTarget(viewporter)
|
ScannerTarget(viewporter)
|
||||||
|
ScannerTarget(xdg-decoration-unstable-v1)
|
||||||
|
|
||||||
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
|
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
|
||||||
$(OBJS): $(GENHEADERS)
|
$(OBJS): $(GENHEADERS)
|
||||||
|
|
1
README
1
README
|
@ -65,6 +65,7 @@ complete degree:
|
||||||
'zwp_linux_dmabuf_v1', version: 4
|
'zwp_linux_dmabuf_v1', version: 4
|
||||||
'zwp_primary_selection_device_manager_v1', version: 1
|
'zwp_primary_selection_device_manager_v1', version: 1
|
||||||
'wp_viewporter', version: 1
|
'wp_viewporter', version: 1
|
||||||
|
'zxdg_decoration_manager_v1', version: 1
|
||||||
|
|
||||||
When built with EGL, the following Wayland protocol is also supported:
|
When built with EGL, the following Wayland protocol is also supported:
|
||||||
|
|
||||||
|
|
|
@ -1140,6 +1140,8 @@ extern void XLGetXdgToplevel (struct wl_client *, struct wl_resource *,
|
||||||
extern Bool XLHandleXEventForXdgToplevels (XEvent *);
|
extern Bool XLHandleXEventForXdgToplevels (XEvent *);
|
||||||
extern Bool XLIsXdgToplevel (Window);
|
extern Bool XLIsXdgToplevel (Window);
|
||||||
extern void XLInitXdgToplevels (void);
|
extern void XLInitXdgToplevels (void);
|
||||||
|
extern void XLXdgToplevelGetDecoration (XdgRoleImplementation *,
|
||||||
|
struct wl_resource *, uint32_t);
|
||||||
|
|
||||||
/* Defined in xdg_popup.c. */
|
/* Defined in xdg_popup.c. */
|
||||||
|
|
||||||
|
@ -1426,6 +1428,10 @@ extern void XLInitWpViewporter (void);
|
||||||
extern void XLWpViewportReportBadSize (ViewportExt *);
|
extern void XLWpViewportReportBadSize (ViewportExt *);
|
||||||
extern void XLWpViewportReportOutOfBuffer (ViewportExt *);
|
extern void XLWpViewportReportOutOfBuffer (ViewportExt *);
|
||||||
|
|
||||||
|
/* Defined in decoration.c. */
|
||||||
|
|
||||||
|
extern void XLInitDecoration (void);
|
||||||
|
|
||||||
/* Utility functions that don't belong in a specific file. */
|
/* Utility functions that don't belong in a specific file. */
|
||||||
|
|
||||||
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
|
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
|
||||||
|
|
226
xdg_toplevel.c
226
xdg_toplevel.c
|
@ -25,15 +25,18 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
#include "xdg-shell.h"
|
#include "xdg-shell.h"
|
||||||
|
#include "xdg-decoration-unstable-v1.h"
|
||||||
|
|
||||||
#define ToplevelFromRoleImpl(impl) ((XdgToplevel *) (impl))
|
#define ToplevelFromRoleImpl(impl) ((XdgToplevel *) (impl))
|
||||||
|
|
||||||
typedef struct _XdgToplevel XdgToplevel;
|
typedef struct _XdgToplevel XdgToplevel;
|
||||||
|
typedef struct _XdgDecoration XdgDecoration;
|
||||||
typedef struct _ToplevelState ToplevelState;
|
typedef struct _ToplevelState ToplevelState;
|
||||||
typedef struct _PropMotifWmHints PropMotifWmHints;
|
typedef struct _PropMotifWmHints PropMotifWmHints;
|
||||||
typedef struct _XdgUnmapCallback XdgUnmapCallback;
|
typedef struct _XdgUnmapCallback XdgUnmapCallback;
|
||||||
|
|
||||||
typedef enum _How How;
|
typedef enum _How How;
|
||||||
|
typedef enum _DecorationMode DecorationMode;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -45,6 +48,7 @@ enum
|
||||||
StatePendingResize = (1 << 5),
|
StatePendingResize = (1 << 5),
|
||||||
StatePendingConfigureSize = (1 << 6),
|
StatePendingConfigureSize = (1 << 6),
|
||||||
StatePendingConfigureStates = (1 << 7),
|
StatePendingConfigureStates = (1 << 7),
|
||||||
|
StateDecorationModeDirty = (1 << 8),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -68,6 +72,12 @@ enum _How
|
||||||
Toggle = 2,
|
Toggle = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum _DecorationMode
|
||||||
|
{
|
||||||
|
DecorationModeClient = 0,
|
||||||
|
DecorationModeWindowManager = 1,
|
||||||
|
};
|
||||||
|
|
||||||
struct _XdgUnmapCallback
|
struct _XdgUnmapCallback
|
||||||
{
|
{
|
||||||
/* Function run when the toplevel is unmapped or detached. */
|
/* Function run when the toplevel is unmapped or detached. */
|
||||||
|
@ -218,6 +228,21 @@ struct _XdgToplevel
|
||||||
/* The width and height used by that timer if
|
/* The width and height used by that timer if
|
||||||
StatePendingConfigureSize is set. */
|
StatePendingConfigureSize is set. */
|
||||||
int configure_width, configure_height;
|
int configure_width, configure_height;
|
||||||
|
|
||||||
|
/* Any decoration resource associated with this toplevel. */
|
||||||
|
XdgDecoration *decoration;
|
||||||
|
|
||||||
|
/* The decoration mode. */
|
||||||
|
DecorationMode decor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _XdgDecoration
|
||||||
|
{
|
||||||
|
/* The associated resource. */
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
|
/* The associated toplevel. */
|
||||||
|
XdgToplevel *toplevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* iconv context used to convert between UTF-8 and Latin-1. */
|
/* iconv context used to convert between UTF-8 and Latin-1. */
|
||||||
|
@ -361,6 +386,39 @@ SendConfigure (XdgToplevel *toplevel, unsigned int width,
|
||||||
toplevel->conf_serial = serial;
|
toplevel->conf_serial = serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendDecorationConfigure (XdgToplevel *toplevel)
|
||||||
|
{
|
||||||
|
uint32_t serial;
|
||||||
|
|
||||||
|
/* This should never be NULL when called! */
|
||||||
|
XLAssert (toplevel->decoration != NULL);
|
||||||
|
|
||||||
|
serial = wl_display_next_serial (compositor.wl_display);
|
||||||
|
|
||||||
|
#define ServerSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
|
||||||
|
#define ClientSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE
|
||||||
|
|
||||||
|
if (toplevel->decor == DecorationModeClient)
|
||||||
|
zxdg_toplevel_decoration_v1_send_configure (toplevel->decoration->resource,
|
||||||
|
ClientSide);
|
||||||
|
else
|
||||||
|
zxdg_toplevel_decoration_v1_send_configure (toplevel->decoration->resource,
|
||||||
|
ServerSide);
|
||||||
|
|
||||||
|
#undef ServerSide
|
||||||
|
#undef ClientSide
|
||||||
|
|
||||||
|
XLXdgRoleSendConfigure (toplevel->role, serial);
|
||||||
|
|
||||||
|
toplevel->conf_reply = True;
|
||||||
|
toplevel->conf_serial = serial;
|
||||||
|
|
||||||
|
/* This means that the decoration should be reapplied upon the next
|
||||||
|
commit. */
|
||||||
|
toplevel->state |= StateDecorationModeDirty;
|
||||||
|
}
|
||||||
|
|
||||||
/* Forward declaration. */
|
/* Forward declaration. */
|
||||||
|
|
||||||
static void SendStates (XdgToplevel *);
|
static void SendStates (XdgToplevel *);
|
||||||
|
@ -1094,6 +1152,20 @@ Commit (Role *role, Surface *surface, XdgRoleImplementation *impl)
|
||||||
if (!(toplevel->state & StateIsMapped))
|
if (!(toplevel->state & StateIsMapped))
|
||||||
Map (toplevel);
|
Map (toplevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!toplevel->conf_reply
|
||||||
|
&& toplevel->state & StateDecorationModeDirty)
|
||||||
|
{
|
||||||
|
/* The decoration is dirty and all configure events were
|
||||||
|
aknowledged; apply the new decoration. */
|
||||||
|
|
||||||
|
if (toplevel->decor == DecorationModeWindowManager)
|
||||||
|
SetDecorated (toplevel, True);
|
||||||
|
else
|
||||||
|
SetDecorated (toplevel, False);
|
||||||
|
|
||||||
|
toplevel->state &= ~StateDecorationModeDirty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1459,12 +1531,15 @@ HandleResourceDestroy (struct wl_resource *resource)
|
||||||
toplevel = wl_resource_get_user_data (resource);
|
toplevel = wl_resource_get_user_data (resource);
|
||||||
toplevel->resource = NULL;
|
toplevel->resource = NULL;
|
||||||
|
|
||||||
|
/* If there is an attached decoration resource, detach it. */
|
||||||
|
if (toplevel->decoration)
|
||||||
|
toplevel->decoration->toplevel = NULL;
|
||||||
|
|
||||||
DestroyBacking (toplevel);
|
DestroyBacking (toplevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
Destroy (struct wl_client *client,
|
Destroy (struct wl_client *client, struct wl_resource *resource)
|
||||||
struct wl_resource *resource)
|
|
||||||
{
|
{
|
||||||
XdgToplevel *toplevel;
|
XdgToplevel *toplevel;
|
||||||
|
|
||||||
|
@ -1474,6 +1549,14 @@ Destroy (struct wl_client *client,
|
||||||
XLXdgRoleDetachImplementation (toplevel->role,
|
XLXdgRoleDetachImplementation (toplevel->role,
|
||||||
&toplevel->impl);
|
&toplevel->impl);
|
||||||
|
|
||||||
|
/* If the resource still has a decoration applied, then this is an
|
||||||
|
error. */
|
||||||
|
if (toplevel->decoration)
|
||||||
|
wl_resource_post_error (resource,
|
||||||
|
ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ORPHANED,
|
||||||
|
"the attached decoration would be orphaned by"
|
||||||
|
" the destruction of this resource");
|
||||||
|
else
|
||||||
wl_resource_destroy (resource);
|
wl_resource_destroy (resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2129,3 +2212,142 @@ XLIsXdgToplevel (Window window)
|
||||||
{
|
{
|
||||||
return XLLookUpXdgToplevel (window) != NULL;
|
return XLLookUpXdgToplevel (window) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
DestroyDecoration (struct wl_client *client, struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
wl_resource_destroy (resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SetMode (struct wl_client *client, struct wl_resource *resource,
|
||||||
|
uint32_t mode)
|
||||||
|
{
|
||||||
|
XdgDecoration *decoration;
|
||||||
|
|
||||||
|
decoration = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
if (!decoration->toplevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:
|
||||||
|
decoration->toplevel->decor = DecorationModeClient;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:
|
||||||
|
decoration->toplevel->decor = DecorationModeWindowManager;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wl_resource_post_error (resource, WL_DISPLAY_ERROR_IMPLEMENTATION,
|
||||||
|
"trying to set bogus decoration mode %u",
|
||||||
|
mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendDecorationConfigure (decoration->toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
UnsetMode (struct wl_client *client, struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
XdgDecoration *decoration;
|
||||||
|
|
||||||
|
decoration = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
if (!decoration->toplevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Default to using window manager decorations. */
|
||||||
|
decoration->toplevel->decor = DecorationModeWindowManager;
|
||||||
|
SendDecorationConfigure (decoration->toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zxdg_toplevel_decoration_v1_interface decoration_impl =
|
||||||
|
{
|
||||||
|
.destroy = DestroyDecoration,
|
||||||
|
.set_mode = SetMode,
|
||||||
|
.unset_mode = UnsetMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
HandleDecorationResourceDestroy (struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
XdgDecoration *decoration;
|
||||||
|
|
||||||
|
decoration = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
/* Detach the decoration from the toplevel if the latter still
|
||||||
|
exists. */
|
||||||
|
if (decoration->toplevel)
|
||||||
|
decoration->toplevel->decoration = NULL;
|
||||||
|
|
||||||
|
/* Free the decoration. */
|
||||||
|
XLFree (decoration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XLXdgToplevelGetDecoration (XdgRoleImplementation *impl,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
uint32_t id)
|
||||||
|
{
|
||||||
|
XdgToplevel *toplevel;
|
||||||
|
XdgDecoration *decoration;
|
||||||
|
|
||||||
|
toplevel = ToplevelFromRoleImpl (impl);
|
||||||
|
|
||||||
|
/* See if a decoration object is already attached. */
|
||||||
|
if (toplevel->decoration)
|
||||||
|
{
|
||||||
|
#define AlreadyConstructed ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ALREADY_CONSTRUCTED
|
||||||
|
wl_resource_post_error (resource, AlreadyConstructed,
|
||||||
|
"the given toplevel already has a decoration"
|
||||||
|
"object.");
|
||||||
|
#undef AlreadyConstructed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if a buffer is already attached. */
|
||||||
|
if (toplevel->role->surface
|
||||||
|
&& toplevel->role->surface->current_state.buffer)
|
||||||
|
{
|
||||||
|
#define UnconfiguredBuffer ZXDG_TOPLEVEL_DECORATION_V1_ERROR_UNCONFIGURED_BUFFER
|
||||||
|
wl_resource_post_error (resource, UnconfiguredBuffer,
|
||||||
|
"given toplevel already has attached buffer");
|
||||||
|
#undef UnconfiguredBuffer
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoration = XLSafeMalloc (sizeof *decoration);
|
||||||
|
|
||||||
|
if (!decoration)
|
||||||
|
{
|
||||||
|
wl_resource_post_no_memory (resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (decoration, 0, sizeof *decoration);
|
||||||
|
decoration->resource
|
||||||
|
= wl_resource_create (wl_resource_get_client (resource),
|
||||||
|
&zxdg_toplevel_decoration_v1_interface,
|
||||||
|
wl_resource_get_version (resource), id);
|
||||||
|
|
||||||
|
if (!decoration->resource)
|
||||||
|
{
|
||||||
|
XLFree (decoration);
|
||||||
|
wl_resource_post_no_memory (resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now attach the decoration to the toplevel and vice versa. */
|
||||||
|
toplevel->decoration = decoration;
|
||||||
|
decoration->toplevel = toplevel;
|
||||||
|
|
||||||
|
/* And set the implementation. */
|
||||||
|
wl_resource_set_implementation (decoration->resource, &decoration_impl,
|
||||||
|
decoration, HandleDecorationResourceDestroy);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue