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); }