mirror of
https://github.com/scorpion-26/gBar.git
synced 2024-11-24 20:22:10 +00:00
Workspaces: Implement ext_workspace protocol
Even though it isn't faster than Hyprland IPC, it still is more flexible and more future proof. Closes https://github.com/scorpion-26/gBar/issues/8
This commit is contained in:
parent
63faae741f
commit
ad92b7c12a
11 changed files with 677 additions and 42 deletions
|
@ -1,4 +1,4 @@
|
||||||
# gBar
|
# gBar
|
||||||
My personal blazingly fast and efficient status bar + widgets, in case anyone finds a use for it.
|
My personal blazingly fast and efficient status bar + widgets, in case anyone finds a use for it.
|
||||||
|
|
||||||
*gBar: **G**TK **Bar***
|
*gBar: **G**TK **Bar***
|
||||||
|
@ -71,7 +71,7 @@ gBar bluetooth [monitor]
|
||||||
|
|
||||||
## Features / Widgets
|
## Features / Widgets
|
||||||
Bar:
|
Bar:
|
||||||
- Workspaces (Hyprland only)
|
- Workspaces (Hyprland only. Technically works on all compositors implementing ext_workspace, though workspace control relies on Hyprland)
|
||||||
- Time
|
- Time
|
||||||
- Bluetooth (BlueZ only)
|
- Bluetooth (BlueZ only)
|
||||||
- Audio control
|
- Audio control
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
];
|
];
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
wayland
|
wayland
|
||||||
|
wayland-protocols
|
||||||
|
wayland-scanner
|
||||||
bluez
|
bluez
|
||||||
gtk3
|
gtk3
|
||||||
gtk-layer-shell
|
gtk-layer-shell
|
||||||
|
|
48
meson.build
48
meson.build
|
@ -1,14 +1,28 @@
|
||||||
project('gBar',
|
project('gBar',
|
||||||
['cpp'],
|
['c', 'cpp'],
|
||||||
version: '0.0.1',
|
version: '0.0.1',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=0.49.0',
|
meson_version: '>=0.49.0',
|
||||||
default_options: ['c_std=c++17',
|
default_options: ['cpp_std=c++17',
|
||||||
'warning_level=3',
|
'warning_level=3',
|
||||||
'default_library=static',
|
'default_library=static',
|
||||||
'buildtype=release'],
|
'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 = dependency('gtk+-3.0')
|
||||||
gtk_layer_shell = dependency('gtk-layer-shell-0')
|
gtk_layer_shell = dependency('gtk-layer-shell-0')
|
||||||
|
|
||||||
|
@ -24,8 +38,12 @@ headers = [
|
||||||
]
|
]
|
||||||
|
|
||||||
if get_option('WithHyprland')
|
if get_option('WithHyprland')
|
||||||
add_global_arguments('-DWITH_HYPRLAND', language: 'cpp')
|
add_global_arguments('-DWITH_WORKSPACES', language: 'cpp')
|
||||||
headers += 'src/Hyprland.h'
|
headers += 'src/Workspaces.h'
|
||||||
|
endif
|
||||||
|
if get_option('WithWorkspaces')
|
||||||
|
add_global_arguments('-DWITH_WORKSPACES', language: 'cpp')
|
||||||
|
headers += 'src/Workspaces.h'
|
||||||
endif
|
endif
|
||||||
if get_option('WithNvidia')
|
if get_option('WithNvidia')
|
||||||
add_global_arguments('-DWITH_NVIDIA', language: 'cpp')
|
add_global_arguments('-DWITH_NVIDIA', language: 'cpp')
|
||||||
|
@ -41,24 +59,30 @@ endif
|
||||||
if get_option('WithSys')
|
if get_option('WithSys')
|
||||||
add_global_arguments('-DWITH_SYS', language: 'cpp')
|
add_global_arguments('-DWITH_SYS', language: 'cpp')
|
||||||
endif
|
endif
|
||||||
|
if get_option('ForceHyprlandIPC')
|
||||||
|
add_global_arguments('-DFORCE_HYPRLAND_IPC', language: 'cpp')
|
||||||
|
endif
|
||||||
|
|
||||||
add_global_arguments('-DUSE_LOGFILE', language: 'cpp')
|
add_global_arguments('-DUSE_LOGFILE', language: 'cpp')
|
||||||
|
|
||||||
pulse = dependency('libpulse')
|
pulse = dependency('libpulse')
|
||||||
|
|
||||||
libgBar = library('gBar',
|
libgBar = library('gBar',
|
||||||
['src/Window.cpp',
|
[ ext_workspace_src,
|
||||||
'src/Widget.cpp',
|
ext_workspace_header,
|
||||||
'src/System.cpp',
|
'src/Window.cpp',
|
||||||
'src/Bar.cpp',
|
'src/Widget.cpp',
|
||||||
|
'src/System.cpp',
|
||||||
|
'src/Bar.cpp',
|
||||||
|
'src/Workspaces.cpp',
|
||||||
'src/AudioFlyin.cpp',
|
'src/AudioFlyin.cpp',
|
||||||
'src/BluetoothDevices.cpp',
|
'src/BluetoothDevices.cpp',
|
||||||
'src/Plugin.cpp',
|
'src/Plugin.cpp',
|
||||||
'src/Config.cpp',
|
'src/Config.cpp',
|
||||||
'src/CSS.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)
|
install: true)
|
||||||
|
|
||||||
pkg = import('pkgconfig')
|
pkg = import('pkgconfig')
|
||||||
|
@ -66,7 +90,7 @@ pkg.generate(libgBar)
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
'gBar',
|
'gBar',
|
||||||
['src/gBar.cpp'],
|
['src/gBar.cpp'],
|
||||||
dependencies: [gtk],
|
dependencies: [gtk],
|
||||||
link_with: libgBar,
|
link_with: libgBar,
|
||||||
install_rpath: '$ORIGIN/',
|
install_rpath: '$ORIGIN/',
|
||||||
|
|
|
@ -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('WithNvidia', type: 'boolean', value : true)
|
||||||
option('WithAMD', type: 'boolean', value : true)
|
option('WithAMD', type: 'boolean', value : true)
|
||||||
option('WithBlueZ', 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!
|
# You shouldn't enable this, unless you know what you are doing!
|
||||||
option('WithSys', type: 'boolean', value : false)
|
option('WithSys', type: 'boolean', value : false)
|
||||||
|
|
306
protocols/ext-workspace-unstable-v1.xml
Normal file
306
protocols/ext-workspace-unstable-v1.xml
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="ext_workspace_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
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.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="zext_workspace_manager_v1" version="1">
|
||||||
|
<description summary="list and control workspaces">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="workspace_group">
|
||||||
|
<description summary="a workspace group has been created">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
<arg name="workspace_group" type="new_id" interface="zext_workspace_group_handle_v1"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="commit">
|
||||||
|
<description summary="all requests about the workspaces have been sent">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="done">
|
||||||
|
<description summary="all information about the workspace groups has been sent">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="finished">
|
||||||
|
<description summary="the compositor has finished with the workspace_manager">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="stop">
|
||||||
|
<description summary="stop sending events">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zext_workspace_group_handle_v1" version="1">
|
||||||
|
<description summary="a workspace group assigned to a set of outputs">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="output_enter">
|
||||||
|
<description summary="output assigned to workspace group">
|
||||||
|
This event is emitted whenever an output is assigned to the workspace
|
||||||
|
group.
|
||||||
|
</description>
|
||||||
|
<arg name="output" type="object" interface="wl_output"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="output_leave">
|
||||||
|
<description summary="output removed from workspace group">
|
||||||
|
This event is emitted whenever an output is removed from the workspace
|
||||||
|
group.
|
||||||
|
</description>
|
||||||
|
<arg name="output" type="object" interface="wl_output"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="workspace">
|
||||||
|
<description summary="workspace added to 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.
|
||||||
|
</description>
|
||||||
|
<arg name="workspace" type="new_id" interface="zext_workspace_handle_v1"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="remove">
|
||||||
|
<description summary="this workspace group has been destroyed">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="create_workspace">
|
||||||
|
<description summary="create a new workspace">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
<arg name="workspace" type="string"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the zext_workspace_handle_v1 object">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zext_workspace_handle_v1" version="1">
|
||||||
|
<description summary="a workspace handing a group of surfaces">
|
||||||
|
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).
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="name">
|
||||||
|
<description summary="workspace name changed">
|
||||||
|
This event is emitted immediately after the zext_workspace_handle_v1 is
|
||||||
|
created and whenever the name of the workspace changes.
|
||||||
|
</description>
|
||||||
|
<arg name="name" type="string"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="coordinates">
|
||||||
|
<description summary="workspace coordinates changed">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
<arg name="coordinates" type="array"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="state">
|
||||||
|
<description summary="the state of the workspace changed">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
<arg name="state" type="array"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<enum name="state">
|
||||||
|
<description summary="types of states on the workspace">
|
||||||
|
The different states that a workspace can have.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<entry name="active" value="0" summary="the workspace is active"/>
|
||||||
|
<entry name="urgent" value="1" summary="the workspace requests attention"/>
|
||||||
|
<entry name="hidden" value="2">
|
||||||
|
<description summary="the workspace is not visible">
|
||||||
|
The workspace is not visible in its workspace group, and clients
|
||||||
|
attempting to visualize the compositor workspace state should not
|
||||||
|
display such workspaces.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<event name="remove">
|
||||||
|
<description summary="this workspace has been destroyed">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the zext_workspace_handle_v1 object">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="activate">
|
||||||
|
<description summary="activate the workspace">
|
||||||
|
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.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="deactivate">
|
||||||
|
<description summary="activate the workspace">
|
||||||
|
Request that this workspace be deactivated.
|
||||||
|
|
||||||
|
There is no guarantee the workspace will be actually deactivated.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="remove">
|
||||||
|
<description summary="remove the workspace">
|
||||||
|
Request that this workspace be removed.
|
||||||
|
|
||||||
|
There is no guarantee the workspace will be actually removed.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
|
@ -198,7 +198,7 @@ namespace Bar
|
||||||
return TimerResult::Ok;
|
return TimerResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
static std::array<Button*, 9> workspaces;
|
static std::array<Button*, 9> workspaces;
|
||||||
TimerResult UpdateWorkspaces(Box&)
|
TimerResult UpdateWorkspaces(Box&)
|
||||||
{
|
{
|
||||||
|
@ -547,7 +547,7 @@ namespace Bar
|
||||||
parent.AddChild(std::move(eventBox));
|
parent.AddChild(std::move(eventBox));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
void WidgetWorkspaces(Widget& parent)
|
void WidgetWorkspaces(Widget& parent)
|
||||||
{
|
{
|
||||||
auto margin = Widget::Create<Box>();
|
auto margin = Widget::Create<Box>();
|
||||||
|
@ -591,8 +591,8 @@ namespace Bar
|
||||||
auto left = Widget::Create<Box>();
|
auto left = Widget::Create<Box>();
|
||||||
left->SetSpacing({0, false});
|
left->SetSpacing({0, false});
|
||||||
left->SetHorizontalTransform({-1, true, Alignment::Left});
|
left->SetHorizontalTransform({-1, true, Alignment::Left});
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
if (RuntimeConfig::Get().hasHyprland)
|
if (RuntimeConfig::Get().hasWorkspaces)
|
||||||
{
|
{
|
||||||
WidgetWorkspaces(*left);
|
WidgetWorkspaces(*left);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
static const Config& Get();
|
static const Config& Get();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Configs, that rely on specific files to be available(e.g. Hyprland running)
|
// Configs, that rely on specific files to be available(e.g. BlueZ running)
|
||||||
class RuntimeConfig
|
class RuntimeConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -48,10 +48,10 @@ public:
|
||||||
bool hasAMD = false;
|
bool hasAMD = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
bool hasHyprland = true;
|
bool hasWorkspaces = true;
|
||||||
#else
|
#else
|
||||||
bool hasHyprland = false;
|
bool hasWorkspaces = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_BLUEZ
|
#ifdef WITH_BLUEZ
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "NvidiaGPU.h"
|
#include "NvidiaGPU.h"
|
||||||
#include "AMDGPU.h"
|
#include "AMDGPU.h"
|
||||||
#include "PulseAudio.h"
|
#include "PulseAudio.h"
|
||||||
#include "Hyprland.h"
|
#include "Workspaces.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -446,22 +446,22 @@ namespace System
|
||||||
PulseAudio::SetVolumeSource(volume);
|
PulseAudio::SetVolumeSource(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
void PollWorkspaces(uint32_t monitor, uint32_t numWorkspaces)
|
void PollWorkspaces(uint32_t monitor, uint32_t numWorkspaces)
|
||||||
{
|
{
|
||||||
Hyprland::PollStatus(monitor, numWorkspaces);
|
Workspaces::PollStatus(monitor, numWorkspaces);
|
||||||
}
|
}
|
||||||
WorkspaceStatus GetWorkspaceStatus(uint32_t workspace)
|
WorkspaceStatus GetWorkspaceStatus(uint32_t workspace)
|
||||||
{
|
{
|
||||||
return Hyprland::GetStatus(workspace);
|
return Workspaces::GetStatus(workspace);
|
||||||
}
|
}
|
||||||
void GotoWorkspace(uint32_t workspace)
|
void GotoWorkspace(uint32_t workspace)
|
||||||
{
|
{
|
||||||
return Hyprland::Goto(workspace);
|
return Workspaces::Goto(workspace);
|
||||||
}
|
}
|
||||||
void GotoNextWorkspace(char direction)
|
void GotoNextWorkspace(char direction)
|
||||||
{
|
{
|
||||||
return Hyprland::GotoNext(direction);
|
return Workspaces::GotoNext(direction);
|
||||||
}
|
}
|
||||||
std::string GetWorkspaceSymbol(int index)
|
std::string GetWorkspaceSymbol(int index)
|
||||||
{
|
{
|
||||||
|
@ -582,8 +582,8 @@ namespace System
|
||||||
AMDGPU::Init();
|
AMDGPU::Init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
Hyprland::Init();
|
Workspaces::Init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_BLUEZ
|
#ifdef WITH_BLUEZ
|
||||||
|
@ -601,6 +601,10 @@ namespace System
|
||||||
#endif
|
#endif
|
||||||
PulseAudio::Shutdown();
|
PulseAudio::Shutdown();
|
||||||
|
|
||||||
|
#ifdef WITH_WORKSPACES
|
||||||
|
Workspaces::Shutdown();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_BLUEZ
|
#ifdef WITH_BLUEZ
|
||||||
StopBTScan();
|
StopBTScan();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace System
|
||||||
void SetVolumeSink(double volume);
|
void SetVolumeSink(double volume);
|
||||||
void SetVolumeSource(double volume);
|
void SetVolumeSource(double volume);
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
enum class WorkspaceStatus
|
enum class WorkspaceStatus
|
||||||
{
|
{
|
||||||
Dead,
|
Dead,
|
||||||
|
|
283
src/Workspaces.cpp
Normal file
283
src/Workspaces.cpp
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
#include "Workspaces.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <ext-workspace-unstable-v1.h>
|
||||||
|
|
||||||
|
#ifdef WITH_WORKSPACES
|
||||||
|
#ifndef FORCE_HYPRLAND_IPC
|
||||||
|
namespace Workspaces
|
||||||
|
{
|
||||||
|
struct WaylandMonitor
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
wl_output* output;
|
||||||
|
zext_workspace_group_handle_v1* workspaceGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WaylandWorkspace
|
||||||
|
{
|
||||||
|
zext_workspace_group_handle_v1* parent;
|
||||||
|
uint32_t id;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
struct WaylandWorkspaceGroup
|
||||||
|
{
|
||||||
|
std::vector<zext_workspace_handle_v1*> workspaces;
|
||||||
|
zext_workspace_handle_v1* lastActiveWorkspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
// There's probably a better way to avoid the LUTs
|
||||||
|
static std::unordered_map<uint32_t, WaylandMonitor> monitors;
|
||||||
|
static std::unordered_map<zext_workspace_group_handle_v1*, WaylandWorkspaceGroup> workspaceGroups;
|
||||||
|
static std::unordered_map<zext_workspace_handle_v1*, WaylandWorkspace> workspaces;
|
||||||
|
|
||||||
|
static uint32_t curID = 0;
|
||||||
|
|
||||||
|
static wl_display* display;
|
||||||
|
static wl_registry* registry;
|
||||||
|
static zext_workspace_manager_v1* workspaceManager;
|
||||||
|
|
||||||
|
static bool registeredMonitors = false;
|
||||||
|
static bool registeredGroup = false;
|
||||||
|
static bool registeredWorkspace = false;
|
||||||
|
static bool registeredWorkspaceInfo = false;
|
||||||
|
|
||||||
|
// Wayland callbacks
|
||||||
|
|
||||||
|
// Workspace Callbacks
|
||||||
|
static void OnWorkspaceName(void*, zext_workspace_handle_v1* workspace, const char* name)
|
||||||
|
{
|
||||||
|
workspaces[workspace].id = std::stoul(name);
|
||||||
|
LOG("Workspace ID: " << workspaces[workspace].id);
|
||||||
|
registeredWorkspaceInfo = true;
|
||||||
|
}
|
||||||
|
static void OnWorkspaceGeometry(void*, zext_workspace_handle_v1*, wl_array*) {}
|
||||||
|
static void OnWorkspaceState(void*, zext_workspace_handle_v1* ws, wl_array* arrState)
|
||||||
|
{
|
||||||
|
WaylandWorkspace& workspace = workspaces[ws];
|
||||||
|
ASSERT(workspace.parent, "Wayland: Workspace not registered!");
|
||||||
|
WaylandWorkspaceGroup& group = workspaceGroups[workspace.parent];
|
||||||
|
|
||||||
|
workspace.active = false;
|
||||||
|
// Manual wl_array_for_each, since that's broken for C++
|
||||||
|
for (zext_workspace_handle_v1_state* state = (zext_workspace_handle_v1_state*)arrState->data;
|
||||||
|
(uint8_t*)state < (uint8_t*)arrState->data + arrState->size; state += 1)
|
||||||
|
{
|
||||||
|
if (*state == ZEXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE)
|
||||||
|
{
|
||||||
|
group.lastActiveWorkspace = ws;
|
||||||
|
workspace.active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void OnWorkspaceRemove(void*, zext_workspace_handle_v1* ws)
|
||||||
|
{
|
||||||
|
WaylandWorkspace& workspace = workspaces[ws];
|
||||||
|
ASSERT(workspace.parent, "Wayland: Workspace not registered!");
|
||||||
|
WaylandWorkspaceGroup& group = workspaceGroups[workspace.parent];
|
||||||
|
auto it = std::find(group.workspaces.begin(), group.workspaces.end(), ws);
|
||||||
|
group.workspaces.erase(it);
|
||||||
|
|
||||||
|
workspaces.erase(ws);
|
||||||
|
|
||||||
|
LOG("Wayland: Removed workspace!");
|
||||||
|
}
|
||||||
|
zext_workspace_handle_v1_listener workspaceListener = {OnWorkspaceName, OnWorkspaceGeometry, OnWorkspaceState, OnWorkspaceRemove};
|
||||||
|
|
||||||
|
// Workspace Group callbacks
|
||||||
|
static void OnWSGroupOutputEnter(void*, zext_workspace_group_handle_v1* group, wl_output* output)
|
||||||
|
{
|
||||||
|
auto monitor = std::find_if(monitors.begin(), monitors.end(),
|
||||||
|
[&](const std::pair<uint32_t, WaylandMonitor>& mon)
|
||||||
|
{
|
||||||
|
return mon.second.output == output;
|
||||||
|
});
|
||||||
|
ASSERT(monitor != monitors.end(), "Wayland: Registered WS group before monitor!");
|
||||||
|
LOG("Wayland: Added group to monitor");
|
||||||
|
monitor->second.workspaceGroup = group;
|
||||||
|
}
|
||||||
|
static void OnWSGroupOutputLeave(void*, zext_workspace_group_handle_v1*, wl_output* output)
|
||||||
|
{
|
||||||
|
auto monitor = std::find_if(monitors.begin(), monitors.end(),
|
||||||
|
[&](const std::pair<uint32_t, WaylandMonitor>& mon)
|
||||||
|
{
|
||||||
|
return mon.second.output == output;
|
||||||
|
});
|
||||||
|
ASSERT(monitor != monitors.end(), "Wayland: Registered WS group before monitor!");
|
||||||
|
LOG("Wayland: Added group to monitor");
|
||||||
|
monitor->second.workspaceGroup = nullptr;
|
||||||
|
}
|
||||||
|
static void OnWSGroupWorkspaceAdded(void*, zext_workspace_group_handle_v1* workspace, zext_workspace_handle_v1* ws)
|
||||||
|
{
|
||||||
|
LOG("Wayland: Added workspace!");
|
||||||
|
workspaceGroups[workspace].workspaces.push_back(ws);
|
||||||
|
workspaces[ws] = {workspace, (uint32_t)-1};
|
||||||
|
zext_workspace_handle_v1_add_listener(ws, &workspaceListener, nullptr);
|
||||||
|
registeredWorkspace = true;
|
||||||
|
}
|
||||||
|
static void OnWSGroupRemove(void*, zext_workspace_group_handle_v1* workspaceGroup)
|
||||||
|
{
|
||||||
|
workspaceGroups.erase(workspaceGroup);
|
||||||
|
}
|
||||||
|
zext_workspace_group_handle_v1_listener workspaceGroupListener = {OnWSGroupOutputEnter, OnWSGroupOutputLeave, OnWSGroupWorkspaceAdded,
|
||||||
|
OnWSGroupRemove};
|
||||||
|
|
||||||
|
// Workspace Manager Callbacks
|
||||||
|
static void OnWSManagerNewGroup(void*, zext_workspace_manager_v1*, zext_workspace_group_handle_v1* group)
|
||||||
|
{
|
||||||
|
// Register callbacks for the group.
|
||||||
|
registeredGroup = true;
|
||||||
|
zext_workspace_group_handle_v1_add_listener(group, &workspaceGroupListener, nullptr);
|
||||||
|
}
|
||||||
|
static void OnWSManagerDone(void*, zext_workspace_manager_v1*) {}
|
||||||
|
static void OnWSManagerFinished(void*, zext_workspace_manager_v1*)
|
||||||
|
{
|
||||||
|
LOG("Wayland: Workspace manager finished. Disabling workspaces!");
|
||||||
|
RuntimeConfig::Get().hasWorkspaces = false;
|
||||||
|
}
|
||||||
|
zext_workspace_manager_v1_listener workspaceManagerListener = {OnWSManagerNewGroup, OnWSManagerDone, OnWSManagerFinished};
|
||||||
|
|
||||||
|
// Output Callbacks
|
||||||
|
// Very bloated, indeed
|
||||||
|
static void OnOutputGeometry(void*, wl_output*, int32_t, int32_t, int32_t, int32_t, int32_t, const char*, const char*, int32_t) {}
|
||||||
|
static void OnOutputMode(void*, wl_output*, uint32_t, int32_t, int32_t, int32_t) {}
|
||||||
|
static void OnOutputDone(void*, wl_output*) {}
|
||||||
|
static void OnOutputScale(void*, wl_output*, int32_t) {}
|
||||||
|
static void OnOutputName(void*, wl_output* output, const char* name)
|
||||||
|
{
|
||||||
|
LOG("Wayland: Registering monitor " << name << " at ID " << curID);
|
||||||
|
registeredMonitors = true;
|
||||||
|
monitors.try_emplace(curID++, WaylandMonitor{name, output, nullptr});
|
||||||
|
}
|
||||||
|
static void OnOutputDescription(void*, wl_output*, const char*) {}
|
||||||
|
wl_output_listener outputListener = {OnOutputGeometry, OnOutputMode, OnOutputDone, OnOutputScale, OnOutputName, OnOutputDescription};
|
||||||
|
|
||||||
|
// Registry Callbacks
|
||||||
|
static void OnRegistryAdd(void*, wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||||
|
{
|
||||||
|
if (strcmp(interface, "wl_output") == 0)
|
||||||
|
{
|
||||||
|
wl_output* output = (wl_output*)wl_registry_bind(registry, name, &wl_output_interface, 4);
|
||||||
|
wl_output_add_listener(output, &outputListener, nullptr);
|
||||||
|
}
|
||||||
|
if (strcmp(interface, "zext_workspace_manager_v1") == 0)
|
||||||
|
{
|
||||||
|
workspaceManager = (zext_workspace_manager_v1*)wl_registry_bind(registry, name, &zext_workspace_manager_v1_interface, version);
|
||||||
|
zext_workspace_manager_v1_add_listener(workspaceManager, &workspaceManagerListener, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void OnRegistryRemove(void*, wl_registry*, uint32_t) {}
|
||||||
|
wl_registry_listener registryListener = {OnRegistryAdd, OnRegistryRemove};
|
||||||
|
|
||||||
|
// Dispatch events.
|
||||||
|
static void Dispatch()
|
||||||
|
{
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
}
|
||||||
|
static void WaitFor(bool& condition)
|
||||||
|
{
|
||||||
|
while (!condition && wl_display_dispatch(display) != -1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
display = wl_display_connect(nullptr);
|
||||||
|
ASSERT(display, "Cannot connect to wayland compositor!");
|
||||||
|
registry = wl_display_get_registry(display);
|
||||||
|
ASSERT(registry, "Cannot get wayland registry!");
|
||||||
|
|
||||||
|
wl_registry_add_listener(registry, ®istryListener, nullptr);
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
WaitFor(registeredMonitors);
|
||||||
|
registeredMonitors = false;
|
||||||
|
|
||||||
|
if (!workspaceManager)
|
||||||
|
{
|
||||||
|
LOG("Compositor doesn't implement zext_workspace_manager_v1, disabling workspaces!");
|
||||||
|
RuntimeConfig::Get().hasWorkspaces = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hack for unified interface
|
||||||
|
static uint32_t lastPolledMonitor = 0;
|
||||||
|
void PollStatus(uint32_t monitor, uint32_t)
|
||||||
|
{
|
||||||
|
lastPolledMonitor = monitor;
|
||||||
|
// Dispatch events
|
||||||
|
Dispatch();
|
||||||
|
if (registeredGroup)
|
||||||
|
{
|
||||||
|
// New Group, wait for workspaces to be registered.
|
||||||
|
WaitFor(registeredWorkspace);
|
||||||
|
}
|
||||||
|
if (registeredWorkspace)
|
||||||
|
{
|
||||||
|
// New workspace added, need info
|
||||||
|
WaitFor(registeredWorkspaceInfo);
|
||||||
|
}
|
||||||
|
registeredGroup = false;
|
||||||
|
registeredWorkspace = false;
|
||||||
|
registeredWorkspaceInfo = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
||||||
|
{
|
||||||
|
WaylandMonitor& monitor = monitors[lastPolledMonitor];
|
||||||
|
if (!monitor.output)
|
||||||
|
{
|
||||||
|
LOG("Polled monitor doesn't exist!");
|
||||||
|
return System::WorkspaceStatus::Dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto workspaceIt = std::find_if(workspaces.begin(), workspaces.end(),
|
||||||
|
[&](const std::pair<zext_workspace_handle_v1*, WaylandWorkspace>& ws)
|
||||||
|
{
|
||||||
|
return ws.second.id == workspaceId;
|
||||||
|
});
|
||||||
|
if (workspaceIt == workspaces.end())
|
||||||
|
{
|
||||||
|
return System::WorkspaceStatus::Dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaylandWorkspaceGroup& group = workspaceGroups[monitor.workspaceGroup];
|
||||||
|
if (group.lastActiveWorkspace)
|
||||||
|
{
|
||||||
|
WaylandWorkspace& activeWorkspace = workspaces[group.lastActiveWorkspace];
|
||||||
|
if (activeWorkspace.id == workspaceId && activeWorkspace.active)
|
||||||
|
{
|
||||||
|
return System::WorkspaceStatus::Active;
|
||||||
|
}
|
||||||
|
else if (activeWorkspace.id == workspaceId)
|
||||||
|
{
|
||||||
|
// Last active workspace (Means we can still see it, since no other ws is active and thus is only visible)
|
||||||
|
return System::WorkspaceStatus::Current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WaylandWorkspaceGroup& currentWorkspaceGroup = workspaceGroups[workspaceIt->second.parent];
|
||||||
|
if (currentWorkspaceGroup.lastActiveWorkspace == workspaceIt->first)
|
||||||
|
{
|
||||||
|
return System::WorkspaceStatus::Visible;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return System::WorkspaceStatus::Inactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
return System::WorkspaceStatus::Dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown()
|
||||||
|
{
|
||||||
|
wl_display_disconnect(display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -11,16 +11,17 @@
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_WORKSPACES
|
||||||
namespace Hyprland
|
namespace Workspaces
|
||||||
{
|
{
|
||||||
|
#ifdef FORCE_HYPRLAND_IPC
|
||||||
inline void Init()
|
inline void Init()
|
||||||
{
|
{
|
||||||
if (!getenv("HYPRLAND_INSTANCE_SIGNATURE"))
|
if (!getenv("HYPRLAND_INSTANCE_SIGNATURE"))
|
||||||
{
|
{
|
||||||
LOG("Hyprland not running, disabling workspaces");
|
LOG("Workspaces not running, disabling workspaces");
|
||||||
// Not available
|
// Not available
|
||||||
RuntimeConfig::Get().hasHyprland = false;
|
RuntimeConfig::Get().hasWorkspaces = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +60,9 @@ namespace Hyprland
|
||||||
|
|
||||||
inline void PollStatus(uint32_t monitorID, uint32_t numWorkspaces)
|
inline void PollStatus(uint32_t monitorID, uint32_t numWorkspaces)
|
||||||
{
|
{
|
||||||
if (RuntimeConfig::Get().hasHyprland == false)
|
if (RuntimeConfig::Get().hasWorkspaces == false)
|
||||||
{
|
{
|
||||||
LOG("Error: Polled workspace status, but Hyprland isn't open!");
|
LOG("Error: Polled workspace status, but Workspaces isn't open!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
workspaceStati.clear();
|
workspaceStati.clear();
|
||||||
|
@ -135,20 +136,32 @@ namespace Hyprland
|
||||||
|
|
||||||
inline System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
inline System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
||||||
{
|
{
|
||||||
if (RuntimeConfig::Get().hasHyprland == false)
|
if (RuntimeConfig::Get().hasWorkspaces == false)
|
||||||
{
|
{
|
||||||
LOG("Error: Queried for workspace status, but Hyprland isn't open!");
|
LOG("Error: Queried for workspace status, but Workspaces isn't open!");
|
||||||
return System::WorkspaceStatus::Dead;
|
return System::WorkspaceStatus::Dead;
|
||||||
}
|
}
|
||||||
ASSERT(workspaceId > 0 && workspaceId <= workspaceStati.size(), "Invalid workspaceId, you need to poll the workspace first!");
|
ASSERT(workspaceId > 0 && workspaceId <= workspaceStati.size(), "Invalid workspaceId, you need to poll the workspace first!");
|
||||||
return workspaceStati[workspaceId - 1];
|
return workspaceStati[workspaceId - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Shutdown() {}
|
||||||
|
#else
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void PollStatus(uint32_t monitorID, uint32_t numWorkspaces);
|
||||||
|
|
||||||
|
System::WorkspaceStatus GetStatus(uint32_t workspaceId);
|
||||||
|
|
||||||
|
void Shutdown();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: Use ext_workspaces for this
|
||||||
inline void Goto(uint32_t workspace)
|
inline void Goto(uint32_t workspace)
|
||||||
{
|
{
|
||||||
if (RuntimeConfig::Get().hasHyprland == false)
|
if (RuntimeConfig::Get().hasWorkspaces == false)
|
||||||
{
|
{
|
||||||
LOG("Error: Called Go to workspace, but Hyprland isn't open!");
|
LOG("Error: Called Go to workspace, but Workspaces isn't open!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue