mirror of
https://github.com/scorpion-26/gBar.git
synced 2024-11-22 03:02:49 +00:00
Refactor Wayland code out
This commit is contained in:
parent
f2dc5a806c
commit
7567465454
6 changed files with 315 additions and 266 deletions
|
@ -35,6 +35,7 @@ headers = [
|
||||||
'src/PulseAudio.h',
|
'src/PulseAudio.h',
|
||||||
'src/Widget.h',
|
'src/Widget.h',
|
||||||
'src/Window.h',
|
'src/Window.h',
|
||||||
|
'src/Wayland.h',
|
||||||
'src/Config.h',
|
'src/Config.h',
|
||||||
'src/CSS.h'
|
'src/CSS.h'
|
||||||
]
|
]
|
||||||
|
@ -44,6 +45,7 @@ sources = [
|
||||||
ext_workspace_header,
|
ext_workspace_header,
|
||||||
'src/Window.cpp',
|
'src/Window.cpp',
|
||||||
'src/Widget.cpp',
|
'src/Widget.cpp',
|
||||||
|
'src/Wayland.cpp',
|
||||||
'src/System.cpp',
|
'src/System.cpp',
|
||||||
'src/Bar.cpp',
|
'src/Bar.cpp',
|
||||||
'src/Workspaces.cpp',
|
'src/Workspaces.cpp',
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "Workspaces.h"
|
#include "Workspaces.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "SNI.h"
|
#include "SNI.h"
|
||||||
|
#include "Wayland.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -639,6 +640,8 @@ namespace System
|
||||||
|
|
||||||
Config::Load();
|
Config::Load();
|
||||||
|
|
||||||
|
Wayland::Init();
|
||||||
|
|
||||||
#ifdef WITH_NVIDIA
|
#ifdef WITH_NVIDIA
|
||||||
NvidiaGPU::Init();
|
NvidiaGPU::Init();
|
||||||
#endif
|
#endif
|
||||||
|
@ -681,6 +684,8 @@ namespace System
|
||||||
SNI::Shutdown();
|
SNI::Shutdown();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Wayland::Shutdown();
|
||||||
|
|
||||||
Logging::Shutdown();
|
Logging::Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
255
src/Wayland.cpp
Normal file
255
src/Wayland.cpp
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Wayland.h"
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Config.h"
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <ext-workspace-unstable-v1.h>
|
||||||
|
|
||||||
|
namespace Wayland
|
||||||
|
{
|
||||||
|
// There's probably a better way to avoid the LUTs
|
||||||
|
static std::unordered_map<uint32_t, Monitor> monitors;
|
||||||
|
static std::unordered_map<zext_workspace_group_handle_v1*, WorkspaceGroup> workspaceGroups;
|
||||||
|
static std::unordered_map<zext_workspace_handle_v1*, Workspace> 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)
|
||||||
|
{
|
||||||
|
Workspace& workspace = workspaces[ws];
|
||||||
|
ASSERT(workspace.parent, "Wayland: Workspace not registered!");
|
||||||
|
WorkspaceGroup& 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)
|
||||||
|
{
|
||||||
|
LOG("Wayland: Activate Workspace " << workspace.id);
|
||||||
|
group.lastActiveWorkspace = ws;
|
||||||
|
workspace.active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!workspace.active)
|
||||||
|
{
|
||||||
|
LOG("Wayland: Deactivate Workspace " << workspace.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void OnWorkspaceRemove(void*, zext_workspace_handle_v1* ws)
|
||||||
|
{
|
||||||
|
Workspace& workspace = workspaces[ws];
|
||||||
|
ASSERT(workspace.parent, "Wayland: Workspace not registered!");
|
||||||
|
WorkspaceGroup& 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, Monitor>& 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, Monitor>& 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++, Monitor{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: manually activate workspace for each monitor
|
||||||
|
for (auto& monitor : monitors)
|
||||||
|
{
|
||||||
|
// Find group
|
||||||
|
auto& group = workspaceGroups[monitor.second.workspaceGroup];
|
||||||
|
|
||||||
|
// Find ws with monitor index + 1
|
||||||
|
auto workspaceIt = std::find_if(workspaces.begin(), workspaces.end(),
|
||||||
|
[&](const std::pair<zext_workspace_handle_v1*, Workspace>& ws)
|
||||||
|
{
|
||||||
|
return ws.second.id == monitor.first + 1;
|
||||||
|
});
|
||||||
|
if (workspaceIt != workspaces.end())
|
||||||
|
{
|
||||||
|
LOG("Forcefully activate workspace " << workspaceIt->second.id)
|
||||||
|
if (workspaceIt->second.id == 1)
|
||||||
|
{
|
||||||
|
// Activate first workspace
|
||||||
|
workspaceIt->second.active = true;
|
||||||
|
}
|
||||||
|
// Make it visible
|
||||||
|
group.lastActiveWorkspace = workspaceIt->first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PollEvents()
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown()
|
||||||
|
{
|
||||||
|
if (display)
|
||||||
|
wl_display_disconnect(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<uint32_t, Monitor>& GetMonitors()
|
||||||
|
{
|
||||||
|
return monitors;
|
||||||
|
}
|
||||||
|
const std::unordered_map<zext_workspace_group_handle_v1*, WorkspaceGroup>& GetWorkspaceGroups()
|
||||||
|
{
|
||||||
|
return workspaceGroups;
|
||||||
|
}
|
||||||
|
const std::unordered_map<zext_workspace_handle_v1*, Workspace>& GetWorkspaces()
|
||||||
|
{
|
||||||
|
return workspaces;
|
||||||
|
}
|
||||||
|
}
|
36
src/Wayland.h
Normal file
36
src/Wayland.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
|
struct wl_output;
|
||||||
|
struct zext_workspace_group_handle_v1;
|
||||||
|
struct zext_workspace_handle_v1;
|
||||||
|
namespace Wayland
|
||||||
|
{
|
||||||
|
struct Monitor
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
wl_output* output;
|
||||||
|
zext_workspace_group_handle_v1* workspaceGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Workspace
|
||||||
|
{
|
||||||
|
zext_workspace_group_handle_v1* parent;
|
||||||
|
uint32_t id;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
struct WorkspaceGroup
|
||||||
|
{
|
||||||
|
std::vector<zext_workspace_handle_v1*> workspaces;
|
||||||
|
zext_workspace_handle_v1* lastActiveWorkspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void PollEvents();
|
||||||
|
|
||||||
|
const std::unordered_map<uint32_t, Monitor>& GetMonitors();
|
||||||
|
const std::unordered_map<zext_workspace_group_handle_v1*, WorkspaceGroup>& GetWorkspaceGroups();
|
||||||
|
const std::unordered_map<zext_workspace_handle_v1*, Workspace>& GetWorkspaces();
|
||||||
|
|
||||||
|
void Shutdown();
|
||||||
|
}
|
|
@ -1,272 +1,33 @@
|
||||||
#include "Workspaces.h"
|
#include "Workspaces.h"
|
||||||
|
#include "Wayland.h"
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#include <ext-workspace-unstable-v1.h>
|
#include <ext-workspace-unstable-v1.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#ifdef WITH_WORKSPACES
|
#ifdef WITH_WORKSPACES
|
||||||
namespace Workspaces
|
namespace Workspaces
|
||||||
{
|
{
|
||||||
namespace Wayland
|
namespace Wayland
|
||||||
{
|
{
|
||||||
struct WaylandMonitor
|
using WaylandMonitor = ::Wayland::Monitor;
|
||||||
{
|
using WaylandWorkspaceGroup = ::Wayland::WorkspaceGroup;
|
||||||
std::string name;
|
using WaylandWorkspace = ::Wayland::Workspace;
|
||||||
wl_output* output;
|
|
||||||
zext_workspace_group_handle_v1* workspaceGroup;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WaylandWorkspace
|
static uint32_t lastPolledMonitor;
|
||||||
|
void PollStatus(uint32_t monitorID, uint32_t)
|
||||||
{
|
{
|
||||||
zext_workspace_group_handle_v1* parent;
|
::Wayland::PollEvents();
|
||||||
uint32_t id;
|
lastPolledMonitor = monitorID;
|
||||||
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)
|
|
||||||
{
|
|
||||||
LOG("Wayland: Activate Workspace " << workspace.id);
|
|
||||||
group.lastActiveWorkspace = ws;
|
|
||||||
workspace.active = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!workspace.active)
|
|
||||||
{
|
|
||||||
LOG("Wayland: Deactivate Workspace " << workspace.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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: manually activate workspace for each monitor
|
|
||||||
for (auto& monitor : monitors)
|
|
||||||
{
|
|
||||||
// Find group
|
|
||||||
auto& group = workspaceGroups[monitor.second.workspaceGroup];
|
|
||||||
|
|
||||||
// Find ws with monitor index + 1
|
|
||||||
auto workspaceIt = std::find_if(workspaces.begin(), workspaces.end(),
|
|
||||||
[&](const std::pair<zext_workspace_handle_v1*, WaylandWorkspace>& ws)
|
|
||||||
{
|
|
||||||
return ws.second.id == monitor.first + 1;
|
|
||||||
});
|
|
||||||
if (workspaceIt != workspaces.end())
|
|
||||||
{
|
|
||||||
LOG("Forcefully activate workspace " << workspaceIt->second.id)
|
|
||||||
if (workspaceIt->second.id == 1)
|
|
||||||
{
|
|
||||||
// Activate first workspace
|
|
||||||
workspaceIt->second.active = true;
|
|
||||||
}
|
|
||||||
// Make it visible
|
|
||||||
group.lastActiveWorkspace = workspaceIt->first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
||||||
{
|
{
|
||||||
WaylandMonitor& monitor = monitors[lastPolledMonitor];
|
const WaylandMonitor& monitor = ::Wayland::GetMonitors().at(lastPolledMonitor);
|
||||||
if (!monitor.output)
|
if (!monitor.output)
|
||||||
{
|
{
|
||||||
LOG("Polled monitor doesn't exist!");
|
LOG("Polled monitor doesn't exist!");
|
||||||
return System::WorkspaceStatus::Dead;
|
return System::WorkspaceStatus::Dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& workspaces = ::Wayland::GetWorkspaces();
|
||||||
auto workspaceIt = std::find_if(workspaces.begin(), workspaces.end(),
|
auto workspaceIt = std::find_if(workspaces.begin(), workspaces.end(),
|
||||||
[&](const std::pair<zext_workspace_handle_v1*, WaylandWorkspace>& ws)
|
[&](const std::pair<zext_workspace_handle_v1*, WaylandWorkspace>& ws)
|
||||||
{
|
{
|
||||||
|
@ -277,10 +38,10 @@ namespace Workspaces
|
||||||
return System::WorkspaceStatus::Dead;
|
return System::WorkspaceStatus::Dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaylandWorkspaceGroup& group = workspaceGroups[monitor.workspaceGroup];
|
const WaylandWorkspaceGroup& group = ::Wayland::GetWorkspaceGroups().at(monitor.workspaceGroup);
|
||||||
if (group.lastActiveWorkspace)
|
if (group.lastActiveWorkspace)
|
||||||
{
|
{
|
||||||
WaylandWorkspace& activeWorkspace = workspaces[group.lastActiveWorkspace];
|
const WaylandWorkspace& activeWorkspace = workspaces.at(group.lastActiveWorkspace);
|
||||||
if (activeWorkspace.id == workspaceId && activeWorkspace.active)
|
if (activeWorkspace.id == workspaceId && activeWorkspace.active)
|
||||||
{
|
{
|
||||||
return System::WorkspaceStatus::Active;
|
return System::WorkspaceStatus::Active;
|
||||||
|
@ -292,7 +53,7 @@ namespace Workspaces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WaylandWorkspaceGroup& currentWorkspaceGroup = workspaceGroups[workspaceIt->second.parent];
|
const WaylandWorkspaceGroup& currentWorkspaceGroup = ::Wayland::GetWorkspaceGroups().at(workspaceIt->second.parent);
|
||||||
if (currentWorkspaceGroup.lastActiveWorkspace == workspaceIt->first)
|
if (currentWorkspaceGroup.lastActiveWorkspace == workspaceIt->first)
|
||||||
{
|
{
|
||||||
return System::WorkspaceStatus::Visible;
|
return System::WorkspaceStatus::Visible;
|
||||||
|
@ -304,12 +65,6 @@ namespace Workspaces
|
||||||
|
|
||||||
return System::WorkspaceStatus::Dead;
|
return System::WorkspaceStatus::Dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
|
||||||
{
|
|
||||||
if (display)
|
|
||||||
wl_display_disconnect(display);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_HYPRLAND
|
||||||
|
@ -456,7 +211,6 @@ namespace Workspaces
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Wayland::Init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollStatus(uint32_t monitorID, uint32_t numWorkspaces)
|
void PollStatus(uint32_t monitorID, uint32_t numWorkspaces)
|
||||||
|
@ -482,9 +236,6 @@ namespace Workspaces
|
||||||
return Wayland::GetStatus(workspaceId);
|
return Wayland::GetStatus(workspaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown() {}
|
||||||
{
|
|
||||||
Wayland::Shutdown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue