.gear/rules | 2 +
.gear/tags/list | 1 +
meson.build | 9 +++
proto/wayfire-shell.xml | 130 ++++++++++++++++++++--------------------
src/background/background.cpp | 5 +-
src/dock/dock-app.cpp | 2 +
src/dock/dock.cpp | 2 +-
src/dock/toplevel-icon.cpp | 58 ++++++++++++++++--
src/dock/toplevel-icon.hpp | 8 +++
src/panel/panel.cpp | 2 +-
src/panel/widgets/launchers.cpp | 9 +--
src/util/gtk-utils.cpp | 12 ++++
src/util/gtk-utils.hpp | 3 +
src/util/wf-autohide-window.cpp | 5 +-
src/util/wf-autohide-window.hpp | 2 +-
src/util/wf-shell-app.cpp | 13 +++-
wf-shell.ini.example | 4 ++
wf-shell.spec | 44 ++++++++++++++
18 files changed, 225 insertions(+), 86 deletions(-)
diff --git a/.gear/rules b/.gear/rules
new file mode 100644
index 0000000..4fcfd99
--- /dev/null
+++ b/.gear/rules
@@ -0,0 +1,2 @@
+tar: @version@:.
+diff: @version@:. .
diff --git a/.gear/tags/list b/.gear/tags/list
new file mode 100644
index 0000000..91a3d88
--- /dev/null
+++ b/.gear/tags/list
@@ -0,0 +1 @@
+4cb058da549e425edf71c534298682bb5b30ce24 0.1
diff --git a/meson.build b/meson.build
index 344aba0..35a41df 100644
--- a/meson.build
+++ b/meson.build
@@ -10,6 +10,7 @@ project(
'c_std=c11',
'warning_level=2',
'werror=false',
+ 'sysconfdir=/etc',
],
)
@@ -18,10 +19,18 @@ wayland_protos = dependency('wayland-protocols')
gtkmm = dependency('gtkmm-3.0')
wfconfig = dependency('wf-config') #TODO fallback submodule
+prefixdir=get_option('prefix')
+sysconfdir=join_paths(prefixdir, get_option('sysconfdir'))
+conf_data = configuration_data()
+conf_data.set('SYSCONFDIR', get_option('sysconfdir'))
+install_data('wf-shell.ini.example', rename: 'wf-shell.ini',
+ install_dir: join_paths(sysconfdir, 'wf-shell'))
+
add_project_arguments(['-Wno-pedantic', '-Wno-unused-parameter', '-Wno-parentheses', '-Wno-cast-function-type'], language: 'cpp')
icon_dir = join_paths(get_option('prefix'), 'share', 'wayfire', 'icons')
add_global_arguments('-DICONDIR="' + icon_dir + '"', language : 'cpp')
+add_global_arguments('-DSYSCONFDIR="' + get_option('sysconfdir') + '"', language : 'cpp')
subdir('proto')
subdir('data')
diff --git a/proto/wayfire-shell.xml b/proto/wayfire-shell.xml
index 6709e28..d1d4f82 100644
--- a/proto/wayfire-shell.xml
+++ b/proto/wayfire-shell.xml
@@ -18,6 +18,65 @@
+
+
+
+ Assign the given role to the given surface and add it to the
+ given output. A client can specify a null output, in which case
+ the compositor will assign the surface to the focused output,
+ if any such output.
+
+ The role cannot be changed later, and neither can the surface be
+ moved to a different output, except by the compositor.
+
+
+
+
+
+
+
+
+
+
+
+ Represents a single output.
+ Each output is managed independently from the others.
+
+
+
+ Panels are always rendered on top, even above fullscreen windows.
+ If autohide is 1, the event indicates that the panels should hide
+ itself, by for example unmapping or sliding outside of the output.
+ If autohide is 0, this means that the reason for the last request
+ with autohide == 1 is no longer valid, i.e the panels can show
+ themselves.
+
+ The output_hide_panels can be called multiple times with
+ autohide = 1, and the panel should show itself only when
+ it has received a matching number of events with autohide = 0
+
+
+
+
+
+
+
+ Request the compositor to not render the output, so
+ the output usually is cleared to black color.
+ To enable output rendering again, call inhibit_output_done
+
+
+
+
+
+ Stop inhibiting the output. This must be called as many times
+ as inhibit_output was called to actually uninhibit rendering.
+
+ The inhibit/inhibit_done requests can be called multiple times,
+ even from different apps, so don't assume that a call to
+ inhibit_done would always mean actually starting the rendering process.
+
+
@@ -26,6 +85,13 @@
It belongs to the output which it was created for.
+
+
+
+
+
+
+
@@ -99,68 +165,4 @@
-
-
-
- Represents a single output.
- Each output is managed independently from the others.
-
-
-
-
-
-
-
-
-
-
-
- Assign the given role to the given surface
- and add it to the current output.
-
- The role cannot be changed later, and neither
- can it be moved to a different output.
-
-
-
-
-
-
-
-
-
- Panels are always rendered on top, even above fullscreen windows.
- If autohide is 1, the event indicates that the panels should hide
- itself, by for example unmapping or sliding outside of the output.
- If autohide is 0, this means that the reason for the last request
- with autohide == 1 is no longer valid, i.e the panels can show
- themselves.
-
- The output_hide_panels can be called multiple times with
- autohide = 1, and the panel should show itself only when
- it has received a matching number of events with autohide = 0
-
-
-
-
-
-
-
- Request the compositor to not render the output, so
- the output usually is cleared to black color.
- To enable output rendering again, call inhibit_output_done
-
-
-
-
-
- Stop inhibiting the output. This must be called as many times
- as inhibit_output was called to actually uninhibit rendering.
-
- The inhibit/inhibit_done requests can be called multiple times,
- even from different apps, so don't assume that a call to
- inhibit_done would always mean actually starting the rendering process.
-
-
-
diff --git a/src/background/background.cpp b/src/background/background.cpp
index 782f5bf..ea60183 100644
--- a/src/background/background.cpp
+++ b/src/background/background.cpp
@@ -32,8 +32,9 @@ class WayfireBackground
std::exit(-1);
}
- wm_surface = zwf_output_v1_get_wm_surface(output->zwf, surface,
- ZWF_OUTPUT_V1_WM_ROLE_BACKGROUND);
+ wm_surface = zwf_shell_manager_v1_get_wm_surface(
+ output->display->zwf_shell_manager, surface,
+ ZWF_WM_SURFACE_V1_ROLE_BACKGROUND, output->handle);
zwf_wm_surface_v1_configure(wm_surface, 0, 0);
}
diff --git a/src/dock/dock-app.cpp b/src/dock/dock-app.cpp
index fef6c5b..17f9429 100644
--- a/src/dock/dock-app.cpp
+++ b/src/dock/dock-app.cpp
@@ -1,5 +1,6 @@
#include "dock.hpp"
#include "toplevel.hpp"
+#include "toplevel-icon.hpp"
#include
#include
@@ -46,6 +47,7 @@ class WfDockApp::impl : public WayfireShellApp
void on_activate() override
{
WayfireShellApp::on_activate();
+ IconProvider::load_custom_icons(this->config->get_section("dock"));
/* At this point, wayland connection has been initialized,
* and hopefully outputs have been created */
diff --git a/src/dock/dock.cpp b/src/dock/dock.cpp
index 4cdd6fa..40a2796 100644
--- a/src/dock/dock.cpp
+++ b/src/dock/dock.cpp
@@ -27,7 +27,7 @@ class WfDock::impl
this->output = output;
window = std::unique_ptr (
new WayfireAutohidingWindow(100, 100, output,
- ZWF_OUTPUT_V1_WM_ROLE_PANEL));
+ ZWF_WM_SURFACE_V1_ROLE_PANEL));
window->set_keyboard_mode(ZWF_WM_SURFACE_V1_KEYBOARD_FOCUS_MODE_NO_FOCUS);
window->increase_autohide();
diff --git a/src/dock/toplevel-icon.cpp b/src/dock/toplevel-icon.cpp
index 28cb1a4..63c6b79 100644
--- a/src/dock/toplevel-icon.cpp
+++ b/src/dock/toplevel-icon.cpp
@@ -119,7 +119,15 @@ class WfToplevelIcon::impl
void set_state(uint32_t state)
{
+ bool was_activated = this->state & WF_TOPLEVEL_STATE_ACTIVATED;
this->state = state;
+ bool is_activated = this->state & WF_TOPLEVEL_STATE_ACTIVATED;
+
+ if (!was_activated && is_activated) {
+ this->button.get_style_context()->remove_class("flat");
+ } else if (was_activated && !is_activated) {
+ this->button.get_style_context()->add_class("flat");
+ }
}
~impl()
@@ -151,6 +159,34 @@ namespace IconProvider
c = std::tolower(c);
return str;
}
+
+ std::map custom_icons;
+ }
+
+ void load_custom_icons(wayfire_config_section *section)
+ {
+ static const std::string prefix = "icon_mapping_";
+ for (auto option : section->options)
+ {
+ if (option->name.compare(0, prefix.length(), prefix) != 0)
+ continue;
+
+ auto app_id = option->name.substr(prefix.length());
+ custom_icons[app_id] = option->as_string();
+ }
+ }
+
+ bool set_custom_icon(Gtk::Image& image, std::string app_id, int size, int scale)
+ {
+ if (!custom_icons.count(app_id))
+ return false;
+
+ auto pb = load_icon_pixbuf_safe(custom_icons[app_id], size * scale);
+ if (!pb.get())
+ return false;
+
+ set_image_pixbuf(image, pb, scale);
+ return true;
}
/* Gio::DesktopAppInfo
@@ -201,26 +237,32 @@ namespace IconProvider
return Icon{};
}
- /* Second method: Just look up the built-in icon theme,
- * perhaps some icon can be found there */
-
void set_image_from_icon(Gtk::Image& image,
std::string app_id_list, int size, int scale)
{
std::string app_id;
std::istringstream stream(app_id_list);
+ bool found_icon = false;
+
/* Wayfire sends a list of app-id's in space separated format, other compositors
* send a single app-id, but in any case this works fine */
while (stream >> app_id)
{
+ /* Try first method: custom icon file provided by the user */
+ if (set_custom_icon(image, app_id, size, scale))
+ {
+ found_icon = true;
+ break;
+ }
+
+ /* Then try to load the DesktopAppInfo */
auto icon = get_from_desktop_app_info(app_id);
std::string icon_name = "unknown";
if (!icon)
{
- /* Perhaps no desktop app info, but we might still be able to
- * get an icon directly from the icon theme */
+ /* Finally try directly looking up the icon, if it exists */
if (Gtk::IconTheme::get_default()->lookup_icon(app_id, 24))
icon_name = app_id;
} else
@@ -234,7 +276,13 @@ namespace IconProvider
/* finally found some icon */
if (icon_name != "unknown")
+ {
+ found_icon = true;
break;
+ }
}
+
+ if (!found_icon)
+ std::cout << "Failed to load icon for any of " << app_id_list << std::endl;
}
};
diff --git a/src/dock/toplevel-icon.hpp b/src/dock/toplevel-icon.hpp
index 25b5f03..186aa01 100644
--- a/src/dock/toplevel-icon.hpp
+++ b/src/dock/toplevel-icon.hpp
@@ -2,6 +2,7 @@
#define WF_DOCK_TOPLEVEL_ICON_HPP
#include "display.hpp"
+#include "config.hpp"
#include
#include
@@ -19,4 +20,11 @@ class WfToplevelIcon
std::unique_ptr pimpl;
};
+namespace IconProvider
+{
+ /* Loads custom app_id -> icon file mappings from the section
+ * They have the format icon_mapping_ = */
+ void load_custom_icons(wayfire_config_section *section);
+}
+
#endif /* end of include guard: WF_DOCK_TOPLEVEL_ICON_HPP */
diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp
index 5ffd4d3..9d92f57 100644
--- a/src/panel/panel.cpp
+++ b/src/panel/panel.cpp
@@ -132,7 +132,7 @@ class WayfirePanel
this->current_output_width,
minimal_panel_height->as_int(),
this->output,
- ZWF_OUTPUT_V1_WM_ROLE_OVERLAY));
+ ZWF_WM_SURFACE_V1_ROLE_OVERLAY));
bg_color = config_section->get_option("background_color", "gtk_headerbar");
bg_color->add_updated_handler(&on_window_color_updated);
diff --git a/src/panel/widgets/launchers.cpp b/src/panel/widgets/launchers.cpp
index 641da1b..9d7d985 100644
--- a/src/panel/widgets/launchers.cpp
+++ b/src/panel/widgets/launchers.cpp
@@ -68,14 +68,7 @@ struct FileLauncherInfo : public LauncherInfo
command = name;
this->icon = icon;
- try {
- // check if file is loadable
- Gdk::Pixbuf::create_from_file(icon, 24, 24);
- } catch(...) {
- return false;
- }
-
- return true;
+ return load_icon_pixbuf_safe(icon, 24).get() != nullptr;
}
Glib::RefPtr get_pixbuf(int32_t size)
diff --git a/src/util/gtk-utils.cpp b/src/util/gtk-utils.cpp
index 3d947c6..248a4a6 100644
--- a/src/util/gtk-utils.cpp
+++ b/src/util/gtk-utils.cpp
@@ -3,6 +3,18 @@
#include
#include
+Glib::RefPtr load_icon_pixbuf_safe(std::string icon_path, int size)
+{
+ try
+ {
+ auto pb = Gdk::Pixbuf::create_from_file(icon_path, size, size);
+ return pb;
+ } catch(...)
+ {
+ return {};
+ }
+}
+
void invert_pixbuf(Glib::RefPtr& pbuff)
{
int channels = pbuff->get_n_channels();
diff --git a/src/util/gtk-utils.hpp b/src/util/gtk-utils.hpp
index ecfb448..0878957 100644
--- a/src/util/gtk-utils.hpp
+++ b/src/util/gtk-utils.hpp
@@ -4,6 +4,9 @@
#include
#include
+/* Loads a pixbuf with the given size from the given file, returns null if unsuccessful */
+Glib::RefPtr load_icon_pixbuf_safe(std::string icon_path, int size);
+
struct WfIconLoadOptions
{
int user_scale = -1;
diff --git a/src/util/wf-autohide-window.cpp b/src/util/wf-autohide-window.cpp
index 2c61874..417da30 100644
--- a/src/util/wf-autohide-window.cpp
+++ b/src/util/wf-autohide-window.cpp
@@ -5,7 +5,7 @@
#include
WayfireAutohidingWindow::WayfireAutohidingWindow(int width, int height,
- WayfireOutput *output, zwf_output_v1_wm_role role)
+ WayfireOutput *output, zwf_wm_surface_v1_role role)
{
this->set_size_request(width, height);
this->set_decorated(false);
@@ -22,7 +22,8 @@ WayfireAutohidingWindow::WayfireAutohidingWindow(int width, int height,
std::exit(-1);
}
- wm_surface = zwf_output_v1_get_wm_surface(output->zwf, surface, role);
+ wm_surface = zwf_shell_manager_v1_get_wm_surface(
+ output->display->zwf_shell_manager, surface, role, output->handle);
this->m_position_changed = [=] () {this->update_position();};
this->signal_draw().connect_notify(
diff --git a/src/util/wf-autohide-window.hpp b/src/util/wf-autohide-window.hpp
index d683dc8..218bb04 100644
--- a/src/util/wf-autohide-window.hpp
+++ b/src/util/wf-autohide-window.hpp
@@ -42,7 +42,7 @@ class WayfireAutohidingWindow : public Gtk::Window
public:
WayfireAutohidingWindow(int width, int height,
- WayfireOutput *output, zwf_output_v1_wm_role role);
+ WayfireOutput *output, zwf_wm_surface_v1_role role);
zwf_wm_surface_v1* get_wm_surface() const;
/* Sets the edge of the screen where the window is */
diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp
index 948cc23..85e31aa 100644
--- a/src/util/wf-shell-app.cpp
+++ b/src/util/wf-shell-app.cpp
@@ -6,8 +6,17 @@
std::string WayfireShellApp::get_config_file()
{
- std::string home_dir = getenv("HOME");
- std::string config_file = home_dir + "/.config/wf-shell.ini";
+ const char *config_basename = "wf-shell.ini";
+
+ std::string config_dir = getenv("XDG_CONFIG_DIR") ? :
+ (std::string(getenv("HOME") ? : "") + "./config");
+ std::string config_file = config_dir + "/" + config_basename;
+
+ /* use system-wide config file if local is not accessible */
+ /* FIXME: there can be a race */
+ if (access(config_file.c_str(), F_OK) == -1)
+ std::string(SYSCONFDIR "/wf-shell/") + config_basename;
+
return config_file;
}
diff --git a/wf-shell.ini.example b/wf-shell.ini.example
index 0d2b778..5a1c3ad 100644
--- a/wf-shell.ini.example
+++ b/wf-shell.ini.example
@@ -103,3 +103,7 @@ menu_fuzzy_search = 1
[dock]
position = bottom # or top
+
+# For applications that aren't installed/configured properly, you can manually
+# set icons for given app_id's. Below is an example for IntelliJ IDEA
+icon_mapping_jetbrains-idea-ce = //idea.png
diff --git a/wf-shell.spec b/wf-shell.spec
new file mode 100644
index 0000000..f4f18bd
--- /dev/null
+++ b/wf-shell.spec
@@ -0,0 +1,44 @@
+Name: wf-shell
+Version: 0.1
+Release: alt1
+
+Summary: A panel for the Wayfire compositor
+
+License: MIT
+Group: Graphical desktop/Other
+Url: https://github.com/WayfireWM/wf-shell
+
+Source: %name-%version.tar
+Patch1: %name-%version-%release.patch
+
+# Automatically added by buildreq on Sun Mar 17 2019
+# optimized out: at-spi2-atk fontconfig fontconfig-devel glib2-devel glibc-kernheaders-generic glibc-kernheaders-x86 libat-spi2-core libatk-devel libatkmm-devel libcairo-devel libcairo-gobject libcairo-gobject-devel libcairomm-devel libfreetype-devel libgdk-pixbuf libgdk-pixbuf-devel libgio-devel libglibmm-devel libgpg-error libgtk+3-devel libpango-devel libpangomm-devel libsigc++2-devel libstdc++-devel libwayland-client libwayland-client-devel libwayland-cursor libwayland-egl libwf-config ninja-build pkg-config python-base python-modules python3 python3-base python3-module-pkg_resources sh4 wayland-devel xz
+BuildRequires: gcc-c++ libgtkmm3-devel libwf-config-devel meson wayland-protocols
+
+%description
+%summary.
+
+%prep
+%setup
+%patch1 -p1
+
+%build
+%meson
+%meson_build
+
+%install
+%meson_install
+
+%check
+%meson_test
+
+%files
+%config(noreplace) %_sysconfdir/%name/%name.ini
+%_bindir/*
+%_datadir/wayfire
+
+%changelog
+* Fri Mar 15 2019 Vladimir D. Seleznev 0.1-alt1
+- Initial build for Sisyphus.
+
+