mirror of
https://github.com/scorpion-26/gBar.git
synced 2024-11-22 03:02:49 +00:00
Handle monitor changes
Since there is no way to map a connector to a Gdk Window ID and window ID's are not static per monitor, the entire Window and Wayland system has been rewritten to store a "target monitor" connector name, which is the name of the monitor we want to be on. Every time a monitor is removed or added, it is checked against the monitors of our Wayland backend to match connector to Gdk ID and then the Window is created/destroyed on the window(The target monitor is preferred, but if it doesn't exist, other monitors are used too). This is not perfect, since the matching of connector name to Gdk ID is only an approximation of the Gdk behaviour (Especially rough on hyprland with the headless monitor. A hack is needed to handle that). Additionally the monitor can now be specified by connector name when starting up (e.g. "gBar bar DP-1").
This commit is contained in:
parent
18170ab1c7
commit
1b16e40598
19 changed files with 341 additions and 158 deletions
|
@ -1,12 +1,11 @@
|
||||||
#include <gBar/Common.h>
|
#include <gBar/Common.h>
|
||||||
#include <gBar/Window.h>
|
#include <gBar/Window.h>
|
||||||
|
|
||||||
void Create(Window& window, int32_t monitor)
|
void Create(Window& window, const std::string& monitor)
|
||||||
{
|
{
|
||||||
auto mainWidget = Widget::Create<Text>();
|
auto mainWidget = Widget::Create<Text>();
|
||||||
mainWidget->SetText("Hello, World!");
|
mainWidget->SetText("Hello, World!");
|
||||||
|
|
||||||
window = Window(monitor);
|
|
||||||
window.SetMainWidget(std::move(mainWidget));
|
window.SetMainWidget(std::move(mainWidget));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ namespace AudioFlyin
|
||||||
parent.AddChild(std::move(icon));
|
parent.AddChild(std::move(icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Create(Window& window, UNUSED int32_t monitor, Type type)
|
void Create(Window& window, UNUSED const std::string& monitor, Type type)
|
||||||
{
|
{
|
||||||
DynCtx::win = &window;
|
DynCtx::win = &window;
|
||||||
DynCtx::type = type;
|
DynCtx::type = type;
|
||||||
|
|
|
@ -9,5 +9,5 @@ namespace AudioFlyin
|
||||||
Speaker,
|
Speaker,
|
||||||
Microphone
|
Microphone
|
||||||
};
|
};
|
||||||
void Create(Window& window, int32_t monitor, Type type);
|
void Create(Window& window, const std::string& monitor, Type type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Bar
|
||||||
return (Config::Get().location == 'L' || Config::Get().location == 'R') && Config::Get().iconsAlwaysUp;
|
return (Config::Get().location == 'L' || Config::Get().location == 'R') && Config::Get().iconsAlwaysUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t monitorID;
|
static std::string monitor;
|
||||||
|
|
||||||
namespace DynCtx
|
namespace DynCtx
|
||||||
{
|
{
|
||||||
|
@ -393,7 +393,7 @@ namespace Bar
|
||||||
static std::vector<Button*> workspaces;
|
static std::vector<Button*> workspaces;
|
||||||
TimerResult UpdateWorkspaces(Box&)
|
TimerResult UpdateWorkspaces(Box&)
|
||||||
{
|
{
|
||||||
System::PollWorkspaces((uint32_t)monitorID, workspaces.size());
|
System::PollWorkspaces(monitor, workspaces.size());
|
||||||
for (size_t i = 0; i < workspaces.size(); i++)
|
for (size_t i = 0; i < workspaces.size(); i++)
|
||||||
{
|
{
|
||||||
switch (System::GetWorkspaceStatus(i + 1))
|
switch (System::GetWorkspaceStatus(i + 1))
|
||||||
|
@ -1187,9 +1187,10 @@ namespace Bar
|
||||||
"VRAM, GPU, RAM, CPU, Battery, Power");
|
"VRAM, GPU, RAM, CPU, Battery, Power");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Create(Window& window, int32_t monitor)
|
void Create(Window& window, const std::string& monitorName)
|
||||||
{
|
{
|
||||||
monitorID = monitor;
|
ASSERT(!window.GetName().empty(), "Error: The bar requires a specified monitor. Use 'gBar bar <monitor>' instead!");
|
||||||
|
monitor = monitorName;
|
||||||
|
|
||||||
auto mainWidget = Widget::Create<Box>();
|
auto mainWidget = Widget::Create<Box>();
|
||||||
mainWidget->SetOrientation(Utils::GetOrientation());
|
mainWidget->SetOrientation(Utils::GetOrientation());
|
||||||
|
|
|
@ -4,5 +4,5 @@
|
||||||
|
|
||||||
namespace Bar
|
namespace Bar
|
||||||
{
|
{
|
||||||
void Create(Window& window, int32_t monitor);
|
void Create(Window& window, const std::string& monitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,7 +286,7 @@ namespace BluetoothDevices
|
||||||
parentWidget.AddChild(std::move(bodyBox));
|
parentWidget.AddChild(std::move(bodyBox));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Create(Window& window, UNUSED int32_t monitor)
|
void Create(Window& window, UNUSED const std::string& monitor)
|
||||||
{
|
{
|
||||||
DynCtx::win = &window;
|
DynCtx::win = &window;
|
||||||
auto mainWidget = Widget::Create<Box>();
|
auto mainWidget = Widget::Create<Box>();
|
||||||
|
|
|
@ -4,5 +4,5 @@
|
||||||
|
|
||||||
namespace BluetoothDevices
|
namespace BluetoothDevices
|
||||||
{
|
{
|
||||||
void Create(Window& window, int32_t monitor);
|
void Create(Window& window, const std::string& monitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ inline Process OpenProcess(const std::string& command)
|
||||||
{ \
|
{ \
|
||||||
return DL_VERSION; \
|
return DL_VERSION; \
|
||||||
}; \
|
}; \
|
||||||
extern "C" void Plugin_InvokeCreateFun(void* window, int32_t monitor) \
|
extern "C" void Plugin_InvokeCreateFun(void* window, void* monitor) \
|
||||||
{ \
|
{ \
|
||||||
fun(*(Window*)window, monitor); \
|
fun(*(Window*)window, *(const std::string&*)monitor); \
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
void Plugin::LoadWidgetFromPlugin(const std::string& pluginName, Window& window, int32_t monitor)
|
void Plugin::LoadWidgetFromPlugin(const std::string& pluginName, Window& window, const std::string& monitor)
|
||||||
{
|
{
|
||||||
std::string home = std::getenv("HOME");
|
std::string home = std::getenv("HOME");
|
||||||
std::array<std::string, 3> paths = {home + "/.local/lib/gBar", "/usr/local/lib/gBar", "/usr/lib/gBar"};
|
std::array<std::string, 3> paths = {home + "/.local/lib/gBar", "/usr/local/lib/gBar", "/usr/lib/gBar"};
|
||||||
|
@ -18,19 +18,19 @@ void Plugin::LoadWidgetFromPlugin(const std::string& pluginName, Window& window,
|
||||||
if (dl)
|
if (dl)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ASSERT(dl, "Error: Cannot find plugin \"" << pluginName << "\"!\n"
|
ASSERT(dl, "Error: Cannot find plugin \"" << pluginName
|
||||||
|
<< "\"!\n"
|
||||||
"Note: Did you mean to run \"gBar bar\" instead?");
|
"Note: Did you mean to run \"gBar bar\" instead?");
|
||||||
|
|
||||||
typedef void (*PFN_InvokeCreateFun)(void*, int32_t);
|
typedef void (*PFN_InvokeCreateFun)(void*, void*);
|
||||||
typedef int32_t (*PFN_GetVersion)();
|
typedef int32_t (*PFN_GetVersion)();
|
||||||
auto getVersion = (PFN_GetVersion)dlsym(dl, "Plugin_GetVersion");
|
auto getVersion = (PFN_GetVersion)dlsym(dl, "Plugin_GetVersion");
|
||||||
ASSERT(getVersion, "DL is not a valid gBar plugin!");
|
ASSERT(getVersion, "DL is not a valid gBar plugin!");
|
||||||
ASSERT(getVersion() == DL_VERSION, "Mismatching version, please recompile your plugin!");
|
ASSERT(getVersion() == DL_VERSION, "Mismatching version, please recompile your plugin!");
|
||||||
|
|
||||||
typedef void (*PFN_InvokeCreateFun)(void*, int32_t);
|
|
||||||
auto invokeCreateFun = (PFN_InvokeCreateFun)dlsym(dl, "Plugin_InvokeCreateFun");
|
auto invokeCreateFun = (PFN_InvokeCreateFun)dlsym(dl, "Plugin_InvokeCreateFun");
|
||||||
ASSERT(invokeCreateFun, "DL is not a valid gBar plugin!");
|
ASSERT(invokeCreateFun, "DL is not a valid gBar plugin!");
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
invokeCreateFun(&window, monitor);
|
invokeCreateFun(&window, (void*)&monitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,5 @@
|
||||||
|
|
||||||
namespace Plugin
|
namespace Plugin
|
||||||
{
|
{
|
||||||
void LoadWidgetFromPlugin(const std::string& pluginName, Window& window, int32_t monitor);
|
void LoadWidgetFromPlugin(const std::string& pluginName, Window& window, const std::string& monitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,7 +485,7 @@ namespace System
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_WORKSPACES
|
#ifdef WITH_WORKSPACES
|
||||||
void PollWorkspaces(uint32_t monitor, uint32_t numWorkspaces)
|
void PollWorkspaces(const std::string& monitor, uint32_t numWorkspaces)
|
||||||
{
|
{
|
||||||
Workspaces::PollStatus(monitor, numWorkspaces);
|
Workspaces::PollStatus(monitor, numWorkspaces);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ namespace System
|
||||||
Current,
|
Current,
|
||||||
Active
|
Active
|
||||||
};
|
};
|
||||||
void PollWorkspaces(uint32_t monitor, uint32_t numWorkspaces);
|
void PollWorkspaces(const std::string& monitor, uint32_t numWorkspaces);
|
||||||
WorkspaceStatus GetWorkspaceStatus(uint32_t workspace);
|
WorkspaceStatus GetWorkspaceStatus(uint32_t workspace);
|
||||||
void GotoWorkspace(uint32_t workspace);
|
void GotoWorkspace(uint32_t workspace);
|
||||||
// direction: + or -
|
// direction: + or -
|
||||||
|
|
109
src/Wayland.cpp
109
src/Wayland.cpp
|
@ -8,17 +8,15 @@
|
||||||
namespace Wayland
|
namespace Wayland
|
||||||
{
|
{
|
||||||
// There's probably a better way to avoid the LUTs
|
// There's probably a better way to avoid the LUTs
|
||||||
static std::unordered_map<std::string, Monitor> monitors;
|
static std::unordered_map<wl_output*, Monitor> monitors;
|
||||||
static std::unordered_map<zext_workspace_group_handle_v1*, WorkspaceGroup> workspaceGroups;
|
static std::unordered_map<zext_workspace_group_handle_v1*, WorkspaceGroup> workspaceGroups;
|
||||||
static std::unordered_map<zext_workspace_handle_v1*, Workspace> workspaces;
|
static std::unordered_map<zext_workspace_handle_v1*, Workspace> workspaces;
|
||||||
|
|
||||||
static uint32_t curID = 0;
|
|
||||||
|
|
||||||
static wl_display* display;
|
static wl_display* display;
|
||||||
static wl_registry* registry;
|
static wl_registry* registry;
|
||||||
static zext_workspace_manager_v1* workspaceManager;
|
static zext_workspace_manager_v1* workspaceManager;
|
||||||
|
|
||||||
static bool registeredMonitors = false;
|
static bool registeredMonitor = false;
|
||||||
static bool registeredGroup = false;
|
static bool registeredGroup = false;
|
||||||
static bool registeredWorkspace = false;
|
static bool registeredWorkspace = false;
|
||||||
static bool registeredWorkspaceInfo = false;
|
static bool registeredWorkspaceInfo = false;
|
||||||
|
@ -87,22 +85,14 @@ namespace Wayland
|
||||||
// Workspace Group callbacks
|
// Workspace Group callbacks
|
||||||
static void OnWSGroupOutputEnter(void*, zext_workspace_group_handle_v1* group, wl_output* output)
|
static void OnWSGroupOutputEnter(void*, zext_workspace_group_handle_v1* group, wl_output* output)
|
||||||
{
|
{
|
||||||
auto monitor = std::find_if(monitors.begin(), monitors.end(),
|
auto monitor = monitors.find(output);
|
||||||
[&](const std::pair<std::string, Monitor>& mon)
|
|
||||||
{
|
|
||||||
return mon.second.output == output;
|
|
||||||
});
|
|
||||||
ASSERT(monitor != monitors.end(), "Wayland: Registered WS group before monitor!");
|
ASSERT(monitor != monitors.end(), "Wayland: Registered WS group before monitor!");
|
||||||
LOG("Wayland: Added group to monitor");
|
LOG("Wayland: Added group to monitor");
|
||||||
monitor->second.workspaceGroup = group;
|
monitor->second.workspaceGroup = group;
|
||||||
}
|
}
|
||||||
static void OnWSGroupOutputLeave(void*, zext_workspace_group_handle_v1*, wl_output* output)
|
static void OnWSGroupOutputLeave(void*, zext_workspace_group_handle_v1*, wl_output* output)
|
||||||
{
|
{
|
||||||
auto monitor = std::find_if(monitors.begin(), monitors.end(),
|
auto monitor = monitors.find(output);
|
||||||
[&](const std::pair<std::string, Monitor>& mon)
|
|
||||||
{
|
|
||||||
return mon.second.output == output;
|
|
||||||
});
|
|
||||||
ASSERT(monitor != monitors.end(), "Wayland: Registered WS group before monitor!");
|
ASSERT(monitor != monitors.end(), "Wayland: Registered WS group before monitor!");
|
||||||
LOG("Wayland: Added group to monitor");
|
LOG("Wayland: Added group to monitor");
|
||||||
monitor->second.workspaceGroup = nullptr;
|
monitor->second.workspaceGroup = nullptr;
|
||||||
|
@ -140,24 +130,22 @@ namespace Wayland
|
||||||
// Output Callbacks
|
// Output Callbacks
|
||||||
// Very bloated, indeed
|
// 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 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 OnOutputMode(void*, wl_output* output, uint32_t, int32_t width, int32_t height, int32_t)
|
||||||
static void OnOutputDone(void*, wl_output*) {}
|
{
|
||||||
|
auto it = monitors.find(output);
|
||||||
|
ASSERT(it != monitors.end(), "Error: OnOutputMode called on unknown monitor");
|
||||||
|
it->second.width = width;
|
||||||
|
it->second.height = height;
|
||||||
|
}
|
||||||
|
static void OnOutputDone(void*, wl_output* output) {}
|
||||||
static void OnOutputScale(void*, wl_output*, int32_t) {}
|
static void OnOutputScale(void*, wl_output*, int32_t) {}
|
||||||
static void OnOutputName(void*, wl_output* output, const char* name)
|
static void OnOutputName(void*, wl_output* output, const char* name)
|
||||||
{
|
{
|
||||||
std::string nameStr = name;
|
auto it = monitors.find(output);
|
||||||
auto it = monitors.find(nameStr);
|
ASSERT(it != monitors.end(), "Error: OnOutputName called on unknown monitor");
|
||||||
if (it == monitors.end())
|
it->second.name = name;
|
||||||
{
|
LOG("Wayland: Monitor at ID " << it->second.ID << " got name " << name);
|
||||||
LOG("Wayland: Registering monitor " << name << " at ID " << curID);
|
registeredMonitor = true;
|
||||||
registeredMonitors = true;
|
|
||||||
Monitor mon = {nameStr, output, nullptr, curID++};
|
|
||||||
monitors.try_emplace(nameStr, mon);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG("Wayland: Recovering monitor " << name << " at ID " << curID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static void OnOutputDescription(void*, wl_output*, const char*) {}
|
static void OnOutputDescription(void*, wl_output*, const char*) {}
|
||||||
wl_output_listener outputListener = {OnOutputGeometry, OnOutputMode, OnOutputDone, OnOutputScale, OnOutputName, OnOutputDescription};
|
wl_output_listener outputListener = {OnOutputGeometry, OnOutputMode, OnOutputDone, OnOutputScale, OnOutputName, OnOutputDescription};
|
||||||
|
@ -168,6 +156,10 @@ namespace Wayland
|
||||||
if (strcmp(interface, "wl_output") == 0)
|
if (strcmp(interface, "wl_output") == 0)
|
||||||
{
|
{
|
||||||
wl_output* output = (wl_output*)wl_registry_bind(registry, name, &wl_output_interface, 4);
|
wl_output* output = (wl_output*)wl_registry_bind(registry, name, &wl_output_interface, 4);
|
||||||
|
Monitor mon = Monitor{"", name, 0, 0, nullptr, (uint32_t)monitors.size()};
|
||||||
|
monitors.emplace(output, mon);
|
||||||
|
|
||||||
|
LOG("Wayland: Register <pending> at ID " << mon.ID);
|
||||||
wl_output_add_listener(output, &outputListener, nullptr);
|
wl_output_add_listener(output, &outputListener, nullptr);
|
||||||
}
|
}
|
||||||
if (strcmp(interface, "zext_workspace_manager_v1") == 0 && !Config::Get().useHyprlandIPC)
|
if (strcmp(interface, "zext_workspace_manager_v1") == 0 && !Config::Get().useHyprlandIPC)
|
||||||
|
@ -176,7 +168,31 @@ namespace Wayland
|
||||||
zext_workspace_manager_v1_add_listener(workspaceManager, &workspaceManagerListener, nullptr);
|
zext_workspace_manager_v1_add_listener(workspaceManager, &workspaceManagerListener, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void OnRegistryRemove(void*, wl_registry*, uint32_t) {}
|
static void OnRegistryRemove(void*, wl_registry*, uint32_t name)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(monitors.begin(), monitors.end(),
|
||||||
|
[&](const std::pair<wl_output*, const Monitor&>& elem)
|
||||||
|
{
|
||||||
|
return elem.second.wlName == name;
|
||||||
|
});
|
||||||
|
if (it != monitors.end())
|
||||||
|
{
|
||||||
|
LOG("Wayland: Removing monitor " << it->second.name << " at ID " << it->second.ID);
|
||||||
|
// Monitor has been removed. Update the ids of the other accordingly
|
||||||
|
for (auto& mon : monitors)
|
||||||
|
{
|
||||||
|
if (mon.second.ID > it->second.ID)
|
||||||
|
{
|
||||||
|
mon.second.ID -= 1;
|
||||||
|
auto name = mon.second.name.empty() ? "<pending>" : mon.second.name;
|
||||||
|
LOG("Wayland: " << name << " got new ID " << mon.second.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
registeredMonitor = true;
|
||||||
|
monitors.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wl_registry_listener registryListener = {OnRegistryAdd, OnRegistryRemove};
|
wl_registry_listener registryListener = {OnRegistryAdd, OnRegistryRemove};
|
||||||
|
|
||||||
// Dispatch events.
|
// Dispatch events.
|
||||||
|
@ -201,8 +217,8 @@ namespace Wayland
|
||||||
wl_registry_add_listener(registry, ®istryListener, nullptr);
|
wl_registry_add_listener(registry, ®istryListener, nullptr);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
WaitFor(registeredMonitors);
|
WaitFor(registeredMonitor);
|
||||||
registeredMonitors = false;
|
registeredMonitor = false;
|
||||||
|
|
||||||
if (!workspaceManager && !Config::Get().useHyprlandIPC)
|
if (!workspaceManager && !Config::Get().useHyprlandIPC)
|
||||||
{
|
{
|
||||||
|
@ -255,7 +271,6 @@ namespace Wayland
|
||||||
registeredGroup = false;
|
registeredGroup = false;
|
||||||
registeredWorkspace = false;
|
registeredWorkspace = false;
|
||||||
registeredWorkspaceInfo = false;
|
registeredWorkspaceInfo = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
|
@ -264,7 +279,33 @@ namespace Wayland
|
||||||
wl_display_disconnect(display);
|
wl_display_disconnect(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::unordered_map<std::string, Monitor>& GetMonitors()
|
std::string GtkMonitorIDToName(int32_t monitorID)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(monitors.begin(), monitors.end(),
|
||||||
|
[&](const std::pair<wl_output*, Monitor>& el)
|
||||||
|
{
|
||||||
|
return el.second.ID == (uint32_t)monitorID;
|
||||||
|
});
|
||||||
|
if (it == monitors.end())
|
||||||
|
{
|
||||||
|
LOG("Wayland: No monitor registered with ID " << monitorID);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return it->second.name;
|
||||||
|
}
|
||||||
|
int32_t NameToGtkMonitorID(const std::string& name)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(monitors.begin(), monitors.end(),
|
||||||
|
[&](const std::pair<wl_output*, Monitor>& el)
|
||||||
|
{
|
||||||
|
return el.second.name == name;
|
||||||
|
});
|
||||||
|
if (it == monitors.end())
|
||||||
|
return -1;
|
||||||
|
return it->second.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<wl_output*, Monitor>& GetMonitors()
|
||||||
{
|
{
|
||||||
return monitors;
|
return monitors;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,11 @@ namespace Wayland
|
||||||
struct Monitor
|
struct Monitor
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
wl_output* output;
|
uint32_t wlName;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
zext_workspace_group_handle_v1* workspaceGroup;
|
zext_workspace_group_handle_v1* workspaceGroup;
|
||||||
|
// The Gdk monitor index. This is only a hacky approximation, since there is no way to get the wl_output from a GdkMonitor
|
||||||
uint32_t ID;
|
uint32_t ID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,9 +32,13 @@ namespace Wayland
|
||||||
void Init();
|
void Init();
|
||||||
void PollEvents();
|
void PollEvents();
|
||||||
|
|
||||||
const std::unordered_map<std::string, Monitor>& GetMonitors();
|
const std::unordered_map<wl_output*, Monitor>& GetMonitors();
|
||||||
const std::unordered_map<zext_workspace_group_handle_v1*, WorkspaceGroup>& GetWorkspaceGroups();
|
const std::unordered_map<zext_workspace_group_handle_v1*, WorkspaceGroup>& GetWorkspaceGroups();
|
||||||
const std::unordered_map<zext_workspace_handle_v1*, Workspace>& GetWorkspaces();
|
const std::unordered_map<zext_workspace_handle_v1*, Workspace>& GetWorkspaces();
|
||||||
|
|
||||||
|
// Returns the connector name of the monitor
|
||||||
|
std::string GtkMonitorIDToName(int32_t monitorID);
|
||||||
|
int32_t NameToGtkMonitorID(const std::string& name);
|
||||||
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
}
|
}
|
||||||
|
|
160
src/Window.cpp
160
src/Window.cpp
|
@ -1,14 +1,15 @@
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "CSS.h"
|
#include "CSS.h"
|
||||||
|
#include "Wayland.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include <thread>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <gtk-layer-shell.h>
|
#include <gtk-layer-shell.h>
|
||||||
|
|
||||||
Window::Window(int32_t monitor) : m_MonitorID(monitor) {}
|
Window::Window(int32_t monitor) : m_MonitorName(Wayland::GtkMonitorIDToName(monitor)) {}
|
||||||
|
Window::Window(const std::string& monitor) : m_MonitorName(monitor) {}
|
||||||
|
|
||||||
Window::~Window()
|
Window::~Window()
|
||||||
{
|
{
|
||||||
|
@ -21,6 +22,8 @@ Window::~Window()
|
||||||
|
|
||||||
void Window::Init(const std::string& overideConfigLocation)
|
void Window::Init(const std::string& overideConfigLocation)
|
||||||
{
|
{
|
||||||
|
m_TargetMonitor = m_MonitorName;
|
||||||
|
|
||||||
gtk_init(NULL, NULL);
|
gtk_init(NULL, NULL);
|
||||||
|
|
||||||
// Style
|
// Style
|
||||||
|
@ -30,13 +33,14 @@ void Window::Init(const std::string& overideConfigLocation)
|
||||||
|
|
||||||
GdkDisplay* defaultDisplay = gdk_display_get_default();
|
GdkDisplay* defaultDisplay = gdk_display_get_default();
|
||||||
ASSERT(defaultDisplay != nullptr, "Cannot get display!");
|
ASSERT(defaultDisplay != nullptr, "Cannot get display!");
|
||||||
if (m_MonitorID != -1)
|
if (!m_MonitorName.empty())
|
||||||
{
|
{
|
||||||
m_Monitor = gdk_display_get_monitor(defaultDisplay, m_MonitorID);
|
m_Monitor = gdk_display_get_monitor(defaultDisplay, Wayland::NameToGtkMonitorID(m_MonitorName));
|
||||||
ASSERT(m_Monitor, "Cannot get monitor!");
|
ASSERT(m_Monitor, "Cannot get monitor \"" << m_MonitorName << "\"!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LOG("Window: Requested monitor not found. Falling back to current monitor!")
|
||||||
m_Monitor = gdk_display_get_primary_monitor(defaultDisplay);
|
m_Monitor = gdk_display_get_primary_monitor(defaultDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,12 +59,87 @@ void Window::Init(const std::string& overideConfigLocation)
|
||||||
|
|
||||||
void Window::Run()
|
void Window::Run()
|
||||||
{
|
{
|
||||||
ASSERT(m_MainWidget, "Main Widget not set!");
|
Create();
|
||||||
|
while (gtk_main_iteration())
|
||||||
|
{
|
||||||
|
if (bHandleMonitorChanges)
|
||||||
|
{
|
||||||
|
// Flush the event loop
|
||||||
|
while (gtk_events_pending())
|
||||||
|
{
|
||||||
|
if (!gtk_main_iteration())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("Window: Handling monitor changes");
|
||||||
|
bHandleMonitorChanges = false;
|
||||||
|
|
||||||
|
if (m_MonitorName == m_TargetMonitor)
|
||||||
|
{
|
||||||
|
// Don't care
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Process Wayland
|
||||||
|
Wayland::PollEvents();
|
||||||
|
|
||||||
|
GdkDisplay* display = gdk_display_get_default();
|
||||||
|
auto& mons = Wayland::GetMonitors();
|
||||||
|
|
||||||
|
// HACK: Discrepancies are mostly caused by the HEADLESS monitor. Assume that.
|
||||||
|
bool bGotHeadless = (size_t)gdk_display_get_n_monitors(display) != mons.size();
|
||||||
|
if (bGotHeadless)
|
||||||
|
{
|
||||||
|
LOG("Window: Found discrepancy between GDK and Wayland!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find our target monitor
|
||||||
|
auto it = std::find_if(mons.begin(), mons.end(),
|
||||||
|
[&](const std::pair<wl_output*, Wayland::Monitor>& mon)
|
||||||
|
{
|
||||||
|
return mon.second.name == m_TargetMonitor;
|
||||||
|
});
|
||||||
|
if (it != mons.end())
|
||||||
|
{
|
||||||
|
// Found target monitor, snap back.
|
||||||
|
if (m_MainWidget)
|
||||||
|
Destroy();
|
||||||
|
m_MonitorName = m_TargetMonitor;
|
||||||
|
m_Monitor = gdk_display_get_monitor(display, bGotHeadless ? it->second.ID + 1 : it->second.ID);
|
||||||
|
Create();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We haven't yet created, check if we can.
|
||||||
|
if (m_MainWidget == nullptr)
|
||||||
|
{
|
||||||
|
// Find a non-headless monitor
|
||||||
|
auto it = std::find_if(mons.begin(), mons.end(),
|
||||||
|
[&](const std::pair<wl_output*, Wayland::Monitor>& mon)
|
||||||
|
{
|
||||||
|
return mon.second.name.find("HEADLESS") == std::string::npos;
|
||||||
|
});
|
||||||
|
if (it == mons.end())
|
||||||
|
continue;
|
||||||
|
m_MonitorName = it->second.name;
|
||||||
|
m_Monitor = gdk_display_get_monitor(display, bGotHeadless ? it->second.ID + 1 : it->second.ID);
|
||||||
|
Create();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::Create()
|
||||||
|
{
|
||||||
|
LOG("Window: Create on monitor " << m_MonitorName);
|
||||||
m_Window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
m_Window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
||||||
gtk_layer_init_for_window(m_Window);
|
gtk_layer_init_for_window(m_Window);
|
||||||
|
|
||||||
|
// Notify our main method, that we want to init
|
||||||
|
OnWidget();
|
||||||
|
|
||||||
|
ASSERT(m_MainWidget, "Main Widget not set!");
|
||||||
|
|
||||||
switch (m_Layer)
|
switch (m_Layer)
|
||||||
{
|
{
|
||||||
case Layer::Top: gtk_layer_set_layer(m_Window, GTK_LAYER_SHELL_LAYER_TOP); break;
|
case Layer::Top: gtk_layer_set_layer(m_Window, GTK_LAYER_SHELL_LAYER_TOP); break;
|
||||||
|
@ -94,13 +173,18 @@ void Window::Run()
|
||||||
Widget::CreateAndAddWidget(m_MainWidget.get(), (GtkWidget*)m_Window);
|
Widget::CreateAndAddWidget(m_MainWidget.get(), (GtkWidget*)m_Window);
|
||||||
|
|
||||||
gtk_widget_show_all((GtkWidget*)m_Window);
|
gtk_widget_show_all((GtkWidget*)m_Window);
|
||||||
|
}
|
||||||
|
|
||||||
gtk_main();
|
void Window::Destroy()
|
||||||
|
{
|
||||||
|
LOG("Window: Destroy");
|
||||||
|
m_MainWidget = nullptr;
|
||||||
|
gtk_widget_destroy((GtkWidget*)m_Window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::Close()
|
void Window::Close()
|
||||||
{
|
{
|
||||||
gtk_widget_hide((GtkWidget*)m_Window);
|
Destroy();
|
||||||
gtk_main_quit();
|
gtk_main_quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,42 +243,52 @@ void Window::SetMargin(Anchor anchor, int32_t margin)
|
||||||
|
|
||||||
int Window::GetWidth() const
|
int Window::GetWidth() const
|
||||||
{
|
{
|
||||||
GdkRectangle rect{};
|
// gdk_monitor_get_geometry is really unreliable for some reason.
|
||||||
|
// Use our wayland backend instead
|
||||||
|
|
||||||
|
/*GdkRectangle rect{};
|
||||||
gdk_monitor_get_geometry(m_Monitor, &rect);
|
gdk_monitor_get_geometry(m_Monitor, &rect);
|
||||||
return rect.width;
|
return rect.width;*/
|
||||||
|
auto& mons = Wayland::GetMonitors();
|
||||||
|
auto it = std::find_if(mons.begin(), mons.end(),
|
||||||
|
[&](const std::pair<wl_output*, Wayland::Monitor>& mon)
|
||||||
|
{
|
||||||
|
return mon.second.name == m_MonitorName;
|
||||||
|
});
|
||||||
|
ASSERT(it != mons.end(), "Window: Couldn't find monitor");
|
||||||
|
return it->second.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::GetHeight() const
|
int Window::GetHeight() const
|
||||||
{
|
{
|
||||||
GdkRectangle rect{};
|
/*GdkRectangle rect{};
|
||||||
gdk_monitor_get_geometry(m_Monitor, &rect);
|
gdk_monitor_get_geometry(m_Monitor, &rect);
|
||||||
return rect.height;
|
return rect.height;*/
|
||||||
|
|
||||||
|
auto& mons = Wayland::GetMonitors();
|
||||||
|
auto it = std::find_if(mons.begin(), mons.end(),
|
||||||
|
[&](const std::pair<wl_output*, Wayland::Monitor>& mon)
|
||||||
|
{
|
||||||
|
return mon.second.name == m_MonitorName;
|
||||||
|
});
|
||||||
|
ASSERT(it != mons.end(), "Window: Couldn't find monitor");
|
||||||
|
return it->second.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::MonitorAdded(GdkDisplay* display, GdkMonitor* mon)
|
void Window::MonitorAdded(GdkDisplay*, GdkMonitor*)
|
||||||
{
|
{
|
||||||
LOG("Window: Monitor added: " << mon);
|
bHandleMonitorChanges = true;
|
||||||
if (!m_Monitor)
|
|
||||||
{
|
|
||||||
LOG("Window: Activating window");
|
|
||||||
gtk_layer_set_monitor(m_Window, mon);
|
|
||||||
m_Monitor = mon;
|
|
||||||
gtk_widget_show_all((GtkWidget*)m_Window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::MonitorRemoved(GdkDisplay* display, GdkMonitor* mon)
|
void Window::MonitorRemoved(GdkDisplay*, GdkMonitor* mon)
|
||||||
{
|
{
|
||||||
LOG("Window: Monitor removed: " << mon);
|
bHandleMonitorChanges = true;
|
||||||
|
// Immediately react
|
||||||
if (mon == m_Monitor)
|
if (mon == m_Monitor)
|
||||||
{
|
{
|
||||||
// Hide the window, so it doesn't get rendered on an invalid monitor
|
LOG("Window: Current monitor removed!")
|
||||||
gtk_widget_hide((GtkWidget*)m_Window);
|
m_Monitor = nullptr;
|
||||||
// Notify gtk layer shell and redisplay window
|
m_MonitorName = "";
|
||||||
gtk_layer_set_monitor(m_Window, nullptr);
|
Destroy();
|
||||||
m_Monitor = gtk_layer_get_monitor(m_Window);
|
|
||||||
LOG("Window: New Monitor: " << m_Monitor);
|
|
||||||
if (m_Monitor)
|
|
||||||
gtk_widget_show_all((GtkWidget*)m_Window);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
src/Window.h
19
src/Window.h
|
@ -23,6 +23,7 @@ class Window
|
||||||
public:
|
public:
|
||||||
Window() = default;
|
Window() = default;
|
||||||
Window(int32_t monitor);
|
Window(int32_t monitor);
|
||||||
|
Window(const std::string& monitor);
|
||||||
Window(Window&& window) noexcept = default;
|
Window(Window&& window) noexcept = default;
|
||||||
Window& operator=(Window&& other) noexcept = default;
|
Window& operator=(Window&& other) noexcept = default;
|
||||||
~Window();
|
~Window();
|
||||||
|
@ -42,7 +43,16 @@ public:
|
||||||
int GetWidth() const;
|
int GetWidth() const;
|
||||||
int GetHeight() const;
|
int GetHeight() const;
|
||||||
|
|
||||||
|
// Returns the connector name of the currnet monitor
|
||||||
|
std::string GetName() const { return m_MonitorName; }
|
||||||
|
|
||||||
|
// Callback when the widget should be recreated
|
||||||
|
std::function<void()> OnWidget;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void Create();
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
void UpdateMargin();
|
void UpdateMargin();
|
||||||
|
|
||||||
void LoadCSS(GtkCssProvider* provider);
|
void LoadCSS(GtkCssProvider* provider);
|
||||||
|
@ -60,6 +70,13 @@ private:
|
||||||
bool m_Exclusive = true;
|
bool m_Exclusive = true;
|
||||||
Layer m_Layer = Layer::Top;
|
Layer m_Layer = Layer::Top;
|
||||||
|
|
||||||
int32_t m_MonitorID;
|
// The monitor we are currently on.
|
||||||
|
std::string m_MonitorName;
|
||||||
|
|
||||||
|
// The monitor we want to be on.
|
||||||
|
std::string m_TargetMonitor;
|
||||||
|
|
||||||
GdkMonitor* m_Monitor = nullptr;
|
GdkMonitor* m_Monitor = nullptr;
|
||||||
|
|
||||||
|
bool bHandleMonitorChanges = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,19 +12,19 @@ namespace Workspaces
|
||||||
using WaylandWorkspaceGroup = ::Wayland::WorkspaceGroup;
|
using WaylandWorkspaceGroup = ::Wayland::WorkspaceGroup;
|
||||||
using WaylandWorkspace = ::Wayland::Workspace;
|
using WaylandWorkspace = ::Wayland::Workspace;
|
||||||
|
|
||||||
static uint32_t lastPolledMonitor;
|
static std::string lastPolledMonitor;
|
||||||
void PollStatus(uint32_t monitorID, uint32_t)
|
void PollStatus(const std::string& monitor, uint32_t)
|
||||||
{
|
{
|
||||||
::Wayland::PollEvents();
|
::Wayland::PollEvents();
|
||||||
lastPolledMonitor = monitorID;
|
lastPolledMonitor = monitor;
|
||||||
}
|
}
|
||||||
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
||||||
{
|
{
|
||||||
auto& mons = ::Wayland::GetMonitors();
|
auto& mons = ::Wayland::GetMonitors();
|
||||||
auto it = std::find_if(mons.begin(), mons.end(),
|
auto it = std::find_if(mons.begin(), mons.end(),
|
||||||
[&](const std::pair<std::string, ::Wayland::Monitor>& mon)
|
[&](const std::pair<wl_output*, ::Wayland::Monitor>& mon)
|
||||||
{
|
{
|
||||||
return mon.second.ID == workspaceId;
|
return mon.second.name == lastPolledMonitor;
|
||||||
});
|
});
|
||||||
if (it == mons.end())
|
if (it == mons.end())
|
||||||
{
|
{
|
||||||
|
@ -147,7 +147,7 @@ namespace Workspaces
|
||||||
|
|
||||||
static std::vector<System::WorkspaceStatus> workspaceStati;
|
static std::vector<System::WorkspaceStatus> workspaceStati;
|
||||||
|
|
||||||
void PollStatus(uint32_t monitorID, uint32_t numWorkspaces)
|
void PollStatus(const std::string& monitor, uint32_t numWorkspaces)
|
||||||
{
|
{
|
||||||
if (RuntimeConfig::Get().hasWorkspaces == false)
|
if (RuntimeConfig::Get().hasWorkspaces == false)
|
||||||
{
|
{
|
||||||
|
@ -182,11 +182,11 @@ namespace Workspaces
|
||||||
parseIdx = 0;
|
parseIdx = 0;
|
||||||
while ((parseIdx = monitors.find("Monitor ", parseIdx)) != std::string::npos)
|
while ((parseIdx = monitors.find("Monitor ", parseIdx)) != std::string::npos)
|
||||||
{
|
{
|
||||||
// Goto ( and remove ID (=Advance 4 spaces, 1 for (, two for ID, one for space)
|
// Query monitor name
|
||||||
size_t begMonNum = monitors.find('(', parseIdx) + 4;
|
// Format: Monitor <name> (ID <id>)
|
||||||
size_t endMonNum = monitors.find(')', begMonNum);
|
size_t begMonNum = monitors.find(' ', parseIdx) + 1;
|
||||||
|
size_t endMonNum = monitors.find(' ', begMonNum);
|
||||||
std::string mon = monitors.substr(begMonNum, endMonNum - begMonNum);
|
std::string mon = monitors.substr(begMonNum, endMonNum - begMonNum);
|
||||||
int32_t monIdx = std::atoi(mon.c_str());
|
|
||||||
|
|
||||||
// Parse active workspace
|
// Parse active workspace
|
||||||
parseIdx = monitors.find("active workspace: ", parseIdx);
|
parseIdx = monitors.find("active workspace: ", parseIdx);
|
||||||
|
@ -205,7 +205,7 @@ namespace Workspaces
|
||||||
|
|
||||||
if (wsId >= 1 && wsId <= (int32_t)numWorkspaces)
|
if (wsId >= 1 && wsId <= (int32_t)numWorkspaces)
|
||||||
{
|
{
|
||||||
if ((uint32_t)monIdx == monitorID)
|
if (mon == monitor)
|
||||||
{
|
{
|
||||||
if (focused)
|
if (focused)
|
||||||
{
|
{
|
||||||
|
@ -248,16 +248,16 @@ namespace Workspaces
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollStatus(uint32_t monitorID, uint32_t numWorkspaces)
|
void PollStatus(const std::string& monitor, uint32_t numWorkspaces)
|
||||||
{
|
{
|
||||||
#ifdef WITH_HYPRLAND
|
#ifdef WITH_HYPRLAND
|
||||||
if (Config::Get().useHyprlandIPC)
|
if (Config::Get().useHyprlandIPC)
|
||||||
{
|
{
|
||||||
Hyprland::PollStatus(monitorID, numWorkspaces);
|
Hyprland::PollStatus(monitor, numWorkspaces);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Wayland::PollStatus(monitorID, numWorkspaces);
|
Wayland::PollStatus(monitor, numWorkspaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Workspaces
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void PollStatus(uint32_t monitorID, uint32_t numWorkspaces);
|
void PollStatus(const std::string& monitor, uint32_t numWorkspaces);
|
||||||
|
|
||||||
System::WorkspaceStatus GetStatus(uint32_t workspaceId);
|
System::WorkspaceStatus GetStatus(uint32_t workspaceId);
|
||||||
|
|
||||||
|
|
112
src/gBar.cpp
112
src/gBar.cpp
|
@ -16,7 +16,7 @@ const char* bluetoothTmpFilePath = "/tmp/gBar__bluetooth";
|
||||||
|
|
||||||
static bool tmpFileOpen = false;
|
static bool tmpFileOpen = false;
|
||||||
|
|
||||||
void OpenAudioFlyin(Window& window, int32_t monitor, AudioFlyin::Type type)
|
void OpenAudioFlyin(Window& window, const std::string& monitor, AudioFlyin::Type type)
|
||||||
{
|
{
|
||||||
tmpFileOpen = true;
|
tmpFileOpen = true;
|
||||||
if (access(audioTmpFilePath, F_OK) != 0)
|
if (access(audioTmpFilePath, F_OK) != 0)
|
||||||
|
@ -71,10 +71,57 @@ void PrintHelp()
|
||||||
"\t[plugin] \tTries to open and run the plugin lib[plugin].so\n");
|
"\t[plugin] \tTries to open and run the plugin lib[plugin].so\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreateWidget(const std::string& widget, Window& window)
|
||||||
|
{
|
||||||
|
if (widget == "bar")
|
||||||
|
{
|
||||||
|
Bar::Create(window, window.GetName());
|
||||||
|
}
|
||||||
|
else if (widget == "audio")
|
||||||
|
{
|
||||||
|
OpenAudioFlyin(window, window.GetName(), AudioFlyin::Type::Speaker);
|
||||||
|
}
|
||||||
|
else if (widget == "mic")
|
||||||
|
{
|
||||||
|
OpenAudioFlyin(window, window.GetName(), AudioFlyin::Type::Microphone);
|
||||||
|
}
|
||||||
|
#ifdef WITH_BLUEZ
|
||||||
|
else if (widget == "bluetooth")
|
||||||
|
{
|
||||||
|
if (RuntimeConfig::Get().hasBlueZ)
|
||||||
|
{
|
||||||
|
if (access(bluetoothTmpFilePath, F_OK) != 0)
|
||||||
|
{
|
||||||
|
tmpFileOpen = true;
|
||||||
|
FILE* bluetoothTmpFile = fopen(bluetoothTmpFilePath, "w");
|
||||||
|
BluetoothDevices::Create(window, window.GetName());
|
||||||
|
fclose(bluetoothTmpFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Already open, close
|
||||||
|
LOG("Bluetooth widget already open (/tmp/gBar__bluetooth exists)! Exiting...");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("Blutooth disabled, cannot open bluetooth widget!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Plugin::LoadWidgetFromPlugin(widget, window, window.GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
std::string widget;
|
std::string widget;
|
||||||
int32_t monitor = -1;
|
int32_t monitor = -1;
|
||||||
|
std::string monitorName;
|
||||||
std::string overrideConfigLocation = "";
|
std::string overrideConfigLocation = "";
|
||||||
|
|
||||||
// Arg parsing
|
// Arg parsing
|
||||||
|
@ -83,20 +130,27 @@ int main(int argc, char** argv)
|
||||||
std::string arg = argv[i];
|
std::string arg = argv[i];
|
||||||
if (arg.size() < 1 || arg[0] != '-')
|
if (arg.size() < 1 || arg[0] != '-')
|
||||||
{
|
{
|
||||||
// This must be the widget selection
|
// This must be the widget selection.
|
||||||
widget = arg;
|
widget = arg;
|
||||||
if (i + 1 < argc)
|
if (i + 1 < argc)
|
||||||
{
|
{
|
||||||
std::string mon = argv[i + 1];
|
std::string mon = argv[i + 1];
|
||||||
if (mon.size() < 1 || mon[0] != '-')
|
|
||||||
|
// Check if a monitor was supplied
|
||||||
|
if (mon.empty() || mon[0] == '-')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (std::isdigit(mon[0]))
|
||||||
{
|
{
|
||||||
// Next comes the monitor
|
// Monitor using ID
|
||||||
monitor = std::stoi(mon);
|
monitor = std::stoi(mon);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Not the monitor
|
// Monitor using connector name
|
||||||
|
monitorName = std::move(mon);
|
||||||
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,51 +187,21 @@ int main(int argc, char** argv)
|
||||||
signal(SIGINT, CloseTmpFiles);
|
signal(SIGINT, CloseTmpFiles);
|
||||||
System::Init(overrideConfigLocation);
|
System::Init(overrideConfigLocation);
|
||||||
|
|
||||||
Window window(monitor);
|
Window window;
|
||||||
window.Init(overrideConfigLocation);
|
if (monitor != -1)
|
||||||
if (widget == "bar")
|
|
||||||
{
|
{
|
||||||
Bar::Create(window, monitor);
|
window = Window(monitor);
|
||||||
}
|
|
||||||
else if (widget == "audio")
|
|
||||||
{
|
|
||||||
OpenAudioFlyin(window, monitor, AudioFlyin::Type::Speaker);
|
|
||||||
}
|
|
||||||
else if (widget == "mic")
|
|
||||||
{
|
|
||||||
OpenAudioFlyin(window, monitor, AudioFlyin::Type::Microphone);
|
|
||||||
}
|
|
||||||
#ifdef WITH_BLUEZ
|
|
||||||
else if (widget == "bluetooth")
|
|
||||||
{
|
|
||||||
if (RuntimeConfig::Get().hasBlueZ)
|
|
||||||
{
|
|
||||||
if (access(bluetoothTmpFilePath, F_OK) != 0)
|
|
||||||
{
|
|
||||||
tmpFileOpen = true;
|
|
||||||
FILE* bluetoothTmpFile = fopen(bluetoothTmpFilePath, "w");
|
|
||||||
BluetoothDevices::Create(window, monitor);
|
|
||||||
fclose(bluetoothTmpFile);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Already open, close
|
window = Window(monitorName);
|
||||||
LOG("Bluetooth widget already open (/tmp/gBar__bluetooth exists)! Exiting...");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG("Blutooth disabled, cannot open bluetooth widget!");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Plugin::LoadWidgetFromPlugin(widget, window, monitor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.Init(overrideConfigLocation);
|
||||||
|
window.OnWidget = [&]()
|
||||||
|
{
|
||||||
|
CreateWidget(widget, window);
|
||||||
|
};
|
||||||
window.Run();
|
window.Run();
|
||||||
|
|
||||||
System::FreeResources();
|
System::FreeResources();
|
||||||
|
|
Loading…
Reference in a new issue