<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSPrincipalClass</key>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>CFBundleShortVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleLongVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleGetInfoString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSHumanReadableCopyright</key>
- <string>6.11</string>
+ <string>6.12</string>
</dict>
</plist>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSPrincipalClass</key>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>CFBundleShortVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleLongVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleGetInfoString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSHumanReadableCopyright</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSMainNibFile</key>
<string>SaverRunner</string>
<key>CFBundleIconFile</key>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSPrincipalClass</key>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>CFBundleShortVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleLongVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleGetInfoString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSHumanReadableCopyright</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSMainNibFile</key>
<string>Updater</string>
<key>CFBundleIconFile</key>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSPrincipalClass</key>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>CFBundleShortVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleLongVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleGetInfoString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSHumanReadableCopyright</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSMainNibFile</key>
<string>SaverRunner</string>
</dict>
\b0 by Jamie Zawinski\
and many others\
\
-version 6.11\
-01-Jul-2025\
+version 6.12\
+07-Jul-2025\
\
{\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
\pard\pardeftab720
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>CFBundleShortVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleLongVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleGetInfoString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSHumanReadableCopyright</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSMainNibFile</key>
<string>iSaverRunner</string>
<key>CFBundleDisplayName</key>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>CFBundleShortVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleLongVersionString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleGetInfoString</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>NSHumanReadableCopyright</key>
- <string>6.11</string>
+ <string>6.12</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleIcons</key>
perl pkg-config gettext intltool libx11 libxext libxi libxt libxft
libxinerama libxrandr libxxf86vm libgl libglu libgle libgtk-3
- libgdk-pixbuf2.0 libjpeg libxml2 libpam libsystemd elogind
+ libgdk-pixbuf2.0 libjpeg libxml2 libpam libsystemd elogind libwayland
BSD systems might need gmake instead of make.
Version History
===============================================================================
+6.12 * X11: DPMS works on Wayland.
+ * X11: Fading uses GL now which should be more performant.
+
6.11 * X11: Now supports Wayland (blanking only, not locking).
* X11: More reliable and timely DPMS activation.
* X11: Dead keys work in password input.
* X11: Fixed a couple of minor Y2038 bugs.
+
6.10 * New hacks, `dumpsterfire', `hopffibration', `platonicfolding' and
`klondike'.
* Rewrote the VT100 emulator for 'apple2' and 'phosphor'.
SETUID_HACKS
SETUID_AUTH
PROG_SETCAP
+WAYLAND_GTK_OBJS
+WAYLAND_DPMS_OBJS
WAYLAND_IDLE_OBJS
+WAYLAND_DPY_OBJS
WAYLAND_GEN
WAYLAND_DATADIR
WAYLAND_LIBS
XINERAMA_LIBS
XDPMS_LIBS
GLE_LIBS
+GFX_GL_OBJS
+GL_CFLAGS
GL_LIBS
PTY_LIBS
HACK_LIBS
pkgs=''
ok="yes"
- pkg_check_version wayland-server 1.0
- pkg_check_version wayland-client 1.0
- pkg_check_version wayland-scanner 1.0
+ pkg_check_version wayland-server 1.8
+ pkg_check_version wayland-client 1.8
+ #pkg_check_version wayland-scanner 1.8
ac_wayland_version_string="$vers"
have_wayland="$ok"
wayland_pkgs="$pkgs"
WAYLAND_DATADIR=""
WAYLAND_GEN=""
+ WAYLAND_DPY_OBJS=""
WAYLAND_IDLE_OBJS=""
+ WAYLAND_DPMS_OBJS=""
+ WAYLAND_GTK_OBJS=""
if test "$have_wayland" = yes; then
WAYLAND_DATADIR=`$pkg_config --variable=prefix wayland-client`
WAYLAND_DATADIR="$WAYLAND_DATADIR/share"
WAYLAND_GEN='$(WAYLAND_GEN_HDRS) $(WAYLAND_GEN_SRCS)'
+ WAYLAND_DPY_OBJS='$(WAYLAND_DPY_OBJS_1)'
WAYLAND_IDLE_OBJS='$(WAYLAND_IDLE_OBJS_1)'
+ WAYLAND_DPMS_OBJS='$(WAYLAND_DPMS_OBJS_1)'
+ WAYLAND_GTK_OBJS='$(WAYLAND_GTK_OBJS_1)'
fi
if test "$have_wayland" = yes; then
printf "%s\n" "#define HAVE_GL 1" >>confdefs.h
+ GL_CFLAGS="-DUSE_GL"
+ GFX_GL_OBJS='$(GFX_GL_OBJS_1)'
+
# OpenGL 1.0 didn't have multiple textures.
ac_save_CPPFLAGS="$CPPFLAGS"
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+# Since there is no .in file to force its creation in a different build dir
+test -d driver/wayland-protocols || mkdir driver/wayland-protocols
+
###############################################################################
#
# Print some warnings at the end.
-# configure.in --- xscreensaver, Copyright © 1997-2025 Jamie Zawinski.
+# configure.ac --- xscreensaver, Copyright © 1997-2025 Jamie Zawinski.
#
-# Note: upgrading past 2.69_5 breaks the world, mostly the po/ shitshow.
AC_PREREQ([2.69])
-
-# If you accidentally upgraded autoconf, re-install the 2019-08-23 version:
-#
-# git clone --single-branch https://github.com/macports/macports-ports.git
-# cd macports-ports/
-# git checkout 1d802b48a7b00b6c154e971119a2a309550c79c2
-# cd devel/autoconf
-# sudo port install
-# port installed autoconf
-
AC_INIT
AC_CONFIG_SRCDIR([driver/subprocs.c])
AC_CONFIG_HEADERS([config.h])
pkgs=''
ok="yes"
- pkg_check_version wayland-server 1.0
- pkg_check_version wayland-client 1.0
- pkg_check_version wayland-scanner 1.0
+ pkg_check_version wayland-server 1.8
+ pkg_check_version wayland-client 1.8
+ #pkg_check_version wayland-scanner 1.8
ac_wayland_version_string="$vers"
have_wayland="$ok"
wayland_pkgs="$pkgs"
WAYLAND_DATADIR=""
WAYLAND_GEN=""
+ WAYLAND_DPY_OBJS=""
WAYLAND_IDLE_OBJS=""
+ WAYLAND_DPMS_OBJS=""
+ WAYLAND_GTK_OBJS=""
if test "$have_wayland" = yes; then
WAYLAND_DATADIR=`$pkg_config --variable=prefix wayland-client`
WAYLAND_DATADIR="$WAYLAND_DATADIR/share"
WAYLAND_GEN='$(WAYLAND_GEN_HDRS) $(WAYLAND_GEN_SRCS)'
+ WAYLAND_DPY_OBJS='$(WAYLAND_DPY_OBJS_1)'
WAYLAND_IDLE_OBJS='$(WAYLAND_IDLE_OBJS_1)'
+ WAYLAND_DPMS_OBJS='$(WAYLAND_DPMS_OBJS_1)'
+ WAYLAND_GTK_OBJS='$(WAYLAND_GTK_OBJS_1)'
fi
if test "$have_wayland" = yes; then
if test "$have_gl" = yes; then
AC_DEFINE(HAVE_GL)
+ GL_CFLAGS="-DUSE_GL"
+ GFX_GL_OBJS='$(GFX_GL_OBJS_1)'
# OpenGL 1.0 didn't have multiple textures.
AC_CHECK_X_LIB($gl_lib_1, glBindTexture, [AC_DEFINE(HAVE_GLBINDTEXTURE)],
AC_SUBST(HACK_LIBS)
AC_SUBST(PTY_LIBS)
AC_SUBST(GL_LIBS)
+AC_SUBST(GL_CFLAGS)
+AC_SUBST(GFX_GL_OBJS)
AC_SUBST(GLE_LIBS)
AC_SUBST(XDPMS_LIBS)
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(WAYLAND_LIBS)
AC_SUBST(WAYLAND_DATADIR)
AC_SUBST(WAYLAND_GEN)
+AC_SUBST(WAYLAND_DPY_OBJS)
AC_SUBST(WAYLAND_IDLE_OBJS)
+AC_SUBST(WAYLAND_DPMS_OBJS)
+AC_SUBST(WAYLAND_GTK_OBJS)
AC_SUBST(PROG_SETCAP)
AC_SUBST(SETUID_AUTH)
AC_SUBST(SETUID_HACKS)
driver/XScreenSaver.ad])
AC_OUTPUT
+# Since there is no .in file to force its creation in a different build dir
+test -d driver/wayland-protocols || mkdir driver/wayland-protocols
+
+
###############################################################################
#
# Print some warnings at the end.
WAYLAND_DATADIR = @WAYLAND_DATADIR@
WAYLAND_GEN = @WAYLAND_GEN@
-WAYLAND_GEN_XML = xdg-shell.xml \
- ext-idle-notify-v1.xml \
- idle.xml
-WAYLAND_GEN_HDRS = xdg-shell-v1-client-protocol.h \
- ext-idle-notify-v1-client-protocol.h \
- idle-client-protocol.h
-WAYLAND_GEN_SRCS = xdg-shell-v1-protocol.c \
- ext-idle-notify-v1-protocol.c \
- idle-protocol.c
+WAYLAND_PROTO = wayland-protocols
+WAYLAND_GEN_XML = $(WAYLAND_PROTO)/xdg-shell.xml \
+ $(WAYLAND_PROTO)/ext-idle-notify-v1.xml \
+ $(WAYLAND_PROTO)/idle.xml \
+ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1.xml \
+ $(WAYLAND_PROTO)/dpms.xml
+
+WAYLAND_GEN_HDRS = $(WAYLAND_PROTO)/xdg-shell-v1-client-protocol.h \
+ $(WAYLAND_PROTO)/ext-idle-notify-v1-client-protocol.h \
+ $(WAYLAND_PROTO)/idle-client-protocol.h \
+ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-client-protocol.h \
+ $(WAYLAND_PROTO)/dpms-client-protocol.h
+
+WAYLAND_GEN_SRCS = $(WAYLAND_PROTO)/xdg-shell-v1-protocol.c \
+ $(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.c \
+ $(WAYLAND_PROTO)/idle-protocol.c \
+ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.c \
+ $(WAYLAND_PROTO)/dpms-protocol.c
+
+WAYLAND_DPY_OBJS = @WAYLAND_DPY_OBJS@
+WAYLAND_DPY_SRCS = wayland-dpy.c
+WAYLAND_DPY_OBJS_1 = wayland-dpy.o
WAYLAND_IDLE_OBJS = @WAYLAND_IDLE_OBJS@
WAYLAND_IDLE_SRCS = wayland-idle.c
WAYLAND_IDLE_OBJS_1 = wayland-idle.o \
- ext-idle-notify-v1-protocol.o \
- idle-protocol.o
+ $(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.o \
+ $(WAYLAND_PROTO)/idle-protocol.o
+
+WAYLAND_DPMS_OBJS = @WAYLAND_DPMS_OBJS@
+WAYLAND_DPMS_SRCS = wayland-dpms.c
+WAYLAND_DPMS_OBJS_1 = wayland-dpms.o \
+ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.o \
+ $(WAYLAND_PROTO)/dpms-protocol.o
+
+WAYLAND_GTK_OBJS = @WAYLAND_GTK_OBJS@
+WAYLAND_GTK_SRCS = wayland-dpms.c
+WAYLAND_GTK_OBJS_1 = $(WAYLAND_DPY_OBJS) $(WAYLAND_IDLE_OBJS) \
+ $(WAYLAND_DPMS_OBJS)
HACKDIR = @HACKDIR@
HACK_CONF_DIR = @HACK_CONF_DIR@
DAEMON_DEFS = -DDEFAULT_PATH_PREFIX='"@HACKDIR@"' -DAD_DIR='"$(AD_DIR)"'
DAEMON_SRCS = xscreensaver.c blurb.c atoms.c clientmsg.c xinput.c prefs.c \
- $(WAYLAND_IDLE_SRCS)
+ $(WAYLAND_DPY_SRCS) $(WAYLAND_IDLE_SRCS)
DAEMON_OBJS = xscreensaver.o blurb.o atoms.o clientmsg.o xinput.o prefs.o \
- $(UTILS_BIN)/xmu.o $(WAYLAND_IDLE_OBJS)
+ $(UTILS_BIN)/xmu.o $(WAYLAND_DPY_OBJS) $(WAYLAND_IDLE_OBJS)
DAEMON_LIBS = $(LIBS_PRE) $(XINPUT_LIBS) -lX11 $(WAYLAND_LIBS) $(LIBS_POST)
-GFX_DEFS = -DLOCALEDIR=\"$(localedir)\"
+GFX_DEFS = @GL_CFLAGS@ -DLOCALEDIR=\"$(localedir)\"
+SUBP_DEFS = @GL_CFLAGS@
GFX_SRCS = xscreensaver-gfx.c screens.c windows.c subprocs.c \
- exec.c prefsw.c dpms.c fade.c exts.c atomswm.c
+ exec.c prefsw.c dpms.c fade.c exts.c atomswm.c \
+ $(WAYLAND_DPY_SRCS) $(WAYLAND_DPMS_SRCS)
GFX_OBJS = xscreensaver-gfx.o screens.o windows.o subprocs.o \
exec.o prefsw.o dpms.o fade.o exts.o atomswm.o \
prefs.o blurb.o atoms.o clientmsg.o xinput.o \
+ $(WAYLAND_DPY_OBJS) $(WAYLAND_DPMS_OBJS) \
$(UTILS_BIN)/xmu.o \
$(UTILS_BIN)/yarandom.o \
$(UTILS_BIN)/resources.o \
$(UTILS_BIN)/xft.o \
$(UTILS_BIN)/utf8wc.o \
$(UTILS_BIN)/xshm.o \
- $(UTILS_BIN)/aligned_malloc.o
+ $(UTILS_BIN)/aligned_malloc.o \
+ $(GFX_GL_OBJS)
+GFX_GL_OBJS = @GFX_GL_OBJS@
+GFX_GL_OBJS_1 = $(UTILS_BIN)/visual-gl.o $(UTILS_BIN)/pow2.o
GFX_LIBS = $(LIBS_PRE) $(XFT_LIBS) $(XDPMS_LIBS) $(XINERAMA_LIBS) \
- @SAVER_LIBS@ -lXt -lX11 -lXext -lXi $(LIBS_POST) $(INTL_LIBS)
+ @SAVER_LIBS@ -lXt -lX11 -lXext -lXi @GL_LIBS@ \
+ $(WAYLAND_LIBS) $(LIBS_POST) $(INTL_LIBS)
PWENT_SRCS = passwd-pwent.c
PWENT_OBJS = passwd-pwent.o
GTK_OBJS = demo-Gtk.o demo-Gtk-conf.o demo-Gtk-resources.o \
blurb.o exec.o prefs.o prefsw.o dpms.o remote.o screens.o \
clientmsg.o atoms.o \
- $(WAYLAND_IDLE_OBJS) \
+ $(WAYLAND_GTK_OBJS) \
$(UTILS_BIN)/xmu.o \
$(UTILS_BIN)/resources.o \
$(UTILS_BIN)/visual.o \
HDRS = XScreenSaver_ad.h XScreenSaver_Xm_ad.h \
xscreensaver.h prefs.h remote.h exec.h \
demo-Gtk-conf.h auth.h types.h blurb.h atoms.h clientmsg.h \
- screens.h xinput.h fade.h wayland-idle.h \
+ screens.h xinput.h fade.h wayland-dpy.h wayland-dpyI.h \
+ wayland-idle.h wayland-dpms.h \
$(WAYLAND_GEN_HDRS)
MENA = xscreensaver.man xscreensaver-settings.man \
xscreensaver-command.man
rm -f $(install_prefix)$(HACK_CONF_DIR)/README
-# Generate .c and .h files for various Wayland APIs.
-#
-xdg-shell.xml: $(WAYLAND_DATADIR)/wayland-protocols/stable/xdg-shell/xdg-shell.xml
- cp -p $< $@
-xdg-shell-v1-client-protocol.h: xdg-shell.xml
- wayland-scanner client-header < $< > $@
-xdg-shell-v1-protocol.c: xdg-shell.xml
- wayland-scanner private-code < $< > $@
-
-ext-idle-notify-v1.xml: \
- $(WAYLAND_DATADIR)/wayland-protocols/staging/ext-idle-notify/ext-idle-notify-v1.xml
- cp -p $< $@
-ext-idle-notify-v1-client-protocol.h: ext-idle-notify-v1.xml
- wayland-scanner client-header < $< > $@
-ext-idle-notify-v1-protocol.c: ext-idle-notify-v1.xml
- wayland-scanner private-code < $< > $@
-
-# org_kde_kwin_idle -- I don't know why this isn't in WAYLAND_DATADIR
-#idle.xml: $(WAYLAND_DATADIR)/wayland-protocols/stable/ext-idle-notify/idle.xml
-# cp -p $< $@
-idle-client-protocol.h: idle.xml
- wayland-scanner client-header < $< > $@
-idle-protocol.c: idle.xml
- wayland-scanner private-code < $< > $@
-
-
##############################################################################
#
# Clean and dependencies
$(UTILS_BIN)/xshm.o: $(UTILS_SRC)/xshm.c
$(UTILS_BIN)/aligned_malloc.o: $(UTILS_SRC)/aligned_malloc.c
$(UTILS_BIN)/screenshot.o: $(UTILS_SRC)/screenshot.c
+$(UTILS_BIN)/visual-gl.o: $(UTILS_SRC)/visual-gl.c
+$(UTILS_BIN)/pow2.o: $(UTILS_SRC)/pow2.c
UTIL_OBJS = $(UTILS_BIN)/overlay.o \
$(UTILS_BIN)/font-retry.o \
$(UTILS_BIN)/xshm.o \
$(UTILS_BIN)/aligned_malloc.o \
- $(UTILS_BIN)/screenshot.o
+ $(UTILS_BIN)/screenshot.o \
+ $(UTILS_BIN)/visual-gl.o \
+ $(UTILS_BIN)/pow2.o
$(UTIL_OBJS):
$(MAKE2CC) -C $(UTILS_BIN) $(@F)
.c.o:
$(CC) -c $(CC_ALL) $<
-# # subprocs takes an extra -D option.
-# subprocs.o: subprocs.c
-# $(CC) -c $(CC_ALL) $(SUBP_DEFS) $<
+# subprocs takes an extra -D option.
+subprocs.o: subprocs.c
+ $(CC) -c $(CC_ALL) $(SUBP_DEFS) $<
+fade.o: fade.c
+ $(CC) -c $(CC_ALL) $(SUBP_DEFS) $<
# xscreensaver takes an extra -D option.
xscreensaver.o: xscreensaver.c
@INTLTOOL_SERVICE_RULE@
+##############################################################################
+#
+# Wayland protocols
+#
+##############################################################################
+
+# Generate .c and .h files for various Wayland APIs.
+#
+# Since this stuff never changes and is small, the tar file includes the
+# generated files in $(srcdir), so that client builds probably won't ever
+# need to run "wayland-scanner". But we print a warning if the system's
+# XML files exist and differ from our own.
+
+# "xdg-shell" isn't used yet but probably will be.
+#
+$(srcdir)/$(WAYLAND_PROTO)/xdg-shell.xml::
+ @\
+ F=$(WAYLAND_DATADIR)/wayland-protocols/stable/xdg-shell/xdg-shell.xml ; \
+ if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \
+ echo "WARNING: $$F and $@ differ" >&2 ; \
+ fi
+$(srcdir)/$(WAYLAND_PROTO)/xdg-shell-v1-client-protocol.h: \
+$(srcdir)/$(WAYLAND_PROTO)/xdg-shell.xml
+ wayland-scanner client-header < $< > $@
+$(srcdir)/$(WAYLAND_PROTO)/xdg-shell-v1-protocol.c: \
+$(srcdir)/$(WAYLAND_PROTO)/xdg-shell.xml
+ wayland-scanner private-code < $< > $@
+$(WAYLAND_PROTO)/xdg-shell-v1-protocol.o: \
+$(srcdir)/$(WAYLAND_PROTO)/xdg-shell-v1-protocol.c
+ $(CC) -c $(CC_ALL) $< -o $@
+
+# "idle-notify-v1" for wayland-idle.c
+#
+$(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1.xml::
+ @\
+ F=$(WAYLAND_DATADIR)/wayland-protocols/staging/ext-idle-notify/ext-idle-notify-v1.xml ; \
+ if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \
+ echo "WARNING: $$F and $@ differ" >&2 ; \
+ fi
+$(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1-client-protocol.h: \
+$(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1.xml
+ wayland-scanner client-header < $< > $@
+$(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.c: \
+$(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1.xml
+ wayland-scanner private-code < $< > $@
+$(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.o: \
+$(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.c
+ $(CC) -c $(CC_ALL) $< -o $@
+
+# "kde-idle" for wayland-idle.c
+# "apt install plasma-wayland-protocols" to get the system XML file.
+#
+$(srcdir)/$(WAYLAND_PROTO)/idle.xml::
+ @\
+ F="$(WAYLAND_DATADIR)/plasma-wayland-protocols/idle.xml" ; \
+ if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \
+ echo "WARNING: $$F and $@ differ" >&2 ; \
+ fi
+$(srcdir)/$(WAYLAND_PROTO)/idle-client-protocol.h: \
+$(srcdir)/$(WAYLAND_PROTO)/idle.xml
+ wayland-scanner client-header < $< > $@
+$(srcdir)/$(WAYLAND_PROTO)/idle-protocol.c: \
+$(srcdir)/$(WAYLAND_PROTO)/idle.xml
+ wayland-scanner private-code < $< > $@
+$(WAYLAND_PROTO)/idle-protocol.o: \
+$(srcdir)/$(WAYLAND_PROTO)/idle-protocol.c
+ $(CC) -c $(CC_ALL) $< -o $@
+
+# "wlr-output-power-management" for wayland-dpms.c
+# I don't know what to install to get this into $(WAYLAND_DATADIR)
+#
+$(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1.xml::
+ @\
+ F="$(WAYLAND_DATADIR)/wayland-protocols/staging/wlr-output-power-management-unstable-v1.xml" ; \
+ if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \
+ echo "WARNING: $$F and $@ differ" >&2 ; \
+ fi
+$(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-client-protocol.h: \
+$(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1.xml
+ wayland-scanner client-header < $< > $@
+$(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.c: \
+$(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1.xml
+ wayland-scanner private-code < $< > $@
+$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.o: \
+$(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.c
+ $(CC) -c $(CC_ALL) $< -o $@
+
+# "kde-dpms" for wayland-idle.c
+# "apt install plasma-wayland-protocols" to get the system XML file.
+#
+$(srcdir)/$(WAYLAND_PROTO)/dpms.xml::
+ @\
+ F="$(WAYLAND_DATADIR)/plasma-wayland-protocols/dpms.xml" ; \
+ if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \
+ echo "WARNING: $$F and $@ differ" >&2 ; \
+ fi
+$(srcdir)/$(WAYLAND_PROTO)/dpms-client-protocol.h: \
+$(srcdir)/$(WAYLAND_PROTO)/dpms.xml
+ wayland-scanner client-header < $< > $@
+$(srcdir)/$(WAYLAND_PROTO)/dpms-protocol.c: \
+$(srcdir)/$(WAYLAND_PROTO)/dpms.xml
+ wayland-scanner private-code < $< > $@
+$(WAYLAND_PROTO)/dpms-protocol.o: \
+$(srcdir)/$(WAYLAND_PROTO)/dpms-protocol.c
+ $(CC) -c $(CC_ALL) $< -o $@
+
+
+
##############################################################################
#
# Debugging utilities, not built by default
$(UTILS_BIN)/visual.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/usleep.o \
$(UTILS_BIN)/logo.o $(UTILS_BIN)/minixpm.o $(UTILS_BIN)/xshm.o \
$(UTILS_BIN)/xmu.o $(UTILS_BIN)/aligned_malloc.o \
- $(UTILS_BIN)/screenshot.o
+ $(UTILS_BIN)/screenshot.o $(GFX_GL_OBJS)
test-fade: $(TEST_FADE_OBJS)
$(CC) $(LDFLAGS) -o $@ $(TEST_FADE_OBJS) $(GFX_LIBS)
fade.o: $(srcdir)/clientmsg.h
fade.o: ../config.h
fade.o: $(srcdir)/fade.h
+fade.o: $(UTILS_SRC)/pow2.h
+fade.o: $(UTILS_SRC)/screenshot.h
fade.o: $(UTILS_SRC)/usleep.h
fade.o: $(UTILS_SRC)/visual.h
fade.o: $(UTILS_SRC)/xmu.h
test-yarandom.o: $(srcdir)/blurb.h
test-yarandom.o: ../config.h
test-yarandom.o: $(UTILS_SRC)/yarandom.h
+wayland-dpms.o: $(srcdir)/blurb.h
+wayland-dpms.o: ../config.h
+wayland-dpms.o: $(srcdir)/types.h
+wayland-dpms.o: $(srcdir)/wayland-dpms.h
+wayland-dpms.o: $(srcdir)/wayland-dpyI.h
+wayland-dpms.o: $(srcdir)/wayland-dpy.h
+wayland-dpms.o: $(srcdir)/wayland-protocols/dpms-client-protocol.h
+wayland-dpms.o: $(srcdir)/wayland-protocols/wlr-output-power-management-unstable-v1-client-protocol.h
+wayland-dpy.o: $(srcdir)/blurb.h
+wayland-dpy.o: $(srcdir)/blurb.h
+wayland-dpy.o: ../config.h
+wayland-dpy.o: ../config.h
+wayland-dpy.o: $(srcdir)/wayland-dpyI.h
+wayland-dpy.o: $(srcdir)/wayland-dpyI.h
+wayland-dpy.o: $(srcdir)/wayland-dpy.h
+wayland-dpy.o: $(srcdir)/wayland-dpy.h
wayland-idle.o: $(srcdir)/blurb.h
wayland-idle.o: ../config.h
-wayland-idle.o: $(srcdir)/ext-idle-notify-v1-client-protocol.h
-wayland-idle.o: $(srcdir)/idle-client-protocol.h
+wayland-idle.o: $(srcdir)/wayland-dpyI.h
+wayland-idle.o: $(srcdir)/wayland-dpy.h
wayland-idle.o: $(srcdir)/wayland-idle.h
+wayland-idle.o: $(srcdir)/wayland-protocols/ext-idle-notify-v1-client-protocol.h
+wayland-idle.o: $(srcdir)/wayland-protocols/idle-client-protocol.h
windows.o: $(srcdir)/atoms.h
windows.o: $(srcdir)/blurb.h
windows.o: ../config.h
! a screen saver and locker for the X window system
! by Jamie Zawinski
!
-! version 6.11
-! 01-Jul-2025
+! version 6.12
+! 07-Jul-2025
!
! See "man xscreensaver" for more info. The latest version is always
! available at https://www.jwz.org/xscreensaver/
#include "blurb.h"
#include "xscreensaver-intl.h"
#include "version.h"
+
#include "types.h"
#include "resources.h" /* for parse_time() */
#include "remote.h" /* for xscreensaver_command() */
#include "screenshot.h"
#include "xmu.h"
+#include "demo-Gtk-conf.h"
+
#ifdef HAVE_WAYLAND
# include "wayland-idle.h"
+# include "wayland-dpms.h"
#endif
-#include "demo-Gtk-conf.h"
-
/* from exec.c */
extern void exec_command (const char *shell, const char *command, int nice);
Pixmap screenshot;
Visual *gl_visual;
+# ifdef HAVE_WAYLAND
+ wayland_dpy *wayland_dpy;
+ wayland_idle *wayland_idle;
+ wayland_dpms *wayland_dpms;
+# endif
+
conf_data *cdata; /* private data for per-hack configuration */
Bool debug_p; /* whether to print diagnostics */
Bool flushing_p; /* flag for breaking recursion loops */
Bool saving_p; /* flag for breaking recursion loops */
Bool dpms_supported_p; /* Whether XDPMS is available */
+ Bool dpms_partial_p; /* Whether DPMS only supports "Off" */
Bool grabbing_supported_p; /* Whether "Grab Desktop" and "Fade" work */
char *desired_preview_cmd; /* subprocess we intend to run */
if (changed)
{
if (s->dpy)
- sync_server_dpms_settings (s->dpy, p);
+ sync_server_dpms_settings_1 (s->dpy, p);
demo_write_init_file (s, p);
/* Tell the xscreensaver daemon to wake up and reload the init file,
(double) ((LOWER) + 59) / (60 * 1000))
MINUTES (standby, timeout, dpms_standby_spinbutton);
MINUTES (suspend, standby, dpms_suspend_spinbutton);
- MINUTES (off, standby, dpms_off_spinbutton);
- MINUTES (off, suspend, dpms_off_spinbutton);
+ if (!s->dpms_partial_p)
+ {
+ /* Since standby and suspend are not editable, ignore them. */
+ MINUTES (off, standby, dpms_off_spinbutton);
+ MINUTES (off, suspend, dpms_off_spinbutton);
+ }
# undef MINUTES
return GDK_EVENT_PROPAGATE;
saver_preferences *p = &s->prefs;
Bool can_lock_p = TRUE;
+ Bool dpms_full_p;
# ifdef NO_LOCKING
can_lock_p = FALSE;
# define TOGGLE_ACTIVE(NAME,ACTIVEP) \
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (win->NAME), (ACTIVEP))
- TOGGLE_ACTIVE (lock_button, p->lock_p);
- TOGGLE_ACTIVE (dpms_button, p->dpms_enabled_p && s->dpms_supported_p);
- TOGGLE_ACTIVE (dpms_quickoff_button, (p->dpms_quickoff_p &&
- s->dpms_supported_p));
- TOGGLE_ACTIVE (grab_desk_button, (p->grab_desktop_p &&
- s->grabbing_supported_p));
- TOGGLE_ACTIVE (grab_video_button, p->grab_video_p);
- TOGGLE_ACTIVE (grab_image_button, p->random_image_p);
- TOGGLE_ACTIVE (fade_button, p->fade_p && s->grabbing_supported_p);
- TOGGLE_ACTIVE (unfade_button, p->unfade_p && s->grabbing_supported_p);
+ TOGGLE_ACTIVE (lock_button, p->lock_p);
+ TOGGLE_ACTIVE (dpms_button, p->dpms_enabled_p);
+ TOGGLE_ACTIVE (dpms_quickoff_button, p->dpms_quickoff_p);
+ TOGGLE_ACTIVE (grab_desk_button, p->grab_desktop_p);
+ TOGGLE_ACTIVE (grab_video_button, p->grab_video_p);
+ TOGGLE_ACTIVE (grab_image_button, p->random_image_p);
+ TOGGLE_ACTIVE (fade_button, p->fade_p);
+ TOGGLE_ACTIVE (unfade_button, p->unfade_p);
switch (p->tmode)
{
/* DPMS
*/
+ dpms_full_p = s->dpms_supported_p && !s->dpms_partial_p;
SENSITIZE (dpms_button, s->dpms_supported_p);
- SENSITIZE (dpms_standby_label, s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_standby_mlabel, s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_standby_spinbutton,s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_suspend_label, s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_suspend_mlabel, s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_suspend_spinbutton,s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_off_label, s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_off_mlabel, s->dpms_supported_p && p->dpms_enabled_p);
- SENSITIZE (dpms_off_spinbutton, s->dpms_supported_p && p->dpms_enabled_p);
+ SENSITIZE (dpms_standby_label, p->dpms_enabled_p && dpms_full_p);
+ SENSITIZE (dpms_standby_mlabel, p->dpms_enabled_p && dpms_full_p);
+ SENSITIZE (dpms_standby_spinbutton,p->dpms_enabled_p && dpms_full_p);
+ SENSITIZE (dpms_suspend_label, p->dpms_enabled_p && dpms_full_p);
+ SENSITIZE (dpms_suspend_mlabel, p->dpms_enabled_p && dpms_full_p);
+ SENSITIZE (dpms_suspend_spinbutton,p->dpms_enabled_p && dpms_full_p);
+ SENSITIZE (dpms_off_label, p->dpms_enabled_p && s->dpms_supported_p);
+ SENSITIZE (dpms_off_mlabel, p->dpms_enabled_p && s->dpms_supported_p);
+ SENSITIZE (dpms_off_spinbutton, p->dpms_enabled_p && s->dpms_supported_p);
SENSITIZE (dpms_quickoff_button, s->dpms_supported_p);
/* Fading
if (s->backend != X11_BACKEND)
{
# ifdef HAVE_WAYLAND
- /* Connect to the Wayland server in the same way that the XScreenSaver
- daemon will, and if we are in a state where the daemon won't work
- properly, pop up a dialog box explaining why.
+ /* If we are in a state where the daemon won't work properly, pop up a
+ dialog box explaining why.
*/
- const char *wayland_err = 0;
- wayland_state *wayland = wayland_idle_init (NULL, NULL, &wayland_err);
-
- if (s->debug_p && wayland_err)
- fprintf (stderr, "%s: wayland: %s\n", blurb(), wayland_err);
-
- if (wayland) /* Connected to Wayland, have necessary extensions. */
+ if (s->wayland_idle)
+ ; /* Connected to Wayland and can detect activity. */
+ else if (s->wayland_dpy)
{
- wayland_idle_free (wayland);
+ /* Connected but the necessary extensions are missing. */
+ warning_dialog (s->window, _("Warning"),
+ _("Wayland error: idle detection is impossible. "
+ "The XScreenSaver daemon will not work.\n"));
}
- else if (wayland_err && !strcmp (wayland_err, "connection failed"))
+ else if (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET"))
{
- if (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET"))
- {
- warning_dialog (s->window, _("Warning"),
- _("Unable to connect to the Wayland server. "
- "The XScreenSaver daemon will not work.\n"));
- }
- /* Otherwise, presumably running under real X11. */
+ /* Running under Wayland, but unable to connect. */
+ warning_dialog (s->window, _("Warning"),
+ _("Unable to connect to the Wayland server. "
+ "The XScreenSaver daemon will not work.\n"));
}
- else if (wayland_err)
+ else
{
- /* Connected but the necessary extensions are missing. */
- char msg [1024];
- sprintf (msg,
- _("Wayland error:\n\n"
- "%.100s\n\n"
- "The XScreenSaver daemon will not work.\n"),
- wayland_err);
- warning_dialog (s->window, _("Warning"), msg);
+ if (verbose_p)
+ fprintf (stderr,
+ "%s: wayland: connection failed; assuming real X11\n",
+ blurb());
}
# else /* !HAVE_WAYLAND */
if (s->debug_p)
# endif
}
+# ifdef HAVE_WAYLAND
+ /* Connect to the Wayland server in the same way that xscreensaver
+ and xscreensaver-gfx will, to see if blanking and DPMS will work.
+ */
+ s->wayland_dpy = wayland_dpy_connect();
+ s->wayland_idle = wayland_idle_init (s->wayland_dpy, NULL, NULL);
+ s->wayland_dpms = wayland_dpms_init (s->wayland_dpy);
+# endif /* HAVE_WAYLAND */
+
s->multi_screen_p = multi_screen_p (s->dpy);
/* Let's see if the server supports DPMS.
*/
s->dpms_supported_p = FALSE;
+ s->dpms_partial_p = TRUE;
+
+# ifdef HAVE_WAYLAND
+ if (s->wayland_dpms)
+ {
+ s->dpms_supported_p = TRUE;
+ s->dpms_partial_p = TRUE;
+ }
+ else if (s->wayland_dpy)
+ {
+ s->dpms_supported_p = FALSE;
+ }
+ else
+# endif /* HAVE_WAYLAND */
+
# ifdef HAVE_DPMS_EXTENSION
{
int op = 0, event = 0, error = 0;
{
const char *prog = "grim";
char *desk = getenv ("XDG_CURRENT_DESKTOP");
-fprintf(stderr,"##A %s\n", desk);
if (desk &&
(strcasestr (desk, "GNOME") ||
- strcasestr (desk, "KDE")))
+ strcasestr (desk, "KDE") ||
+ strcasestr (desk, "plasma")))
{
-fprintf(stderr,"##B %s\n", desk);
s->grabbing_supported_p = False;
if (s->debug_p)
fprintf (stderr,
}
else if (! on_path_p (prog))
{
-fprintf(stderr,"##C %s\n", desk);
s->grabbing_supported_p = False;
if (s->debug_p)
fprintf (stderr,
Status s = 0;
KeySym keysym2 = 0;
int size2 = Xutf8LookupString (ws->ic, (XKeyPressedEvent *) event,
- decoded2, sizeof(decoded2)-1
- , &keysym2, &s);
+ decoded2, sizeof(decoded2)-1,
+ &keysym2, &s);
decoded2[size2] = 0;
switch (s) {
- case XLookupChars: /* Set 'c2' to a UTF8 string */
+ case XLookupChars: /* Set 'decoded2' to a UTF8 string */
if (*decoded2)
{
strcpy ((char *) decoded, (char *) decoded2);
}
break;
case XLookupNone: /* No input yet */
- case XBufferOverflow: /* 'c2' was too small */
+ case XBufferOverflow: /* 'decoded2' was too small */
break;
default:
abort();
#include "xscreensaver.h"
+#ifdef HAVE_WAYLAND
+# include "wayland-dpms.h"
+#endif
+
/* Disable the X11 built-in screen saver. This is not directly related
to DPMS, but it does need to be prevented from fighting with us.
*/
#ifndef HAVE_DPMS_EXTENSION /* almost the whole file */
void
-sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
+sync_server_dpms_settings (saver_info *si)
+{
+ sync_server_dpms_settings_1 (si->dpy, &si->prefs);
+}
+
+void
+sync_server_dpms_settings_1 (Display *dpy, struct saver_preferences *p)
{
disable_builtin_saver (dpy);
if (p->verbose_p)
fprintf (stderr, "%s: DPMS not supported at compile time\n", blurb());
}
-Bool monitor_powered_on_p (Display *dpy)
+Bool monitor_powered_on_p (saver_info *si)
{
+# ifdef HAVE_WAYLAND
+ if (si->wayland_dpms)
+ return wayland_monitor_powered_on_p (si->wayland_dpms);
+# endif
if (verbose_p > 1)
fprintf (stderr,
"%s: DPMS disabled at compile time, assuming monitor on\n",
void monitor_power_on (saver_info *si, Bool on_p)
{
+# ifdef HAVE_WAYLAND
+ if (si->wayland_dpms)
+ wayland_monitor_power_on (si->wayland_dpms, on_p);
+ else
+# endif
if (verbose_p > 1)
fprintf (stderr,
"%s: DPMS disabled at compile time, not turning monitor %s\n",
void
-sync_server_dpms_settings (Display *dpy, struct saver_preferences *p)
+sync_server_dpms_settings (saver_info *si)
+{
+# ifdef HAVE_WAYLAND /* The XDPMS extension is definitely not available */
+ if (si->wayland_dpy)
+ {
+ disable_builtin_saver (si->dpy);
+ return;
+ }
+# endif /* HAVE_WAYLAND */
+
+ /* If the monitor is currently powered off, defer any changes until we are
+ next called while it is powered on. Making changes to the DPMS settings
+ can have the side-effect of powering the monitor back on.
+ */
+ if (! monitor_powered_on_p (si))
+ {
+ if (verbose_p > 1)
+ fprintf (stderr, "%s: DPMS: monitor off, skipping sync\n", blurb());
+ return;
+ }
+
+ sync_server_dpms_settings_1 (si->dpy, &si->prefs);
+}
+
+void
+sync_server_dpms_settings_1 (Display *dpy, struct saver_preferences *p)
{
int event = 0, error = 0;
BOOL o_enabled = False;
Bool verbose_p = p->verbose_p;
static Bool warned_p = False;
- /* If the monitor is currently powered off, defer any changes until we are
- next called while it is powered on. Making changes to the DPMS settings
- can have the side-effect of powering the monitor back on.
- */
- if (! monitor_powered_on_p (dpy))
- {
- if (verbose_p > 1)
- fprintf (stderr, "%s: DPMS: monitor off, skipping sync\n", blurb());
- return;
- }
-
changed_p = disable_builtin_saver (dpy);
if (dpms_quickoff_p && !off_secs)
}
Bool
-monitor_powered_on_p (Display *dpy)
+monitor_powered_on_p (saver_info *si)
{
Bool result;
int event_number, error_number;
BOOL onoff = False;
CARD16 state;
- if (!DPMSQueryExtension(dpy, &event_number, &error_number))
+# ifdef HAVE_WAYLAND
+
+ if (si->wayland_dpms)
+ return wayland_monitor_powered_on_p (si->wayland_dpms);
+ else if (si->wayland_dpy)
+ return True; /* Wayland server does not support DPMS */
+
+# endif /* HAVE_WAYLAND */
+
+ if (!DPMSQueryExtension(si->dpy, &event_number, &error_number))
{
/* Server doesn't know -- assume the monitor is on. */
if (verbose_p > 1)
result = True;
}
- else if (!DPMSCapable(dpy))
+ else if (!DPMSCapable(si->dpy))
{
/* Server says the monitor doesn't do power management -- so it's on. */
if (verbose_p > 1)
else
{
- DPMSInfo(dpy, &state, &onoff);
+ DPMSInfo(si->dpy, &state, &onoff);
if (!onoff)
{
/* Server says DPMS is disabled -- so the monitor is on. */
monitor_power_on (saver_info *si, Bool on_p)
{
Bool verbose_p = si->prefs.verbose_p;
- if ((!!on_p) != monitor_powered_on_p (si->dpy))
+ if ((!!on_p) != monitor_powered_on_p (si))
{
XErrorHandler old_handler;
int event_number, error_number;
static Bool warned_p = False;
+
+# ifdef HAVE_WAYLAND
+ if (si->wayland_dpms)
+ {
+ wayland_monitor_power_on (si->wayland_dpms, on_p);
+ return;
+ }
+ else if (si->wayland_dpy)
+ {
+ if (verbose_p > 1 || (verbose_p && !warned_p))
+ fprintf (stderr,
+ "%s: wayland: unable to power %s monitor\n",
+ blurb(), (on_p ? "on" : "off"));
+ warned_p = True;
+ return;
+ }
+# endif /* HAVE_WAYLAND */
+
if (!DPMSQueryExtension(si->dpy, &event_number, &error_number) ||
!DPMSCapable(si->dpy))
{
if (verbose_p > 1 && error_handler_hit_p)
fprintf (stderr, "%s: DPMSForceLevel got an X11 error\n", blurb());
- if ((!!on_p) != monitor_powered_on_p (si->dpy)) /* double-check */
+ if ((!!on_p) != monitor_powered_on_p (si)) /* double-check */
fprintf (stderr,
"%s: DPMSForceLevel(dpy, %s) did not change monitor power state\n",
blurb(),
/* Force the server DPMS state to be what the wall clock says it should be.
*/
void
-brute_force_dpms (Display *dpy, struct saver_preferences *p,
- time_t activity_time)
+brute_force_dpms (saver_info *si, time_t activity_time)
{
+ Display *dpy = si->dpy;
+ saver_preferences *p = &si->prefs;
XErrorHandler old_handler;
int event_number, error_number;
BOOL onoff = False;
CARD16 state;
CARD16 target;
time_t age = time ((time_t *) 0) - activity_time;
+ Bool enabled_p = (p->dpms_enabled_p && p->mode != DONT_BLANK);
if (activity_time == 0) /* Auth dialog is visible */
target = DPMSModeOn;
else if (p->mode == BLANK_ONLY && p->dpms_quickoff_p)
target = DPMSModeOff;
- else if (p->dpms_off && age >= (p->dpms_off / 1000))
+ else if (enabled_p && p->dpms_off && age >= (p->dpms_off / 1000))
target = DPMSModeOff;
- else if (p->dpms_suspend && age >= (p->dpms_suspend / 1000))
+ else if (enabled_p && p->dpms_suspend && age >= (p->dpms_suspend / 1000))
target = DPMSModeSuspend;
- else if (p->dpms_standby && age >= (p->dpms_standby / 1000))
+ else if (enabled_p && p->dpms_standby && age >= (p->dpms_standby / 1000))
target = DPMSModeStandby;
else
/* We have no opinion about the desired DPMS state, so if it is off,
leave it off. It may have been powered down manually with xset. */
return;
+# ifdef HAVE_WAYLAND
+ {
+ Bool have = monitor_powered_on_p (si);
+ Bool want = (target == DPMSModeOn);
+
+ if (have == want)
+ ;
+ else if (si->wayland_dpms)
+ {
+ wayland_monitor_power_on (si->wayland_dpms, want);
+ if (p->verbose_p)
+ fprintf (stderr, "%s: powered %s monitor\n", blurb(),
+ (want ? "on" : "off"));
+ return;
+ }
+ else if (si->wayland_dpy)
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: wayland: unable to power %s monitor\n",
+ blurb(), (want ? "on" : "off"));
+ return;
+ }
+ }
+# endif /* HAVE_WAYLAND */
+
if (!DPMSQueryExtension (dpy, &event_number, &error_number) ||
!DPMSCapable (dpy))
return;
+++ /dev/null
-/* Generated by wayland-scanner 1.23.1 */
-
-#ifndef EXT_IDLE_NOTIFY_V1_CLIENT_PROTOCOL_H
-#define EXT_IDLE_NOTIFY_V1_CLIENT_PROTOCOL_H
-
-#include <stdint.h>
-#include <stddef.h>
-#include "wayland-client.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @page page_ext_idle_notify_v1 The ext_idle_notify_v1 protocol
- * @section page_ifaces_ext_idle_notify_v1 Interfaces
- * - @subpage page_iface_ext_idle_notifier_v1 - idle notification manager
- * - @subpage page_iface_ext_idle_notification_v1 - idle notification
- * @section page_copyright_ext_idle_notify_v1 Copyright
- * <pre>
- *
- * Copyright © 2015 Martin Gräßlin
- * Copyright © 2022 Simon Ser
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * </pre>
- */
-struct ext_idle_notification_v1;
-struct ext_idle_notifier_v1;
-struct wl_seat;
-
-#ifndef EXT_IDLE_NOTIFIER_V1_INTERFACE
-#define EXT_IDLE_NOTIFIER_V1_INTERFACE
-/**
- * @page page_iface_ext_idle_notifier_v1 ext_idle_notifier_v1
- * @section page_iface_ext_idle_notifier_v1_desc Description
- *
- * This interface allows clients to monitor user idle status.
- *
- * After binding to this global, clients can create ext_idle_notification_v1
- * objects to get notified when the user is idle for a given amount of time.
- * @section page_iface_ext_idle_notifier_v1_api API
- * See @ref iface_ext_idle_notifier_v1.
- */
-/**
- * @defgroup iface_ext_idle_notifier_v1 The ext_idle_notifier_v1 interface
- *
- * This interface allows clients to monitor user idle status.
- *
- * After binding to this global, clients can create ext_idle_notification_v1
- * objects to get notified when the user is idle for a given amount of time.
- */
-extern const struct wl_interface ext_idle_notifier_v1_interface;
-#endif
-#ifndef EXT_IDLE_NOTIFICATION_V1_INTERFACE
-#define EXT_IDLE_NOTIFICATION_V1_INTERFACE
-/**
- * @page page_iface_ext_idle_notification_v1 ext_idle_notification_v1
- * @section page_iface_ext_idle_notification_v1_desc Description
- *
- * This interface is used by the compositor to send idle notification events
- * to clients.
- *
- * Initially the notification object is not idle. The notification object
- * becomes idle when no user activity has happened for at least the timeout
- * duration, starting from the creation of the notification object. User
- * activity may include input events or a presence sensor, but is
- * compositor-specific.
- *
- * How this notification responds to idle inhibitors depends on how
- * it was constructed. If constructed from the
- * get_idle_notification request, then if an idle inhibitor is
- * active (e.g. another client has created a zwp_idle_inhibitor_v1
- * on a visible surface), the compositor must not make the
- * notification object idle. However, if constructed from the
- * get_input_idle_notification request, then idle inhibitors are
- * ignored, and only input from the user, e.g. from a keyboard or
- * mouse, counts as activity.
- *
- * When the notification object becomes idle, an idled event is sent. When
- * user activity starts again, the notification object stops being idle,
- * a resumed event is sent and the timeout is restarted.
- * @section page_iface_ext_idle_notification_v1_api API
- * See @ref iface_ext_idle_notification_v1.
- */
-/**
- * @defgroup iface_ext_idle_notification_v1 The ext_idle_notification_v1 interface
- *
- * This interface is used by the compositor to send idle notification events
- * to clients.
- *
- * Initially the notification object is not idle. The notification object
- * becomes idle when no user activity has happened for at least the timeout
- * duration, starting from the creation of the notification object. User
- * activity may include input events or a presence sensor, but is
- * compositor-specific.
- *
- * How this notification responds to idle inhibitors depends on how
- * it was constructed. If constructed from the
- * get_idle_notification request, then if an idle inhibitor is
- * active (e.g. another client has created a zwp_idle_inhibitor_v1
- * on a visible surface), the compositor must not make the
- * notification object idle. However, if constructed from the
- * get_input_idle_notification request, then idle inhibitors are
- * ignored, and only input from the user, e.g. from a keyboard or
- * mouse, counts as activity.
- *
- * When the notification object becomes idle, an idled event is sent. When
- * user activity starts again, the notification object stops being idle,
- * a resumed event is sent and the timeout is restarted.
- */
-extern const struct wl_interface ext_idle_notification_v1_interface;
-#endif
-
-#define EXT_IDLE_NOTIFIER_V1_DESTROY 0
-#define EXT_IDLE_NOTIFIER_V1_GET_IDLE_NOTIFICATION 1
-#define EXT_IDLE_NOTIFIER_V1_GET_INPUT_IDLE_NOTIFICATION 2
-
-
-/**
- * @ingroup iface_ext_idle_notifier_v1
- */
-#define EXT_IDLE_NOTIFIER_V1_DESTROY_SINCE_VERSION 1
-/**
- * @ingroup iface_ext_idle_notifier_v1
- */
-#define EXT_IDLE_NOTIFIER_V1_GET_IDLE_NOTIFICATION_SINCE_VERSION 1
-/**
- * @ingroup iface_ext_idle_notifier_v1
- */
-#define EXT_IDLE_NOTIFIER_V1_GET_INPUT_IDLE_NOTIFICATION_SINCE_VERSION 2
-
-/** @ingroup iface_ext_idle_notifier_v1 */
-static inline void
-ext_idle_notifier_v1_set_user_data(struct ext_idle_notifier_v1 *ext_idle_notifier_v1, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) ext_idle_notifier_v1, user_data);
-}
-
-/** @ingroup iface_ext_idle_notifier_v1 */
-static inline void *
-ext_idle_notifier_v1_get_user_data(struct ext_idle_notifier_v1 *ext_idle_notifier_v1)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) ext_idle_notifier_v1);
-}
-
-static inline uint32_t
-ext_idle_notifier_v1_get_version(struct ext_idle_notifier_v1 *ext_idle_notifier_v1)
-{
- return wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1);
-}
-
-/**
- * @ingroup iface_ext_idle_notifier_v1
- *
- * Destroy the manager object. All objects created via this interface
- * remain valid.
- */
-static inline void
-ext_idle_notifier_v1_destroy(struct ext_idle_notifier_v1 *ext_idle_notifier_v1)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notifier_v1,
- EXT_IDLE_NOTIFIER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1), WL_MARSHAL_FLAG_DESTROY);
-}
-
-/**
- * @ingroup iface_ext_idle_notifier_v1
- *
- * Create a new idle notification object.
- *
- * The notification object has a minimum timeout duration and is tied to a
- * seat. The client will be notified if the seat is inactive for at least
- * the provided timeout. See ext_idle_notification_v1 for more details.
- *
- * A zero timeout is valid and means the client wants to be notified as
- * soon as possible when the seat is inactive.
- */
-static inline struct ext_idle_notification_v1 *
-ext_idle_notifier_v1_get_idle_notification(struct ext_idle_notifier_v1 *ext_idle_notifier_v1, uint32_t timeout, struct wl_seat *seat)
-{
- struct wl_proxy *id;
-
- id = wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notifier_v1,
- EXT_IDLE_NOTIFIER_V1_GET_IDLE_NOTIFICATION, &ext_idle_notification_v1_interface, wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1), 0, NULL, timeout, seat);
-
- return (struct ext_idle_notification_v1 *) id;
-}
-
-/**
- * @ingroup iface_ext_idle_notifier_v1
- *
- * Create a new idle notification object to track input from the
- * user, such as keyboard and mouse movement. Because this object is
- * meant to track user input alone, it ignores idle inhibitors.
- *
- * The notification object has a minimum timeout duration and is tied to a
- * seat. The client will be notified if the seat is inactive for at least
- * the provided timeout. See ext_idle_notification_v1 for more details.
- *
- * A zero timeout is valid and means the client wants to be notified as
- * soon as possible when the seat is inactive.
- */
-static inline struct ext_idle_notification_v1 *
-ext_idle_notifier_v1_get_input_idle_notification(struct ext_idle_notifier_v1 *ext_idle_notifier_v1, uint32_t timeout, struct wl_seat *seat)
-{
- struct wl_proxy *id;
-
- id = wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notifier_v1,
- EXT_IDLE_NOTIFIER_V1_GET_INPUT_IDLE_NOTIFICATION, &ext_idle_notification_v1_interface, wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1), 0, NULL, timeout, seat);
-
- return (struct ext_idle_notification_v1 *) id;
-}
-
-/**
- * @ingroup iface_ext_idle_notification_v1
- * @struct ext_idle_notification_v1_listener
- */
-struct ext_idle_notification_v1_listener {
- /**
- * notification object is idle
- *
- * This event is sent when the notification object becomes idle.
- *
- * It's a compositor protocol error to send this event twice
- * without a resumed event in-between.
- */
- void (*idled)(void *data,
- struct ext_idle_notification_v1 *ext_idle_notification_v1);
- /**
- * notification object is no longer idle
- *
- * This event is sent when the notification object stops being
- * idle.
- *
- * It's a compositor protocol error to send this event twice
- * without an idled event in-between. It's a compositor protocol
- * error to send this event prior to any idled event.
- */
- void (*resumed)(void *data,
- struct ext_idle_notification_v1 *ext_idle_notification_v1);
-};
-
-/**
- * @ingroup iface_ext_idle_notification_v1
- */
-static inline int
-ext_idle_notification_v1_add_listener(struct ext_idle_notification_v1 *ext_idle_notification_v1,
- const struct ext_idle_notification_v1_listener *listener, void *data)
-{
- return wl_proxy_add_listener((struct wl_proxy *) ext_idle_notification_v1,
- (void (**)(void)) listener, data);
-}
-
-#define EXT_IDLE_NOTIFICATION_V1_DESTROY 0
-
-/**
- * @ingroup iface_ext_idle_notification_v1
- */
-#define EXT_IDLE_NOTIFICATION_V1_IDLED_SINCE_VERSION 1
-/**
- * @ingroup iface_ext_idle_notification_v1
- */
-#define EXT_IDLE_NOTIFICATION_V1_RESUMED_SINCE_VERSION 1
-
-/**
- * @ingroup iface_ext_idle_notification_v1
- */
-#define EXT_IDLE_NOTIFICATION_V1_DESTROY_SINCE_VERSION 1
-
-/** @ingroup iface_ext_idle_notification_v1 */
-static inline void
-ext_idle_notification_v1_set_user_data(struct ext_idle_notification_v1 *ext_idle_notification_v1, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) ext_idle_notification_v1, user_data);
-}
-
-/** @ingroup iface_ext_idle_notification_v1 */
-static inline void *
-ext_idle_notification_v1_get_user_data(struct ext_idle_notification_v1 *ext_idle_notification_v1)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) ext_idle_notification_v1);
-}
-
-static inline uint32_t
-ext_idle_notification_v1_get_version(struct ext_idle_notification_v1 *ext_idle_notification_v1)
-{
- return wl_proxy_get_version((struct wl_proxy *) ext_idle_notification_v1);
-}
-
-/**
- * @ingroup iface_ext_idle_notification_v1
- *
- * Destroy the notification object.
- */
-static inline void
-ext_idle_notification_v1_destroy(struct ext_idle_notification_v1 *ext_idle_notification_v1)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notification_v1,
- EXT_IDLE_NOTIFICATION_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_idle_notification_v1), WL_MARSHAL_FLAG_DESTROY);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* Generated by wayland-scanner 1.23.1 */
-
-/*
- * Copyright © 2015 Martin Gräßlin
- * Copyright © 2022 Simon Ser
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "wayland-util.h"
-
-#ifndef __has_attribute
-# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
-#endif
-
-#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
-#define WL_PRIVATE __attribute__ ((visibility("hidden")))
-#else
-#define WL_PRIVATE
-#endif
-
-extern const struct wl_interface ext_idle_notification_v1_interface;
-extern const struct wl_interface wl_seat_interface;
-
-static const struct wl_interface *ext_idle_notify_v1_types[] = {
- &ext_idle_notification_v1_interface,
- NULL,
- &wl_seat_interface,
- &ext_idle_notification_v1_interface,
- NULL,
- &wl_seat_interface,
-};
-
-static const struct wl_message ext_idle_notifier_v1_requests[] = {
- { "destroy", "", ext_idle_notify_v1_types + 0 },
- { "get_idle_notification", "nuo", ext_idle_notify_v1_types + 0 },
- { "get_input_idle_notification", "2nuo", ext_idle_notify_v1_types + 3 },
-};
-
-WL_PRIVATE const struct wl_interface ext_idle_notifier_v1_interface = {
- "ext_idle_notifier_v1", 2,
- 3, ext_idle_notifier_v1_requests,
- 0, NULL,
-};
-
-static const struct wl_message ext_idle_notification_v1_requests[] = {
- { "destroy", "", ext_idle_notify_v1_types + 0 },
-};
-
-static const struct wl_message ext_idle_notification_v1_events[] = {
- { "idled", "", ext_idle_notify_v1_types + 0 },
- { "resumed", "", ext_idle_notify_v1_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface ext_idle_notification_v1_interface = {
- "ext_idle_notification_v1", 2,
- 1, ext_idle_notification_v1_requests,
- 2, ext_idle_notification_v1_events,
-};
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<protocol name="ext_idle_notify_v1">
- <copyright>
- Copyright © 2015 Martin Gräßlin
- Copyright © 2022 Simon Ser
-
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice (including the next
- paragraph) shall be included in all copies or substantial portions of the
- Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
- </copyright>
-
- <interface name="ext_idle_notifier_v1" version="2">
- <description summary="idle notification manager">
- This interface allows clients to monitor user idle status.
-
- After binding to this global, clients can create ext_idle_notification_v1
- objects to get notified when the user is idle for a given amount of time.
- </description>
-
- <request name="destroy" type="destructor">
- <description summary="destroy the manager">
- Destroy the manager object. All objects created via this interface
- remain valid.
- </description>
- </request>
-
- <request name="get_idle_notification">
- <description summary="create a notification object">
- Create a new idle notification object.
-
- The notification object has a minimum timeout duration and is tied to a
- seat. The client will be notified if the seat is inactive for at least
- the provided timeout. See ext_idle_notification_v1 for more details.
-
- A zero timeout is valid and means the client wants to be notified as
- soon as possible when the seat is inactive.
- </description>
- <arg name="id" type="new_id" interface="ext_idle_notification_v1"/>
- <arg name="timeout" type="uint" summary="minimum idle timeout in msec"/>
- <arg name="seat" type="object" interface="wl_seat"/>
- </request>
-
- <!-- Version 2 additions -->
-
- <request name="get_input_idle_notification" since="2">
- <description summary="create a notification object">
- Create a new idle notification object to track input from the
- user, such as keyboard and mouse movement. Because this object is
- meant to track user input alone, it ignores idle inhibitors.
-
- The notification object has a minimum timeout duration and is tied to a
- seat. The client will be notified if the seat is inactive for at least
- the provided timeout. See ext_idle_notification_v1 for more details.
-
- A zero timeout is valid and means the client wants to be notified as
- soon as possible when the seat is inactive.
- </description>
- <arg name="id" type="new_id" interface="ext_idle_notification_v1"/>
- <arg name="timeout" type="uint" summary="minimum idle timeout in msec"/>
- <arg name="seat" type="object" interface="wl_seat"/>
- </request>
-
- </interface>
-
- <interface name="ext_idle_notification_v1" version="2">
- <description summary="idle notification">
- This interface is used by the compositor to send idle notification events
- to clients.
-
- Initially the notification object is not idle. The notification object
- becomes idle when no user activity has happened for at least the timeout
- duration, starting from the creation of the notification object. User
- activity may include input events or a presence sensor, but is
- compositor-specific.
-
- How this notification responds to idle inhibitors depends on how
- it was constructed. If constructed from the
- get_idle_notification request, then if an idle inhibitor is
- active (e.g. another client has created a zwp_idle_inhibitor_v1
- on a visible surface), the compositor must not make the
- notification object idle. However, if constructed from the
- get_input_idle_notification request, then idle inhibitors are
- ignored, and only input from the user, e.g. from a keyboard or
- mouse, counts as activity.
-
- When the notification object becomes idle, an idled event is sent. When
- user activity starts again, the notification object stops being idle,
- a resumed event is sent and the timeout is restarted.
- </description>
-
- <request name="destroy" type="destructor">
- <description summary="destroy the notification object">
- Destroy the notification object.
- </description>
- </request>
-
- <event name="idled">
- <description summary="notification object is idle">
- This event is sent when the notification object becomes idle.
-
- It's a compositor protocol error to send this event twice without a
- resumed event in-between.
- </description>
- </event>
-
- <event name="resumed">
- <description summary="notification object is no longer idle">
- This event is sent when the notification object stops being idle.
-
- It's a compositor protocol error to send this event twice without an
- idled event in-between. It's a compositor protocol error to send this
- event prior to any idled event.
- </description>
- </event>
- </interface>
-</protocol>
by running "xscreensaver-getimage" which in turn runs "grim", if it is
installed, which it might not be.
- In summary, everything is terrible because X11 doesn't support alpha.
-
+ - OpenGL: This is like XSHM but uses OpenGL for rendering. Faster, but
+ same screenshot- and Wayland-related downsides.
- Another thing to consider is to implement fading with OpenGL: put the
- screen shot in a textured quad and just change its color for fading.
- That should be efficient on both X11 and Wayland. However it would
- require linking the OpenGL libraries into "xscreensaver-gfx".
+ In summary, everything is terrible because X11 doesn't support alpha.
The fade process goes like this:
# include <X11/Intrinsic.h>
#endif /* !HAVE_JWXYZ */
+#ifdef USE_GL
+# include <GL/gl.h>
+# include <GL/glu.h>
+# ifdef HAVE_EGL
+# include <EGL/egl.h>
+# include <EGL/eglext.h>
+# else
+# include <GL/glx.h>
+# endif
+#endif /* USE_GL */
+
#include "blurb.h"
#include "visual.h"
+#ifdef USE_GL
+#include "visual-gl.h"
+#endif
#include "usleep.h"
#include "fade.h"
#include "xshm.h"
#include "atoms.h"
#include "clientmsg.h"
#include "xmu.h"
+#include "pow2.h"
+#include "screenshot.h"
/* Since gamma fading doesn't work on the Raspberry Pi, probably the single
most popular desktop Linux system these days, let's not use this fade
} fade_state;
-/* #### There's a bunch of duplicated code in the back half of the
- four _fade and _whack functions that could probably be combined.
- */
#ifdef HAVE_SGI_VC_EXTENSION
static int sgi_gamma_fade (XtAppContext, Display *, Window *wins, int count,
double secs, Bool out_p);
/****************************************************************************
- XSHM screen-shot fading
+ XSHM or OpenGL screenshot fading
+ This module does one or the other, depending on USE_GL
****************************************************************************/
typedef struct {
- GC gc;
Window window;
+ XImage *src;
Pixmap screenshot;
- XImage *src, *intermediate;
+# ifndef USE_GL
+ XImage *intermediate;
+ GC gc;
+# else /* USE_GL */
+ GLuint texid;
+ GLfloat texw, texh;
+# ifdef HAVE_EGL
+ egl_data *glx_context;
+# else
+ GLXContext glx_context;
+# endif
+# endif /* USE_GL */
} xshm_fade_info;
+#ifdef USE_GL
+static int opengl_whack (Display *, xshm_fade_info *, float ratio);
+#else
static int xshm_whack (Display *, XShmSegmentInfo *,
xshm_fade_info *, float ratio);
-
+#endif
/* Grab a screenshot and return it.
It will be the size and extent of the given window.
XWindowAttributes xgwa;
Pixmap pixmap = 0;
Bool external_p = False;
+ double start = double_time();
# ifdef HAVE_MACOS_X11
external_p = True;
external_p = getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET");
# endif
+ if (from_desktop_p)
+ {
+ Pixmap p = screenshot_load (dpy, window, verbose_p);
+ if (p) return p;
+ }
+
XGetWindowAttributes (dpy, window, &xgwa);
pixmap = XCreatePixmap (dpy, window, xgwa.width, xgwa.height, xgwa.depth);
if (!pixmap) return None;
}
# endif /* HAVE_MACOS_X11 */
+ {
+ double elapsed = double_time() - start;
+ char late[100];
+ if (elapsed >= 0.75)
+ sprintf (late, " -- took %.1f seconds", elapsed);
+ else
+ *late = 0;
+
+ if (verbose_p || !pixmap || *late)
+ fprintf (stderr, "%s: %s screenshot 0x%lx %dx%d"
+ " for window 0x%lx%s\n", blurb(),
+ (pixmap ? "saved" : "failed to save"),
+ (unsigned long) pixmap, xgwa.width, xgwa.height,
+ (unsigned long) window,
+ late);
+ }
+
return pixmap;
}
+#ifdef USE_GL
+static void
+opengl_make_current (Display *dpy, xshm_fade_info *info)
+{
+# ifdef HAVE_EGL
+ egl_data *d = info->glx_context;
+ if (! eglMakeCurrent (d->egl_display, d->egl_surface, d->egl_surface,
+ d->egl_context))
+ abort();
+# else /* !HAVE_EGL */
+ glXMakeCurrent (dpy, info->window, info->glx_context);
+# endif /* !HAVE_EGL */
+
+}
+
+/* report a GL error. */
+static Bool
+check_gl_error (const char *type)
+{
+ char buf[100];
+ GLenum i;
+ const char *e;
+ switch ((i = glGetError())) {
+ case GL_NO_ERROR: return False;
+ case GL_INVALID_ENUM: e = "invalid enum"; break;
+ case GL_INVALID_VALUE: e = "invalid value"; break;
+ case GL_INVALID_OPERATION: e = "invalid operation"; break;
+ case GL_STACK_OVERFLOW: e = "stack overflow"; break;
+ case GL_STACK_UNDERFLOW: e = "stack underflow"; break;
+ case GL_OUT_OF_MEMORY: e = "out of memory"; break;
+#ifdef GL_INVALID_FRAMEBUFFER_OPERATION
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ e = "invalid framebuffer operation";
+ break;
+#endif
+#ifdef GL_TABLE_TOO_LARGE_EXT
+ case GL_TABLE_TOO_LARGE_EXT: e = "table too large"; break;
+#endif
+#ifdef GL_TEXTURE_TOO_LARGE_EXT
+ case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break;
+#endif
+ default:
+ e = buf; sprintf (buf, "unknown error %d", (int) i); break;
+ }
+ fprintf (stderr, "%s: %s error: %s\n", progname, type, e);
+ return True;
+}
+#endif /* USE_GL */
+
+
/* Returns:
0: faded normally
1: canceled by user activity
int screen;
int status = -1;
xshm_fade_info *info = 0;
+# ifndef USE_GL
XShmSegmentInfo shm_info;
+# endif
Window saver_window = 0;
XErrorHandler old_handler = 0;
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
error_handler_hit_p = False;
+# ifdef USE_GL
if (verbose_p > 1)
- fprintf (stderr, "%s: SHM fade %s\n",
- blurb(), (out_p ? "out" : "in"));
+ fprintf (stderr, "%s: GL fade %s\n", blurb(), (out_p ? "out" : "in"));
+# else /* !USE_GL */
+ if (verbose_p > 1)
+ fprintf (stderr, "%s: SHM fade %s\n", blurb(), (out_p ? "out" : "in"));
+# endif /* !USE_GL */
info = (xshm_fade_info *) calloc(nwindows, sizeof(*info));
if (!info) goto FAIL;
{
XWindowAttributes xgwa;
Window root;
- XGCValues gcv;
- unsigned long attrmask = 0;
+ Visual *visual;
XSetWindowAttributes attrs;
+ unsigned long attrmask = 0;
+# ifndef USE_GL
+ XGCValues gcv;
+# endif /* USE_GL */
XGetWindowAttributes (dpy, saver_windows[screen], &xgwa);
root = RootWindowOfScreen (xgwa.screen);
+# ifdef USE_GL
+ visual = get_gl_visual (xgwa.screen);
+# else /* !USE_GL */
+ visual = xgwa.visual;
+# endif /* !USE_GL */
+# ifdef USE_GL
info[screen].src =
- create_xshm_image (dpy, xgwa.visual, xgwa.depth,
+ XCreateImage (dpy, visual, 32, ZPixmap, 0, NULL,
+ xgwa.width, xgwa.height, 32, 0);
+ if (!info[screen].src) goto FAIL;
+ info[screen].src->data = (char *)
+ malloc (info[screen].src->height * info[screen].src->bytes_per_line);
+ info[screen].src->bitmap_bit_order =
+ info[screen].src->byte_order = MSBFirst;
+
+ while (glGetError() != GL_NO_ERROR)
+ ; /* Flush */
+
+# else /* !USE_GL */
+ info[screen].src =
+ create_xshm_image (dpy, visual, xgwa.depth,
ZPixmap, &shm_info, xgwa.width, xgwa.height);
if (!info[screen].src) goto FAIL;
info[screen].intermediate =
- create_xshm_image (dpy, xgwa.visual, xgwa.depth,
+ create_xshm_image (dpy, visual, xgwa.depth,
ZPixmap, &shm_info, xgwa.width, xgwa.height);
if (!info[screen].intermediate) goto FAIL;
+# endif /* !USE_GL */
if (!out_p)
{
info[screen].window =
XCreateWindow (dpy, root, xgwa.x, xgwa.y,
xgwa.width, xgwa.height, xgwa.border_width, xgwa.depth,
- InputOutput, xgwa.visual,
+ InputOutput, visual,
attrmask, &attrs);
if (!info[screen].window) goto FAIL;
/* XSelectInput (dpy, info[screen].window,
KeyPressMask | ButtonPressMask); */
+# ifdef USE_GL
+ /* Copy the screenshot pixmap to the texture XImage */
+ XGetSubImage (dpy, info[screen].screenshot,
+ 0, 0, xgwa.width, xgwa.height,
+ ~0L, ZPixmap, info[screen].src, 0, 0);
+
+ /* Convert 0RGB to RGBA */
+ {
+ XImage *ximage = info[screen].src;
+ int x, y;
+ for (y = 0; y < ximage->height; y++)
+ for (x = 0; x < ximage->width; x++)
+ {
+ unsigned long p = XGetPixel (ximage, x, y);
+ unsigned long a = 0xFF;
+ /* unsigned long a = (p >> 24) & 0xFF; */
+ unsigned long r = (p >> 16) & 0xFF;
+ unsigned long g = (p >> 8) & 0xFF;
+ unsigned long b = (p >> 0) & 0xFF;
+ p = (r << 24) | (g << 16) | (b << 8) | (a << 0);
+ XPutPixel (ximage, x, y, p);
+ }
+ }
+
+ /* Connect the window to an OpenGL context */
+ info[screen].glx_context =
+ openGL_context_for_window (xgwa.screen, info[screen].window);
+ opengl_make_current (dpy, &info[screen]);
+ if (check_gl_error ("connect")) goto FAIL;
+
+ glEnable (GL_TEXTURE_2D);
+ glEnable (GL_NORMALIZE);
+ glGenTextures (1, &info[screen].texid);
+ glBindTexture (GL_TEXTURE_2D, info[screen].texid);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ if (check_gl_error ("bind texture")) goto FAIL;
+
+ {
+ int tex_width = (GLsizei) to_pow2 (info[screen].src->width);
+ int tex_height = (GLsizei) to_pow2 (info[screen].src->height);
+ /* Create power of 2 empty texture */
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ if (check_gl_error ("glTexImage2D")) goto FAIL;
+ /* Load our non-power-of-2 image data into it. */
+ glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
+ info[screen].src->width, info[screen].src->height,
+ GL_RGBA, GL_UNSIGNED_BYTE, info[screen].src->data);
+ if (check_gl_error ("glTexSubImage2D")) goto FAIL;
+ info[screen].texw = info[screen].src->width / (GLfloat) tex_width;
+ info[screen].texh = info[screen].src->height / (GLfloat) tex_height;
+ }
+
+ glViewport (0, 0, xgwa.width, xgwa.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho (0, 1, 1, 0, -1, 1);
+ glMatrixMode (GL_MODELVIEW);
+ glLoadIdentity();
+ glClearColor (0, 0, 0, 1);
+ glClear (GL_COLOR_BUFFER_BIT);
+ glFrontFace (GL_CCW);
+ if (check_gl_error ("GL setup")) goto FAIL;
+
+# else /* !USE_GL */
/* Copy the screenshot pixmap to the source image */
if (! get_xshm_image (dpy, info[screen].screenshot, info[screen].src,
0, 0, ~0L, &shm_info))
gcv.function = GXcopy;
info[screen].gc = XCreateGC (dpy, info[screen].window, GCFunction, &gcv);
+# endif /* !USE_GL */
}
/* If we're fading out from the desktop, save our screen shots for later use.
for (screen = 0; screen < nwindows; screen++)
{
+# ifndef USE_GL
if (out_p)
/* Copy the screenshot to the fader window */
XSetWindowBackgroundPixmap (dpy, info[screen].window,
XSetWindowBackgroundPixmap (dpy, info[screen].window, None);
XSetWindowBackground (dpy, info[screen].window, BlackPixel (dpy, 0));
}
+# endif /* USE_GL */
XMapRaised (dpy, info[screen].window);
if (!out_p) ratio = 1-ratio;
for (screen = 0; screen < nwindows; screen++)
+# ifdef USE_GL
+ if (opengl_whack (dpy, &info[screen], ratio))
+ goto FAIL;
+# else /* !USE_GL */
if (xshm_whack (dpy, &shm_info, &info[screen], ratio))
goto FAIL;
+# endif /* !USE_GL */
if (error_handler_hit_p)
goto FAIL;
{
for (screen = 0; screen < nwindows; screen++)
{
+# ifdef USE_GL
+ if (info[screen].src)
+ XDestroyImage (info[screen].src);
+ if (info[screen].texid)
+ glDeleteTextures (1, &info[screen].texid);
+ openGL_destroy_context (dpy, info[screen].glx_context);
+# else /* !USE_GL */
if (info[screen].src)
destroy_xshm_image (dpy, info[screen].src, &shm_info);
if (info[screen].intermediate)
destroy_xshm_image (dpy, info[screen].intermediate, &shm_info);
- if (info[screen].window)
- defer_XDestroyWindow (app, dpy, info[screen].window);
if (info[screen].gc)
XFreeGC (dpy, info[screen].gc);
+# endif /* !USE_GL */
+
+ if (info[screen].window)
+ defer_XDestroyWindow (app, dpy, info[screen].window);
}
free (info);
}
if (error_handler_hit_p) status = -1;
if (verbose_p > 1 && status)
+# ifdef HAVE_GL
+ fprintf (stderr, "%s: GL fade %s failed\n",
+ blurb(), (out_p ? "out" : "in"));
+# else /* !HAVE_GL */
fprintf (stderr, "%s: SHM fade %s failed\n",
blurb(), (out_p ? "out" : "in"));
+# endif /* !HAVE_GL */
return status;
}
+#ifdef USE_GL
+
+static int
+opengl_whack (Display *dpy, xshm_fade_info *info, float ratio)
+{
+ GLfloat w = info->texw;
+ GLfloat h = info->texh;
+
+ opengl_make_current (dpy, info);
+ glBindTexture (GL_TEXTURE_2D, info->texid);
+ glClear (GL_COLOR_BUFFER_BIT);
+
+ if (ratio < 0) ratio = 0;
+ if (ratio > 1) ratio = 1;
+
+ glColor3f (ratio, ratio, ratio);
+
+ glBegin (GL_QUADS);
+ glTexCoord2f (0, 0); glVertex3f (0, 0, 0);
+ glTexCoord2f (0, h); glVertex3f (0, 1, 0);
+ glTexCoord2f (w, h); glVertex3f (1, 1, 0);
+ glTexCoord2f (w, 0); glVertex3f (1, 0, 0);
+ glEnd();
+ glFinish();
+
+# ifdef HAVE_EGL
+ if (! eglSwapBuffers (info->glx_context->egl_display,
+ info->glx_context->egl_surface))
+ return True;
+# else
+ glXSwapBuffers (dpy, info->window);
+# endif
+
+ if (check_gl_error ("gl whack")) return True;
+ return False;
+}
+
+
+#else /* !USE_GL */
+
static int
xshm_whack (Display *dpy, XShmSegmentInfo *shm_info,
xshm_fade_info *info, float ratio)
XSync (dpy, False);
return 0;
}
+
+#endif /* !USE_GL */
+
+++ /dev/null
-/* Generated by wayland-scanner 1.23.1 */
-
-#ifndef IDLE_CLIENT_PROTOCOL_H
-#define IDLE_CLIENT_PROTOCOL_H
-
-#include <stdint.h>
-#include <stddef.h>
-#include "wayland-client.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @page page_idle The idle protocol
- * @section page_ifaces_idle Interfaces
- * - @subpage page_iface_org_kde_kwin_idle - User idle time manager
- * - @subpage page_iface_org_kde_kwin_idle_timeout -
- * @section page_copyright_idle Copyright
- * <pre>
- *
- * Copyright (C) 2015 Martin Gräßlin
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * </pre>
- */
-struct org_kde_kwin_idle;
-struct org_kde_kwin_idle_timeout;
-struct wl_seat;
-
-#ifndef ORG_KDE_KWIN_IDLE_INTERFACE
-#define ORG_KDE_KWIN_IDLE_INTERFACE
-/**
- * @page page_iface_org_kde_kwin_idle org_kde_kwin_idle
- * @section page_iface_org_kde_kwin_idle_desc Description
- *
- * This interface allows to monitor user idle time on a given seat. The interface
- * allows to register timers which trigger after no user activity was registered
- * on the seat for a given interval. It notifies when user activity resumes.
- *
- * This is useful for applications wanting to perform actions when the user is not
- * interacting with the system, e.g. chat applications setting the user as away, power
- * management features to dim screen, etc..
- * @section page_iface_org_kde_kwin_idle_api API
- * See @ref iface_org_kde_kwin_idle.
- */
-/**
- * @defgroup iface_org_kde_kwin_idle The org_kde_kwin_idle interface
- *
- * This interface allows to monitor user idle time on a given seat. The interface
- * allows to register timers which trigger after no user activity was registered
- * on the seat for a given interval. It notifies when user activity resumes.
- *
- * This is useful for applications wanting to perform actions when the user is not
- * interacting with the system, e.g. chat applications setting the user as away, power
- * management features to dim screen, etc..
- */
-extern const struct wl_interface org_kde_kwin_idle_interface;
-#endif
-#ifndef ORG_KDE_KWIN_IDLE_TIMEOUT_INTERFACE
-#define ORG_KDE_KWIN_IDLE_TIMEOUT_INTERFACE
-/**
- * @page page_iface_org_kde_kwin_idle_timeout org_kde_kwin_idle_timeout
- * @section page_iface_org_kde_kwin_idle_timeout_api API
- * See @ref iface_org_kde_kwin_idle_timeout.
- */
-/**
- * @defgroup iface_org_kde_kwin_idle_timeout The org_kde_kwin_idle_timeout interface
- */
-extern const struct wl_interface org_kde_kwin_idle_timeout_interface;
-#endif
-
-#define ORG_KDE_KWIN_IDLE_GET_IDLE_TIMEOUT 0
-
-
-/**
- * @ingroup iface_org_kde_kwin_idle
- */
-#define ORG_KDE_KWIN_IDLE_GET_IDLE_TIMEOUT_SINCE_VERSION 1
-
-/** @ingroup iface_org_kde_kwin_idle */
-static inline void
-org_kde_kwin_idle_set_user_data(struct org_kde_kwin_idle *org_kde_kwin_idle, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) org_kde_kwin_idle, user_data);
-}
-
-/** @ingroup iface_org_kde_kwin_idle */
-static inline void *
-org_kde_kwin_idle_get_user_data(struct org_kde_kwin_idle *org_kde_kwin_idle)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) org_kde_kwin_idle);
-}
-
-static inline uint32_t
-org_kde_kwin_idle_get_version(struct org_kde_kwin_idle *org_kde_kwin_idle)
-{
- return wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle);
-}
-
-/** @ingroup iface_org_kde_kwin_idle */
-static inline void
-org_kde_kwin_idle_destroy(struct org_kde_kwin_idle *org_kde_kwin_idle)
-{
- wl_proxy_destroy((struct wl_proxy *) org_kde_kwin_idle);
-}
-
-/**
- * @ingroup iface_org_kde_kwin_idle
- */
-static inline struct org_kde_kwin_idle_timeout *
-org_kde_kwin_idle_get_idle_timeout(struct org_kde_kwin_idle *org_kde_kwin_idle, struct wl_seat *seat, uint32_t timeout)
-{
- struct wl_proxy *id;
-
- id = wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_idle,
- ORG_KDE_KWIN_IDLE_GET_IDLE_TIMEOUT, &org_kde_kwin_idle_timeout_interface, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle), 0, NULL, seat, timeout);
-
- return (struct org_kde_kwin_idle_timeout *) id;
-}
-
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- * @struct org_kde_kwin_idle_timeout_listener
- */
-struct org_kde_kwin_idle_timeout_listener {
- /**
- * Triggered when there has not been any user activity in the requested idle time interval
- *
- *
- */
- void (*idle)(void *data,
- struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout);
- /**
- * Triggered on the first user activity after an idle event
- *
- *
- */
- void (*resumed)(void *data,
- struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout);
-};
-
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- */
-static inline int
-org_kde_kwin_idle_timeout_add_listener(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout,
- const struct org_kde_kwin_idle_timeout_listener *listener, void *data)
-{
- return wl_proxy_add_listener((struct wl_proxy *) org_kde_kwin_idle_timeout,
- (void (**)(void)) listener, data);
-}
-
-#define ORG_KDE_KWIN_IDLE_TIMEOUT_RELEASE 0
-#define ORG_KDE_KWIN_IDLE_TIMEOUT_SIMULATE_USER_ACTIVITY 1
-
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- */
-#define ORG_KDE_KWIN_IDLE_TIMEOUT_IDLE_SINCE_VERSION 1
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- */
-#define ORG_KDE_KWIN_IDLE_TIMEOUT_RESUMED_SINCE_VERSION 1
-
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- */
-#define ORG_KDE_KWIN_IDLE_TIMEOUT_RELEASE_SINCE_VERSION 1
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- */
-#define ORG_KDE_KWIN_IDLE_TIMEOUT_SIMULATE_USER_ACTIVITY_SINCE_VERSION 1
-
-/** @ingroup iface_org_kde_kwin_idle_timeout */
-static inline void
-org_kde_kwin_idle_timeout_set_user_data(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) org_kde_kwin_idle_timeout, user_data);
-}
-
-/** @ingroup iface_org_kde_kwin_idle_timeout */
-static inline void *
-org_kde_kwin_idle_timeout_get_user_data(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) org_kde_kwin_idle_timeout);
-}
-
-static inline uint32_t
-org_kde_kwin_idle_timeout_get_version(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
-{
- return wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle_timeout);
-}
-
-/** @ingroup iface_org_kde_kwin_idle_timeout */
-static inline void
-org_kde_kwin_idle_timeout_destroy(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
-{
- wl_proxy_destroy((struct wl_proxy *) org_kde_kwin_idle_timeout);
-}
-
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- */
-static inline void
-org_kde_kwin_idle_timeout_release(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_idle_timeout,
- ORG_KDE_KWIN_IDLE_TIMEOUT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle_timeout), WL_MARSHAL_FLAG_DESTROY);
-}
-
-/**
- * @ingroup iface_org_kde_kwin_idle_timeout
- */
-static inline void
-org_kde_kwin_idle_timeout_simulate_user_activity(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_idle_timeout,
- ORG_KDE_KWIN_IDLE_TIMEOUT_SIMULATE_USER_ACTIVITY, NULL, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle_timeout), 0);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* Generated by wayland-scanner 1.23.1 */
-
-/*
- * Copyright (C) 2015 Martin Gräßlin
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "wayland-util.h"
-
-#ifndef __has_attribute
-# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
-#endif
-
-#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
-#define WL_PRIVATE __attribute__ ((visibility("hidden")))
-#else
-#define WL_PRIVATE
-#endif
-
-extern const struct wl_interface org_kde_kwin_idle_timeout_interface;
-extern const struct wl_interface wl_seat_interface;
-
-static const struct wl_interface *idle_types[] = {
- &org_kde_kwin_idle_timeout_interface,
- &wl_seat_interface,
- NULL,
-};
-
-static const struct wl_message org_kde_kwin_idle_requests[] = {
- { "get_idle_timeout", "nou", idle_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface org_kde_kwin_idle_interface = {
- "org_kde_kwin_idle", 1,
- 1, org_kde_kwin_idle_requests,
- 0, NULL,
-};
-
-static const struct wl_message org_kde_kwin_idle_timeout_requests[] = {
- { "release", "", idle_types + 0 },
- { "simulate_user_activity", "", idle_types + 0 },
-};
-
-static const struct wl_message org_kde_kwin_idle_timeout_events[] = {
- { "idle", "", idle_types + 0 },
- { "resumed", "", idle_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface org_kde_kwin_idle_timeout_interface = {
- "org_kde_kwin_idle_timeout", 1,
- 2, org_kde_kwin_idle_timeout_requests,
- 2, org_kde_kwin_idle_timeout_events,
-};
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<protocol name="idle">
- <copyright><![CDATA[
- Copyright (C) 2015 Martin Gräßlin
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- ]]></copyright>
- <interface name="org_kde_kwin_idle" version="1">
- <description summary="User idle time manager">
- This interface allows to monitor user idle time on a given seat. The interface
- allows to register timers which trigger after no user activity was registered
- on the seat for a given interval. It notifies when user activity resumes.
-
- This is useful for applications wanting to perform actions when the user is not
- interacting with the system, e.g. chat applications setting the user as away, power
- management features to dim screen, etc..
- </description>
- <request name="get_idle_timeout">
- <arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/>
- <arg name="seat" type="object" interface="wl_seat"/>
- <arg name="timeout" type="uint" summary="The idle timeout in msec"/>
- </request>
- </interface>
- <interface name="org_kde_kwin_idle_timeout" version="1">
- <request name="release" type="destructor">
- <description summary="release the timeout object"/>
- </request>
- <request name="simulate_user_activity">
- <description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/>
- </request>
- <event name="idle">
- <description summary="Triggered when there has not been any user activity in the requested idle time interval"/>
- </event>
- <event name="resumed">
- <description summary="Triggered on the first user activity after an idle event"/>
- </event>
- </interface>
-</protocol>
p->fade_p = False;
if (! p->fade_p) p->unfade_p = False;
- /* DPMS settings may be zero, but otherwise, if they < 10 sec or negative,
+ /* DPMS settings may be zero, but otherwise, if they're < 10 sec or negative,
set them to 2 minutes. */
# define THROTTLE(FIELD) \
if (p->FIELD != 0 && ((long) p->FIELD) < 10 * 1000) \
p->FIELD = p->LOWER
THROTTLE (dpms_standby, timeout);
THROTTLE (dpms_suspend, dpms_standby);
- THROTTLE (dpms_off, dpms_standby);
- THROTTLE (dpms_off, dpms_suspend);
+/* This requires a check for dpms_partial_p which demo-Gtk.c sets. */
+/* THROTTLE (dpms_off, dpms_standby); */
+/* THROTTLE (dpms_off, dpms_suspend); */
#undef THROTTLE
if (p->dpms_standby == 0 && /* if *all* are 0, then DPMS is disabled */
# define _(S) (S)
#endif
+#if defined(USE_GL) && !defined(HAVE_EGL)
+# include <OpenGL/gl.h> /* For GLXContext in visual-gl.h */
+# include <GL/glx.h>
+#endif
+
#include "xscreensaver.h"
#include "exec.h"
#include "yarandom.h"
#include "atoms.h"
#include "screenshot.h"
+#ifdef USE_GL
+# include "visual-gl.h"
+#endif
enum job_status {
job_running, /* the process is still alive */
catch_signal (sig, SIG_DFL);
/* The first time a signal fires, inform Xt of that so that it will run
- xt_signal_handler(). "XtNoticeSignal is the only Intrinsics function
+ xt_sigterm_handler(). "XtNoticeSignal is the only Intrinsics function
that can safely be called from a signal handler". */
if (xt_sigterm_id)
XtNoticeSignal (xt_sigterm_id);
abort();
}
+#ifdef HAVE_WAYLAND
+/* Called when the Wayland socket drops our connection.
+ We should also die with a SIGPIPE from the XWayland X11 socket,
+ and also a SIGTERM from xscreensaver, so it's a death race.
+ */
+static void
+gfx_wayland_exit (void *closure)
+{
+ saver_info *si = (saver_info *) closure;
+ int i;
+ si->terminating_p = True;
+ for (i = 0; i < si->nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ kill_screenhack (ssi);
+ }
+ exit (1);
+}
+#endif /* HAVE_WAYLAND */
+
/* SIGCHLD handling. Basically the same deal as SIGTERM.
*/
xt_sigchld_id = XtAppAddSignal (si->app, xt_sigchld_handler, si);
xt_sigterm_id = XtAppAddSignal (si->app, xt_sigterm_handler, si);
+
+# ifdef HAVE_WAYLAND
+ if (si->wayland_dpy)
+ wayland_dpy_atexit (si->wayland_dpy, gfx_wayland_exit, si);
+# endif /* HAVE_WAYLAND */
}
saver_preferences *p = &si->prefs;
XFlush (si->dpy);
- if (!monitor_powered_on_p (si->dpy))
+ if (!monitor_powered_on_p (si))
{
if (si->prefs.verbose_p)
fprintf (stderr,
}
+#ifdef USE_GL
+
+Visual *
+get_best_gl_visual (saver_info *si, Screen *screen)
+{
+ saver_preferences *p = &si->prefs;
+ Visual *v = get_gl_visual (screen);
+ if (!v)
+ fprintf (stderr, "%s: %d: no GL visual!\n", blurb(),
+ screen_number (screen));
+ else if (p->verbose_p)
+ fprintf (stderr, "%s: %d: GL visual is 0x%X%s\n",
+ blurb(), screen_number (screen),
+ (unsigned int) XVisualIDFromVisual (v),
+ (v == DefaultVisualOfScreen (screen)
+ ? " (default)" : ""));
+ return v;
+}
+
+#else /* !USE_GL */
+
/* Fork "xscreensaver-gl-visual" and wait for it to print the IDs of
the GL visual that should be used on this screen.
*/
abort();
}
+
+#endif /* !USE_GL */
#ifndef __XSCREENSAVER_TYPES_H__
#define __XSCREENSAVER_TYPES_H__
+#ifdef HAVE_WAYLAND
+# include "wayland-dpy.h"
+#endif
+
typedef struct saver_info saver_info;
typedef struct screenhack screenhack;
char *version;
saver_preferences prefs;
+# ifdef HAVE_WAYLAND
+ wayland_dpy *wayland_dpy;
+ wayland_idle *wayland_idle;
+ wayland_dpms *wayland_dpms;
+# endif /* HAVE_WAYLAND */
+
int nscreens;
int ssi_count;
saver_screen_info *screens;
/* From dpms.c */
-extern void sync_server_dpms_settings (Display *, struct saver_preferences *);
-extern void brute_force_dpms (Display *, struct saver_preferences *, time_t);
+extern void sync_server_dpms_settings (saver_info *);
+extern void sync_server_dpms_settings_1 (Display *, struct saver_preferences *);
+extern void brute_force_dpms (saver_info *, time_t);
const char *init_file_name (void);
--- /dev/null
+/* xscreensaver, Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * Detecting and changing whether monitors are powered on under Wayland.
+ * What was ~50 lines of code under X11 (with error checking!) is now 360+.
+ * Wayland is incredible (pej., obs.)
+ *
+ * This code uses either the "wlr-output-power-management-unstable-v1" or
+ * "org-kde-kwin-dpms-manager" protocol. Without one of these, XScreenSaver
+ * cannot power down the screen after the configured timeout, and cannot know
+ * to stop running hacks on a powered-down screen.
+ *
+ * These protocols are, of course, not supported by GNOME. As is traditional.
+ *
+ * Also! Under "wlr", the monitors are not automatically turned back on when
+ * there is user activity. So if this program crashes with the screens off,
+ * good luck getting them to turn back on. KDE does the right thing.
+ *
+ * GNOME does the following crap, because they have never seen a Wayland
+ * protocol that they didn't think should be replaced with DBus instead:
+ *
+ * busctl --user set-property \
+ * org.gnome.Mutter.DisplayConfig \
+ * /org/gnome/Mutter/DisplayConfig \
+ * org.gnome.Mutter.DisplayConfig PowerSaveMode \
+ * i \
+ * [ "0" or "1" ]
+ *
+ * So that's nice.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+
+#include <wayland-client.h>
+#include <wayland-server.h>
+#include "wayland-protocols/wlr-output-power-management-unstable-v1-client-protocol.h"
+#include "wayland-protocols/dpms-client-protocol.h"
+
+#include "wayland-dpyI.h"
+#include "wayland-dpms.h"
+#include "types.h"
+#include "blurb.h"
+
+struct wayland_dpms {
+ wayland_dpy *parent;
+ struct wl_registry *reg;
+ struct zwlr_output_power_manager_v1 *wlr_mgr;
+ struct org_kde_kwin_dpms_manager *kde_mgr;
+ struct wl_list outputs;
+};
+
+typedef struct dpms_output {
+ struct wl_list link;
+
+ struct wl_output *wl_output;
+ char *name;
+ Bool wl_done; /* wl_output: all info about this output has been sent */
+
+ struct zwlr_output_power_v1 *wlr_out;
+ enum zwlr_output_power_v1_mode wlr_mode;
+ Bool wlr_failed; /* I have no idea what this means */
+
+ struct org_kde_kwin_dpms *kde_out;
+ enum org_kde_kwin_dpms_mode kde_mode;
+ Bool kde_done;
+
+} dpms_output;
+
+
+static void
+wl_handle_name (void *data, struct wl_output *wl_output, const char *name)
+{
+ dpms_output *out = (dpms_output *) data;
+ if (out->name) free (out->name);
+ out->name = strdup (name);
+ if (verbose_p > 2)
+ fprintf (stderr, "%s: wayland: dpms: output %s\n", blurb(), name);
+}
+
+/* Even though we don't use any of these callback functions, they have to
+ be included in the listener or it crashes. How very. */
+
+static void
+wl_handle_geometry (void *data, struct wl_output *wl_output,
+ int32_t x, int32_t y,
+ int32_t physical_width, int32_t physical_height,
+ int32_t subpixel, const char *make, const char* model,
+ int32_t transform)
+{
+}
+
+static void
+wl_handle_mode (void *data, struct wl_output *wl_output,
+ uint32_t flags, int32_t width, int32_t height, int32_t refresh)
+{
+}
+
+static void
+wl_handle_scale (void *data, struct wl_output *wl_output, int32_t scale)
+{
+}
+
+static void
+wl_handle_description (void *data, struct wl_output *wl_output,
+ const char *desc)
+{
+}
+
+static void
+wl_handle_done (void *data, struct wl_output *wl_output)
+{
+ dpms_output *out = (dpms_output *) data;
+ out->wl_done = True;
+}
+
+
+static void
+wlr_handle_mode (void *data,
+ struct zwlr_output_power_v1 *wlr_output_power,
+ enum zwlr_output_power_v1_mode mode)
+{
+ dpms_output *out = (dpms_output *) data;
+ out->wlr_mode = mode;
+ if (verbose_p > 2)
+ fprintf (stderr, "%s: wayland: dpms: output %s is %s\n", blurb(),
+ out->name,
+ (out->wlr_mode == ZWLR_OUTPUT_POWER_V1_MODE_ON ? "on" : "off"));
+}
+
+static void
+wlr_handle_failed (void *data, struct zwlr_output_power_v1 *wlr_output_power)
+{
+ dpms_output *out = (dpms_output *) data;
+ out->wlr_failed = True;
+ if (verbose_p > 2)
+ fprintf (stderr, "%s: wayland: dpms: output %s is FAILED?\n", blurb(),
+ out->name);
+}
+
+
+static void
+kde_handle_supported (void *data, struct org_kde_kwin_dpms *dpms,
+ uint32_t supported)
+{
+}
+
+static void
+kde_handle_mode (void *data, struct org_kde_kwin_dpms *dpms, uint32_t mode)
+{
+ dpms_output *out = (dpms_output *) data;
+ out->kde_mode = mode;
+ if (verbose_p > 2)
+ fprintf (stderr, "%s: wayland: dpms: output %s is %s\n", blurb(),
+ out->name,
+ (out->kde_mode == ORG_KDE_KWIN_DPMS_MODE_ON ? "on" :
+ out->kde_mode == ORG_KDE_KWIN_DPMS_MODE_STANDBY ? "standby" :
+ out->kde_mode == ORG_KDE_KWIN_DPMS_MODE_SUSPEND ? "suspend" :
+ out->kde_mode == ORG_KDE_KWIN_DPMS_MODE_OFF ? "off" :
+ "???"));
+}
+
+static void
+kde_handle_done (void *data, struct org_kde_kwin_dpms *dpms)
+{
+ dpms_output *out = (dpms_output *) data;
+ out->kde_done = True;
+}
+
+
+/* This is an iterator for all of the extensions that Wayland provides,
+ so we can find the ones we are interested in.
+ */
+static void
+handle_global (void *data, struct wl_registry *reg,
+ uint32_t name, const char *iface, uint32_t version)
+{
+ wayland_dpms *state = (wayland_dpms *) data;
+
+ if (!strcmp (iface, wl_output_interface.name))
+ {
+ static const struct wl_output_listener wl_listener = {
+ .name = wl_handle_name,
+ .geometry = wl_handle_geometry,
+ .mode = wl_handle_mode,
+ .scale = wl_handle_scale,
+ .description = wl_handle_description,
+ .done = wl_handle_done,
+ };
+ static const struct zwlr_output_power_v1_listener wlr_listener = {
+ .mode = wlr_handle_mode,
+ .failed = wlr_handle_failed,
+ };
+ static const struct org_kde_kwin_dpms_listener kde_listener = {
+ .supported = kde_handle_supported,
+ .mode = kde_handle_mode,
+ .done = kde_handle_done,
+ };
+
+ dpms_output *out = (dpms_output *) calloc (sizeof (*out), 1);
+ wl_list_insert (&state->outputs, &out->link);
+
+ if (verbose_p > 2)
+ fprintf (stderr, "%s: wayland: dpms: found: %s\n", blurb(), iface);
+
+ /* First listener: properties of the wl_output object. */
+ out->wl_output = wl_registry_bind (reg, name, &wl_output_interface,
+ version);
+ wl_output_add_listener (out->wl_output, &wl_listener, out);
+
+ if (state->wlr_mgr)
+ {
+ /* Second listener: changes to its DPMS state. */
+ out->wlr_out =
+ zwlr_output_power_manager_v1_get_output_power (state->wlr_mgr,
+ out->wl_output);
+ zwlr_output_power_v1_add_listener (out->wlr_out, &wlr_listener, out);
+ }
+ else if (state->kde_mgr)
+ {
+ /* Second listener: changes to its DPMS state. */
+ out->kde_out =
+ org_kde_kwin_dpms_manager_get (state->kde_mgr, out->wl_output);
+ org_kde_kwin_dpms_add_listener (out->kde_out, &kde_listener, out);
+ }
+ }
+ else if (!strcmp (iface, zwlr_output_power_manager_v1_interface.name))
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: wayland: dpms: found: %s\n", blurb(), iface);
+ state->wlr_mgr =
+ wl_registry_bind (reg, name, &zwlr_output_power_manager_v1_interface,
+ version);
+ }
+ else if (!strcmp (iface, org_kde_kwin_dpms_manager_interface.name))
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: wayland: dpms: found: %s\n", blurb(), iface);
+ state->kde_mgr =
+ wl_registry_bind (reg, name, &org_kde_kwin_dpms_manager_interface,
+ version);
+ }
+}
+
+
+static void
+handle_global_remove (void *data, struct wl_registry *registry, uint32_t name)
+{
+}
+
+
+wayland_dpms *
+wayland_dpms_init (wayland_dpy *dpy)
+{
+ static const struct wl_registry_listener listener = {
+ .global = handle_global,
+ .global_remove = handle_global_remove,
+ };
+ wayland_dpms *state;
+ if (!dpy) return NULL;
+
+ state = (wayland_dpms *) calloc (sizeof (*state), 1);
+ state->parent = dpy;
+ wl_list_init (&state->outputs);
+
+ state->reg = wl_display_get_registry (dpy->dpy);
+ wl_registry_add_listener (state->reg, &listener, state);
+
+ /* Do the first round trip to load the wl_outputs. */
+ wayland_dpy_process_events (dpy, true);
+
+ /* Now do more round trips until we have all the info about them. FFS! */
+ while (1)
+ {
+ Bool all_done = True;
+ dpms_output *out;
+ wl_list_for_each (out, &state->outputs, link)
+ {
+ if (!out->wl_done)
+ all_done = False;
+ if (state->kde_mgr && !out->kde_done)
+ all_done = False;
+ }
+ if (all_done) break;
+ wayland_dpy_process_events (dpy, true);
+ }
+
+ if (!state->wlr_mgr && !state->kde_mgr)
+ {
+ fprintf (stderr,
+ "%s: wayland: dpms: server doesn't implement \"%s\" or \"%s\"\n",
+ blurb(),
+ zwlr_output_power_manager_v1_interface.name,
+ org_kde_kwin_dpms_manager_interface.name);
+ wayland_dpms_free (state);
+ return NULL;
+ }
+
+ return state;
+}
+
+
+void
+wayland_dpms_free (wayland_dpms *state)
+{
+ dpms_output *out, *tmp;
+ wl_list_for_each_safe (out, tmp, &state->outputs, link)
+ {
+ wl_list_remove (&out->link);
+ /* #### out->wl_output ? */
+ /* #### out->zwlr_output_power_v1, etc ? */
+ free (out);
+ }
+
+ /* #### state->reg ? */
+ /* #### state->zwlr_output_power_manager_v1, etc ? */
+ free (state);
+}
+
+
+/* True if any head is enabled.
+ */
+Bool
+wayland_monitor_powered_on_p (wayland_dpms *state)
+{
+ Bool on_p = False;
+ dpms_output *out;
+
+ if (!state) return on_p;
+
+ wayland_dpy_process_events (state->parent, True);
+ wl_list_for_each (out, &state->outputs, link)
+ {
+ if (out->wlr_out)
+ {
+ if (out->wlr_mode == ZWLR_OUTPUT_POWER_V1_MODE_ON)
+ on_p = True;
+ }
+ else if (out->kde_out)
+ {
+ if (out->kde_mode == ORG_KDE_KWIN_DPMS_MODE_ON)
+ on_p = True;
+ }
+ else
+ abort();
+ }
+
+ return on_p;
+}
+
+
+/* Set all heads to 'enabled' or 'disabled'.
+ */
+void
+wayland_monitor_power_on (wayland_dpms *state, Bool on_p)
+{
+ enum zwlr_output_power_v1_mode wlr_target =
+ (on_p ? ZWLR_OUTPUT_POWER_V1_MODE_ON : ZWLR_OUTPUT_POWER_V1_MODE_OFF);
+ enum org_kde_kwin_dpms_mode kde_target =
+ (on_p ? ORG_KDE_KWIN_DPMS_MODE_ON : ORG_KDE_KWIN_DPMS_MODE_OFF);
+ dpms_output *out;
+
+ if (!state) return;
+
+ wl_list_for_each (out, &state->outputs, link)
+ {
+ if (out->wlr_out)
+ {
+ if (out->wlr_mode == wlr_target)
+ continue;
+ else
+ zwlr_output_power_v1_set_mode (out->wlr_out, wlr_target);
+ }
+ else if (out->kde_out)
+ {
+ if (out->kde_mode == kde_target)
+ continue;
+ else
+ org_kde_kwin_dpms_set (out->kde_out, kde_target);
+ }
+ else
+ abort();
+
+ if (verbose_p > 2)
+ fprintf (stderr, "%s: wayland: dpms: set output %s to %s\n", blurb(),
+ out->name, (on_p ? "on" : "off"));
+ }
+
+ wayland_dpy_process_events (state->parent, True);
+}
+
--- /dev/null
+/* xscreensaver, Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#ifndef __XSCREENSAVER_WAYLAND_DPMS_H__
+#define __XSCREENSAVER_WAYLAND_DPMS_H__
+
+/* Binds to Wayland DPMS-detection protocols and returns an opaque state
+ object on success. */
+extern wayland_dpms *wayland_dpms_init (wayland_dpy *dpy);
+Bool wayland_monitor_powered_on_p (wayland_dpms *);
+void wayland_monitor_power_on (wayland_dpms *, Bool on_p);
+extern void wayland_dpms_free (wayland_dpms *);
+
+#endif /* __XSCREENSAVER_WAYLAND_DPMS_H__ */
--- /dev/null
+/* xscreensaver, Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * Connecting to a Wayland server, and a few connection-related utilities.
+ * The various other wayland-*.c modules (idle, dpms, etc.) build on this.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <wayland-client.h>
+#include <wayland-server.h>
+#include "wayland-dpyI.h"
+#include "blurb.h"
+
+/* Dispatch any events that have been read. */
+static int
+handle_event (int fd, uint32_t mask, void *data)
+{
+ wayland_dpy *state = (wayland_dpy *) data;
+ int count = 0;
+
+ if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR))
+ {
+ fprintf (stderr, "%s: Wayland connection closed\n", blurb());
+ if (state->atexit_cb)
+ (*state->atexit_cb) (state->atexit_closure);
+ exit (1);
+ }
+
+ if (mask & WL_EVENT_READABLE)
+ count = wl_display_dispatch (state->dpy);
+
+ if (mask & WL_EVENT_WRITABLE)
+ wl_display_flush (state->dpy);
+
+ if (mask == 0)
+ {
+ count = wl_display_dispatch_pending (state->dpy);
+ wl_display_flush (state->dpy);
+ }
+
+ return count;
+}
+
+
+/* Connects to Wayland and returns an opaque state object on success. */
+wayland_dpy *
+wayland_dpy_connect (void)
+{
+ wayland_dpy *state = (wayland_dpy *) calloc (sizeof (*state), 1);
+ state->dpy = wl_display_connect (NULL);
+ if (!state->dpy)
+ {
+ free (state);
+ return NULL;
+ }
+
+ if (verbose_p)
+ fprintf (stderr, "%s: wayland: server connected\n", blurb());
+
+ state->event_loop = wl_event_loop_create();
+
+ { /* Tell the event loop to select() on the display connection. */
+ struct wl_event_source *source =
+ wl_event_loop_add_fd (state->event_loop,
+ wl_display_get_fd (state->dpy),
+ WL_EVENT_READABLE, handle_event, state);
+ wl_event_source_check (source);
+ /* #### Do I need to free 'source'? */
+ }
+
+ wayland_dpy_process_events (state, 0);
+ return state;
+}
+
+int
+wayland_dpy_get_fd (wayland_dpy *state)
+{
+ return wl_display_get_fd (state->dpy);
+}
+
+
+static void
+sync_cb (void *data, struct wl_callback *cb, uint32_t serial)
+{
+ int *done = data;
+ *done = 1;
+ wl_callback_destroy (cb);
+}
+
+/* Handle any notifications from the Wayland server and run callbacks.
+ If sync_p, blocks until all outstanding events have been processed.
+ */
+void
+wayland_dpy_process_events (wayland_dpy *state, int sync_p)
+{
+ struct wl_callback *cb;
+ int done = 0, ret = 0;
+
+ /* Process all outstanding events without blocking. */
+ wl_event_loop_dispatch (state->event_loop, 0);
+
+ /* Block until we get our own ACK, meaning queue is flushed. */
+ if (sync_p)
+ {
+ static const struct wl_callback_listener listener = { sync_cb };
+ cb = wl_display_sync (state->dpy);
+ wl_callback_add_listener (cb, &listener, &done);
+ while (ret != -1 && !done)
+ ret = wl_display_dispatch (state->dpy);
+ if (!done)
+ wl_callback_destroy (cb);
+ }
+}
+
+void
+wayland_dpy_close (wayland_dpy *state)
+{
+ wl_display_disconnect (state->dpy);
+ if (state->event_loop)
+ wl_event_loop_destroy (state->event_loop);
+ free (state);
+ if (verbose_p)
+ fprintf (stderr, "%s: wayland: disconnected\n", blurb());
+}
+
+void
+wayland_dpy_atexit (wayland_dpy *dpy,
+ void (*cb) (void *closure),
+ void *closure)
+{
+ dpy->atexit_cb = cb;
+ dpy->atexit_closure = closure;
+}
--- /dev/null
+/* xscreensaver, Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#ifndef __XSCREENSAVER_WAYLAND_DPY_H__
+#define __XSCREENSAVER_WAYLAND_DPY_H__
+
+typedef struct wayland_dpy wayland_dpy;
+typedef struct wayland_idle wayland_idle;
+typedef struct wayland_dpms wayland_dpms;
+
+/* Connects to Wayland and returns a state object on success. */
+extern wayland_dpy *wayland_dpy_connect (void);
+
+/* Returns the file descriptor of the Wayland display connection.
+ You may select on this to see if it needs attention. */
+extern int wayland_dpy_get_fd (wayland_dpy *);
+
+/* Handle any notifications from the Wayland server and run callbacks.
+ If sync_p, blocks until all outstanding events have been processed.
+ */
+extern void wayland_dpy_process_events (wayland_dpy *, int sync_p);
+
+/* Run this callback when the Wayland server drops the connection. */
+extern void wayland_dpy_atexit (wayland_dpy *,
+ void (*cb) (void *closure),
+ void *closure);
+
+/* Shut it all down. */
+extern void wayland_dpy_close (wayland_dpy *);
+
+#endif /* __XSCREENSAVER_WAYLAND_DPY_H__ */
--- /dev/null
+/* xscreensaver, Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#ifndef __XSCREENSAVER_WAYLAND_DPYI_H__
+#define __XSCREENSAVER_WAYLAND_DPYI_H__
+
+#include "wayland-dpy.h"
+
+struct wayland_dpy {
+ struct wl_display *dpy;
+ struct wl_event_loop *event_loop;
+
+ void (*atexit_cb) (void *closure);
+ void *atexit_closure;
+};
+
+#endif /* __XSCREENSAVER_WAYLAND_DPYI_H__ */
*
* Detecting idleness via a connection to the Wayland server and the
* "idle-notify-v1" protocol: https://wayland.app/protocols/ext-idle-notify-v1
+ * If the Wayland server does not implement this protocol, XScreenSaver cannot
+ * function. KDE implements it, but GNOME does not.
*/
#ifdef HAVE_CONFIG_H
#include <stdio.h>
#include <ctype.h>
#include <string.h>
-/* #include <wayland-client-protocol.h> */
+
#include <wayland-client.h>
#include <wayland-server.h>
-/* #include <wayland-util.h> */
-#include "ext-idle-notify-v1-client-protocol.h"
-#include "idle-client-protocol.h"
-#include "wayland-idle.h"
+
#include "blurb.h"
+#include "wayland-dpyI.h"
+#include "wayland-idle.h"
+#include "wayland-protocols/ext-idle-notify-v1-client-protocol.h"
+#include "wayland-protocols/idle-client-protocol.h"
-struct wayland_state {
+struct wayland_idle {
+ wayland_dpy *parent;
struct wl_display *dpy;
struct wl_registry *reg;
struct wl_event_loop *event_loop;
static void
seat_handle_capabilities (void *data, struct wl_seat *seat, uint32_t caps)
{
- wayland_state *state = (wayland_state *) data;
+ wayland_idle *state = (wayland_idle *) data;
state->seat_caps = caps;
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: seat caps: 0x%02lX\n", blurb(),
+ fprintf (stderr, "%s: wayland: idle: seat caps: 0x%02lX\n", blurb(),
(unsigned long) caps);
}
static void
seat_handle_name (void *data, struct wl_seat *seat, const char *name)
{
- wayland_state *state = (wayland_state *) data;
+ wayland_idle *state = (wayland_idle *) data;
state->seat_name = strdup (name);
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: seat name: \"%s\"\n", blurb(), name);
+ fprintf (stderr, "%s: wayland: idle: seat name: \"%s\"\n", blurb(), name);
}
handle_global (void *data, struct wl_registry *reg,
uint32_t name, const char *iface, uint32_t version)
{
- wayland_state *state = (wayland_state *) data;
+ wayland_idle *state = (wayland_idle *) data;
if (!strcmp (iface, wl_seat_interface.name))
{
.capabilities = seat_handle_capabilities,
};
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: found: %s\n", blurb(), iface);
+ fprintf (stderr, "%s: wayland: idle: found: %s\n", blurb(), iface);
state->seat = wl_registry_bind (reg, name, &wl_seat_interface, version);
wl_seat_add_listener (state->seat, &seat_listener, state);
}
else if (!strcmp (iface, ext_idle_notifier_v1_interface.name))
{
if (verbose_p)
- fprintf (stderr, "%s: wayland: found: %s\n", blurb(), iface);
+ fprintf (stderr, "%s: wayland: idle: found: %s\n", blurb(), iface);
state->ext_idle_notifier =
wl_registry_bind (reg, name, &ext_idle_notifier_v1_interface, 1);
}
else if (!strcmp (iface, org_kde_kwin_idle_interface.name))
{
if (verbose_p)
- fprintf (stderr, "%s: wayland: found: %s\n", blurb(), iface);
+ fprintf (stderr, "%s: wayland: idle: found: %s\n", blurb(), iface);
state->kde_idle_manager =
wl_registry_bind (reg, name, &org_kde_kwin_idle_interface, 1);
}
static void
ext_handle_idled (void *data, struct ext_idle_notification_v1 *note)
{
- /* wayland_state *state = (wayland_state *) data; */
+ /* wayland_idle *state = (wayland_idle *) data; */
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: ext_idle: idle notification\n", blurb());
+ fprintf (stderr, "%s: wayland: idle: ext_idle notification\n", blurb());
}
/* Called when the user is no longer idle. */
static void
ext_handle_resumed (void *data, struct ext_idle_notification_v1 *note)
{
- wayland_state *state = (wayland_state *) data;
+ wayland_idle *state = (wayland_idle *) data;
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: ext_idle: active notification\n", blurb());
+ fprintf (stderr, "%s: wayland: idle: ext_idle active notification\n",
+ blurb());
(*state->activity_cb) (state->closure);
}
static void
kde_handle_idle (void *data, struct org_kde_kwin_idle_timeout *timer)
{
- /* wayland_state *state = (wayland_state *) data; */
+ /* wayland_idle *state = (wayland_idle *) data; */
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: kde_idle: idle notification\n", blurb());
+ fprintf (stderr, "%s: wayland: idle: kde_idle notification\n", blurb());
}
static void
kde_handle_resumed (void *data, struct org_kde_kwin_idle_timeout *timer)
{
- wayland_state *state = (wayland_state *) data;
+ wayland_idle *state = (wayland_idle *) data;
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: kde_idle: active notification\n", blurb());
+ fprintf (stderr, "%s: wayland: idle: kde_idle active notification\n",
+ blurb());
(*state->activity_cb) (state->closure);
}
static void
-destroy_timer (wayland_state *state)
+destroy_timer (wayland_idle *state)
{
if (state->ext_idle_notification)
{
ext_idle_notification_v1_destroy (state->ext_idle_notification);
state->ext_idle_notification = 0;
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: destroyed kde_idle timer\n", blurb());
+ fprintf (stderr, "%s: wayland: idle: destroyed kde_idle timer\n",
+ blurb());
}
if (state->kde_idle_timer)
{
org_kde_kwin_idle_timeout_release (state->kde_idle_timer);
state->kde_idle_timer = 0;
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: destroyed ext_idle timer\n", blurb());
+ fprintf (stderr, "%s: wayland: idle: destroyed ext_idle timer\n",
+ blurb());
}
}
static void
-register_timer (wayland_state *state, int timeout)
+register_timer (wayland_idle *state, int timeout)
{
destroy_timer (state);
if (state->ext_idle_notifier)
&ext_idle_notification_listener,
state);
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: registered ext_idle timer\n", blurb());
+ fprintf (stderr, "%s: wayland: idle: registered ext_idle timer\n",
+ blurb());
}
else
{
&kde_idle_timer_listener,
state);
if (verbose_p > 2)
- fprintf (stderr, "%s: wayland: registered kde_idle timer\n", blurb());
- }
-}
-
-
-/* Dispatch any events that have been read. */
-static int
-dpy_handle_event (int fd, uint32_t mask, void *data)
-{
- wayland_state *state = (wayland_state *) data;
- int count = 0;
-
- if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR))
- {
- /* Nothing good can come of this... */
+ fprintf (stderr, "%s: wayland: idle: registered kde_idle timer\n",
+ blurb());
}
-
- if (mask & WL_EVENT_READABLE)
- count = wl_display_dispatch (state->dpy);
-
- if (mask & WL_EVENT_WRITABLE)
- wl_display_flush (state->dpy);
-
- if (mask == 0)
- {
- count = wl_display_dispatch_pending (state->dpy);
- wl_display_flush (state->dpy);
- }
-
- return count;
}
-/* Connects to Wayland and returns an opaque state object on success.
- When user activity is detected, the callback will be run with the
- provided object as its argument. On failure, returns NULL and
- an error message.
+/* Binds to Wayland idle-detection protocols and returns an opaque state
+ object on success. When user activity is detected, the callback will
+ be run with the provided object as its argument.
*/
-wayland_state *
-wayland_idle_init (void (*activity_cb) (void *closure),
- void *closure,
- const char **error_ret)
+wayland_idle *
+wayland_idle_init (wayland_dpy *dpy,
+ void (*activity_cb) (void *closure),
+ void *closure)
{
- wayland_state *state = (wayland_state *) calloc (sizeof (*state), 1);
- state->activity_cb = activity_cb;
- state->closure = closure;
+ wayland_idle *state;
+ static const struct wl_registry_listener listener = {
+ .global = handle_global,
+ .global_remove = handle_global_remove,
+ };
- state->dpy = wl_display_connect (NULL);
- if (!state->dpy)
- {
- free (state);
- if (error_ret) *error_ret = "connection failed";
- return NULL;
- }
+ if (!dpy) return NULL;
- if (verbose_p)
- fprintf (stderr, "%s: wayland: server connected\n", blurb());
-
- state->reg = wl_display_get_registry (state->dpy);
+ state = (wayland_idle *) calloc (sizeof (*state), 1);
+ state->parent = dpy;
+ state->activity_cb = activity_cb;
+ state->closure = closure;
- {
- static const struct wl_registry_listener listener = {
- .global = handle_global,
- .global_remove = handle_global_remove,
- };
- wl_registry_add_listener (state->reg, &listener, state);
- }
+ state->reg = wl_display_get_registry (dpy->dpy);
+ wl_registry_add_listener (state->reg, &listener, state);
- wl_display_roundtrip (state->dpy); /* First time to register seats */
- wl_display_roundtrip (state->dpy); /* Second time to register timers */
+ /* It takes two round trips: first to register seats, then timers. */
+ wayland_dpy_process_events (dpy, true);
if (! state->seat)
{
wayland_idle_free (state);
- if (error_ret) *error_ret = "server has no seats";
+ fprintf (stderr, "%s: wayland: idle: server has no seats\n", blurb());
return NULL;
}
if (! (state->kde_idle_manager ||
state->ext_idle_notifier))
{
- static char err[300];
- sprintf (err, "server doesn't implement \"%.100s\" or \"%.100s\"",
+ fprintf (stderr,
+ "%s: wayland: idle: server doesn't implement \"%s\" or \"%s\"\n",
+ blurb(),
ext_idle_notifier_v1_interface.name,
org_kde_kwin_idle_interface.name);
wayland_idle_free (state);
- if (error_ret) *error_ret = err;
return NULL;
}
- state->event_loop = wl_event_loop_create();
-
- { /* Tell the event loop to select() on the display connection. */
- struct wl_event_source *source =
- wl_event_loop_add_fd (state->event_loop,
- wl_display_get_fd (state->dpy),
- WL_EVENT_READABLE,
- dpy_handle_event,
- state);
- wl_event_source_check (source);
- /* #### Do I need to free 'source'? */
- }
-
register_timer (state, 1000); /* milliseconds */
- wayland_idle_process_events (state);
-
- if (error_ret) *error_ret = 0;
return state;
}
-int
-wayland_idle_get_fd (wayland_state *state)
-{
- return wl_display_get_fd (state->dpy);
-}
-
-
-/* Handle any notifications from the Wayland server and run callbacks.
- */
-void
-wayland_idle_process_events (wayland_state *state)
-{
- /* Process all outstanding events without blocking. */
- wl_event_loop_dispatch (state->event_loop, 0);
-}
-
-
void
-wayland_idle_free (wayland_state *state)
+wayland_idle_free (wayland_idle *state)
{
- wl_display_disconnect (state->dpy);
- if (state->event_loop)
- wl_event_loop_destroy (state->event_loop);
if (state->seat_name)
free (state->seat_name);
+ /* #### state->reg ? */
+ /* #### state->seat ? */
+ /* #### state->ext_idle_notifier, etc ? */
free (state);
- if (verbose_p)
- fprintf (stderr, "%s: wayland: disconnected\n", blurb());
}
#ifndef __XSCREENSAVER_WAYLAND_IDLE_H__
#define __XSCREENSAVER_WAYLAND_IDLE_H__
-typedef struct wayland_state wayland_state;
-
-/* Connects to Wayland and returns an opaque state object on success.
- When user activity is detected, the callback will be run with the
- provided object as its argument. On failure, returns NULL and
- an error message.
+/* Binds to Wayland idle-detection protocols and returns an opaque state
+ object on success. When user activity is detected, the callback will
+ be run with the provided object as its argument.
*/
-extern wayland_state *
-wayland_idle_init (void (*activity_cb) (void *closure),
- void *closure,
- const char **error_ret);
-
-/* Returns the file descriptor of the Wayland display connection.
- You may select on this to see if it needs attention. */
-extern int wayland_idle_get_fd (wayland_state *);
-
-/* Handle any notifications from the Wayland server and run callbacks. */
-extern void wayland_idle_process_events (wayland_state *);
+extern wayland_idle *
+wayland_idle_init (wayland_dpy *dpy,
+ void (*activity_cb) (void *closure),
+ void *closure);
/* Shut it all down. */
-extern void wayland_idle_free (wayland_state *);
+extern void wayland_idle_free (wayland_idle *);
-#endif /* __XSCREENSAVER_WAYLAND_H__ */
+#endif /* __XSCREENSAVER_WAYLAND_IDLE_H__ */
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+#ifndef DPMS_CLIENT_PROTOCOL_H
+#define DPMS_CLIENT_PROTOCOL_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @page page_dpms The dpms protocol
+ * @section page_ifaces_dpms Interfaces
+ * - @subpage page_iface_org_kde_kwin_dpms_manager - Output dpms manager
+ * - @subpage page_iface_org_kde_kwin_dpms - Dpms for a wl_output
+ * @section page_copyright_dpms Copyright
+ * <pre>
+ *
+ * SPDX-FileCopyrightText: 2015 Martin Gräßlin
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ * </pre>
+ */
+struct org_kde_kwin_dpms;
+struct org_kde_kwin_dpms_manager;
+struct wl_output;
+
+#ifndef ORG_KDE_KWIN_DPMS_MANAGER_INTERFACE
+#define ORG_KDE_KWIN_DPMS_MANAGER_INTERFACE
+/**
+ * @page page_iface_org_kde_kwin_dpms_manager org_kde_kwin_dpms_manager
+ * @section page_iface_org_kde_kwin_dpms_manager_desc Description
+ *
+ * The Dpms manager allows to get a org_kde_kwin_dpms for a given wl_output.
+ * The org_kde_kwin_dpms provides the currently used VESA Display Power Management
+ * Signaling state (see https://en.wikipedia.org/wiki/VESA_Display_Power_Management_Signaling ).
+ * In addition it allows to request a state change. A compositor is not obliged to honor it
+ * and will normally automatically switch back to on state.
+ * @section page_iface_org_kde_kwin_dpms_manager_api API
+ * See @ref iface_org_kde_kwin_dpms_manager.
+ */
+/**
+ * @defgroup iface_org_kde_kwin_dpms_manager The org_kde_kwin_dpms_manager interface
+ *
+ * The Dpms manager allows to get a org_kde_kwin_dpms for a given wl_output.
+ * The org_kde_kwin_dpms provides the currently used VESA Display Power Management
+ * Signaling state (see https://en.wikipedia.org/wiki/VESA_Display_Power_Management_Signaling ).
+ * In addition it allows to request a state change. A compositor is not obliged to honor it
+ * and will normally automatically switch back to on state.
+ */
+extern const struct wl_interface org_kde_kwin_dpms_manager_interface;
+#endif
+#ifndef ORG_KDE_KWIN_DPMS_INTERFACE
+#define ORG_KDE_KWIN_DPMS_INTERFACE
+/**
+ * @page page_iface_org_kde_kwin_dpms org_kde_kwin_dpms
+ * @section page_iface_org_kde_kwin_dpms_desc Description
+ *
+ * This interface provides information about the VESA DPMS state for a wl_output.
+ * It gets created through the request get on the org_kde_kwin_dpms_manager interface.
+ *
+ * On creating the resource the server will push whether DPSM is supported for the output,
+ * the currently used DPMS state and notifies the client through the done event once all
+ * states are pushed. Whenever a state changes the set of changes is committed with the
+ * done event.
+ * @section page_iface_org_kde_kwin_dpms_api API
+ * See @ref iface_org_kde_kwin_dpms.
+ */
+/**
+ * @defgroup iface_org_kde_kwin_dpms The org_kde_kwin_dpms interface
+ *
+ * This interface provides information about the VESA DPMS state for a wl_output.
+ * It gets created through the request get on the org_kde_kwin_dpms_manager interface.
+ *
+ * On creating the resource the server will push whether DPSM is supported for the output,
+ * the currently used DPMS state and notifies the client through the done event once all
+ * states are pushed. Whenever a state changes the set of changes is committed with the
+ * done event.
+ */
+extern const struct wl_interface org_kde_kwin_dpms_interface;
+#endif
+
+#define ORG_KDE_KWIN_DPMS_MANAGER_GET 0
+
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms_manager
+ */
+#define ORG_KDE_KWIN_DPMS_MANAGER_GET_SINCE_VERSION 1
+
+/** @ingroup iface_org_kde_kwin_dpms_manager */
+static inline void
+org_kde_kwin_dpms_manager_set_user_data(struct org_kde_kwin_dpms_manager *org_kde_kwin_dpms_manager, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) org_kde_kwin_dpms_manager, user_data);
+}
+
+/** @ingroup iface_org_kde_kwin_dpms_manager */
+static inline void *
+org_kde_kwin_dpms_manager_get_user_data(struct org_kde_kwin_dpms_manager *org_kde_kwin_dpms_manager)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) org_kde_kwin_dpms_manager);
+}
+
+static inline uint32_t
+org_kde_kwin_dpms_manager_get_version(struct org_kde_kwin_dpms_manager *org_kde_kwin_dpms_manager)
+{
+ return wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_dpms_manager);
+}
+
+/** @ingroup iface_org_kde_kwin_dpms_manager */
+static inline void
+org_kde_kwin_dpms_manager_destroy(struct org_kde_kwin_dpms_manager *org_kde_kwin_dpms_manager)
+{
+ wl_proxy_destroy((struct wl_proxy *) org_kde_kwin_dpms_manager);
+}
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms_manager
+ *
+ * Factory request to get the org_kde_kwin_dpms for a given wl_output.
+ */
+static inline struct org_kde_kwin_dpms *
+org_kde_kwin_dpms_manager_get(struct org_kde_kwin_dpms_manager *org_kde_kwin_dpms_manager, struct wl_output *output)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_dpms_manager,
+ ORG_KDE_KWIN_DPMS_MANAGER_GET, &org_kde_kwin_dpms_interface, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_dpms_manager), 0, NULL, output);
+
+ return (struct org_kde_kwin_dpms *) id;
+}
+
+#ifndef ORG_KDE_KWIN_DPMS_MODE_ENUM
+#define ORG_KDE_KWIN_DPMS_MODE_ENUM
+enum org_kde_kwin_dpms_mode {
+ ORG_KDE_KWIN_DPMS_MODE_ON = 0,
+ ORG_KDE_KWIN_DPMS_MODE_STANDBY = 1,
+ ORG_KDE_KWIN_DPMS_MODE_SUSPEND = 2,
+ ORG_KDE_KWIN_DPMS_MODE_OFF = 3,
+};
+#endif /* ORG_KDE_KWIN_DPMS_MODE_ENUM */
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ * @struct org_kde_kwin_dpms_listener
+ */
+struct org_kde_kwin_dpms_listener {
+ /**
+ * Event indicating whether DPMS is supported on the wl_output
+ *
+ * This event gets pushed on binding the resource and indicates
+ * whether the wl_output supports DPMS. There are operation modes
+ * of a Wayland server where DPMS might not make sense (e.g. nested
+ * compositors).
+ * @param supported Boolean value whether DPMS is supported (1) for the wl_output or not (0)
+ */
+ void (*supported)(void *data,
+ struct org_kde_kwin_dpms *org_kde_kwin_dpms,
+ uint32_t supported);
+ /**
+ * Event indicating used DPMS mode
+ *
+ * This mode gets pushed on binding the resource and provides the
+ * currently used DPMS mode. It also gets pushed if DPMS is not
+ * supported for the wl_output, in that case the value will be On.
+ *
+ * The event is also pushed whenever the state changes.
+ * @param mode The new currently used mode
+ */
+ void (*mode)(void *data,
+ struct org_kde_kwin_dpms *org_kde_kwin_dpms,
+ uint32_t mode);
+ /**
+ * All changes are pushed
+ *
+ * This event gets pushed on binding the resource once all other
+ * states are pushed.
+ *
+ * In addition it gets pushed whenever a state changes to tell the
+ * client that all state changes have been pushed.
+ */
+ void (*done)(void *data,
+ struct org_kde_kwin_dpms *org_kde_kwin_dpms);
+};
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ */
+static inline int
+org_kde_kwin_dpms_add_listener(struct org_kde_kwin_dpms *org_kde_kwin_dpms,
+ const struct org_kde_kwin_dpms_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) org_kde_kwin_dpms,
+ (void (**)(void)) listener, data);
+}
+
+#define ORG_KDE_KWIN_DPMS_SET 0
+#define ORG_KDE_KWIN_DPMS_RELEASE 1
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ */
+#define ORG_KDE_KWIN_DPMS_SUPPORTED_SINCE_VERSION 1
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ */
+#define ORG_KDE_KWIN_DPMS_MODE_SINCE_VERSION 1
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ */
+#define ORG_KDE_KWIN_DPMS_DONE_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ */
+#define ORG_KDE_KWIN_DPMS_SET_SINCE_VERSION 1
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ */
+#define ORG_KDE_KWIN_DPMS_RELEASE_SINCE_VERSION 1
+
+/** @ingroup iface_org_kde_kwin_dpms */
+static inline void
+org_kde_kwin_dpms_set_user_data(struct org_kde_kwin_dpms *org_kde_kwin_dpms, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) org_kde_kwin_dpms, user_data);
+}
+
+/** @ingroup iface_org_kde_kwin_dpms */
+static inline void *
+org_kde_kwin_dpms_get_user_data(struct org_kde_kwin_dpms *org_kde_kwin_dpms)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) org_kde_kwin_dpms);
+}
+
+static inline uint32_t
+org_kde_kwin_dpms_get_version(struct org_kde_kwin_dpms *org_kde_kwin_dpms)
+{
+ return wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_dpms);
+}
+
+/** @ingroup iface_org_kde_kwin_dpms */
+static inline void
+org_kde_kwin_dpms_destroy(struct org_kde_kwin_dpms *org_kde_kwin_dpms)
+{
+ wl_proxy_destroy((struct wl_proxy *) org_kde_kwin_dpms);
+}
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ *
+ * Requests that the compositor puts the wl_output into the passed mode. The compositor
+ * is not obliged to change the state. In addition the compositor might leave the mode
+ * whenever it seems suitable. E.g. the compositor might return to On state on user input.
+ *
+ * The client should not assume that the mode changed after requesting a new mode.
+ * Instead the client should listen for the mode event.
+ */
+static inline void
+org_kde_kwin_dpms_set(struct org_kde_kwin_dpms *org_kde_kwin_dpms, uint32_t mode)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_dpms,
+ ORG_KDE_KWIN_DPMS_SET, NULL, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_dpms), 0, mode);
+}
+
+/**
+ * @ingroup iface_org_kde_kwin_dpms
+ */
+static inline void
+org_kde_kwin_dpms_release(struct org_kde_kwin_dpms *org_kde_kwin_dpms)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_dpms,
+ ORG_KDE_KWIN_DPMS_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_dpms), WL_MARSHAL_FLAG_DESTROY);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+/*
+ * SPDX-FileCopyrightText: 2015 Martin Gräßlin
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
+#endif
+
+#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
+#define WL_PRIVATE __attribute__ ((visibility("hidden")))
+#else
+#define WL_PRIVATE
+#endif
+
+extern const struct wl_interface org_kde_kwin_dpms_interface;
+extern const struct wl_interface wl_output_interface;
+
+static const struct wl_interface *dpms_types[] = {
+ NULL,
+ &org_kde_kwin_dpms_interface,
+ &wl_output_interface,
+};
+
+static const struct wl_message org_kde_kwin_dpms_manager_requests[] = {
+ { "get", "no", dpms_types + 1 },
+};
+
+WL_PRIVATE const struct wl_interface org_kde_kwin_dpms_manager_interface = {
+ "org_kde_kwin_dpms_manager", 1,
+ 1, org_kde_kwin_dpms_manager_requests,
+ 0, NULL,
+};
+
+static const struct wl_message org_kde_kwin_dpms_requests[] = {
+ { "set", "u", dpms_types + 0 },
+ { "release", "", dpms_types + 0 },
+};
+
+static const struct wl_message org_kde_kwin_dpms_events[] = {
+ { "supported", "u", dpms_types + 0 },
+ { "mode", "u", dpms_types + 0 },
+ { "done", "", dpms_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface org_kde_kwin_dpms_interface = {
+ "org_kde_kwin_dpms", 1,
+ 2, org_kde_kwin_dpms_requests,
+ 3, org_kde_kwin_dpms_events,
+};
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="dpms">
+ <copyright><![CDATA[
+ SPDX-FileCopyrightText: 2015 Martin Gräßlin
+
+ SPDX-License-Identifier: LGPL-2.1-or-later
+ ]]></copyright>
+ <interface name="org_kde_kwin_dpms_manager" version="1">
+ <description summary="Output dpms manager">
+ The Dpms manager allows to get a org_kde_kwin_dpms for a given wl_output.
+ The org_kde_kwin_dpms provides the currently used VESA Display Power Management
+ Signaling state (see https://en.wikipedia.org/wiki/VESA_Display_Power_Management_Signaling ).
+ In addition it allows to request a state change. A compositor is not obliged to honor it
+ and will normally automatically switch back to on state.
+ </description>
+ <request name="get">
+ <description summary="Get org_kde_kwin_dpms for wl_output">
+ Factory request to get the org_kde_kwin_dpms for a given wl_output.
+ </description>
+ <arg name="id" type="new_id" interface="org_kde_kwin_dpms"/>
+ <arg name="output" type="object" interface="wl_output"/>
+ </request>
+ </interface>
+ <interface name="org_kde_kwin_dpms" version="1">
+ <description summary="Dpms for a wl_output">
+ This interface provides information about the VESA DPMS state for a wl_output.
+ It gets created through the request get on the org_kde_kwin_dpms_manager interface.
+
+ On creating the resource the server will push whether DPSM is supported for the output,
+ the currently used DPMS state and notifies the client through the done event once all
+ states are pushed. Whenever a state changes the set of changes is committed with the
+ done event.
+ </description>
+ <event name="supported">
+ <description summary="Event indicating whether DPMS is supported on the wl_output">
+ This event gets pushed on binding the resource and indicates whether the wl_output
+ supports DPMS. There are operation modes of a Wayland server where DPMS might not
+ make sense (e.g. nested compositors).
+ </description>
+ <arg name="supported" type="uint" summary="Boolean value whether DPMS is supported (1) for the wl_output or not (0)"/>
+ </event>
+ <enum name="mode">
+ <entry name="On" value="0"/>
+ <entry name="Standby" value="1"/>
+ <entry name="Suspend" value="2"/>
+ <entry name="Off" value="3"/>
+ </enum>
+ <event name="mode">
+ <description summary="Event indicating used DPMS mode">
+ This mode gets pushed on binding the resource and provides the currently used
+ DPMS mode. It also gets pushed if DPMS is not supported for the wl_output, in that
+ case the value will be On.
+
+ The event is also pushed whenever the state changes.
+ </description>
+ <arg name="mode" type="uint" summary="The new currently used mode"/>
+ </event>
+ <event name="done">
+ <description summary="All changes are pushed">
+ This event gets pushed on binding the resource once all other states are pushed.
+
+ In addition it gets pushed whenever a state changes to tell the client that all
+ state changes have been pushed.
+ </description>
+ </event>
+ <request name="set">
+ <description summary="Request DPMS state change for the wl_output">
+ Requests that the compositor puts the wl_output into the passed mode. The compositor
+ is not obliged to change the state. In addition the compositor might leave the mode
+ whenever it seems suitable. E.g. the compositor might return to On state on user input.
+
+ The client should not assume that the mode changed after requesting a new mode.
+ Instead the client should listen for the mode event.
+ </description>
+ <arg name="mode" type="uint" summary="Requested mode"/>
+ </request>
+ <request name="release" type="destructor">
+ <description summary="release the dpms object"/>
+ </request>
+ </interface>
+</protocol>
+
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+#ifndef EXT_IDLE_NOTIFY_V1_CLIENT_PROTOCOL_H
+#define EXT_IDLE_NOTIFY_V1_CLIENT_PROTOCOL_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @page page_ext_idle_notify_v1 The ext_idle_notify_v1 protocol
+ * @section page_ifaces_ext_idle_notify_v1 Interfaces
+ * - @subpage page_iface_ext_idle_notifier_v1 - idle notification manager
+ * - @subpage page_iface_ext_idle_notification_v1 - idle notification
+ * @section page_copyright_ext_idle_notify_v1 Copyright
+ * <pre>
+ *
+ * Copyright © 2015 Martin Gräßlin
+ * Copyright © 2022 Simon Ser
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * </pre>
+ */
+struct ext_idle_notification_v1;
+struct ext_idle_notifier_v1;
+struct wl_seat;
+
+#ifndef EXT_IDLE_NOTIFIER_V1_INTERFACE
+#define EXT_IDLE_NOTIFIER_V1_INTERFACE
+/**
+ * @page page_iface_ext_idle_notifier_v1 ext_idle_notifier_v1
+ * @section page_iface_ext_idle_notifier_v1_desc Description
+ *
+ * This interface allows clients to monitor user idle status.
+ *
+ * After binding to this global, clients can create ext_idle_notification_v1
+ * objects to get notified when the user is idle for a given amount of time.
+ * @section page_iface_ext_idle_notifier_v1_api API
+ * See @ref iface_ext_idle_notifier_v1.
+ */
+/**
+ * @defgroup iface_ext_idle_notifier_v1 The ext_idle_notifier_v1 interface
+ *
+ * This interface allows clients to monitor user idle status.
+ *
+ * After binding to this global, clients can create ext_idle_notification_v1
+ * objects to get notified when the user is idle for a given amount of time.
+ */
+extern const struct wl_interface ext_idle_notifier_v1_interface;
+#endif
+#ifndef EXT_IDLE_NOTIFICATION_V1_INTERFACE
+#define EXT_IDLE_NOTIFICATION_V1_INTERFACE
+/**
+ * @page page_iface_ext_idle_notification_v1 ext_idle_notification_v1
+ * @section page_iface_ext_idle_notification_v1_desc Description
+ *
+ * This interface is used by the compositor to send idle notification events
+ * to clients.
+ *
+ * Initially the notification object is not idle. The notification object
+ * becomes idle when no user activity has happened for at least the timeout
+ * duration, starting from the creation of the notification object. User
+ * activity may include input events or a presence sensor, but is
+ * compositor-specific.
+ *
+ * How this notification responds to idle inhibitors depends on how
+ * it was constructed. If constructed from the
+ * get_idle_notification request, then if an idle inhibitor is
+ * active (e.g. another client has created a zwp_idle_inhibitor_v1
+ * on a visible surface), the compositor must not make the
+ * notification object idle. However, if constructed from the
+ * get_input_idle_notification request, then idle inhibitors are
+ * ignored, and only input from the user, e.g. from a keyboard or
+ * mouse, counts as activity.
+ *
+ * When the notification object becomes idle, an idled event is sent. When
+ * user activity starts again, the notification object stops being idle,
+ * a resumed event is sent and the timeout is restarted.
+ * @section page_iface_ext_idle_notification_v1_api API
+ * See @ref iface_ext_idle_notification_v1.
+ */
+/**
+ * @defgroup iface_ext_idle_notification_v1 The ext_idle_notification_v1 interface
+ *
+ * This interface is used by the compositor to send idle notification events
+ * to clients.
+ *
+ * Initially the notification object is not idle. The notification object
+ * becomes idle when no user activity has happened for at least the timeout
+ * duration, starting from the creation of the notification object. User
+ * activity may include input events or a presence sensor, but is
+ * compositor-specific.
+ *
+ * How this notification responds to idle inhibitors depends on how
+ * it was constructed. If constructed from the
+ * get_idle_notification request, then if an idle inhibitor is
+ * active (e.g. another client has created a zwp_idle_inhibitor_v1
+ * on a visible surface), the compositor must not make the
+ * notification object idle. However, if constructed from the
+ * get_input_idle_notification request, then idle inhibitors are
+ * ignored, and only input from the user, e.g. from a keyboard or
+ * mouse, counts as activity.
+ *
+ * When the notification object becomes idle, an idled event is sent. When
+ * user activity starts again, the notification object stops being idle,
+ * a resumed event is sent and the timeout is restarted.
+ */
+extern const struct wl_interface ext_idle_notification_v1_interface;
+#endif
+
+#define EXT_IDLE_NOTIFIER_V1_DESTROY 0
+#define EXT_IDLE_NOTIFIER_V1_GET_IDLE_NOTIFICATION 1
+#define EXT_IDLE_NOTIFIER_V1_GET_INPUT_IDLE_NOTIFICATION 2
+
+
+/**
+ * @ingroup iface_ext_idle_notifier_v1
+ */
+#define EXT_IDLE_NOTIFIER_V1_DESTROY_SINCE_VERSION 1
+/**
+ * @ingroup iface_ext_idle_notifier_v1
+ */
+#define EXT_IDLE_NOTIFIER_V1_GET_IDLE_NOTIFICATION_SINCE_VERSION 1
+/**
+ * @ingroup iface_ext_idle_notifier_v1
+ */
+#define EXT_IDLE_NOTIFIER_V1_GET_INPUT_IDLE_NOTIFICATION_SINCE_VERSION 2
+
+/** @ingroup iface_ext_idle_notifier_v1 */
+static inline void
+ext_idle_notifier_v1_set_user_data(struct ext_idle_notifier_v1 *ext_idle_notifier_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) ext_idle_notifier_v1, user_data);
+}
+
+/** @ingroup iface_ext_idle_notifier_v1 */
+static inline void *
+ext_idle_notifier_v1_get_user_data(struct ext_idle_notifier_v1 *ext_idle_notifier_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) ext_idle_notifier_v1);
+}
+
+static inline uint32_t
+ext_idle_notifier_v1_get_version(struct ext_idle_notifier_v1 *ext_idle_notifier_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1);
+}
+
+/**
+ * @ingroup iface_ext_idle_notifier_v1
+ *
+ * Destroy the manager object. All objects created via this interface
+ * remain valid.
+ */
+static inline void
+ext_idle_notifier_v1_destroy(struct ext_idle_notifier_v1 *ext_idle_notifier_v1)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notifier_v1,
+ EXT_IDLE_NOTIFIER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1), WL_MARSHAL_FLAG_DESTROY);
+}
+
+/**
+ * @ingroup iface_ext_idle_notifier_v1
+ *
+ * Create a new idle notification object.
+ *
+ * The notification object has a minimum timeout duration and is tied to a
+ * seat. The client will be notified if the seat is inactive for at least
+ * the provided timeout. See ext_idle_notification_v1 for more details.
+ *
+ * A zero timeout is valid and means the client wants to be notified as
+ * soon as possible when the seat is inactive.
+ */
+static inline struct ext_idle_notification_v1 *
+ext_idle_notifier_v1_get_idle_notification(struct ext_idle_notifier_v1 *ext_idle_notifier_v1, uint32_t timeout, struct wl_seat *seat)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notifier_v1,
+ EXT_IDLE_NOTIFIER_V1_GET_IDLE_NOTIFICATION, &ext_idle_notification_v1_interface, wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1), 0, NULL, timeout, seat);
+
+ return (struct ext_idle_notification_v1 *) id;
+}
+
+/**
+ * @ingroup iface_ext_idle_notifier_v1
+ *
+ * Create a new idle notification object to track input from the
+ * user, such as keyboard and mouse movement. Because this object is
+ * meant to track user input alone, it ignores idle inhibitors.
+ *
+ * The notification object has a minimum timeout duration and is tied to a
+ * seat. The client will be notified if the seat is inactive for at least
+ * the provided timeout. See ext_idle_notification_v1 for more details.
+ *
+ * A zero timeout is valid and means the client wants to be notified as
+ * soon as possible when the seat is inactive.
+ */
+static inline struct ext_idle_notification_v1 *
+ext_idle_notifier_v1_get_input_idle_notification(struct ext_idle_notifier_v1 *ext_idle_notifier_v1, uint32_t timeout, struct wl_seat *seat)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notifier_v1,
+ EXT_IDLE_NOTIFIER_V1_GET_INPUT_IDLE_NOTIFICATION, &ext_idle_notification_v1_interface, wl_proxy_get_version((struct wl_proxy *) ext_idle_notifier_v1), 0, NULL, timeout, seat);
+
+ return (struct ext_idle_notification_v1 *) id;
+}
+
+/**
+ * @ingroup iface_ext_idle_notification_v1
+ * @struct ext_idle_notification_v1_listener
+ */
+struct ext_idle_notification_v1_listener {
+ /**
+ * notification object is idle
+ *
+ * This event is sent when the notification object becomes idle.
+ *
+ * It's a compositor protocol error to send this event twice
+ * without a resumed event in-between.
+ */
+ void (*idled)(void *data,
+ struct ext_idle_notification_v1 *ext_idle_notification_v1);
+ /**
+ * notification object is no longer idle
+ *
+ * This event is sent when the notification object stops being
+ * idle.
+ *
+ * It's a compositor protocol error to send this event twice
+ * without an idled event in-between. It's a compositor protocol
+ * error to send this event prior to any idled event.
+ */
+ void (*resumed)(void *data,
+ struct ext_idle_notification_v1 *ext_idle_notification_v1);
+};
+
+/**
+ * @ingroup iface_ext_idle_notification_v1
+ */
+static inline int
+ext_idle_notification_v1_add_listener(struct ext_idle_notification_v1 *ext_idle_notification_v1,
+ const struct ext_idle_notification_v1_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) ext_idle_notification_v1,
+ (void (**)(void)) listener, data);
+}
+
+#define EXT_IDLE_NOTIFICATION_V1_DESTROY 0
+
+/**
+ * @ingroup iface_ext_idle_notification_v1
+ */
+#define EXT_IDLE_NOTIFICATION_V1_IDLED_SINCE_VERSION 1
+/**
+ * @ingroup iface_ext_idle_notification_v1
+ */
+#define EXT_IDLE_NOTIFICATION_V1_RESUMED_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_ext_idle_notification_v1
+ */
+#define EXT_IDLE_NOTIFICATION_V1_DESTROY_SINCE_VERSION 1
+
+/** @ingroup iface_ext_idle_notification_v1 */
+static inline void
+ext_idle_notification_v1_set_user_data(struct ext_idle_notification_v1 *ext_idle_notification_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) ext_idle_notification_v1, user_data);
+}
+
+/** @ingroup iface_ext_idle_notification_v1 */
+static inline void *
+ext_idle_notification_v1_get_user_data(struct ext_idle_notification_v1 *ext_idle_notification_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) ext_idle_notification_v1);
+}
+
+static inline uint32_t
+ext_idle_notification_v1_get_version(struct ext_idle_notification_v1 *ext_idle_notification_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) ext_idle_notification_v1);
+}
+
+/**
+ * @ingroup iface_ext_idle_notification_v1
+ *
+ * Destroy the notification object.
+ */
+static inline void
+ext_idle_notification_v1_destroy(struct ext_idle_notification_v1 *ext_idle_notification_v1)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) ext_idle_notification_v1,
+ EXT_IDLE_NOTIFICATION_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_idle_notification_v1), WL_MARSHAL_FLAG_DESTROY);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+/*
+ * Copyright © 2015 Martin Gräßlin
+ * Copyright © 2022 Simon Ser
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
+#endif
+
+#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
+#define WL_PRIVATE __attribute__ ((visibility("hidden")))
+#else
+#define WL_PRIVATE
+#endif
+
+extern const struct wl_interface ext_idle_notification_v1_interface;
+extern const struct wl_interface wl_seat_interface;
+
+static const struct wl_interface *ext_idle_notify_v1_types[] = {
+ &ext_idle_notification_v1_interface,
+ NULL,
+ &wl_seat_interface,
+ &ext_idle_notification_v1_interface,
+ NULL,
+ &wl_seat_interface,
+};
+
+static const struct wl_message ext_idle_notifier_v1_requests[] = {
+ { "destroy", "", ext_idle_notify_v1_types + 0 },
+ { "get_idle_notification", "nuo", ext_idle_notify_v1_types + 0 },
+ { "get_input_idle_notification", "2nuo", ext_idle_notify_v1_types + 3 },
+};
+
+WL_PRIVATE const struct wl_interface ext_idle_notifier_v1_interface = {
+ "ext_idle_notifier_v1", 2,
+ 3, ext_idle_notifier_v1_requests,
+ 0, NULL,
+};
+
+static const struct wl_message ext_idle_notification_v1_requests[] = {
+ { "destroy", "", ext_idle_notify_v1_types + 0 },
+};
+
+static const struct wl_message ext_idle_notification_v1_events[] = {
+ { "idled", "", ext_idle_notify_v1_types + 0 },
+ { "resumed", "", ext_idle_notify_v1_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface ext_idle_notification_v1_interface = {
+ "ext_idle_notification_v1", 2,
+ 1, ext_idle_notification_v1_requests,
+ 2, ext_idle_notification_v1_events,
+};
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="ext_idle_notify_v1">
+ <copyright>
+ Copyright © 2015 Martin Gräßlin
+ Copyright © 2022 Simon Ser
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="ext_idle_notifier_v1" version="2">
+ <description summary="idle notification manager">
+ This interface allows clients to monitor user idle status.
+
+ After binding to this global, clients can create ext_idle_notification_v1
+ objects to get notified when the user is idle for a given amount of time.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the manager">
+ Destroy the manager object. All objects created via this interface
+ remain valid.
+ </description>
+ </request>
+
+ <request name="get_idle_notification">
+ <description summary="create a notification object">
+ Create a new idle notification object.
+
+ The notification object has a minimum timeout duration and is tied to a
+ seat. The client will be notified if the seat is inactive for at least
+ the provided timeout. See ext_idle_notification_v1 for more details.
+
+ A zero timeout is valid and means the client wants to be notified as
+ soon as possible when the seat is inactive.
+ </description>
+ <arg name="id" type="new_id" interface="ext_idle_notification_v1"/>
+ <arg name="timeout" type="uint" summary="minimum idle timeout in msec"/>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ </request>
+
+ <!-- Version 2 additions -->
+
+ <request name="get_input_idle_notification" since="2">
+ <description summary="create a notification object">
+ Create a new idle notification object to track input from the
+ user, such as keyboard and mouse movement. Because this object is
+ meant to track user input alone, it ignores idle inhibitors.
+
+ The notification object has a minimum timeout duration and is tied to a
+ seat. The client will be notified if the seat is inactive for at least
+ the provided timeout. See ext_idle_notification_v1 for more details.
+
+ A zero timeout is valid and means the client wants to be notified as
+ soon as possible when the seat is inactive.
+ </description>
+ <arg name="id" type="new_id" interface="ext_idle_notification_v1"/>
+ <arg name="timeout" type="uint" summary="minimum idle timeout in msec"/>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ </request>
+
+ </interface>
+
+ <interface name="ext_idle_notification_v1" version="2">
+ <description summary="idle notification">
+ This interface is used by the compositor to send idle notification events
+ to clients.
+
+ Initially the notification object is not idle. The notification object
+ becomes idle when no user activity has happened for at least the timeout
+ duration, starting from the creation of the notification object. User
+ activity may include input events or a presence sensor, but is
+ compositor-specific.
+
+ How this notification responds to idle inhibitors depends on how
+ it was constructed. If constructed from the
+ get_idle_notification request, then if an idle inhibitor is
+ active (e.g. another client has created a zwp_idle_inhibitor_v1
+ on a visible surface), the compositor must not make the
+ notification object idle. However, if constructed from the
+ get_input_idle_notification request, then idle inhibitors are
+ ignored, and only input from the user, e.g. from a keyboard or
+ mouse, counts as activity.
+
+ When the notification object becomes idle, an idled event is sent. When
+ user activity starts again, the notification object stops being idle,
+ a resumed event is sent and the timeout is restarted.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the notification object">
+ Destroy the notification object.
+ </description>
+ </request>
+
+ <event name="idled">
+ <description summary="notification object is idle">
+ This event is sent when the notification object becomes idle.
+
+ It's a compositor protocol error to send this event twice without a
+ resumed event in-between.
+ </description>
+ </event>
+
+ <event name="resumed">
+ <description summary="notification object is no longer idle">
+ This event is sent when the notification object stops being idle.
+
+ It's a compositor protocol error to send this event twice without an
+ idled event in-between. It's a compositor protocol error to send this
+ event prior to any idled event.
+ </description>
+ </event>
+ </interface>
+</protocol>
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+#ifndef IDLE_CLIENT_PROTOCOL_H
+#define IDLE_CLIENT_PROTOCOL_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @page page_idle The idle protocol
+ * @section page_ifaces_idle Interfaces
+ * - @subpage page_iface_org_kde_kwin_idle - User idle time manager
+ * - @subpage page_iface_org_kde_kwin_idle_timeout -
+ * @section page_copyright_idle Copyright
+ * <pre>
+ *
+ * Copyright (C) 2015 Martin Gräßlin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * </pre>
+ */
+struct org_kde_kwin_idle;
+struct org_kde_kwin_idle_timeout;
+struct wl_seat;
+
+#ifndef ORG_KDE_KWIN_IDLE_INTERFACE
+#define ORG_KDE_KWIN_IDLE_INTERFACE
+/**
+ * @page page_iface_org_kde_kwin_idle org_kde_kwin_idle
+ * @section page_iface_org_kde_kwin_idle_desc Description
+ *
+ * This interface allows to monitor user idle time on a given seat. The interface
+ * allows to register timers which trigger after no user activity was registered
+ * on the seat for a given interval. It notifies when user activity resumes.
+ *
+ * This is useful for applications wanting to perform actions when the user is not
+ * interacting with the system, e.g. chat applications setting the user as away, power
+ * management features to dim screen, etc..
+ * @section page_iface_org_kde_kwin_idle_api API
+ * See @ref iface_org_kde_kwin_idle.
+ */
+/**
+ * @defgroup iface_org_kde_kwin_idle The org_kde_kwin_idle interface
+ *
+ * This interface allows to monitor user idle time on a given seat. The interface
+ * allows to register timers which trigger after no user activity was registered
+ * on the seat for a given interval. It notifies when user activity resumes.
+ *
+ * This is useful for applications wanting to perform actions when the user is not
+ * interacting with the system, e.g. chat applications setting the user as away, power
+ * management features to dim screen, etc..
+ */
+extern const struct wl_interface org_kde_kwin_idle_interface;
+#endif
+#ifndef ORG_KDE_KWIN_IDLE_TIMEOUT_INTERFACE
+#define ORG_KDE_KWIN_IDLE_TIMEOUT_INTERFACE
+/**
+ * @page page_iface_org_kde_kwin_idle_timeout org_kde_kwin_idle_timeout
+ * @section page_iface_org_kde_kwin_idle_timeout_api API
+ * See @ref iface_org_kde_kwin_idle_timeout.
+ */
+/**
+ * @defgroup iface_org_kde_kwin_idle_timeout The org_kde_kwin_idle_timeout interface
+ */
+extern const struct wl_interface org_kde_kwin_idle_timeout_interface;
+#endif
+
+#define ORG_KDE_KWIN_IDLE_GET_IDLE_TIMEOUT 0
+
+
+/**
+ * @ingroup iface_org_kde_kwin_idle
+ */
+#define ORG_KDE_KWIN_IDLE_GET_IDLE_TIMEOUT_SINCE_VERSION 1
+
+/** @ingroup iface_org_kde_kwin_idle */
+static inline void
+org_kde_kwin_idle_set_user_data(struct org_kde_kwin_idle *org_kde_kwin_idle, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) org_kde_kwin_idle, user_data);
+}
+
+/** @ingroup iface_org_kde_kwin_idle */
+static inline void *
+org_kde_kwin_idle_get_user_data(struct org_kde_kwin_idle *org_kde_kwin_idle)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) org_kde_kwin_idle);
+}
+
+static inline uint32_t
+org_kde_kwin_idle_get_version(struct org_kde_kwin_idle *org_kde_kwin_idle)
+{
+ return wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle);
+}
+
+/** @ingroup iface_org_kde_kwin_idle */
+static inline void
+org_kde_kwin_idle_destroy(struct org_kde_kwin_idle *org_kde_kwin_idle)
+{
+ wl_proxy_destroy((struct wl_proxy *) org_kde_kwin_idle);
+}
+
+/**
+ * @ingroup iface_org_kde_kwin_idle
+ */
+static inline struct org_kde_kwin_idle_timeout *
+org_kde_kwin_idle_get_idle_timeout(struct org_kde_kwin_idle *org_kde_kwin_idle, struct wl_seat *seat, uint32_t timeout)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_idle,
+ ORG_KDE_KWIN_IDLE_GET_IDLE_TIMEOUT, &org_kde_kwin_idle_timeout_interface, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle), 0, NULL, seat, timeout);
+
+ return (struct org_kde_kwin_idle_timeout *) id;
+}
+
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ * @struct org_kde_kwin_idle_timeout_listener
+ */
+struct org_kde_kwin_idle_timeout_listener {
+ /**
+ * Triggered when there has not been any user activity in the requested idle time interval
+ *
+ *
+ */
+ void (*idle)(void *data,
+ struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout);
+ /**
+ * Triggered on the first user activity after an idle event
+ *
+ *
+ */
+ void (*resumed)(void *data,
+ struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout);
+};
+
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ */
+static inline int
+org_kde_kwin_idle_timeout_add_listener(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout,
+ const struct org_kde_kwin_idle_timeout_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) org_kde_kwin_idle_timeout,
+ (void (**)(void)) listener, data);
+}
+
+#define ORG_KDE_KWIN_IDLE_TIMEOUT_RELEASE 0
+#define ORG_KDE_KWIN_IDLE_TIMEOUT_SIMULATE_USER_ACTIVITY 1
+
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ */
+#define ORG_KDE_KWIN_IDLE_TIMEOUT_IDLE_SINCE_VERSION 1
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ */
+#define ORG_KDE_KWIN_IDLE_TIMEOUT_RESUMED_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ */
+#define ORG_KDE_KWIN_IDLE_TIMEOUT_RELEASE_SINCE_VERSION 1
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ */
+#define ORG_KDE_KWIN_IDLE_TIMEOUT_SIMULATE_USER_ACTIVITY_SINCE_VERSION 1
+
+/** @ingroup iface_org_kde_kwin_idle_timeout */
+static inline void
+org_kde_kwin_idle_timeout_set_user_data(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) org_kde_kwin_idle_timeout, user_data);
+}
+
+/** @ingroup iface_org_kde_kwin_idle_timeout */
+static inline void *
+org_kde_kwin_idle_timeout_get_user_data(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) org_kde_kwin_idle_timeout);
+}
+
+static inline uint32_t
+org_kde_kwin_idle_timeout_get_version(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
+{
+ return wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle_timeout);
+}
+
+/** @ingroup iface_org_kde_kwin_idle_timeout */
+static inline void
+org_kde_kwin_idle_timeout_destroy(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
+{
+ wl_proxy_destroy((struct wl_proxy *) org_kde_kwin_idle_timeout);
+}
+
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ */
+static inline void
+org_kde_kwin_idle_timeout_release(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_idle_timeout,
+ ORG_KDE_KWIN_IDLE_TIMEOUT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle_timeout), WL_MARSHAL_FLAG_DESTROY);
+}
+
+/**
+ * @ingroup iface_org_kde_kwin_idle_timeout
+ */
+static inline void
+org_kde_kwin_idle_timeout_simulate_user_activity(struct org_kde_kwin_idle_timeout *org_kde_kwin_idle_timeout)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) org_kde_kwin_idle_timeout,
+ ORG_KDE_KWIN_IDLE_TIMEOUT_SIMULATE_USER_ACTIVITY, NULL, wl_proxy_get_version((struct wl_proxy *) org_kde_kwin_idle_timeout), 0);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+/*
+ * Copyright (C) 2015 Martin Gräßlin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
+#endif
+
+#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
+#define WL_PRIVATE __attribute__ ((visibility("hidden")))
+#else
+#define WL_PRIVATE
+#endif
+
+extern const struct wl_interface org_kde_kwin_idle_timeout_interface;
+extern const struct wl_interface wl_seat_interface;
+
+static const struct wl_interface *idle_types[] = {
+ &org_kde_kwin_idle_timeout_interface,
+ &wl_seat_interface,
+ NULL,
+};
+
+static const struct wl_message org_kde_kwin_idle_requests[] = {
+ { "get_idle_timeout", "nou", idle_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface org_kde_kwin_idle_interface = {
+ "org_kde_kwin_idle", 1,
+ 1, org_kde_kwin_idle_requests,
+ 0, NULL,
+};
+
+static const struct wl_message org_kde_kwin_idle_timeout_requests[] = {
+ { "release", "", idle_types + 0 },
+ { "simulate_user_activity", "", idle_types + 0 },
+};
+
+static const struct wl_message org_kde_kwin_idle_timeout_events[] = {
+ { "idle", "", idle_types + 0 },
+ { "resumed", "", idle_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface org_kde_kwin_idle_timeout_interface = {
+ "org_kde_kwin_idle_timeout", 1,
+ 2, org_kde_kwin_idle_timeout_requests,
+ 2, org_kde_kwin_idle_timeout_events,
+};
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="idle">
+ <copyright><![CDATA[
+ SPDX-FileCopyrightText: 2015 Martin Gräßlin
+
+ SPDX-License-Identifier: LGPL-2.1-or-later
+ ]]></copyright>
+ <interface name="org_kde_kwin_idle" version="1">
+ <description summary="User idle time manager">
+ This interface allows to monitor user idle time on a given seat. The interface
+ allows to register timers which trigger after no user activity was registered
+ on the seat for a given interval. It notifies when user activity resumes.
+
+ This is useful for applications wanting to perform actions when the user is not
+ interacting with the system, e.g. chat applications setting the user as away, power
+ management features to dim screen, etc..
+ </description>
+ <request name="get_idle_timeout">
+ <arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ <arg name="timeout" type="uint" summary="The idle timeout in msec"/>
+ </request>
+ </interface>
+ <interface name="org_kde_kwin_idle_timeout" version="1">
+ <request name="release" type="destructor">
+ <description summary="release the timeout object"/>
+ </request>
+ <request name="simulate_user_activity">
+ <description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/>
+ </request>
+ <event name="idle">
+ <description summary="Triggered when there has not been any user activity in the requested idle time interval"/>
+ </event>
+ <event name="resumed">
+ <description summary="Triggered on the first user activity after an idle event"/>
+ </event>
+ </interface>
+</protocol>
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+#ifndef WLR_OUTPUT_POWER_MANAGEMENT_UNSTABLE_V1_CLIENT_PROTOCOL_H
+#define WLR_OUTPUT_POWER_MANAGEMENT_UNSTABLE_V1_CLIENT_PROTOCOL_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @page page_wlr_output_power_management_unstable_v1 The wlr_output_power_management_unstable_v1 protocol
+ * Control power management modes of outputs
+ *
+ * @section page_desc_wlr_output_power_management_unstable_v1 Description
+ *
+ * This protocol allows clients to control power management modes
+ * of outputs that are currently part of the compositor space. The
+ * intent is to allow special clients like desktop shells to power
+ * down outputs when the system is idle.
+ *
+ * To modify outputs not currently part of the compositor space see
+ * wlr-output-management.
+ *
+ * Warning! The protocol described in this file is experimental and
+ * backward incompatible changes may be made. Backward compatible changes
+ * may be added together with the corresponding interface version bump.
+ * Backward incompatible changes are done by bumping the version number in
+ * the protocol and interface names and resetting the interface version.
+ * Once the protocol is to be declared stable, the 'z' prefix and the
+ * version number in the protocol and interface names are removed and the
+ * interface version number is reset.
+ *
+ * @section page_ifaces_wlr_output_power_management_unstable_v1 Interfaces
+ * - @subpage page_iface_zwlr_output_power_manager_v1 - manager to create per-output power management
+ * - @subpage page_iface_zwlr_output_power_v1 - adjust power management mode for an output
+ * @section page_copyright_wlr_output_power_management_unstable_v1 Copyright
+ * <pre>
+ *
+ * Copyright © 2019 Purism SPC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * </pre>
+ */
+struct wl_output;
+struct zwlr_output_power_manager_v1;
+struct zwlr_output_power_v1;
+
+#ifndef ZWLR_OUTPUT_POWER_MANAGER_V1_INTERFACE
+#define ZWLR_OUTPUT_POWER_MANAGER_V1_INTERFACE
+/**
+ * @page page_iface_zwlr_output_power_manager_v1 zwlr_output_power_manager_v1
+ * @section page_iface_zwlr_output_power_manager_v1_desc Description
+ *
+ * This interface is a manager that allows creating per-output power
+ * management mode controls.
+ * @section page_iface_zwlr_output_power_manager_v1_api API
+ * See @ref iface_zwlr_output_power_manager_v1.
+ */
+/**
+ * @defgroup iface_zwlr_output_power_manager_v1 The zwlr_output_power_manager_v1 interface
+ *
+ * This interface is a manager that allows creating per-output power
+ * management mode controls.
+ */
+extern const struct wl_interface zwlr_output_power_manager_v1_interface;
+#endif
+#ifndef ZWLR_OUTPUT_POWER_V1_INTERFACE
+#define ZWLR_OUTPUT_POWER_V1_INTERFACE
+/**
+ * @page page_iface_zwlr_output_power_v1 zwlr_output_power_v1
+ * @section page_iface_zwlr_output_power_v1_desc Description
+ *
+ * This object offers requests to set the power management mode of
+ * an output.
+ * @section page_iface_zwlr_output_power_v1_api API
+ * See @ref iface_zwlr_output_power_v1.
+ */
+/**
+ * @defgroup iface_zwlr_output_power_v1 The zwlr_output_power_v1 interface
+ *
+ * This object offers requests to set the power management mode of
+ * an output.
+ */
+extern const struct wl_interface zwlr_output_power_v1_interface;
+#endif
+
+#define ZWLR_OUTPUT_POWER_MANAGER_V1_GET_OUTPUT_POWER 0
+#define ZWLR_OUTPUT_POWER_MANAGER_V1_DESTROY 1
+
+
+/**
+ * @ingroup iface_zwlr_output_power_manager_v1
+ */
+#define ZWLR_OUTPUT_POWER_MANAGER_V1_GET_OUTPUT_POWER_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwlr_output_power_manager_v1
+ */
+#define ZWLR_OUTPUT_POWER_MANAGER_V1_DESTROY_SINCE_VERSION 1
+
+/** @ingroup iface_zwlr_output_power_manager_v1 */
+static inline void
+zwlr_output_power_manager_v1_set_user_data(struct zwlr_output_power_manager_v1 *zwlr_output_power_manager_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) zwlr_output_power_manager_v1, user_data);
+}
+
+/** @ingroup iface_zwlr_output_power_manager_v1 */
+static inline void *
+zwlr_output_power_manager_v1_get_user_data(struct zwlr_output_power_manager_v1 *zwlr_output_power_manager_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) zwlr_output_power_manager_v1);
+}
+
+static inline uint32_t
+zwlr_output_power_manager_v1_get_version(struct zwlr_output_power_manager_v1 *zwlr_output_power_manager_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) zwlr_output_power_manager_v1);
+}
+
+/**
+ * @ingroup iface_zwlr_output_power_manager_v1
+ *
+ * Create an output power management mode control that can be used to
+ * adjust the power management mode for a given output.
+ */
+static inline struct zwlr_output_power_v1 *
+zwlr_output_power_manager_v1_get_output_power(struct zwlr_output_power_manager_v1 *zwlr_output_power_manager_v1, struct wl_output *output)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) zwlr_output_power_manager_v1,
+ ZWLR_OUTPUT_POWER_MANAGER_V1_GET_OUTPUT_POWER, &zwlr_output_power_v1_interface, wl_proxy_get_version((struct wl_proxy *) zwlr_output_power_manager_v1), 0, NULL, output);
+
+ return (struct zwlr_output_power_v1 *) id;
+}
+
+/**
+ * @ingroup iface_zwlr_output_power_manager_v1
+ *
+ * All objects created by the manager will still remain valid, until their
+ * appropriate destroy request has been called.
+ */
+static inline void
+zwlr_output_power_manager_v1_destroy(struct zwlr_output_power_manager_v1 *zwlr_output_power_manager_v1)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) zwlr_output_power_manager_v1,
+ ZWLR_OUTPUT_POWER_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwlr_output_power_manager_v1), WL_MARSHAL_FLAG_DESTROY);
+}
+
+#ifndef ZWLR_OUTPUT_POWER_V1_MODE_ENUM
+#define ZWLR_OUTPUT_POWER_V1_MODE_ENUM
+enum zwlr_output_power_v1_mode {
+ /**
+ * Output is turned off.
+ */
+ ZWLR_OUTPUT_POWER_V1_MODE_OFF = 0,
+ /**
+ * Output is turned on, no power saving
+ */
+ ZWLR_OUTPUT_POWER_V1_MODE_ON = 1,
+};
+#endif /* ZWLR_OUTPUT_POWER_V1_MODE_ENUM */
+
+#ifndef ZWLR_OUTPUT_POWER_V1_ERROR_ENUM
+#define ZWLR_OUTPUT_POWER_V1_ERROR_ENUM
+enum zwlr_output_power_v1_error {
+ /**
+ * nonexistent power save mode
+ */
+ ZWLR_OUTPUT_POWER_V1_ERROR_INVALID_MODE = 1,
+};
+#endif /* ZWLR_OUTPUT_POWER_V1_ERROR_ENUM */
+
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ * @struct zwlr_output_power_v1_listener
+ */
+struct zwlr_output_power_v1_listener {
+ /**
+ * Report a power management mode change
+ *
+ * Report the power management mode change of an output.
+ *
+ * The mode event is sent after an output changed its power
+ * management mode. The reason can be a client using set_mode or
+ * the compositor deciding to change an output's mode. This event
+ * is also sent immediately when the object is created so the
+ * client is informed about the current power management mode.
+ * @param mode the output's new power management mode
+ */
+ void (*mode)(void *data,
+ struct zwlr_output_power_v1 *zwlr_output_power_v1,
+ uint32_t mode);
+ /**
+ * object no longer valid
+ *
+ * This event indicates that the output power management mode
+ * control is no longer valid. This can happen for a number of
+ * reasons, including: - The output doesn't support power
+ * management - Another client already has exclusive power
+ * management mode control for this output - The output disappeared
+ *
+ * Upon receiving this event, the client should destroy this
+ * object.
+ */
+ void (*failed)(void *data,
+ struct zwlr_output_power_v1 *zwlr_output_power_v1);
+};
+
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ */
+static inline int
+zwlr_output_power_v1_add_listener(struct zwlr_output_power_v1 *zwlr_output_power_v1,
+ const struct zwlr_output_power_v1_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) zwlr_output_power_v1,
+ (void (**)(void)) listener, data);
+}
+
+#define ZWLR_OUTPUT_POWER_V1_SET_MODE 0
+#define ZWLR_OUTPUT_POWER_V1_DESTROY 1
+
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ */
+#define ZWLR_OUTPUT_POWER_V1_MODE_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ */
+#define ZWLR_OUTPUT_POWER_V1_FAILED_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ */
+#define ZWLR_OUTPUT_POWER_V1_SET_MODE_SINCE_VERSION 1
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ */
+#define ZWLR_OUTPUT_POWER_V1_DESTROY_SINCE_VERSION 1
+
+/** @ingroup iface_zwlr_output_power_v1 */
+static inline void
+zwlr_output_power_v1_set_user_data(struct zwlr_output_power_v1 *zwlr_output_power_v1, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) zwlr_output_power_v1, user_data);
+}
+
+/** @ingroup iface_zwlr_output_power_v1 */
+static inline void *
+zwlr_output_power_v1_get_user_data(struct zwlr_output_power_v1 *zwlr_output_power_v1)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) zwlr_output_power_v1);
+}
+
+static inline uint32_t
+zwlr_output_power_v1_get_version(struct zwlr_output_power_v1 *zwlr_output_power_v1)
+{
+ return wl_proxy_get_version((struct wl_proxy *) zwlr_output_power_v1);
+}
+
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ *
+ * Set an output's power save mode to the given mode. The mode change
+ * is effective immediately. If the output does not support the given
+ * mode a failed event is sent.
+ */
+static inline void
+zwlr_output_power_v1_set_mode(struct zwlr_output_power_v1 *zwlr_output_power_v1, uint32_t mode)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) zwlr_output_power_v1,
+ ZWLR_OUTPUT_POWER_V1_SET_MODE, NULL, wl_proxy_get_version((struct wl_proxy *) zwlr_output_power_v1), 0, mode);
+}
+
+/**
+ * @ingroup iface_zwlr_output_power_v1
+ *
+ * Destroys the output power management mode control object.
+ */
+static inline void
+zwlr_output_power_v1_destroy(struct zwlr_output_power_v1 *zwlr_output_power_v1)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) zwlr_output_power_v1,
+ ZWLR_OUTPUT_POWER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwlr_output_power_v1), WL_MARSHAL_FLAG_DESTROY);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+/*
+ * Copyright © 2019 Purism SPC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
+#endif
+
+#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
+#define WL_PRIVATE __attribute__ ((visibility("hidden")))
+#else
+#define WL_PRIVATE
+#endif
+
+extern const struct wl_interface wl_output_interface;
+extern const struct wl_interface zwlr_output_power_v1_interface;
+
+static const struct wl_interface *wlr_output_power_management_unstable_v1_types[] = {
+ NULL,
+ &zwlr_output_power_v1_interface,
+ &wl_output_interface,
+};
+
+static const struct wl_message zwlr_output_power_manager_v1_requests[] = {
+ { "get_output_power", "no", wlr_output_power_management_unstable_v1_types + 1 },
+ { "destroy", "", wlr_output_power_management_unstable_v1_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface zwlr_output_power_manager_v1_interface = {
+ "zwlr_output_power_manager_v1", 1,
+ 2, zwlr_output_power_manager_v1_requests,
+ 0, NULL,
+};
+
+static const struct wl_message zwlr_output_power_v1_requests[] = {
+ { "set_mode", "u", wlr_output_power_management_unstable_v1_types + 0 },
+ { "destroy", "", wlr_output_power_management_unstable_v1_types + 0 },
+};
+
+static const struct wl_message zwlr_output_power_v1_events[] = {
+ { "mode", "u", wlr_output_power_management_unstable_v1_types + 0 },
+ { "failed", "", wlr_output_power_management_unstable_v1_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface zwlr_output_power_v1_interface = {
+ "zwlr_output_power_v1", 1,
+ 2, zwlr_output_power_v1_requests,
+ 2, zwlr_output_power_v1_events,
+};
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="wlr_output_power_management_unstable_v1">
+ <copyright>
+ Copyright © 2019 Purism SPC
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <description summary="Control power management modes of outputs">
+ This protocol allows clients to control power management modes
+ of outputs that are currently part of the compositor space. The
+ intent is to allow special clients like desktop shells to power
+ down outputs when the system is idle.
+
+ To modify outputs not currently part of the compositor space see
+ wlr-output-management.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+ </description>
+
+ <interface name="zwlr_output_power_manager_v1" version="1">
+ <description summary="manager to create per-output power management">
+ This interface is a manager that allows creating per-output power
+ management mode controls.
+ </description>
+
+ <request name="get_output_power">
+ <description summary="get a power management for an output">
+ Create an output power management mode control that can be used to
+ adjust the power management mode for a given output.
+ </description>
+ <arg name="id" type="new_id" interface="zwlr_output_power_v1"/>
+ <arg name="output" type="object" interface="wl_output"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the manager">
+ All objects created by the manager will still remain valid, until their
+ appropriate destroy request has been called.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwlr_output_power_v1" version="1">
+ <description summary="adjust power management mode for an output">
+ This object offers requests to set the power management mode of
+ an output.
+ </description>
+
+ <enum name="mode">
+ <entry name="off" value="0"
+ summary="Output is turned off."/>
+ <entry name="on" value="1"
+ summary="Output is turned on, no power saving"/>
+ </enum>
+
+ <enum name="error">
+ <entry name="invalid_mode" value="1" summary="nonexistent power save mode"/>
+ </enum>
+
+ <request name="set_mode">
+ <description summary="Set an outputs power save mode">
+ Set an output's power save mode to the given mode. The mode change
+ is effective immediately. If the output does not support the given
+ mode a failed event is sent.
+ </description>
+ <arg name="mode" type="uint" enum="mode" summary="the power save mode to set"/>
+ </request>
+
+ <event name="mode">
+ <description summary="Report a power management mode change">
+ Report the power management mode change of an output.
+
+ The mode event is sent after an output changed its power
+ management mode. The reason can be a client using set_mode or the
+ compositor deciding to change an output's mode.
+ This event is also sent immediately when the object is created
+ so the client is informed about the current power management mode.
+ </description>
+ <arg name="mode" type="uint" enum="mode"
+ summary="the output's new power management mode"/>
+ </event>
+
+ <event name="failed">
+ <description summary="object no longer valid">
+ This event indicates that the output power management mode control
+ is no longer valid. This can happen for a number of reasons,
+ including:
+ - The output doesn't support power management
+ - Another client already has exclusive power management mode control
+ for this output
+ - The output disappeared
+
+ Upon receiving this event, the client should destroy this object.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy this power management">
+ Destroys the output power management mode control object.
+ </description>
+ </request>
+ </interface>
+</protocol>
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+#ifndef XDG_SHELL_CLIENT_PROTOCOL_H
+#define XDG_SHELL_CLIENT_PROTOCOL_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @page page_xdg_shell The xdg_shell protocol
+ * @section page_ifaces_xdg_shell Interfaces
+ * - @subpage page_iface_xdg_wm_base - create desktop-style surfaces
+ * - @subpage page_iface_xdg_positioner - child surface positioner
+ * - @subpage page_iface_xdg_surface - desktop user interface surface base interface
+ * - @subpage page_iface_xdg_toplevel - toplevel surface
+ * - @subpage page_iface_xdg_popup - short-lived, popup surfaces for menus
+ * @section page_copyright_xdg_shell Copyright
+ * <pre>
+ *
+ * Copyright © 2008-2013 Kristian Høgsberg
+ * Copyright © 2013 Rafael Antognolli
+ * Copyright © 2013 Jasper St. Pierre
+ * Copyright © 2010-2013 Intel Corporation
+ * Copyright © 2015-2017 Samsung Electronics Co., Ltd
+ * Copyright © 2015-2017 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * </pre>
+ */
+struct wl_output;
+struct wl_seat;
+struct wl_surface;
+struct xdg_popup;
+struct xdg_positioner;
+struct xdg_surface;
+struct xdg_toplevel;
+struct xdg_wm_base;
+
+#ifndef XDG_WM_BASE_INTERFACE
+#define XDG_WM_BASE_INTERFACE
+/**
+ * @page page_iface_xdg_wm_base xdg_wm_base
+ * @section page_iface_xdg_wm_base_desc Description
+ *
+ * The xdg_wm_base interface is exposed as a global object enabling clients
+ * to turn their wl_surfaces into windows in a desktop environment. It
+ * defines the basic functionality needed for clients and the compositor to
+ * create windows that can be dragged, resized, maximized, etc, as well as
+ * creating transient windows such as popup menus.
+ * @section page_iface_xdg_wm_base_api API
+ * See @ref iface_xdg_wm_base.
+ */
+/**
+ * @defgroup iface_xdg_wm_base The xdg_wm_base interface
+ *
+ * The xdg_wm_base interface is exposed as a global object enabling clients
+ * to turn their wl_surfaces into windows in a desktop environment. It
+ * defines the basic functionality needed for clients and the compositor to
+ * create windows that can be dragged, resized, maximized, etc, as well as
+ * creating transient windows such as popup menus.
+ */
+extern const struct wl_interface xdg_wm_base_interface;
+#endif
+#ifndef XDG_POSITIONER_INTERFACE
+#define XDG_POSITIONER_INTERFACE
+/**
+ * @page page_iface_xdg_positioner xdg_positioner
+ * @section page_iface_xdg_positioner_desc Description
+ *
+ * The xdg_positioner provides a collection of rules for the placement of a
+ * child surface relative to a parent surface. Rules can be defined to ensure
+ * the child surface remains within the visible area's borders, and to
+ * specify how the child surface changes its position, such as sliding along
+ * an axis, or flipping around a rectangle. These positioner-created rules are
+ * constrained by the requirement that a child surface must intersect with or
+ * be at least partially adjacent to its parent surface.
+ *
+ * See the various requests for details about possible rules.
+ *
+ * At the time of the request, the compositor makes a copy of the rules
+ * specified by the xdg_positioner. Thus, after the request is complete the
+ * xdg_positioner object can be destroyed or reused; further changes to the
+ * object will have no effect on previous usages.
+ *
+ * For an xdg_positioner object to be considered complete, it must have a
+ * non-zero size set by set_size, and a non-zero anchor rectangle set by
+ * set_anchor_rect. Passing an incomplete xdg_positioner object when
+ * positioning a surface raises an invalid_positioner error.
+ * @section page_iface_xdg_positioner_api API
+ * See @ref iface_xdg_positioner.
+ */
+/**
+ * @defgroup iface_xdg_positioner The xdg_positioner interface
+ *
+ * The xdg_positioner provides a collection of rules for the placement of a
+ * child surface relative to a parent surface. Rules can be defined to ensure
+ * the child surface remains within the visible area's borders, and to
+ * specify how the child surface changes its position, such as sliding along
+ * an axis, or flipping around a rectangle. These positioner-created rules are
+ * constrained by the requirement that a child surface must intersect with or
+ * be at least partially adjacent to its parent surface.
+ *
+ * See the various requests for details about possible rules.
+ *
+ * At the time of the request, the compositor makes a copy of the rules
+ * specified by the xdg_positioner. Thus, after the request is complete the
+ * xdg_positioner object can be destroyed or reused; further changes to the
+ * object will have no effect on previous usages.
+ *
+ * For an xdg_positioner object to be considered complete, it must have a
+ * non-zero size set by set_size, and a non-zero anchor rectangle set by
+ * set_anchor_rect. Passing an incomplete xdg_positioner object when
+ * positioning a surface raises an invalid_positioner error.
+ */
+extern const struct wl_interface xdg_positioner_interface;
+#endif
+#ifndef XDG_SURFACE_INTERFACE
+#define XDG_SURFACE_INTERFACE
+/**
+ * @page page_iface_xdg_surface xdg_surface
+ * @section page_iface_xdg_surface_desc Description
+ *
+ * An interface that may be implemented by a wl_surface, for
+ * implementations that provide a desktop-style user interface.
+ *
+ * It provides a base set of functionality required to construct user
+ * interface elements requiring management by the compositor, such as
+ * toplevel windows, menus, etc. The types of functionality are split into
+ * xdg_surface roles.
+ *
+ * Creating an xdg_surface does not set the role for a wl_surface. In order
+ * to map an xdg_surface, the client must create a role-specific object
+ * using, e.g., get_toplevel, get_popup. The wl_surface for any given
+ * xdg_surface can have at most one role, and may not be assigned any role
+ * not based on xdg_surface.
+ *
+ * A role must be assigned before any other requests are made to the
+ * xdg_surface object.
+ *
+ * The client must call wl_surface.commit on the corresponding wl_surface
+ * for the xdg_surface state to take effect.
+ *
+ * Creating an xdg_surface from a wl_surface which has a buffer attached or
+ * committed is a client error, and any attempts by a client to attach or
+ * manipulate a buffer prior to the first xdg_surface.configure call must
+ * also be treated as errors.
+ *
+ * After creating a role-specific object and setting it up (e.g. by sending
+ * the title, app ID, size constraints, parent, etc), the client must
+ * perform an initial commit without any buffer attached. The compositor
+ * will reply with initial wl_surface state such as
+ * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
+ * event. The client must acknowledge it and is then allowed to attach a
+ * buffer to map the surface.
+ *
+ * Mapping an xdg_surface-based role surface is defined as making it
+ * possible for the surface to be shown by the compositor. Note that
+ * a mapped surface is not guaranteed to be visible once it is mapped.
+ *
+ * For an xdg_surface to be mapped by the compositor, the following
+ * conditions must be met:
+ * (1) the client has assigned an xdg_surface-based role to the surface
+ * (2) the client has set and committed the xdg_surface state and the
+ * role-dependent state to the surface
+ * (3) the client has committed a buffer to the surface
+ *
+ * A newly-unmapped surface is considered to have met condition (1) out
+ * of the 3 required conditions for mapping a surface if its role surface
+ * has not been destroyed, i.e. the client must perform the initial commit
+ * again before attaching a buffer.
+ * @section page_iface_xdg_surface_api API
+ * See @ref iface_xdg_surface.
+ */
+/**
+ * @defgroup iface_xdg_surface The xdg_surface interface
+ *
+ * An interface that may be implemented by a wl_surface, for
+ * implementations that provide a desktop-style user interface.
+ *
+ * It provides a base set of functionality required to construct user
+ * interface elements requiring management by the compositor, such as
+ * toplevel windows, menus, etc. The types of functionality are split into
+ * xdg_surface roles.
+ *
+ * Creating an xdg_surface does not set the role for a wl_surface. In order
+ * to map an xdg_surface, the client must create a role-specific object
+ * using, e.g., get_toplevel, get_popup. The wl_surface for any given
+ * xdg_surface can have at most one role, and may not be assigned any role
+ * not based on xdg_surface.
+ *
+ * A role must be assigned before any other requests are made to the
+ * xdg_surface object.
+ *
+ * The client must call wl_surface.commit on the corresponding wl_surface
+ * for the xdg_surface state to take effect.
+ *
+ * Creating an xdg_surface from a wl_surface which has a buffer attached or
+ * committed is a client error, and any attempts by a client to attach or
+ * manipulate a buffer prior to the first xdg_surface.configure call must
+ * also be treated as errors.
+ *
+ * After creating a role-specific object and setting it up (e.g. by sending
+ * the title, app ID, size constraints, parent, etc), the client must
+ * perform an initial commit without any buffer attached. The compositor
+ * will reply with initial wl_surface state such as
+ * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
+ * event. The client must acknowledge it and is then allowed to attach a
+ * buffer to map the surface.
+ *
+ * Mapping an xdg_surface-based role surface is defined as making it
+ * possible for the surface to be shown by the compositor. Note that
+ * a mapped surface is not guaranteed to be visible once it is mapped.
+ *
+ * For an xdg_surface to be mapped by the compositor, the following
+ * conditions must be met:
+ * (1) the client has assigned an xdg_surface-based role to the surface
+ * (2) the client has set and committed the xdg_surface state and the
+ * role-dependent state to the surface
+ * (3) the client has committed a buffer to the surface
+ *
+ * A newly-unmapped surface is considered to have met condition (1) out
+ * of the 3 required conditions for mapping a surface if its role surface
+ * has not been destroyed, i.e. the client must perform the initial commit
+ * again before attaching a buffer.
+ */
+extern const struct wl_interface xdg_surface_interface;
+#endif
+#ifndef XDG_TOPLEVEL_INTERFACE
+#define XDG_TOPLEVEL_INTERFACE
+/**
+ * @page page_iface_xdg_toplevel xdg_toplevel
+ * @section page_iface_xdg_toplevel_desc Description
+ *
+ * This interface defines an xdg_surface role which allows a surface to,
+ * among other things, set window-like properties such as maximize,
+ * fullscreen, and minimize, set application-specific metadata like title and
+ * id, and well as trigger user interactive operations such as interactive
+ * resize and move.
+ *
+ * A xdg_toplevel by default is responsible for providing the full intended
+ * visual representation of the toplevel, which depending on the window
+ * state, may mean things like a title bar, window controls and drop shadow.
+ *
+ * Unmapping an xdg_toplevel means that the surface cannot be shown
+ * by the compositor until it is explicitly mapped again.
+ * All active operations (e.g., move, resize) are canceled and all
+ * attributes (e.g. title, state, stacking, ...) are discarded for
+ * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
+ * the state it had right after xdg_surface.get_toplevel. The client
+ * can re-map the toplevel by performing a commit without any buffer
+ * attached, waiting for a configure event and handling it as usual (see
+ * xdg_surface description).
+ *
+ * Attaching a null buffer to a toplevel unmaps the surface.
+ * @section page_iface_xdg_toplevel_api API
+ * See @ref iface_xdg_toplevel.
+ */
+/**
+ * @defgroup iface_xdg_toplevel The xdg_toplevel interface
+ *
+ * This interface defines an xdg_surface role which allows a surface to,
+ * among other things, set window-like properties such as maximize,
+ * fullscreen, and minimize, set application-specific metadata like title and
+ * id, and well as trigger user interactive operations such as interactive
+ * resize and move.
+ *
+ * A xdg_toplevel by default is responsible for providing the full intended
+ * visual representation of the toplevel, which depending on the window
+ * state, may mean things like a title bar, window controls and drop shadow.
+ *
+ * Unmapping an xdg_toplevel means that the surface cannot be shown
+ * by the compositor until it is explicitly mapped again.
+ * All active operations (e.g., move, resize) are canceled and all
+ * attributes (e.g. title, state, stacking, ...) are discarded for
+ * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
+ * the state it had right after xdg_surface.get_toplevel. The client
+ * can re-map the toplevel by performing a commit without any buffer
+ * attached, waiting for a configure event and handling it as usual (see
+ * xdg_surface description).
+ *
+ * Attaching a null buffer to a toplevel unmaps the surface.
+ */
+extern const struct wl_interface xdg_toplevel_interface;
+#endif
+#ifndef XDG_POPUP_INTERFACE
+#define XDG_POPUP_INTERFACE
+/**
+ * @page page_iface_xdg_popup xdg_popup
+ * @section page_iface_xdg_popup_desc Description
+ *
+ * A popup surface is a short-lived, temporary surface. It can be used to
+ * implement for example menus, popovers, tooltips and other similar user
+ * interface concepts.
+ *
+ * A popup can be made to take an explicit grab. See xdg_popup.grab for
+ * details.
+ *
+ * When the popup is dismissed, a popup_done event will be sent out, and at
+ * the same time the surface will be unmapped. See the xdg_popup.popup_done
+ * event for details.
+ *
+ * Explicitly destroying the xdg_popup object will also dismiss the popup and
+ * unmap the surface. Clients that want to dismiss the popup when another
+ * surface of their own is clicked should dismiss the popup using the destroy
+ * request.
+ *
+ * A newly created xdg_popup will be stacked on top of all previously created
+ * xdg_popup surfaces associated with the same xdg_toplevel.
+ *
+ * The parent of an xdg_popup must be mapped (see the xdg_surface
+ * description) before the xdg_popup itself.
+ *
+ * The client must call wl_surface.commit on the corresponding wl_surface
+ * for the xdg_popup state to take effect.
+ * @section page_iface_xdg_popup_api API
+ * See @ref iface_xdg_popup.
+ */
+/**
+ * @defgroup iface_xdg_popup The xdg_popup interface
+ *
+ * A popup surface is a short-lived, temporary surface. It can be used to
+ * implement for example menus, popovers, tooltips and other similar user
+ * interface concepts.
+ *
+ * A popup can be made to take an explicit grab. See xdg_popup.grab for
+ * details.
+ *
+ * When the popup is dismissed, a popup_done event will be sent out, and at
+ * the same time the surface will be unmapped. See the xdg_popup.popup_done
+ * event for details.
+ *
+ * Explicitly destroying the xdg_popup object will also dismiss the popup and
+ * unmap the surface. Clients that want to dismiss the popup when another
+ * surface of their own is clicked should dismiss the popup using the destroy
+ * request.
+ *
+ * A newly created xdg_popup will be stacked on top of all previously created
+ * xdg_popup surfaces associated with the same xdg_toplevel.
+ *
+ * The parent of an xdg_popup must be mapped (see the xdg_surface
+ * description) before the xdg_popup itself.
+ *
+ * The client must call wl_surface.commit on the corresponding wl_surface
+ * for the xdg_popup state to take effect.
+ */
+extern const struct wl_interface xdg_popup_interface;
+#endif
+
+#ifndef XDG_WM_BASE_ERROR_ENUM
+#define XDG_WM_BASE_ERROR_ENUM
+enum xdg_wm_base_error {
+ /**
+ * given wl_surface has another role
+ */
+ XDG_WM_BASE_ERROR_ROLE = 0,
+ /**
+ * xdg_wm_base was destroyed before children
+ */
+ XDG_WM_BASE_ERROR_DEFUNCT_SURFACES = 1,
+ /**
+ * the client tried to map or destroy a non-topmost popup
+ */
+ XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP = 2,
+ /**
+ * the client specified an invalid popup parent surface
+ */
+ XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT = 3,
+ /**
+ * the client provided an invalid surface state
+ */
+ XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE = 4,
+ /**
+ * the client provided an invalid positioner
+ */
+ XDG_WM_BASE_ERROR_INVALID_POSITIONER = 5,
+ /**
+ * the client didn’t respond to a ping event in time
+ */
+ XDG_WM_BASE_ERROR_UNRESPONSIVE = 6,
+};
+#endif /* XDG_WM_BASE_ERROR_ENUM */
+
+/**
+ * @ingroup iface_xdg_wm_base
+ * @struct xdg_wm_base_listener
+ */
+struct xdg_wm_base_listener {
+ /**
+ * check if the client is alive
+ *
+ * The ping event asks the client if it's still alive. Pass the
+ * serial specified in the event back to the compositor by sending
+ * a "pong" request back with the specified serial. See
+ * xdg_wm_base.pong.
+ *
+ * Compositors can use this to determine if the client is still
+ * alive. It's unspecified what will happen if the client doesn't
+ * respond to the ping request, or in what timeframe. Clients
+ * should try to respond in a reasonable amount of time. The
+ * “unresponsive” error is provided for compositors that wish
+ * to disconnect unresponsive clients.
+ *
+ * A compositor is free to ping in any way it wants, but a client
+ * must always respond to any xdg_wm_base object it created.
+ * @param serial pass this to the pong request
+ */
+ void (*ping)(void *data,
+ struct xdg_wm_base *xdg_wm_base,
+ uint32_t serial);
+};
+
+/**
+ * @ingroup iface_xdg_wm_base
+ */
+static inline int
+xdg_wm_base_add_listener(struct xdg_wm_base *xdg_wm_base,
+ const struct xdg_wm_base_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) xdg_wm_base,
+ (void (**)(void)) listener, data);
+}
+
+#define XDG_WM_BASE_DESTROY 0
+#define XDG_WM_BASE_CREATE_POSITIONER 1
+#define XDG_WM_BASE_GET_XDG_SURFACE 2
+#define XDG_WM_BASE_PONG 3
+
+/**
+ * @ingroup iface_xdg_wm_base
+ */
+#define XDG_WM_BASE_PING_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_xdg_wm_base
+ */
+#define XDG_WM_BASE_DESTROY_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_wm_base
+ */
+#define XDG_WM_BASE_CREATE_POSITIONER_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_wm_base
+ */
+#define XDG_WM_BASE_GET_XDG_SURFACE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_wm_base
+ */
+#define XDG_WM_BASE_PONG_SINCE_VERSION 1
+
+/** @ingroup iface_xdg_wm_base */
+static inline void
+xdg_wm_base_set_user_data(struct xdg_wm_base *xdg_wm_base, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) xdg_wm_base, user_data);
+}
+
+/** @ingroup iface_xdg_wm_base */
+static inline void *
+xdg_wm_base_get_user_data(struct xdg_wm_base *xdg_wm_base)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) xdg_wm_base);
+}
+
+static inline uint32_t
+xdg_wm_base_get_version(struct xdg_wm_base *xdg_wm_base)
+{
+ return wl_proxy_get_version((struct wl_proxy *) xdg_wm_base);
+}
+
+/**
+ * @ingroup iface_xdg_wm_base
+ *
+ * Destroy this xdg_wm_base object.
+ *
+ * Destroying a bound xdg_wm_base object while there are surfaces
+ * still alive created by this xdg_wm_base object instance is illegal
+ * and will result in a defunct_surfaces error.
+ */
+static inline void
+xdg_wm_base_destroy(struct xdg_wm_base *xdg_wm_base)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
+ XDG_WM_BASE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), WL_MARSHAL_FLAG_DESTROY);
+}
+
+/**
+ * @ingroup iface_xdg_wm_base
+ *
+ * Create a positioner object. A positioner object is used to position
+ * surfaces relative to some parent surface. See the interface description
+ * and xdg_surface.get_popup for details.
+ */
+static inline struct xdg_positioner *
+xdg_wm_base_create_positioner(struct xdg_wm_base *xdg_wm_base)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
+ XDG_WM_BASE_CREATE_POSITIONER, &xdg_positioner_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL);
+
+ return (struct xdg_positioner *) id;
+}
+
+/**
+ * @ingroup iface_xdg_wm_base
+ *
+ * This creates an xdg_surface for the given surface. While xdg_surface
+ * itself is not a role, the corresponding surface may only be assigned
+ * a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
+ * illegal to create an xdg_surface for a wl_surface which already has an
+ * assigned role and this will result in a role error.
+ *
+ * This creates an xdg_surface for the given surface. An xdg_surface is
+ * used as basis to define a role to a given surface, such as xdg_toplevel
+ * or xdg_popup. It also manages functionality shared between xdg_surface
+ * based surface roles.
+ *
+ * See the documentation of xdg_surface for more details about what an
+ * xdg_surface is and how it is used.
+ */
+static inline struct xdg_surface *
+xdg_wm_base_get_xdg_surface(struct xdg_wm_base *xdg_wm_base, struct wl_surface *surface)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
+ XDG_WM_BASE_GET_XDG_SURFACE, &xdg_surface_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL, surface);
+
+ return (struct xdg_surface *) id;
+}
+
+/**
+ * @ingroup iface_xdg_wm_base
+ *
+ * A client must respond to a ping event with a pong request or
+ * the client may be deemed unresponsive. See xdg_wm_base.ping
+ * and xdg_wm_base.error.unresponsive.
+ */
+static inline void
+xdg_wm_base_pong(struct xdg_wm_base *xdg_wm_base, uint32_t serial)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
+ XDG_WM_BASE_PONG, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, serial);
+}
+
+#ifndef XDG_POSITIONER_ERROR_ENUM
+#define XDG_POSITIONER_ERROR_ENUM
+enum xdg_positioner_error {
+ /**
+ * invalid input provided
+ */
+ XDG_POSITIONER_ERROR_INVALID_INPUT = 0,
+};
+#endif /* XDG_POSITIONER_ERROR_ENUM */
+
+#ifndef XDG_POSITIONER_ANCHOR_ENUM
+#define XDG_POSITIONER_ANCHOR_ENUM
+enum xdg_positioner_anchor {
+ XDG_POSITIONER_ANCHOR_NONE = 0,
+ XDG_POSITIONER_ANCHOR_TOP = 1,
+ XDG_POSITIONER_ANCHOR_BOTTOM = 2,
+ XDG_POSITIONER_ANCHOR_LEFT = 3,
+ XDG_POSITIONER_ANCHOR_RIGHT = 4,
+ XDG_POSITIONER_ANCHOR_TOP_LEFT = 5,
+ XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6,
+ XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7,
+ XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8,
+};
+#endif /* XDG_POSITIONER_ANCHOR_ENUM */
+
+#ifndef XDG_POSITIONER_GRAVITY_ENUM
+#define XDG_POSITIONER_GRAVITY_ENUM
+enum xdg_positioner_gravity {
+ XDG_POSITIONER_GRAVITY_NONE = 0,
+ XDG_POSITIONER_GRAVITY_TOP = 1,
+ XDG_POSITIONER_GRAVITY_BOTTOM = 2,
+ XDG_POSITIONER_GRAVITY_LEFT = 3,
+ XDG_POSITIONER_GRAVITY_RIGHT = 4,
+ XDG_POSITIONER_GRAVITY_TOP_LEFT = 5,
+ XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6,
+ XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7,
+ XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8,
+};
+#endif /* XDG_POSITIONER_GRAVITY_ENUM */
+
+#ifndef XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM
+#define XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM
+/**
+ * @ingroup iface_xdg_positioner
+ * constraint adjustments
+ *
+ * The constraint adjustment value define ways the compositor will adjust
+ * the position of the surface, if the unadjusted position would result
+ * in the surface being partly constrained.
+ *
+ * Whether a surface is considered 'constrained' is left to the compositor
+ * to determine. For example, the surface may be partly outside the
+ * compositor's defined 'work area', thus necessitating the child surface's
+ * position be adjusted until it is entirely inside the work area.
+ *
+ * The adjustments can be combined, according to a defined precedence: 1)
+ * Flip, 2) Slide, 3) Resize.
+ */
+enum xdg_positioner_constraint_adjustment {
+ /**
+ * don't move the child surface when constrained
+ *
+ * Don't alter the surface position even if it is constrained on
+ * some axis, for example partially outside the edge of an output.
+ */
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0,
+ /**
+ * move along the x axis until unconstrained
+ *
+ * Slide the surface along the x axis until it is no longer
+ * constrained.
+ *
+ * First try to slide towards the direction of the gravity on the x
+ * axis until either the edge in the opposite direction of the
+ * gravity is unconstrained or the edge in the direction of the
+ * gravity is constrained.
+ *
+ * Then try to slide towards the opposite direction of the gravity
+ * on the x axis until either the edge in the direction of the
+ * gravity is unconstrained or the edge in the opposite direction
+ * of the gravity is constrained.
+ */
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1,
+ /**
+ * move along the y axis until unconstrained
+ *
+ * Slide the surface along the y axis until it is no longer
+ * constrained.
+ *
+ * First try to slide towards the direction of the gravity on the y
+ * axis until either the edge in the opposite direction of the
+ * gravity is unconstrained or the edge in the direction of the
+ * gravity is constrained.
+ *
+ * Then try to slide towards the opposite direction of the gravity
+ * on the y axis until either the edge in the direction of the
+ * gravity is unconstrained or the edge in the opposite direction
+ * of the gravity is constrained.
+ */
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2,
+ /**
+ * invert the anchor and gravity on the x axis
+ *
+ * Invert the anchor and gravity on the x axis if the surface is
+ * constrained on the x axis. For example, if the left edge of the
+ * surface is constrained, the gravity is 'left' and the anchor is
+ * 'left', change the gravity to 'right' and the anchor to 'right'.
+ *
+ * If the adjusted position also ends up being constrained, the
+ * resulting position of the flip_x adjustment will be the one
+ * before the adjustment.
+ */
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4,
+ /**
+ * invert the anchor and gravity on the y axis
+ *
+ * Invert the anchor and gravity on the y axis if the surface is
+ * constrained on the y axis. For example, if the bottom edge of
+ * the surface is constrained, the gravity is 'bottom' and the
+ * anchor is 'bottom', change the gravity to 'top' and the anchor
+ * to 'top'.
+ *
+ * The adjusted position is calculated given the original anchor
+ * rectangle and offset, but with the new flipped anchor and
+ * gravity values.
+ *
+ * If the adjusted position also ends up being constrained, the
+ * resulting position of the flip_y adjustment will be the one
+ * before the adjustment.
+ */
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8,
+ /**
+ * horizontally resize the surface
+ *
+ * Resize the surface horizontally so that it is completely
+ * unconstrained.
+ */
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16,
+ /**
+ * vertically resize the surface
+ *
+ * Resize the surface vertically so that it is completely
+ * unconstrained.
+ */
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32,
+};
+#endif /* XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM */
+
+#define XDG_POSITIONER_DESTROY 0
+#define XDG_POSITIONER_SET_SIZE 1
+#define XDG_POSITIONER_SET_ANCHOR_RECT 2
+#define XDG_POSITIONER_SET_ANCHOR 3
+#define XDG_POSITIONER_SET_GRAVITY 4
+#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT 5
+#define XDG_POSITIONER_SET_OFFSET 6
+#define XDG_POSITIONER_SET_REACTIVE 7
+#define XDG_POSITIONER_SET_PARENT_SIZE 8
+#define XDG_POSITIONER_SET_PARENT_CONFIGURE 9
+
+
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_DESTROY_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_SIZE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_ANCHOR_RECT_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_ANCHOR_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_GRAVITY_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_OFFSET_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION 3
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_PARENT_SIZE_SINCE_VERSION 3
+/**
+ * @ingroup iface_xdg_positioner
+ */
+#define XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION 3
+
+/** @ingroup iface_xdg_positioner */
+static inline void
+xdg_positioner_set_user_data(struct xdg_positioner *xdg_positioner, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) xdg_positioner, user_data);
+}
+
+/** @ingroup iface_xdg_positioner */
+static inline void *
+xdg_positioner_get_user_data(struct xdg_positioner *xdg_positioner)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) xdg_positioner);
+}
+
+static inline uint32_t
+xdg_positioner_get_version(struct xdg_positioner *xdg_positioner)
+{
+ return wl_proxy_get_version((struct wl_proxy *) xdg_positioner);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Notify the compositor that the xdg_positioner will no longer be used.
+ */
+static inline void
+xdg_positioner_destroy(struct xdg_positioner *xdg_positioner)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), WL_MARSHAL_FLAG_DESTROY);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Set the size of the surface that is to be positioned with the positioner
+ * object. The size is in surface-local coordinates and corresponds to the
+ * window geometry. See xdg_surface.set_window_geometry.
+ *
+ * If a zero or negative size is set the invalid_input error is raised.
+ */
+static inline void
+xdg_positioner_set_size(struct xdg_positioner *xdg_positioner, int32_t width, int32_t height)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, width, height);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Specify the anchor rectangle within the parent surface that the child
+ * surface will be placed relative to. The rectangle is relative to the
+ * window geometry as defined by xdg_surface.set_window_geometry of the
+ * parent surface.
+ *
+ * When the xdg_positioner object is used to position a child surface, the
+ * anchor rectangle may not extend outside the window geometry of the
+ * positioned child's parent surface.
+ *
+ * If a negative size is set the invalid_input error is raised.
+ */
+static inline void
+xdg_positioner_set_anchor_rect(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_ANCHOR_RECT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y, width, height);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Defines the anchor point for the anchor rectangle. The specified anchor
+ * is used derive an anchor point that the child surface will be
+ * positioned relative to. If a corner anchor is set (e.g. 'top_left' or
+ * 'bottom_right'), the anchor point will be at the specified corner;
+ * otherwise, the derived anchor point will be centered on the specified
+ * edge, or in the center of the anchor rectangle if no edge is specified.
+ */
+static inline void
+xdg_positioner_set_anchor(struct xdg_positioner *xdg_positioner, uint32_t anchor)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_ANCHOR, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, anchor);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Defines in what direction a surface should be positioned, relative to
+ * the anchor point of the parent surface. If a corner gravity is
+ * specified (e.g. 'bottom_right' or 'top_left'), then the child surface
+ * will be placed towards the specified gravity; otherwise, the child
+ * surface will be centered over the anchor point on any axis that had no
+ * gravity specified. If the gravity is not in the ‘gravity’ enum, an
+ * invalid_input error is raised.
+ */
+static inline void
+xdg_positioner_set_gravity(struct xdg_positioner *xdg_positioner, uint32_t gravity)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_GRAVITY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, gravity);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Specify how the window should be positioned if the originally intended
+ * position caused the surface to be constrained, meaning at least
+ * partially outside positioning boundaries set by the compositor. The
+ * adjustment is set by constructing a bitmask describing the adjustment to
+ * be made when the surface is constrained on that axis.
+ *
+ * If no bit for one axis is set, the compositor will assume that the child
+ * surface should not change its position on that axis when constrained.
+ *
+ * If more than one bit for one axis is set, the order of how adjustments
+ * are applied is specified in the corresponding adjustment descriptions.
+ *
+ * The default adjustment is none.
+ */
+static inline void
+xdg_positioner_set_constraint_adjustment(struct xdg_positioner *xdg_positioner, uint32_t constraint_adjustment)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, constraint_adjustment);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Specify the surface position offset relative to the position of the
+ * anchor on the anchor rectangle and the anchor on the surface. For
+ * example if the anchor of the anchor rectangle is at (x, y), the surface
+ * has the gravity bottom|right, and the offset is (ox, oy), the calculated
+ * surface position will be (x + ox, y + oy). The offset position of the
+ * surface is the one used for constraint testing. See
+ * set_constraint_adjustment.
+ *
+ * An example use case is placing a popup menu on top of a user interface
+ * element, while aligning the user interface element of the parent surface
+ * with some user interface element placed somewhere in the popup surface.
+ */
+static inline void
+xdg_positioner_set_offset(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_OFFSET, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * When set reactive, the surface is reconstrained if the conditions used
+ * for constraining changed, e.g. the parent window moved.
+ *
+ * If the conditions changed and the popup was reconstrained, an
+ * xdg_popup.configure event is sent with updated geometry, followed by an
+ * xdg_surface.configure event.
+ */
+static inline void
+xdg_positioner_set_reactive(struct xdg_positioner *xdg_positioner)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_REACTIVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Set the parent window geometry the compositor should use when
+ * positioning the popup. The compositor may use this information to
+ * determine the future state the popup should be constrained using. If
+ * this doesn't match the dimension of the parent the popup is eventually
+ * positioned against, the behavior is undefined.
+ *
+ * The arguments are given in the surface-local coordinate space.
+ */
+static inline void
+xdg_positioner_set_parent_size(struct xdg_positioner *xdg_positioner, int32_t parent_width, int32_t parent_height)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_PARENT_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, parent_width, parent_height);
+}
+
+/**
+ * @ingroup iface_xdg_positioner
+ *
+ * Set the serial of an xdg_surface.configure event this positioner will be
+ * used in response to. The compositor may use this information together
+ * with set_parent_size to determine what future state the popup should be
+ * constrained using.
+ */
+static inline void
+xdg_positioner_set_parent_configure(struct xdg_positioner *xdg_positioner, uint32_t serial)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
+ XDG_POSITIONER_SET_PARENT_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, serial);
+}
+
+#ifndef XDG_SURFACE_ERROR_ENUM
+#define XDG_SURFACE_ERROR_ENUM
+enum xdg_surface_error {
+ /**
+ * Surface was not fully constructed
+ */
+ XDG_SURFACE_ERROR_NOT_CONSTRUCTED = 1,
+ /**
+ * Surface was already constructed
+ */
+ XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED = 2,
+ /**
+ * Attaching a buffer to an unconfigured surface
+ */
+ XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER = 3,
+ /**
+ * Invalid serial number when acking a configure event
+ */
+ XDG_SURFACE_ERROR_INVALID_SERIAL = 4,
+ /**
+ * Width or height was zero or negative
+ */
+ XDG_SURFACE_ERROR_INVALID_SIZE = 5,
+ /**
+ * Surface was destroyed before its role object
+ */
+ XDG_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT = 6,
+};
+#endif /* XDG_SURFACE_ERROR_ENUM */
+
+/**
+ * @ingroup iface_xdg_surface
+ * @struct xdg_surface_listener
+ */
+struct xdg_surface_listener {
+ /**
+ * suggest a surface change
+ *
+ * The configure event marks the end of a configure sequence. A
+ * configure sequence is a set of one or more events configuring
+ * the state of the xdg_surface, including the final
+ * xdg_surface.configure event.
+ *
+ * Where applicable, xdg_surface surface roles will during a
+ * configure sequence extend this event as a latched state sent as
+ * events before the xdg_surface.configure event. Such events
+ * should be considered to make up a set of atomically applied
+ * configuration states, where the xdg_surface.configure commits
+ * the accumulated state.
+ *
+ * Clients should arrange their surface for the new states, and
+ * then send an ack_configure request with the serial sent in this
+ * configure event at some point before committing the new surface.
+ *
+ * If the client receives multiple configure events before it can
+ * respond to one, it is free to discard all but the last event it
+ * received.
+ * @param serial serial of the configure event
+ */
+ void (*configure)(void *data,
+ struct xdg_surface *xdg_surface,
+ uint32_t serial);
+};
+
+/**
+ * @ingroup iface_xdg_surface
+ */
+static inline int
+xdg_surface_add_listener(struct xdg_surface *xdg_surface,
+ const struct xdg_surface_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) xdg_surface,
+ (void (**)(void)) listener, data);
+}
+
+#define XDG_SURFACE_DESTROY 0
+#define XDG_SURFACE_GET_TOPLEVEL 1
+#define XDG_SURFACE_GET_POPUP 2
+#define XDG_SURFACE_SET_WINDOW_GEOMETRY 3
+#define XDG_SURFACE_ACK_CONFIGURE 4
+
+/**
+ * @ingroup iface_xdg_surface
+ */
+#define XDG_SURFACE_CONFIGURE_SINCE_VERSION 1
+
+/**
+ * @ingroup iface_xdg_surface
+ */
+#define XDG_SURFACE_DESTROY_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_surface
+ */
+#define XDG_SURFACE_GET_TOPLEVEL_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_surface
+ */
+#define XDG_SURFACE_GET_POPUP_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_surface
+ */
+#define XDG_SURFACE_SET_WINDOW_GEOMETRY_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_surface
+ */
+#define XDG_SURFACE_ACK_CONFIGURE_SINCE_VERSION 1
+
+/** @ingroup iface_xdg_surface */
+static inline void
+xdg_surface_set_user_data(struct xdg_surface *xdg_surface, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) xdg_surface, user_data);
+}
+
+/** @ingroup iface_xdg_surface */
+static inline void *
+xdg_surface_get_user_data(struct xdg_surface *xdg_surface)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) xdg_surface);
+}
+
+static inline uint32_t
+xdg_surface_get_version(struct xdg_surface *xdg_surface)
+{
+ return wl_proxy_get_version((struct wl_proxy *) xdg_surface);
+}
+
+/**
+ * @ingroup iface_xdg_surface
+ *
+ * Destroy the xdg_surface object. An xdg_surface must only be destroyed
+ * after its role object has been destroyed, otherwise
+ * a defunct_role_object error is raised.
+ */
+static inline void
+xdg_surface_destroy(struct xdg_surface *xdg_surface)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
+ XDG_SURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), WL_MARSHAL_FLAG_DESTROY);
+}
+
+/**
+ * @ingroup iface_xdg_surface
+ *
+ * This creates an xdg_toplevel object for the given xdg_surface and gives
+ * the associated wl_surface the xdg_toplevel role.
+ *
+ * See the documentation of xdg_toplevel for more details about what an
+ * xdg_toplevel is and how it is used.
+ */
+static inline struct xdg_toplevel *
+xdg_surface_get_toplevel(struct xdg_surface *xdg_surface)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
+ XDG_SURFACE_GET_TOPLEVEL, &xdg_toplevel_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL);
+
+ return (struct xdg_toplevel *) id;
+}
+
+/**
+ * @ingroup iface_xdg_surface
+ *
+ * This creates an xdg_popup object for the given xdg_surface and gives
+ * the associated wl_surface the xdg_popup role.
+ *
+ * If null is passed as a parent, a parent surface must be specified using
+ * some other protocol, before committing the initial state.
+ *
+ * See the documentation of xdg_popup for more details about what an
+ * xdg_popup is and how it is used.
+ */
+static inline struct xdg_popup *
+xdg_surface_get_popup(struct xdg_surface *xdg_surface, struct xdg_surface *parent, struct xdg_positioner *positioner)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
+ XDG_SURFACE_GET_POPUP, &xdg_popup_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL, parent, positioner);
+
+ return (struct xdg_popup *) id;
+}
+
+/**
+ * @ingroup iface_xdg_surface
+ *
+ * The window geometry of a surface is its "visible bounds" from the
+ * user's perspective. Client-side decorations often have invisible
+ * portions like drop-shadows which should be ignored for the
+ * purposes of aligning, placing and constraining windows.
+ *
+ * The window geometry is double-buffered state, see wl_surface.commit.
+ *
+ * When maintaining a position, the compositor should treat the (x, y)
+ * coordinate of the window geometry as the top left corner of the window.
+ * A client changing the (x, y) window geometry coordinate should in
+ * general not alter the position of the window.
+ *
+ * Once the window geometry of the surface is set, it is not possible to
+ * unset it, and it will remain the same until set_window_geometry is
+ * called again, even if a new subsurface or buffer is attached.
+ *
+ * If never set, the value is the full bounds of the surface,
+ * including any subsurfaces. This updates dynamically on every
+ * commit. This unset is meant for extremely simple clients.
+ *
+ * The arguments are given in the surface-local coordinate space of
+ * the wl_surface associated with this xdg_surface, and may extend outside
+ * of the wl_surface itself to mark parts of the subsurface tree as part of
+ * the window geometry.
+ *
+ * When applied, the effective window geometry will be the set window
+ * geometry clamped to the bounding rectangle of the combined
+ * geometry of the surface of the xdg_surface and the associated
+ * subsurfaces.
+ *
+ * The effective geometry will not be recalculated unless a new call to
+ * set_window_geometry is done and the new pending surface state is
+ * subsequently applied.
+ *
+ * The width and height of the effective window geometry must be
+ * greater than zero. Setting an invalid size will raise an
+ * invalid_size error.
+ */
+static inline void
+xdg_surface_set_window_geometry(struct xdg_surface *xdg_surface, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
+ XDG_SURFACE_SET_WINDOW_GEOMETRY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, x, y, width, height);
+}
+
+/**
+ * @ingroup iface_xdg_surface
+ *
+ * When a configure event is received, if a client commits the
+ * surface in response to the configure event, then the client
+ * must make an ack_configure request sometime before the commit
+ * request, passing along the serial of the configure event.
+ *
+ * For instance, for toplevel surfaces the compositor might use this
+ * information to move a surface to the top left only when the client has
+ * drawn itself for the maximized or fullscreen state.
+ *
+ * If the client receives multiple configure events before it
+ * can respond to one, it only has to ack the last configure event.
+ * Acking a configure event that was never sent raises an invalid_serial
+ * error.
+ *
+ * A client is not required to commit immediately after sending
+ * an ack_configure request - it may even ack_configure several times
+ * before its next surface commit.
+ *
+ * A client may send multiple ack_configure requests before committing, but
+ * only the last request sent before a commit indicates which configure
+ * event the client really is responding to.
+ *
+ * Sending an ack_configure request consumes the serial number sent with
+ * the request, as well as serial numbers sent by all configure events
+ * sent on this xdg_surface prior to the configure event referenced by
+ * the committed serial.
+ *
+ * It is an error to issue multiple ack_configure requests referencing a
+ * serial from the same configure event, or to issue an ack_configure
+ * request referencing a serial from a configure event issued before the
+ * event identified by the last ack_configure request for the same
+ * xdg_surface. Doing so will raise an invalid_serial error.
+ */
+static inline void
+xdg_surface_ack_configure(struct xdg_surface *xdg_surface, uint32_t serial)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
+ XDG_SURFACE_ACK_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, serial);
+}
+
+#ifndef XDG_TOPLEVEL_ERROR_ENUM
+#define XDG_TOPLEVEL_ERROR_ENUM
+enum xdg_toplevel_error {
+ /**
+ * provided value is not a valid variant of the resize_edge enum
+ */
+ XDG_TOPLEVEL_ERROR_INVALID_RESIZE_EDGE = 0,
+ /**
+ * invalid parent toplevel
+ */
+ XDG_TOPLEVEL_ERROR_INVALID_PARENT = 1,
+ /**
+ * client provided an invalid min or max size
+ */
+ XDG_TOPLEVEL_ERROR_INVALID_SIZE = 2,
+};
+#endif /* XDG_TOPLEVEL_ERROR_ENUM */
+
+#ifndef XDG_TOPLEVEL_RESIZE_EDGE_ENUM
+#define XDG_TOPLEVEL_RESIZE_EDGE_ENUM
+/**
+ * @ingroup iface_xdg_toplevel
+ * edge values for resizing
+ *
+ * These values are used to indicate which edge of a surface
+ * is being dragged in a resize operation.
+ */
+enum xdg_toplevel_resize_edge {
+ XDG_TOPLEVEL_RESIZE_EDGE_NONE = 0,
+ XDG_TOPLEVEL_RESIZE_EDGE_TOP = 1,
+ XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM = 2,
+ XDG_TOPLEVEL_RESIZE_EDGE_LEFT = 4,
+ XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT = 5,
+ XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT = 6,
+ XDG_TOPLEVEL_RESIZE_EDGE_RIGHT = 8,
+ XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT = 9,
+ XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT = 10,
+};
+#endif /* XDG_TOPLEVEL_RESIZE_EDGE_ENUM */
+
+#ifndef XDG_TOPLEVEL_STATE_ENUM
+#define XDG_TOPLEVEL_STATE_ENUM
+/**
+ * @ingroup iface_xdg_toplevel
+ * types of state on the surface
+ *
+ * The different state values used on the surface. This is designed for
+ * state values like maximized, fullscreen. It is paired with the
+ * configure event to ensure that both the client and the compositor
+ * setting the state can be synchronized.
+ *
+ * States set in this way are double-buffered, see wl_surface.commit.
+ */
+enum xdg_toplevel_state {
+ /**
+ * the surface is maximized
+ * the surface is maximized
+ *
+ * The surface is maximized. The window geometry specified in the
+ * configure event must be obeyed by the client, or the
+ * xdg_wm_base.invalid_surface_state error is raised.
+ *
+ * The client should draw without shadow or other decoration
+ * outside of the window geometry.
+ */
+ XDG_TOPLEVEL_STATE_MAXIMIZED = 1,
+ /**
+ * the surface is fullscreen
+ * the surface is fullscreen
+ *
+ * The surface is fullscreen. The window geometry specified in
+ * the configure event is a maximum; the client cannot resize
+ * beyond it. For a surface to cover the whole fullscreened area,
+ * the geometry dimensions must be obeyed by the client. For more
+ * details, see xdg_toplevel.set_fullscreen.
+ */
+ XDG_TOPLEVEL_STATE_FULLSCREEN = 2,
+ /**
+ * the surface is being resized
+ * the surface is being resized
+ *
+ * The surface is being resized. The window geometry specified in
+ * the configure event is a maximum; the client cannot resize
+ * beyond it. Clients that have aspect ratio or cell sizing
+ * configuration can use a smaller size, however.
+ */
+ XDG_TOPLEVEL_STATE_RESIZING = 3,
+ /**
+ * the surface is now activated
+ * the surface is now activated
+ *
+ * Client window decorations should be painted as if the window
+ * is active. Do not assume this means that the window actually has
+ * keyboard or pointer focus.
+ */
+ XDG_TOPLEVEL_STATE_ACTIVATED = 4,
+ /**
+ * the surface’s left edge is tiled
+ *
+ * The window is currently in a tiled layout and the left edge is
+ * considered to be adjacent to another part of the tiling grid.
+ *
+ * The client should draw without shadow or other decoration
+ * outside of the window geometry on the left edge.
+ * @since 2
+ */
+ XDG_TOPLEVEL_STATE_TILED_LEFT = 5,
+ /**
+ * the surface’s right edge is tiled
+ *
+ * The window is currently in a tiled layout and the right edge
+ * is considered to be adjacent to another part of the tiling grid.
+ *
+ * The client should draw without shadow or other decoration
+ * outside of the window geometry on the right edge.
+ * @since 2
+ */
+ XDG_TOPLEVEL_STATE_TILED_RIGHT = 6,
+ /**
+ * the surface’s top edge is tiled
+ *
+ * The window is currently in a tiled layout and the top edge is
+ * considered to be adjacent to another part of the tiling grid.
+ *
+ * The client should draw without shadow or other decoration
+ * outside of the window geometry on the top edge.
+ * @since 2
+ */
+ XDG_TOPLEVEL_STATE_TILED_TOP = 7,
+ /**
+ * the surface’s bottom edge is tiled
+ *
+ * The window is currently in a tiled layout and the bottom edge
+ * is considered to be adjacent to another part of the tiling grid.
+ *
+ * The client should draw without shadow or other decoration
+ * outside of the window geometry on the bottom edge.
+ * @since 2
+ */
+ XDG_TOPLEVEL_STATE_TILED_BOTTOM = 8,
+ /**
+ * surface repaint is suspended
+ *
+ * The surface is currently not ordinarily being repainted; for
+ * example because its content is occluded by another window, or
+ * its outputs are switched off due to screen locking.
+ * @since 6
+ */
+ XDG_TOPLEVEL_STATE_SUSPENDED = 9,
+ /**
+ * the surface’s left edge is constrained
+ *
+ * The left edge of the window is currently constrained, meaning
+ * it shouldn't attempt to resize from that edge. It can for
+ * example mean it's tiled next to a monitor edge on the
+ * constrained side of the window.
+ * @since 7
+ */
+ XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT = 10,
+ /**
+ * the surface’s right edge is constrained
+ *
+ * The right edge of the window is currently constrained, meaning
+ * it shouldn't attempt to resize from that edge. It can for
+ * example mean it's tiled next to a monitor edge on the
+ * constrained side of the window.
+ * @since 7
+ */
+ XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT = 11,
+ /**
+ * the surface’s top edge is constrained
+ *
+ * The top edge of the window is currently constrained, meaning
+ * it shouldn't attempt to resize from that edge. It can for
+ * example mean it's tiled next to a monitor edge on the
+ * constrained side of the window.
+ * @since 7
+ */
+ XDG_TOPLEVEL_STATE_CONSTRAINED_TOP = 12,
+ /**
+ * the surface’s bottom edge is tiled
+ *
+ * The bottom edge of the window is currently constrained,
+ * meaning it shouldn't attempt to resize from that edge. It can
+ * for example mean it's tiled next to a monitor edge on the
+ * constrained side of the window.
+ * @since 7
+ */
+ XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM = 13,
+};
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION 2
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION 2
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_TILED_TOP_SINCE_VERSION 2
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_TILED_BOTTOM_SINCE_VERSION 2
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION 6
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION 7
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT_SINCE_VERSION 7
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_CONSTRAINED_TOP_SINCE_VERSION 7
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM_SINCE_VERSION 7
+#endif /* XDG_TOPLEVEL_STATE_ENUM */
+
+#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM
+#define XDG_TOPLEVEL_WM_CAPABILITIES_ENUM
+enum xdg_toplevel_wm_capabilities {
+ /**
+ * show_window_menu is available
+ */
+ XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU = 1,
+ /**
+ * set_maximized and unset_maximized are available
+ */
+ XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE = 2,
+ /**
+ * set_fullscreen and unset_fullscreen are available
+ */
+ XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 3,
+ /**
+ * set_minimized is available
+ */
+ XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE = 4,
+};
+#endif /* XDG_TOPLEVEL_WM_CAPABILITIES_ENUM */
+
+/**
+ * @ingroup iface_xdg_toplevel
+ * @struct xdg_toplevel_listener
+ */
+struct xdg_toplevel_listener {
+ /**
+ * suggest a surface change
+ *
+ * This configure event asks the client to resize its toplevel
+ * surface or to change its state. The configured state should not
+ * be applied immediately. See xdg_surface.configure for details.
+ *
+ * The width and height arguments specify a hint to the window
+ * about how its surface should be resized in window geometry
+ * coordinates. See set_window_geometry.
+ *
+ * If the width or height arguments are zero, it means the client
+ * should decide its own window dimension. This may happen when the
+ * compositor needs to configure the state of the surface but
+ * doesn't have any information about any previous or expected
+ * dimension.
+ *
+ * The states listed in the event specify how the width/height
+ * arguments should be interpreted, and possibly how it should be
+ * drawn.
+ *
+ * Clients must send an ack_configure in response to this event.
+ * See xdg_surface.configure and xdg_surface.ack_configure for
+ * details.
+ */
+ void (*configure)(void *data,
+ struct xdg_toplevel *xdg_toplevel,
+ int32_t width,
+ int32_t height,
+ struct wl_array *states);
+ /**
+ * surface wants to be closed
+ *
+ * The close event is sent by the compositor when the user wants
+ * the surface to be closed. This should be equivalent to the user
+ * clicking the close button in client-side decorations, if your
+ * application has any.
+ *
+ * This is only a request that the user intends to close the
+ * window. The client may choose to ignore this request, or show a
+ * dialog to ask the user to save their data, etc.
+ */
+ void (*close)(void *data,
+ struct xdg_toplevel *xdg_toplevel);
+ /**
+ * recommended window geometry bounds
+ *
+ * The configure_bounds event may be sent prior to a
+ * xdg_toplevel.configure event to communicate the bounds a window
+ * geometry size is recommended to constrain to.
+ *
+ * The passed width and height are in surface coordinate space. If
+ * width and height are 0, it means bounds is unknown and
+ * equivalent to as if no configure_bounds event was ever sent for
+ * this surface.
+ *
+ * The bounds can for example correspond to the size of a monitor
+ * excluding any panels or other shell components, so that a
+ * surface isn't created in a way that it cannot fit.
+ *
+ * The bounds may change at any point, and in such a case, a new
+ * xdg_toplevel.configure_bounds will be sent, followed by
+ * xdg_toplevel.configure and xdg_surface.configure.
+ * @since 4
+ */
+ void (*configure_bounds)(void *data,
+ struct xdg_toplevel *xdg_toplevel,
+ int32_t width,
+ int32_t height);
+ /**
+ * compositor capabilities
+ *
+ * This event advertises the capabilities supported by the
+ * compositor. If a capability isn't supported, clients should hide
+ * or disable the UI elements that expose this functionality. For
+ * instance, if the compositor doesn't advertise support for
+ * minimized toplevels, a button triggering the set_minimized
+ * request should not be displayed.
+ *
+ * The compositor will ignore requests it doesn't support. For
+ * instance, a compositor which doesn't advertise support for
+ * minimized will ignore set_minimized requests.
+ *
+ * Compositors must send this event once before the first
+ * xdg_surface.configure event. When the capabilities change,
+ * compositors must send this event again and then send an
+ * xdg_surface.configure event.
+ *
+ * The configured state should not be applied immediately. See
+ * xdg_surface.configure for details.
+ *
+ * The capabilities are sent as an array of 32-bit unsigned
+ * integers in native endianness.
+ * @param capabilities array of 32-bit capabilities
+ * @since 5
+ */
+ void (*wm_capabilities)(void *data,
+ struct xdg_toplevel *xdg_toplevel,
+ struct wl_array *capabilities);
+};
+
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+static inline int
+xdg_toplevel_add_listener(struct xdg_toplevel *xdg_toplevel,
+ const struct xdg_toplevel_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) xdg_toplevel,
+ (void (**)(void)) listener, data);
+}
+
+#define XDG_TOPLEVEL_DESTROY 0
+#define XDG_TOPLEVEL_SET_PARENT 1
+#define XDG_TOPLEVEL_SET_TITLE 2
+#define XDG_TOPLEVEL_SET_APP_ID 3
+#define XDG_TOPLEVEL_SHOW_WINDOW_MENU 4
+#define XDG_TOPLEVEL_MOVE 5
+#define XDG_TOPLEVEL_RESIZE 6
+#define XDG_TOPLEVEL_SET_MAX_SIZE 7
+#define XDG_TOPLEVEL_SET_MIN_SIZE 8
+#define XDG_TOPLEVEL_SET_MAXIMIZED 9
+#define XDG_TOPLEVEL_UNSET_MAXIMIZED 10
+#define XDG_TOPLEVEL_SET_FULLSCREEN 11
+#define XDG_TOPLEVEL_UNSET_FULLSCREEN 12
+#define XDG_TOPLEVEL_SET_MINIMIZED 13
+
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_CONFIGURE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_CLOSE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION 4
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION 5
+
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_DESTROY_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_PARENT_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_TITLE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_APP_ID_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SHOW_WINDOW_MENU_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_MOVE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_RESIZE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_MAX_SIZE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_MIN_SIZE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_MAXIMIZED_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_UNSET_MAXIMIZED_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_FULLSCREEN_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_UNSET_FULLSCREEN_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_toplevel
+ */
+#define XDG_TOPLEVEL_SET_MINIMIZED_SINCE_VERSION 1
+
+/** @ingroup iface_xdg_toplevel */
+static inline void
+xdg_toplevel_set_user_data(struct xdg_toplevel *xdg_toplevel, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) xdg_toplevel, user_data);
+}
+
+/** @ingroup iface_xdg_toplevel */
+static inline void *
+xdg_toplevel_get_user_data(struct xdg_toplevel *xdg_toplevel)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) xdg_toplevel);
+}
+
+static inline uint32_t
+xdg_toplevel_get_version(struct xdg_toplevel *xdg_toplevel)
+{
+ return wl_proxy_get_version((struct wl_proxy *) xdg_toplevel);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * This request destroys the role surface and unmaps the surface;
+ * see "Unmapping" behavior in interface section for details.
+ */
+static inline void
+xdg_toplevel_destroy(struct xdg_toplevel *xdg_toplevel)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), WL_MARSHAL_FLAG_DESTROY);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Set the "parent" of this surface. This surface should be stacked
+ * above the parent surface and all other ancestor surfaces.
+ *
+ * Parent surfaces should be set on dialogs, toolboxes, or other
+ * "auxiliary" surfaces, so that the parent is raised when the dialog
+ * is raised.
+ *
+ * Setting a null parent for a child surface unsets its parent. Setting
+ * a null parent for a surface which currently has no parent is a no-op.
+ *
+ * Only mapped surfaces can have child surfaces. Setting a parent which
+ * is not mapped is equivalent to setting a null parent. If a surface
+ * becomes unmapped, its children's parent is set to the parent of
+ * the now-unmapped surface. If the now-unmapped surface has no parent,
+ * its children's parent is unset. If the now-unmapped surface becomes
+ * mapped again, its parent-child relationship is not restored.
+ *
+ * The parent toplevel must not be one of the child toplevel's
+ * descendants, and the parent must be different from the child toplevel,
+ * otherwise the invalid_parent protocol error is raised.
+ */
+static inline void
+xdg_toplevel_set_parent(struct xdg_toplevel *xdg_toplevel, struct xdg_toplevel *parent)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_PARENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, parent);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Set a short title for the surface.
+ *
+ * This string may be used to identify the surface in a task bar,
+ * window list, or other user interface elements provided by the
+ * compositor.
+ *
+ * The string must be encoded in UTF-8.
+ */
+static inline void
+xdg_toplevel_set_title(struct xdg_toplevel *xdg_toplevel, const char *title)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_TITLE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, title);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Set an application identifier for the surface.
+ *
+ * The app ID identifies the general class of applications to which
+ * the surface belongs. The compositor can use this to group multiple
+ * surfaces together, or to determine how to launch a new application.
+ *
+ * For D-Bus activatable applications, the app ID is used as the D-Bus
+ * service name.
+ *
+ * The compositor shell will try to group application surfaces together
+ * by their app ID. As a best practice, it is suggested to select app
+ * ID's that match the basename of the application's .desktop file.
+ * For example, "org.freedesktop.FooViewer" where the .desktop file is
+ * "org.freedesktop.FooViewer.desktop".
+ *
+ * Like other properties, a set_app_id request can be sent after the
+ * xdg_toplevel has been mapped to update the property.
+ *
+ * See the desktop-entry specification [0] for more details on
+ * application identifiers and how they relate to well-known D-Bus
+ * names and .desktop files.
+ *
+ * [0] https://standards.freedesktop.org/desktop-entry-spec/
+ */
+static inline void
+xdg_toplevel_set_app_id(struct xdg_toplevel *xdg_toplevel, const char *app_id)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_APP_ID, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, app_id);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Clients implementing client-side decorations might want to show
+ * a context menu when right-clicking on the decorations, giving the
+ * user a menu that they can use to maximize or minimize the window.
+ *
+ * This request asks the compositor to pop up such a window menu at
+ * the given position, relative to the local surface coordinates of
+ * the parent surface. There are no guarantees as to what menu items
+ * the window menu contains, or even if a window menu will be drawn
+ * at all.
+ *
+ * This request must be used in response to some sort of user action
+ * like a button press, key press, or touch down event.
+ */
+static inline void
+xdg_toplevel_show_window_menu(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, int32_t x, int32_t y)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SHOW_WINDOW_MENU, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, x, y);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Start an interactive, user-driven move of the surface.
+ *
+ * This request must be used in response to some sort of user action
+ * like a button press, key press, or touch down event. The passed
+ * serial is used to determine the type of interactive move (touch,
+ * pointer, etc).
+ *
+ * The server may ignore move requests depending on the state of
+ * the surface (e.g. fullscreen or maximized), or if the passed serial
+ * is no longer valid.
+ *
+ * If triggered, the surface will lose the focus of the device
+ * (wl_pointer, wl_touch, etc) used for the move. It is up to the
+ * compositor to visually indicate that the move is taking place, such as
+ * updating a pointer cursor, during the move. There is no guarantee
+ * that the device focus will return when the move is completed.
+ */
+static inline void
+xdg_toplevel_move(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_MOVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Start a user-driven, interactive resize of the surface.
+ *
+ * This request must be used in response to some sort of user action
+ * like a button press, key press, or touch down event. The passed
+ * serial is used to determine the type of interactive resize (touch,
+ * pointer, etc).
+ *
+ * The server may ignore resize requests depending on the state of
+ * the surface (e.g. fullscreen or maximized).
+ *
+ * If triggered, the client will receive configure events with the
+ * "resize" state enum value and the expected sizes. See the "resize"
+ * enum value for more details about what is required. The client
+ * must also acknowledge configure events using "ack_configure". After
+ * the resize is completed, the client will receive another "configure"
+ * event without the resize state.
+ *
+ * If triggered, the surface also will lose the focus of the device
+ * (wl_pointer, wl_touch, etc) used for the resize. It is up to the
+ * compositor to visually indicate that the resize is taking place,
+ * such as updating a pointer cursor, during the resize. There is no
+ * guarantee that the device focus will return when the resize is
+ * completed.
+ *
+ * The edges parameter specifies how the surface should be resized, and
+ * is one of the values of the resize_edge enum. Values not matching
+ * a variant of the enum will cause the invalid_resize_edge protocol error.
+ * The compositor may use this information to update the surface position
+ * for example when dragging the top left corner. The compositor may also
+ * use this information to adapt its behavior, e.g. choose an appropriate
+ * cursor image.
+ */
+static inline void
+xdg_toplevel_resize(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, uint32_t edges)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, edges);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Set a maximum size for the window.
+ *
+ * The client can specify a maximum size so that the compositor does
+ * not try to configure the window beyond this size.
+ *
+ * The width and height arguments are in window geometry coordinates.
+ * See xdg_surface.set_window_geometry.
+ *
+ * Values set in this way are double-buffered, see wl_surface.commit.
+ *
+ * The compositor can use this information to allow or disallow
+ * different states like maximize or fullscreen and draw accurate
+ * animations.
+ *
+ * Similarly, a tiling window manager may use this information to
+ * place and resize client windows in a more effective way.
+ *
+ * The client should not rely on the compositor to obey the maximum
+ * size. The compositor may decide to ignore the values set by the
+ * client and request a larger size.
+ *
+ * If never set, or a value of zero in the request, means that the
+ * client has no expected maximum size in the given dimension.
+ * As a result, a client wishing to reset the maximum size
+ * to an unspecified state can use zero for width and height in the
+ * request.
+ *
+ * Requesting a maximum size to be smaller than the minimum size of
+ * a surface is illegal and will result in an invalid_size error.
+ *
+ * The width and height must be greater than or equal to zero. Using
+ * strictly negative values for width or height will result in a
+ * invalid_size error.
+ */
+static inline void
+xdg_toplevel_set_max_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_MAX_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Set a minimum size for the window.
+ *
+ * The client can specify a minimum size so that the compositor does
+ * not try to configure the window below this size.
+ *
+ * The width and height arguments are in window geometry coordinates.
+ * See xdg_surface.set_window_geometry.
+ *
+ * Values set in this way are double-buffered, see wl_surface.commit.
+ *
+ * The compositor can use this information to allow or disallow
+ * different states like maximize or fullscreen and draw accurate
+ * animations.
+ *
+ * Similarly, a tiling window manager may use this information to
+ * place and resize client windows in a more effective way.
+ *
+ * The client should not rely on the compositor to obey the minimum
+ * size. The compositor may decide to ignore the values set by the
+ * client and request a smaller size.
+ *
+ * If never set, or a value of zero in the request, means that the
+ * client has no expected minimum size in the given dimension.
+ * As a result, a client wishing to reset the minimum size
+ * to an unspecified state can use zero for width and height in the
+ * request.
+ *
+ * Requesting a minimum size to be larger than the maximum size of
+ * a surface is illegal and will result in an invalid_size error.
+ *
+ * The width and height must be greater than or equal to zero. Using
+ * strictly negative values for width and height will result in a
+ * invalid_size error.
+ */
+static inline void
+xdg_toplevel_set_min_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_MIN_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Maximize the surface.
+ *
+ * After requesting that the surface should be maximized, the compositor
+ * will respond by emitting a configure event. Whether this configure
+ * actually sets the window maximized is subject to compositor policies.
+ * The client must then update its content, drawing in the configured
+ * state. The client must also acknowledge the configure when committing
+ * the new content (see ack_configure).
+ *
+ * It is up to the compositor to decide how and where to maximize the
+ * surface, for example which output and what region of the screen should
+ * be used.
+ *
+ * If the surface was already maximized, the compositor will still emit
+ * a configure event with the "maximized" state.
+ *
+ * If the surface is in a fullscreen state, this request has no direct
+ * effect. It may alter the state the surface is returned to when
+ * unmaximized unless overridden by the compositor.
+ */
+static inline void
+xdg_toplevel_set_maximized(struct xdg_toplevel *xdg_toplevel)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Unmaximize the surface.
+ *
+ * After requesting that the surface should be unmaximized, the compositor
+ * will respond by emitting a configure event. Whether this actually
+ * un-maximizes the window is subject to compositor policies.
+ * If available and applicable, the compositor will include the window
+ * geometry dimensions the window had prior to being maximized in the
+ * configure event. The client must then update its content, drawing it in
+ * the configured state. The client must also acknowledge the configure
+ * when committing the new content (see ack_configure).
+ *
+ * It is up to the compositor to position the surface after it was
+ * unmaximized; usually the position the surface had before maximizing, if
+ * applicable.
+ *
+ * If the surface was already not maximized, the compositor will still
+ * emit a configure event without the "maximized" state.
+ *
+ * If the surface is in a fullscreen state, this request has no direct
+ * effect. It may alter the state the surface is returned to when
+ * unmaximized unless overridden by the compositor.
+ */
+static inline void
+xdg_toplevel_unset_maximized(struct xdg_toplevel *xdg_toplevel)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_UNSET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Make the surface fullscreen.
+ *
+ * After requesting that the surface should be fullscreened, the
+ * compositor will respond by emitting a configure event. Whether the
+ * client is actually put into a fullscreen state is subject to compositor
+ * policies. The client must also acknowledge the configure when
+ * committing the new content (see ack_configure).
+ *
+ * The output passed by the request indicates the client's preference as
+ * to which display it should be set fullscreen on. If this value is NULL,
+ * it's up to the compositor to choose which display will be used to map
+ * this surface.
+ *
+ * If the surface doesn't cover the whole output, the compositor will
+ * position the surface in the center of the output and compensate with
+ * with border fill covering the rest of the output. The content of the
+ * border fill is undefined, but should be assumed to be in some way that
+ * attempts to blend into the surrounding area (e.g. solid black).
+ *
+ * If the fullscreened surface is not opaque, the compositor must make
+ * sure that other screen content not part of the same surface tree (made
+ * up of subsurfaces, popups or similarly coupled surfaces) are not
+ * visible below the fullscreened surface.
+ */
+static inline void
+xdg_toplevel_set_fullscreen(struct xdg_toplevel *xdg_toplevel, struct wl_output *output)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, output);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Make the surface no longer fullscreen.
+ *
+ * After requesting that the surface should be unfullscreened, the
+ * compositor will respond by emitting a configure event.
+ * Whether this actually removes the fullscreen state of the client is
+ * subject to compositor policies.
+ *
+ * Making a surface unfullscreen sets states for the surface based on the following:
+ * * the state(s) it may have had before becoming fullscreen
+ * * any state(s) decided by the compositor
+ * * any state(s) requested by the client while the surface was fullscreen
+ *
+ * The compositor may include the previous window geometry dimensions in
+ * the configure event, if applicable.
+ *
+ * The client must also acknowledge the configure when committing the new
+ * content (see ack_configure).
+ */
+static inline void
+xdg_toplevel_unset_fullscreen(struct xdg_toplevel *xdg_toplevel)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_UNSET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
+}
+
+/**
+ * @ingroup iface_xdg_toplevel
+ *
+ * Request that the compositor minimize your surface. There is no
+ * way to know if the surface is currently minimized, nor is there
+ * any way to unset minimization on this surface.
+ *
+ * If you are looking to throttle redrawing when minimized, please
+ * instead use the wl_surface.frame event for this, as this will
+ * also work with live previews on windows in Alt-Tab, Expose or
+ * similar compositor features.
+ */
+static inline void
+xdg_toplevel_set_minimized(struct xdg_toplevel *xdg_toplevel)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
+ XDG_TOPLEVEL_SET_MINIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
+}
+
+#ifndef XDG_POPUP_ERROR_ENUM
+#define XDG_POPUP_ERROR_ENUM
+enum xdg_popup_error {
+ /**
+ * tried to grab after being mapped
+ */
+ XDG_POPUP_ERROR_INVALID_GRAB = 0,
+};
+#endif /* XDG_POPUP_ERROR_ENUM */
+
+/**
+ * @ingroup iface_xdg_popup
+ * @struct xdg_popup_listener
+ */
+struct xdg_popup_listener {
+ /**
+ * configure the popup surface
+ *
+ * This event asks the popup surface to configure itself given
+ * the configuration. The configured state should not be applied
+ * immediately. See xdg_surface.configure for details.
+ *
+ * The x and y arguments represent the position the popup was
+ * placed at given the xdg_positioner rule, relative to the upper
+ * left corner of the window geometry of the parent surface.
+ *
+ * For version 2 or older, the configure event for an xdg_popup is
+ * only ever sent once for the initial configuration. Starting with
+ * version 3, it may be sent again if the popup is setup with an
+ * xdg_positioner with set_reactive requested, or in response to
+ * xdg_popup.reposition requests.
+ * @param x x position relative to parent surface window geometry
+ * @param y y position relative to parent surface window geometry
+ * @param width window geometry width
+ * @param height window geometry height
+ */
+ void (*configure)(void *data,
+ struct xdg_popup *xdg_popup,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height);
+ /**
+ * popup interaction is done
+ *
+ * The popup_done event is sent out when a popup is dismissed by
+ * the compositor. The client should destroy the xdg_popup object
+ * at this point.
+ */
+ void (*popup_done)(void *data,
+ struct xdg_popup *xdg_popup);
+ /**
+ * signal the completion of a repositioned request
+ *
+ * The repositioned event is sent as part of a popup
+ * configuration sequence, together with xdg_popup.configure and
+ * lastly xdg_surface.configure to notify the completion of a
+ * reposition request.
+ *
+ * The repositioned event is to notify about the completion of a
+ * xdg_popup.reposition request. The token argument is the token
+ * passed in the xdg_popup.reposition request.
+ *
+ * Immediately after this event is emitted, xdg_popup.configure and
+ * xdg_surface.configure will be sent with the updated size and
+ * position, as well as a new configure serial.
+ *
+ * The client should optionally update the content of the popup,
+ * but must acknowledge the new popup configuration for the new
+ * position to take effect. See xdg_surface.ack_configure for
+ * details.
+ * @param token reposition request token
+ * @since 3
+ */
+ void (*repositioned)(void *data,
+ struct xdg_popup *xdg_popup,
+ uint32_t token);
+};
+
+/**
+ * @ingroup iface_xdg_popup
+ */
+static inline int
+xdg_popup_add_listener(struct xdg_popup *xdg_popup,
+ const struct xdg_popup_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) xdg_popup,
+ (void (**)(void)) listener, data);
+}
+
+#define XDG_POPUP_DESTROY 0
+#define XDG_POPUP_GRAB 1
+#define XDG_POPUP_REPOSITION 2
+
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_CONFIGURE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_POPUP_DONE_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_REPOSITIONED_SINCE_VERSION 3
+
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_DESTROY_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_GRAB_SINCE_VERSION 1
+/**
+ * @ingroup iface_xdg_popup
+ */
+#define XDG_POPUP_REPOSITION_SINCE_VERSION 3
+
+/** @ingroup iface_xdg_popup */
+static inline void
+xdg_popup_set_user_data(struct xdg_popup *xdg_popup, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) xdg_popup, user_data);
+}
+
+/** @ingroup iface_xdg_popup */
+static inline void *
+xdg_popup_get_user_data(struct xdg_popup *xdg_popup)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) xdg_popup);
+}
+
+static inline uint32_t
+xdg_popup_get_version(struct xdg_popup *xdg_popup)
+{
+ return wl_proxy_get_version((struct wl_proxy *) xdg_popup);
+}
+
+/**
+ * @ingroup iface_xdg_popup
+ *
+ * This destroys the popup. Explicitly destroying the xdg_popup
+ * object will also dismiss the popup, and unmap the surface.
+ *
+ * If this xdg_popup is not the "topmost" popup, the
+ * xdg_wm_base.not_the_topmost_popup protocol error will be sent.
+ */
+static inline void
+xdg_popup_destroy(struct xdg_popup *xdg_popup)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup,
+ XDG_POPUP_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), WL_MARSHAL_FLAG_DESTROY);
+}
+
+/**
+ * @ingroup iface_xdg_popup
+ *
+ * This request makes the created popup take an explicit grab. An explicit
+ * grab will be dismissed when the user dismisses the popup, or when the
+ * client destroys the xdg_popup. This can be done by the user clicking
+ * outside the surface, using the keyboard, or even locking the screen
+ * through closing the lid or a timeout.
+ *
+ * If the compositor denies the grab, the popup will be immediately
+ * dismissed.
+ *
+ * This request must be used in response to some sort of user action like a
+ * button press, key press, or touch down event. The serial number of the
+ * event should be passed as 'serial'.
+ *
+ * The parent of a grabbing popup must either be an xdg_toplevel surface or
+ * another xdg_popup with an explicit grab. If the parent is another
+ * xdg_popup it means that the popups are nested, with this popup now being
+ * the topmost popup.
+ *
+ * Nested popups must be destroyed in the reverse order they were created
+ * in, e.g. the only popup you are allowed to destroy at all times is the
+ * topmost one.
+ *
+ * When compositors choose to dismiss a popup, they may dismiss every
+ * nested grabbing popup as well. When a compositor dismisses popups, it
+ * will follow the same dismissing order as required from the client.
+ *
+ * If the topmost grabbing popup is destroyed, the grab will be returned to
+ * the parent of the popup, if that parent previously had an explicit grab.
+ *
+ * If the parent is a grabbing popup which has already been dismissed, this
+ * popup will be immediately dismissed. If the parent is a popup that did
+ * not take an explicit grab, an error will be raised.
+ *
+ * During a popup grab, the client owning the grab will receive pointer
+ * and touch events for all their surfaces as normal (similar to an
+ * "owner-events" grab in X11 parlance), while the top most grabbing popup
+ * will always have keyboard focus.
+ */
+static inline void
+xdg_popup_grab(struct xdg_popup *xdg_popup, struct wl_seat *seat, uint32_t serial)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup,
+ XDG_POPUP_GRAB, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, seat, serial);
+}
+
+/**
+ * @ingroup iface_xdg_popup
+ *
+ * Reposition an already-mapped popup. The popup will be placed given the
+ * details in the passed xdg_positioner object, and a
+ * xdg_popup.repositioned followed by xdg_popup.configure and
+ * xdg_surface.configure will be emitted in response. Any parameters set
+ * by the previous positioner will be discarded.
+ *
+ * The passed token will be sent in the corresponding
+ * xdg_popup.repositioned event. The new popup position will not take
+ * effect until the corresponding configure event is acknowledged by the
+ * client. See xdg_popup.repositioned for details. The token itself is
+ * opaque, and has no other special meaning.
+ *
+ * If multiple reposition requests are sent, the compositor may skip all
+ * but the last one.
+ *
+ * If the popup is repositioned in response to a configure event for its
+ * parent, the client should send an xdg_positioner.set_parent_configure
+ * and possibly an xdg_positioner.set_parent_size request to allow the
+ * compositor to properly constrain the popup.
+ *
+ * If the popup is repositioned together with a parent that is being
+ * resized, but not in response to a configure event, the client should
+ * send an xdg_positioner.set_parent_size request.
+ */
+static inline void
+xdg_popup_reposition(struct xdg_popup *xdg_popup, struct xdg_positioner *positioner, uint32_t token)
+{
+ wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup,
+ XDG_POPUP_REPOSITION, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, positioner, token);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* Generated by wayland-scanner 1.23.1 */
+
+/*
+ * Copyright © 2008-2013 Kristian Høgsberg
+ * Copyright © 2013 Rafael Antognolli
+ * Copyright © 2013 Jasper St. Pierre
+ * Copyright © 2010-2013 Intel Corporation
+ * Copyright © 2015-2017 Samsung Electronics Co., Ltd
+ * Copyright © 2015-2017 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
+#endif
+
+#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
+#define WL_PRIVATE __attribute__ ((visibility("hidden")))
+#else
+#define WL_PRIVATE
+#endif
+
+extern const struct wl_interface wl_output_interface;
+extern const struct wl_interface wl_seat_interface;
+extern const struct wl_interface wl_surface_interface;
+extern const struct wl_interface xdg_popup_interface;
+extern const struct wl_interface xdg_positioner_interface;
+extern const struct wl_interface xdg_surface_interface;
+extern const struct wl_interface xdg_toplevel_interface;
+
+static const struct wl_interface *xdg_shell_types[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &xdg_positioner_interface,
+ &xdg_surface_interface,
+ &wl_surface_interface,
+ &xdg_toplevel_interface,
+ &xdg_popup_interface,
+ &xdg_surface_interface,
+ &xdg_positioner_interface,
+ &xdg_toplevel_interface,
+ &wl_seat_interface,
+ NULL,
+ NULL,
+ NULL,
+ &wl_seat_interface,
+ NULL,
+ &wl_seat_interface,
+ NULL,
+ NULL,
+ &wl_output_interface,
+ &wl_seat_interface,
+ NULL,
+ &xdg_positioner_interface,
+ NULL,
+};
+
+static const struct wl_message xdg_wm_base_requests[] = {
+ { "destroy", "", xdg_shell_types + 0 },
+ { "create_positioner", "n", xdg_shell_types + 4 },
+ { "get_xdg_surface", "no", xdg_shell_types + 5 },
+ { "pong", "u", xdg_shell_types + 0 },
+};
+
+static const struct wl_message xdg_wm_base_events[] = {
+ { "ping", "u", xdg_shell_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface xdg_wm_base_interface = {
+ "xdg_wm_base", 7,
+ 4, xdg_wm_base_requests,
+ 1, xdg_wm_base_events,
+};
+
+static const struct wl_message xdg_positioner_requests[] = {
+ { "destroy", "", xdg_shell_types + 0 },
+ { "set_size", "ii", xdg_shell_types + 0 },
+ { "set_anchor_rect", "iiii", xdg_shell_types + 0 },
+ { "set_anchor", "u", xdg_shell_types + 0 },
+ { "set_gravity", "u", xdg_shell_types + 0 },
+ { "set_constraint_adjustment", "u", xdg_shell_types + 0 },
+ { "set_offset", "ii", xdg_shell_types + 0 },
+ { "set_reactive", "3", xdg_shell_types + 0 },
+ { "set_parent_size", "3ii", xdg_shell_types + 0 },
+ { "set_parent_configure", "3u", xdg_shell_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface xdg_positioner_interface = {
+ "xdg_positioner", 7,
+ 10, xdg_positioner_requests,
+ 0, NULL,
+};
+
+static const struct wl_message xdg_surface_requests[] = {
+ { "destroy", "", xdg_shell_types + 0 },
+ { "get_toplevel", "n", xdg_shell_types + 7 },
+ { "get_popup", "n?oo", xdg_shell_types + 8 },
+ { "set_window_geometry", "iiii", xdg_shell_types + 0 },
+ { "ack_configure", "u", xdg_shell_types + 0 },
+};
+
+static const struct wl_message xdg_surface_events[] = {
+ { "configure", "u", xdg_shell_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface xdg_surface_interface = {
+ "xdg_surface", 7,
+ 5, xdg_surface_requests,
+ 1, xdg_surface_events,
+};
+
+static const struct wl_message xdg_toplevel_requests[] = {
+ { "destroy", "", xdg_shell_types + 0 },
+ { "set_parent", "?o", xdg_shell_types + 11 },
+ { "set_title", "s", xdg_shell_types + 0 },
+ { "set_app_id", "s", xdg_shell_types + 0 },
+ { "show_window_menu", "ouii", xdg_shell_types + 12 },
+ { "move", "ou", xdg_shell_types + 16 },
+ { "resize", "ouu", xdg_shell_types + 18 },
+ { "set_max_size", "ii", xdg_shell_types + 0 },
+ { "set_min_size", "ii", xdg_shell_types + 0 },
+ { "set_maximized", "", xdg_shell_types + 0 },
+ { "unset_maximized", "", xdg_shell_types + 0 },
+ { "set_fullscreen", "?o", xdg_shell_types + 21 },
+ { "unset_fullscreen", "", xdg_shell_types + 0 },
+ { "set_minimized", "", xdg_shell_types + 0 },
+};
+
+static const struct wl_message xdg_toplevel_events[] = {
+ { "configure", "iia", xdg_shell_types + 0 },
+ { "close", "", xdg_shell_types + 0 },
+ { "configure_bounds", "4ii", xdg_shell_types + 0 },
+ { "wm_capabilities", "5a", xdg_shell_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface xdg_toplevel_interface = {
+ "xdg_toplevel", 7,
+ 14, xdg_toplevel_requests,
+ 4, xdg_toplevel_events,
+};
+
+static const struct wl_message xdg_popup_requests[] = {
+ { "destroy", "", xdg_shell_types + 0 },
+ { "grab", "ou", xdg_shell_types + 22 },
+ { "reposition", "3ou", xdg_shell_types + 24 },
+};
+
+static const struct wl_message xdg_popup_events[] = {
+ { "configure", "iiii", xdg_shell_types + 0 },
+ { "popup_done", "", xdg_shell_types + 0 },
+ { "repositioned", "3u", xdg_shell_types + 0 },
+};
+
+WL_PRIVATE const struct wl_interface xdg_popup_interface = {
+ "xdg_popup", 7,
+ 3, xdg_popup_requests,
+ 3, xdg_popup_events,
+};
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="xdg_shell">
+
+ <copyright>
+ Copyright © 2008-2013 Kristian Høgsberg
+ Copyright © 2013 Rafael Antognolli
+ Copyright © 2013 Jasper St. Pierre
+ Copyright © 2010-2013 Intel Corporation
+ Copyright © 2015-2017 Samsung Electronics Co., Ltd
+ Copyright © 2015-2017 Red Hat Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="xdg_wm_base" version="7">
+ <description summary="create desktop-style surfaces">
+ The xdg_wm_base interface is exposed as a global object enabling clients
+ to turn their wl_surfaces into windows in a desktop environment. It
+ defines the basic functionality needed for clients and the compositor to
+ create windows that can be dragged, resized, maximized, etc, as well as
+ creating transient windows such as popup menus.
+ </description>
+
+ <enum name="error">
+ <entry name="role" value="0" summary="given wl_surface has another role"/>
+ <entry name="defunct_surfaces" value="1"
+ summary="xdg_wm_base was destroyed before children"/>
+ <entry name="not_the_topmost_popup" value="2"
+ summary="the client tried to map or destroy a non-topmost popup"/>
+ <entry name="invalid_popup_parent" value="3"
+ summary="the client specified an invalid popup parent surface"/>
+ <entry name="invalid_surface_state" value="4"
+ summary="the client provided an invalid surface state"/>
+ <entry name="invalid_positioner" value="5"
+ summary="the client provided an invalid positioner"/>
+ <entry name="unresponsive" value="6"
+ summary="the client didn’t respond to a ping event in time"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy xdg_wm_base">
+ Destroy this xdg_wm_base object.
+
+ Destroying a bound xdg_wm_base object while there are surfaces
+ still alive created by this xdg_wm_base object instance is illegal
+ and will result in a defunct_surfaces error.
+ </description>
+ </request>
+
+ <request name="create_positioner">
+ <description summary="create a positioner object">
+ Create a positioner object. A positioner object is used to position
+ surfaces relative to some parent surface. See the interface description
+ and xdg_surface.get_popup for details.
+ </description>
+ <arg name="id" type="new_id" interface="xdg_positioner"/>
+ </request>
+
+ <request name="get_xdg_surface">
+ <description summary="create a shell surface from a surface">
+ This creates an xdg_surface for the given surface. While xdg_surface
+ itself is not a role, the corresponding surface may only be assigned
+ a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
+ illegal to create an xdg_surface for a wl_surface which already has an
+ assigned role and this will result in a role error.
+
+ This creates an xdg_surface for the given surface. An xdg_surface is
+ used as basis to define a role to a given surface, such as xdg_toplevel
+ or xdg_popup. It also manages functionality shared between xdg_surface
+ based surface roles.
+
+ See the documentation of xdg_surface for more details about what an
+ xdg_surface is and how it is used.
+ </description>
+ <arg name="id" type="new_id" interface="xdg_surface"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+
+ <request name="pong">
+ <description summary="respond to a ping event">
+ A client must respond to a ping event with a pong request or
+ the client may be deemed unresponsive. See xdg_wm_base.ping
+ and xdg_wm_base.error.unresponsive.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the ping event"/>
+ </request>
+
+ <event name="ping">
+ <description summary="check if the client is alive">
+ The ping event asks the client if it's still alive. Pass the
+ serial specified in the event back to the compositor by sending
+ a "pong" request back with the specified serial. See xdg_wm_base.pong.
+
+ Compositors can use this to determine if the client is still
+ alive. It's unspecified what will happen if the client doesn't
+ respond to the ping request, or in what timeframe. Clients should
+ try to respond in a reasonable amount of time. The “unresponsive”
+ error is provided for compositors that wish to disconnect unresponsive
+ clients.
+
+ A compositor is free to ping in any way it wants, but a client must
+ always respond to any xdg_wm_base object it created.
+ </description>
+ <arg name="serial" type="uint" summary="pass this to the pong request"/>
+ </event>
+ </interface>
+
+ <interface name="xdg_positioner" version="7">
+ <description summary="child surface positioner">
+ The xdg_positioner provides a collection of rules for the placement of a
+ child surface relative to a parent surface. Rules can be defined to ensure
+ the child surface remains within the visible area's borders, and to
+ specify how the child surface changes its position, such as sliding along
+ an axis, or flipping around a rectangle. These positioner-created rules are
+ constrained by the requirement that a child surface must intersect with or
+ be at least partially adjacent to its parent surface.
+
+ See the various requests for details about possible rules.
+
+ At the time of the request, the compositor makes a copy of the rules
+ specified by the xdg_positioner. Thus, after the request is complete the
+ xdg_positioner object can be destroyed or reused; further changes to the
+ object will have no effect on previous usages.
+
+ For an xdg_positioner object to be considered complete, it must have a
+ non-zero size set by set_size, and a non-zero anchor rectangle set by
+ set_anchor_rect. Passing an incomplete xdg_positioner object when
+ positioning a surface raises an invalid_positioner error.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_input" value="0" summary="invalid input provided"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xdg_positioner object">
+ Notify the compositor that the xdg_positioner will no longer be used.
+ </description>
+ </request>
+
+ <request name="set_size">
+ <description summary="set the size of the to-be positioned rectangle">
+ Set the size of the surface that is to be positioned with the positioner
+ object. The size is in surface-local coordinates and corresponds to the
+ window geometry. See xdg_surface.set_window_geometry.
+
+ If a zero or negative size is set the invalid_input error is raised.
+ </description>
+ <arg name="width" type="int" summary="width of positioned rectangle"/>
+ <arg name="height" type="int" summary="height of positioned rectangle"/>
+ </request>
+
+ <request name="set_anchor_rect">
+ <description summary="set the anchor rectangle within the parent surface">
+ Specify the anchor rectangle within the parent surface that the child
+ surface will be placed relative to. The rectangle is relative to the
+ window geometry as defined by xdg_surface.set_window_geometry of the
+ parent surface.
+
+ When the xdg_positioner object is used to position a child surface, the
+ anchor rectangle may not extend outside the window geometry of the
+ positioned child's parent surface.
+
+ If a negative size is set the invalid_input error is raised.
+ </description>
+ <arg name="x" type="int" summary="x position of anchor rectangle"/>
+ <arg name="y" type="int" summary="y position of anchor rectangle"/>
+ <arg name="width" type="int" summary="width of anchor rectangle"/>
+ <arg name="height" type="int" summary="height of anchor rectangle"/>
+ </request>
+
+ <enum name="anchor">
+ <entry name="none" value="0"/>
+ <entry name="top" value="1"/>
+ <entry name="bottom" value="2"/>
+ <entry name="left" value="3"/>
+ <entry name="right" value="4"/>
+ <entry name="top_left" value="5"/>
+ <entry name="bottom_left" value="6"/>
+ <entry name="top_right" value="7"/>
+ <entry name="bottom_right" value="8"/>
+ </enum>
+
+ <request name="set_anchor">
+ <description summary="set anchor rectangle anchor">
+ Defines the anchor point for the anchor rectangle. The specified anchor
+ is used derive an anchor point that the child surface will be
+ positioned relative to. If a corner anchor is set (e.g. 'top_left' or
+ 'bottom_right'), the anchor point will be at the specified corner;
+ otherwise, the derived anchor point will be centered on the specified
+ edge, or in the center of the anchor rectangle if no edge is specified.
+ </description>
+ <arg name="anchor" type="uint" enum="anchor"
+ summary="anchor"/>
+ </request>
+
+ <enum name="gravity">
+ <entry name="none" value="0"/>
+ <entry name="top" value="1"/>
+ <entry name="bottom" value="2"/>
+ <entry name="left" value="3"/>
+ <entry name="right" value="4"/>
+ <entry name="top_left" value="5"/>
+ <entry name="bottom_left" value="6"/>
+ <entry name="top_right" value="7"/>
+ <entry name="bottom_right" value="8"/>
+ </enum>
+
+ <request name="set_gravity">
+ <description summary="set child surface gravity">
+ Defines in what direction a surface should be positioned, relative to
+ the anchor point of the parent surface. If a corner gravity is
+ specified (e.g. 'bottom_right' or 'top_left'), then the child surface
+ will be placed towards the specified gravity; otherwise, the child
+ surface will be centered over the anchor point on any axis that had no
+ gravity specified. If the gravity is not in the ‘gravity’ enum, an
+ invalid_input error is raised.
+ </description>
+ <arg name="gravity" type="uint" enum="gravity"
+ summary="gravity direction"/>
+ </request>
+
+ <enum name="constraint_adjustment" bitfield="true">
+ <description summary="constraint adjustments">
+ The constraint adjustment value define ways the compositor will adjust
+ the position of the surface, if the unadjusted position would result
+ in the surface being partly constrained.
+
+ Whether a surface is considered 'constrained' is left to the compositor
+ to determine. For example, the surface may be partly outside the
+ compositor's defined 'work area', thus necessitating the child surface's
+ position be adjusted until it is entirely inside the work area.
+
+ The adjustments can be combined, according to a defined precedence: 1)
+ Flip, 2) Slide, 3) Resize.
+ </description>
+ <entry name="none" value="0">
+ <description summary="don't move the child surface when constrained">
+ Don't alter the surface position even if it is constrained on some
+ axis, for example partially outside the edge of an output.
+ </description>
+ </entry>
+ <entry name="slide_x" value="1">
+ <description summary="move along the x axis until unconstrained">
+ Slide the surface along the x axis until it is no longer constrained.
+
+ First try to slide towards the direction of the gravity on the x axis
+ until either the edge in the opposite direction of the gravity is
+ unconstrained or the edge in the direction of the gravity is
+ constrained.
+
+ Then try to slide towards the opposite direction of the gravity on the
+ x axis until either the edge in the direction of the gravity is
+ unconstrained or the edge in the opposite direction of the gravity is
+ constrained.
+ </description>
+ </entry>
+ <entry name="slide_y" value="2">
+ <description summary="move along the y axis until unconstrained">
+ Slide the surface along the y axis until it is no longer constrained.
+
+ First try to slide towards the direction of the gravity on the y axis
+ until either the edge in the opposite direction of the gravity is
+ unconstrained or the edge in the direction of the gravity is
+ constrained.
+
+ Then try to slide towards the opposite direction of the gravity on the
+ y axis until either the edge in the direction of the gravity is
+ unconstrained or the edge in the opposite direction of the gravity is
+ constrained.
+ </description>
+ </entry>
+ <entry name="flip_x" value="4">
+ <description summary="invert the anchor and gravity on the x axis">
+ Invert the anchor and gravity on the x axis if the surface is
+ constrained on the x axis. For example, if the left edge of the
+ surface is constrained, the gravity is 'left' and the anchor is
+ 'left', change the gravity to 'right' and the anchor to 'right'.
+
+ If the adjusted position also ends up being constrained, the resulting
+ position of the flip_x adjustment will be the one before the
+ adjustment.
+ </description>
+ </entry>
+ <entry name="flip_y" value="8">
+ <description summary="invert the anchor and gravity on the y axis">
+ Invert the anchor and gravity on the y axis if the surface is
+ constrained on the y axis. For example, if the bottom edge of the
+ surface is constrained, the gravity is 'bottom' and the anchor is
+ 'bottom', change the gravity to 'top' and the anchor to 'top'.
+
+ The adjusted position is calculated given the original anchor
+ rectangle and offset, but with the new flipped anchor and gravity
+ values.
+
+ If the adjusted position also ends up being constrained, the resulting
+ position of the flip_y adjustment will be the one before the
+ adjustment.
+ </description>
+ </entry>
+ <entry name="resize_x" value="16">
+ <description summary="horizontally resize the surface">
+ Resize the surface horizontally so that it is completely
+ unconstrained.
+ </description>
+ </entry>
+ <entry name="resize_y" value="32">
+ <description summary="vertically resize the surface">
+ Resize the surface vertically so that it is completely unconstrained.
+ </description>
+ </entry>
+ </enum>
+
+ <request name="set_constraint_adjustment">
+ <description summary="set the adjustment to be done when constrained">
+ Specify how the window should be positioned if the originally intended
+ position caused the surface to be constrained, meaning at least
+ partially outside positioning boundaries set by the compositor. The
+ adjustment is set by constructing a bitmask describing the adjustment to
+ be made when the surface is constrained on that axis.
+
+ If no bit for one axis is set, the compositor will assume that the child
+ surface should not change its position on that axis when constrained.
+
+ If more than one bit for one axis is set, the order of how adjustments
+ are applied is specified in the corresponding adjustment descriptions.
+
+ The default adjustment is none.
+ </description>
+ <arg name="constraint_adjustment" type="uint" enum="constraint_adjustment"
+ summary="bit mask of constraint adjustments"/>
+ </request>
+
+ <request name="set_offset">
+ <description summary="set surface position offset">
+ Specify the surface position offset relative to the position of the
+ anchor on the anchor rectangle and the anchor on the surface. For
+ example if the anchor of the anchor rectangle is at (x, y), the surface
+ has the gravity bottom|right, and the offset is (ox, oy), the calculated
+ surface position will be (x + ox, y + oy). The offset position of the
+ surface is the one used for constraint testing. See
+ set_constraint_adjustment.
+
+ An example use case is placing a popup menu on top of a user interface
+ element, while aligning the user interface element of the parent surface
+ with some user interface element placed somewhere in the popup surface.
+ </description>
+ <arg name="x" type="int" summary="surface position x offset"/>
+ <arg name="y" type="int" summary="surface position y offset"/>
+ </request>
+
+ <!-- Version 3 additions -->
+
+ <request name="set_reactive" since="3">
+ <description summary="continuously reconstrain the surface">
+ When set reactive, the surface is reconstrained if the conditions used
+ for constraining changed, e.g. the parent window moved.
+
+ If the conditions changed and the popup was reconstrained, an
+ xdg_popup.configure event is sent with updated geometry, followed by an
+ xdg_surface.configure event.
+ </description>
+ </request>
+
+ <request name="set_parent_size" since="3">
+ <description summary="">
+ Set the parent window geometry the compositor should use when
+ positioning the popup. The compositor may use this information to
+ determine the future state the popup should be constrained using. If
+ this doesn't match the dimension of the parent the popup is eventually
+ positioned against, the behavior is undefined.
+
+ The arguments are given in the surface-local coordinate space.
+ </description>
+ <arg name="parent_width" type="int"
+ summary="future window geometry width of parent"/>
+ <arg name="parent_height" type="int"
+ summary="future window geometry height of parent"/>
+ </request>
+
+ <request name="set_parent_configure" since="3">
+ <description summary="set parent configure this is a response to">
+ Set the serial of an xdg_surface.configure event this positioner will be
+ used in response to. The compositor may use this information together
+ with set_parent_size to determine what future state the popup should be
+ constrained using.
+ </description>
+ <arg name="serial" type="uint"
+ summary="serial of parent configure event"/>
+ </request>
+ </interface>
+
+ <interface name="xdg_surface" version="7">
+ <description summary="desktop user interface surface base interface">
+ An interface that may be implemented by a wl_surface, for
+ implementations that provide a desktop-style user interface.
+
+ It provides a base set of functionality required to construct user
+ interface elements requiring management by the compositor, such as
+ toplevel windows, menus, etc. The types of functionality are split into
+ xdg_surface roles.
+
+ Creating an xdg_surface does not set the role for a wl_surface. In order
+ to map an xdg_surface, the client must create a role-specific object
+ using, e.g., get_toplevel, get_popup. The wl_surface for any given
+ xdg_surface can have at most one role, and may not be assigned any role
+ not based on xdg_surface.
+
+ A role must be assigned before any other requests are made to the
+ xdg_surface object.
+
+ The client must call wl_surface.commit on the corresponding wl_surface
+ for the xdg_surface state to take effect.
+
+ Creating an xdg_surface from a wl_surface which has a buffer attached or
+ committed is a client error, and any attempts by a client to attach or
+ manipulate a buffer prior to the first xdg_surface.configure call must
+ also be treated as errors.
+
+ After creating a role-specific object and setting it up (e.g. by sending
+ the title, app ID, size constraints, parent, etc), the client must
+ perform an initial commit without any buffer attached. The compositor
+ will reply with initial wl_surface state such as
+ wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
+ event. The client must acknowledge it and is then allowed to attach a
+ buffer to map the surface.
+
+ Mapping an xdg_surface-based role surface is defined as making it
+ possible for the surface to be shown by the compositor. Note that
+ a mapped surface is not guaranteed to be visible once it is mapped.
+
+ For an xdg_surface to be mapped by the compositor, the following
+ conditions must be met:
+ (1) the client has assigned an xdg_surface-based role to the surface
+ (2) the client has set and committed the xdg_surface state and the
+ role-dependent state to the surface
+ (3) the client has committed a buffer to the surface
+
+ A newly-unmapped surface is considered to have met condition (1) out
+ of the 3 required conditions for mapping a surface if its role surface
+ has not been destroyed, i.e. the client must perform the initial commit
+ again before attaching a buffer.
+ </description>
+
+ <enum name="error">
+ <entry name="not_constructed" value="1"
+ summary="Surface was not fully constructed"/>
+ <entry name="already_constructed" value="2"
+ summary="Surface was already constructed"/>
+ <entry name="unconfigured_buffer" value="3"
+ summary="Attaching a buffer to an unconfigured surface"/>
+ <entry name="invalid_serial" value="4"
+ summary="Invalid serial number when acking a configure event"/>
+ <entry name="invalid_size" value="5"
+ summary="Width or height was zero or negative"/>
+ <entry name="defunct_role_object" value="6"
+ summary="Surface was destroyed before its role object"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xdg_surface">
+ Destroy the xdg_surface object. An xdg_surface must only be destroyed
+ after its role object has been destroyed, otherwise
+ a defunct_role_object error is raised.
+ </description>
+ </request>
+
+ <request name="get_toplevel">
+ <description summary="assign the xdg_toplevel surface role">
+ This creates an xdg_toplevel object for the given xdg_surface and gives
+ the associated wl_surface the xdg_toplevel role.
+
+ See the documentation of xdg_toplevel for more details about what an
+ xdg_toplevel is and how it is used.
+ </description>
+ <arg name="id" type="new_id" interface="xdg_toplevel"/>
+ </request>
+
+ <request name="get_popup">
+ <description summary="assign the xdg_popup surface role">
+ This creates an xdg_popup object for the given xdg_surface and gives
+ the associated wl_surface the xdg_popup role.
+
+ If null is passed as a parent, a parent surface must be specified using
+ some other protocol, before committing the initial state.
+
+ See the documentation of xdg_popup for more details about what an
+ xdg_popup is and how it is used.
+ </description>
+ <arg name="id" type="new_id" interface="xdg_popup"/>
+ <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
+ <arg name="positioner" type="object" interface="xdg_positioner"/>
+ </request>
+
+ <request name="set_window_geometry">
+ <description summary="set the new window geometry">
+ The window geometry of a surface is its "visible bounds" from the
+ user's perspective. Client-side decorations often have invisible
+ portions like drop-shadows which should be ignored for the
+ purposes of aligning, placing and constraining windows.
+
+ The window geometry is double-buffered state, see wl_surface.commit.
+
+ When maintaining a position, the compositor should treat the (x, y)
+ coordinate of the window geometry as the top left corner of the window.
+ A client changing the (x, y) window geometry coordinate should in
+ general not alter the position of the window.
+
+ Once the window geometry of the surface is set, it is not possible to
+ unset it, and it will remain the same until set_window_geometry is
+ called again, even if a new subsurface or buffer is attached.
+
+ If never set, the value is the full bounds of the surface,
+ including any subsurfaces. This updates dynamically on every
+ commit. This unset is meant for extremely simple clients.
+
+ The arguments are given in the surface-local coordinate space of
+ the wl_surface associated with this xdg_surface, and may extend outside
+ of the wl_surface itself to mark parts of the subsurface tree as part of
+ the window geometry.
+
+ When applied, the effective window geometry will be the set window
+ geometry clamped to the bounding rectangle of the combined
+ geometry of the surface of the xdg_surface and the associated
+ subsurfaces.
+
+ The effective geometry will not be recalculated unless a new call to
+ set_window_geometry is done and the new pending surface state is
+ subsequently applied.
+
+ The width and height of the effective window geometry must be
+ greater than zero. Setting an invalid size will raise an
+ invalid_size error.
+ </description>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <request name="ack_configure">
+ <description summary="ack a configure event">
+ When a configure event is received, if a client commits the
+ surface in response to the configure event, then the client
+ must make an ack_configure request sometime before the commit
+ request, passing along the serial of the configure event.
+
+ For instance, for toplevel surfaces the compositor might use this
+ information to move a surface to the top left only when the client has
+ drawn itself for the maximized or fullscreen state.
+
+ If the client receives multiple configure events before it
+ can respond to one, it only has to ack the last configure event.
+ Acking a configure event that was never sent raises an invalid_serial
+ error.
+
+ A client is not required to commit immediately after sending
+ an ack_configure request - it may even ack_configure several times
+ before its next surface commit.
+
+ A client may send multiple ack_configure requests before committing, but
+ only the last request sent before a commit indicates which configure
+ event the client really is responding to.
+
+ Sending an ack_configure request consumes the serial number sent with
+ the request, as well as serial numbers sent by all configure events
+ sent on this xdg_surface prior to the configure event referenced by
+ the committed serial.
+
+ It is an error to issue multiple ack_configure requests referencing a
+ serial from the same configure event, or to issue an ack_configure
+ request referencing a serial from a configure event issued before the
+ event identified by the last ack_configure request for the same
+ xdg_surface. Doing so will raise an invalid_serial error.
+ </description>
+ <arg name="serial" type="uint" summary="the serial from the configure event"/>
+ </request>
+
+ <event name="configure">
+ <description summary="suggest a surface change">
+ The configure event marks the end of a configure sequence. A configure
+ sequence is a set of one or more events configuring the state of the
+ xdg_surface, including the final xdg_surface.configure event.
+
+ Where applicable, xdg_surface surface roles will during a configure
+ sequence extend this event as a latched state sent as events before the
+ xdg_surface.configure event. Such events should be considered to make up
+ a set of atomically applied configuration states, where the
+ xdg_surface.configure commits the accumulated state.
+
+ Clients should arrange their surface for the new states, and then send
+ an ack_configure request with the serial sent in this configure event at
+ some point before committing the new surface.
+
+ If the client receives multiple configure events before it can respond
+ to one, it is free to discard all but the last event it received.
+ </description>
+ <arg name="serial" type="uint" summary="serial of the configure event"/>
+ </event>
+
+ </interface>
+
+ <interface name="xdg_toplevel" version="7">
+ <description summary="toplevel surface">
+ This interface defines an xdg_surface role which allows a surface to,
+ among other things, set window-like properties such as maximize,
+ fullscreen, and minimize, set application-specific metadata like title and
+ id, and well as trigger user interactive operations such as interactive
+ resize and move.
+
+ A xdg_toplevel by default is responsible for providing the full intended
+ visual representation of the toplevel, which depending on the window
+ state, may mean things like a title bar, window controls and drop shadow.
+
+ Unmapping an xdg_toplevel means that the surface cannot be shown
+ by the compositor until it is explicitly mapped again.
+ All active operations (e.g., move, resize) are canceled and all
+ attributes (e.g. title, state, stacking, ...) are discarded for
+ an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
+ the state it had right after xdg_surface.get_toplevel. The client
+ can re-map the toplevel by performing a commit without any buffer
+ attached, waiting for a configure event and handling it as usual (see
+ xdg_surface description).
+
+ Attaching a null buffer to a toplevel unmaps the surface.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the xdg_toplevel">
+ This request destroys the role surface and unmaps the surface;
+ see "Unmapping" behavior in interface section for details.
+ </description>
+ </request>
+
+ <enum name="error">
+ <entry name="invalid_resize_edge" value="0" summary="provided value is
+ not a valid variant of the resize_edge enum"/>
+ <entry name="invalid_parent" value="1"
+ summary="invalid parent toplevel"/>
+ <entry name="invalid_size" value="2"
+ summary="client provided an invalid min or max size"/>
+ </enum>
+
+ <request name="set_parent">
+ <description summary="set the parent of this surface">
+ Set the "parent" of this surface. This surface should be stacked
+ above the parent surface and all other ancestor surfaces.
+
+ Parent surfaces should be set on dialogs, toolboxes, or other
+ "auxiliary" surfaces, so that the parent is raised when the dialog
+ is raised.
+
+ Setting a null parent for a child surface unsets its parent. Setting
+ a null parent for a surface which currently has no parent is a no-op.
+
+ Only mapped surfaces can have child surfaces. Setting a parent which
+ is not mapped is equivalent to setting a null parent. If a surface
+ becomes unmapped, its children's parent is set to the parent of
+ the now-unmapped surface. If the now-unmapped surface has no parent,
+ its children's parent is unset. If the now-unmapped surface becomes
+ mapped again, its parent-child relationship is not restored.
+
+ The parent toplevel must not be one of the child toplevel's
+ descendants, and the parent must be different from the child toplevel,
+ otherwise the invalid_parent protocol error is raised.
+ </description>
+ <arg name="parent" type="object" interface="xdg_toplevel" allow-null="true"/>
+ </request>
+
+ <request name="set_title">
+ <description summary="set surface title">
+ Set a short title for the surface.
+
+ This string may be used to identify the surface in a task bar,
+ window list, or other user interface elements provided by the
+ compositor.
+
+ The string must be encoded in UTF-8.
+ </description>
+ <arg name="title" type="string"/>
+ </request>
+
+ <request name="set_app_id">
+ <description summary="set application ID">
+ Set an application identifier for the surface.
+
+ The app ID identifies the general class of applications to which
+ the surface belongs. The compositor can use this to group multiple
+ surfaces together, or to determine how to launch a new application.
+
+ For D-Bus activatable applications, the app ID is used as the D-Bus
+ service name.
+
+ The compositor shell will try to group application surfaces together
+ by their app ID. As a best practice, it is suggested to select app
+ ID's that match the basename of the application's .desktop file.
+ For example, "org.freedesktop.FooViewer" where the .desktop file is
+ "org.freedesktop.FooViewer.desktop".
+
+ Like other properties, a set_app_id request can be sent after the
+ xdg_toplevel has been mapped to update the property.
+
+ See the desktop-entry specification [0] for more details on
+ application identifiers and how they relate to well-known D-Bus
+ names and .desktop files.
+
+ [0] https://standards.freedesktop.org/desktop-entry-spec/
+ </description>
+ <arg name="app_id" type="string"/>
+ </request>
+
+ <request name="show_window_menu">
+ <description summary="show the window menu">
+ Clients implementing client-side decorations might want to show
+ a context menu when right-clicking on the decorations, giving the
+ user a menu that they can use to maximize or minimize the window.
+
+ This request asks the compositor to pop up such a window menu at
+ the given position, relative to the local surface coordinates of
+ the parent surface. There are no guarantees as to what menu items
+ the window menu contains, or even if a window menu will be drawn
+ at all.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
+ <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
+ </request>
+
+ <request name="move">
+ <description summary="start an interactive move">
+ Start an interactive, user-driven move of the surface.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event. The passed
+ serial is used to determine the type of interactive move (touch,
+ pointer, etc).
+
+ The server may ignore move requests depending on the state of
+ the surface (e.g. fullscreen or maximized), or if the passed serial
+ is no longer valid.
+
+ If triggered, the surface will lose the focus of the device
+ (wl_pointer, wl_touch, etc) used for the move. It is up to the
+ compositor to visually indicate that the move is taking place, such as
+ updating a pointer cursor, during the move. There is no guarantee
+ that the device focus will return when the move is completed.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ </request>
+
+ <enum name="resize_edge">
+ <description summary="edge values for resizing">
+ These values are used to indicate which edge of a surface
+ is being dragged in a resize operation.
+ </description>
+ <entry name="none" value="0"/>
+ <entry name="top" value="1"/>
+ <entry name="bottom" value="2"/>
+ <entry name="left" value="4"/>
+ <entry name="top_left" value="5"/>
+ <entry name="bottom_left" value="6"/>
+ <entry name="right" value="8"/>
+ <entry name="top_right" value="9"/>
+ <entry name="bottom_right" value="10"/>
+ </enum>
+
+ <request name="resize">
+ <description summary="start an interactive resize">
+ Start a user-driven, interactive resize of the surface.
+
+ This request must be used in response to some sort of user action
+ like a button press, key press, or touch down event. The passed
+ serial is used to determine the type of interactive resize (touch,
+ pointer, etc).
+
+ The server may ignore resize requests depending on the state of
+ the surface (e.g. fullscreen or maximized).
+
+ If triggered, the client will receive configure events with the
+ "resize" state enum value and the expected sizes. See the "resize"
+ enum value for more details about what is required. The client
+ must also acknowledge configure events using "ack_configure". After
+ the resize is completed, the client will receive another "configure"
+ event without the resize state.
+
+ If triggered, the surface also will lose the focus of the device
+ (wl_pointer, wl_touch, etc) used for the resize. It is up to the
+ compositor to visually indicate that the resize is taking place,
+ such as updating a pointer cursor, during the resize. There is no
+ guarantee that the device focus will return when the resize is
+ completed.
+
+ The edges parameter specifies how the surface should be resized, and
+ is one of the values of the resize_edge enum. Values not matching
+ a variant of the enum will cause the invalid_resize_edge protocol error.
+ The compositor may use this information to update the surface position
+ for example when dragging the top left corner. The compositor may also
+ use this information to adapt its behavior, e.g. choose an appropriate
+ cursor image.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ <arg name="edges" type="uint" enum="resize_edge" summary="which edge or corner is being dragged"/>
+ </request>
+
+ <enum name="state">
+ <description summary="types of state on the surface">
+ The different state values used on the surface. This is designed for
+ state values like maximized, fullscreen. It is paired with the
+ configure event to ensure that both the client and the compositor
+ setting the state can be synchronized.
+
+ States set in this way are double-buffered, see wl_surface.commit.
+ </description>
+ <entry name="maximized" value="1" summary="the surface is maximized">
+ <description summary="the surface is maximized">
+ The surface is maximized. The window geometry specified in the configure
+ event must be obeyed by the client, or the xdg_wm_base.invalid_surface_state
+ error is raised.
+
+ The client should draw without shadow or other
+ decoration outside of the window geometry.
+ </description>
+ </entry>
+ <entry name="fullscreen" value="2" summary="the surface is fullscreen">
+ <description summary="the surface is fullscreen">
+ The surface is fullscreen. The window geometry specified in the
+ configure event is a maximum; the client cannot resize beyond it. For
+ a surface to cover the whole fullscreened area, the geometry
+ dimensions must be obeyed by the client. For more details, see
+ xdg_toplevel.set_fullscreen.
+ </description>
+ </entry>
+ <entry name="resizing" value="3" summary="the surface is being resized">
+ <description summary="the surface is being resized">
+ The surface is being resized. The window geometry specified in the
+ configure event is a maximum; the client cannot resize beyond it.
+ Clients that have aspect ratio or cell sizing configuration can use
+ a smaller size, however.
+ </description>
+ </entry>
+ <entry name="activated" value="4" summary="the surface is now activated">
+ <description summary="the surface is now activated">
+ Client window decorations should be painted as if the window is
+ active. Do not assume this means that the window actually has
+ keyboard or pointer focus.
+ </description>
+ </entry>
+ <entry name="tiled_left" value="5" since="2">
+ <description summary="the surface’s left edge is tiled">
+ The window is currently in a tiled layout and the left edge is
+ considered to be adjacent to another part of the tiling grid.
+
+ The client should draw without shadow or other decoration outside of
+ the window geometry on the left edge.
+ </description>
+ </entry>
+ <entry name="tiled_right" value="6" since="2">
+ <description summary="the surface’s right edge is tiled">
+ The window is currently in a tiled layout and the right edge is
+ considered to be adjacent to another part of the tiling grid.
+
+ The client should draw without shadow or other decoration outside of
+ the window geometry on the right edge.
+ </description>
+ </entry>
+ <entry name="tiled_top" value="7" since="2">
+ <description summary="the surface’s top edge is tiled">
+ The window is currently in a tiled layout and the top edge is
+ considered to be adjacent to another part of the tiling grid.
+
+ The client should draw without shadow or other decoration outside of
+ the window geometry on the top edge.
+ </description>
+ </entry>
+ <entry name="tiled_bottom" value="8" since="2">
+ <description summary="the surface’s bottom edge is tiled">
+ The window is currently in a tiled layout and the bottom edge is
+ considered to be adjacent to another part of the tiling grid.
+
+ The client should draw without shadow or other decoration outside of
+ the window geometry on the bottom edge.
+ </description>
+ </entry>
+ <entry name="suspended" value="9" since="6">
+ <description summary="surface repaint is suspended">
+ The surface is currently not ordinarily being repainted; for
+ example because its content is occluded by another window, or its
+ outputs are switched off due to screen locking.
+ </description>
+ </entry>
+ <entry name="constrained_left" value="10" since="7">
+ <description summary="the surface’s left edge is constrained">
+ The left edge of the window is currently constrained, meaning it
+ shouldn't attempt to resize from that edge. It can for example mean
+ it's tiled next to a monitor edge on the constrained side of the
+ window.
+ </description>
+ </entry>
+ <entry name="constrained_right" value="11" since="7">
+ <description summary="the surface’s right edge is constrained">
+ The right edge of the window is currently constrained, meaning it
+ shouldn't attempt to resize from that edge. It can for example mean
+ it's tiled next to a monitor edge on the constrained side of the
+ window.
+ </description>
+ </entry>
+ <entry name="constrained_top" value="12" since="7">
+ <description summary="the surface’s top edge is constrained">
+ The top edge of the window is currently constrained, meaning it
+ shouldn't attempt to resize from that edge. It can for example mean
+ it's tiled next to a monitor edge on the constrained side of the
+ window.
+ </description>
+ </entry>
+ <entry name="constrained_bottom" value="13" since="7">
+ <description summary="the surface’s bottom edge is tiled">
+ The bottom edge of the window is currently constrained, meaning it
+ shouldn't attempt to resize from that edge. It can for example mean
+ it's tiled next to a monitor edge on the constrained side of the
+ window.
+ </description>
+ </entry>
+ </enum>
+
+ <request name="set_max_size">
+ <description summary="set the maximum size">
+ Set a maximum size for the window.
+
+ The client can specify a maximum size so that the compositor does
+ not try to configure the window beyond this size.
+
+ The width and height arguments are in window geometry coordinates.
+ See xdg_surface.set_window_geometry.
+
+ Values set in this way are double-buffered, see wl_surface.commit.
+
+ The compositor can use this information to allow or disallow
+ different states like maximize or fullscreen and draw accurate
+ animations.
+
+ Similarly, a tiling window manager may use this information to
+ place and resize client windows in a more effective way.
+
+ The client should not rely on the compositor to obey the maximum
+ size. The compositor may decide to ignore the values set by the
+ client and request a larger size.
+
+ If never set, or a value of zero in the request, means that the
+ client has no expected maximum size in the given dimension.
+ As a result, a client wishing to reset the maximum size
+ to an unspecified state can use zero for width and height in the
+ request.
+
+ Requesting a maximum size to be smaller than the minimum size of
+ a surface is illegal and will result in an invalid_size error.
+
+ The width and height must be greater than or equal to zero. Using
+ strictly negative values for width or height will result in a
+ invalid_size error.
+ </description>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <request name="set_min_size">
+ <description summary="set the minimum size">
+ Set a minimum size for the window.
+
+ The client can specify a minimum size so that the compositor does
+ not try to configure the window below this size.
+
+ The width and height arguments are in window geometry coordinates.
+ See xdg_surface.set_window_geometry.
+
+ Values set in this way are double-buffered, see wl_surface.commit.
+
+ The compositor can use this information to allow or disallow
+ different states like maximize or fullscreen and draw accurate
+ animations.
+
+ Similarly, a tiling window manager may use this information to
+ place and resize client windows in a more effective way.
+
+ The client should not rely on the compositor to obey the minimum
+ size. The compositor may decide to ignore the values set by the
+ client and request a smaller size.
+
+ If never set, or a value of zero in the request, means that the
+ client has no expected minimum size in the given dimension.
+ As a result, a client wishing to reset the minimum size
+ to an unspecified state can use zero for width and height in the
+ request.
+
+ Requesting a minimum size to be larger than the maximum size of
+ a surface is illegal and will result in an invalid_size error.
+
+ The width and height must be greater than or equal to zero. Using
+ strictly negative values for width and height will result in a
+ invalid_size error.
+ </description>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </request>
+
+ <request name="set_maximized">
+ <description summary="maximize the window">
+ Maximize the surface.
+
+ After requesting that the surface should be maximized, the compositor
+ will respond by emitting a configure event. Whether this configure
+ actually sets the window maximized is subject to compositor policies.
+ The client must then update its content, drawing in the configured
+ state. The client must also acknowledge the configure when committing
+ the new content (see ack_configure).
+
+ It is up to the compositor to decide how and where to maximize the
+ surface, for example which output and what region of the screen should
+ be used.
+
+ If the surface was already maximized, the compositor will still emit
+ a configure event with the "maximized" state.
+
+ If the surface is in a fullscreen state, this request has no direct
+ effect. It may alter the state the surface is returned to when
+ unmaximized unless overridden by the compositor.
+ </description>
+ </request>
+
+ <request name="unset_maximized">
+ <description summary="unmaximize the window">
+ Unmaximize the surface.
+
+ After requesting that the surface should be unmaximized, the compositor
+ will respond by emitting a configure event. Whether this actually
+ un-maximizes the window is subject to compositor policies.
+ If available and applicable, the compositor will include the window
+ geometry dimensions the window had prior to being maximized in the
+ configure event. The client must then update its content, drawing it in
+ the configured state. The client must also acknowledge the configure
+ when committing the new content (see ack_configure).
+
+ It is up to the compositor to position the surface after it was
+ unmaximized; usually the position the surface had before maximizing, if
+ applicable.
+
+ If the surface was already not maximized, the compositor will still
+ emit a configure event without the "maximized" state.
+
+ If the surface is in a fullscreen state, this request has no direct
+ effect. It may alter the state the surface is returned to when
+ unmaximized unless overridden by the compositor.
+ </description>
+ </request>
+
+ <request name="set_fullscreen">
+ <description summary="set the window as fullscreen on an output">
+ Make the surface fullscreen.
+
+ After requesting that the surface should be fullscreened, the
+ compositor will respond by emitting a configure event. Whether the
+ client is actually put into a fullscreen state is subject to compositor
+ policies. The client must also acknowledge the configure when
+ committing the new content (see ack_configure).
+
+ The output passed by the request indicates the client's preference as
+ to which display it should be set fullscreen on. If this value is NULL,
+ it's up to the compositor to choose which display will be used to map
+ this surface.
+
+ If the surface doesn't cover the whole output, the compositor will
+ position the surface in the center of the output and compensate with
+ with border fill covering the rest of the output. The content of the
+ border fill is undefined, but should be assumed to be in some way that
+ attempts to blend into the surrounding area (e.g. solid black).
+
+ If the fullscreened surface is not opaque, the compositor must make
+ sure that other screen content not part of the same surface tree (made
+ up of subsurfaces, popups or similarly coupled surfaces) are not
+ visible below the fullscreened surface.
+ </description>
+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
+ </request>
+
+ <request name="unset_fullscreen">
+ <description summary="unset the window as fullscreen">
+ Make the surface no longer fullscreen.
+
+ After requesting that the surface should be unfullscreened, the
+ compositor will respond by emitting a configure event.
+ Whether this actually removes the fullscreen state of the client is
+ subject to compositor policies.
+
+ Making a surface unfullscreen sets states for the surface based on the following:
+ * the state(s) it may have had before becoming fullscreen
+ * any state(s) decided by the compositor
+ * any state(s) requested by the client while the surface was fullscreen
+
+ The compositor may include the previous window geometry dimensions in
+ the configure event, if applicable.
+
+ The client must also acknowledge the configure when committing the new
+ content (see ack_configure).
+ </description>
+ </request>
+
+ <request name="set_minimized">
+ <description summary="set the window as minimized">
+ Request that the compositor minimize your surface. There is no
+ way to know if the surface is currently minimized, nor is there
+ any way to unset minimization on this surface.
+
+ If you are looking to throttle redrawing when minimized, please
+ instead use the wl_surface.frame event for this, as this will
+ also work with live previews on windows in Alt-Tab, Expose or
+ similar compositor features.
+ </description>
+ </request>
+
+ <event name="configure">
+ <description summary="suggest a surface change">
+ This configure event asks the client to resize its toplevel surface or
+ to change its state. The configured state should not be applied
+ immediately. See xdg_surface.configure for details.
+
+ The width and height arguments specify a hint to the window
+ about how its surface should be resized in window geometry
+ coordinates. See set_window_geometry.
+
+ If the width or height arguments are zero, it means the client
+ should decide its own window dimension. This may happen when the
+ compositor needs to configure the state of the surface but doesn't
+ have any information about any previous or expected dimension.
+
+ The states listed in the event specify how the width/height
+ arguments should be interpreted, and possibly how it should be
+ drawn.
+
+ Clients must send an ack_configure in response to this event. See
+ xdg_surface.configure and xdg_surface.ack_configure for details.
+ </description>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="states" type="array"/>
+ </event>
+
+ <event name="close">
+ <description summary="surface wants to be closed">
+ The close event is sent by the compositor when the user
+ wants the surface to be closed. This should be equivalent to
+ the user clicking the close button in client-side decorations,
+ if your application has any.
+
+ This is only a request that the user intends to close the
+ window. The client may choose to ignore this request, or show
+ a dialog to ask the user to save their data, etc.
+ </description>
+ </event>
+
+ <!-- Version 4 additions -->
+
+ <event name="configure_bounds" since="4">
+ <description summary="recommended window geometry bounds">
+ The configure_bounds event may be sent prior to a xdg_toplevel.configure
+ event to communicate the bounds a window geometry size is recommended
+ to constrain to.
+
+ The passed width and height are in surface coordinate space. If width
+ and height are 0, it means bounds is unknown and equivalent to as if no
+ configure_bounds event was ever sent for this surface.
+
+ The bounds can for example correspond to the size of a monitor excluding
+ any panels or other shell components, so that a surface isn't created in
+ a way that it cannot fit.
+
+ The bounds may change at any point, and in such a case, a new
+ xdg_toplevel.configure_bounds will be sent, followed by
+ xdg_toplevel.configure and xdg_surface.configure.
+ </description>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ </event>
+
+ <!-- Version 5 additions -->
+
+ <enum name="wm_capabilities" since="5">
+ <entry name="window_menu" value="1" summary="show_window_menu is available"/>
+ <entry name="maximize" value="2" summary="set_maximized and unset_maximized are available"/>
+ <entry name="fullscreen" value="3" summary="set_fullscreen and unset_fullscreen are available"/>
+ <entry name="minimize" value="4" summary="set_minimized is available"/>
+ </enum>
+
+ <event name="wm_capabilities" since="5">
+ <description summary="compositor capabilities">
+ This event advertises the capabilities supported by the compositor. If
+ a capability isn't supported, clients should hide or disable the UI
+ elements that expose this functionality. For instance, if the
+ compositor doesn't advertise support for minimized toplevels, a button
+ triggering the set_minimized request should not be displayed.
+
+ The compositor will ignore requests it doesn't support. For instance,
+ a compositor which doesn't advertise support for minimized will ignore
+ set_minimized requests.
+
+ Compositors must send this event once before the first
+ xdg_surface.configure event. When the capabilities change, compositors
+ must send this event again and then send an xdg_surface.configure
+ event.
+
+ The configured state should not be applied immediately. See
+ xdg_surface.configure for details.
+
+ The capabilities are sent as an array of 32-bit unsigned integers in
+ native endianness.
+ </description>
+ <arg name="capabilities" type="array" summary="array of 32-bit capabilities"/>
+ </event>
+ </interface>
+
+ <interface name="xdg_popup" version="7">
+ <description summary="short-lived, popup surfaces for menus">
+ A popup surface is a short-lived, temporary surface. It can be used to
+ implement for example menus, popovers, tooltips and other similar user
+ interface concepts.
+
+ A popup can be made to take an explicit grab. See xdg_popup.grab for
+ details.
+
+ When the popup is dismissed, a popup_done event will be sent out, and at
+ the same time the surface will be unmapped. See the xdg_popup.popup_done
+ event for details.
+
+ Explicitly destroying the xdg_popup object will also dismiss the popup and
+ unmap the surface. Clients that want to dismiss the popup when another
+ surface of their own is clicked should dismiss the popup using the destroy
+ request.
+
+ A newly created xdg_popup will be stacked on top of all previously created
+ xdg_popup surfaces associated with the same xdg_toplevel.
+
+ The parent of an xdg_popup must be mapped (see the xdg_surface
+ description) before the xdg_popup itself.
+
+ The client must call wl_surface.commit on the corresponding wl_surface
+ for the xdg_popup state to take effect.
+ </description>
+
+ <enum name="error">
+ <entry name="invalid_grab" value="0"
+ summary="tried to grab after being mapped"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="remove xdg_popup interface">
+ This destroys the popup. Explicitly destroying the xdg_popup
+ object will also dismiss the popup, and unmap the surface.
+
+ If this xdg_popup is not the "topmost" popup, the
+ xdg_wm_base.not_the_topmost_popup protocol error will be sent.
+ </description>
+ </request>
+
+ <request name="grab">
+ <description summary="make the popup take an explicit grab">
+ This request makes the created popup take an explicit grab. An explicit
+ grab will be dismissed when the user dismisses the popup, or when the
+ client destroys the xdg_popup. This can be done by the user clicking
+ outside the surface, using the keyboard, or even locking the screen
+ through closing the lid or a timeout.
+
+ If the compositor denies the grab, the popup will be immediately
+ dismissed.
+
+ This request must be used in response to some sort of user action like a
+ button press, key press, or touch down event. The serial number of the
+ event should be passed as 'serial'.
+
+ The parent of a grabbing popup must either be an xdg_toplevel surface or
+ another xdg_popup with an explicit grab. If the parent is another
+ xdg_popup it means that the popups are nested, with this popup now being
+ the topmost popup.
+
+ Nested popups must be destroyed in the reverse order they were created
+ in, e.g. the only popup you are allowed to destroy at all times is the
+ topmost one.
+
+ When compositors choose to dismiss a popup, they may dismiss every
+ nested grabbing popup as well. When a compositor dismisses popups, it
+ will follow the same dismissing order as required from the client.
+
+ If the topmost grabbing popup is destroyed, the grab will be returned to
+ the parent of the popup, if that parent previously had an explicit grab.
+
+ If the parent is a grabbing popup which has already been dismissed, this
+ popup will be immediately dismissed. If the parent is a popup that did
+ not take an explicit grab, an error will be raised.
+
+ During a popup grab, the client owning the grab will receive pointer
+ and touch events for all their surfaces as normal (similar to an
+ "owner-events" grab in X11 parlance), while the top most grabbing popup
+ will always have keyboard focus.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"
+ summary="the wl_seat of the user event"/>
+ <arg name="serial" type="uint" summary="the serial of the user event"/>
+ </request>
+
+ <event name="configure">
+ <description summary="configure the popup surface">
+ This event asks the popup surface to configure itself given the
+ configuration. The configured state should not be applied immediately.
+ See xdg_surface.configure for details.
+
+ The x and y arguments represent the position the popup was placed at
+ given the xdg_positioner rule, relative to the upper left corner of the
+ window geometry of the parent surface.
+
+ For version 2 or older, the configure event for an xdg_popup is only
+ ever sent once for the initial configuration. Starting with version 3,
+ it may be sent again if the popup is setup with an xdg_positioner with
+ set_reactive requested, or in response to xdg_popup.reposition requests.
+ </description>
+ <arg name="x" type="int"
+ summary="x position relative to parent surface window geometry"/>
+ <arg name="y" type="int"
+ summary="y position relative to parent surface window geometry"/>
+ <arg name="width" type="int" summary="window geometry width"/>
+ <arg name="height" type="int" summary="window geometry height"/>
+ </event>
+
+ <event name="popup_done">
+ <description summary="popup interaction is done">
+ The popup_done event is sent out when a popup is dismissed by the
+ compositor. The client should destroy the xdg_popup object at this
+ point.
+ </description>
+ </event>
+
+ <!-- Version 3 additions -->
+
+ <request name="reposition" since="3">
+ <description summary="recalculate the popup's location">
+ Reposition an already-mapped popup. The popup will be placed given the
+ details in the passed xdg_positioner object, and a
+ xdg_popup.repositioned followed by xdg_popup.configure and
+ xdg_surface.configure will be emitted in response. Any parameters set
+ by the previous positioner will be discarded.
+
+ The passed token will be sent in the corresponding
+ xdg_popup.repositioned event. The new popup position will not take
+ effect until the corresponding configure event is acknowledged by the
+ client. See xdg_popup.repositioned for details. The token itself is
+ opaque, and has no other special meaning.
+
+ If multiple reposition requests are sent, the compositor may skip all
+ but the last one.
+
+ If the popup is repositioned in response to a configure event for its
+ parent, the client should send an xdg_positioner.set_parent_configure
+ and possibly an xdg_positioner.set_parent_size request to allow the
+ compositor to properly constrain the popup.
+
+ If the popup is repositioned together with a parent that is being
+ resized, but not in response to a configure event, the client should
+ send an xdg_positioner.set_parent_size request.
+ </description>
+ <arg name="positioner" type="object" interface="xdg_positioner"/>
+ <arg name="token" type="uint" summary="reposition request token"/>
+ </request>
+
+ <event name="repositioned" since="3">
+ <description summary="signal the completion of a repositioned request">
+ The repositioned event is sent as part of a popup configuration
+ sequence, together with xdg_popup.configure and lastly
+ xdg_surface.configure to notify the completion of a reposition request.
+
+ The repositioned event is to notify about the completion of a
+ xdg_popup.reposition request. The token argument is the token passed
+ in the xdg_popup.reposition request.
+
+ Immediately after this event is emitted, xdg_popup.configure and
+ xdg_surface.configure will be sent with the updated size and position,
+ as well as a new configure serial.
+
+ The client should optionally update the content of the popup, but must
+ acknowledge the new popup configuration for the new position to take
+ effect. See xdg_surface.ack_configure for details.
+ </description>
+ <arg name="token" type="uint" summary="reposition request token"/>
+ </event>
+
+ </interface>
+</protocol>
Bool grabbing_supported_p = True;
initialize_screensaver_window (si);
- sync_server_dpms_settings (si->dpy, p);
+ sync_server_dpms_settings (si);
/* Under Wayland, we can only grab screenshots if "grim" is installed,
and even so, there's no way to grab screenshots under GNOME or KDE.
See comment in xscreensaver-getimage.c, and discussion thread here:
https://www.jwz.org/blog/2025/06/wayland-screenshots/#comment-260326
*/
- if (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET"))
+ if (
+# ifdef HAVE_WAYLAND
+ si->wayland_dpy ||
+# endif
+ (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET")))
{
const char *prog = "grim";
char *desk = getenv ("XDG_CURRENT_DESKTOP");
if (desk &&
(strcasestr (desk, "GNOME") ||
- strcasestr (desk, "KDE")))
+ strcasestr (desk, "KDE") ||
+ strcasestr (desk, "plasma")))
{
grabbing_supported_p = False;
if (p->verbose_p || p->fade_p || p->unfade_p || p->grab_desktop_p)
ssi->screenshot =
screenshot_grab (si->dpy, ssi->screensaver_window, False,
p->verbose_p);
+ if (ssi->screenshot)
+ screenshot_save (si->dpy, ssi->screensaver_window, ssi->screenshot);
}
if (p->fade_p &&
watchdog_timer (XtPointer closure, XtIntervalId *id)
{
saver_info *si = (saver_info *) closure;
- saver_preferences *p = &si->prefs;
Bool running_p, on_p, terminating_p;
/* If the DPMS settings on the server have changed, change them back to
what ~/.xscreensaver says they should be. */
- sync_server_dpms_settings (si->dpy, p);
+ sync_server_dpms_settings (si);
/* If the wall clock tells us that the monitor should be powered off now,
and the auth dialog is not currently on screen, make sure that the
monitor is off. */
- brute_force_dpms (si->dpy, p,
+ brute_force_dpms (si,
(si->auth_p
? 0
: si->activity_time));
raise_windows (si);
running_p = any_screenhacks_running_p (si);
- on_p = monitor_powered_on_p (si->dpy);
+ on_p = monitor_powered_on_p (si);
terminating_p = si->terminating_p;
if (running_p && !on_p)
{
+++ /dev/null
-/* Generated by wayland-scanner 1.23.1 */
-
-#ifndef XDG_SHELL_CLIENT_PROTOCOL_H
-#define XDG_SHELL_CLIENT_PROTOCOL_H
-
-#include <stdint.h>
-#include <stddef.h>
-#include "wayland-client.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @page page_xdg_shell The xdg_shell protocol
- * @section page_ifaces_xdg_shell Interfaces
- * - @subpage page_iface_xdg_wm_base - create desktop-style surfaces
- * - @subpage page_iface_xdg_positioner - child surface positioner
- * - @subpage page_iface_xdg_surface - desktop user interface surface base interface
- * - @subpage page_iface_xdg_toplevel - toplevel surface
- * - @subpage page_iface_xdg_popup - short-lived, popup surfaces for menus
- * @section page_copyright_xdg_shell Copyright
- * <pre>
- *
- * Copyright © 2008-2013 Kristian Høgsberg
- * Copyright © 2013 Rafael Antognolli
- * Copyright © 2013 Jasper St. Pierre
- * Copyright © 2010-2013 Intel Corporation
- * Copyright © 2015-2017 Samsung Electronics Co., Ltd
- * Copyright © 2015-2017 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * </pre>
- */
-struct wl_output;
-struct wl_seat;
-struct wl_surface;
-struct xdg_popup;
-struct xdg_positioner;
-struct xdg_surface;
-struct xdg_toplevel;
-struct xdg_wm_base;
-
-#ifndef XDG_WM_BASE_INTERFACE
-#define XDG_WM_BASE_INTERFACE
-/**
- * @page page_iface_xdg_wm_base xdg_wm_base
- * @section page_iface_xdg_wm_base_desc Description
- *
- * The xdg_wm_base interface is exposed as a global object enabling clients
- * to turn their wl_surfaces into windows in a desktop environment. It
- * defines the basic functionality needed for clients and the compositor to
- * create windows that can be dragged, resized, maximized, etc, as well as
- * creating transient windows such as popup menus.
- * @section page_iface_xdg_wm_base_api API
- * See @ref iface_xdg_wm_base.
- */
-/**
- * @defgroup iface_xdg_wm_base The xdg_wm_base interface
- *
- * The xdg_wm_base interface is exposed as a global object enabling clients
- * to turn their wl_surfaces into windows in a desktop environment. It
- * defines the basic functionality needed for clients and the compositor to
- * create windows that can be dragged, resized, maximized, etc, as well as
- * creating transient windows such as popup menus.
- */
-extern const struct wl_interface xdg_wm_base_interface;
-#endif
-#ifndef XDG_POSITIONER_INTERFACE
-#define XDG_POSITIONER_INTERFACE
-/**
- * @page page_iface_xdg_positioner xdg_positioner
- * @section page_iface_xdg_positioner_desc Description
- *
- * The xdg_positioner provides a collection of rules for the placement of a
- * child surface relative to a parent surface. Rules can be defined to ensure
- * the child surface remains within the visible area's borders, and to
- * specify how the child surface changes its position, such as sliding along
- * an axis, or flipping around a rectangle. These positioner-created rules are
- * constrained by the requirement that a child surface must intersect with or
- * be at least partially adjacent to its parent surface.
- *
- * See the various requests for details about possible rules.
- *
- * At the time of the request, the compositor makes a copy of the rules
- * specified by the xdg_positioner. Thus, after the request is complete the
- * xdg_positioner object can be destroyed or reused; further changes to the
- * object will have no effect on previous usages.
- *
- * For an xdg_positioner object to be considered complete, it must have a
- * non-zero size set by set_size, and a non-zero anchor rectangle set by
- * set_anchor_rect. Passing an incomplete xdg_positioner object when
- * positioning a surface raises an invalid_positioner error.
- * @section page_iface_xdg_positioner_api API
- * See @ref iface_xdg_positioner.
- */
-/**
- * @defgroup iface_xdg_positioner The xdg_positioner interface
- *
- * The xdg_positioner provides a collection of rules for the placement of a
- * child surface relative to a parent surface. Rules can be defined to ensure
- * the child surface remains within the visible area's borders, and to
- * specify how the child surface changes its position, such as sliding along
- * an axis, or flipping around a rectangle. These positioner-created rules are
- * constrained by the requirement that a child surface must intersect with or
- * be at least partially adjacent to its parent surface.
- *
- * See the various requests for details about possible rules.
- *
- * At the time of the request, the compositor makes a copy of the rules
- * specified by the xdg_positioner. Thus, after the request is complete the
- * xdg_positioner object can be destroyed or reused; further changes to the
- * object will have no effect on previous usages.
- *
- * For an xdg_positioner object to be considered complete, it must have a
- * non-zero size set by set_size, and a non-zero anchor rectangle set by
- * set_anchor_rect. Passing an incomplete xdg_positioner object when
- * positioning a surface raises an invalid_positioner error.
- */
-extern const struct wl_interface xdg_positioner_interface;
-#endif
-#ifndef XDG_SURFACE_INTERFACE
-#define XDG_SURFACE_INTERFACE
-/**
- * @page page_iface_xdg_surface xdg_surface
- * @section page_iface_xdg_surface_desc Description
- *
- * An interface that may be implemented by a wl_surface, for
- * implementations that provide a desktop-style user interface.
- *
- * It provides a base set of functionality required to construct user
- * interface elements requiring management by the compositor, such as
- * toplevel windows, menus, etc. The types of functionality are split into
- * xdg_surface roles.
- *
- * Creating an xdg_surface does not set the role for a wl_surface. In order
- * to map an xdg_surface, the client must create a role-specific object
- * using, e.g., get_toplevel, get_popup. The wl_surface for any given
- * xdg_surface can have at most one role, and may not be assigned any role
- * not based on xdg_surface.
- *
- * A role must be assigned before any other requests are made to the
- * xdg_surface object.
- *
- * The client must call wl_surface.commit on the corresponding wl_surface
- * for the xdg_surface state to take effect.
- *
- * Creating an xdg_surface from a wl_surface which has a buffer attached or
- * committed is a client error, and any attempts by a client to attach or
- * manipulate a buffer prior to the first xdg_surface.configure call must
- * also be treated as errors.
- *
- * After creating a role-specific object and setting it up (e.g. by sending
- * the title, app ID, size constraints, parent, etc), the client must
- * perform an initial commit without any buffer attached. The compositor
- * will reply with initial wl_surface state such as
- * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
- * event. The client must acknowledge it and is then allowed to attach a
- * buffer to map the surface.
- *
- * Mapping an xdg_surface-based role surface is defined as making it
- * possible for the surface to be shown by the compositor. Note that
- * a mapped surface is not guaranteed to be visible once it is mapped.
- *
- * For an xdg_surface to be mapped by the compositor, the following
- * conditions must be met:
- * (1) the client has assigned an xdg_surface-based role to the surface
- * (2) the client has set and committed the xdg_surface state and the
- * role-dependent state to the surface
- * (3) the client has committed a buffer to the surface
- *
- * A newly-unmapped surface is considered to have met condition (1) out
- * of the 3 required conditions for mapping a surface if its role surface
- * has not been destroyed, i.e. the client must perform the initial commit
- * again before attaching a buffer.
- * @section page_iface_xdg_surface_api API
- * See @ref iface_xdg_surface.
- */
-/**
- * @defgroup iface_xdg_surface The xdg_surface interface
- *
- * An interface that may be implemented by a wl_surface, for
- * implementations that provide a desktop-style user interface.
- *
- * It provides a base set of functionality required to construct user
- * interface elements requiring management by the compositor, such as
- * toplevel windows, menus, etc. The types of functionality are split into
- * xdg_surface roles.
- *
- * Creating an xdg_surface does not set the role for a wl_surface. In order
- * to map an xdg_surface, the client must create a role-specific object
- * using, e.g., get_toplevel, get_popup. The wl_surface for any given
- * xdg_surface can have at most one role, and may not be assigned any role
- * not based on xdg_surface.
- *
- * A role must be assigned before any other requests are made to the
- * xdg_surface object.
- *
- * The client must call wl_surface.commit on the corresponding wl_surface
- * for the xdg_surface state to take effect.
- *
- * Creating an xdg_surface from a wl_surface which has a buffer attached or
- * committed is a client error, and any attempts by a client to attach or
- * manipulate a buffer prior to the first xdg_surface.configure call must
- * also be treated as errors.
- *
- * After creating a role-specific object and setting it up (e.g. by sending
- * the title, app ID, size constraints, parent, etc), the client must
- * perform an initial commit without any buffer attached. The compositor
- * will reply with initial wl_surface state such as
- * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
- * event. The client must acknowledge it and is then allowed to attach a
- * buffer to map the surface.
- *
- * Mapping an xdg_surface-based role surface is defined as making it
- * possible for the surface to be shown by the compositor. Note that
- * a mapped surface is not guaranteed to be visible once it is mapped.
- *
- * For an xdg_surface to be mapped by the compositor, the following
- * conditions must be met:
- * (1) the client has assigned an xdg_surface-based role to the surface
- * (2) the client has set and committed the xdg_surface state and the
- * role-dependent state to the surface
- * (3) the client has committed a buffer to the surface
- *
- * A newly-unmapped surface is considered to have met condition (1) out
- * of the 3 required conditions for mapping a surface if its role surface
- * has not been destroyed, i.e. the client must perform the initial commit
- * again before attaching a buffer.
- */
-extern const struct wl_interface xdg_surface_interface;
-#endif
-#ifndef XDG_TOPLEVEL_INTERFACE
-#define XDG_TOPLEVEL_INTERFACE
-/**
- * @page page_iface_xdg_toplevel xdg_toplevel
- * @section page_iface_xdg_toplevel_desc Description
- *
- * This interface defines an xdg_surface role which allows a surface to,
- * among other things, set window-like properties such as maximize,
- * fullscreen, and minimize, set application-specific metadata like title and
- * id, and well as trigger user interactive operations such as interactive
- * resize and move.
- *
- * A xdg_toplevel by default is responsible for providing the full intended
- * visual representation of the toplevel, which depending on the window
- * state, may mean things like a title bar, window controls and drop shadow.
- *
- * Unmapping an xdg_toplevel means that the surface cannot be shown
- * by the compositor until it is explicitly mapped again.
- * All active operations (e.g., move, resize) are canceled and all
- * attributes (e.g. title, state, stacking, ...) are discarded for
- * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
- * the state it had right after xdg_surface.get_toplevel. The client
- * can re-map the toplevel by performing a commit without any buffer
- * attached, waiting for a configure event and handling it as usual (see
- * xdg_surface description).
- *
- * Attaching a null buffer to a toplevel unmaps the surface.
- * @section page_iface_xdg_toplevel_api API
- * See @ref iface_xdg_toplevel.
- */
-/**
- * @defgroup iface_xdg_toplevel The xdg_toplevel interface
- *
- * This interface defines an xdg_surface role which allows a surface to,
- * among other things, set window-like properties such as maximize,
- * fullscreen, and minimize, set application-specific metadata like title and
- * id, and well as trigger user interactive operations such as interactive
- * resize and move.
- *
- * A xdg_toplevel by default is responsible for providing the full intended
- * visual representation of the toplevel, which depending on the window
- * state, may mean things like a title bar, window controls and drop shadow.
- *
- * Unmapping an xdg_toplevel means that the surface cannot be shown
- * by the compositor until it is explicitly mapped again.
- * All active operations (e.g., move, resize) are canceled and all
- * attributes (e.g. title, state, stacking, ...) are discarded for
- * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
- * the state it had right after xdg_surface.get_toplevel. The client
- * can re-map the toplevel by performing a commit without any buffer
- * attached, waiting for a configure event and handling it as usual (see
- * xdg_surface description).
- *
- * Attaching a null buffer to a toplevel unmaps the surface.
- */
-extern const struct wl_interface xdg_toplevel_interface;
-#endif
-#ifndef XDG_POPUP_INTERFACE
-#define XDG_POPUP_INTERFACE
-/**
- * @page page_iface_xdg_popup xdg_popup
- * @section page_iface_xdg_popup_desc Description
- *
- * A popup surface is a short-lived, temporary surface. It can be used to
- * implement for example menus, popovers, tooltips and other similar user
- * interface concepts.
- *
- * A popup can be made to take an explicit grab. See xdg_popup.grab for
- * details.
- *
- * When the popup is dismissed, a popup_done event will be sent out, and at
- * the same time the surface will be unmapped. See the xdg_popup.popup_done
- * event for details.
- *
- * Explicitly destroying the xdg_popup object will also dismiss the popup and
- * unmap the surface. Clients that want to dismiss the popup when another
- * surface of their own is clicked should dismiss the popup using the destroy
- * request.
- *
- * A newly created xdg_popup will be stacked on top of all previously created
- * xdg_popup surfaces associated with the same xdg_toplevel.
- *
- * The parent of an xdg_popup must be mapped (see the xdg_surface
- * description) before the xdg_popup itself.
- *
- * The client must call wl_surface.commit on the corresponding wl_surface
- * for the xdg_popup state to take effect.
- * @section page_iface_xdg_popup_api API
- * See @ref iface_xdg_popup.
- */
-/**
- * @defgroup iface_xdg_popup The xdg_popup interface
- *
- * A popup surface is a short-lived, temporary surface. It can be used to
- * implement for example menus, popovers, tooltips and other similar user
- * interface concepts.
- *
- * A popup can be made to take an explicit grab. See xdg_popup.grab for
- * details.
- *
- * When the popup is dismissed, a popup_done event will be sent out, and at
- * the same time the surface will be unmapped. See the xdg_popup.popup_done
- * event for details.
- *
- * Explicitly destroying the xdg_popup object will also dismiss the popup and
- * unmap the surface. Clients that want to dismiss the popup when another
- * surface of their own is clicked should dismiss the popup using the destroy
- * request.
- *
- * A newly created xdg_popup will be stacked on top of all previously created
- * xdg_popup surfaces associated with the same xdg_toplevel.
- *
- * The parent of an xdg_popup must be mapped (see the xdg_surface
- * description) before the xdg_popup itself.
- *
- * The client must call wl_surface.commit on the corresponding wl_surface
- * for the xdg_popup state to take effect.
- */
-extern const struct wl_interface xdg_popup_interface;
-#endif
-
-#ifndef XDG_WM_BASE_ERROR_ENUM
-#define XDG_WM_BASE_ERROR_ENUM
-enum xdg_wm_base_error {
- /**
- * given wl_surface has another role
- */
- XDG_WM_BASE_ERROR_ROLE = 0,
- /**
- * xdg_wm_base was destroyed before children
- */
- XDG_WM_BASE_ERROR_DEFUNCT_SURFACES = 1,
- /**
- * the client tried to map or destroy a non-topmost popup
- */
- XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP = 2,
- /**
- * the client specified an invalid popup parent surface
- */
- XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT = 3,
- /**
- * the client provided an invalid surface state
- */
- XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE = 4,
- /**
- * the client provided an invalid positioner
- */
- XDG_WM_BASE_ERROR_INVALID_POSITIONER = 5,
- /**
- * the client didn’t respond to a ping event in time
- */
- XDG_WM_BASE_ERROR_UNRESPONSIVE = 6,
-};
-#endif /* XDG_WM_BASE_ERROR_ENUM */
-
-/**
- * @ingroup iface_xdg_wm_base
- * @struct xdg_wm_base_listener
- */
-struct xdg_wm_base_listener {
- /**
- * check if the client is alive
- *
- * The ping event asks the client if it's still alive. Pass the
- * serial specified in the event back to the compositor by sending
- * a "pong" request back with the specified serial. See
- * xdg_wm_base.pong.
- *
- * Compositors can use this to determine if the client is still
- * alive. It's unspecified what will happen if the client doesn't
- * respond to the ping request, or in what timeframe. Clients
- * should try to respond in a reasonable amount of time. The
- * “unresponsive” error is provided for compositors that wish
- * to disconnect unresponsive clients.
- *
- * A compositor is free to ping in any way it wants, but a client
- * must always respond to any xdg_wm_base object it created.
- * @param serial pass this to the pong request
- */
- void (*ping)(void *data,
- struct xdg_wm_base *xdg_wm_base,
- uint32_t serial);
-};
-
-/**
- * @ingroup iface_xdg_wm_base
- */
-static inline int
-xdg_wm_base_add_listener(struct xdg_wm_base *xdg_wm_base,
- const struct xdg_wm_base_listener *listener, void *data)
-{
- return wl_proxy_add_listener((struct wl_proxy *) xdg_wm_base,
- (void (**)(void)) listener, data);
-}
-
-#define XDG_WM_BASE_DESTROY 0
-#define XDG_WM_BASE_CREATE_POSITIONER 1
-#define XDG_WM_BASE_GET_XDG_SURFACE 2
-#define XDG_WM_BASE_PONG 3
-
-/**
- * @ingroup iface_xdg_wm_base
- */
-#define XDG_WM_BASE_PING_SINCE_VERSION 1
-
-/**
- * @ingroup iface_xdg_wm_base
- */
-#define XDG_WM_BASE_DESTROY_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_wm_base
- */
-#define XDG_WM_BASE_CREATE_POSITIONER_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_wm_base
- */
-#define XDG_WM_BASE_GET_XDG_SURFACE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_wm_base
- */
-#define XDG_WM_BASE_PONG_SINCE_VERSION 1
-
-/** @ingroup iface_xdg_wm_base */
-static inline void
-xdg_wm_base_set_user_data(struct xdg_wm_base *xdg_wm_base, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) xdg_wm_base, user_data);
-}
-
-/** @ingroup iface_xdg_wm_base */
-static inline void *
-xdg_wm_base_get_user_data(struct xdg_wm_base *xdg_wm_base)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) xdg_wm_base);
-}
-
-static inline uint32_t
-xdg_wm_base_get_version(struct xdg_wm_base *xdg_wm_base)
-{
- return wl_proxy_get_version((struct wl_proxy *) xdg_wm_base);
-}
-
-/**
- * @ingroup iface_xdg_wm_base
- *
- * Destroy this xdg_wm_base object.
- *
- * Destroying a bound xdg_wm_base object while there are surfaces
- * still alive created by this xdg_wm_base object instance is illegal
- * and will result in a defunct_surfaces error.
- */
-static inline void
-xdg_wm_base_destroy(struct xdg_wm_base *xdg_wm_base)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
- XDG_WM_BASE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), WL_MARSHAL_FLAG_DESTROY);
-}
-
-/**
- * @ingroup iface_xdg_wm_base
- *
- * Create a positioner object. A positioner object is used to position
- * surfaces relative to some parent surface. See the interface description
- * and xdg_surface.get_popup for details.
- */
-static inline struct xdg_positioner *
-xdg_wm_base_create_positioner(struct xdg_wm_base *xdg_wm_base)
-{
- struct wl_proxy *id;
-
- id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
- XDG_WM_BASE_CREATE_POSITIONER, &xdg_positioner_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL);
-
- return (struct xdg_positioner *) id;
-}
-
-/**
- * @ingroup iface_xdg_wm_base
- *
- * This creates an xdg_surface for the given surface. While xdg_surface
- * itself is not a role, the corresponding surface may only be assigned
- * a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
- * illegal to create an xdg_surface for a wl_surface which already has an
- * assigned role and this will result in a role error.
- *
- * This creates an xdg_surface for the given surface. An xdg_surface is
- * used as basis to define a role to a given surface, such as xdg_toplevel
- * or xdg_popup. It also manages functionality shared between xdg_surface
- * based surface roles.
- *
- * See the documentation of xdg_surface for more details about what an
- * xdg_surface is and how it is used.
- */
-static inline struct xdg_surface *
-xdg_wm_base_get_xdg_surface(struct xdg_wm_base *xdg_wm_base, struct wl_surface *surface)
-{
- struct wl_proxy *id;
-
- id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
- XDG_WM_BASE_GET_XDG_SURFACE, &xdg_surface_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL, surface);
-
- return (struct xdg_surface *) id;
-}
-
-/**
- * @ingroup iface_xdg_wm_base
- *
- * A client must respond to a ping event with a pong request or
- * the client may be deemed unresponsive. See xdg_wm_base.ping
- * and xdg_wm_base.error.unresponsive.
- */
-static inline void
-xdg_wm_base_pong(struct xdg_wm_base *xdg_wm_base, uint32_t serial)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base,
- XDG_WM_BASE_PONG, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, serial);
-}
-
-#ifndef XDG_POSITIONER_ERROR_ENUM
-#define XDG_POSITIONER_ERROR_ENUM
-enum xdg_positioner_error {
- /**
- * invalid input provided
- */
- XDG_POSITIONER_ERROR_INVALID_INPUT = 0,
-};
-#endif /* XDG_POSITIONER_ERROR_ENUM */
-
-#ifndef XDG_POSITIONER_ANCHOR_ENUM
-#define XDG_POSITIONER_ANCHOR_ENUM
-enum xdg_positioner_anchor {
- XDG_POSITIONER_ANCHOR_NONE = 0,
- XDG_POSITIONER_ANCHOR_TOP = 1,
- XDG_POSITIONER_ANCHOR_BOTTOM = 2,
- XDG_POSITIONER_ANCHOR_LEFT = 3,
- XDG_POSITIONER_ANCHOR_RIGHT = 4,
- XDG_POSITIONER_ANCHOR_TOP_LEFT = 5,
- XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6,
- XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7,
- XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8,
-};
-#endif /* XDG_POSITIONER_ANCHOR_ENUM */
-
-#ifndef XDG_POSITIONER_GRAVITY_ENUM
-#define XDG_POSITIONER_GRAVITY_ENUM
-enum xdg_positioner_gravity {
- XDG_POSITIONER_GRAVITY_NONE = 0,
- XDG_POSITIONER_GRAVITY_TOP = 1,
- XDG_POSITIONER_GRAVITY_BOTTOM = 2,
- XDG_POSITIONER_GRAVITY_LEFT = 3,
- XDG_POSITIONER_GRAVITY_RIGHT = 4,
- XDG_POSITIONER_GRAVITY_TOP_LEFT = 5,
- XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6,
- XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7,
- XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8,
-};
-#endif /* XDG_POSITIONER_GRAVITY_ENUM */
-
-#ifndef XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM
-#define XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM
-/**
- * @ingroup iface_xdg_positioner
- * constraint adjustments
- *
- * The constraint adjustment value define ways the compositor will adjust
- * the position of the surface, if the unadjusted position would result
- * in the surface being partly constrained.
- *
- * Whether a surface is considered 'constrained' is left to the compositor
- * to determine. For example, the surface may be partly outside the
- * compositor's defined 'work area', thus necessitating the child surface's
- * position be adjusted until it is entirely inside the work area.
- *
- * The adjustments can be combined, according to a defined precedence: 1)
- * Flip, 2) Slide, 3) Resize.
- */
-enum xdg_positioner_constraint_adjustment {
- /**
- * don't move the child surface when constrained
- *
- * Don't alter the surface position even if it is constrained on
- * some axis, for example partially outside the edge of an output.
- */
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0,
- /**
- * move along the x axis until unconstrained
- *
- * Slide the surface along the x axis until it is no longer
- * constrained.
- *
- * First try to slide towards the direction of the gravity on the x
- * axis until either the edge in the opposite direction of the
- * gravity is unconstrained or the edge in the direction of the
- * gravity is constrained.
- *
- * Then try to slide towards the opposite direction of the gravity
- * on the x axis until either the edge in the direction of the
- * gravity is unconstrained or the edge in the opposite direction
- * of the gravity is constrained.
- */
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1,
- /**
- * move along the y axis until unconstrained
- *
- * Slide the surface along the y axis until it is no longer
- * constrained.
- *
- * First try to slide towards the direction of the gravity on the y
- * axis until either the edge in the opposite direction of the
- * gravity is unconstrained or the edge in the direction of the
- * gravity is constrained.
- *
- * Then try to slide towards the opposite direction of the gravity
- * on the y axis until either the edge in the direction of the
- * gravity is unconstrained or the edge in the opposite direction
- * of the gravity is constrained.
- */
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2,
- /**
- * invert the anchor and gravity on the x axis
- *
- * Invert the anchor and gravity on the x axis if the surface is
- * constrained on the x axis. For example, if the left edge of the
- * surface is constrained, the gravity is 'left' and the anchor is
- * 'left', change the gravity to 'right' and the anchor to 'right'.
- *
- * If the adjusted position also ends up being constrained, the
- * resulting position of the flip_x adjustment will be the one
- * before the adjustment.
- */
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4,
- /**
- * invert the anchor and gravity on the y axis
- *
- * Invert the anchor and gravity on the y axis if the surface is
- * constrained on the y axis. For example, if the bottom edge of
- * the surface is constrained, the gravity is 'bottom' and the
- * anchor is 'bottom', change the gravity to 'top' and the anchor
- * to 'top'.
- *
- * The adjusted position is calculated given the original anchor
- * rectangle and offset, but with the new flipped anchor and
- * gravity values.
- *
- * If the adjusted position also ends up being constrained, the
- * resulting position of the flip_y adjustment will be the one
- * before the adjustment.
- */
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8,
- /**
- * horizontally resize the surface
- *
- * Resize the surface horizontally so that it is completely
- * unconstrained.
- */
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16,
- /**
- * vertically resize the surface
- *
- * Resize the surface vertically so that it is completely
- * unconstrained.
- */
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32,
-};
-#endif /* XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM */
-
-#define XDG_POSITIONER_DESTROY 0
-#define XDG_POSITIONER_SET_SIZE 1
-#define XDG_POSITIONER_SET_ANCHOR_RECT 2
-#define XDG_POSITIONER_SET_ANCHOR 3
-#define XDG_POSITIONER_SET_GRAVITY 4
-#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT 5
-#define XDG_POSITIONER_SET_OFFSET 6
-#define XDG_POSITIONER_SET_REACTIVE 7
-#define XDG_POSITIONER_SET_PARENT_SIZE 8
-#define XDG_POSITIONER_SET_PARENT_CONFIGURE 9
-
-
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_DESTROY_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_SIZE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_ANCHOR_RECT_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_ANCHOR_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_GRAVITY_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_OFFSET_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION 3
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_PARENT_SIZE_SINCE_VERSION 3
-/**
- * @ingroup iface_xdg_positioner
- */
-#define XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION 3
-
-/** @ingroup iface_xdg_positioner */
-static inline void
-xdg_positioner_set_user_data(struct xdg_positioner *xdg_positioner, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) xdg_positioner, user_data);
-}
-
-/** @ingroup iface_xdg_positioner */
-static inline void *
-xdg_positioner_get_user_data(struct xdg_positioner *xdg_positioner)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) xdg_positioner);
-}
-
-static inline uint32_t
-xdg_positioner_get_version(struct xdg_positioner *xdg_positioner)
-{
- return wl_proxy_get_version((struct wl_proxy *) xdg_positioner);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Notify the compositor that the xdg_positioner will no longer be used.
- */
-static inline void
-xdg_positioner_destroy(struct xdg_positioner *xdg_positioner)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), WL_MARSHAL_FLAG_DESTROY);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Set the size of the surface that is to be positioned with the positioner
- * object. The size is in surface-local coordinates and corresponds to the
- * window geometry. See xdg_surface.set_window_geometry.
- *
- * If a zero or negative size is set the invalid_input error is raised.
- */
-static inline void
-xdg_positioner_set_size(struct xdg_positioner *xdg_positioner, int32_t width, int32_t height)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, width, height);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Specify the anchor rectangle within the parent surface that the child
- * surface will be placed relative to. The rectangle is relative to the
- * window geometry as defined by xdg_surface.set_window_geometry of the
- * parent surface.
- *
- * When the xdg_positioner object is used to position a child surface, the
- * anchor rectangle may not extend outside the window geometry of the
- * positioned child's parent surface.
- *
- * If a negative size is set the invalid_input error is raised.
- */
-static inline void
-xdg_positioner_set_anchor_rect(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y, int32_t width, int32_t height)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_ANCHOR_RECT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y, width, height);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Defines the anchor point for the anchor rectangle. The specified anchor
- * is used derive an anchor point that the child surface will be
- * positioned relative to. If a corner anchor is set (e.g. 'top_left' or
- * 'bottom_right'), the anchor point will be at the specified corner;
- * otherwise, the derived anchor point will be centered on the specified
- * edge, or in the center of the anchor rectangle if no edge is specified.
- */
-static inline void
-xdg_positioner_set_anchor(struct xdg_positioner *xdg_positioner, uint32_t anchor)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_ANCHOR, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, anchor);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Defines in what direction a surface should be positioned, relative to
- * the anchor point of the parent surface. If a corner gravity is
- * specified (e.g. 'bottom_right' or 'top_left'), then the child surface
- * will be placed towards the specified gravity; otherwise, the child
- * surface will be centered over the anchor point on any axis that had no
- * gravity specified. If the gravity is not in the ‘gravity’ enum, an
- * invalid_input error is raised.
- */
-static inline void
-xdg_positioner_set_gravity(struct xdg_positioner *xdg_positioner, uint32_t gravity)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_GRAVITY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, gravity);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Specify how the window should be positioned if the originally intended
- * position caused the surface to be constrained, meaning at least
- * partially outside positioning boundaries set by the compositor. The
- * adjustment is set by constructing a bitmask describing the adjustment to
- * be made when the surface is constrained on that axis.
- *
- * If no bit for one axis is set, the compositor will assume that the child
- * surface should not change its position on that axis when constrained.
- *
- * If more than one bit for one axis is set, the order of how adjustments
- * are applied is specified in the corresponding adjustment descriptions.
- *
- * The default adjustment is none.
- */
-static inline void
-xdg_positioner_set_constraint_adjustment(struct xdg_positioner *xdg_positioner, uint32_t constraint_adjustment)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, constraint_adjustment);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Specify the surface position offset relative to the position of the
- * anchor on the anchor rectangle and the anchor on the surface. For
- * example if the anchor of the anchor rectangle is at (x, y), the surface
- * has the gravity bottom|right, and the offset is (ox, oy), the calculated
- * surface position will be (x + ox, y + oy). The offset position of the
- * surface is the one used for constraint testing. See
- * set_constraint_adjustment.
- *
- * An example use case is placing a popup menu on top of a user interface
- * element, while aligning the user interface element of the parent surface
- * with some user interface element placed somewhere in the popup surface.
- */
-static inline void
-xdg_positioner_set_offset(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_OFFSET, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * When set reactive, the surface is reconstrained if the conditions used
- * for constraining changed, e.g. the parent window moved.
- *
- * If the conditions changed and the popup was reconstrained, an
- * xdg_popup.configure event is sent with updated geometry, followed by an
- * xdg_surface.configure event.
- */
-static inline void
-xdg_positioner_set_reactive(struct xdg_positioner *xdg_positioner)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_REACTIVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Set the parent window geometry the compositor should use when
- * positioning the popup. The compositor may use this information to
- * determine the future state the popup should be constrained using. If
- * this doesn't match the dimension of the parent the popup is eventually
- * positioned against, the behavior is undefined.
- *
- * The arguments are given in the surface-local coordinate space.
- */
-static inline void
-xdg_positioner_set_parent_size(struct xdg_positioner *xdg_positioner, int32_t parent_width, int32_t parent_height)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_PARENT_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, parent_width, parent_height);
-}
-
-/**
- * @ingroup iface_xdg_positioner
- *
- * Set the serial of an xdg_surface.configure event this positioner will be
- * used in response to. The compositor may use this information together
- * with set_parent_size to determine what future state the popup should be
- * constrained using.
- */
-static inline void
-xdg_positioner_set_parent_configure(struct xdg_positioner *xdg_positioner, uint32_t serial)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner,
- XDG_POSITIONER_SET_PARENT_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, serial);
-}
-
-#ifndef XDG_SURFACE_ERROR_ENUM
-#define XDG_SURFACE_ERROR_ENUM
-enum xdg_surface_error {
- /**
- * Surface was not fully constructed
- */
- XDG_SURFACE_ERROR_NOT_CONSTRUCTED = 1,
- /**
- * Surface was already constructed
- */
- XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED = 2,
- /**
- * Attaching a buffer to an unconfigured surface
- */
- XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER = 3,
- /**
- * Invalid serial number when acking a configure event
- */
- XDG_SURFACE_ERROR_INVALID_SERIAL = 4,
- /**
- * Width or height was zero or negative
- */
- XDG_SURFACE_ERROR_INVALID_SIZE = 5,
- /**
- * Surface was destroyed before its role object
- */
- XDG_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT = 6,
-};
-#endif /* XDG_SURFACE_ERROR_ENUM */
-
-/**
- * @ingroup iface_xdg_surface
- * @struct xdg_surface_listener
- */
-struct xdg_surface_listener {
- /**
- * suggest a surface change
- *
- * The configure event marks the end of a configure sequence. A
- * configure sequence is a set of one or more events configuring
- * the state of the xdg_surface, including the final
- * xdg_surface.configure event.
- *
- * Where applicable, xdg_surface surface roles will during a
- * configure sequence extend this event as a latched state sent as
- * events before the xdg_surface.configure event. Such events
- * should be considered to make up a set of atomically applied
- * configuration states, where the xdg_surface.configure commits
- * the accumulated state.
- *
- * Clients should arrange their surface for the new states, and
- * then send an ack_configure request with the serial sent in this
- * configure event at some point before committing the new surface.
- *
- * If the client receives multiple configure events before it can
- * respond to one, it is free to discard all but the last event it
- * received.
- * @param serial serial of the configure event
- */
- void (*configure)(void *data,
- struct xdg_surface *xdg_surface,
- uint32_t serial);
-};
-
-/**
- * @ingroup iface_xdg_surface
- */
-static inline int
-xdg_surface_add_listener(struct xdg_surface *xdg_surface,
- const struct xdg_surface_listener *listener, void *data)
-{
- return wl_proxy_add_listener((struct wl_proxy *) xdg_surface,
- (void (**)(void)) listener, data);
-}
-
-#define XDG_SURFACE_DESTROY 0
-#define XDG_SURFACE_GET_TOPLEVEL 1
-#define XDG_SURFACE_GET_POPUP 2
-#define XDG_SURFACE_SET_WINDOW_GEOMETRY 3
-#define XDG_SURFACE_ACK_CONFIGURE 4
-
-/**
- * @ingroup iface_xdg_surface
- */
-#define XDG_SURFACE_CONFIGURE_SINCE_VERSION 1
-
-/**
- * @ingroup iface_xdg_surface
- */
-#define XDG_SURFACE_DESTROY_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_surface
- */
-#define XDG_SURFACE_GET_TOPLEVEL_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_surface
- */
-#define XDG_SURFACE_GET_POPUP_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_surface
- */
-#define XDG_SURFACE_SET_WINDOW_GEOMETRY_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_surface
- */
-#define XDG_SURFACE_ACK_CONFIGURE_SINCE_VERSION 1
-
-/** @ingroup iface_xdg_surface */
-static inline void
-xdg_surface_set_user_data(struct xdg_surface *xdg_surface, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) xdg_surface, user_data);
-}
-
-/** @ingroup iface_xdg_surface */
-static inline void *
-xdg_surface_get_user_data(struct xdg_surface *xdg_surface)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) xdg_surface);
-}
-
-static inline uint32_t
-xdg_surface_get_version(struct xdg_surface *xdg_surface)
-{
- return wl_proxy_get_version((struct wl_proxy *) xdg_surface);
-}
-
-/**
- * @ingroup iface_xdg_surface
- *
- * Destroy the xdg_surface object. An xdg_surface must only be destroyed
- * after its role object has been destroyed, otherwise
- * a defunct_role_object error is raised.
- */
-static inline void
-xdg_surface_destroy(struct xdg_surface *xdg_surface)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
- XDG_SURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), WL_MARSHAL_FLAG_DESTROY);
-}
-
-/**
- * @ingroup iface_xdg_surface
- *
- * This creates an xdg_toplevel object for the given xdg_surface and gives
- * the associated wl_surface the xdg_toplevel role.
- *
- * See the documentation of xdg_toplevel for more details about what an
- * xdg_toplevel is and how it is used.
- */
-static inline struct xdg_toplevel *
-xdg_surface_get_toplevel(struct xdg_surface *xdg_surface)
-{
- struct wl_proxy *id;
-
- id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
- XDG_SURFACE_GET_TOPLEVEL, &xdg_toplevel_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL);
-
- return (struct xdg_toplevel *) id;
-}
-
-/**
- * @ingroup iface_xdg_surface
- *
- * This creates an xdg_popup object for the given xdg_surface and gives
- * the associated wl_surface the xdg_popup role.
- *
- * If null is passed as a parent, a parent surface must be specified using
- * some other protocol, before committing the initial state.
- *
- * See the documentation of xdg_popup for more details about what an
- * xdg_popup is and how it is used.
- */
-static inline struct xdg_popup *
-xdg_surface_get_popup(struct xdg_surface *xdg_surface, struct xdg_surface *parent, struct xdg_positioner *positioner)
-{
- struct wl_proxy *id;
-
- id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
- XDG_SURFACE_GET_POPUP, &xdg_popup_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL, parent, positioner);
-
- return (struct xdg_popup *) id;
-}
-
-/**
- * @ingroup iface_xdg_surface
- *
- * The window geometry of a surface is its "visible bounds" from the
- * user's perspective. Client-side decorations often have invisible
- * portions like drop-shadows which should be ignored for the
- * purposes of aligning, placing and constraining windows.
- *
- * The window geometry is double-buffered state, see wl_surface.commit.
- *
- * When maintaining a position, the compositor should treat the (x, y)
- * coordinate of the window geometry as the top left corner of the window.
- * A client changing the (x, y) window geometry coordinate should in
- * general not alter the position of the window.
- *
- * Once the window geometry of the surface is set, it is not possible to
- * unset it, and it will remain the same until set_window_geometry is
- * called again, even if a new subsurface or buffer is attached.
- *
- * If never set, the value is the full bounds of the surface,
- * including any subsurfaces. This updates dynamically on every
- * commit. This unset is meant for extremely simple clients.
- *
- * The arguments are given in the surface-local coordinate space of
- * the wl_surface associated with this xdg_surface, and may extend outside
- * of the wl_surface itself to mark parts of the subsurface tree as part of
- * the window geometry.
- *
- * When applied, the effective window geometry will be the set window
- * geometry clamped to the bounding rectangle of the combined
- * geometry of the surface of the xdg_surface and the associated
- * subsurfaces.
- *
- * The effective geometry will not be recalculated unless a new call to
- * set_window_geometry is done and the new pending surface state is
- * subsequently applied.
- *
- * The width and height of the effective window geometry must be
- * greater than zero. Setting an invalid size will raise an
- * invalid_size error.
- */
-static inline void
-xdg_surface_set_window_geometry(struct xdg_surface *xdg_surface, int32_t x, int32_t y, int32_t width, int32_t height)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
- XDG_SURFACE_SET_WINDOW_GEOMETRY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, x, y, width, height);
-}
-
-/**
- * @ingroup iface_xdg_surface
- *
- * When a configure event is received, if a client commits the
- * surface in response to the configure event, then the client
- * must make an ack_configure request sometime before the commit
- * request, passing along the serial of the configure event.
- *
- * For instance, for toplevel surfaces the compositor might use this
- * information to move a surface to the top left only when the client has
- * drawn itself for the maximized or fullscreen state.
- *
- * If the client receives multiple configure events before it
- * can respond to one, it only has to ack the last configure event.
- * Acking a configure event that was never sent raises an invalid_serial
- * error.
- *
- * A client is not required to commit immediately after sending
- * an ack_configure request - it may even ack_configure several times
- * before its next surface commit.
- *
- * A client may send multiple ack_configure requests before committing, but
- * only the last request sent before a commit indicates which configure
- * event the client really is responding to.
- *
- * Sending an ack_configure request consumes the serial number sent with
- * the request, as well as serial numbers sent by all configure events
- * sent on this xdg_surface prior to the configure event referenced by
- * the committed serial.
- *
- * It is an error to issue multiple ack_configure requests referencing a
- * serial from the same configure event, or to issue an ack_configure
- * request referencing a serial from a configure event issued before the
- * event identified by the last ack_configure request for the same
- * xdg_surface. Doing so will raise an invalid_serial error.
- */
-static inline void
-xdg_surface_ack_configure(struct xdg_surface *xdg_surface, uint32_t serial)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface,
- XDG_SURFACE_ACK_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, serial);
-}
-
-#ifndef XDG_TOPLEVEL_ERROR_ENUM
-#define XDG_TOPLEVEL_ERROR_ENUM
-enum xdg_toplevel_error {
- /**
- * provided value is not a valid variant of the resize_edge enum
- */
- XDG_TOPLEVEL_ERROR_INVALID_RESIZE_EDGE = 0,
- /**
- * invalid parent toplevel
- */
- XDG_TOPLEVEL_ERROR_INVALID_PARENT = 1,
- /**
- * client provided an invalid min or max size
- */
- XDG_TOPLEVEL_ERROR_INVALID_SIZE = 2,
-};
-#endif /* XDG_TOPLEVEL_ERROR_ENUM */
-
-#ifndef XDG_TOPLEVEL_RESIZE_EDGE_ENUM
-#define XDG_TOPLEVEL_RESIZE_EDGE_ENUM
-/**
- * @ingroup iface_xdg_toplevel
- * edge values for resizing
- *
- * These values are used to indicate which edge of a surface
- * is being dragged in a resize operation.
- */
-enum xdg_toplevel_resize_edge {
- XDG_TOPLEVEL_RESIZE_EDGE_NONE = 0,
- XDG_TOPLEVEL_RESIZE_EDGE_TOP = 1,
- XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM = 2,
- XDG_TOPLEVEL_RESIZE_EDGE_LEFT = 4,
- XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT = 5,
- XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT = 6,
- XDG_TOPLEVEL_RESIZE_EDGE_RIGHT = 8,
- XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT = 9,
- XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT = 10,
-};
-#endif /* XDG_TOPLEVEL_RESIZE_EDGE_ENUM */
-
-#ifndef XDG_TOPLEVEL_STATE_ENUM
-#define XDG_TOPLEVEL_STATE_ENUM
-/**
- * @ingroup iface_xdg_toplevel
- * types of state on the surface
- *
- * The different state values used on the surface. This is designed for
- * state values like maximized, fullscreen. It is paired with the
- * configure event to ensure that both the client and the compositor
- * setting the state can be synchronized.
- *
- * States set in this way are double-buffered, see wl_surface.commit.
- */
-enum xdg_toplevel_state {
- /**
- * the surface is maximized
- * the surface is maximized
- *
- * The surface is maximized. The window geometry specified in the
- * configure event must be obeyed by the client, or the
- * xdg_wm_base.invalid_surface_state error is raised.
- *
- * The client should draw without shadow or other decoration
- * outside of the window geometry.
- */
- XDG_TOPLEVEL_STATE_MAXIMIZED = 1,
- /**
- * the surface is fullscreen
- * the surface is fullscreen
- *
- * The surface is fullscreen. The window geometry specified in
- * the configure event is a maximum; the client cannot resize
- * beyond it. For a surface to cover the whole fullscreened area,
- * the geometry dimensions must be obeyed by the client. For more
- * details, see xdg_toplevel.set_fullscreen.
- */
- XDG_TOPLEVEL_STATE_FULLSCREEN = 2,
- /**
- * the surface is being resized
- * the surface is being resized
- *
- * The surface is being resized. The window geometry specified in
- * the configure event is a maximum; the client cannot resize
- * beyond it. Clients that have aspect ratio or cell sizing
- * configuration can use a smaller size, however.
- */
- XDG_TOPLEVEL_STATE_RESIZING = 3,
- /**
- * the surface is now activated
- * the surface is now activated
- *
- * Client window decorations should be painted as if the window
- * is active. Do not assume this means that the window actually has
- * keyboard or pointer focus.
- */
- XDG_TOPLEVEL_STATE_ACTIVATED = 4,
- /**
- * the surface’s left edge is tiled
- *
- * The window is currently in a tiled layout and the left edge is
- * considered to be adjacent to another part of the tiling grid.
- *
- * The client should draw without shadow or other decoration
- * outside of the window geometry on the left edge.
- * @since 2
- */
- XDG_TOPLEVEL_STATE_TILED_LEFT = 5,
- /**
- * the surface’s right edge is tiled
- *
- * The window is currently in a tiled layout and the right edge
- * is considered to be adjacent to another part of the tiling grid.
- *
- * The client should draw without shadow or other decoration
- * outside of the window geometry on the right edge.
- * @since 2
- */
- XDG_TOPLEVEL_STATE_TILED_RIGHT = 6,
- /**
- * the surface’s top edge is tiled
- *
- * The window is currently in a tiled layout and the top edge is
- * considered to be adjacent to another part of the tiling grid.
- *
- * The client should draw without shadow or other decoration
- * outside of the window geometry on the top edge.
- * @since 2
- */
- XDG_TOPLEVEL_STATE_TILED_TOP = 7,
- /**
- * the surface’s bottom edge is tiled
- *
- * The window is currently in a tiled layout and the bottom edge
- * is considered to be adjacent to another part of the tiling grid.
- *
- * The client should draw without shadow or other decoration
- * outside of the window geometry on the bottom edge.
- * @since 2
- */
- XDG_TOPLEVEL_STATE_TILED_BOTTOM = 8,
- /**
- * surface repaint is suspended
- *
- * The surface is currently not ordinarily being repainted; for
- * example because its content is occluded by another window, or
- * its outputs are switched off due to screen locking.
- * @since 6
- */
- XDG_TOPLEVEL_STATE_SUSPENDED = 9,
- /**
- * the surface’s left edge is constrained
- *
- * The left edge of the window is currently constrained, meaning
- * it shouldn't attempt to resize from that edge. It can for
- * example mean it's tiled next to a monitor edge on the
- * constrained side of the window.
- * @since 7
- */
- XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT = 10,
- /**
- * the surface’s right edge is constrained
- *
- * The right edge of the window is currently constrained, meaning
- * it shouldn't attempt to resize from that edge. It can for
- * example mean it's tiled next to a monitor edge on the
- * constrained side of the window.
- * @since 7
- */
- XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT = 11,
- /**
- * the surface’s top edge is constrained
- *
- * The top edge of the window is currently constrained, meaning
- * it shouldn't attempt to resize from that edge. It can for
- * example mean it's tiled next to a monitor edge on the
- * constrained side of the window.
- * @since 7
- */
- XDG_TOPLEVEL_STATE_CONSTRAINED_TOP = 12,
- /**
- * the surface’s bottom edge is tiled
- *
- * The bottom edge of the window is currently constrained,
- * meaning it shouldn't attempt to resize from that edge. It can
- * for example mean it's tiled next to a monitor edge on the
- * constrained side of the window.
- * @since 7
- */
- XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM = 13,
-};
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION 2
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION 2
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_TILED_TOP_SINCE_VERSION 2
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_TILED_BOTTOM_SINCE_VERSION 2
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION 6
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION 7
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT_SINCE_VERSION 7
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_CONSTRAINED_TOP_SINCE_VERSION 7
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM_SINCE_VERSION 7
-#endif /* XDG_TOPLEVEL_STATE_ENUM */
-
-#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM
-#define XDG_TOPLEVEL_WM_CAPABILITIES_ENUM
-enum xdg_toplevel_wm_capabilities {
- /**
- * show_window_menu is available
- */
- XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU = 1,
- /**
- * set_maximized and unset_maximized are available
- */
- XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE = 2,
- /**
- * set_fullscreen and unset_fullscreen are available
- */
- XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 3,
- /**
- * set_minimized is available
- */
- XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE = 4,
-};
-#endif /* XDG_TOPLEVEL_WM_CAPABILITIES_ENUM */
-
-/**
- * @ingroup iface_xdg_toplevel
- * @struct xdg_toplevel_listener
- */
-struct xdg_toplevel_listener {
- /**
- * suggest a surface change
- *
- * This configure event asks the client to resize its toplevel
- * surface or to change its state. The configured state should not
- * be applied immediately. See xdg_surface.configure for details.
- *
- * The width and height arguments specify a hint to the window
- * about how its surface should be resized in window geometry
- * coordinates. See set_window_geometry.
- *
- * If the width or height arguments are zero, it means the client
- * should decide its own window dimension. This may happen when the
- * compositor needs to configure the state of the surface but
- * doesn't have any information about any previous or expected
- * dimension.
- *
- * The states listed in the event specify how the width/height
- * arguments should be interpreted, and possibly how it should be
- * drawn.
- *
- * Clients must send an ack_configure in response to this event.
- * See xdg_surface.configure and xdg_surface.ack_configure for
- * details.
- */
- void (*configure)(void *data,
- struct xdg_toplevel *xdg_toplevel,
- int32_t width,
- int32_t height,
- struct wl_array *states);
- /**
- * surface wants to be closed
- *
- * The close event is sent by the compositor when the user wants
- * the surface to be closed. This should be equivalent to the user
- * clicking the close button in client-side decorations, if your
- * application has any.
- *
- * This is only a request that the user intends to close the
- * window. The client may choose to ignore this request, or show a
- * dialog to ask the user to save their data, etc.
- */
- void (*close)(void *data,
- struct xdg_toplevel *xdg_toplevel);
- /**
- * recommended window geometry bounds
- *
- * The configure_bounds event may be sent prior to a
- * xdg_toplevel.configure event to communicate the bounds a window
- * geometry size is recommended to constrain to.
- *
- * The passed width and height are in surface coordinate space. If
- * width and height are 0, it means bounds is unknown and
- * equivalent to as if no configure_bounds event was ever sent for
- * this surface.
- *
- * The bounds can for example correspond to the size of a monitor
- * excluding any panels or other shell components, so that a
- * surface isn't created in a way that it cannot fit.
- *
- * The bounds may change at any point, and in such a case, a new
- * xdg_toplevel.configure_bounds will be sent, followed by
- * xdg_toplevel.configure and xdg_surface.configure.
- * @since 4
- */
- void (*configure_bounds)(void *data,
- struct xdg_toplevel *xdg_toplevel,
- int32_t width,
- int32_t height);
- /**
- * compositor capabilities
- *
- * This event advertises the capabilities supported by the
- * compositor. If a capability isn't supported, clients should hide
- * or disable the UI elements that expose this functionality. For
- * instance, if the compositor doesn't advertise support for
- * minimized toplevels, a button triggering the set_minimized
- * request should not be displayed.
- *
- * The compositor will ignore requests it doesn't support. For
- * instance, a compositor which doesn't advertise support for
- * minimized will ignore set_minimized requests.
- *
- * Compositors must send this event once before the first
- * xdg_surface.configure event. When the capabilities change,
- * compositors must send this event again and then send an
- * xdg_surface.configure event.
- *
- * The configured state should not be applied immediately. See
- * xdg_surface.configure for details.
- *
- * The capabilities are sent as an array of 32-bit unsigned
- * integers in native endianness.
- * @param capabilities array of 32-bit capabilities
- * @since 5
- */
- void (*wm_capabilities)(void *data,
- struct xdg_toplevel *xdg_toplevel,
- struct wl_array *capabilities);
-};
-
-/**
- * @ingroup iface_xdg_toplevel
- */
-static inline int
-xdg_toplevel_add_listener(struct xdg_toplevel *xdg_toplevel,
- const struct xdg_toplevel_listener *listener, void *data)
-{
- return wl_proxy_add_listener((struct wl_proxy *) xdg_toplevel,
- (void (**)(void)) listener, data);
-}
-
-#define XDG_TOPLEVEL_DESTROY 0
-#define XDG_TOPLEVEL_SET_PARENT 1
-#define XDG_TOPLEVEL_SET_TITLE 2
-#define XDG_TOPLEVEL_SET_APP_ID 3
-#define XDG_TOPLEVEL_SHOW_WINDOW_MENU 4
-#define XDG_TOPLEVEL_MOVE 5
-#define XDG_TOPLEVEL_RESIZE 6
-#define XDG_TOPLEVEL_SET_MAX_SIZE 7
-#define XDG_TOPLEVEL_SET_MIN_SIZE 8
-#define XDG_TOPLEVEL_SET_MAXIMIZED 9
-#define XDG_TOPLEVEL_UNSET_MAXIMIZED 10
-#define XDG_TOPLEVEL_SET_FULLSCREEN 11
-#define XDG_TOPLEVEL_UNSET_FULLSCREEN 12
-#define XDG_TOPLEVEL_SET_MINIMIZED 13
-
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_CONFIGURE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_CLOSE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION 4
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION 5
-
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_DESTROY_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_PARENT_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_TITLE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_APP_ID_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SHOW_WINDOW_MENU_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_MOVE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_RESIZE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_MAX_SIZE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_MIN_SIZE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_MAXIMIZED_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_UNSET_MAXIMIZED_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_FULLSCREEN_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_UNSET_FULLSCREEN_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_toplevel
- */
-#define XDG_TOPLEVEL_SET_MINIMIZED_SINCE_VERSION 1
-
-/** @ingroup iface_xdg_toplevel */
-static inline void
-xdg_toplevel_set_user_data(struct xdg_toplevel *xdg_toplevel, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) xdg_toplevel, user_data);
-}
-
-/** @ingroup iface_xdg_toplevel */
-static inline void *
-xdg_toplevel_get_user_data(struct xdg_toplevel *xdg_toplevel)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) xdg_toplevel);
-}
-
-static inline uint32_t
-xdg_toplevel_get_version(struct xdg_toplevel *xdg_toplevel)
-{
- return wl_proxy_get_version((struct wl_proxy *) xdg_toplevel);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * This request destroys the role surface and unmaps the surface;
- * see "Unmapping" behavior in interface section for details.
- */
-static inline void
-xdg_toplevel_destroy(struct xdg_toplevel *xdg_toplevel)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), WL_MARSHAL_FLAG_DESTROY);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Set the "parent" of this surface. This surface should be stacked
- * above the parent surface and all other ancestor surfaces.
- *
- * Parent surfaces should be set on dialogs, toolboxes, or other
- * "auxiliary" surfaces, so that the parent is raised when the dialog
- * is raised.
- *
- * Setting a null parent for a child surface unsets its parent. Setting
- * a null parent for a surface which currently has no parent is a no-op.
- *
- * Only mapped surfaces can have child surfaces. Setting a parent which
- * is not mapped is equivalent to setting a null parent. If a surface
- * becomes unmapped, its children's parent is set to the parent of
- * the now-unmapped surface. If the now-unmapped surface has no parent,
- * its children's parent is unset. If the now-unmapped surface becomes
- * mapped again, its parent-child relationship is not restored.
- *
- * The parent toplevel must not be one of the child toplevel's
- * descendants, and the parent must be different from the child toplevel,
- * otherwise the invalid_parent protocol error is raised.
- */
-static inline void
-xdg_toplevel_set_parent(struct xdg_toplevel *xdg_toplevel, struct xdg_toplevel *parent)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_PARENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, parent);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Set a short title for the surface.
- *
- * This string may be used to identify the surface in a task bar,
- * window list, or other user interface elements provided by the
- * compositor.
- *
- * The string must be encoded in UTF-8.
- */
-static inline void
-xdg_toplevel_set_title(struct xdg_toplevel *xdg_toplevel, const char *title)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_TITLE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, title);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Set an application identifier for the surface.
- *
- * The app ID identifies the general class of applications to which
- * the surface belongs. The compositor can use this to group multiple
- * surfaces together, or to determine how to launch a new application.
- *
- * For D-Bus activatable applications, the app ID is used as the D-Bus
- * service name.
- *
- * The compositor shell will try to group application surfaces together
- * by their app ID. As a best practice, it is suggested to select app
- * ID's that match the basename of the application's .desktop file.
- * For example, "org.freedesktop.FooViewer" where the .desktop file is
- * "org.freedesktop.FooViewer.desktop".
- *
- * Like other properties, a set_app_id request can be sent after the
- * xdg_toplevel has been mapped to update the property.
- *
- * See the desktop-entry specification [0] for more details on
- * application identifiers and how they relate to well-known D-Bus
- * names and .desktop files.
- *
- * [0] https://standards.freedesktop.org/desktop-entry-spec/
- */
-static inline void
-xdg_toplevel_set_app_id(struct xdg_toplevel *xdg_toplevel, const char *app_id)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_APP_ID, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, app_id);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Clients implementing client-side decorations might want to show
- * a context menu when right-clicking on the decorations, giving the
- * user a menu that they can use to maximize or minimize the window.
- *
- * This request asks the compositor to pop up such a window menu at
- * the given position, relative to the local surface coordinates of
- * the parent surface. There are no guarantees as to what menu items
- * the window menu contains, or even if a window menu will be drawn
- * at all.
- *
- * This request must be used in response to some sort of user action
- * like a button press, key press, or touch down event.
- */
-static inline void
-xdg_toplevel_show_window_menu(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, int32_t x, int32_t y)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SHOW_WINDOW_MENU, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, x, y);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Start an interactive, user-driven move of the surface.
- *
- * This request must be used in response to some sort of user action
- * like a button press, key press, or touch down event. The passed
- * serial is used to determine the type of interactive move (touch,
- * pointer, etc).
- *
- * The server may ignore move requests depending on the state of
- * the surface (e.g. fullscreen or maximized), or if the passed serial
- * is no longer valid.
- *
- * If triggered, the surface will lose the focus of the device
- * (wl_pointer, wl_touch, etc) used for the move. It is up to the
- * compositor to visually indicate that the move is taking place, such as
- * updating a pointer cursor, during the move. There is no guarantee
- * that the device focus will return when the move is completed.
- */
-static inline void
-xdg_toplevel_move(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_MOVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Start a user-driven, interactive resize of the surface.
- *
- * This request must be used in response to some sort of user action
- * like a button press, key press, or touch down event. The passed
- * serial is used to determine the type of interactive resize (touch,
- * pointer, etc).
- *
- * The server may ignore resize requests depending on the state of
- * the surface (e.g. fullscreen or maximized).
- *
- * If triggered, the client will receive configure events with the
- * "resize" state enum value and the expected sizes. See the "resize"
- * enum value for more details about what is required. The client
- * must also acknowledge configure events using "ack_configure". After
- * the resize is completed, the client will receive another "configure"
- * event without the resize state.
- *
- * If triggered, the surface also will lose the focus of the device
- * (wl_pointer, wl_touch, etc) used for the resize. It is up to the
- * compositor to visually indicate that the resize is taking place,
- * such as updating a pointer cursor, during the resize. There is no
- * guarantee that the device focus will return when the resize is
- * completed.
- *
- * The edges parameter specifies how the surface should be resized, and
- * is one of the values of the resize_edge enum. Values not matching
- * a variant of the enum will cause the invalid_resize_edge protocol error.
- * The compositor may use this information to update the surface position
- * for example when dragging the top left corner. The compositor may also
- * use this information to adapt its behavior, e.g. choose an appropriate
- * cursor image.
- */
-static inline void
-xdg_toplevel_resize(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, uint32_t edges)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, edges);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Set a maximum size for the window.
- *
- * The client can specify a maximum size so that the compositor does
- * not try to configure the window beyond this size.
- *
- * The width and height arguments are in window geometry coordinates.
- * See xdg_surface.set_window_geometry.
- *
- * Values set in this way are double-buffered, see wl_surface.commit.
- *
- * The compositor can use this information to allow or disallow
- * different states like maximize or fullscreen and draw accurate
- * animations.
- *
- * Similarly, a tiling window manager may use this information to
- * place and resize client windows in a more effective way.
- *
- * The client should not rely on the compositor to obey the maximum
- * size. The compositor may decide to ignore the values set by the
- * client and request a larger size.
- *
- * If never set, or a value of zero in the request, means that the
- * client has no expected maximum size in the given dimension.
- * As a result, a client wishing to reset the maximum size
- * to an unspecified state can use zero for width and height in the
- * request.
- *
- * Requesting a maximum size to be smaller than the minimum size of
- * a surface is illegal and will result in an invalid_size error.
- *
- * The width and height must be greater than or equal to zero. Using
- * strictly negative values for width or height will result in a
- * invalid_size error.
- */
-static inline void
-xdg_toplevel_set_max_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_MAX_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Set a minimum size for the window.
- *
- * The client can specify a minimum size so that the compositor does
- * not try to configure the window below this size.
- *
- * The width and height arguments are in window geometry coordinates.
- * See xdg_surface.set_window_geometry.
- *
- * Values set in this way are double-buffered, see wl_surface.commit.
- *
- * The compositor can use this information to allow or disallow
- * different states like maximize or fullscreen and draw accurate
- * animations.
- *
- * Similarly, a tiling window manager may use this information to
- * place and resize client windows in a more effective way.
- *
- * The client should not rely on the compositor to obey the minimum
- * size. The compositor may decide to ignore the values set by the
- * client and request a smaller size.
- *
- * If never set, or a value of zero in the request, means that the
- * client has no expected minimum size in the given dimension.
- * As a result, a client wishing to reset the minimum size
- * to an unspecified state can use zero for width and height in the
- * request.
- *
- * Requesting a minimum size to be larger than the maximum size of
- * a surface is illegal and will result in an invalid_size error.
- *
- * The width and height must be greater than or equal to zero. Using
- * strictly negative values for width and height will result in a
- * invalid_size error.
- */
-static inline void
-xdg_toplevel_set_min_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_MIN_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Maximize the surface.
- *
- * After requesting that the surface should be maximized, the compositor
- * will respond by emitting a configure event. Whether this configure
- * actually sets the window maximized is subject to compositor policies.
- * The client must then update its content, drawing in the configured
- * state. The client must also acknowledge the configure when committing
- * the new content (see ack_configure).
- *
- * It is up to the compositor to decide how and where to maximize the
- * surface, for example which output and what region of the screen should
- * be used.
- *
- * If the surface was already maximized, the compositor will still emit
- * a configure event with the "maximized" state.
- *
- * If the surface is in a fullscreen state, this request has no direct
- * effect. It may alter the state the surface is returned to when
- * unmaximized unless overridden by the compositor.
- */
-static inline void
-xdg_toplevel_set_maximized(struct xdg_toplevel *xdg_toplevel)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Unmaximize the surface.
- *
- * After requesting that the surface should be unmaximized, the compositor
- * will respond by emitting a configure event. Whether this actually
- * un-maximizes the window is subject to compositor policies.
- * If available and applicable, the compositor will include the window
- * geometry dimensions the window had prior to being maximized in the
- * configure event. The client must then update its content, drawing it in
- * the configured state. The client must also acknowledge the configure
- * when committing the new content (see ack_configure).
- *
- * It is up to the compositor to position the surface after it was
- * unmaximized; usually the position the surface had before maximizing, if
- * applicable.
- *
- * If the surface was already not maximized, the compositor will still
- * emit a configure event without the "maximized" state.
- *
- * If the surface is in a fullscreen state, this request has no direct
- * effect. It may alter the state the surface is returned to when
- * unmaximized unless overridden by the compositor.
- */
-static inline void
-xdg_toplevel_unset_maximized(struct xdg_toplevel *xdg_toplevel)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_UNSET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Make the surface fullscreen.
- *
- * After requesting that the surface should be fullscreened, the
- * compositor will respond by emitting a configure event. Whether the
- * client is actually put into a fullscreen state is subject to compositor
- * policies. The client must also acknowledge the configure when
- * committing the new content (see ack_configure).
- *
- * The output passed by the request indicates the client's preference as
- * to which display it should be set fullscreen on. If this value is NULL,
- * it's up to the compositor to choose which display will be used to map
- * this surface.
- *
- * If the surface doesn't cover the whole output, the compositor will
- * position the surface in the center of the output and compensate with
- * with border fill covering the rest of the output. The content of the
- * border fill is undefined, but should be assumed to be in some way that
- * attempts to blend into the surrounding area (e.g. solid black).
- *
- * If the fullscreened surface is not opaque, the compositor must make
- * sure that other screen content not part of the same surface tree (made
- * up of subsurfaces, popups or similarly coupled surfaces) are not
- * visible below the fullscreened surface.
- */
-static inline void
-xdg_toplevel_set_fullscreen(struct xdg_toplevel *xdg_toplevel, struct wl_output *output)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, output);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Make the surface no longer fullscreen.
- *
- * After requesting that the surface should be unfullscreened, the
- * compositor will respond by emitting a configure event.
- * Whether this actually removes the fullscreen state of the client is
- * subject to compositor policies.
- *
- * Making a surface unfullscreen sets states for the surface based on the following:
- * * the state(s) it may have had before becoming fullscreen
- * * any state(s) decided by the compositor
- * * any state(s) requested by the client while the surface was fullscreen
- *
- * The compositor may include the previous window geometry dimensions in
- * the configure event, if applicable.
- *
- * The client must also acknowledge the configure when committing the new
- * content (see ack_configure).
- */
-static inline void
-xdg_toplevel_unset_fullscreen(struct xdg_toplevel *xdg_toplevel)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_UNSET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
-}
-
-/**
- * @ingroup iface_xdg_toplevel
- *
- * Request that the compositor minimize your surface. There is no
- * way to know if the surface is currently minimized, nor is there
- * any way to unset minimization on this surface.
- *
- * If you are looking to throttle redrawing when minimized, please
- * instead use the wl_surface.frame event for this, as this will
- * also work with live previews on windows in Alt-Tab, Expose or
- * similar compositor features.
- */
-static inline void
-xdg_toplevel_set_minimized(struct xdg_toplevel *xdg_toplevel)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel,
- XDG_TOPLEVEL_SET_MINIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0);
-}
-
-#ifndef XDG_POPUP_ERROR_ENUM
-#define XDG_POPUP_ERROR_ENUM
-enum xdg_popup_error {
- /**
- * tried to grab after being mapped
- */
- XDG_POPUP_ERROR_INVALID_GRAB = 0,
-};
-#endif /* XDG_POPUP_ERROR_ENUM */
-
-/**
- * @ingroup iface_xdg_popup
- * @struct xdg_popup_listener
- */
-struct xdg_popup_listener {
- /**
- * configure the popup surface
- *
- * This event asks the popup surface to configure itself given
- * the configuration. The configured state should not be applied
- * immediately. See xdg_surface.configure for details.
- *
- * The x and y arguments represent the position the popup was
- * placed at given the xdg_positioner rule, relative to the upper
- * left corner of the window geometry of the parent surface.
- *
- * For version 2 or older, the configure event for an xdg_popup is
- * only ever sent once for the initial configuration. Starting with
- * version 3, it may be sent again if the popup is setup with an
- * xdg_positioner with set_reactive requested, or in response to
- * xdg_popup.reposition requests.
- * @param x x position relative to parent surface window geometry
- * @param y y position relative to parent surface window geometry
- * @param width window geometry width
- * @param height window geometry height
- */
- void (*configure)(void *data,
- struct xdg_popup *xdg_popup,
- int32_t x,
- int32_t y,
- int32_t width,
- int32_t height);
- /**
- * popup interaction is done
- *
- * The popup_done event is sent out when a popup is dismissed by
- * the compositor. The client should destroy the xdg_popup object
- * at this point.
- */
- void (*popup_done)(void *data,
- struct xdg_popup *xdg_popup);
- /**
- * signal the completion of a repositioned request
- *
- * The repositioned event is sent as part of a popup
- * configuration sequence, together with xdg_popup.configure and
- * lastly xdg_surface.configure to notify the completion of a
- * reposition request.
- *
- * The repositioned event is to notify about the completion of a
- * xdg_popup.reposition request. The token argument is the token
- * passed in the xdg_popup.reposition request.
- *
- * Immediately after this event is emitted, xdg_popup.configure and
- * xdg_surface.configure will be sent with the updated size and
- * position, as well as a new configure serial.
- *
- * The client should optionally update the content of the popup,
- * but must acknowledge the new popup configuration for the new
- * position to take effect. See xdg_surface.ack_configure for
- * details.
- * @param token reposition request token
- * @since 3
- */
- void (*repositioned)(void *data,
- struct xdg_popup *xdg_popup,
- uint32_t token);
-};
-
-/**
- * @ingroup iface_xdg_popup
- */
-static inline int
-xdg_popup_add_listener(struct xdg_popup *xdg_popup,
- const struct xdg_popup_listener *listener, void *data)
-{
- return wl_proxy_add_listener((struct wl_proxy *) xdg_popup,
- (void (**)(void)) listener, data);
-}
-
-#define XDG_POPUP_DESTROY 0
-#define XDG_POPUP_GRAB 1
-#define XDG_POPUP_REPOSITION 2
-
-/**
- * @ingroup iface_xdg_popup
- */
-#define XDG_POPUP_CONFIGURE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_popup
- */
-#define XDG_POPUP_POPUP_DONE_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_popup
- */
-#define XDG_POPUP_REPOSITIONED_SINCE_VERSION 3
-
-/**
- * @ingroup iface_xdg_popup
- */
-#define XDG_POPUP_DESTROY_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_popup
- */
-#define XDG_POPUP_GRAB_SINCE_VERSION 1
-/**
- * @ingroup iface_xdg_popup
- */
-#define XDG_POPUP_REPOSITION_SINCE_VERSION 3
-
-/** @ingroup iface_xdg_popup */
-static inline void
-xdg_popup_set_user_data(struct xdg_popup *xdg_popup, void *user_data)
-{
- wl_proxy_set_user_data((struct wl_proxy *) xdg_popup, user_data);
-}
-
-/** @ingroup iface_xdg_popup */
-static inline void *
-xdg_popup_get_user_data(struct xdg_popup *xdg_popup)
-{
- return wl_proxy_get_user_data((struct wl_proxy *) xdg_popup);
-}
-
-static inline uint32_t
-xdg_popup_get_version(struct xdg_popup *xdg_popup)
-{
- return wl_proxy_get_version((struct wl_proxy *) xdg_popup);
-}
-
-/**
- * @ingroup iface_xdg_popup
- *
- * This destroys the popup. Explicitly destroying the xdg_popup
- * object will also dismiss the popup, and unmap the surface.
- *
- * If this xdg_popup is not the "topmost" popup, the
- * xdg_wm_base.not_the_topmost_popup protocol error will be sent.
- */
-static inline void
-xdg_popup_destroy(struct xdg_popup *xdg_popup)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup,
- XDG_POPUP_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), WL_MARSHAL_FLAG_DESTROY);
-}
-
-/**
- * @ingroup iface_xdg_popup
- *
- * This request makes the created popup take an explicit grab. An explicit
- * grab will be dismissed when the user dismisses the popup, or when the
- * client destroys the xdg_popup. This can be done by the user clicking
- * outside the surface, using the keyboard, or even locking the screen
- * through closing the lid or a timeout.
- *
- * If the compositor denies the grab, the popup will be immediately
- * dismissed.
- *
- * This request must be used in response to some sort of user action like a
- * button press, key press, or touch down event. The serial number of the
- * event should be passed as 'serial'.
- *
- * The parent of a grabbing popup must either be an xdg_toplevel surface or
- * another xdg_popup with an explicit grab. If the parent is another
- * xdg_popup it means that the popups are nested, with this popup now being
- * the topmost popup.
- *
- * Nested popups must be destroyed in the reverse order they were created
- * in, e.g. the only popup you are allowed to destroy at all times is the
- * topmost one.
- *
- * When compositors choose to dismiss a popup, they may dismiss every
- * nested grabbing popup as well. When a compositor dismisses popups, it
- * will follow the same dismissing order as required from the client.
- *
- * If the topmost grabbing popup is destroyed, the grab will be returned to
- * the parent of the popup, if that parent previously had an explicit grab.
- *
- * If the parent is a grabbing popup which has already been dismissed, this
- * popup will be immediately dismissed. If the parent is a popup that did
- * not take an explicit grab, an error will be raised.
- *
- * During a popup grab, the client owning the grab will receive pointer
- * and touch events for all their surfaces as normal (similar to an
- * "owner-events" grab in X11 parlance), while the top most grabbing popup
- * will always have keyboard focus.
- */
-static inline void
-xdg_popup_grab(struct xdg_popup *xdg_popup, struct wl_seat *seat, uint32_t serial)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup,
- XDG_POPUP_GRAB, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, seat, serial);
-}
-
-/**
- * @ingroup iface_xdg_popup
- *
- * Reposition an already-mapped popup. The popup will be placed given the
- * details in the passed xdg_positioner object, and a
- * xdg_popup.repositioned followed by xdg_popup.configure and
- * xdg_surface.configure will be emitted in response. Any parameters set
- * by the previous positioner will be discarded.
- *
- * The passed token will be sent in the corresponding
- * xdg_popup.repositioned event. The new popup position will not take
- * effect until the corresponding configure event is acknowledged by the
- * client. See xdg_popup.repositioned for details. The token itself is
- * opaque, and has no other special meaning.
- *
- * If multiple reposition requests are sent, the compositor may skip all
- * but the last one.
- *
- * If the popup is repositioned in response to a configure event for its
- * parent, the client should send an xdg_positioner.set_parent_configure
- * and possibly an xdg_positioner.set_parent_size request to allow the
- * compositor to properly constrain the popup.
- *
- * If the popup is repositioned together with a parent that is being
- * resized, but not in response to a configure event, the client should
- * send an xdg_positioner.set_parent_size request.
- */
-static inline void
-xdg_popup_reposition(struct xdg_popup *xdg_popup, struct xdg_positioner *positioner, uint32_t token)
-{
- wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup,
- XDG_POPUP_REPOSITION, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, positioner, token);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* Generated by wayland-scanner 1.23.1 */
-
-/*
- * Copyright © 2008-2013 Kristian Høgsberg
- * Copyright © 2013 Rafael Antognolli
- * Copyright © 2013 Jasper St. Pierre
- * Copyright © 2010-2013 Intel Corporation
- * Copyright © 2015-2017 Samsung Electronics Co., Ltd
- * Copyright © 2015-2017 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "wayland-util.h"
-
-#ifndef __has_attribute
-# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
-#endif
-
-#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
-#define WL_PRIVATE __attribute__ ((visibility("hidden")))
-#else
-#define WL_PRIVATE
-#endif
-
-extern const struct wl_interface wl_output_interface;
-extern const struct wl_interface wl_seat_interface;
-extern const struct wl_interface wl_surface_interface;
-extern const struct wl_interface xdg_popup_interface;
-extern const struct wl_interface xdg_positioner_interface;
-extern const struct wl_interface xdg_surface_interface;
-extern const struct wl_interface xdg_toplevel_interface;
-
-static const struct wl_interface *xdg_shell_types[] = {
- NULL,
- NULL,
- NULL,
- NULL,
- &xdg_positioner_interface,
- &xdg_surface_interface,
- &wl_surface_interface,
- &xdg_toplevel_interface,
- &xdg_popup_interface,
- &xdg_surface_interface,
- &xdg_positioner_interface,
- &xdg_toplevel_interface,
- &wl_seat_interface,
- NULL,
- NULL,
- NULL,
- &wl_seat_interface,
- NULL,
- &wl_seat_interface,
- NULL,
- NULL,
- &wl_output_interface,
- &wl_seat_interface,
- NULL,
- &xdg_positioner_interface,
- NULL,
-};
-
-static const struct wl_message xdg_wm_base_requests[] = {
- { "destroy", "", xdg_shell_types + 0 },
- { "create_positioner", "n", xdg_shell_types + 4 },
- { "get_xdg_surface", "no", xdg_shell_types + 5 },
- { "pong", "u", xdg_shell_types + 0 },
-};
-
-static const struct wl_message xdg_wm_base_events[] = {
- { "ping", "u", xdg_shell_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface xdg_wm_base_interface = {
- "xdg_wm_base", 7,
- 4, xdg_wm_base_requests,
- 1, xdg_wm_base_events,
-};
-
-static const struct wl_message xdg_positioner_requests[] = {
- { "destroy", "", xdg_shell_types + 0 },
- { "set_size", "ii", xdg_shell_types + 0 },
- { "set_anchor_rect", "iiii", xdg_shell_types + 0 },
- { "set_anchor", "u", xdg_shell_types + 0 },
- { "set_gravity", "u", xdg_shell_types + 0 },
- { "set_constraint_adjustment", "u", xdg_shell_types + 0 },
- { "set_offset", "ii", xdg_shell_types + 0 },
- { "set_reactive", "3", xdg_shell_types + 0 },
- { "set_parent_size", "3ii", xdg_shell_types + 0 },
- { "set_parent_configure", "3u", xdg_shell_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface xdg_positioner_interface = {
- "xdg_positioner", 7,
- 10, xdg_positioner_requests,
- 0, NULL,
-};
-
-static const struct wl_message xdg_surface_requests[] = {
- { "destroy", "", xdg_shell_types + 0 },
- { "get_toplevel", "n", xdg_shell_types + 7 },
- { "get_popup", "n?oo", xdg_shell_types + 8 },
- { "set_window_geometry", "iiii", xdg_shell_types + 0 },
- { "ack_configure", "u", xdg_shell_types + 0 },
-};
-
-static const struct wl_message xdg_surface_events[] = {
- { "configure", "u", xdg_shell_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface xdg_surface_interface = {
- "xdg_surface", 7,
- 5, xdg_surface_requests,
- 1, xdg_surface_events,
-};
-
-static const struct wl_message xdg_toplevel_requests[] = {
- { "destroy", "", xdg_shell_types + 0 },
- { "set_parent", "?o", xdg_shell_types + 11 },
- { "set_title", "s", xdg_shell_types + 0 },
- { "set_app_id", "s", xdg_shell_types + 0 },
- { "show_window_menu", "ouii", xdg_shell_types + 12 },
- { "move", "ou", xdg_shell_types + 16 },
- { "resize", "ouu", xdg_shell_types + 18 },
- { "set_max_size", "ii", xdg_shell_types + 0 },
- { "set_min_size", "ii", xdg_shell_types + 0 },
- { "set_maximized", "", xdg_shell_types + 0 },
- { "unset_maximized", "", xdg_shell_types + 0 },
- { "set_fullscreen", "?o", xdg_shell_types + 21 },
- { "unset_fullscreen", "", xdg_shell_types + 0 },
- { "set_minimized", "", xdg_shell_types + 0 },
-};
-
-static const struct wl_message xdg_toplevel_events[] = {
- { "configure", "iia", xdg_shell_types + 0 },
- { "close", "", xdg_shell_types + 0 },
- { "configure_bounds", "4ii", xdg_shell_types + 0 },
- { "wm_capabilities", "5a", xdg_shell_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface xdg_toplevel_interface = {
- "xdg_toplevel", 7,
- 14, xdg_toplevel_requests,
- 4, xdg_toplevel_events,
-};
-
-static const struct wl_message xdg_popup_requests[] = {
- { "destroy", "", xdg_shell_types + 0 },
- { "grab", "ou", xdg_shell_types + 22 },
- { "reposition", "3ou", xdg_shell_types + 24 },
-};
-
-static const struct wl_message xdg_popup_events[] = {
- { "configure", "iiii", xdg_shell_types + 0 },
- { "popup_done", "", xdg_shell_types + 0 },
- { "repositioned", "3u", xdg_shell_types + 0 },
-};
-
-WL_PRIVATE const struct wl_interface xdg_popup_interface = {
- "xdg_popup", 7,
- 3, xdg_popup_requests,
- 3, xdg_popup_events,
-};
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<protocol name="xdg_shell">
-
- <copyright>
- Copyright © 2008-2013 Kristian Høgsberg
- Copyright © 2013 Rafael Antognolli
- Copyright © 2013 Jasper St. Pierre
- Copyright © 2010-2013 Intel Corporation
- Copyright © 2015-2017 Samsung Electronics Co., Ltd
- Copyright © 2015-2017 Red Hat Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice (including the next
- paragraph) shall be included in all copies or substantial portions of the
- Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
- </copyright>
-
- <interface name="xdg_wm_base" version="7">
- <description summary="create desktop-style surfaces">
- The xdg_wm_base interface is exposed as a global object enabling clients
- to turn their wl_surfaces into windows in a desktop environment. It
- defines the basic functionality needed for clients and the compositor to
- create windows that can be dragged, resized, maximized, etc, as well as
- creating transient windows such as popup menus.
- </description>
-
- <enum name="error">
- <entry name="role" value="0" summary="given wl_surface has another role"/>
- <entry name="defunct_surfaces" value="1"
- summary="xdg_wm_base was destroyed before children"/>
- <entry name="not_the_topmost_popup" value="2"
- summary="the client tried to map or destroy a non-topmost popup"/>
- <entry name="invalid_popup_parent" value="3"
- summary="the client specified an invalid popup parent surface"/>
- <entry name="invalid_surface_state" value="4"
- summary="the client provided an invalid surface state"/>
- <entry name="invalid_positioner" value="5"
- summary="the client provided an invalid positioner"/>
- <entry name="unresponsive" value="6"
- summary="the client didn’t respond to a ping event in time"/>
- </enum>
-
- <request name="destroy" type="destructor">
- <description summary="destroy xdg_wm_base">
- Destroy this xdg_wm_base object.
-
- Destroying a bound xdg_wm_base object while there are surfaces
- still alive created by this xdg_wm_base object instance is illegal
- and will result in a defunct_surfaces error.
- </description>
- </request>
-
- <request name="create_positioner">
- <description summary="create a positioner object">
- Create a positioner object. A positioner object is used to position
- surfaces relative to some parent surface. See the interface description
- and xdg_surface.get_popup for details.
- </description>
- <arg name="id" type="new_id" interface="xdg_positioner"/>
- </request>
-
- <request name="get_xdg_surface">
- <description summary="create a shell surface from a surface">
- This creates an xdg_surface for the given surface. While xdg_surface
- itself is not a role, the corresponding surface may only be assigned
- a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
- illegal to create an xdg_surface for a wl_surface which already has an
- assigned role and this will result in a role error.
-
- This creates an xdg_surface for the given surface. An xdg_surface is
- used as basis to define a role to a given surface, such as xdg_toplevel
- or xdg_popup. It also manages functionality shared between xdg_surface
- based surface roles.
-
- See the documentation of xdg_surface for more details about what an
- xdg_surface is and how it is used.
- </description>
- <arg name="id" type="new_id" interface="xdg_surface"/>
- <arg name="surface" type="object" interface="wl_surface"/>
- </request>
-
- <request name="pong">
- <description summary="respond to a ping event">
- A client must respond to a ping event with a pong request or
- the client may be deemed unresponsive. See xdg_wm_base.ping
- and xdg_wm_base.error.unresponsive.
- </description>
- <arg name="serial" type="uint" summary="serial of the ping event"/>
- </request>
-
- <event name="ping">
- <description summary="check if the client is alive">
- The ping event asks the client if it's still alive. Pass the
- serial specified in the event back to the compositor by sending
- a "pong" request back with the specified serial. See xdg_wm_base.pong.
-
- Compositors can use this to determine if the client is still
- alive. It's unspecified what will happen if the client doesn't
- respond to the ping request, or in what timeframe. Clients should
- try to respond in a reasonable amount of time. The “unresponsive”
- error is provided for compositors that wish to disconnect unresponsive
- clients.
-
- A compositor is free to ping in any way it wants, but a client must
- always respond to any xdg_wm_base object it created.
- </description>
- <arg name="serial" type="uint" summary="pass this to the pong request"/>
- </event>
- </interface>
-
- <interface name="xdg_positioner" version="7">
- <description summary="child surface positioner">
- The xdg_positioner provides a collection of rules for the placement of a
- child surface relative to a parent surface. Rules can be defined to ensure
- the child surface remains within the visible area's borders, and to
- specify how the child surface changes its position, such as sliding along
- an axis, or flipping around a rectangle. These positioner-created rules are
- constrained by the requirement that a child surface must intersect with or
- be at least partially adjacent to its parent surface.
-
- See the various requests for details about possible rules.
-
- At the time of the request, the compositor makes a copy of the rules
- specified by the xdg_positioner. Thus, after the request is complete the
- xdg_positioner object can be destroyed or reused; further changes to the
- object will have no effect on previous usages.
-
- For an xdg_positioner object to be considered complete, it must have a
- non-zero size set by set_size, and a non-zero anchor rectangle set by
- set_anchor_rect. Passing an incomplete xdg_positioner object when
- positioning a surface raises an invalid_positioner error.
- </description>
-
- <enum name="error">
- <entry name="invalid_input" value="0" summary="invalid input provided"/>
- </enum>
-
- <request name="destroy" type="destructor">
- <description summary="destroy the xdg_positioner object">
- Notify the compositor that the xdg_positioner will no longer be used.
- </description>
- </request>
-
- <request name="set_size">
- <description summary="set the size of the to-be positioned rectangle">
- Set the size of the surface that is to be positioned with the positioner
- object. The size is in surface-local coordinates and corresponds to the
- window geometry. See xdg_surface.set_window_geometry.
-
- If a zero or negative size is set the invalid_input error is raised.
- </description>
- <arg name="width" type="int" summary="width of positioned rectangle"/>
- <arg name="height" type="int" summary="height of positioned rectangle"/>
- </request>
-
- <request name="set_anchor_rect">
- <description summary="set the anchor rectangle within the parent surface">
- Specify the anchor rectangle within the parent surface that the child
- surface will be placed relative to. The rectangle is relative to the
- window geometry as defined by xdg_surface.set_window_geometry of the
- parent surface.
-
- When the xdg_positioner object is used to position a child surface, the
- anchor rectangle may not extend outside the window geometry of the
- positioned child's parent surface.
-
- If a negative size is set the invalid_input error is raised.
- </description>
- <arg name="x" type="int" summary="x position of anchor rectangle"/>
- <arg name="y" type="int" summary="y position of anchor rectangle"/>
- <arg name="width" type="int" summary="width of anchor rectangle"/>
- <arg name="height" type="int" summary="height of anchor rectangle"/>
- </request>
-
- <enum name="anchor">
- <entry name="none" value="0"/>
- <entry name="top" value="1"/>
- <entry name="bottom" value="2"/>
- <entry name="left" value="3"/>
- <entry name="right" value="4"/>
- <entry name="top_left" value="5"/>
- <entry name="bottom_left" value="6"/>
- <entry name="top_right" value="7"/>
- <entry name="bottom_right" value="8"/>
- </enum>
-
- <request name="set_anchor">
- <description summary="set anchor rectangle anchor">
- Defines the anchor point for the anchor rectangle. The specified anchor
- is used derive an anchor point that the child surface will be
- positioned relative to. If a corner anchor is set (e.g. 'top_left' or
- 'bottom_right'), the anchor point will be at the specified corner;
- otherwise, the derived anchor point will be centered on the specified
- edge, or in the center of the anchor rectangle if no edge is specified.
- </description>
- <arg name="anchor" type="uint" enum="anchor"
- summary="anchor"/>
- </request>
-
- <enum name="gravity">
- <entry name="none" value="0"/>
- <entry name="top" value="1"/>
- <entry name="bottom" value="2"/>
- <entry name="left" value="3"/>
- <entry name="right" value="4"/>
- <entry name="top_left" value="5"/>
- <entry name="bottom_left" value="6"/>
- <entry name="top_right" value="7"/>
- <entry name="bottom_right" value="8"/>
- </enum>
-
- <request name="set_gravity">
- <description summary="set child surface gravity">
- Defines in what direction a surface should be positioned, relative to
- the anchor point of the parent surface. If a corner gravity is
- specified (e.g. 'bottom_right' or 'top_left'), then the child surface
- will be placed towards the specified gravity; otherwise, the child
- surface will be centered over the anchor point on any axis that had no
- gravity specified. If the gravity is not in the ‘gravity’ enum, an
- invalid_input error is raised.
- </description>
- <arg name="gravity" type="uint" enum="gravity"
- summary="gravity direction"/>
- </request>
-
- <enum name="constraint_adjustment" bitfield="true">
- <description summary="constraint adjustments">
- The constraint adjustment value define ways the compositor will adjust
- the position of the surface, if the unadjusted position would result
- in the surface being partly constrained.
-
- Whether a surface is considered 'constrained' is left to the compositor
- to determine. For example, the surface may be partly outside the
- compositor's defined 'work area', thus necessitating the child surface's
- position be adjusted until it is entirely inside the work area.
-
- The adjustments can be combined, according to a defined precedence: 1)
- Flip, 2) Slide, 3) Resize.
- </description>
- <entry name="none" value="0">
- <description summary="don't move the child surface when constrained">
- Don't alter the surface position even if it is constrained on some
- axis, for example partially outside the edge of an output.
- </description>
- </entry>
- <entry name="slide_x" value="1">
- <description summary="move along the x axis until unconstrained">
- Slide the surface along the x axis until it is no longer constrained.
-
- First try to slide towards the direction of the gravity on the x axis
- until either the edge in the opposite direction of the gravity is
- unconstrained or the edge in the direction of the gravity is
- constrained.
-
- Then try to slide towards the opposite direction of the gravity on the
- x axis until either the edge in the direction of the gravity is
- unconstrained or the edge in the opposite direction of the gravity is
- constrained.
- </description>
- </entry>
- <entry name="slide_y" value="2">
- <description summary="move along the y axis until unconstrained">
- Slide the surface along the y axis until it is no longer constrained.
-
- First try to slide towards the direction of the gravity on the y axis
- until either the edge in the opposite direction of the gravity is
- unconstrained or the edge in the direction of the gravity is
- constrained.
-
- Then try to slide towards the opposite direction of the gravity on the
- y axis until either the edge in the direction of the gravity is
- unconstrained or the edge in the opposite direction of the gravity is
- constrained.
- </description>
- </entry>
- <entry name="flip_x" value="4">
- <description summary="invert the anchor and gravity on the x axis">
- Invert the anchor and gravity on the x axis if the surface is
- constrained on the x axis. For example, if the left edge of the
- surface is constrained, the gravity is 'left' and the anchor is
- 'left', change the gravity to 'right' and the anchor to 'right'.
-
- If the adjusted position also ends up being constrained, the resulting
- position of the flip_x adjustment will be the one before the
- adjustment.
- </description>
- </entry>
- <entry name="flip_y" value="8">
- <description summary="invert the anchor and gravity on the y axis">
- Invert the anchor and gravity on the y axis if the surface is
- constrained on the y axis. For example, if the bottom edge of the
- surface is constrained, the gravity is 'bottom' and the anchor is
- 'bottom', change the gravity to 'top' and the anchor to 'top'.
-
- The adjusted position is calculated given the original anchor
- rectangle and offset, but with the new flipped anchor and gravity
- values.
-
- If the adjusted position also ends up being constrained, the resulting
- position of the flip_y adjustment will be the one before the
- adjustment.
- </description>
- </entry>
- <entry name="resize_x" value="16">
- <description summary="horizontally resize the surface">
- Resize the surface horizontally so that it is completely
- unconstrained.
- </description>
- </entry>
- <entry name="resize_y" value="32">
- <description summary="vertically resize the surface">
- Resize the surface vertically so that it is completely unconstrained.
- </description>
- </entry>
- </enum>
-
- <request name="set_constraint_adjustment">
- <description summary="set the adjustment to be done when constrained">
- Specify how the window should be positioned if the originally intended
- position caused the surface to be constrained, meaning at least
- partially outside positioning boundaries set by the compositor. The
- adjustment is set by constructing a bitmask describing the adjustment to
- be made when the surface is constrained on that axis.
-
- If no bit for one axis is set, the compositor will assume that the child
- surface should not change its position on that axis when constrained.
-
- If more than one bit for one axis is set, the order of how adjustments
- are applied is specified in the corresponding adjustment descriptions.
-
- The default adjustment is none.
- </description>
- <arg name="constraint_adjustment" type="uint" enum="constraint_adjustment"
- summary="bit mask of constraint adjustments"/>
- </request>
-
- <request name="set_offset">
- <description summary="set surface position offset">
- Specify the surface position offset relative to the position of the
- anchor on the anchor rectangle and the anchor on the surface. For
- example if the anchor of the anchor rectangle is at (x, y), the surface
- has the gravity bottom|right, and the offset is (ox, oy), the calculated
- surface position will be (x + ox, y + oy). The offset position of the
- surface is the one used for constraint testing. See
- set_constraint_adjustment.
-
- An example use case is placing a popup menu on top of a user interface
- element, while aligning the user interface element of the parent surface
- with some user interface element placed somewhere in the popup surface.
- </description>
- <arg name="x" type="int" summary="surface position x offset"/>
- <arg name="y" type="int" summary="surface position y offset"/>
- </request>
-
- <!-- Version 3 additions -->
-
- <request name="set_reactive" since="3">
- <description summary="continuously reconstrain the surface">
- When set reactive, the surface is reconstrained if the conditions used
- for constraining changed, e.g. the parent window moved.
-
- If the conditions changed and the popup was reconstrained, an
- xdg_popup.configure event is sent with updated geometry, followed by an
- xdg_surface.configure event.
- </description>
- </request>
-
- <request name="set_parent_size" since="3">
- <description summary="">
- Set the parent window geometry the compositor should use when
- positioning the popup. The compositor may use this information to
- determine the future state the popup should be constrained using. If
- this doesn't match the dimension of the parent the popup is eventually
- positioned against, the behavior is undefined.
-
- The arguments are given in the surface-local coordinate space.
- </description>
- <arg name="parent_width" type="int"
- summary="future window geometry width of parent"/>
- <arg name="parent_height" type="int"
- summary="future window geometry height of parent"/>
- </request>
-
- <request name="set_parent_configure" since="3">
- <description summary="set parent configure this is a response to">
- Set the serial of an xdg_surface.configure event this positioner will be
- used in response to. The compositor may use this information together
- with set_parent_size to determine what future state the popup should be
- constrained using.
- </description>
- <arg name="serial" type="uint"
- summary="serial of parent configure event"/>
- </request>
- </interface>
-
- <interface name="xdg_surface" version="7">
- <description summary="desktop user interface surface base interface">
- An interface that may be implemented by a wl_surface, for
- implementations that provide a desktop-style user interface.
-
- It provides a base set of functionality required to construct user
- interface elements requiring management by the compositor, such as
- toplevel windows, menus, etc. The types of functionality are split into
- xdg_surface roles.
-
- Creating an xdg_surface does not set the role for a wl_surface. In order
- to map an xdg_surface, the client must create a role-specific object
- using, e.g., get_toplevel, get_popup. The wl_surface for any given
- xdg_surface can have at most one role, and may not be assigned any role
- not based on xdg_surface.
-
- A role must be assigned before any other requests are made to the
- xdg_surface object.
-
- The client must call wl_surface.commit on the corresponding wl_surface
- for the xdg_surface state to take effect.
-
- Creating an xdg_surface from a wl_surface which has a buffer attached or
- committed is a client error, and any attempts by a client to attach or
- manipulate a buffer prior to the first xdg_surface.configure call must
- also be treated as errors.
-
- After creating a role-specific object and setting it up (e.g. by sending
- the title, app ID, size constraints, parent, etc), the client must
- perform an initial commit without any buffer attached. The compositor
- will reply with initial wl_surface state such as
- wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
- event. The client must acknowledge it and is then allowed to attach a
- buffer to map the surface.
-
- Mapping an xdg_surface-based role surface is defined as making it
- possible for the surface to be shown by the compositor. Note that
- a mapped surface is not guaranteed to be visible once it is mapped.
-
- For an xdg_surface to be mapped by the compositor, the following
- conditions must be met:
- (1) the client has assigned an xdg_surface-based role to the surface
- (2) the client has set and committed the xdg_surface state and the
- role-dependent state to the surface
- (3) the client has committed a buffer to the surface
-
- A newly-unmapped surface is considered to have met condition (1) out
- of the 3 required conditions for mapping a surface if its role surface
- has not been destroyed, i.e. the client must perform the initial commit
- again before attaching a buffer.
- </description>
-
- <enum name="error">
- <entry name="not_constructed" value="1"
- summary="Surface was not fully constructed"/>
- <entry name="already_constructed" value="2"
- summary="Surface was already constructed"/>
- <entry name="unconfigured_buffer" value="3"
- summary="Attaching a buffer to an unconfigured surface"/>
- <entry name="invalid_serial" value="4"
- summary="Invalid serial number when acking a configure event"/>
- <entry name="invalid_size" value="5"
- summary="Width or height was zero or negative"/>
- <entry name="defunct_role_object" value="6"
- summary="Surface was destroyed before its role object"/>
- </enum>
-
- <request name="destroy" type="destructor">
- <description summary="destroy the xdg_surface">
- Destroy the xdg_surface object. An xdg_surface must only be destroyed
- after its role object has been destroyed, otherwise
- a defunct_role_object error is raised.
- </description>
- </request>
-
- <request name="get_toplevel">
- <description summary="assign the xdg_toplevel surface role">
- This creates an xdg_toplevel object for the given xdg_surface and gives
- the associated wl_surface the xdg_toplevel role.
-
- See the documentation of xdg_toplevel for more details about what an
- xdg_toplevel is and how it is used.
- </description>
- <arg name="id" type="new_id" interface="xdg_toplevel"/>
- </request>
-
- <request name="get_popup">
- <description summary="assign the xdg_popup surface role">
- This creates an xdg_popup object for the given xdg_surface and gives
- the associated wl_surface the xdg_popup role.
-
- If null is passed as a parent, a parent surface must be specified using
- some other protocol, before committing the initial state.
-
- See the documentation of xdg_popup for more details about what an
- xdg_popup is and how it is used.
- </description>
- <arg name="id" type="new_id" interface="xdg_popup"/>
- <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
- <arg name="positioner" type="object" interface="xdg_positioner"/>
- </request>
-
- <request name="set_window_geometry">
- <description summary="set the new window geometry">
- The window geometry of a surface is its "visible bounds" from the
- user's perspective. Client-side decorations often have invisible
- portions like drop-shadows which should be ignored for the
- purposes of aligning, placing and constraining windows.
-
- The window geometry is double-buffered state, see wl_surface.commit.
-
- When maintaining a position, the compositor should treat the (x, y)
- coordinate of the window geometry as the top left corner of the window.
- A client changing the (x, y) window geometry coordinate should in
- general not alter the position of the window.
-
- Once the window geometry of the surface is set, it is not possible to
- unset it, and it will remain the same until set_window_geometry is
- called again, even if a new subsurface or buffer is attached.
-
- If never set, the value is the full bounds of the surface,
- including any subsurfaces. This updates dynamically on every
- commit. This unset is meant for extremely simple clients.
-
- The arguments are given in the surface-local coordinate space of
- the wl_surface associated with this xdg_surface, and may extend outside
- of the wl_surface itself to mark parts of the subsurface tree as part of
- the window geometry.
-
- When applied, the effective window geometry will be the set window
- geometry clamped to the bounding rectangle of the combined
- geometry of the surface of the xdg_surface and the associated
- subsurfaces.
-
- The effective geometry will not be recalculated unless a new call to
- set_window_geometry is done and the new pending surface state is
- subsequently applied.
-
- The width and height of the effective window geometry must be
- greater than zero. Setting an invalid size will raise an
- invalid_size error.
- </description>
- <arg name="x" type="int"/>
- <arg name="y" type="int"/>
- <arg name="width" type="int"/>
- <arg name="height" type="int"/>
- </request>
-
- <request name="ack_configure">
- <description summary="ack a configure event">
- When a configure event is received, if a client commits the
- surface in response to the configure event, then the client
- must make an ack_configure request sometime before the commit
- request, passing along the serial of the configure event.
-
- For instance, for toplevel surfaces the compositor might use this
- information to move a surface to the top left only when the client has
- drawn itself for the maximized or fullscreen state.
-
- If the client receives multiple configure events before it
- can respond to one, it only has to ack the last configure event.
- Acking a configure event that was never sent raises an invalid_serial
- error.
-
- A client is not required to commit immediately after sending
- an ack_configure request - it may even ack_configure several times
- before its next surface commit.
-
- A client may send multiple ack_configure requests before committing, but
- only the last request sent before a commit indicates which configure
- event the client really is responding to.
-
- Sending an ack_configure request consumes the serial number sent with
- the request, as well as serial numbers sent by all configure events
- sent on this xdg_surface prior to the configure event referenced by
- the committed serial.
-
- It is an error to issue multiple ack_configure requests referencing a
- serial from the same configure event, or to issue an ack_configure
- request referencing a serial from a configure event issued before the
- event identified by the last ack_configure request for the same
- xdg_surface. Doing so will raise an invalid_serial error.
- </description>
- <arg name="serial" type="uint" summary="the serial from the configure event"/>
- </request>
-
- <event name="configure">
- <description summary="suggest a surface change">
- The configure event marks the end of a configure sequence. A configure
- sequence is a set of one or more events configuring the state of the
- xdg_surface, including the final xdg_surface.configure event.
-
- Where applicable, xdg_surface surface roles will during a configure
- sequence extend this event as a latched state sent as events before the
- xdg_surface.configure event. Such events should be considered to make up
- a set of atomically applied configuration states, where the
- xdg_surface.configure commits the accumulated state.
-
- Clients should arrange their surface for the new states, and then send
- an ack_configure request with the serial sent in this configure event at
- some point before committing the new surface.
-
- If the client receives multiple configure events before it can respond
- to one, it is free to discard all but the last event it received.
- </description>
- <arg name="serial" type="uint" summary="serial of the configure event"/>
- </event>
-
- </interface>
-
- <interface name="xdg_toplevel" version="7">
- <description summary="toplevel surface">
- This interface defines an xdg_surface role which allows a surface to,
- among other things, set window-like properties such as maximize,
- fullscreen, and minimize, set application-specific metadata like title and
- id, and well as trigger user interactive operations such as interactive
- resize and move.
-
- A xdg_toplevel by default is responsible for providing the full intended
- visual representation of the toplevel, which depending on the window
- state, may mean things like a title bar, window controls and drop shadow.
-
- Unmapping an xdg_toplevel means that the surface cannot be shown
- by the compositor until it is explicitly mapped again.
- All active operations (e.g., move, resize) are canceled and all
- attributes (e.g. title, state, stacking, ...) are discarded for
- an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
- the state it had right after xdg_surface.get_toplevel. The client
- can re-map the toplevel by performing a commit without any buffer
- attached, waiting for a configure event and handling it as usual (see
- xdg_surface description).
-
- Attaching a null buffer to a toplevel unmaps the surface.
- </description>
-
- <request name="destroy" type="destructor">
- <description summary="destroy the xdg_toplevel">
- This request destroys the role surface and unmaps the surface;
- see "Unmapping" behavior in interface section for details.
- </description>
- </request>
-
- <enum name="error">
- <entry name="invalid_resize_edge" value="0" summary="provided value is
- not a valid variant of the resize_edge enum"/>
- <entry name="invalid_parent" value="1"
- summary="invalid parent toplevel"/>
- <entry name="invalid_size" value="2"
- summary="client provided an invalid min or max size"/>
- </enum>
-
- <request name="set_parent">
- <description summary="set the parent of this surface">
- Set the "parent" of this surface. This surface should be stacked
- above the parent surface and all other ancestor surfaces.
-
- Parent surfaces should be set on dialogs, toolboxes, or other
- "auxiliary" surfaces, so that the parent is raised when the dialog
- is raised.
-
- Setting a null parent for a child surface unsets its parent. Setting
- a null parent for a surface which currently has no parent is a no-op.
-
- Only mapped surfaces can have child surfaces. Setting a parent which
- is not mapped is equivalent to setting a null parent. If a surface
- becomes unmapped, its children's parent is set to the parent of
- the now-unmapped surface. If the now-unmapped surface has no parent,
- its children's parent is unset. If the now-unmapped surface becomes
- mapped again, its parent-child relationship is not restored.
-
- The parent toplevel must not be one of the child toplevel's
- descendants, and the parent must be different from the child toplevel,
- otherwise the invalid_parent protocol error is raised.
- </description>
- <arg name="parent" type="object" interface="xdg_toplevel" allow-null="true"/>
- </request>
-
- <request name="set_title">
- <description summary="set surface title">
- Set a short title for the surface.
-
- This string may be used to identify the surface in a task bar,
- window list, or other user interface elements provided by the
- compositor.
-
- The string must be encoded in UTF-8.
- </description>
- <arg name="title" type="string"/>
- </request>
-
- <request name="set_app_id">
- <description summary="set application ID">
- Set an application identifier for the surface.
-
- The app ID identifies the general class of applications to which
- the surface belongs. The compositor can use this to group multiple
- surfaces together, or to determine how to launch a new application.
-
- For D-Bus activatable applications, the app ID is used as the D-Bus
- service name.
-
- The compositor shell will try to group application surfaces together
- by their app ID. As a best practice, it is suggested to select app
- ID's that match the basename of the application's .desktop file.
- For example, "org.freedesktop.FooViewer" where the .desktop file is
- "org.freedesktop.FooViewer.desktop".
-
- Like other properties, a set_app_id request can be sent after the
- xdg_toplevel has been mapped to update the property.
-
- See the desktop-entry specification [0] for more details on
- application identifiers and how they relate to well-known D-Bus
- names and .desktop files.
-
- [0] https://standards.freedesktop.org/desktop-entry-spec/
- </description>
- <arg name="app_id" type="string"/>
- </request>
-
- <request name="show_window_menu">
- <description summary="show the window menu">
- Clients implementing client-side decorations might want to show
- a context menu when right-clicking on the decorations, giving the
- user a menu that they can use to maximize or minimize the window.
-
- This request asks the compositor to pop up such a window menu at
- the given position, relative to the local surface coordinates of
- the parent surface. There are no guarantees as to what menu items
- the window menu contains, or even if a window menu will be drawn
- at all.
-
- This request must be used in response to some sort of user action
- like a button press, key press, or touch down event.
- </description>
- <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
- <arg name="serial" type="uint" summary="the serial of the user event"/>
- <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
- <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
- </request>
-
- <request name="move">
- <description summary="start an interactive move">
- Start an interactive, user-driven move of the surface.
-
- This request must be used in response to some sort of user action
- like a button press, key press, or touch down event. The passed
- serial is used to determine the type of interactive move (touch,
- pointer, etc).
-
- The server may ignore move requests depending on the state of
- the surface (e.g. fullscreen or maximized), or if the passed serial
- is no longer valid.
-
- If triggered, the surface will lose the focus of the device
- (wl_pointer, wl_touch, etc) used for the move. It is up to the
- compositor to visually indicate that the move is taking place, such as
- updating a pointer cursor, during the move. There is no guarantee
- that the device focus will return when the move is completed.
- </description>
- <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
- <arg name="serial" type="uint" summary="the serial of the user event"/>
- </request>
-
- <enum name="resize_edge">
- <description summary="edge values for resizing">
- These values are used to indicate which edge of a surface
- is being dragged in a resize operation.
- </description>
- <entry name="none" value="0"/>
- <entry name="top" value="1"/>
- <entry name="bottom" value="2"/>
- <entry name="left" value="4"/>
- <entry name="top_left" value="5"/>
- <entry name="bottom_left" value="6"/>
- <entry name="right" value="8"/>
- <entry name="top_right" value="9"/>
- <entry name="bottom_right" value="10"/>
- </enum>
-
- <request name="resize">
- <description summary="start an interactive resize">
- Start a user-driven, interactive resize of the surface.
-
- This request must be used in response to some sort of user action
- like a button press, key press, or touch down event. The passed
- serial is used to determine the type of interactive resize (touch,
- pointer, etc).
-
- The server may ignore resize requests depending on the state of
- the surface (e.g. fullscreen or maximized).
-
- If triggered, the client will receive configure events with the
- "resize" state enum value and the expected sizes. See the "resize"
- enum value for more details about what is required. The client
- must also acknowledge configure events using "ack_configure". After
- the resize is completed, the client will receive another "configure"
- event without the resize state.
-
- If triggered, the surface also will lose the focus of the device
- (wl_pointer, wl_touch, etc) used for the resize. It is up to the
- compositor to visually indicate that the resize is taking place,
- such as updating a pointer cursor, during the resize. There is no
- guarantee that the device focus will return when the resize is
- completed.
-
- The edges parameter specifies how the surface should be resized, and
- is one of the values of the resize_edge enum. Values not matching
- a variant of the enum will cause the invalid_resize_edge protocol error.
- The compositor may use this information to update the surface position
- for example when dragging the top left corner. The compositor may also
- use this information to adapt its behavior, e.g. choose an appropriate
- cursor image.
- </description>
- <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
- <arg name="serial" type="uint" summary="the serial of the user event"/>
- <arg name="edges" type="uint" enum="resize_edge" summary="which edge or corner is being dragged"/>
- </request>
-
- <enum name="state">
- <description summary="types of state on the surface">
- The different state values used on the surface. This is designed for
- state values like maximized, fullscreen. It is paired with the
- configure event to ensure that both the client and the compositor
- setting the state can be synchronized.
-
- States set in this way are double-buffered, see wl_surface.commit.
- </description>
- <entry name="maximized" value="1" summary="the surface is maximized">
- <description summary="the surface is maximized">
- The surface is maximized. The window geometry specified in the configure
- event must be obeyed by the client, or the xdg_wm_base.invalid_surface_state
- error is raised.
-
- The client should draw without shadow or other
- decoration outside of the window geometry.
- </description>
- </entry>
- <entry name="fullscreen" value="2" summary="the surface is fullscreen">
- <description summary="the surface is fullscreen">
- The surface is fullscreen. The window geometry specified in the
- configure event is a maximum; the client cannot resize beyond it. For
- a surface to cover the whole fullscreened area, the geometry
- dimensions must be obeyed by the client. For more details, see
- xdg_toplevel.set_fullscreen.
- </description>
- </entry>
- <entry name="resizing" value="3" summary="the surface is being resized">
- <description summary="the surface is being resized">
- The surface is being resized. The window geometry specified in the
- configure event is a maximum; the client cannot resize beyond it.
- Clients that have aspect ratio or cell sizing configuration can use
- a smaller size, however.
- </description>
- </entry>
- <entry name="activated" value="4" summary="the surface is now activated">
- <description summary="the surface is now activated">
- Client window decorations should be painted as if the window is
- active. Do not assume this means that the window actually has
- keyboard or pointer focus.
- </description>
- </entry>
- <entry name="tiled_left" value="5" since="2">
- <description summary="the surface’s left edge is tiled">
- The window is currently in a tiled layout and the left edge is
- considered to be adjacent to another part of the tiling grid.
-
- The client should draw without shadow or other decoration outside of
- the window geometry on the left edge.
- </description>
- </entry>
- <entry name="tiled_right" value="6" since="2">
- <description summary="the surface’s right edge is tiled">
- The window is currently in a tiled layout and the right edge is
- considered to be adjacent to another part of the tiling grid.
-
- The client should draw without shadow or other decoration outside of
- the window geometry on the right edge.
- </description>
- </entry>
- <entry name="tiled_top" value="7" since="2">
- <description summary="the surface’s top edge is tiled">
- The window is currently in a tiled layout and the top edge is
- considered to be adjacent to another part of the tiling grid.
-
- The client should draw without shadow or other decoration outside of
- the window geometry on the top edge.
- </description>
- </entry>
- <entry name="tiled_bottom" value="8" since="2">
- <description summary="the surface’s bottom edge is tiled">
- The window is currently in a tiled layout and the bottom edge is
- considered to be adjacent to another part of the tiling grid.
-
- The client should draw without shadow or other decoration outside of
- the window geometry on the bottom edge.
- </description>
- </entry>
- <entry name="suspended" value="9" since="6">
- <description summary="surface repaint is suspended">
- The surface is currently not ordinarily being repainted; for
- example because its content is occluded by another window, or its
- outputs are switched off due to screen locking.
- </description>
- </entry>
- <entry name="constrained_left" value="10" since="7">
- <description summary="the surface’s left edge is constrained">
- The left edge of the window is currently constrained, meaning it
- shouldn't attempt to resize from that edge. It can for example mean
- it's tiled next to a monitor edge on the constrained side of the
- window.
- </description>
- </entry>
- <entry name="constrained_right" value="11" since="7">
- <description summary="the surface’s right edge is constrained">
- The right edge of the window is currently constrained, meaning it
- shouldn't attempt to resize from that edge. It can for example mean
- it's tiled next to a monitor edge on the constrained side of the
- window.
- </description>
- </entry>
- <entry name="constrained_top" value="12" since="7">
- <description summary="the surface’s top edge is constrained">
- The top edge of the window is currently constrained, meaning it
- shouldn't attempt to resize from that edge. It can for example mean
- it's tiled next to a monitor edge on the constrained side of the
- window.
- </description>
- </entry>
- <entry name="constrained_bottom" value="13" since="7">
- <description summary="the surface’s bottom edge is tiled">
- The bottom edge of the window is currently constrained, meaning it
- shouldn't attempt to resize from that edge. It can for example mean
- it's tiled next to a monitor edge on the constrained side of the
- window.
- </description>
- </entry>
- </enum>
-
- <request name="set_max_size">
- <description summary="set the maximum size">
- Set a maximum size for the window.
-
- The client can specify a maximum size so that the compositor does
- not try to configure the window beyond this size.
-
- The width and height arguments are in window geometry coordinates.
- See xdg_surface.set_window_geometry.
-
- Values set in this way are double-buffered, see wl_surface.commit.
-
- The compositor can use this information to allow or disallow
- different states like maximize or fullscreen and draw accurate
- animations.
-
- Similarly, a tiling window manager may use this information to
- place and resize client windows in a more effective way.
-
- The client should not rely on the compositor to obey the maximum
- size. The compositor may decide to ignore the values set by the
- client and request a larger size.
-
- If never set, or a value of zero in the request, means that the
- client has no expected maximum size in the given dimension.
- As a result, a client wishing to reset the maximum size
- to an unspecified state can use zero for width and height in the
- request.
-
- Requesting a maximum size to be smaller than the minimum size of
- a surface is illegal and will result in an invalid_size error.
-
- The width and height must be greater than or equal to zero. Using
- strictly negative values for width or height will result in a
- invalid_size error.
- </description>
- <arg name="width" type="int"/>
- <arg name="height" type="int"/>
- </request>
-
- <request name="set_min_size">
- <description summary="set the minimum size">
- Set a minimum size for the window.
-
- The client can specify a minimum size so that the compositor does
- not try to configure the window below this size.
-
- The width and height arguments are in window geometry coordinates.
- See xdg_surface.set_window_geometry.
-
- Values set in this way are double-buffered, see wl_surface.commit.
-
- The compositor can use this information to allow or disallow
- different states like maximize or fullscreen and draw accurate
- animations.
-
- Similarly, a tiling window manager may use this information to
- place and resize client windows in a more effective way.
-
- The client should not rely on the compositor to obey the minimum
- size. The compositor may decide to ignore the values set by the
- client and request a smaller size.
-
- If never set, or a value of zero in the request, means that the
- client has no expected minimum size in the given dimension.
- As a result, a client wishing to reset the minimum size
- to an unspecified state can use zero for width and height in the
- request.
-
- Requesting a minimum size to be larger than the maximum size of
- a surface is illegal and will result in an invalid_size error.
-
- The width and height must be greater than or equal to zero. Using
- strictly negative values for width and height will result in a
- invalid_size error.
- </description>
- <arg name="width" type="int"/>
- <arg name="height" type="int"/>
- </request>
-
- <request name="set_maximized">
- <description summary="maximize the window">
- Maximize the surface.
-
- After requesting that the surface should be maximized, the compositor
- will respond by emitting a configure event. Whether this configure
- actually sets the window maximized is subject to compositor policies.
- The client must then update its content, drawing in the configured
- state. The client must also acknowledge the configure when committing
- the new content (see ack_configure).
-
- It is up to the compositor to decide how and where to maximize the
- surface, for example which output and what region of the screen should
- be used.
-
- If the surface was already maximized, the compositor will still emit
- a configure event with the "maximized" state.
-
- If the surface is in a fullscreen state, this request has no direct
- effect. It may alter the state the surface is returned to when
- unmaximized unless overridden by the compositor.
- </description>
- </request>
-
- <request name="unset_maximized">
- <description summary="unmaximize the window">
- Unmaximize the surface.
-
- After requesting that the surface should be unmaximized, the compositor
- will respond by emitting a configure event. Whether this actually
- un-maximizes the window is subject to compositor policies.
- If available and applicable, the compositor will include the window
- geometry dimensions the window had prior to being maximized in the
- configure event. The client must then update its content, drawing it in
- the configured state. The client must also acknowledge the configure
- when committing the new content (see ack_configure).
-
- It is up to the compositor to position the surface after it was
- unmaximized; usually the position the surface had before maximizing, if
- applicable.
-
- If the surface was already not maximized, the compositor will still
- emit a configure event without the "maximized" state.
-
- If the surface is in a fullscreen state, this request has no direct
- effect. It may alter the state the surface is returned to when
- unmaximized unless overridden by the compositor.
- </description>
- </request>
-
- <request name="set_fullscreen">
- <description summary="set the window as fullscreen on an output">
- Make the surface fullscreen.
-
- After requesting that the surface should be fullscreened, the
- compositor will respond by emitting a configure event. Whether the
- client is actually put into a fullscreen state is subject to compositor
- policies. The client must also acknowledge the configure when
- committing the new content (see ack_configure).
-
- The output passed by the request indicates the client's preference as
- to which display it should be set fullscreen on. If this value is NULL,
- it's up to the compositor to choose which display will be used to map
- this surface.
-
- If the surface doesn't cover the whole output, the compositor will
- position the surface in the center of the output and compensate with
- with border fill covering the rest of the output. The content of the
- border fill is undefined, but should be assumed to be in some way that
- attempts to blend into the surrounding area (e.g. solid black).
-
- If the fullscreened surface is not opaque, the compositor must make
- sure that other screen content not part of the same surface tree (made
- up of subsurfaces, popups or similarly coupled surfaces) are not
- visible below the fullscreened surface.
- </description>
- <arg name="output" type="object" interface="wl_output" allow-null="true"/>
- </request>
-
- <request name="unset_fullscreen">
- <description summary="unset the window as fullscreen">
- Make the surface no longer fullscreen.
-
- After requesting that the surface should be unfullscreened, the
- compositor will respond by emitting a configure event.
- Whether this actually removes the fullscreen state of the client is
- subject to compositor policies.
-
- Making a surface unfullscreen sets states for the surface based on the following:
- * the state(s) it may have had before becoming fullscreen
- * any state(s) decided by the compositor
- * any state(s) requested by the client while the surface was fullscreen
-
- The compositor may include the previous window geometry dimensions in
- the configure event, if applicable.
-
- The client must also acknowledge the configure when committing the new
- content (see ack_configure).
- </description>
- </request>
-
- <request name="set_minimized">
- <description summary="set the window as minimized">
- Request that the compositor minimize your surface. There is no
- way to know if the surface is currently minimized, nor is there
- any way to unset minimization on this surface.
-
- If you are looking to throttle redrawing when minimized, please
- instead use the wl_surface.frame event for this, as this will
- also work with live previews on windows in Alt-Tab, Expose or
- similar compositor features.
- </description>
- </request>
-
- <event name="configure">
- <description summary="suggest a surface change">
- This configure event asks the client to resize its toplevel surface or
- to change its state. The configured state should not be applied
- immediately. See xdg_surface.configure for details.
-
- The width and height arguments specify a hint to the window
- about how its surface should be resized in window geometry
- coordinates. See set_window_geometry.
-
- If the width or height arguments are zero, it means the client
- should decide its own window dimension. This may happen when the
- compositor needs to configure the state of the surface but doesn't
- have any information about any previous or expected dimension.
-
- The states listed in the event specify how the width/height
- arguments should be interpreted, and possibly how it should be
- drawn.
-
- Clients must send an ack_configure in response to this event. See
- xdg_surface.configure and xdg_surface.ack_configure for details.
- </description>
- <arg name="width" type="int"/>
- <arg name="height" type="int"/>
- <arg name="states" type="array"/>
- </event>
-
- <event name="close">
- <description summary="surface wants to be closed">
- The close event is sent by the compositor when the user
- wants the surface to be closed. This should be equivalent to
- the user clicking the close button in client-side decorations,
- if your application has any.
-
- This is only a request that the user intends to close the
- window. The client may choose to ignore this request, or show
- a dialog to ask the user to save their data, etc.
- </description>
- </event>
-
- <!-- Version 4 additions -->
-
- <event name="configure_bounds" since="4">
- <description summary="recommended window geometry bounds">
- The configure_bounds event may be sent prior to a xdg_toplevel.configure
- event to communicate the bounds a window geometry size is recommended
- to constrain to.
-
- The passed width and height are in surface coordinate space. If width
- and height are 0, it means bounds is unknown and equivalent to as if no
- configure_bounds event was ever sent for this surface.
-
- The bounds can for example correspond to the size of a monitor excluding
- any panels or other shell components, so that a surface isn't created in
- a way that it cannot fit.
-
- The bounds may change at any point, and in such a case, a new
- xdg_toplevel.configure_bounds will be sent, followed by
- xdg_toplevel.configure and xdg_surface.configure.
- </description>
- <arg name="width" type="int"/>
- <arg name="height" type="int"/>
- </event>
-
- <!-- Version 5 additions -->
-
- <enum name="wm_capabilities" since="5">
- <entry name="window_menu" value="1" summary="show_window_menu is available"/>
- <entry name="maximize" value="2" summary="set_maximized and unset_maximized are available"/>
- <entry name="fullscreen" value="3" summary="set_fullscreen and unset_fullscreen are available"/>
- <entry name="minimize" value="4" summary="set_minimized is available"/>
- </enum>
-
- <event name="wm_capabilities" since="5">
- <description summary="compositor capabilities">
- This event advertises the capabilities supported by the compositor. If
- a capability isn't supported, clients should hide or disable the UI
- elements that expose this functionality. For instance, if the
- compositor doesn't advertise support for minimized toplevels, a button
- triggering the set_minimized request should not be displayed.
-
- The compositor will ignore requests it doesn't support. For instance,
- a compositor which doesn't advertise support for minimized will ignore
- set_minimized requests.
-
- Compositors must send this event once before the first
- xdg_surface.configure event. When the capabilities change, compositors
- must send this event again and then send an xdg_surface.configure
- event.
-
- The configured state should not be applied immediately. See
- xdg_surface.configure for details.
-
- The capabilities are sent as an array of 32-bit unsigned integers in
- native endianness.
- </description>
- <arg name="capabilities" type="array" summary="array of 32-bit capabilities"/>
- </event>
- </interface>
-
- <interface name="xdg_popup" version="7">
- <description summary="short-lived, popup surfaces for menus">
- A popup surface is a short-lived, temporary surface. It can be used to
- implement for example menus, popovers, tooltips and other similar user
- interface concepts.
-
- A popup can be made to take an explicit grab. See xdg_popup.grab for
- details.
-
- When the popup is dismissed, a popup_done event will be sent out, and at
- the same time the surface will be unmapped. See the xdg_popup.popup_done
- event for details.
-
- Explicitly destroying the xdg_popup object will also dismiss the popup and
- unmap the surface. Clients that want to dismiss the popup when another
- surface of their own is clicked should dismiss the popup using the destroy
- request.
-
- A newly created xdg_popup will be stacked on top of all previously created
- xdg_popup surfaces associated with the same xdg_toplevel.
-
- The parent of an xdg_popup must be mapped (see the xdg_surface
- description) before the xdg_popup itself.
-
- The client must call wl_surface.commit on the corresponding wl_surface
- for the xdg_popup state to take effect.
- </description>
-
- <enum name="error">
- <entry name="invalid_grab" value="0"
- summary="tried to grab after being mapped"/>
- </enum>
-
- <request name="destroy" type="destructor">
- <description summary="remove xdg_popup interface">
- This destroys the popup. Explicitly destroying the xdg_popup
- object will also dismiss the popup, and unmap the surface.
-
- If this xdg_popup is not the "topmost" popup, the
- xdg_wm_base.not_the_topmost_popup protocol error will be sent.
- </description>
- </request>
-
- <request name="grab">
- <description summary="make the popup take an explicit grab">
- This request makes the created popup take an explicit grab. An explicit
- grab will be dismissed when the user dismisses the popup, or when the
- client destroys the xdg_popup. This can be done by the user clicking
- outside the surface, using the keyboard, or even locking the screen
- through closing the lid or a timeout.
-
- If the compositor denies the grab, the popup will be immediately
- dismissed.
-
- This request must be used in response to some sort of user action like a
- button press, key press, or touch down event. The serial number of the
- event should be passed as 'serial'.
-
- The parent of a grabbing popup must either be an xdg_toplevel surface or
- another xdg_popup with an explicit grab. If the parent is another
- xdg_popup it means that the popups are nested, with this popup now being
- the topmost popup.
-
- Nested popups must be destroyed in the reverse order they were created
- in, e.g. the only popup you are allowed to destroy at all times is the
- topmost one.
-
- When compositors choose to dismiss a popup, they may dismiss every
- nested grabbing popup as well. When a compositor dismisses popups, it
- will follow the same dismissing order as required from the client.
-
- If the topmost grabbing popup is destroyed, the grab will be returned to
- the parent of the popup, if that parent previously had an explicit grab.
-
- If the parent is a grabbing popup which has already been dismissed, this
- popup will be immediately dismissed. If the parent is a popup that did
- not take an explicit grab, an error will be raised.
-
- During a popup grab, the client owning the grab will receive pointer
- and touch events for all their surfaces as normal (similar to an
- "owner-events" grab in X11 parlance), while the top most grabbing popup
- will always have keyboard focus.
- </description>
- <arg name="seat" type="object" interface="wl_seat"
- summary="the wl_seat of the user event"/>
- <arg name="serial" type="uint" summary="the serial of the user event"/>
- </request>
-
- <event name="configure">
- <description summary="configure the popup surface">
- This event asks the popup surface to configure itself given the
- configuration. The configured state should not be applied immediately.
- See xdg_surface.configure for details.
-
- The x and y arguments represent the position the popup was placed at
- given the xdg_positioner rule, relative to the upper left corner of the
- window geometry of the parent surface.
-
- For version 2 or older, the configure event for an xdg_popup is only
- ever sent once for the initial configuration. Starting with version 3,
- it may be sent again if the popup is setup with an xdg_positioner with
- set_reactive requested, or in response to xdg_popup.reposition requests.
- </description>
- <arg name="x" type="int"
- summary="x position relative to parent surface window geometry"/>
- <arg name="y" type="int"
- summary="y position relative to parent surface window geometry"/>
- <arg name="width" type="int" summary="window geometry width"/>
- <arg name="height" type="int" summary="window geometry height"/>
- </event>
-
- <event name="popup_done">
- <description summary="popup interaction is done">
- The popup_done event is sent out when a popup is dismissed by the
- compositor. The client should destroy the xdg_popup object at this
- point.
- </description>
- </event>
-
- <!-- Version 3 additions -->
-
- <request name="reposition" since="3">
- <description summary="recalculate the popup's location">
- Reposition an already-mapped popup. The popup will be placed given the
- details in the passed xdg_positioner object, and a
- xdg_popup.repositioned followed by xdg_popup.configure and
- xdg_surface.configure will be emitted in response. Any parameters set
- by the previous positioner will be discarded.
-
- The passed token will be sent in the corresponding
- xdg_popup.repositioned event. The new popup position will not take
- effect until the corresponding configure event is acknowledged by the
- client. See xdg_popup.repositioned for details. The token itself is
- opaque, and has no other special meaning.
-
- If multiple reposition requests are sent, the compositor may skip all
- but the last one.
-
- If the popup is repositioned in response to a configure event for its
- parent, the client should send an xdg_positioner.set_parent_configure
- and possibly an xdg_positioner.set_parent_size request to allow the
- compositor to properly constrain the popup.
-
- If the popup is repositioned together with a parent that is being
- resized, but not in response to a configure event, the client should
- send an xdg_positioner.set_parent_size request.
- </description>
- <arg name="positioner" type="object" interface="xdg_positioner"/>
- <arg name="token" type="uint" summary="reposition request token"/>
- </request>
-
- <event name="repositioned" since="3">
- <description summary="signal the completion of a repositioned request">
- The repositioned event is sent as part of a popup configuration
- sequence, together with xdg_popup.configure and lastly
- xdg_surface.configure to notify the completion of a reposition request.
-
- The repositioned event is to notify about the completion of a
- xdg_popup.reposition request. The token argument is the token passed
- in the xdg_popup.reposition request.
-
- Immediately after this event is emitted, xdg_popup.configure and
- xdg_surface.configure will be sent with the updated size and position,
- as well as a new configure serial.
-
- The client should optionally update the content of the popup, but must
- acknowledge the new popup configuration for the new position to take
- effect. See xdg_surface.ack_configure for details.
- </description>
- <arg name="token" type="uint" summary="reposition request token"/>
- </event>
-
- </interface>
-</protocol>
# include <libintl.h>
#endif
+#ifdef HAVE_WAYLAND
+# include "wayland-dpy.h"
+# include "wayland-dpms.h"
+#endif
+
#include "xscreensaver.h"
#include "version.h"
#include "atoms.h"
/* If the DPMS settings in the init file have changed, change the
settings on the server to match. This also would have happened at
the watchdog timer. */
- sync_server_dpms_settings (si->dpy, p);
+ sync_server_dpms_settings (si);
}
}
}
else
{
- if (p->verbose_p ||
- !(getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET")))
+ if (p->verbose_p)
fprintf (stderr, "%s: xscreensaver does not seem to be running!\n",
blurb());
- /* Under normal circumstances, that window should have been created
- by the "xscreensaver" process. But if for some reason someone
- has run "xscreensaver-gfx" directly (Wayland?) we need this window
+ /* Under normal circumstances, that window should have been created by
+ the "xscreensaver" process. But if for some reason someone has run
+ "xscreensaver-gfx" directly (Wayland swayidle?) we need this window
to exist for ClientMessages to be receivable. So let's make one.
*/
XClassHint class_hints;
daemon_window = XCreateWindow (si->dpy, RootWindow (si->dpy, 0),
0, 0, 1, 1, 0,
DefaultDepth (si->dpy, 0), InputOutput,
- DefaultVisual (si->dpy, 0), attrmask, &attrs);
+ DefaultVisual (si->dpy, 0),
+ attrmask, &attrs);
XStoreName (si->dpy, daemon_window, "XScreenSaver GFX");
XSetClassHint (si->dpy, daemon_window, &class_hints);
XChangeProperty (si->dpy, daemon_window, XA_WM_COMMAND, XA_STRING,
8, PropModeReplace, (unsigned char *) progname,
strlen (progname));
- XChangeProperty (si->dpy, daemon_window, XA_SCREENSAVER_VERSION, XA_STRING,
- 8, PropModeReplace, (unsigned char *) version_number,
+ XChangeProperty (si->dpy, daemon_window, XA_SCREENSAVER_VERSION,
+ XA_STRING, 8, PropModeReplace,
+ (unsigned char *) version_number,
strlen (version_number));
XChangeProperty (si->dpy, daemon_window, XA_SCREENSAVER_ID, XA_STRING,
8, PropModeReplace, (unsigned char *) id, strlen (id));
#endif /* DEBUG_MULTISCREEN */
+#ifdef HAVE_WAYLAND
+static void
+wayland_dpy_cb (XtPointer closure, int *source, XtInputId *id)
+{
+ saver_info *si = (saver_info *) closure;
+ wayland_dpy_process_events (si->wayland_dpy, False);
+}
+#endif /* HAVE_WAYLAND */
+
+
static void
main_loop (saver_info *si, Bool init_p)
{
if (init_p && p->verbose_p)
print_available_extensions (si);
+# ifdef HAVE_WAYLAND
+ si->wayland_dpy = wayland_dpy_connect();
+ if (si->wayland_dpy)
+ {
+ /* Process input on the Wayland socket. */
+ int fd = wayland_dpy_get_fd (si->wayland_dpy);
+ XtAppAddInput (si->app, fd,
+ (XtPointer) (XtInputReadMask | XtInputExceptMask),
+ wayland_dpy_cb, (XtPointer) si);
+ si->wayland_dpms = wayland_dpms_init (si->wayland_dpy);
+ }
+# endif /* HAVE_WAYLAND */
+
initialize_randr (si);
update_screen_layout (si);
#include <X11/extensions/XInput2.h>
#ifdef HAVE_WAYLAND
+# include "wayland-dpy.h"
# include "wayland-idle.h"
#endif
}
+#ifdef HAVE_WAYLAND
+static void
+saver_wayland_exit (void *closure)
+{
+ saver_exit (1);
+}
+#endif
+
+
static void
catch_signal (int sig, RETSIGTYPE (*handler) (int))
{
# ifdef HAVE_WAYLAND
Bool wayland_active_p = False;
- const char *wayland_err = 0;
- wayland_state *wayland = wayland_idle_init (wayland_activity_cb,
- &wayland_active_p,
- &wayland_err);
- if (wayland)
+ wayland_dpy *wdpy = wayland_dpy_connect();
+ wayland_idle *widle = wayland_idle_init (wdpy,
+ wayland_activity_cb,
+ &wayland_active_p);
+ if (widle)
{
- wayland_p = True; /* Connected to Wayland */
+ wayland_p = True; /* Connected to Wayland and can detect activity. */
}
- else if (wayland_err && !strcmp (wayland_err, "connection failed"))
+ else if (wdpy)
{
- if (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET"))
- {
- /* Running under Wayland, but unable to connect. */
- fprintf (stderr, "%s: wayland: %s\n", blurb(), wayland_err);
- exit (1);
- }
- else
- {
- /* Running under real X11, presumably. */
- if (verbose_p)
- fprintf (stderr, "%s: wayland: %s (assuming real X11)\n",
- blurb(), wayland_err);
- }
+ /* Connected to Wayland, but no idle protocols available. */
+ fprintf (stderr, "%s: wayland: idle detection is impossible.\n",
+ blurb());
+ exit (1);
}
- else if (wayland_err)
+ else if (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET"))
{
- /* Connected to Wayland, but initialization failed. */
- fprintf (stderr, "%s: wayland: %s\n", blurb(), wayland_err);
+ /* Running under Wayland, but unable to connect. */
+ fprintf (stderr, "%s: wayland: connection failed\n", blurb());
exit (1);
}
else
- abort();
-
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: wayland: connection failed; assuming real X11\n",
+ blurb());
+ }
# else /* !HAVE_WAYLAND */
if (getenv ("WAYLAND_DISPLAY") || getenv ("WAYLAND_SOCKET"))
if (! init_xinput (dpy, &xi_opcode))
saver_exit (1);
+# ifdef HAVE_WAYLAND
+ if (wdpy)
+ wayland_dpy_atexit (wdpy, saver_wayland_exit, NULL);
+# endif
+
/* Disable server built-in screen saver. */
XSetScreenSaver (dpy, 0, 0, 0, 0);
XForceScreenSaver (dpy, ScreenSaverReset);
# ifdef HAVE_WAYLAND
/* Stop blocking if there is activity on either the X11 socket
or the Wayland socket. */
- if (wayland)
+ if (wdpy)
{
- int wfd = wayland_idle_get_fd (wayland);
+ int wfd = wayland_dpy_get_fd (wdpy);
FD_SET (wfd, &in_fds);
fd = MAX (xfd, wfd);
}
# ifdef HAVE_WAYLAND
- if (wayland)
+ if (wdpy)
{
- wayland_idle_process_events (wayland);
+ wayland_dpy_process_events (wdpy, False);
if (wayland_active_p)
{
active_at = now;
extern Bool ensure_no_screensaver_running (Display *, Screen *);
/* Display Power Management System (DPMS) interface. */
-extern Bool monitor_powered_on_p (Display *);
-extern void monitor_power_on (saver_info *si, Bool on_p);
-
+extern Bool monitor_powered_on_p (saver_info *);
+extern void monitor_power_on (saver_info *, Bool on_p);
/* =======================================================================
blanking
protocols that allow us to tell when the user is idle. It works with KDE
and most other compositors, however.
.TP 3
-\fB2:\fP Even a single pixel of mouse motion will cause the screen to
-un-blank: there is no pointer hysteresis.
+\fB2:\fP No mouse hystersis.
+
+Even a single pixel of mouse motion will cause the screen to un-blank.
+
.TP 3
-\fB2:\fP Fading in and out might not work; hacks that grab and manipulate
-a desktop screenshot might not work.
+\fB3:\fP Fading and screenshots might not work.
-Under Wayland, these features depend on the program
+Under Wayland, Fading in and out, and allowing hacks to grab and
+manipulate a desktop screenshot, depend on the program
+.BR grim (1)
+being installed to grab screenshots for us. And
.BR grim (1)
-being installed to grab screenshots for us. And \fBgrim\fP doesn't work
-under the GNOME or KDE compositors.
+doesn't work under the GNOME or KDE compositors.
.RE
For XScreenSaver to be able to lock, you will need to switch off
a screen saver and locker for the X window system
by Jamie Zawinski
- version 6.11
- 01-Jul-2025
+ version 6.12
+ 07-Jul-2025
https://www.jwz.org/xscreensaver/
CC = @CC@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
-DEFS = -DSTANDALONE -DUSE_GL @DEFS@
+DEFS = -DSTANDALONE @GL_CFLAGS@ @DEFS@
LIBS = @LIBS@
PERL = @PERL@
# These hacks use a slightly-differently-compiled variant of recanim.c.
# This is how to make the the other .o file from it.
#
-XLM_CFLAGS=-DUSE_GL $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS)
+XLM_CFLAGS=@GL_CFLAGS@ $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS)
recanim-gl.o: $(HACK_SRC)/recanim.c
$(CC) -o $@ -c $(XLM_CFLAGS) $(HACK_SRC)/recanim.c
xlock-gl-utils.o: $(UTILS_SRC)/hsv.h
xlock-gl-utils.o: $(UTILS_SRC)/resources.h
xlock-gl-utils.o: $(UTILS_SRC)/usleep.h
+xlock-gl-utils.o: $(UTILS_SRC)/visual-gl.h
xlock-gl-utils.o: $(UTILS_SRC)/visual.h
xlock-gl-utils.o: $(UTILS_SRC)/xft.h
xlock-gl-utils.o: $(UTILS_SRC)/yarandom.h
xlock-gl-utils.o: $(HACK_SRC)/xlockmoreI.h
xscreensaver-gl-visual.o: ../../config.h
+xscreensaver-gl-visual.o: $(UTILS_SRC)/visual-gl.h
xscreensaver-gl-visual.o: $(UTILS_SRC)/visual.h
-/* mapscroller, Copyright © 2021-2023 Jamie Zawinski <jwz@jwz.org>
+/* mapscroller, Copyright © 2021-2025 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
typedef struct {
GLXContext *glx_context;
char *url_template;
+ char *loader;
int map_level;
GLfloat speed;
int duration;
Bool ocean_p;
enum { FADE_OUT, RUN } mode;
- time_t change_time;
+ time_t start_time, change_time;
double opacity;
pid_t pid;
int fd1[2], fd2[2];
int ac = 0;
- av[ac++] = get_string_resource (mi->dpy, "loaderProgram", "Program");
+ av[ac++] = bp->loader;
if (verbose_p == 1) av[ac++] = "-v";
if (verbose_p == 2) av[ac++] = "-vv";
else if (verbose_p == 3) av[ac++] = "-vvv";
bp->font_data = load_texture_font (mi->dpy, "titleFont");
+ bp->loader = get_string_resource (mi->dpy, "loaderProgram", "Program");
bp->url_template = url_template_arg;
if (!bp->url_template ||
!*bp->url_template ||
bp->mode = RUN;
bp->opacity = 1;
- bp->change_time = time ((time_t *) 0);
+ bp->start_time = time ((time_t *) 0);
+ bp->change_time = bp->start_time;
fork_loader (mi);
reshape_map (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
map_configuration *bp = &bps[MI_SCREEN(mi)];
Display *dpy = MI_DISPLAY(mi);
Window window = MI_WINDOW(mi);
+ time_t now = time ((time_t *) 0);
if (!bp->glx_context)
return;
if (!strcasecmp (origin_arg, "random") ||
!strcasecmp (origin_arg, "random-city"))
{
- time_t now = time ((time_t *) 0);
if (force_change_p ||
(bp->mode == RUN &&
now > bp->change_time + bp->duration))
MI_WIDTH(mi), MI_HEIGHT(mi), 1, buf);
}
- if (bp->dead_p)
+ if (bp->dead_p ||
+ (bp->tile_count == 0 &&
+ now >= bp->start_time + 5))
{
- static char buf[1024] = "";
- if (! *buf)
- {
- char *s = get_string_resource (mi->dpy, "loaderProgram", "Program");
- sprintf (buf, "\n\n\n\n\n\n%.100s subprocess died.", s);
- free (s);
- if (bp->tile_count < 10)
- strcat (buf,
- " Is Perl broken? Maybe try:\n\n"
- "sudo cpan LWP::Simple LWP::Protocol::https Mozilla::CA");
- }
+ char buf[1024];
+ char *s = buf;
+ *s = 0;
+ strcat (s, "\n\n\n\n\n\n");
+ s += strlen (s);
+ if (bp->dead_p)
+ sprintf (s, "%.100s subprocess died.", bp->loader);
+ else
+ sprintf (s, "%.100s subprocess produced no tiles.", bp->loader);
+ s += strlen (s);
+
+ if (! bp->dead_p)
+ strcat (s, " Network problem?");
+ s += strlen (s);
+
+ if (bp->tile_count < 10)
+ strcat (s,
+ " Is Perl broken? Maybe try:\n\n"
+ "sudo cpan LWP::Simple LWP::Protocol::https Mozilla::CA");
+
glColor3f (0.3, 0.3, 0.3);
print_texture_label (mi->dpy, bp->font_data,
MI_WIDTH(mi), MI_HEIGHT(mi), 0, buf);
}
+
if (mi->fps_p && !bp->dead_p)
{
if (!MI_IS_WIREFRAME(mi))
my $progname = $0; $progname =~ s@.*/@@g;
$progname =~ s@\.pl$@@g;
-my ($version) = ('$Revision: 1.9 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.10 $' =~ m/\s(\d[.\d]+)\s/s);
my $verbose = 0;
my $url_template = undef;
#ifdef HAVE_GL /* whole file */
+#include "visual-gl.h"
#include "texfont.h"
#ifndef isupper
#endif
-# ifndef HAVE_EGL
-/* Gag -- we use this to turn X errors from glXCreateContext() into
- something that will actually make sense to the user.
- */
-static XErrorHandler orig_ehandler = 0;
-static Bool got_error = 0;
-
-static int
-BadValue_ehandler (Display *dpy, XErrorEvent *error)
-{
- if (error->error_code == BadValue)
- {
- got_error = True;
- return 0;
- }
- else
- return orig_ehandler (dpy, error);
-}
-#endif /* !HAVE_EGL */
-
-
#ifndef HAVE_JWZGLES
# undef glEnable
void (* glEnable_fn) (GLuint) = glEnable;
Display *dpy = mi->dpy;
Window window = mi->window;
Screen *screen = mi->xgwa.screen;
- Visual *visual = mi->xgwa.visual;
- XVisualInfo vi_in, *vi_out;
- int out_count;
if (mi->glx_context) {
glXMakeCurrent (dpy, window, mi->glx_context);
mi->xlmft->jwzgles_make_current (mi->jwzgles_state);
# endif
- vi_in.screen = screen_number (screen);
- vi_in.visualid = XVisualIDFromVisual (visual);
- vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
- &vi_in, &out_count);
- if (! vi_out) abort ();
-
-# ifdef HAVE_EGL
- {
- egl_data *d = (egl_data *) calloc (1, sizeof(*d));
-
- /* The correct EGL config has been selected by utils/visual-gl.c
- (via hacks/glx/xscreensaver-gl-visual) by calling get_egl_config()
- from get_gl_visual and returning the corresponding X11 Visual.
- That visual is the one that was used to create our window. We will
- pass the corresponding visual ID to get_egl_config() to obtain the
- same configuration here. */
- unsigned int vid = XVisualIDFromVisual (visual);
-
- const EGLint ctxattr1[] = {
-# ifdef HAVE_JWZGLES
- EGL_CONTEXT_MAJOR_VERSION, 1, /* Request an OpenGL ES 1.1 context. */
- EGL_CONTEXT_MINOR_VERSION, 1,
-# else
- EGL_CONTEXT_MAJOR_VERSION, 1, /* Request an OpenGL 1.3 context. */
- EGL_CONTEXT_MINOR_VERSION, 3,
-# endif
- EGL_NONE
- };
- const EGLint *ctxattr = ctxattr1;
-
-# ifdef HAVE_GLES3
- const EGLint ctxattr3[] = {
- EGL_CONTEXT_MAJOR_VERSION, 3, /* Request an OpenGL ES 3.0 context. */
- EGL_CONTEXT_MINOR_VERSION, 0,
- EGL_NONE
- };
-
- if (get_boolean_resource (dpy, "prefersGLSL", "PrefersGLSL"))
- ctxattr = ctxattr3;
-# endif /* HAVE_GLES3 */
-
- /* This is re-used, no need to close it. */
- d->egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR,
- (void *) dpy, NULL);
- if (!d->egl_display)
- {
- fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname);
- abort();
- }
-
- get_egl_config (dpy, d->egl_display, vid, &d->egl_config);
- if (!d->egl_config)
- {
- /* get_egl_config already printed this:
- fprintf (stderr, "%s: no matching EGL config for X11 visual 0x%lx\n",
- progname, vi_out->visualid); */
- /* returning 0 might be reasonable, but makes all the GL hacks
- simply draw nothing in a loop. */
- exit (1);
- }
-
- d->egl_surface = eglCreatePlatformWindowSurface (d->egl_display,
- d->egl_config,
- &window, NULL);
- if (! d->egl_surface)
- {
- fprintf (stderr, "%s: eglCreatePlatformWindowSurface failed:"
- " window 0x%lx visual 0x%x\n", progname, window, vid);
- abort();
- }
-
-#ifdef HAVE_JWZGLES
- /* This call is not strictly necessary to get an OpenGL ES context
- since the default API is EGL_OPENGL_ES_API, but it makes our
- intention clear.
- */
- if (!eglBindAPI (EGL_OPENGL_ES_API))
- {
- fprintf (stderr, "%s: eglBindAPI failed\n", progname);
- }
-#else /* !HAVE_JWZGLES */
- /* This is necessary to get a OpenGL context instead of an OpenGLES
- context.
- */
- if (!eglBindAPI (EGL_OPENGL_API))
- {
- fprintf (stderr, "%s: eglBindAPI failed\n", progname);
- }
-#endif /* !HAVE_JWZGLES */
-
- d->egl_context = eglCreateContext (d->egl_display, d->egl_config,
- EGL_NO_CONTEXT, ctxattr);
-
-# ifdef HAVE_GLES3
- /* If creation of a GLES 3.0 context failed, fall back to GLES 1.x. */
- if (!d->egl_context && ctxattr != ctxattr1)
- {
- /* fprintf (stderr, "%s: eglCreateContext 3.0 failed\n", progname); */
- d->egl_context = eglCreateContext (d->egl_display, d->egl_config,
- EGL_NO_CONTEXT, ctxattr1);
- }
-# endif /* HAVE_GLES3 */
-
- if (!d->egl_context)
- {
- fprintf (stderr, "%s: eglCreateContext failed\n", progname);
- abort();
- }
-
- /* describe_gl_visual (stderr, screen, visual, False); */
-
- mi->glx_context = d; /* #### leaked */
-
- glXMakeCurrent (dpy, window, mi->glx_context);
- }
-# else /* GLX */
- {
- XSync (dpy, False);
- orig_ehandler = XSetErrorHandler (BadValue_ehandler);
- mi->glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
- XSync (dpy, False);
- XSetErrorHandler (orig_ehandler);
- if (got_error)
- mi->glx_context = 0;
- }
-
- if (!mi->glx_context)
- {
- fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n",
- progname, (unsigned int) XVisualIDFromVisual (visual));
- exit(1);
- }
-
- glXMakeCurrent (dpy, window, mi->glx_context);
-
- {
- GLboolean rgba_mode = 0;
- glGetBooleanv(GL_RGBA_MODE, &rgba_mode);
- if (!rgba_mode)
- {
- glIndexi (WhitePixelOfScreen (screen));
- glClearIndex (BlackPixelOfScreen (screen));
- }
- }
-# endif /* GLX */
-
- XFree((char *) vi_out);
-
-
- /* jwz: the doc for glDrawBuffer says "The initial value is GL_FRONT
- for single-buffered contexts, and GL_BACK for double-buffered
- contexts." However, I find that this is not always the case,
- at least with Mesa 3.4.2 -- sometimes the default seems to be
- GL_FRONT even when glGet(GL_DOUBLEBUFFER) is true. So, let's
- make sure.
-
- Oh, hmm -- maybe this only happens when we are re-using the
- xscreensaver window, and the previous GL hack happened to die with
- the other buffer selected? I'm not sure. Anyway, this fixes it.
- */
- {
- GLboolean d = False;
- glGetBooleanv (GL_DOUBLEBUFFER, &d);
- if (d)
- glDrawBuffer (GL_BACK);
- else
- glDrawBuffer (GL_FRONT);
- }
-
- /* Sometimes glDrawBuffer() throws "invalid op". Dunno why. Ignore. */
- clear_gl_error ();
+ mi->glx_context = openGL_context_for_window (screen, window);
/* Process the -background argument. */
{
-/* xscreensaver, Copyright (c) 2000-2021 by Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2000-2025 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include <GL/glx.h>
#include "visual.h"
+#include "visual-gl.h"
char *progname = 0;
char *progclass = "XScreenSaver";
}
-static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW, XA_NET_WM_PID;
+static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW, XA_NET_WM_PID,
+ XA_NET_WM_PING;
/* Dead-trivial event handling: exits if "q" or "ESC" are typed.
Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
fprintf (stderr, "%s: unknown ClientMessage %s received!\n",
progname, s);
}
- else if (event->xclient.data.l[0] != XA_WM_DELETE_WINDOW)
+ else if (event->xclient.data.l[0] == XA_WM_DELETE_WINDOW)
+ {
+ return False; /* exit */
+ }
+ else if (event->xclient.data.l[0] == XA_NET_WM_PING)
+ {
+ event->xclient.window = DefaultRootWindow (dpy);
+ if (! XSendEvent (dpy, event->xclient.window, False,
+ PropertyChangeMask, event))
+ fprintf (stderr, "%s: WM_PONG failed\n", progname);
+ }
+ else
{
char *s1 = XGetAtomName(dpy, event->xclient.message_type);
char *s2 = XGetAtomName(dpy, event->xclient.data.l[0]);
fprintf (stderr, "%s: unknown ClientMessage %s[%s] received!\n",
progname, s1, s2);
}
- else
- {
- return False; /* exit */
- }
}
break;
}
XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
XA_NET_WM_PID = XInternAtom (dpy, "_NET_WM_PID", False);
+ XA_NET_WM_PING = XInternAtom (dpy, "_NET_WM_PING", False);
{
char *v = (char *) strdup(strchr(screensaver_id, ' '));
/* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules.
- * xscreensaver, Copyright (c) 1997-2021 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright © 1997-2025 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#endif /* !HAVE_EGL */
#if defined(HAVE_EGL) && defined(USE_GL)
- typedef struct egl_data {
- EGLDisplay egl_display;
- EGLSurface egl_surface;
- EGLContext egl_context; /* Unused */
- EGLConfig egl_config; /* Unused */
- } egl_data;
-
extern Bool glXMakeCurrent (Display *, GLXDrawable, GLXContext);
extern void glXSwapBuffers (Display *, GLXDrawable);
#endif /* HAVE_EGL && USE_GL */
or KDE. They invented their own, incompatible APIs, which always
play a camera noise and flash the screen white, and might also
pop up a confirmation dialog.
+
+ ---------------------------------------------------------------------
+
+ Further notes on the Wayland screen-grabbing situation...
+ Which is absolute bugfuck insanity, I might add...
+
+ Rather than exec'ing "grim", which may not be installed, we could
+ instead connect to the Wayland server directly and do the thing that
+ grim does, but that is an *enormous* amount of code, requiring four
+ or five nonstandard "staging" protocols:
+
+ - "ext-image-capture-source-v1" and its required companion
+ "ext-image-copy-capture-v1" (and why they aren't the same thing,
+ I could not tell you);
+ - And "ext-foreign-toplevel-list-v1" which they also depend on;
+ - And "zxdg-output-manager-v1", because without that, a "wl_output"
+ will tell you its size but not its position. It's
+ Heisenbergisterical!
+
+ Once you've done that, you have to figure out what rectangle you want
+ from the source outputs. Easy right? Except that they might be rotated,
+ mirrored or scaled arbitrarily (e.g. "retina"), and you have to
+ recapitulate that in the grabbed image. Look at the madness in grim's
+ render.c.
+
+ So pretty much the only part you can leave out is the "write a PNG
+ file" bit. The rest of grim's ~1,800 lines of code is insanely
+ complicated and sadly necessary.
+
+ It would be easier for me to just include grim with XScreenSaver.
+
+
+ Grim does not support GNOME or KDE, which provide four (4) different
+ interfaces for us to also not support:
+
+ - GNOME has a DBus endpoint, "org.gnome.Shell.Screenshot", but it's
+ not clear to me whether it is possible to use it without an
+ interactive dialog popping up, a shutter sound, and a screen flash:
+ https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/data/dbus-interfaces/org.gnome.Shell.Screenshot.xml
+
+ - KDE also has a DBus endpoint, "org.kde.KWin.ScreenShot2", which
+ says: "The application that requests the screenshot must have the
+ org.kde.KWin.ScreenShot2 interface listed in the
+ X-KDE-DBUS-Restricted-Interfaces desktop file entry." This may also
+ do the mandatory "ask for permission, shutter sound, flash" thing
+ that GNOME does, I can't tell:
+ https://invent.kde.org/plasma/kwin/-/blob/master/src/plugins/screenshot/org.kde.KWin.ScreenShot2.xml
+
+ - Supposedly KDE and GNOME also support the DBus endpoint
+ "org.freedesktop.portal.Screenshot", but I imagine that's just a
+ wrapper around their native versions with all the same downsides:
+ https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Screenshot.html
+
+ - Back in the Wayland world, there is "kde-zkde-screencast-unstable"
+ https://wayland.app/protocols/kde-zkde-screencast-unstable-v1
+ Does this one require the user to click OK first? Probably, but who
+ can tell?
+
+ More discussion and links in this thread:
+ https://www.jwz.org/blog/2025/06/wayland-screenshots/#comment-260369
*/
#include "utils.h"
#include "xmu.h"
#include "vroot.h"
#include "../driver/prefs.h"
-
-#include "../driver/blurb.c" /* Eh, this is awful but so what */
-
+#include "../driver/blurb.c"
#ifndef _XSCREENSAVER_VROOT_H_
# error Error! You have an old version of vroot.h! Check -I args.
sprintf (rect, "%d,%d,%d,%d", xgwa.x, xgwa.y, xgwa.width, xgwa.height);
av[ac++] = GETIMAGE_SCREEN_PROGRAM; /* "screencapture" */
- av[ac++] = "-x"; /* no sound */
- av[ac++] = "-C"; /* capture mouse */
- av[ac++] = "-R"; /* rect */
+ av[ac++] = "-x"; /* no sound */
+ av[ac++] = "-R"; /* rect */
av[ac++] = rect;
- av[ac++] = "-t"; /* file type */
+ av[ac++] = "-t"; /* file type */
av[ac++] = "png";
av[ac++] = outfile;
sprintf (rect, "%d,%d %dx%d", xgwa.x, xgwa.y, xgwa.width, xgwa.height);
av[ac++] = GETIMAGE_SCREEN_PROGRAM; /* "grim" */
- av[ac++] = "-c"; /* capture mouse */
- av[ac++] = "-g"; /* geometry */
+ av[ac++] = "-g"; /* geometry */
av[ac++] = rect;
- av[ac++] = "-t"; /* file type */
+ av[ac++] = "-t"; /* file type */
av[ac++] = "png";
av[ac++] = outfile;
# else
-# Auto-generated: Tue Jul 1 18:29:55 PDT 2025
+# Auto-generated: Mon Jul 7 12:46:55 PDT 2025
driver/demo-Gtk-conf.c
driver/demo-Gtk.c
driver/demo.ui
-# utils/Makefile.in --- xscreensaver, Copyright © 1997-2023 Jamie Zawinski.
+# utils/Makefile.in --- xscreensaver, Copyright © 1997-2025 Jamie Zawinski.
# the `../configure' script generates `utils/Makefile' from this file.
async_netdb.o xft.o xftwrap.o utf8wc.o pow2.o font-retry.o \
screenshot.o
HDRS = alpha.h colors.h grabclient.h hsv.h resources.h \
- spline.h usleep.h utils.h version.h visual.h vroot.h xmu.h \
- yarandom.h erase.h xshm.h xdbe.h colorbars.h minixpm.h \
- xscreensaver-intl.h textclient.h aligned_malloc.h \
- thread_util.h async_netdb.h xft.h xftwrap.h utf8wc.h pow2.h \
- font-retry.h queue.h screenshot.h
+ spline.h usleep.h utils.h version.h visual.h visual-gl.h \
+ vroot.h xmu.h yarandom.h erase.h xshm.h xdbe.h colorbars.h \
+ minixpm.h xscreensaver-intl.h textclient.h aligned_malloc.h \
+ thread_util.h async_netdb.h xft.h xftwrap.h utf8wc.h pow2.h \
+ font-retry.h queue.h screenshot.h
STAR = *
LOGOS = images/$(STAR).xpm \
images/$(STAR).png \
visual-gl.o: ../config.h
visual-gl.o: $(srcdir)/resources.h
visual-gl.o: $(srcdir)/utils.h
+visual-gl.o: $(srcdir)/visual-gl.h
visual-gl.o: $(srcdir)/visual.h
visual.o: ../config.h
visual.o: $(srcdir)/resources.h
-/* xscreensaver, Copyright (c) 2001-2018 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2001-2025 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include "colorbars.h"
#include "../hacks/ximage-loader.h"
+#define LGBTQIA
+#ifndef LGBTQIA /* SMPTE ECR-1-1978 */
static const char * const colors[7][18] = {
{ "#CCCCCC", "#FFFF00", "#00FFFF", "#00FF00", /* tall bars */
"#FF00FF", "#FF0000", "#0000FF", "#000000",
"#FFFFFF", "#FFFFFF", "#FFFFFF",
"#0000AD", "#0000AD", "#0000AD",
"#131313", "#131313", "#131313",
- "#000000", "#000000", "#262626",
+ "#000000", "#131313", "#262626", /* ramp */
"#000000", "#000000", "#000000"
}
};
+#else /* LGBTQIA pride flag colorbars designed by
+ Cable Contributes to Life <https://bsky.app/profile/cctl.me> --
+ https://web.archive.org/web/20250701065803/https://bsky.app/profile/cctl.me/post/3lsthzde3h22g
+ "The first set of columns use the colors of the gay pride flag,
+ with the addition of the original SMPTE color on the final column.
+ The second set of columns contains two pride flags: the pansexual
+ flag horizontally, and the asexual flag flipped and horizontal.
+ The final set of columns contains the three colors of the
+ transgender flag and the two POC-inclusive colors, followed by
+ the original bar gradient from the SMPTE ECR-1-1978 pattern."
+ */
+
+static const char * const colors[7][18] = {
+ { "#E40303", "#FF8C00", "#FFED00", "#008026", /* tall bars, pride */
+ "#004CFF", "#732982", "#0000FF",
+ 0
+ }, {
+ "#FF218C", "#FFD800", "#21B1FF", "#800080", /* short bars, pan a */
+ "#FFFFFF", "#A3A3A3", "#000000",
+ 0
+ }, {
+ "#000000", 0 /* blank */
+ }, {
+ "#FFFFFF", "#EEEEEE", "#DDDDDD", "#CCCCCC", /* gray ramp */
+ "#BBBBBB", "#AAAAAA", "#999999", "#888888",
+ "#777777", "#666666", "#555555", "#444444",
+ "#333333", "#222222", "#111111", "#000000"
+ }, {
+ "#000000", "#111111", "#222222", "#333333", /* gray rev ramp */
+ "#444444", "#555555", "#666666", "#777777",
+ "#888888", "#999999", "#AAAAAA", "#BBBBBB",
+ "#CCCCCC", "#DDDDDD", "#EEEEEE", "#FFFFFF"
+ }, {
+ "#000000", 0 /* blank */
+ }, {
+ "#5BCEFA", "#5BCEFA", "#5BCEFA", /* trans poc */
+ "#F5A9B8", "#F5A9B8", "#F5A9B8",
+ "#FFFFFF", "#FFFFFF", "#FFFFFF",
+ "#613704", "#613704", "#613704",
+ "#000000", "#131313", "#262626", /* ramp */
+ "#000000", "#000000", "#000000"
+ }
+};
+#endif /* LGBTQIA */
+
+
static const int heights[7] = { 63, 10, 1, 5, 5, 1, 15 }; /* percentages */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/time.h>
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h> /* for waitpid() and associated macros */
}
+static double
+double_time (void)
+{
+ struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+ struct timezone tzp;
+ gettimeofday(&now, &tzp);
+# else
+ gettimeofday(&now);
+# endif
+
+ return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
+
/* Grab a screenshot and return it.
It will be the size and extent of the given window,
or the full screen, as requested.
struct { int x, y, x2, y2; } root, win;
XErrorHandler old_handler;
Bool external_p = False;
+ double start = double_time();
XGetWindowAttributes (dpy, window, &win_xgwa);
root_window = XRootWindowOfScreen (win_xgwa.screen);
XFreeGC (dpy, gc);
}
- if (verbose_p || !pixmap)
- fprintf (stderr, "%s: %s screenshot 0x%lx %dx%d"
- " for window 0x%lx %dx%d+%d+%d\n", blurb(),
- (pixmap ? "saved" : "failed to save"),
- (unsigned long) pixmap, win_xgwa.width, win_xgwa.height,
- (unsigned long) window,
- owin_xgwa.width, owin_xgwa.height, owin_xgwa.x, owin_xgwa.y);
+ {
+ double elapsed = double_time() - start;
+ char late[100];
+ if (elapsed >= 0.75)
+ sprintf (late, " -- took %.1f seconds", elapsed);
+ else
+ *late = 0;
+
+ if (verbose_p || !pixmap || *late)
+ fprintf (stderr, "%s: %s screenshot 0x%lx %dx%d"
+ " for window 0x%lx %dx%d+%d+%d%s\n", blurb(),
+ (pixmap ? "saved" : "failed to save"),
+ (unsigned long) pixmap, win_xgwa.width, win_xgwa.height,
+ (unsigned long) window,
+ owin_xgwa.width, owin_xgwa.height, owin_xgwa.x, owin_xgwa.y,
+ late);
+ }
+
return pixmap;
}
(unsigned long) window,
win_xgwa.width, win_xgwa.height, win_xgwa.x, win_xgwa.y,
(unsigned long) screenshot, root.w, root.h);
+
return p2;
}
static const char screensaver_id[] =
- "@(#)xscreensaver 6.11 (01-Jul-2025), by Jamie Zawinski (jwz@jwz.org)";
-#define XSCREENSAVER_VERSION "6.11"
-#define XSCREENSAVER_RELEASED 1751396400
+ "@(#)xscreensaver 6.12 (07-Jul-2025), by Jamie Zawinski (jwz@jwz.org)";
+#define XSCREENSAVER_VERSION "6.12"
+#define XSCREENSAVER_RELEASED 1751914800
# endif
#endif /* HAVE_GL */
-#include "visual.h" /* after EGL/egl.h */
+#include "visual.h"
+#include "visual-gl.h" /* after EGL/egl.h */
#undef countof
#define countof(x) (sizeof(x)/sizeof(*(x)))
(value == GLX_NONE_EXT ? "none" :
value == GLX_SLOW_VISUAL_EXT ? "slow" :
value == GLX_NON_CONFORMANT_EXT ? "non-conformant" :
- "???");
+ "???"));
# else
fprintf (f, " GLX rating: %s\n",
(value == GLX_NONE_EXT ? "none" :
#endif /* !HAVE_GL */
}
+
+
+# ifndef HAVE_EGL
+/* Gag -- we use this to turn X errors from glXCreateContext() into
+ something that will actually make sense to the user.
+ */
+static XErrorHandler orig_ehandler = 0;
+static Bool got_error = 0;
+
+static int
+BadValue_ehandler (Display *dpy, XErrorEvent *error)
+{
+ if (error->error_code == BadValue)
+ {
+ got_error = True;
+ return 0;
+ }
+ else
+ return orig_ehandler (dpy, error);
+}
+#endif /* !HAVE_EGL */
+
+
+/* Initializes OpenGL and returns a GLXContext or egl_data for the window.
+ The window is assumed to have been created with the proper visual.
+ */
+#ifdef HAVE_EGL
+egl_data *openGL_context_for_window (Screen *screen, Window window)
+#else
+GLXContext openGL_context_for_window (Screen *screen, Window window)
+#endif
+{
+ Display *dpy = DisplayOfScreen (screen);
+ XWindowAttributes xgwa;
+ Visual *visual;
+ XVisualInfo vi_in, *vi_out;
+ int out_count;
+
+# ifdef HAVE_EGL
+ egl_data *egl_data_ret = NULL;
+# else
+ GLXContext glx_context = NULL;
+# endif
+
+ XGetWindowAttributes (dpy, window, &xgwa);
+ visual = xgwa.visual;
+
+ vi_in.screen = screen_number (screen);
+ vi_in.visualid = XVisualIDFromVisual (visual);
+ vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+ &vi_in, &out_count);
+ if (! vi_out) abort ();
+
+# ifdef HAVE_EGL
+ {
+ egl_data *d = (egl_data *) calloc (1, sizeof(*d));
+
+ /* The correct EGL config has been selected by calling get_egl_config()
+ from get_gl_visual and returning the corresponding X11 Visual.
+ That visual is the one that was used to create the window. We will
+ pass the corresponding visual ID to get_egl_config() to obtain the
+ same configuration here. */
+ unsigned int vid = XVisualIDFromVisual (visual);
+
+ const EGLint ctxattr1[] = {
+# ifdef HAVE_JWZGLES
+ EGL_CONTEXT_MAJOR_VERSION, 1, /* Request an OpenGL ES 1.1 context. */
+ EGL_CONTEXT_MINOR_VERSION, 1,
+# else
+ EGL_CONTEXT_MAJOR_VERSION, 1, /* Request an OpenGL 1.3 context. */
+ EGL_CONTEXT_MINOR_VERSION, 3,
+# endif
+ EGL_NONE
+ };
+ const EGLint *ctxattr = ctxattr1;
+
+# ifdef HAVE_GLES3
+ const EGLint ctxattr3[] = {
+ EGL_CONTEXT_MAJOR_VERSION, 3, /* Request an OpenGL ES 3.0 context. */
+ EGL_CONTEXT_MINOR_VERSION, 0,
+ EGL_NONE
+ };
+
+ if (get_boolean_resource (dpy, "prefersGLSL", "PrefersGLSL"))
+ ctxattr = ctxattr3;
+# endif /* HAVE_GLES3 */
+
+ /* This is re-used, no need to close it. */
+ d->egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR,
+ (void *) dpy, NULL);
+ if (!d->egl_display)
+ {
+ fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname);
+ abort();
+ }
+
+ get_egl_config (dpy, d->egl_display, vid, &d->egl_config);
+ if (!d->egl_config)
+ {
+ /* get_egl_config already printed this:
+ fprintf (stderr, "%s: no matching EGL config for X11 visual 0x%lx\n",
+ progname, vi_out->visualid); */
+ /* returning 0 might be reasonable, but makes all the GL hacks
+ simply draw nothing in a loop. */
+ exit (1);
+ }
+
+ d->egl_surface = eglCreatePlatformWindowSurface (d->egl_display,
+ d->egl_config,
+ &window, NULL);
+ if (! d->egl_surface)
+ {
+ fprintf (stderr, "%s: eglCreatePlatformWindowSurface failed:"
+ " window 0x%lx visual 0x%x\n", progname, window, vid);
+ abort();
+ }
+
+#ifdef HAVE_JWZGLES
+ /* This call is not strictly necessary to get an OpenGL ES context
+ since the default API is EGL_OPENGL_ES_API, but it makes our
+ intention clear.
+ */
+ if (!eglBindAPI (EGL_OPENGL_ES_API))
+ {
+ fprintf (stderr, "%s: eglBindAPI failed\n", progname);
+ }
+#else /* !HAVE_JWZGLES */
+ /* This is necessary to get a OpenGL context instead of an OpenGLES
+ context.
+ */
+ if (!eglBindAPI (EGL_OPENGL_API))
+ {
+ fprintf (stderr, "%s: eglBindAPI failed\n", progname);
+ }
+#endif /* !HAVE_JWZGLES */
+
+ d->egl_context = eglCreateContext (d->egl_display, d->egl_config,
+ EGL_NO_CONTEXT, ctxattr);
+
+# ifdef HAVE_GLES3
+ /* If creation of a GLES 3.0 context failed, fall back to GLES 1.x. */
+ if (!d->egl_context && ctxattr != ctxattr1)
+ {
+ /* fprintf (stderr, "%s: eglCreateContext 3.0 failed\n", progname); */
+ d->egl_context = eglCreateContext (d->egl_display, d->egl_config,
+ EGL_NO_CONTEXT, ctxattr1);
+ }
+# endif /* HAVE_GLES3 */
+
+ if (!d->egl_context)
+ {
+ fprintf (stderr, "%s: eglCreateContext failed\n", progname);
+ abort();
+ }
+
+ /* describe_gl_visual (stderr, screen, visual, False); */
+
+ if (! eglMakeCurrent (d->egl_display, d->egl_surface, d->egl_surface,
+ d->egl_context))
+ abort();
+
+ egl_data_ret = d;
+ }
+# else /* GLX */
+ {
+ XSync (dpy, False);
+ orig_ehandler = XSetErrorHandler (BadValue_ehandler);
+ glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
+ XSync (dpy, False);
+ XSetErrorHandler (orig_ehandler);
+ if (got_error)
+ glx_context = 0;
+ }
+
+ if (!glx_context)
+ {
+ fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n",
+ progname, (unsigned int) XVisualIDFromVisual (visual));
+ exit(1);
+ }
+
+ glXMakeCurrent (dpy, window, glx_context);
+
+ {
+ GLboolean rgba_mode = 0;
+ glGetBooleanv(GL_RGBA_MODE, &rgba_mode);
+ if (!rgba_mode)
+ {
+ glIndexi (WhitePixelOfScreen (screen));
+ glClearIndex (BlackPixelOfScreen (screen));
+ }
+ }
+# endif /* GLX */
+
+ XFree((char *) vi_out);
+
+
+ /* jwz: the doc for glDrawBuffer says "The initial value is GL_FRONT
+ for single-buffered contexts, and GL_BACK for double-buffered
+ contexts." However, I find that this is not always the case,
+ at least with Mesa 3.4.2 -- sometimes the default seems to be
+ GL_FRONT even when glGet(GL_DOUBLEBUFFER) is true. So, let's
+ make sure.
+
+ Oh, hmm -- maybe this only happens when we are re-using the
+ xscreensaver window, and the previous GL hack happened to die with
+ the other buffer selected? I'm not sure. Anyway, this fixes it.
+ */
+ {
+ GLboolean d = False;
+ glGetBooleanv (GL_DOUBLEBUFFER, &d);
+ if (d)
+ glDrawBuffer (GL_BACK);
+ else
+ glDrawBuffer (GL_FRONT);
+ }
+
+ /* Sometimes glDrawBuffer() throws "invalid op". Dunno why. Ignore. */
+ while (glGetError() != GL_NO_ERROR)
+ ;
+
+# ifdef HAVE_EGL
+ return egl_data_ret;
+# else
+ return glx_context;
+# endif
+}
+
+#ifdef HAVE_EGL
+
+void
+openGL_destroy_context (Display *dpy, egl_data *data)
+{
+ eglDestroyContext (data->egl_display, data->egl_context);
+ eglDestroySurface (data->egl_display, data->egl_surface);
+ eglTerminate (data->egl_display);
+ free (data);
+}
+
+#else /* HAVE_EGL */
+
+void
+openGL_destroy_context (Display *dpy, GLXContext ctx)
+{
+ glXDestroyContext (dpy, ctx);
+}
+
+#endif /* HAVE_EGL */
--- /dev/null
+/* xscreensaver, Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#ifndef __VISUAL_GL_H__
+#define __VISUAL_GL_H__
+
+extern Visual *get_gl_visual (Screen *);
+extern void describe_gl_visual (FILE *, Screen *, Visual *, Bool priv_cmap_p);
+extern Bool validate_gl_visual (FILE *, Screen *, const char *, Visual *);
+
+#ifdef HAVE_EGL
+
+# ifdef __egl_h_ /* EGL/egl.h included */
+
+extern void get_egl_config (Display *, EGLDisplay *, EGLint vid, EGLConfig *);
+
+typedef struct egl_data {
+ EGLDisplay egl_display;
+ EGLSurface egl_surface;
+ EGLContext egl_context;
+ EGLConfig egl_config;
+} egl_data;
+
+egl_data *openGL_context_for_window (Screen *, Window);
+void openGL_destroy_context (Display *, egl_data *);
+
+# endif /* __egl_h_ */
+
+#else /* !HAVE_EGL -- GLX */
+
+GLXContext openGL_context_for_window (Screen *, Window);
+void openGL_destroy_context (Display *, GLXContext);
+
+#endif /* !HAVE_EGL */
+
+#endif /* __VISUAL_GL_H__ */
-/* xscreensaver, Copyright © 1993-2021 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 1993-2025 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
unsigned long *green_mask,
unsigned long *blue_mask);
-extern Visual *get_gl_visual (Screen *);
-extern void describe_gl_visual (FILE *, Screen *, Visual *, Bool priv_cmap_p);
-extern Bool validate_gl_visual (FILE *, Screen *, const char *, Visual *);
-
-#ifdef __egl_h_ /* EGL/egl.h included */
-extern void get_egl_config (Display *, EGLDisplay *, EGLint vid, EGLConfig *);
-#endif
-
#endif /* __VISUAL_H__ */
%define name xscreensaver
-%define version 6.11
+%define version 6.12
Summary: X screen saver and locker
Name: %{name}