From 3489496418532c495e613a4c59df86d660c72f8b Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Sat, 8 Mar 2014 09:42:38 +0100 Subject: [PATCH] server: Move screen saver code to a class Issue: #131 --- src/server/CMakeLists.txt | 1 + src/server/wl_hawaii/desktop-shell.cpp | 155 +++------------------ src/server/wl_hawaii/desktop-shell.h | 40 +----- src/server/wl_hawaii/screensaver.cpp | 184 +++++++++++++++++++++++++ src/server/wl_hawaii/screensaver.h | 77 +++++++++++ 5 files changed, 286 insertions(+), 171 deletions(-) create mode 100644 src/server/wl_hawaii/screensaver.cpp create mode 100644 src/server/wl_hawaii/screensaver.h diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 39b604e1..d737cf6a 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -39,6 +39,7 @@ set(SOURCES wl_hawaii/hawaiiworkspace.cpp wl_hawaii/panelmanager.cpp wl_hawaii/panelsurface.cpp + wl_hawaii/screensaver.cpp wl_hawaii/shellwindow.cpp wl_shell/wlshell.cpp wl_shell/wlshellsurface.cpp diff --git a/src/server/wl_hawaii/desktop-shell.cpp b/src/server/wl_hawaii/desktop-shell.cpp index 7ef5c99d..33b9fe6d 100644 --- a/src/server/wl_hawaii/desktop-shell.cpp +++ b/src/server/wl_hawaii/desktop-shell.cpp @@ -35,7 +35,6 @@ #include "desktop-shell.h" #include "wayland-hawaii-server-protocol.h" #include "wayland-notification-daemon-server-protocol.h" -#include "wayland-screensaver-server-protocol.h" #include "shellsurface.h" #include "binding.h" #include "inputpanel.h" @@ -52,6 +51,7 @@ #include "wl_hawaii/hawaiiclientwindow.h" #include "wl_hawaii/hawaiiworkspace.h" #include "wl_hawaii/panelmanager.h" +#include "wl_hawaii/screensaver.h" #include "wl_hawaii/shellwindow.h" #include @@ -277,10 +277,6 @@ DesktopShell::DesktopShell(struct weston_compositor *ec) , m_inputPanel(nullptr) , m_splash(nullptr) , m_sessionManager(nullptr) - , m_screenSaverBinding(nullptr) - , m_screenSaverEnabled(false) - , m_screenSaverPath(INSTALL_LIBEXECDIR "/hawaii-screensaver") - , m_screenSaverDuration(5*60*1000) , m_panelManagerBinding(nullptr) , m_notificationsEdge(DesktopShell::EdgeRight) , m_notificationsCornerAnchor(DesktopShell::CornerTopRight) @@ -290,8 +286,6 @@ DesktopShell::DesktopShell(struct weston_compositor *ec) , m_locked(false) , m_lockSurface(nullptr) { - m_screenSaverChild.shell = this; - m_screenSaverChild.process.pid = 0; } DesktopShell::~DesktopShell() @@ -333,10 +327,6 @@ void DesktopShell::init() [](struct wl_client *client, void *data, uint32_t version, uint32_t id) { static_cast(data)->bindNotifications(client, version, id); })) return; - if (!wl_global_create(compositor()->wl_display, &wl_screensaver_interface, 1, this, - [](struct wl_client *client, void *data, uint32_t version, uint32_t id) { static_cast(data)->bindScreenSaver(client, version, id); })) - return; - if (!wl_global_create(compositor()->wl_display, &wl_hawaii_shell_surface_interface, 1, this, [](struct wl_client *client, void *data, uint32_t version, uint32_t id) { static_cast(data)->bindDesktopShellSurface(client, version, id); })) return; @@ -351,10 +341,6 @@ void DesktopShell::init() m_wakeListener.listen(&compositor()->wake_signal); m_wakeListener.signal->connect(this, &DesktopShell::wake); - struct wl_event_loop *loop = wl_display_get_event_loop(compositor()->wl_display); - m_screenSaverTimer = wl_event_loop_add_timer(loop, [](void *data) { - return static_cast(data)->screenSaverTimeout(); }, this); - m_moveBinding = new Binding(); m_moveBinding->buttonTriggered.connect(this, &DesktopShell::moveBinding); m_resizeBinding = new Binding(); @@ -374,6 +360,7 @@ void DesktopShell::init() Shell::quit(); }); + addInterface(new ScreenSaver); addInterface(new PanelManager); WlShell *wls = new WlShell; wls->surfaceResponsivenessChangedSignal.connect(this, &DesktopShell::surfaceResponsivenessChanged); @@ -433,7 +420,8 @@ void DesktopShell::lockSession() // TODO: Disable bindings that are not supposed to work while locked // Run screensaver or sleep - launchScreenSaverProcess(); + ScreenSaver *screenSaver = findInterface(); + screenSaver->launchProcess(); // All this must be undone in resumeDesktop() } @@ -464,7 +452,8 @@ void DesktopShell::unlockSession() void DesktopShell::resumeDesktop() { - terminateScreenSaverProcess(); + ScreenSaver *screenSaver = findInterface(); + screenSaver->terminateProcess(); // Restore layers order m_lockLayer.insert(&compositor()->cursor_layer); @@ -569,6 +558,11 @@ void DesktopShell::addPanelSurfaceToLayer(weston_view *view) configure_static_view_no_position(view, &m_panelsLayer); } +void DesktopShell::prependViewToLockLayer(weston_view *view) +{ + m_lockLayer.prependSurface(view); +} + IRect2D DesktopShell::windowsArea(struct weston_output *output) const { for (Output o: m_outputs) { @@ -620,6 +614,14 @@ void DesktopShell::recalculateAvailableGeometry() } } +void DesktopShell::centerSurfaceOnOutput(weston_view *ev, weston_output *output) +{ + float x = output->x + (output->width - ev->surface->width) / 2; + float y = output->y + (output->height - ev->surface->height) / 2; + + weston_view_set_position(ev, x, y); +} + void DesktopShell::trustedClientDestroyed(void *data) { wl_client *client = static_cast(data); @@ -676,14 +678,6 @@ void DesktopShell::sendInitEvents() } } -void DesktopShell::centerSurfaceOnOutput(weston_view *ev, weston_output *output) -{ - float x = output->x + (output->width - ev->surface->width) / 2; - float y = output->y + (output->height - ev->surface->height) / 2; - - weston_view_set_position(ev, x, y); -} - void DesktopShell::workspaceAdded(HawaiiWorkspace *ws) { wl_hawaii_shell_send_workspace_added(m_child.desktop_shell, ws->resource(), ws->workspace()->isActive()); @@ -759,26 +753,6 @@ void DesktopShell::unbindDesktopShellSurface(struct wl_resource *resource) m_shellSurfaceBindings.remove(resource); } -void DesktopShell::bindScreenSaver(wl_client *client, uint32_t version, uint32_t id) -{ - struct wl_resource *resource = wl_resource_create(client, &wl_screensaver_interface, version, id); - - if (!m_screenSaverBinding) { - wl_resource_set_implementation(resource, &m_screenSaverImpl, this, - [](struct wl_resource *resource) { static_cast(resource->data)->unbindScreenSaver(resource); }); - m_screenSaverBinding = resource; - return; - } - - wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "permission to bind wl_notification_daemon denied"); - wl_resource_destroy(resource); -} - -void DesktopShell::unbindScreenSaver(struct wl_resource *resource) -{ - m_screenSaverBinding = nullptr; -} - void DesktopShell::moveBinding(struct weston_seat *seat, uint32_t time, uint32_t button) { weston_view *view = seat->pointer->focus; @@ -1493,97 +1467,6 @@ const struct wl_notification_daemon_interface DesktopShell::m_notificationDaemon wrapInterface(&DesktopShell::addNotificationSurface) }; -int DesktopShell::screenSaverTimeout() -{ - weston_log("screensaver timeout...\n"); - fadeOut(); - return 1; -} - -void DesktopShell::screenSaverSigChild(int status) -{ - m_screenSaverChild.process.pid = 0; - m_screenSaverChild.client = nullptr; // already destroyed by wayland - - if (m_locked) - weston_compositor_sleep(compositor()); -} - -void DesktopShell::launchScreenSaverProcess() -{ - if (m_screenSaverBinding) - return; - - if (m_screenSaverPath.empty() || !m_screenSaverEnabled) { - weston_compositor_sleep(compositor()); - return; - } - - if (m_screenSaverChild.process.pid != 0) { - weston_log("old screensaver still running\n"); - return; - } - - m_screenSaverChild.client = weston_client_launch(compositor(), - &m_screenSaverChild.process, - m_screenSaverPath.c_str(), - [](struct weston_process *process, int status) { - ScreenSaverChild *child = container_of(process, ScreenSaverChild, process); - child->shell->screenSaverSigChild(status); - }); - - if (!m_screenSaverChild.client) - weston_log("not able to start %s\n", m_screenSaverPath.c_str()); -} - -void DesktopShell::terminateScreenSaverProcess() -{ - if (m_screenSaverChild.process.pid == 0) - return; - - ::kill(m_screenSaverChild.process.pid, SIGTERM); -} - -void DesktopShell::screenSaverConfigure(weston_surface *es, int32_t sx, int32_t sy) -{ - // Starting screensaver beforehand doesn't work - if (!m_locked) - return; - - weston_view *view = container_of(es->views.next, weston_view, surface_link); - - centerSurfaceOnOutput(view, es->output); - - if (wl_list_empty(&view->layer_link)) { - m_lockLayer.prependSurface(view); - weston_view_update_transform(view); - wl_event_source_timer_update(m_screenSaverTimer, m_screenSaverDuration); - fadeIn(); - } -} - -void DesktopShell::setScreenSaverSurface(wl_client *client, wl_resource *resource, - wl_resource *output_resource, - wl_resource *surface_resource) -{ - struct weston_output *output = static_cast(output_resource->data); - struct weston_surface *surface = static_cast(surface_resource->data); - - weston_view *view, *next; - wl_list_for_each_safe(view, next, &surface->views, surface_link) - weston_view_destroy(view); - view = weston_view_create(surface); - - surface->configure = [](struct weston_surface *es, int32_t sx, int32_t sy) { - static_cast(es->configure_private)->screenSaverConfigure(es, sx, sy); }; - surface->configure_private = this; - surface->output = output; -} - -const struct wl_screensaver_interface DesktopShell::m_screenSaverImpl = { - wrapInterface(&DesktopShell::setScreenSaverSurface) -}; - WL_EXPORT int module_init(struct weston_compositor *ec, int *argc, char *argv[]) { diff --git a/src/server/wl_hawaii/desktop-shell.h b/src/server/wl_hawaii/desktop-shell.h index 68ab3925..81030555 100644 --- a/src/server/wl_hawaii/desktop-shell.h +++ b/src/server/wl_hawaii/desktop-shell.h @@ -71,6 +71,8 @@ class DesktopShell : public Shell { weston_view *createBlackSurfaceWithInput(int x, int y, int w, int h, float a); + bool isLocked() const { return m_locked; } + void fadeIn(); void fadeOut(); @@ -81,11 +83,14 @@ class DesktopShell : public Shell { bool isTrusted(wl_client *client, const char *interface) const override; void addPanelSurfaceToLayer(weston_view *view); + void prependViewToLockLayer(weston_view *view); virtual IRect2D windowsArea(struct weston_output *output) const; void recalculateAvailableGeometry(); + void centerSurfaceOnOutput(weston_view *ev, weston_output *output); + protected: virtual void init(); virtual void setGrabCursor(Cursor cursor); @@ -97,8 +102,6 @@ class DesktopShell : public Shell { void sendInitEvents(); - void centerSurfaceOnOutput(weston_view *ev, weston_output *output); - void workspaceAdded(HawaiiWorkspace *ws); void surfaceResponsivenessChanged(ShellSurface *shsurf, bool responsive); @@ -112,9 +115,6 @@ class DesktopShell : public Shell { void bindDesktopShellSurface(struct wl_client *client, uint32_t version, uint32_t id); void unbindDesktopShellSurface(struct wl_resource *resource); - void bindScreenSaver(wl_client *client, uint32_t version, uint32_t id); - void unbindScreenSaver(wl_resource *resource); - void moveBinding(struct weston_seat *seat, uint32_t time, uint32_t button); void resizeBinding(struct weston_seat *seat, uint32_t time, uint32_t button); void closeBinding(struct weston_seat *seat, uint32_t time, uint32_t button); @@ -188,28 +188,11 @@ class DesktopShell : public Shell { void addNotificationSurface(wl_client *client, wl_resource *resource, wl_resource *surface_resource); - /* - * screensaver - */ - - void screenSaverSigChild(int status); - - void launchScreenSaverProcess(); - void terminateScreenSaverProcess(); - - int screenSaverTimeout(); - - void screenSaverConfigure(weston_surface *es, int32_t sx, int32_t sy); - void setScreenSaverSurface(wl_client *client, wl_resource *resource, - wl_resource *output_resource, - wl_resource *surface_resource); - static void configurePopup(weston_surface *es, int32_t sx, int32_t sy); static const struct wl_hawaii_shell_interface m_desktopShellImpl; static const struct wl_hawaii_shell_surface_interface m_shellSurfaceImpl; static const struct wl_notification_daemon_interface m_notificationDaemonImpl; - static const struct wl_screensaver_interface m_screenSaverImpl; WlListener m_idleListener; WlListener m_wakeListener; @@ -235,19 +218,6 @@ class DesktopShell : public Shell { std::list m_shellSurfaceBindings; - wl_resource *m_screenSaverBinding; - wl_event_source *m_screenSaverTimer; - bool m_screenSaverEnabled; - std::string m_screenSaverPath; - int m_screenSaverDuration; - - struct ScreenSaverChild { - DesktopShell *shell; - struct weston_process process; - struct wl_client *client; - }; - ScreenSaverChild m_screenSaverChild; - wl_resource *m_panelManagerBinding; Edge m_notificationsEdge; diff --git a/src/server/wl_hawaii/screensaver.cpp b/src/server/wl_hawaii/screensaver.cpp new file mode 100644 index 00000000..cc65943a --- /dev/null +++ b/src/server/wl_hawaii/screensaver.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** + * This file is part of Hawaii Shell. + * + * Copyright (C) 2014 Pier Luigi Fiorini + * + * Author(s): + * Pier Luigi Fiorini + * + * $BEGIN_LICENSE:LGPL2.1+$ + * + * 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 . + * + * $END_LICENSE$ + ***************************************************************************/ + +#include "cmakedirs.h" +#include "screensaver.h" +#include "desktop-shell.h" + +#include + +ScreenSaver::ScreenSaver() + : Interface() + , m_binding(nullptr) + , m_enabled(false) + , m_path(INSTALL_LIBEXECDIR "/hawaii-screensaver") + , m_duration(5*60*1000) +{ + m_child.screenSaver = this; + m_child.process.pid = 0; + + wl_global_create(Shell::instance()->compositor()->wl_display, &wl_screensaver_interface, 1, this, + [](wl_client *client, void *data, uint32_t version, uint32_t id) { + static_cast(data)->bind(client, version, id); + }); + + struct wl_event_loop *loop = wl_display_get_event_loop(Shell::instance()->compositor()->wl_display); + m_timer = wl_event_loop_add_timer(loop, [](void *data) { + return static_cast(data)->timeout(); }, this); +} + +void ScreenSaver::launchProcess() +{ + if (m_binding) + return; + + if (m_path.empty() || !m_enabled) { + weston_compositor_sleep(Shell::instance()->compositor()); + return; + } + + if (m_child.process.pid != 0) { + weston_log("old screensaver still running\n"); + return; + } + + m_child.client = weston_client_launch(Shell::instance()->compositor(), + &m_child.process, + m_path.c_str(), + [](struct weston_process *process, int status) { + ScreenSaverChild *child = container_of(process, ScreenSaverChild, process); + child->screenSaver->sigChild(status); + }); + + if (!m_child.client) + weston_log("not able to start %s\n", m_path.c_str()); +} + +void ScreenSaver::terminateProcess() +{ + if (m_child.process.pid == 0) + return; + + ::kill(m_child.process.pid, SIGTERM); +} + +void ScreenSaver::bind(wl_client *client, uint32_t version, uint32_t id) +{ + wl_resource *resource = wl_resource_create(client, &wl_screensaver_interface, version, id); + + if (m_binding) { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "only one client is allowed to bind wl_screensaver"); + wl_resource_destroy(resource); + return; + } + + if (client != Shell::instance()->shellClient()) { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "permission to bind wl_screensaver_interface denied"); + wl_resource_destroy(resource); + return; + } + + wl_resource_set_implementation(resource, &implementation, this, + [](struct wl_resource *resource) { + static_cast(resource->data)->unbind(resource); + }); + + m_binding = resource; +} + +void ScreenSaver::unbind(wl_resource *resource) +{ + if (m_binding == resource) + m_binding = nullptr; + free(resource); +} + +void ScreenSaver::sigChild(int) +{ + DesktopShell *shell = static_cast(Shell::instance()); + + m_child.process.pid = 0; + m_child.client = nullptr; // already destroyed by wayland + + if (shell->isLocked()) + weston_compositor_sleep(Shell::instance()->compositor()); +} + +int ScreenSaver::timeout() +{ + DesktopShell *shell = static_cast(Shell::instance()); + + weston_log("screensaver timeout...\n"); + shell->fadeOut(); + return 1; +} + +void ScreenSaver::configure(weston_surface *es) +{ + DesktopShell *shell = static_cast(Shell::instance()); + + // Starting screensaver beforehand doesn't work + if (!shell->isLocked()) + return; + + weston_view *view = container_of(es->views.next, weston_view, surface_link); + + shell->centerSurfaceOnOutput(view, es->output); + + if (wl_list_empty(&view->layer_link)) { + shell->prependViewToLockLayer(view); + weston_view_update_transform(view); + wl_event_source_timer_update(m_timer, m_duration); + shell->fadeIn(); + } +} + +void ScreenSaver::setSurface(wl_client *client, + wl_resource *resource, + wl_resource *output_resource, + wl_resource *surface_resource) +{ + weston_output *output = static_cast(output_resource->data); + weston_surface *surface = static_cast(surface_resource->data); + + weston_view *view, *next; + wl_list_for_each_safe(view, next, &surface->views, surface_link) + weston_view_destroy(view); + view = weston_view_create(surface); + + surface->configure = [](struct weston_surface *es, int32_t sx, int32_t sy) { + static_cast(es->configure_private)->configure(es); }; + surface->configure_private = this; + surface->output = output; +} + +const struct wl_screensaver_interface ScreenSaver::implementation = { + [](wl_client *client, wl_resource *resource, wl_resource *output_resource, wl_resource *surface_resource) { + static_cast(wl_resource_get_user_data(resource))->setSurface(client, resource, output_resource, surface_resource); + } +}; diff --git a/src/server/wl_hawaii/screensaver.h b/src/server/wl_hawaii/screensaver.h new file mode 100644 index 00000000..d686bc7c --- /dev/null +++ b/src/server/wl_hawaii/screensaver.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * This file is part of Hawaii Shell. + * + * Copyright (C) 2014 Pier Luigi Fiorini + * + * Author(s): + * Pier Luigi Fiorini + * + * $BEGIN_LICENSE:LGPL2.1+$ + * + * 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 . + * + * $END_LICENSE$ + ***************************************************************************/ + +#ifndef SCREENSAVER_H +#define SCREENSAVER_H + +#include "interface.h" +#include "wayland-screensaver-server-protocol.h" + +#include +#include + +#include + +class ScreenSaver : public Interface +{ +public: + ScreenSaver(); + + void launchProcess(); + void terminateProcess(); + +private: + void bind(wl_client *client, uint32_t version, uint32_t id); + void unbind(wl_resource *resource); + + void sigChild(int status); + + int timeout(); + + void configure(weston_surface *es); + void setSurface(wl_client *client, + wl_resource *resource, + wl_resource *output_resource, + wl_resource *surface_resource); + + wl_resource *m_binding; + + wl_event_source *m_timer; + bool m_enabled; + std::string m_path; + int m_duration; + + struct ScreenSaverChild { + ScreenSaver *screenSaver; + struct weston_process process; + struct wl_client *client; + }; + ScreenSaverChild m_child; + + static const struct wl_screensaver_interface implementation; +}; + +#endif // SCREENSAVER_H