Skip to content

Commit

Permalink
Merge pull request WayfireWM#9 from WayfireWM/background-view
Browse files Browse the repository at this point in the history
Add background view plugin
  • Loading branch information
ammen99 committed Mar 21, 2020
2 parents 167de1c + b0a9e4d commit 3eed212
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 0 deletions.
16 changes: 16 additions & 0 deletions metadata/background-view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<wayfire>
<plugin name="background-view">
<_short>Background View</_short>
<category>Desktop</category>
<option name="command" type="string">
<_short>Command</_short>
<default>mpv --loop=inf</default>
</option>
<option name="file" type="string">
<_short>File</_short>
<hint>file</hint>
<default></default>
</option>
</plugin>
</wayfire>
1 change: 1 addition & 0 deletions metadata/meson.build
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
install_data('autorotate-iio.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir'))
install_data('background-view.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir'))
install_data('join-views.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir'))
169 changes: 169 additions & 0 deletions src/background-view.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Moreau
*
* 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 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 <signal.h>
#include <wayfire/core.hpp>
#include <wayfire/view.hpp>
#include <wayfire/plugin.hpp>
#include <wayfire/output.hpp>
#include <wayfire/signal-definitions.hpp>
#include <wayfire/workspace-manager.hpp>
#include <wayfire/output-layout.hpp>

extern "C"
{
#include <wlr/config.h>
#if WLR_HAS_XWAYLAND
#define class class_t
#define static
#include <wlr/xwayland.h>
#undef static
#undef class
#endif
}

struct process
{
nonstd::observer_ptr<wf::view_interface_t> view;
pid_t pid;
};

static std::map<wf::output_t *, struct process> procs;

class wayfire_background_view : public wf::plugin_interface_t
{
const std::string transformer_name = "background-view";
/* The command option should be set to a client like mpv, projectM or
* a single xscreensaver.
*/
wf::option_wrapper_t<std::string> command{"background-view/command"};
/* The file option is for convenience when using wcm. If file is set,
* it will be appended to the command, wrapped in double quotes.
*/
wf::option_wrapper_t<std::string> file{"background-view/file"};

public:
void init() override
{
grab_interface->name = transformer_name;
grab_interface->capabilities = 0;

command.set_callback(option_changed);
file.set_callback(option_changed);

output->connect_signal("map-view", &view_mapped);

option_changed();
}

wf::config::option_base_t::updated_callback_t option_changed = [=] ()
{
if (procs[output].view)
{
procs[output].view->close();
kill(procs[output].pid, SIGINT);
}

procs[output].view = nullptr;
procs[output].pid = wf::get_core().run(std::string(command) + add_arg_if_not_empty(file));
};

wf::signal_connection_t view_mapped{[this] (wf::signal_data_t *data)
{
auto view = get_signaled_view(data);
#if WLR_HAS_XWAYLAND
wlr_surface *wlr_surface = view->get_wlr_surface();
bool is_xwayland_surface = wlr_surface_is_xwayland_surface(wlr_surface);
#endif
/* Get pid for view */
pid_t view_pid;
wl_client_get_credentials(view->get_client(), &view_pid, 0, 0);

for (auto& o : wf::get_core().output_layout->get_outputs())
{
/* This condition attempts to match the pid that we got from run()
* to the client pid. This will not work in all cases. Naturally,
* not every command will spawn a view. This wont work well for gtk
* apps because it has a system where the client will defer to an
* existing instance with the same app-id and have that instance
* spawn a new view but have the same pid, meaning when we compare
* the pids, they wont match unless we happen to be the first to run
* the app. This does work well with clients such as mpv, projectM
* and running xscreensavers directly.
*/
if (procs[o].pid == view_pid
#if WLR_HAS_XWAYLAND
|| (is_xwayland_surface &&
/* For this match to work, the client must set _NET_WM_PID */
procs[o].pid == wlr_xwayland_surface_from_wlr_surface(wlr_surface)->pid)
#endif
)
{
view->set_decoration(nullptr);

/* Move to the respective output */
wf::get_core().move_view_to_output(view, o);

/* A client should be used that can be resized to any size.
* If we set it fullscreen, the screensaver would be inhibited
* so we send a resize request that is the size of the output
*/
view->set_geometry(o->get_relative_geometry());

/* Set it as the background */
o->workspace->add_view(view, wf::LAYER_BACKGROUND);

/* Make it show on all workspaces */
view->role = wf::VIEW_ROLE_DESKTOP_ENVIRONMENT;

procs[o].view = view;

break;
}
}
}};

std::string add_arg_if_not_empty(std::string in)
{
if (!in.empty())
{
return " \"" + in + "\"";
}
else
{
return in;
}
}

void fini() override
{
if (procs[output].view)
{
procs[output].view->close();
kill(procs[output].pid, SIGINT);
}
}
};

DECLARE_WAYFIRE_PLUGIN(wayfire_background_view);
4 changes: 4 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ autorotate = shared_module('autorotate-iio', 'autorotate-iio.cpp',
dependencies: [wayfire, wlroots, wfconfig, giomm],
install: true, install_dir: join_paths(get_option('libdir'), 'wayfire'))

background_view = shared_module('background-view', 'background-view.cpp',
dependencies: [wayfire, wlroots, wfconfig],
install: true, install_dir: join_paths(get_option('libdir'), 'wayfire'))

joinviews = shared_module('join-views', 'join-views.cpp',
dependencies: [wayfire, wlroots, wfconfig],
install: true, install_dir: join_paths(get_option('libdir'), 'wayfire'))
Expand Down

0 comments on commit 3eed212

Please sign in to comment.