diff --git a/README.md b/README.md
index 2ed730d..9d88065 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# gBar
+# gBar
My personal blazingly fast and efficient status bar + widgets, in case anyone finds a use for it.
*gBar: **G**TK **Bar***
@@ -71,7 +71,7 @@ gBar bluetooth [monitor]
## Features / Widgets
Bar:
-- Workspaces (Hyprland only)
+- Workspaces (Hyprland only. Technically works on all compositors implementing ext_workspace, though workspace control relies on Hyprland)
- Time
- Bluetooth (BlueZ only)
- Audio control
diff --git a/flake.nix b/flake.nix
index dffe100..eaae0b2 100644
--- a/flake.nix
+++ b/flake.nix
@@ -24,6 +24,8 @@
];
buildInputs = [
wayland
+ wayland-protocols
+ wayland-scanner
bluez
gtk3
gtk-layer-shell
diff --git a/meson.build b/meson.build
index e6f36df..37adeec 100644
--- a/meson.build
+++ b/meson.build
@@ -1,14 +1,28 @@
project('gBar',
- ['cpp'],
+ ['c', 'cpp'],
version: '0.0.1',
license: 'MIT',
meson_version: '>=0.49.0',
- default_options: ['c_std=c++17',
+ default_options: ['cpp_std=c++17',
'warning_level=3',
'default_library=static',
'buildtype=release'],
)
+# Wayland protocols
+wayland_client = dependency('wayland-client')
+wayland_scanner = find_program('wayland-scanner')
+
+ext_workspace_src = custom_target('generate-ext-workspace-src',
+ input: ['protocols/ext-workspace-unstable-v1.xml'],
+ output: ['ext-workspace-unstable-v1.c'],
+ command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'])
+
+ext_workspace_header = custom_target('generate-ext-workspace-header',
+ input: ['protocols/ext-workspace-unstable-v1.xml'],
+ output: ['ext-workspace-unstable-v1.h'],
+ command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'])
+
gtk = dependency('gtk+-3.0')
gtk_layer_shell = dependency('gtk-layer-shell-0')
@@ -24,8 +38,12 @@ headers = [
]
if get_option('WithHyprland')
- add_global_arguments('-DWITH_HYPRLAND', language: 'cpp')
- headers += 'src/Hyprland.h'
+ add_global_arguments('-DWITH_WORKSPACES', language: 'cpp')
+ headers += 'src/Workspaces.h'
+endif
+if get_option('WithWorkspaces')
+ add_global_arguments('-DWITH_WORKSPACES', language: 'cpp')
+ headers += 'src/Workspaces.h'
endif
if get_option('WithNvidia')
add_global_arguments('-DWITH_NVIDIA', language: 'cpp')
@@ -41,24 +59,30 @@ endif
if get_option('WithSys')
add_global_arguments('-DWITH_SYS', language: 'cpp')
endif
+if get_option('ForceHyprlandIPC')
+ add_global_arguments('-DFORCE_HYPRLAND_IPC', language: 'cpp')
+endif
add_global_arguments('-DUSE_LOGFILE', language: 'cpp')
pulse = dependency('libpulse')
-libgBar = library('gBar',
- ['src/Window.cpp',
- 'src/Widget.cpp',
- 'src/System.cpp',
- 'src/Bar.cpp',
+libgBar = library('gBar',
+ [ ext_workspace_src,
+ ext_workspace_header,
+ 'src/Window.cpp',
+ 'src/Widget.cpp',
+ 'src/System.cpp',
+ 'src/Bar.cpp',
+ 'src/Workspaces.cpp',
'src/AudioFlyin.cpp',
'src/BluetoothDevices.cpp',
'src/Plugin.cpp',
'src/Config.cpp',
'src/CSS.cpp',
- 'src/Log.cpp'
+ 'src/Log.cpp',
],
- dependencies: [gtk, gtk_layer_shell, pulse],
+ dependencies: [gtk, gtk_layer_shell, pulse, wayland_client],
install: true)
pkg = import('pkgconfig')
@@ -66,7 +90,7 @@ pkg.generate(libgBar)
executable(
'gBar',
- ['src/gBar.cpp'],
+ ['src/gBar.cpp'],
dependencies: [gtk],
link_with: libgBar,
install_rpath: '$ORIGIN/',
diff --git a/meson_options.txt b/meson_options.txt
index 43924da..4fc3d44 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,7 +1,10 @@
-option('WithHyprland', type: 'boolean', value : true)
+# Deprecated, use WithWorkspaces instead
+option('WithHyprland', type: 'boolean', value : false)
+option('WithWorkspaces', type: 'boolean', value : true)
option('WithNvidia', type: 'boolean', value : true)
option('WithAMD', type: 'boolean', value : true)
option('WithBlueZ', type: 'boolean', value : true)
+option('ForceHyprlandIPC', type: 'boolean', value : false)
# You shouldn't enable this, unless you know what you are doing!
option('WithSys', type: 'boolean', value : false)
diff --git a/protocols/ext-workspace-unstable-v1.xml b/protocols/ext-workspace-unstable-v1.xml
new file mode 100644
index 0000000..24410b6
--- /dev/null
+++ b/protocols/ext-workspace-unstable-v1.xml
@@ -0,0 +1,306 @@
+
+
+
+ Copyright © 2019 Christopher Billington
+ Copyright © 2020 Ilia Bozhinov
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+
+
+
+
+ Workspaces, also called virtual desktops, are groups of surfaces. A
+ compositor with a concept of workspaces may only show some such groups of
+ surfaces (those of 'active' workspaces) at a time. 'Activating' a
+ workspace is a request for the compositor to display that workspace's
+ surfaces as normal, whereas the compositor may hide or otherwise
+ de-emphasise surfaces that are associated only with 'inactive' workspaces.
+ Workspaces are grouped by which sets of outputs they correspond to, and
+ may contain surfaces only from those outputs. In this way, it is possible
+ for each output to have its own set of workspaces, or for all outputs (or
+ any other arbitrary grouping) to share workspaces. Compositors may
+ optionally conceptually arrange each group of workspaces in an
+ N-dimensional grid.
+
+ The purpose of this protocol is to enable the creation of taskbars and
+ docks by providing them with a list of workspaces and their properties,
+ and allowing them to activate and deactivate workspaces.
+
+ After a client binds the zext_workspace_manager_v1, each workspace will be
+ sent via the workspace event.
+
+
+
+
+ This event is emitted whenever a new workspace group has been created.
+
+ All initial details of the workspace group (workspaces, outputs) will be
+ sent immediately after this event via the corresponding events in
+ zext_workspace_group_handle_v1.
+
+
+
+
+
+
+ The client must send this request after it has finished sending other
+ requests. The compositor must process a series of requests preceding a
+ commit request atomically.
+
+ This allows changes to the workspace properties to be seen as atomic,
+ even if they happen via multiple events, and even if they involve
+ multiple zext_workspace_handle_v1 objects, for example, deactivating one
+ workspace and activating another.
+
+
+
+
+
+ This event is sent after all changes in all workspace groups have been
+ sent.
+
+ This allows changes to one or more zext_workspace_group_handle_v1
+ properties to be seen as atomic, even if they happen via multiple
+ events. In particular, an output moving from one workspace group to
+ another sends an output_enter event and an output_leave event to the two
+ zext_workspace_group_handle_v1 objects in question. The compositor sends
+ the done event only after updating the output information in both
+ workspace groups.
+
+
+
+
+
+ This event indicates that the compositor is done sending events to the
+ zext_workspace_manager_v1. The server will destroy the object
+ immediately after sending this request, so it will become invalid and
+ the client should free any resources associated with it.
+
+
+
+
+
+ Indicates the client no longer wishes to receive events for new
+ workspace groups. However the compositor may emit further workspace
+ events, until the finished event is emitted.
+
+ The client must not send any more requests after this one.
+
+
+
+
+
+
+ A zext_workspace_group_handle_v1 object represents a a workspace group
+ that is assigned a set of outputs and contains a number of workspaces.
+
+ The set of outputs assigned to the workspace group is conveyed to the client via
+ output_enter and output_leave events, and its workspaces are conveyed with
+ workspace events.
+
+ For example, a compositor which has a set of workspaces for each output may
+ advertise a workspace group (and its workspaces) per output, whereas a compositor
+ where a workspace spans all outputs may advertise a single workspace group for all
+ outputs.
+
+
+
+
+ This event is emitted whenever an output is assigned to the workspace
+ group.
+
+
+
+
+
+
+ This event is emitted whenever an output is removed from the workspace
+ group.
+
+
+
+
+
+
+ This event is emitted whenever a new workspace has been created.
+
+ All initial details of the workspace (name, coordinates, state) will
+ be sent immediately after this event via the corresponding events in
+ zext_workspace_handle_v1.
+
+
+
+
+
+
+ This event means the zext_workspace_group_handle_v1 has been destroyed.
+ It is guaranteed there won't be any more events for this
+ zext_workspace_group_handle_v1. The zext_workspace_group_handle_v1 becomes
+ inert so any requests will be ignored except the destroy request.
+
+ The compositor must remove all workspaces belonging to a workspace group
+ before removing the workspace group.
+
+
+
+
+
+ Request that the compositor create a new workspace with the given name.
+
+ There is no guarantee that the compositor will create a new workspace,
+ or that the created workspace will have the provided name.
+
+
+
+
+
+
+ Destroys the zext_workspace_handle_v1 object.
+
+ This request should be called either when the client does not want to
+ use the workspace object any more or after the remove event to finalize
+ the destruction of the object.
+
+
+
+
+
+
+ A zext_workspace_handle_v1 object represents a a workspace that handles a
+ group of surfaces.
+
+ Each workspace has a name, conveyed to the client with the name event; a
+ list of states, conveyed to the client with the state event; and
+ optionally a set of coordinates, conveyed to the client with the
+ coordinates event. The client may request that the compositor activate or
+ deactivate the workspace.
+
+ Each workspace can belong to only a single workspace group.
+ Depepending on the compositor policy, there might be workspaces with
+ the same name in different workspace groups, but these workspaces are still
+ separate (e.g. one of them might be active while the other is not).
+
+
+
+
+ This event is emitted immediately after the zext_workspace_handle_v1 is
+ created and whenever the name of the workspace changes.
+
+
+
+
+
+
+ This event is used to organize workspaces into an N-dimensional grid
+ within a workspace group, and if supported, is emitted immediately after
+ the zext_workspace_handle_v1 is created and whenever the coordinates of
+ the workspace change. Compositors may not send this event if they do not
+ conceptually arrange workspaces in this way. If compositors simply
+ number workspaces, without any geometric interpretation, they may send
+ 1D coordinates, which clients should not interpret as implying any
+ geometry. Sending an empty array means that the compositor no longer
+ orders the workspace geometrically.
+
+ Coordinates have an arbitrary number of dimensions N with an uint32
+ position along each dimension. By convention if N > 1, the first
+ dimension is X, the second Y, the third Z, and so on. The compositor may
+ chose to utilize these events for a more novel workspace layout
+ convention, however. No guarantee is made about the grid being filled or
+ bounded; there may be a workspace at coordinate 1 and another at
+ coordinate 1000 and none in between. Within a workspace group, however,
+ workspaces must have unique coordinates of equal dimensionality.
+
+
+
+
+
+
+ This event is emitted immediately after the zext_workspace_handle_v1 is
+ created and each time the workspace state changes, either because of a
+ compositor action or because of a request in this protocol.
+
+
+
+
+
+
+ The different states that a workspace can have.
+
+
+
+
+
+
+ The workspace is not visible in its workspace group, and clients
+ attempting to visualize the compositor workspace state should not
+ display such workspaces.
+
+
+
+
+
+
+ This event means the zext_workspace_handle_v1 has been destroyed. It is
+ guaranteed there won't be any more events for this
+ zext_workspace_handle_v1. The zext_workspace_handle_v1 becomes inert so
+ any requests will be ignored except the destroy request.
+
+
+
+
+
+ Destroys the zext_workspace_handle_v1 object.
+
+ This request should be called either when the client does not want to
+ use the workspace object any more or after the remove event to finalize
+ the destruction of the object.
+
+
+
+
+
+ Request that this workspace be activated.
+
+ There is no guarantee the workspace will be actually activated, and
+ behaviour may be compositor-dependent. For example, activating a
+ workspace may or may not deactivate all other workspaces in the same
+ group.
+
+
+
+
+
+ Request that this workspace be deactivated.
+
+ There is no guarantee the workspace will be actually deactivated.
+
+
+
+
+
+ Request that this workspace be removed.
+
+ There is no guarantee the workspace will be actually removed.
+
+
+
+
diff --git a/src/Bar.cpp b/src/Bar.cpp
index 9ff871b..01fb2c9 100644
--- a/src/Bar.cpp
+++ b/src/Bar.cpp
@@ -198,7 +198,7 @@ namespace Bar
return TimerResult::Ok;
}
-#ifdef WITH_HYPRLAND
+#ifdef WITH_WORKSPACES
static std::array