mirror of
https://github.com/scorpion-26/gBar.git
synced 2024-11-22 11:12:49 +00:00
Don't crash on monitor remove
gBar no longer crashes when it's monitor is removed and is instead evacuated onto another monitor or the next monitor added. We don't change any monitor indices etc., which results in some glitchy results
This commit is contained in:
parent
097c3d97e7
commit
18170ab1c7
5 changed files with 93 additions and 17 deletions
|
@ -8,7 +8,7 @@
|
||||||
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<uint32_t, Monitor> monitors;
|
static std::unordered_map<std::string, 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;
|
||||||
|
|
||||||
|
@ -27,11 +27,18 @@ namespace Wayland
|
||||||
|
|
||||||
// Workspace Callbacks
|
// Workspace Callbacks
|
||||||
static void OnWorkspaceName(void*, zext_workspace_handle_v1* workspace, const char* name)
|
static void OnWorkspaceName(void*, zext_workspace_handle_v1* workspace, const char* name)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
workspaces[workspace].id = std::stoul(name);
|
workspaces[workspace].id = std::stoul(name);
|
||||||
LOG("Workspace ID: " << workspaces[workspace].id);
|
LOG("Workspace ID: " << workspaces[workspace].id);
|
||||||
registeredWorkspaceInfo = true;
|
registeredWorkspaceInfo = true;
|
||||||
}
|
}
|
||||||
|
catch (const std::invalid_argument&)
|
||||||
|
{
|
||||||
|
LOG("Wayland: Invalid WS name: " << name);
|
||||||
|
}
|
||||||
|
}
|
||||||
static void OnWorkspaceGeometry(void*, zext_workspace_handle_v1*, wl_array*) {}
|
static void OnWorkspaceGeometry(void*, zext_workspace_handle_v1*, wl_array*) {}
|
||||||
static void OnWorkspaceState(void*, zext_workspace_handle_v1* ws, wl_array* arrState)
|
static void OnWorkspaceState(void*, zext_workspace_handle_v1* ws, wl_array* arrState)
|
||||||
{
|
{
|
||||||
|
@ -67,6 +74,13 @@ namespace Wayland
|
||||||
workspaces.erase(ws);
|
workspaces.erase(ws);
|
||||||
|
|
||||||
LOG("Wayland: Removed workspace!");
|
LOG("Wayland: Removed workspace!");
|
||||||
|
if (group.lastActiveWorkspace == ws)
|
||||||
|
{
|
||||||
|
if (group.workspaces.size())
|
||||||
|
group.lastActiveWorkspace = group.workspaces[0];
|
||||||
|
else
|
||||||
|
group.lastActiveWorkspace = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
zext_workspace_handle_v1_listener workspaceListener = {OnWorkspaceName, OnWorkspaceGeometry, OnWorkspaceState, OnWorkspaceRemove};
|
zext_workspace_handle_v1_listener workspaceListener = {OnWorkspaceName, OnWorkspaceGeometry, OnWorkspaceState, OnWorkspaceRemove};
|
||||||
|
|
||||||
|
@ -74,7 +88,7 @@ namespace Wayland
|
||||||
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 = std::find_if(monitors.begin(), monitors.end(),
|
||||||
[&](const std::pair<uint32_t, Monitor>& mon)
|
[&](const std::pair<std::string, Monitor>& mon)
|
||||||
{
|
{
|
||||||
return mon.second.output == output;
|
return mon.second.output == output;
|
||||||
});
|
});
|
||||||
|
@ -85,7 +99,7 @@ namespace Wayland
|
||||||
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 = std::find_if(monitors.begin(), monitors.end(),
|
||||||
[&](const std::pair<uint32_t, Monitor>& mon)
|
[&](const std::pair<std::string, Monitor>& mon)
|
||||||
{
|
{
|
||||||
return mon.second.output == output;
|
return mon.second.output == output;
|
||||||
});
|
});
|
||||||
|
@ -130,10 +144,20 @@ namespace Wayland
|
||||||
static void OnOutputDone(void*, wl_output*) {}
|
static void OnOutputDone(void*, wl_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(nameStr);
|
||||||
|
if (it == monitors.end())
|
||||||
{
|
{
|
||||||
LOG("Wayland: Registering monitor " << name << " at ID " << curID);
|
LOG("Wayland: Registering monitor " << name << " at ID " << curID);
|
||||||
registeredMonitors = true;
|
registeredMonitors = true;
|
||||||
monitors.try_emplace(curID++, Monitor{name, output, nullptr});
|
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};
|
||||||
|
@ -198,7 +222,7 @@ namespace Wayland
|
||||||
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*, Workspace>& ws)
|
[&](const std::pair<zext_workspace_handle_v1*, Workspace>& ws)
|
||||||
{
|
{
|
||||||
return ws.second.id == monitor.first + 1;
|
return ws.second.id == monitor.second.ID + 1;
|
||||||
});
|
});
|
||||||
if (workspaceIt != workspaces.end())
|
if (workspaceIt != workspaces.end())
|
||||||
{
|
{
|
||||||
|
@ -240,7 +264,7 @@ namespace Wayland
|
||||||
wl_display_disconnect(display);
|
wl_display_disconnect(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::unordered_map<uint32_t, Monitor>& GetMonitors()
|
const std::unordered_map<std::string, Monitor>& GetMonitors()
|
||||||
{
|
{
|
||||||
return monitors;
|
return monitors;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace Wayland
|
||||||
std::string name;
|
std::string name;
|
||||||
wl_output* output;
|
wl_output* output;
|
||||||
zext_workspace_group_handle_v1* workspaceGroup;
|
zext_workspace_group_handle_v1* workspaceGroup;
|
||||||
|
uint32_t ID;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Workspace
|
struct Workspace
|
||||||
|
@ -28,7 +29,7 @@ namespace Wayland
|
||||||
void Init();
|
void Init();
|
||||||
void PollEvents();
|
void PollEvents();
|
||||||
|
|
||||||
const std::unordered_map<uint32_t, Monitor>& GetMonitors();
|
const std::unordered_map<std::string, 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();
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,18 @@ void Window::Init(const std::string& overideConfigLocation)
|
||||||
{
|
{
|
||||||
m_Monitor = gdk_display_get_primary_monitor(defaultDisplay);
|
m_Monitor = gdk_display_get_primary_monitor(defaultDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register monitor added/removed callbacks
|
||||||
|
auto monAdded = [](GdkDisplay* display, GdkMonitor* mon, void* window)
|
||||||
|
{
|
||||||
|
((Window*)window)->MonitorAdded(display, mon);
|
||||||
|
};
|
||||||
|
g_signal_connect(defaultDisplay, "monitor-added", G_CALLBACK(+monAdded), this);
|
||||||
|
auto monRemoved = [](GdkDisplay* display, GdkMonitor* mon, void* window)
|
||||||
|
{
|
||||||
|
((Window*)window)->MonitorRemoved(display, mon);
|
||||||
|
};
|
||||||
|
g_signal_connect(defaultDisplay, "monitor-removed", G_CALLBACK(+monRemoved), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::Run()
|
void Window::Run()
|
||||||
|
@ -158,3 +170,31 @@ int Window::GetHeight() const
|
||||||
gdk_monitor_get_geometry(m_Monitor, &rect);
|
gdk_monitor_get_geometry(m_Monitor, &rect);
|
||||||
return rect.height;
|
return rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::MonitorAdded(GdkDisplay* display, GdkMonitor* mon)
|
||||||
|
{
|
||||||
|
LOG("Window: Monitor added: " << mon);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
LOG("Window: Monitor removed: " << mon);
|
||||||
|
if (mon == m_Monitor)
|
||||||
|
{
|
||||||
|
// Hide the window, so it doesn't get rendered on an invalid monitor
|
||||||
|
gtk_widget_hide((GtkWidget*)m_Window);
|
||||||
|
// Notify gtk layer shell and redisplay window
|
||||||
|
gtk_layer_set_monitor(m_Window, nullptr);
|
||||||
|
m_Monitor = gtk_layer_get_monitor(m_Window);
|
||||||
|
LOG("Window: New Monitor: " << m_Monitor);
|
||||||
|
if (m_Monitor)
|
||||||
|
gtk_widget_show_all((GtkWidget*)m_Window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -41,11 +41,15 @@ public:
|
||||||
|
|
||||||
int GetWidth() const;
|
int GetWidth() const;
|
||||||
int GetHeight() const;
|
int GetHeight() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateMargin();
|
void UpdateMargin();
|
||||||
|
|
||||||
void LoadCSS(GtkCssProvider* provider);
|
void LoadCSS(GtkCssProvider* provider);
|
||||||
|
|
||||||
|
void MonitorAdded(GdkDisplay* display, GdkMonitor* monitor);
|
||||||
|
void MonitorRemoved(GdkDisplay* display, GdkMonitor* monitor);
|
||||||
|
|
||||||
GtkWindow* m_Window = nullptr;
|
GtkWindow* m_Window = nullptr;
|
||||||
GtkApplication* m_App = nullptr;
|
GtkApplication* m_App = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,18 @@ namespace Workspaces
|
||||||
}
|
}
|
||||||
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
System::WorkspaceStatus GetStatus(uint32_t workspaceId)
|
||||||
{
|
{
|
||||||
const WaylandMonitor& monitor = ::Wayland::GetMonitors().at(lastPolledMonitor);
|
auto& mons = ::Wayland::GetMonitors();
|
||||||
if (!monitor.output)
|
auto it = std::find_if(mons.begin(), mons.end(),
|
||||||
|
[&](const std::pair<std::string, ::Wayland::Monitor>& mon)
|
||||||
|
{
|
||||||
|
return mon.second.ID == workspaceId;
|
||||||
|
});
|
||||||
|
if (it == mons.end())
|
||||||
{
|
{
|
||||||
LOG("Polled monitor doesn't exist!");
|
LOG("Polled monitor doesn't exist!");
|
||||||
return System::WorkspaceStatus::Dead;
|
return System::WorkspaceStatus::Dead;
|
||||||
}
|
}
|
||||||
|
const ::Wayland::Monitor& monitor = it->second;
|
||||||
|
|
||||||
auto& workspaces = ::Wayland::GetWorkspaces();
|
auto& workspaces = ::Wayland::GetWorkspaces();
|
||||||
auto workspaceIt = std::find_if(workspaces.begin(), workspaces.end(),
|
auto workspaceIt = std::find_if(workspaces.begin(), workspaces.end(),
|
||||||
|
@ -156,9 +162,10 @@ namespace Workspaces
|
||||||
std::string workspaces = DispatchIPC("/workspaces");
|
std::string workspaces = DispatchIPC("/workspaces");
|
||||||
while ((parseIdx = workspaces.find("workspace ID ", parseIdx)) != std::string::npos)
|
while ((parseIdx = workspaces.find("workspace ID ", parseIdx)) != std::string::npos)
|
||||||
{
|
{
|
||||||
// Goto (
|
// Advance two spaces
|
||||||
size_t begWSNum = workspaces.find('(', parseIdx) + 1;
|
size_t begWSNum = workspaces.find(' ', parseIdx) + 1;
|
||||||
size_t endWSNum = workspaces.find(')', begWSNum);
|
begWSNum = workspaces.find(' ', begWSNum) + 1;
|
||||||
|
size_t endWSNum = workspaces.find(' ', begWSNum);
|
||||||
|
|
||||||
std::string ws = workspaces.substr(begWSNum, endWSNum - begWSNum);
|
std::string ws = workspaces.substr(begWSNum, endWSNum - begWSNum);
|
||||||
int32_t wsId = std::atoi(ws.c_str());
|
int32_t wsId = std::atoi(ws.c_str());
|
||||||
|
|
Loading…
Reference in a new issue