diff --git a/12to11.c b/12to11.c
index 3e6057d..02048e1 100644
--- a/12to11.c
+++ b/12to11.c
@@ -240,6 +240,7 @@ XLMain (int argc, char **argv)
XLInitPointerConstraints ();
XLInitRelativePointer ();
XLInitKeyboardShortcutsInhibit ();
+ XLInitIdleInhibit ();
/* This has to come after the rest of the initialization. */
DetermineServerTime ();
diff --git a/12to11.man b/12to11.man
index 37974cd..8d8d0a9 100644
--- a/12to11.man
+++ b/12to11.man
@@ -105,22 +105,61 @@ list. When \fBximStyles\fP is not specified, it defaults to:
.EE
.in
.TP
-.B renderer \fP (class \fBRenderer\fP)
+.B renderer\fP (class \fBRenderer\fP)
Specifies the rendering backend the protocol translator uses to
composite the contents of Wayland surfaces onto X windows. This can
either be \fBpicture\fP (the XRender based compositor) or \fBegl\fP
(the OpenGL ES 2.0 based compositor).
.TP
-.B useDirectPresentation \fP (class \fBUseDirectPresentation\fP)
+.B useDirectPresentation\fP (class \fBUseDirectPresentation\fP)
If ``True'' or ``true'', this resource enables the use of direct
presentation on unredirected windows. This is not yet complete
pending the installation of required functionality in the X server.
.TP
-.B wmProtocols \fP (class \fBWmProtocols\fP)
+.B wmProtocols\fP (class \fBWmProtocols\fP)
Comma-separated list of window manager protocols, similar to
\fBinputStyles\fP, that the protocol translator should enable or
disable. The current (and default) list of supported protocols are:
-\fBnetWmPing\fB.
+\fBnetWmPing\fP.
+.TP
+.B idleInhibitCommand\fP (class \fBIdleInhibitCommand\fP)
+.TP
+.B idleIntervalCommand\fP (class \fBIdleInhibitCommand\fP)
+.TP
+.B idleDeinhibitCommand\fP (class \fBIdleDeinhibitCommand\fP)
+These are commands that run when a focused Wayland client asks to
+inhibit the screen saver or screen locker, usually because a video is
+being played and does not require user interaction.
+\fBidleInhibitCommand\fP specifies a command that is run when one such
+client becomes focused or starts inhibiting the screen saver;
+\fBidleIntervalCommand\fP is a command that is run every several
+seconds (by default 60) while the screen saver is inhibited, and
+\fBidleDeinhibitCommand\fP is a command that is run once such a client
+stops inhibiting the screen saver or loses the input focus.
+.IP
+Since there are several different screen saver inhibition protocols
+used by different X desktops, the protocol translator refrains from
+implementing any of them. Instead, it provides the ability to run any
+command necessary to inhibit and de-inhibit the screen saver. For
+example, an
+.BR XScreenSaver(1)
+user may wish to apply the following resources:
+.IP
+.in +4
+.EX
+\fB12to11.IdleInhibitCommand: xscreensaver-command -deactivate\fP
+.EE
+.in
+.IP
+The commands specified are expected to finish. If the process
+corresponding to one command is still running by the time another
+command should have been run, the other command will be queued until
+the first process exits.
+.TP
+.B idleCommandInterval\fP (class \fBIdleCommandInterval\fP)
+The number of seconds the protocol translator waits between
+invocations of the command specified in \fBidleIntervalCommand\fP.
+Defaults to 60.
.IP
.SH ENVIRONMENT
Several environment variables exist that modify the behavior of the
@@ -215,6 +254,7 @@ zwp_text_input_manager_v3 1
wp_single_pixel_buffer_manager_v1 1
zwp_pointer_constraints_v1 1
zwp_relative_pointer_manager 1
+zwp_idle_inhibit_manager_v1 1
.TE
.PP
When the protocol translator is built with EGL support, the following
diff --git a/Imakefile b/Imakefile
index 22547a0..c01bf7f 100644
--- a/Imakefile
+++ b/Imakefile
@@ -24,7 +24,8 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \
picture_renderer.c explicit_synchronization.c transform.c \
wp_viewporter.c decoration.c text_input.c \
single_pixel_buffer.c drm_lease.c pointer_constraints.c \
- time.c relative_pointer.c keyboard_shortcuts_inhibit.c
+ time.c relative_pointer.c keyboard_shortcuts_inhibit.c \
+ idle_inhibit.c process.c
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
@@ -35,7 +36,8 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
picture_renderer.o explicit_synchronization.o transform.o \
wp_viewporter.o decoration.o text_input.o \
single_pixel_buffer.o drm_lease.o pointer_constraints.o \
- time.o relative_pointer.o keyboard_shortcuts_inhibit.o
+ time.o relative_pointer.o keyboard_shortcuts_inhibit.o \
+ idle_inhibit.o process.o
GENHEADERS = transfer_atoms.h
@@ -122,6 +124,7 @@ ScannerTarget(drm-lease-v1)
ScannerTarget(pointer-constraints-unstable-v1)
ScannerTarget(relative-pointer-unstable-v1)
ScannerTarget(keyboard-shortcuts-inhibit-unstable-v1)
+ScannerTarget(idle-inhibit-unstable-v1)
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
$(OBJS): $(GENHEADERS)
diff --git a/README b/README
index ece6452..e7fc12f 100644
--- a/README
+++ b/README
@@ -67,6 +67,7 @@ complete degree:
'wp_single_pixel_buffer_manager_v1', version: 1
'zwp_pointer_constraints_v1', version: 1
'zwp_relative_pointer_manager_v1', version: 1
+ 'zwp_idle_inhibit_manager_v1', version: 1
When built with EGL, the following Wayland protocol is also supported:
@@ -110,3 +111,7 @@ Running the binary should be simple as well:
./12to11
Wayland programs will then run as regular X windows.
+
+Be sure to configure your system so that idle inhibition is reported
+correctly. For more details, see the description of the
+idleInhibitCommand resource in the manual page.
diff --git a/compositor.h b/compositor.h
index 0b45370..8e00a6e 100644
--- a/compositor.h
+++ b/compositor.h
@@ -21,6 +21,7 @@ along with 12to11. If not, see . */
#include
#include
+#include
#include
@@ -649,6 +650,7 @@ extern void XLDeselectInputFromRootWindow (RootWindowSelection *);
extern void XLRecordBusfault (void *, size_t);
extern void XLRemoveBusfault (void *);
+extern Bool XLAddFdFlag (int, int, Bool);
/* Defined in compositor.c. */
@@ -914,6 +916,7 @@ enum _ClientDataType
SubsurfaceData,
PointerConfinementData,
ShortcutInhibitData,
+ IdleInhibitData,
MaxClientData,
};
@@ -1018,6 +1021,9 @@ struct _Surface
/* The number of outputs this surface is known to be on. */
int n_outputs;
+ /* The number of seats that have this surface focused. */
+ int num_focused_seats;
+
/* Bounds inside which the surface output need not be
recomputed. */
pixman_region32_t output_region;
@@ -1692,6 +1698,21 @@ extern void XLInitKeyboardShortcutsInhibit (void);
extern void XLCheckShortcutInhibition (Seat *, Surface *);
extern void XLReleaseShortcutInhibition (Seat *, Surface *);
+/* Defined in idle_inhibit.c. */
+
+extern void XLInitIdleInhibit (void);
+extern void XLIdleInhibitNoticeSurfaceFocused (Surface *);
+extern void XLDetectSurfaceIdleInhibit (void);
+
+/* Defined in process.c. */
+
+typedef struct _ProcessQueue ProcessQueue;
+
+extern void ParseProcessString (const char *, char ***, size_t *);
+extern void RunProcess (ProcessQueue *, char **);
+extern ProcessQueue *MakeProcessQueue (void);
+extern int ProcessPoll (struct pollfd *, nfds_t, struct timespec *);
+
/* Utility functions that don't belong in a specific file. */
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
diff --git a/drm_lease.c b/drm_lease.c
index dd9812b..7d1370d 100644
--- a/drm_lease.c
+++ b/drm_lease.c
@@ -931,6 +931,9 @@ AddProvider (RRProvider provider)
fd = fds[0];
+ /* Make the file descriptor FD_CLOEXEC. */
+ XLAddFdFlag (fd, FD_CLOEXEC, True);
+
if (drmGetNodeTypeFromFd (fd) != DRM_NODE_RENDER)
{
name = drmGetDeviceNameFromFd2 (fd);
@@ -938,7 +941,7 @@ AddProvider (RRProvider provider)
if (name)
{
DebugPrint ("device name is %s", name);
- new = open (name, O_RDWR);
+ new = open (name, O_RDWR | O_CLOEXEC);
if (new >= 0)
{
diff --git a/fns.c b/fns.c
index 8ec41c8..0f6a81d 100644
--- a/fns.c
+++ b/fns.c
@@ -789,8 +789,9 @@ UnblockSigbus (void)
sigset_t sigset;
sigemptyset (&sigset);
+ sigaddset (&sigset, SIGBUS);
- if (sigprocmask (SIG_BLOCK, &sigset, NULL))
+ if (sigprocmask (SIG_UNBLOCK, &sigset, NULL))
{
perror ("sigprocmask");
abort ();
@@ -822,3 +823,37 @@ XLRemoveBusfault (void *data)
RemoveBusfault (&busfault_tree, data);
UnblockSigbus ();
}
+
+Bool
+XLAddFdFlag (int fd, int flag, Bool abort_on_error)
+{
+ int flags, rc;
+
+ flags = fcntl (fd, F_GETFD);
+
+ if (flags < 0)
+ {
+ if (abort_on_error)
+ {
+ perror ("fcntl");
+ abort ();
+ }
+ else
+ return False;
+ }
+
+ rc = fcntl (fd, F_SETFD, flags | flag);
+
+ if (rc < 0)
+ {
+ if (abort_on_error)
+ {
+ perror ("fcntl");
+ abort ();
+ }
+ else
+ return False;
+ }
+
+ return True;
+}
diff --git a/picture_renderer.c b/picture_renderer.c
index 646c17c..de01d63 100644
--- a/picture_renderer.c
+++ b/picture_renderer.c
@@ -1746,6 +1746,8 @@ GetRenderDevice (Bool *error)
fd = fds[0];
+ XLAddFdFlag (fd, FD_CLOEXEC, True);
+
if (fstat (fd, &dev_stat) != 0)
{
close (fd);
diff --git a/run.c b/run.c
index 7279200..60ee082 100644
--- a/run.c
+++ b/run.c
@@ -272,7 +272,7 @@ RunStep (void)
wl_display_flush_clients (compositor.wl_display);
}
- rc = ppoll (fds, 2 + i, &timeout, NULL);
+ rc = ProcessPoll (fds, 2 + i, &timeout);
if (rc > 0)
{
diff --git a/seat.c b/seat.c
index 26f9040..e0c7f95 100644
--- a/seat.c
+++ b/seat.c
@@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
along with 12to11. If not, see . */
#include
+#include
#include
#include
@@ -4346,6 +4347,7 @@ WriteKeymap (void)
FILE *file;
XkbFileInfo result;
Bool ok;
+ int fd;
if (keymap_fd != -1)
close (keymap_fd);
@@ -4362,7 +4364,15 @@ WriteKeymap (void)
result.type = XkmKeymapFile;
result.xkb = xkb_desc;
- file = fdopen (dup (keymap_fd), "w");
+ fd = fcntl (keymap_fd, F_DUPFD_CLOEXEC, 0);
+
+ if (fd < 0)
+ {
+ perror ("fcntl");
+ exit (1);
+ }
+
+ file = fdopen (fd, "w");
if (!file)
{
diff --git a/surface.c b/surface.c
index 88a0676..86ad9bc 100644
--- a/surface.c
+++ b/surface.c
@@ -1752,6 +1752,25 @@ XLSurfaceNoteFocus (Surface *surface, FocusMode focus)
if (!surface->role || !surface->role->funcs.note_focus)
return;
+ switch (focus)
+ {
+ case SurfaceFocusIn:
+ surface->num_focused_seats++;
+
+ /* Check for idle inhibition. */
+ XLIdleInhibitNoticeSurfaceFocused (surface);
+ break;
+
+ case SurfaceFocusOut:
+ surface->num_focused_seats
+ = MAX (0, surface->num_focused_seats - 1);
+
+ if (!surface->num_focused_seats)
+ /* Check if any idle inhibitors are still active. */
+ XLDetectSurfaceIdleInhibit ();
+ break;
+ }
+
surface->role->funcs.note_focus (surface, surface->role,
focus);
}