mirror of
https://github.com/hyprwm/Hypr.git
synced 2024-12-02 01:15:59 +01:00
Bar modules upgrade
This commit is contained in:
parent
ec865f0f8e
commit
6224ffb078
18 changed files with 648 additions and 118 deletions
|
@ -25,7 +25,7 @@ Hypr is a Linux tiling window manager for Xorg. It's written in XCB with modern
|
||||||
|
|
||||||
## Roadmap v2 (not in order)
|
## Roadmap v2 (not in order)
|
||||||
- [x] Upgrade the status bar rendering to Cairo
|
- [x] Upgrade the status bar rendering to Cairo
|
||||||
- [ ] Better status bar configability
|
- [x] Better status bar configability ~ WIP
|
||||||
- [ ] Rounded corners
|
- [ ] Rounded corners
|
||||||
- [x] Replace default X11 cursor with the pointer
|
- [x] Replace default X11 cursor with the pointer
|
||||||
- [x] Fix ghost windows once and for all
|
- [x] Fix ghost windows once and for all
|
||||||
|
|
|
@ -6,10 +6,20 @@
|
||||||
gaps_in=5
|
gaps_in=5
|
||||||
border_size=1
|
border_size=1
|
||||||
gaps_out=20
|
gaps_out=20
|
||||||
bar_height=20
|
max_fps=60 # max fps for updates of config & animations
|
||||||
bar_monitor=0
|
|
||||||
bar_enabled=1
|
# Bar config
|
||||||
max_fps=60
|
Bar {
|
||||||
|
height=20
|
||||||
|
monitor=0
|
||||||
|
enabled=1
|
||||||
|
|
||||||
|
col.bg=0xff111111
|
||||||
|
col.high=0xffff3333
|
||||||
|
|
||||||
|
module=left,0xff8000ff,0xffffffff,1,workspaces
|
||||||
|
module=right,0xffffffff,0xff00ff33,1000,$date +%a,\ %b\ %Y\ \ %I:%M\ %p$
|
||||||
|
}
|
||||||
|
|
||||||
# colors
|
# colors
|
||||||
col.active_border=0x77ff3333
|
col.active_border=0x77ff3333
|
||||||
|
|
169
src/bar/Bar.cpp
169
src/bar/Bar.cpp
|
@ -55,9 +55,19 @@ int64_t barMainThread() {
|
||||||
|
|
||||||
Debug::log(LOG, "Bar setup finished!");
|
Debug::log(LOG, "Bar setup finished!");
|
||||||
|
|
||||||
|
int lazyUpdateCounter = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
// Don't spam these
|
||||||
|
if (lazyUpdateCounter > 10) {
|
||||||
ConfigManager::tick();
|
ConfigManager::tick();
|
||||||
|
|
||||||
|
lazyUpdateCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
++lazyUpdateCounter;
|
||||||
|
|
||||||
// Recieve the message and send our reply
|
// Recieve the message and send our reply
|
||||||
IPCRecieveMessageB(g_pWindowManager->m_sIPCBarPipeIn.szPipeName);
|
IPCRecieveMessageB(g_pWindowManager->m_sIPCBarPipeIn.szPipeName);
|
||||||
SIPCMessageBarToMain message;
|
SIPCMessageBarToMain message;
|
||||||
|
@ -86,6 +96,19 @@ int64_t barMainThread() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CStatusBar::setupModule(SBarModule* module) {
|
||||||
|
uint32_t values[2];
|
||||||
|
module->bgcontext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
||||||
|
values[0] = module->bgcolor;
|
||||||
|
values[1] = module->bgcolor;
|
||||||
|
xcb_create_gc(g_pWindowManager->DisplayConnection, module->bgcontext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStatusBar::destroyModule(SBarModule* module) {
|
||||||
|
if (module->bgcontext)
|
||||||
|
xcb_free_gc(g_pWindowManager->DisplayConnection, module->bgcontext);
|
||||||
|
}
|
||||||
|
|
||||||
void CStatusBar::setup(int MonitorID) {
|
void CStatusBar::setup(int MonitorID) {
|
||||||
Debug::log(LOG, "Creating the bar!");
|
Debug::log(LOG, "Creating the bar!");
|
||||||
|
|
||||||
|
@ -98,7 +121,7 @@ void CStatusBar::setup(int MonitorID) {
|
||||||
|
|
||||||
m_iMonitorID = MonitorID;
|
m_iMonitorID = MonitorID;
|
||||||
m_vecPosition = MONITOR.vecPosition;
|
m_vecPosition = MONITOR.vecPosition;
|
||||||
m_vecSize = Vector2D(MONITOR.vecSize.x, ConfigManager::getInt("bar_height"));
|
m_vecSize = Vector2D(MONITOR.vecSize.x, ConfigManager::getInt("bar:height"));
|
||||||
|
|
||||||
uint32_t values[4];
|
uint32_t values[4];
|
||||||
|
|
||||||
|
@ -129,8 +152,8 @@ void CStatusBar::setup(int MonitorID) {
|
||||||
auto contextBG = &m_mContexts["BG"];
|
auto contextBG = &m_mContexts["BG"];
|
||||||
contextBG->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
contextBG->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
||||||
|
|
||||||
values[0] = 0xFF111111;
|
values[0] = ConfigManager::getInt("bar:col.bg");
|
||||||
values[1] = 0xFF111111;
|
values[1] = ConfigManager::getInt("bar:col.bg");
|
||||||
xcb_create_gc(g_pWindowManager->DisplayConnection, contextBG->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, values);
|
xcb_create_gc(g_pWindowManager->DisplayConnection, contextBG->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, values);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -145,43 +168,16 @@ void CStatusBar::setup(int MonitorID) {
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
auto contextHIGH = &m_mContexts["HIGH"];
|
||||||
|
contextHIGH->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
||||||
|
|
||||||
auto contextBASETEXT = &m_mContexts["BASETEXT"];
|
values[0] = ConfigManager::getInt("bar:col.high");
|
||||||
|
values[1] = ConfigManager::getInt("bar:col.high");
|
||||||
contextBASETEXT->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
xcb_create_gc(g_pWindowManager->DisplayConnection, contextHIGH->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, values);
|
||||||
contextBASETEXT->Font = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
||||||
xcb_open_font(g_pWindowManager->DisplayConnection, contextBASETEXT->Font, 5, "fixed");
|
|
||||||
values[0] = 0xFFFFFFFF;
|
|
||||||
values[1] = 0xFF111111;
|
|
||||||
values[2] = contextBASETEXT->Font;
|
|
||||||
|
|
||||||
xcb_create_gc(g_pWindowManager->DisplayConnection, contextBASETEXT->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND | XCB_GC_FONT, values);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
auto contextHITEXT = &m_mContexts["HITEXT"];
|
|
||||||
contextHITEXT->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
||||||
contextHITEXT->Font = contextBASETEXT->Font;
|
|
||||||
values[0] = 0xFF000000;
|
|
||||||
values[1] = 0xFFFF3333;
|
|
||||||
values[2] = contextHITEXT->Font;
|
|
||||||
|
|
||||||
xcb_create_gc(g_pWindowManager->DisplayConnection, contextHITEXT->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND | XCB_GC_FONT, values);
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
auto contextMEDBG = &m_mContexts["MEDBG"];
|
|
||||||
contextMEDBG->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
||||||
|
|
||||||
values[0] = 0xFFFF3333;
|
|
||||||
values[1] = 0xFF111111;
|
|
||||||
xcb_create_gc(g_pWindowManager->DisplayConnection, contextMEDBG->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, values);
|
|
||||||
|
|
||||||
// don't, i use it later
|
|
||||||
//xcb_close_font(g_pWindowManager->DisplayConnection, contextBASETEXT->Font);
|
|
||||||
|
|
||||||
m_pCairoSurface = cairo_xcb_surface_create(g_pWindowManager->DisplayConnection, m_iPixmap, g_pWindowManager->VisualType,
|
m_pCairoSurface = cairo_xcb_surface_create(g_pWindowManager->DisplayConnection, m_iPixmap, g_pWindowManager->VisualType,
|
||||||
m_vecSize.x, m_vecSize.y);
|
m_vecSize.x, m_vecSize.y);
|
||||||
m_pCairo = cairo_create(m_pCairoSurface);
|
m_pCairo = cairo_create(m_pCairoSurface);
|
||||||
|
@ -223,6 +219,10 @@ void CStatusBar::drawText(Vector2D pos, std::string text, uint32_t color) {
|
||||||
cairo_show_text(m_pCairo, text.c_str());
|
cairo_show_text(m_pCairo, text.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CStatusBar::getTextHalfY() {
|
||||||
|
return m_vecSize.y - (m_vecSize.y - 9) / 2.f;
|
||||||
|
}
|
||||||
|
|
||||||
void CStatusBar::draw() {
|
void CStatusBar::draw() {
|
||||||
|
|
||||||
// const auto WORKSPACE = g_pWindowManager->getWorkspaceByID(g_pWindowManager->activeWorkspaces[m_iMonitorID]);
|
// const auto WORKSPACE = g_pWindowManager->getWorkspaceByID(g_pWindowManager->activeWorkspaces[m_iMonitorID]);
|
||||||
|
@ -235,13 +235,53 @@ void CStatusBar::draw() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ALPHA((uint32_t)ConfigManager::getInt("bar:col.bg")) != 0) {
|
||||||
xcb_rectangle_t rectangles[] = {{(int)0, (int)0, (int)m_vecSize.x, (int)m_vecSize.y}};
|
xcb_rectangle_t rectangles[] = {{(int)0, (int)0, (int)m_vecSize.x, (int)m_vecSize.y}};
|
||||||
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, m_mContexts["BG"].GContext, 1, rectangles);
|
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, m_mContexts["BG"].GContext, 1, rectangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// DRAW ALL MODULES
|
||||||
|
|
||||||
|
int offLeft = 0;
|
||||||
|
int offRight = 0;
|
||||||
|
|
||||||
|
for (auto& module : modules) {
|
||||||
|
|
||||||
|
if (!module.bgcontext && !module.isPad)
|
||||||
|
setupModule(&module);
|
||||||
|
|
||||||
|
if (module.value == "workspaces") {
|
||||||
|
offLeft += drawWorkspacesModule(&module, offLeft);
|
||||||
|
} else {
|
||||||
|
if (module.alignment == LEFT) {
|
||||||
|
offLeft += drawModule(&module, offLeft);
|
||||||
|
} else if (module.alignment == RIGHT) {
|
||||||
|
offRight += drawModule(&module, offRight);
|
||||||
|
} else {
|
||||||
|
drawModule(&module, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
cairo_surface_flush(m_pCairoSurface);
|
||||||
|
|
||||||
|
xcb_copy_area(g_pWindowManager->DisplayConnection, m_iPixmap, m_iWindowID, m_mContexts["BG"].GContext,
|
||||||
|
0, 0, 0, 0, m_vecSize.x, m_vecSize.y);
|
||||||
|
|
||||||
|
xcb_flush(g_pWindowManager->DisplayConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the width
|
||||||
|
int CStatusBar::drawWorkspacesModule(SBarModule* mod, int off) {
|
||||||
// Draw workspaces
|
// Draw workspaces
|
||||||
int drawnWorkspaces = 0;
|
int drawnWorkspaces = 0;
|
||||||
for (long unsigned int i = 0; i < openWorkspaces.size(); ++i) {
|
for (long unsigned int i = 0; i < openWorkspaces.size(); ++i) {
|
||||||
|
|
||||||
const auto WORKSPACE = openWorkspaces[i];
|
const auto WORKSPACE = openWorkspaces[i];
|
||||||
|
|
||||||
// The LastWindow may be on a different one. This is where the mouse is.
|
// The LastWindow may be on a different one. This is where the mouse is.
|
||||||
|
@ -252,32 +292,57 @@ void CStatusBar::draw() {
|
||||||
|
|
||||||
std::string workspaceName = std::to_string(openWorkspaces[i]);
|
std::string workspaceName = std::to_string(openWorkspaces[i]);
|
||||||
|
|
||||||
xcb_rectangle_t rectangleActive[] = { { m_vecSize.y * drawnWorkspaces, 0, m_vecSize.y, m_vecSize.y } };
|
xcb_rectangle_t rectangleActive[] = {{off + m_vecSize.y * drawnWorkspaces, 0, m_vecSize.y, m_vecSize.y}};
|
||||||
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, WORKSPACE == MOUSEWORKSPACEID ? m_mContexts["MEDBG"].GContext : m_mContexts["BG"].GContext, 1, rectangleActive);
|
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, WORKSPACE == MOUSEWORKSPACEID ? m_mContexts["HIGH"].GContext : m_mContexts["BG"].GContext, 1, rectangleActive);
|
||||||
|
|
||||||
drawText(Vector2D(m_vecSize.y * drawnWorkspaces + m_vecSize.y / 2.f - getTextWidth(workspaceName) / 2.f, m_vecSize.y - (m_vecSize.y - 9) / 2.f),
|
drawText(Vector2D(off + m_vecSize.y * drawnWorkspaces + m_vecSize.y / 2.f - getTextWidth(workspaceName) / 2.f, getTextHalfY()),
|
||||||
workspaceName, WORKSPACE == MOUSEWORKSPACEID ? 0xFF111111 : 0xFFFFFFFF);
|
workspaceName, WORKSPACE == MOUSEWORKSPACEID ? 0xFF111111 : 0xFFFFFFFF);
|
||||||
|
|
||||||
drawnWorkspaces++;
|
drawnWorkspaces++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw STATUS to the right
|
return drawnWorkspaces * m_vecSize.y;
|
||||||
std::string STATUS = exec(m_szStatusCommand.c_str());
|
|
||||||
STATUS = STATUS.substr(0, (STATUS.length() > 0 ? STATUS.length() - 1 : 9999999));
|
|
||||||
if (STATUS != "") {
|
|
||||||
drawText(Vector2D(m_vecSize.x - getTextWidth(STATUS), m_vecSize.y - (m_vecSize.y - 9) / 2.f),
|
|
||||||
STATUS, 0xFFFFFFFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CStatusBar::drawModule(SBarModule* mod, int off) {
|
||||||
|
|
||||||
cairo_surface_flush(m_pCairoSurface);
|
if (mod->isPad)
|
||||||
|
return mod->pad;
|
||||||
|
|
||||||
// clear before copying
|
const int PAD = 4;
|
||||||
//xcb_clear_area(g_pWindowManager->DisplayConnection, 0, m_iWindowID, 0, 0, m_vecSize.x, m_vecSize.y);
|
|
||||||
//xcb_flush(g_pWindowManager->DisplayConnection);
|
|
||||||
|
|
||||||
xcb_copy_area(g_pWindowManager->DisplayConnection, m_iPixmap, m_iWindowID, m_mContexts["BG"].GContext,
|
// check if we need to update
|
||||||
0, 0, 0, 0, m_vecSize.x, m_vecSize.y);
|
if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - mod->updateLast).count() > mod->updateEveryMs) {
|
||||||
|
// Yes. Set the new last and do it.
|
||||||
|
mod->updateLast = std::chrono::system_clock::now();
|
||||||
|
|
||||||
xcb_flush(g_pWindowManager->DisplayConnection);
|
mod->valueCalculated = BarCommands::parseCommand(mod->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have the value, draw the module!
|
||||||
|
|
||||||
|
const auto MODULEWIDTH = getTextWidth(mod->valueCalculated) + PAD;
|
||||||
|
|
||||||
|
if (!MODULEWIDTH || mod->valueCalculated == "")
|
||||||
|
return 0; // empty module
|
||||||
|
|
||||||
|
Vector2D position;
|
||||||
|
switch (mod->alignment) {
|
||||||
|
case LEFT:
|
||||||
|
position = Vector2D(off, 0);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
position = Vector2D(m_vecSize.x - off - MODULEWIDTH, 0);
|
||||||
|
break;
|
||||||
|
case CENTER:
|
||||||
|
position = Vector2D(m_vecSize.x / 2.f - MODULEWIDTH / 2.f, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_rectangle_t rects[] = {{ position.x, position.y, MODULEWIDTH, m_vecSize.y }};
|
||||||
|
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, mod->bgcontext, 1, rects);
|
||||||
|
|
||||||
|
drawText(position + Vector2D(PAD / 2, getTextHalfY()), mod->valueCalculated, mod->color);
|
||||||
|
|
||||||
|
return MODULEWIDTH;
|
||||||
}
|
}
|
|
@ -4,26 +4,56 @@
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../ipc/ipc.hpp"
|
#include "../ipc/ipc.hpp"
|
||||||
|
#include "BarCommands.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
struct SDrawingContext {
|
struct SDrawingContext {
|
||||||
xcb_gcontext_t GContext;
|
xcb_gcontext_t GContext;
|
||||||
xcb_font_t Font;
|
xcb_font_t Font;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ModuleAlignment {
|
||||||
|
LEFT = 0,
|
||||||
|
CENTER,
|
||||||
|
RIGHT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SBarModule {
|
||||||
|
ModuleAlignment alignment;
|
||||||
|
std::string value;
|
||||||
|
std::string valueCalculated = "";
|
||||||
|
uint64_t color;
|
||||||
|
uint64_t bgcolor;
|
||||||
|
|
||||||
|
uint64_t updateEveryMs;
|
||||||
|
std::chrono::system_clock::time_point updateLast;
|
||||||
|
|
||||||
|
xcb_gcontext_t bgcontext = NULL;
|
||||||
|
|
||||||
|
// PADS
|
||||||
|
bool isPad = false;
|
||||||
|
int pad = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class CStatusBar {
|
class CStatusBar {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
EXPOSED_MEMBER(WindowID, xcb_window_t, i);
|
EXPOSED_MEMBER(WindowID, xcb_window_t, i);
|
||||||
EXPOSED_MEMBER(MonitorID, int, i);
|
EXPOSED_MEMBER(MonitorID, int, i);
|
||||||
EXPOSED_MEMBER(StatusCommand, std::string, sz); // TODO: make the bar better
|
EXPOSED_MEMBER(StatusCommand, std::string, sz); // TODO: make the bar better
|
||||||
|
EXPOSED_MEMBER(LastWindowName, std::string, sz);
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void setup(int MonitorID);
|
void setup(int MonitorID);
|
||||||
void destroy();
|
void destroy();
|
||||||
|
void setupModule(SBarModule*);
|
||||||
|
void destroyModule(SBarModule*);
|
||||||
|
|
||||||
std::vector<int> openWorkspaces;
|
std::vector<int> openWorkspaces;
|
||||||
EXPOSED_MEMBER(CurrentWorkspace, int, i);
|
EXPOSED_MEMBER(CurrentWorkspace, int, i);
|
||||||
|
|
||||||
|
std::vector<SBarModule> modules;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector2D m_vecSize;
|
Vector2D m_vecSize;
|
||||||
Vector2D m_vecPosition;
|
Vector2D m_vecPosition;
|
||||||
|
@ -38,6 +68,9 @@ private:
|
||||||
|
|
||||||
void drawText(Vector2D, std::string, uint32_t);
|
void drawText(Vector2D, std::string, uint32_t);
|
||||||
int getTextWidth(std::string);
|
int getTextWidth(std::string);
|
||||||
|
int drawModule(SBarModule*, int);
|
||||||
|
int drawWorkspacesModule(SBarModule*, int);
|
||||||
|
int getTextHalfY();
|
||||||
|
|
||||||
std::unordered_map<std::string, SDrawingContext> m_mContexts;
|
std::unordered_map<std::string, SDrawingContext> m_mContexts;
|
||||||
};
|
};
|
||||||
|
|
178
src/bar/BarCommands.cpp
Normal file
178
src/bar/BarCommands.cpp
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
#include "BarCommands.hpp"
|
||||||
|
#include "../windowManager.hpp"
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> lastReads;
|
||||||
|
|
||||||
|
std::string getCpuString() {
|
||||||
|
std::vector<std::pair<int, int>> usageRead;
|
||||||
|
|
||||||
|
std::ifstream cpuif;
|
||||||
|
cpuif.open("/proc/stat");
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(cpuif, line)) {
|
||||||
|
// parse line
|
||||||
|
const auto stats = splitString(line, ' ');
|
||||||
|
|
||||||
|
if (stats.size() < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (stats[0].find("cpu") == std::string::npos)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// get the percent
|
||||||
|
try {
|
||||||
|
const auto user = stol(stats[1]);
|
||||||
|
const auto nice = stol(stats[2]);
|
||||||
|
const auto kern = stol(stats[3]);
|
||||||
|
|
||||||
|
// get total
|
||||||
|
long total = 0;
|
||||||
|
for (const auto& t : stats) {
|
||||||
|
if (t.find("c") != std::string::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
total += stol(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
usageRead.push_back({user + nice + kern, total});
|
||||||
|
} catch( ... ) { ; } // oops
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the values
|
||||||
|
std::pair<int, int> lastReadsTotal = {0, 0};
|
||||||
|
for (const auto& lr : lastReads) {
|
||||||
|
lastReadsTotal.first += lr.first;
|
||||||
|
lastReadsTotal.second += lr.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<int, int> newReadsTotal = {0, 0};
|
||||||
|
for (const auto& nr : usageRead) {
|
||||||
|
newReadsTotal.first += nr.first;
|
||||||
|
newReadsTotal.second += nr.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<int, int> difference = {newReadsTotal.first - lastReadsTotal.first, newReadsTotal.second - lastReadsTotal.second};
|
||||||
|
|
||||||
|
float percUsage = (float)difference.first / (float)difference.second;
|
||||||
|
|
||||||
|
lastReads.clear();
|
||||||
|
|
||||||
|
for (const auto& nr : usageRead) {
|
||||||
|
lastReads.push_back(nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::to_string((int)(percUsage * 100.f)) + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getRamString() {
|
||||||
|
float available = 0;
|
||||||
|
float total = 0;
|
||||||
|
|
||||||
|
std::ifstream ramif;
|
||||||
|
ramif.open("/proc/meminfo");
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(ramif, line)) {
|
||||||
|
// parse line
|
||||||
|
const auto KEY = line.substr(0, line.find_first_of(':'));
|
||||||
|
|
||||||
|
int startValue = 0;
|
||||||
|
for (int i = 0; i < line.length(); ++i) {
|
||||||
|
const auto& c = line[i];
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
startValue = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float VALUE = 0.f;
|
||||||
|
try {
|
||||||
|
std::string toVal = line.substr(startValue);
|
||||||
|
toVal = toVal.substr(0, line.find_first_of(' ', startValue));
|
||||||
|
VALUE = stol(toVal);
|
||||||
|
} catch (...) { ; } // oops
|
||||||
|
VALUE /= 1024.f;
|
||||||
|
|
||||||
|
if (KEY == "MemTotal") {
|
||||||
|
total = VALUE;
|
||||||
|
} else if (KEY == "MemAvailable") {
|
||||||
|
available = VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::to_string((int)(total - available)) + "MB/" + std::to_string((int)total) + "MB";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getCurrentWindowName() {
|
||||||
|
return g_pWindowManager->statusBar->getLastWindowName();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BarCommands::parsePercent(std::string token) {
|
||||||
|
// check what the token is and act accordingly.
|
||||||
|
|
||||||
|
if (token == "RAM") return getRamString();
|
||||||
|
else if (token == "CPU") return getCpuString();
|
||||||
|
else if (token == "WINNAME") return getCurrentWindowName();
|
||||||
|
|
||||||
|
Debug::log(ERR, "Unknown token while parsing module: %" + token + "%");
|
||||||
|
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BarCommands::parseDollar(std::string token) {
|
||||||
|
const auto result = exec(token.c_str());
|
||||||
|
return result.substr(0, result.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BarCommands::parseCommand(std::string command) {
|
||||||
|
|
||||||
|
std::string result = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < command.length(); ++i) {
|
||||||
|
|
||||||
|
const auto c = command[i];
|
||||||
|
|
||||||
|
if (c == '%') {
|
||||||
|
// find the next one
|
||||||
|
for (int j = i + 1; i < command.length(); ++j) {
|
||||||
|
if (command[j] == '%') {
|
||||||
|
// found!
|
||||||
|
auto toSend = command.substr(i + 1);
|
||||||
|
toSend = toSend.substr(0, toSend.find_first_of('%'));
|
||||||
|
result += parsePercent(toSend);
|
||||||
|
i = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command[j] == ' ')
|
||||||
|
break; // if there is a space it's not a token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (c == '$') {
|
||||||
|
// find the next one
|
||||||
|
for (int j = i + 1; i < command.length(); ++j) {
|
||||||
|
if (command[j] == '$') {
|
||||||
|
// found!
|
||||||
|
auto toSend = command.substr(i + 1);
|
||||||
|
toSend = toSend.substr(0, toSend.find_first_of('$'));
|
||||||
|
result += parseDollar(toSend);
|
||||||
|
i = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j + 1 == command.length()) {
|
||||||
|
Debug::log(ERR, "Unescaped $ in a module, module command: ");
|
||||||
|
Debug::log(NONE, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
result += command[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
10
src/bar/BarCommands.hpp
Normal file
10
src/bar/BarCommands.hpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
#include "../defines.hpp"
|
||||||
|
#include "../utilities/Util.hpp"
|
||||||
|
|
||||||
|
namespace BarCommands {
|
||||||
|
std::string parseCommand(std::string);
|
||||||
|
|
||||||
|
std::string parsePercent(std::string);
|
||||||
|
std::string parseDollar(std::string);
|
||||||
|
};
|
|
@ -16,9 +16,11 @@ void ConfigManager::init() {
|
||||||
|
|
||||||
configValues["max_fps"].intValue = 60;
|
configValues["max_fps"].intValue = 60;
|
||||||
|
|
||||||
configValues["bar_monitor"].intValue = 0;
|
configValues["bar:monitor"].intValue = 0;
|
||||||
configValues["bar_enabled"].intValue = 1;
|
configValues["bar:enabled"].intValue = 1;
|
||||||
configValues["bar_height"].intValue = 15;
|
configValues["bar:height"].intValue = 15;
|
||||||
|
configValues["bar:col.bg"].intValue = 0xFF111111;
|
||||||
|
configValues["bar:col.high"].intValue = 0xFFFF3333;
|
||||||
|
|
||||||
configValues["status_command"].strValue = "date +%I:%M\\ %p"; // Time
|
configValues["status_command"].strValue = "date +%I:%M\\ %p"; // Time
|
||||||
|
|
||||||
|
@ -36,6 +38,37 @@ void ConfigManager::init() {
|
||||||
applyKeybindsToX();
|
applyKeybindsToX();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) {
|
||||||
|
if (ConfigManager::configValues.find(COMMAND) == ConfigManager::configValues.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& CONFIGENTRY = ConfigManager::configValues.at(COMMAND);
|
||||||
|
if (CONFIGENTRY.intValue != -1) {
|
||||||
|
try {
|
||||||
|
if (VALUE.find("0x") == 0) {
|
||||||
|
// Values with 0x are hex
|
||||||
|
const auto VALUEWITHOUTHEX = VALUE.substr(2);
|
||||||
|
CONFIGENTRY.intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
|
||||||
|
} else
|
||||||
|
CONFIGENTRY.intValue = stol(VALUE);
|
||||||
|
} catch (...) {
|
||||||
|
Debug::log(WARN, "Error reading value of " + COMMAND);
|
||||||
|
}
|
||||||
|
} else if (CONFIGENTRY.floatValue != -1) {
|
||||||
|
try {
|
||||||
|
CONFIGENTRY.floatValue = stof(VALUE);
|
||||||
|
} catch (...) {
|
||||||
|
Debug::log(WARN, "Error reading value of " + COMMAND);
|
||||||
|
}
|
||||||
|
} else if (CONFIGENTRY.strValue != "") {
|
||||||
|
try {
|
||||||
|
CONFIGENTRY.strValue = VALUE;
|
||||||
|
} catch (...) {
|
||||||
|
Debug::log(WARN, "Error reading value of " + COMMAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleBind(const std::string& command, const std::string& value) {
|
void handleBind(const std::string& command, const std::string& value) {
|
||||||
|
|
||||||
// example:
|
// example:
|
||||||
|
@ -85,6 +118,96 @@ void handleStatusCommand(const std::string& command, const std::string& args) {
|
||||||
g_pWindowManager->statusBar->setStatusCommand(args);
|
g_pWindowManager->statusBar->setStatusCommand(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parseModule(const std::string& COMMANDC, const std::string& VALUE) {
|
||||||
|
SBarModule module;
|
||||||
|
|
||||||
|
auto valueCopy = VALUE;
|
||||||
|
|
||||||
|
const auto ALIGN = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||||
|
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||||
|
|
||||||
|
if (ALIGN == "pad") {
|
||||||
|
const auto ALIGNR = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||||
|
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||||
|
|
||||||
|
const auto PADW = valueCopy;
|
||||||
|
|
||||||
|
if (ALIGNR == "left") module.alignment = LEFT;
|
||||||
|
else if (ALIGNR == "right") module.alignment = RIGHT;
|
||||||
|
else if (ALIGNR == "center") module.alignment = CENTER;
|
||||||
|
|
||||||
|
try {
|
||||||
|
module.pad = stol(PADW);
|
||||||
|
} catch (...) {
|
||||||
|
Debug::log(ERR, "Module creation pad error: invalid pad");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.isPad = true;
|
||||||
|
|
||||||
|
module.color = 0;
|
||||||
|
module.bgcolor = 0;
|
||||||
|
|
||||||
|
g_pWindowManager->statusBar->modules.push_back(module);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto COL1 = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||||
|
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||||
|
|
||||||
|
const auto COL2 = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||||
|
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||||
|
|
||||||
|
const auto UPDATE = valueCopy.substr(0, valueCopy.find_first_of(","));
|
||||||
|
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
|
||||||
|
|
||||||
|
const auto COMMAND = valueCopy;
|
||||||
|
|
||||||
|
if (ALIGN == "left") module.alignment = LEFT;
|
||||||
|
else if (ALIGN == "right") module.alignment = RIGHT;
|
||||||
|
else if (ALIGN == "center") module.alignment = CENTER;
|
||||||
|
|
||||||
|
try {
|
||||||
|
module.color = stol(COL1.substr(2), nullptr, 16);
|
||||||
|
module.bgcolor = stol(COL2.substr(2), nullptr, 16);
|
||||||
|
} catch (...) {
|
||||||
|
Debug::log(ERR, "Module creation color error: invalid color");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
module.updateEveryMs = stol(UPDATE);
|
||||||
|
} catch (...) {
|
||||||
|
Debug::log(ERR, "Module creation error: invalid update interval");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.value = COMMAND;
|
||||||
|
|
||||||
|
g_pWindowManager->statusBar->modules.push_back(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parseBarLine(const std::string& line) {
|
||||||
|
|
||||||
|
// And parse
|
||||||
|
// check if command
|
||||||
|
const auto EQUALSPLACE = line.find_first_of('=');
|
||||||
|
|
||||||
|
if (EQUALSPLACE == std::string::npos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto COMMAND = line.substr(0, EQUALSPLACE);
|
||||||
|
const auto VALUE = line.substr(EQUALSPLACE + 1);
|
||||||
|
|
||||||
|
// Now check commands
|
||||||
|
if (COMMAND == "module") {
|
||||||
|
parseModule(COMMAND, VALUE);
|
||||||
|
} else {
|
||||||
|
configSetValueSafe("bar:" + COMMAND, VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void parseLine(std::string& line) {
|
void parseLine(std::string& line) {
|
||||||
// first check if its not a comment
|
// first check if its not a comment
|
||||||
const auto COMMENTSTART = line.find_first_of('#');
|
const auto COMMENTSTART = line.find_first_of('#');
|
||||||
|
@ -95,6 +218,27 @@ void parseLine(std::string& line) {
|
||||||
if (COMMENTSTART != std::string::npos)
|
if (COMMENTSTART != std::string::npos)
|
||||||
line = line.substr(COMMENTSTART);
|
line = line.substr(COMMENTSTART);
|
||||||
|
|
||||||
|
// remove shit at the beginning
|
||||||
|
while (line[0] == ' ' || line[0] == '\t') {
|
||||||
|
line = line.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.find("Bar {") != std::string::npos) {
|
||||||
|
ConfigManager::isBar = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.find("}") != std::string::npos && ConfigManager::isBar) {
|
||||||
|
ConfigManager::isBar = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConfigManager::isBar) {
|
||||||
|
if (g_pWindowManager->statusBar)
|
||||||
|
parseBarLine(line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// And parse
|
// And parse
|
||||||
// check if command
|
// check if command
|
||||||
const auto EQUALSPLACE = line.find_first_of('=');
|
const auto EQUALSPLACE = line.find_first_of('=');
|
||||||
|
@ -116,39 +260,20 @@ void parseLine(std::string& line) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigManager::configValues.find(COMMAND) == ConfigManager::configValues.end())
|
configSetValueSafe(COMMAND, VALUE);
|
||||||
return;
|
|
||||||
|
|
||||||
auto& CONFIGENTRY = ConfigManager::configValues.at(COMMAND);
|
|
||||||
if (CONFIGENTRY.intValue != -1) {
|
|
||||||
try {
|
|
||||||
if (VALUE.find("0x") == 0) {
|
|
||||||
// Values with 0x are hex
|
|
||||||
const auto VALUEWITHOUTHEX = VALUE.substr(2);
|
|
||||||
CONFIGENTRY.intValue = stoi(VALUEWITHOUTHEX, nullptr, 16);
|
|
||||||
} else
|
|
||||||
CONFIGENTRY.intValue = stoi(VALUE);
|
|
||||||
} catch (...) {
|
|
||||||
Debug::log(WARN, "Error reading value of " + COMMAND);
|
|
||||||
}
|
|
||||||
} else if (CONFIGENTRY.floatValue != -1) {
|
|
||||||
try {
|
|
||||||
CONFIGENTRY.floatValue = stof(VALUE);
|
|
||||||
} catch (...) {
|
|
||||||
Debug::log(WARN, "Error reading value of " + COMMAND);
|
|
||||||
}
|
|
||||||
} else if (CONFIGENTRY.strValue != "") {
|
|
||||||
try {
|
|
||||||
CONFIGENTRY.strValue = VALUE;
|
|
||||||
} catch (...) {
|
|
||||||
Debug::log(WARN, "Error reading value of " + COMMAND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigManager::loadConfigLoadVars() {
|
void ConfigManager::loadConfigLoadVars() {
|
||||||
Debug::log(LOG, "Reloading the config!");
|
Debug::log(LOG, "Reloading the config!");
|
||||||
|
|
||||||
|
if (loadBar && g_pWindowManager->statusBar) {
|
||||||
|
// clear modules as we overwrite them
|
||||||
|
for (auto& m : g_pWindowManager->statusBar->modules) {
|
||||||
|
g_pWindowManager->statusBar->destroyModule(&m);
|
||||||
|
}
|
||||||
|
g_pWindowManager->statusBar->modules.clear();
|
||||||
|
}
|
||||||
|
|
||||||
KeybindManager::keybinds.clear();
|
KeybindManager::keybinds.clear();
|
||||||
|
|
||||||
const char* const ENVHOME = getenv("HOME");
|
const char* const ENVHOME = getenv("HOME");
|
||||||
|
@ -184,7 +309,7 @@ void ConfigManager::loadConfigLoadVars() {
|
||||||
// Reload the bar as well, don't load it before the default is loaded.
|
// Reload the bar as well, don't load it before the default is loaded.
|
||||||
if (loadBar && g_pWindowManager->statusBar) {
|
if (loadBar && g_pWindowManager->statusBar) {
|
||||||
g_pWindowManager->statusBar->destroy();
|
g_pWindowManager->statusBar->destroy();
|
||||||
g_pWindowManager->statusBar->setup(configValues["bar_monitor"].intValue);
|
g_pWindowManager->statusBar->setup(configValues["bar:monitor"].intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadBar = true;
|
loadBar = true;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "../utilities/Debug.hpp"
|
#include "../utilities/Debug.hpp"
|
||||||
|
|
||||||
struct SConfigValue {
|
struct SConfigValue {
|
||||||
int intValue = -1;
|
int64_t intValue = -1;
|
||||||
float floatValue = -1;
|
float floatValue = -1;
|
||||||
std::string strValue = "";
|
std::string strValue = "";
|
||||||
};
|
};
|
||||||
|
@ -15,6 +15,8 @@ namespace ConfigManager {
|
||||||
|
|
||||||
inline bool loadBar = false;
|
inline bool loadBar = false;
|
||||||
|
|
||||||
|
inline bool isBar = false; // If true we send the command to the bar parser
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void loadConfigLoadVars();
|
void loadConfigLoadVars();
|
||||||
void tick();
|
void tick();
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "events.hpp"
|
#include "events.hpp"
|
||||||
|
|
||||||
gpointer handle(gpointer data) {
|
gpointer handle(gpointer data) {
|
||||||
|
int lazyUpdateCounter = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// wait for the main thread to be idle
|
// wait for the main thread to be idle
|
||||||
while (g_pWindowManager->mainThreadBusy) {
|
while (g_pWindowManager->mainThreadBusy) {
|
||||||
|
@ -10,13 +12,26 @@ gpointer handle(gpointer data) {
|
||||||
// set state to let the main thread know to wait.
|
// set state to let the main thread know to wait.
|
||||||
g_pWindowManager->animationUtilBusy = true;
|
g_pWindowManager->animationUtilBusy = true;
|
||||||
|
|
||||||
// check config
|
|
||||||
ConfigManager::tick();
|
|
||||||
|
|
||||||
// update animations.
|
// update animations.
|
||||||
AnimationUtil::move();
|
AnimationUtil::move();
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// Don't spam these
|
||||||
|
if (lazyUpdateCounter > 10){
|
||||||
|
// Update the active window name
|
||||||
|
g_pWindowManager->updateActiveWindowName();
|
||||||
|
|
||||||
|
// Update the bar
|
||||||
|
g_pWindowManager->updateBarInfo();
|
||||||
|
|
||||||
|
// check config
|
||||||
|
ConfigManager::tick();
|
||||||
|
|
||||||
|
lazyUpdateCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
++lazyUpdateCounter;
|
||||||
|
|
||||||
// restore anim state
|
// restore anim state
|
||||||
g_pWindowManager->animationUtilBusy = false;
|
g_pWindowManager->animationUtilBusy = false;
|
||||||
|
|
||||||
|
@ -80,6 +95,11 @@ CWindow* Events::remapFloatingWindow(int windowID, int forcemonitor) {
|
||||||
window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]);
|
window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]);
|
||||||
window.setMonitor(CURRENTSCREEN);
|
window.setMonitor(CURRENTSCREEN);
|
||||||
|
|
||||||
|
// Window name
|
||||||
|
const auto WINNAME = getWindowName(windowID);
|
||||||
|
Debug::log(LOG, "New window got name: " + WINNAME);
|
||||||
|
window.setName(WINNAME);
|
||||||
|
|
||||||
// For all floating windows, get their default size
|
// For all floating windows, get their default size
|
||||||
const auto GEOMETRYCOOKIE = xcb_get_geometry(g_pWindowManager->DisplayConnection, windowID);
|
const auto GEOMETRYCOOKIE = xcb_get_geometry(g_pWindowManager->DisplayConnection, windowID);
|
||||||
const auto GEOMETRY = xcb_get_geometry_reply(g_pWindowManager->DisplayConnection, GEOMETRYCOOKIE, 0);
|
const auto GEOMETRY = xcb_get_geometry_reply(g_pWindowManager->DisplayConnection, GEOMETRYCOOKIE, 0);
|
||||||
|
@ -132,6 +152,11 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
|
||||||
window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]);
|
window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]);
|
||||||
window.setMonitor(CURRENTSCREEN);
|
window.setMonitor(CURRENTSCREEN);
|
||||||
|
|
||||||
|
// Window name
|
||||||
|
const auto WINNAME = getWindowName(windowID);
|
||||||
|
Debug::log(LOG, "New window got name: " + WINNAME);
|
||||||
|
window.setName(WINNAME);
|
||||||
|
|
||||||
// For all floating windows, get their default size
|
// For all floating windows, get their default size
|
||||||
const auto GEOMETRYCOOKIE = xcb_get_geometry(g_pWindowManager->DisplayConnection, windowID);
|
const auto GEOMETRYCOOKIE = xcb_get_geometry(g_pWindowManager->DisplayConnection, windowID);
|
||||||
const auto GEOMETRY = xcb_get_geometry_reply(g_pWindowManager->DisplayConnection, GEOMETRYCOOKIE, 0);
|
const auto GEOMETRY = xcb_get_geometry_reply(g_pWindowManager->DisplayConnection, GEOMETRYCOOKIE, 0);
|
||||||
|
|
|
@ -65,8 +65,16 @@ void IPCSendMessage(const std::string path, SIPCMessageMainToBar smessage) {
|
||||||
message += std::to_string(w) + ",";
|
message += std::to_string(w) + ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message += IPC_MESSAGE_SEPARATOR + "lastwindowname" + IPC_MESSAGE_EQUALITY;
|
||||||
|
|
||||||
|
if (const auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); PLASTWINDOW) {
|
||||||
|
message += PLASTWINDOW->getName() + IPC_MESSAGE_SEPARATOR;
|
||||||
|
} else {
|
||||||
|
message += IPC_MESSAGE_SEPARATOR;
|
||||||
|
}
|
||||||
|
|
||||||
// append the EOF
|
// append the EOF
|
||||||
message += IPC_MESSAGE_SEPARATOR + IPC_END_OF_FILE;
|
message += IPC_END_OF_FILE;
|
||||||
|
|
||||||
// Send
|
// Send
|
||||||
writeToIPCChannel(path, message);
|
writeToIPCChannel(path, message);
|
||||||
|
@ -86,21 +94,21 @@ void IPCRecieveMessageB(const std::string path) {
|
||||||
try {
|
try {
|
||||||
std::string message = readFromIPCChannel(path);
|
std::string message = readFromIPCChannel(path);
|
||||||
|
|
||||||
const auto EOFPOS = message.find_first_of(IPC_END_OF_FILE);
|
const auto EOFPOS = message.find(IPC_END_OF_FILE);
|
||||||
|
|
||||||
if (EOFPOS == std::string::npos)
|
if (EOFPOS == std::string::npos)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
message = message.substr(0, EOFPOS);
|
message = message.substr(0, EOFPOS);
|
||||||
|
|
||||||
while (message.find_first_of(IPC_MESSAGE_SEPARATOR) != 0 && message.find_first_of(IPC_MESSAGE_SEPARATOR) != std::string::npos) {
|
while (message.find(IPC_MESSAGE_SEPARATOR) != std::string::npos && message.find(IPC_MESSAGE_SEPARATOR) != 0) {
|
||||||
// read until done.
|
// read until done.
|
||||||
const auto PROP = message.substr(0, message.find_first_of(IPC_MESSAGE_SEPARATOR));
|
const auto PROP = message.substr(0, message.find(IPC_MESSAGE_SEPARATOR));
|
||||||
message = message.substr(message.find_first_of(IPC_MESSAGE_SEPARATOR) + 1);
|
message = message.substr(message.find(IPC_MESSAGE_SEPARATOR) + IPC_MESSAGE_SEPARATOR.length());
|
||||||
|
|
||||||
// Get the name and value
|
// Get the name and value
|
||||||
const auto PROPNAME = PROP.substr(0, PROP.find_first_of(IPC_MESSAGE_EQUALITY));
|
const auto PROPNAME = PROP.substr(0, PROP.find(IPC_MESSAGE_EQUALITY));
|
||||||
const auto PROPVALUE = PROP.substr(PROP.find_first_of(IPC_MESSAGE_EQUALITY) + 1);
|
const auto PROPVALUE = PROP.substr(PROP.find(IPC_MESSAGE_EQUALITY) + 1);
|
||||||
|
|
||||||
if (PROPNAME == "active") {
|
if (PROPNAME == "active") {
|
||||||
try {
|
try {
|
||||||
|
@ -125,6 +133,9 @@ void IPCRecieveMessageB(const std::string path) {
|
||||||
|
|
||||||
// sort
|
// sort
|
||||||
std::sort(g_pWindowManager->statusBar->openWorkspaces.begin(), g_pWindowManager->statusBar->openWorkspaces.end());
|
std::sort(g_pWindowManager->statusBar->openWorkspaces.begin(), g_pWindowManager->statusBar->openWorkspaces.end());
|
||||||
|
} else if (PROPNAME == "lastwindowname") {
|
||||||
|
g_pWindowManager->statusBar->setLastWindowName(PROPVALUE);
|
||||||
|
Debug::log(LOG, "update window name to " + PROPVALUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
@ -143,21 +154,21 @@ void IPCRecieveMessageM(const std::string path) {
|
||||||
try {
|
try {
|
||||||
std::string message = readFromIPCChannel(path);
|
std::string message = readFromIPCChannel(path);
|
||||||
|
|
||||||
const auto EOFPOS = message.find_first_of(IPC_END_OF_FILE);
|
const auto EOFPOS = message.find(IPC_END_OF_FILE);
|
||||||
|
|
||||||
if (EOFPOS == std::string::npos)
|
if (EOFPOS == std::string::npos)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
message = message.substr(0, EOFPOS);
|
message = message.substr(0, EOFPOS);
|
||||||
|
|
||||||
while (message.find_first_of(IPC_MESSAGE_SEPARATOR) != 0 && message.find_first_of(IPC_MESSAGE_SEPARATOR) != std::string::npos) {
|
while (message.find(IPC_MESSAGE_SEPARATOR) != std::string::npos && message.find(IPC_MESSAGE_SEPARATOR) != 0) {
|
||||||
// read until done.
|
// read until done.
|
||||||
const auto PROP = message.substr(0, message.find_first_of(IPC_MESSAGE_SEPARATOR));
|
const auto PROP = message.substr(0, message.find(IPC_MESSAGE_SEPARATOR));
|
||||||
message = message.substr(message.find_first_of(IPC_MESSAGE_SEPARATOR) + 1);
|
message = message.substr(message.find(IPC_MESSAGE_SEPARATOR) + IPC_MESSAGE_SEPARATOR.length());
|
||||||
|
|
||||||
// Get the name and value
|
// Get the name and value
|
||||||
const auto PROPNAME = PROP.substr(0, PROP.find_first_of(IPC_MESSAGE_EQUALITY));
|
const auto PROPNAME = PROP.substr(0, PROP.find(IPC_MESSAGE_EQUALITY));
|
||||||
const auto PROPVALUE = PROP.substr(PROP.find_first_of(IPC_MESSAGE_EQUALITY) + 1);
|
const auto PROPVALUE = PROP.substr(PROP.find(IPC_MESSAGE_EQUALITY) + 1);
|
||||||
|
|
||||||
if (PROPNAME == "wid") {
|
if (PROPNAME == "wid") {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -5,12 +5,13 @@ std::string readFromIPCChannel(const std::string);
|
||||||
int writeToIPCChannel(const std::string, std::string);
|
int writeToIPCChannel(const std::string, std::string);
|
||||||
|
|
||||||
#define IPC_END_OF_FILE (std::string)"HYPR_END_OF_FILE"
|
#define IPC_END_OF_FILE (std::string)"HYPR_END_OF_FILE"
|
||||||
#define IPC_MESSAGE_SEPARATOR (std::string)"\t"
|
#define IPC_MESSAGE_SEPARATOR std::string("\t")
|
||||||
#define IPC_MESSAGE_EQUALITY (std::string)"="
|
#define IPC_MESSAGE_EQUALITY std::string("=")
|
||||||
|
|
||||||
struct SIPCMessageMainToBar {
|
struct SIPCMessageMainToBar {
|
||||||
std::vector<int> openWorkspaces;
|
std::vector<int> openWorkspaces;
|
||||||
uint64_t activeWorkspace;
|
uint64_t activeWorkspace;
|
||||||
|
std::string lastWindowName;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SIPCMessageBarToMain {
|
struct SIPCMessageBarToMain {
|
||||||
|
|
|
@ -55,3 +55,21 @@ bool xcbContainsAtom(xcb_get_property_reply_t* PROP, xcb_atom_t ATOM) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> splitString(std::string in, char c) {
|
||||||
|
std::vector<std::string> returns;
|
||||||
|
|
||||||
|
while(in.length() > 0) {
|
||||||
|
std::string toPush = in.substr(0, in.find_first_of(c));
|
||||||
|
if (toPush != "") {
|
||||||
|
returns.push_back(toPush);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in.find_first_of(c) != std::string::npos)
|
||||||
|
in = in.substr(in.find_first_of(c) + 1);
|
||||||
|
else
|
||||||
|
in = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return returns;
|
||||||
|
}
|
|
@ -9,3 +9,5 @@ void emptyEvent();
|
||||||
bool xcbContainsAtom(xcb_get_property_reply_t* PROP, xcb_atom_t ATOM);
|
bool xcbContainsAtom(xcb_get_property_reply_t* PROP, xcb_atom_t ATOM);
|
||||||
|
|
||||||
double parabolic(double from, double to, double incline);
|
double parabolic(double from, double to, double incline);
|
||||||
|
|
||||||
|
std::vector<std::string> splitString(std::string, char);
|
|
@ -44,3 +44,16 @@ std::string getRoleName(int64_t window) {
|
||||||
|
|
||||||
return returns;
|
return returns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getWindowName(uint64_t window) {
|
||||||
|
PROP(name_cookie, HYPRATOMS["_NET_WM_NAME"], 128);
|
||||||
|
|
||||||
|
const int len = xcb_get_property_value_length(name_cookiereply);
|
||||||
|
char* name = strndup((const char*)xcb_get_property_value(name_cookiereply), len);
|
||||||
|
std::string stringname(name);
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
free(name_cookiereply);
|
||||||
|
|
||||||
|
return stringname;
|
||||||
|
}
|
|
@ -6,3 +6,4 @@
|
||||||
|
|
||||||
std::pair<std::string, std::string> getClassName(int64_t window);
|
std::pair<std::string, std::string> getClassName(int64_t window);
|
||||||
std::string getRoleName(int64_t window);
|
std::string getRoleName(int64_t window);
|
||||||
|
std::string getWindowName(uint64_t window);
|
|
@ -1,7 +1,7 @@
|
||||||
#include "window.hpp"
|
#include "window.hpp"
|
||||||
#include "windowManager.hpp"
|
#include "windowManager.hpp"
|
||||||
|
|
||||||
CWindow::CWindow() { this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); }
|
CWindow::CWindow() { this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); this->setName(""); }
|
||||||
CWindow::~CWindow() { }
|
CWindow::~CWindow() { }
|
||||||
|
|
||||||
void CWindow::generateNodeID() {
|
void CWindow::generateNodeID() {
|
||||||
|
|
|
@ -255,6 +255,12 @@ bool CWindowManager::handleEvent() {
|
||||||
// remove unused workspaces
|
// remove unused workspaces
|
||||||
cleanupUnusedWorkspaces();
|
cleanupUnusedWorkspaces();
|
||||||
|
|
||||||
|
// Update last window name
|
||||||
|
updateActiveWindowName();
|
||||||
|
|
||||||
|
// Update the bar with the freshest stuff
|
||||||
|
updateBarInfo();
|
||||||
|
|
||||||
xcb_flush(DisplayConnection);
|
xcb_flush(DisplayConnection);
|
||||||
|
|
||||||
// Restore thread state
|
// Restore thread state
|
||||||
|
@ -541,9 +547,9 @@ void CWindowManager::setEffectiveSizePosUsingConfig(CWindow* pWindow) {
|
||||||
pWindow->setEffectiveSize(pWindow->getSize() - (Vector2D(ConfigManager::getInt("border_size"), ConfigManager::getInt("border_size")) * 2));
|
pWindow->setEffectiveSize(pWindow->getSize() - (Vector2D(ConfigManager::getInt("border_size"), ConfigManager::getInt("border_size")) * 2));
|
||||||
|
|
||||||
// do gaps, set top left
|
// do gaps, set top left
|
||||||
pWindow->setEffectivePosition(pWindow->getEffectivePosition() + Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID == ConfigManager::getInt("bar_monitor") ? ConfigManager::getInt("bar_height") : 0) : ConfigManager::getInt("gaps_in")));
|
pWindow->setEffectivePosition(pWindow->getEffectivePosition() + Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID == ConfigManager::getInt("bar:monitor") ? ConfigManager::getInt("bar:height") : 0) : ConfigManager::getInt("gaps_in")));
|
||||||
// fix to old size bottom right
|
// fix to old size bottom right
|
||||||
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID == ConfigManager::getInt("bar_monitor") ? ConfigManager::getInt("bar_height") : 0) : ConfigManager::getInt("gaps_in")));
|
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID == ConfigManager::getInt("bar:monitor") ? ConfigManager::getInt("bar:height") : 0) : ConfigManager::getInt("gaps_in")));
|
||||||
// set bottom right
|
// set bottom right
|
||||||
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYRIGHT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYBOTTOM ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in")));
|
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYRIGHT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYBOTTOM ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in")));
|
||||||
}
|
}
|
||||||
|
@ -1073,8 +1079,22 @@ void CWindowManager::updateBarInfo() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
message.activeWorkspace = activeWorkspaces[getMonitorFromCursor()->ID];
|
message.activeWorkspace = activeWorkspaces[getMonitorFromCursor()->ID];
|
||||||
|
|
||||||
|
auto winname = getWindowFromDrawable(LastWindow) ? getWindowFromDrawable(LastWindow)->getName() : "";
|
||||||
|
|
||||||
|
for (auto& c : winname) {
|
||||||
|
// Remove illegal chars
|
||||||
|
if (c == '=')
|
||||||
|
c = ' ';
|
||||||
|
else if (c == '\t')
|
||||||
|
c = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
message.lastWindowName = winname;
|
||||||
|
|
||||||
for (auto& workspace : workspaces) {
|
for (auto& workspace : workspaces) {
|
||||||
message.openWorkspaces.push_back(workspace.getID());
|
message.openWorkspaces.push_back(workspace.getID());
|
||||||
}
|
}
|
||||||
|
@ -1121,6 +1141,7 @@ bool CWindowManager::shouldBeFloatedOnInit(int64_t window) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Type stuff
|
// Type stuff
|
||||||
//
|
//
|
||||||
|
@ -1147,3 +1168,16 @@ bool CWindowManager::shouldBeFloatedOnInit(int64_t window) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWindowManager::updateActiveWindowName() {
|
||||||
|
if (!getWindowFromDrawable(LastWindow))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto PLASTWINDOW = getWindowFromDrawable(LastWindow);
|
||||||
|
|
||||||
|
auto WINNAME = getWindowName(LastWindow);
|
||||||
|
if (WINNAME != PLASTWINDOW->getName()) {
|
||||||
|
Debug::log(LOG, "Update, window got name: " + WINNAME);
|
||||||
|
PLASTWINDOW->setName(WINNAME);
|
||||||
|
}
|
||||||
|
}
|
|
@ -96,6 +96,9 @@ public:
|
||||||
void createAndOpenAllPipes();
|
void createAndOpenAllPipes();
|
||||||
void setupDepth();
|
void setupDepth();
|
||||||
|
|
||||||
|
void updateActiveWindowName();
|
||||||
|
void updateBarInfo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Internal WM functions that don't have to be exposed
|
// Internal WM functions that don't have to be exposed
|
||||||
|
@ -110,7 +113,6 @@ public:
|
||||||
void setEffectiveSizePosUsingConfig(CWindow* pWindow);
|
void setEffectiveSizePosUsingConfig(CWindow* pWindow);
|
||||||
void cleanupUnusedWorkspaces();
|
void cleanupUnusedWorkspaces();
|
||||||
xcb_visualtype_t* setupColors();
|
xcb_visualtype_t* setupColors();
|
||||||
void updateBarInfo();
|
|
||||||
void updateRootCursor();
|
void updateRootCursor();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue