2021-11-21 11:25:26 +01:00
|
|
|
#include "Bar.hpp"
|
|
|
|
|
|
|
|
#include <codecvt>
|
|
|
|
#include <locale>
|
2021-11-27 13:28:30 +01:00
|
|
|
#include "../config/ConfigManager.hpp"
|
2021-11-21 11:25:26 +01:00
|
|
|
#include "../windowManager.hpp"
|
|
|
|
|
2021-11-27 13:28:30 +01:00
|
|
|
bool isParentDead() {
|
|
|
|
const auto PPID = getppid();
|
|
|
|
|
|
|
|
return PPID == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t barMainThread() {
|
|
|
|
// Main already created all the pipes
|
|
|
|
|
|
|
|
Debug::log(LOG, "Child says Hello World!");
|
|
|
|
|
|
|
|
// Well now this is the init
|
|
|
|
// it's pretty tricky because we only need to init the stuff we need
|
|
|
|
g_pWindowManager->DisplayConnection = xcb_connect(NULL, NULL);
|
|
|
|
if (const auto RET = xcb_connection_has_error(g_pWindowManager->DisplayConnection); RET != 0) {
|
|
|
|
Debug::log(CRIT, "Connection Failed! Return: " + std::to_string(RET));
|
|
|
|
return RET;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Screen
|
|
|
|
g_pWindowManager->Screen = xcb_setup_roots_iterator(xcb_get_setup(g_pWindowManager->DisplayConnection)).data;
|
|
|
|
|
|
|
|
if (!g_pWindowManager->Screen) {
|
|
|
|
Debug::log(CRIT, "Screen was null!");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug::log(LOG, "Bar init Phase 1 done.");
|
|
|
|
|
|
|
|
// Init randr for monitors.
|
|
|
|
g_pWindowManager->setupRandrMonitors();
|
|
|
|
|
|
|
|
// Init depth
|
|
|
|
g_pWindowManager->setupDepth();
|
|
|
|
|
|
|
|
// Setup our bar
|
|
|
|
CStatusBar STATUSBAR;
|
|
|
|
|
|
|
|
// Tell everyone we are in the child process.
|
|
|
|
g_pWindowManager->statusBar = &STATUSBAR;
|
|
|
|
|
|
|
|
Debug::log(LOG, "Bar init Phase 2 done.");
|
|
|
|
|
|
|
|
// Init config manager
|
|
|
|
ConfigManager::init();
|
|
|
|
|
|
|
|
STATUSBAR.setup(0);
|
|
|
|
|
|
|
|
Debug::log(LOG, "Bar setup finished!");
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
ConfigManager::tick();
|
|
|
|
|
|
|
|
// Recieve the message and send our reply
|
|
|
|
IPCRecieveMessageB(g_pWindowManager->m_sIPCBarPipeIn.szPipeName);
|
|
|
|
SIPCMessageBarToMain message;
|
|
|
|
message.windowID = STATUSBAR.getWindowID();
|
|
|
|
IPCSendMessage(g_pWindowManager->m_sIPCBarPipeOut.szPipeName, message);
|
|
|
|
//
|
|
|
|
|
|
|
|
// draw the bar
|
|
|
|
STATUSBAR.draw();
|
|
|
|
|
|
|
|
if (isParentDead()) {
|
|
|
|
// Just for debugging
|
|
|
|
SIPCMessageBarToMain message;
|
|
|
|
message.windowID = 0;
|
|
|
|
IPCSendMessage(g_pWindowManager->m_sIPCBarPipeOut.szPipeName, message);
|
|
|
|
|
|
|
|
Debug::log(LOG, "Bar parent died!");
|
|
|
|
|
|
|
|
return 0; // If the parent died, kill the bar too.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / ConfigManager::getInt("max_fps")));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-21 20:40:22 +01:00
|
|
|
void CStatusBar::setup(int MonitorID) {
|
2021-11-26 20:20:11 +01:00
|
|
|
Debug::log(LOG, "Creating the bar!");
|
2021-11-21 12:40:03 +01:00
|
|
|
|
2021-11-21 20:40:22 +01:00
|
|
|
if (MonitorID > g_pWindowManager->monitors.size()) {
|
|
|
|
MonitorID = 0;
|
|
|
|
Debug::log(ERR, "Incorrect value in MonitorID for the bar. Setting to 0.");
|
2021-11-21 12:40:03 +01:00
|
|
|
}
|
2021-11-21 20:40:22 +01:00
|
|
|
|
|
|
|
const auto MONITOR = g_pWindowManager->monitors[MonitorID];
|
|
|
|
|
|
|
|
m_iMonitorID = MonitorID;
|
|
|
|
m_vecPosition = MONITOR.vecPosition;
|
|
|
|
m_vecSize = Vector2D(MONITOR.vecSize.x, ConfigManager::getInt("bar_height"));
|
2021-11-21 12:40:03 +01:00
|
|
|
|
|
|
|
uint32_t values[4];
|
|
|
|
|
|
|
|
// window
|
|
|
|
m_iWindowID = (xcb_generate_id(g_pWindowManager->DisplayConnection));
|
|
|
|
|
2021-11-27 13:28:30 +01:00
|
|
|
// send the message IMMEDIATELY so that the main thread has time to update our WID.
|
|
|
|
SIPCMessageBarToMain message;
|
|
|
|
message.windowID = m_iWindowID;
|
|
|
|
IPCSendMessage(g_pWindowManager->m_sIPCBarPipeOut.szPipeName, message);
|
|
|
|
|
2021-11-21 12:40:03 +01:00
|
|
|
values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
|
|
|
|
|
|
|
xcb_create_window(g_pWindowManager->DisplayConnection, g_pWindowManager->Depth, m_iWindowID,
|
|
|
|
g_pWindowManager->Screen->root, m_vecPosition.x, m_vecPosition.y, m_vecSize.x, m_vecSize.y,
|
|
|
|
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, g_pWindowManager->Screen->root_visual,
|
|
|
|
XCB_CW_EVENT_MASK, values);
|
|
|
|
|
|
|
|
// map
|
|
|
|
xcb_map_window(g_pWindowManager->DisplayConnection, m_iWindowID);
|
2021-11-21 11:25:26 +01:00
|
|
|
|
|
|
|
// Create a pixmap for writing to.
|
|
|
|
m_iPixmap = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
|
|
xcb_create_pixmap(g_pWindowManager->DisplayConnection, g_pWindowManager->Depth, m_iPixmap, m_iWindowID, m_vecSize.x, m_vecSize.y);
|
|
|
|
|
2021-11-21 12:40:03 +01:00
|
|
|
// setup contexts.. ugh..
|
2021-11-21 11:25:26 +01:00
|
|
|
|
|
|
|
auto contextBG = &m_mContexts["BG"];
|
|
|
|
contextBG->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
values[0] = 0xFF111111;
|
|
|
|
values[1] = 0xFF111111;
|
2021-11-21 11:25:26 +01:00
|
|
|
xcb_create_gc(g_pWindowManager->DisplayConnection, contextBG->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, values);
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
auto contextBGT = &m_mContexts["BGT"];
|
|
|
|
contextBGT->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
|
|
|
|
|
|
values[0] = 0x00000000;
|
|
|
|
values[1] = 0x00000000;
|
|
|
|
xcb_create_gc(g_pWindowManager->DisplayConnection, contextBGT->GContext, m_iPixmap, XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, values);
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
2021-11-21 11:25:26 +01:00
|
|
|
auto contextBASETEXT = &m_mContexts["BASETEXT"];
|
|
|
|
|
|
|
|
contextBASETEXT->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
|
|
contextBASETEXT->Font = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
|
|
xcb_open_font(g_pWindowManager->DisplayConnection, contextBASETEXT->Font, 5, "fixed");
|
2021-11-26 20:20:11 +01:00
|
|
|
values[0] = 0xFFFFFFFF;
|
|
|
|
values[1] = 0xFF111111;
|
2021-11-21 11:25:26 +01:00
|
|
|
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;
|
2021-11-26 20:20:11 +01:00
|
|
|
values[0] = 0xFF000000;
|
|
|
|
values[1] = 0xFFFF3333;
|
2021-11-21 11:25:26 +01:00
|
|
|
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);
|
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
values[0] = 0xFFFF3333;
|
|
|
|
values[1] = 0xFF111111;
|
2021-11-21 11:25:26 +01:00
|
|
|
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);
|
2021-11-22 21:20:32 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
m_pCairoSurface = cairo_xcb_surface_create(g_pWindowManager->DisplayConnection, m_iPixmap, g_pWindowManager->VisualType,
|
|
|
|
m_vecSize.x, m_vecSize.y);
|
|
|
|
m_pCairo = cairo_create(m_pCairoSurface);
|
|
|
|
cairo_surface_destroy(m_pCairoSurface);
|
2021-11-21 11:25:26 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 12:40:03 +01:00
|
|
|
void CStatusBar::destroy() {
|
2021-11-26 20:20:11 +01:00
|
|
|
Debug::log(LOG, "Destroying the bar!");
|
|
|
|
|
2021-11-21 12:40:03 +01:00
|
|
|
xcb_close_font(g_pWindowManager->DisplayConnection, m_mContexts["HITEXT"].Font);
|
|
|
|
xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iWindowID);
|
|
|
|
xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iPixmap);
|
|
|
|
|
|
|
|
xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["BG"].GContext);
|
|
|
|
xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["MEDBG"].GContext);
|
|
|
|
xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["TEXT"].GContext);
|
|
|
|
xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["HITEXT"].GContext);
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
// Free cairo
|
|
|
|
cairo_destroy(m_pCairo);
|
|
|
|
m_pCairo = nullptr;
|
|
|
|
}
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
int CStatusBar::getTextWidth(std::string text) {
|
|
|
|
cairo_select_font_face(m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
|
|
|
cairo_set_font_size(m_pCairo, 12);
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
cairo_text_extents_t textextents;
|
|
|
|
cairo_text_extents(m_pCairo, text.c_str(), &textextents);
|
|
|
|
|
|
|
|
return textextents.width + 1 /* pad */;
|
|
|
|
}
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
void CStatusBar::drawText(Vector2D pos, std::string text, uint32_t color) {
|
|
|
|
cairo_select_font_face(m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
|
|
|
cairo_set_font_size(m_pCairo, 12);
|
|
|
|
cairo_set_source_rgba(m_pCairo, RED(color), GREEN(color), BLUE(color), ALPHA(color));
|
|
|
|
cairo_move_to(m_pCairo, pos.x, pos.y);
|
|
|
|
cairo_show_text(m_pCairo, text.c_str());
|
2021-11-21 11:25:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CStatusBar::draw() {
|
|
|
|
|
2021-11-27 13:28:30 +01:00
|
|
|
// const auto WORKSPACE = g_pWindowManager->getWorkspaceByID(g_pWindowManager->activeWorkspaces[m_iMonitorID]);
|
2021-11-21 19:59:59 +01:00
|
|
|
|
2021-11-27 13:28:30 +01:00
|
|
|
// if (!WORKSPACE || WORKSPACE->getHasFullscreenWindow()) // TODO: fix this
|
|
|
|
// return; // Do not draw a bar on a fullscreen window.
|
2021-11-21 11:42:44 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
if (!m_pCairo) {
|
|
|
|
Debug::log(ERR, "Cairo is null but attempted to draw!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-21 22:24:38 +01:00
|
|
|
xcb_rectangle_t rectangles[] = {{(int)0, (int)0, (int)m_vecSize.x, (int)m_vecSize.y}};
|
2021-11-21 11:25:26 +01:00
|
|
|
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, m_mContexts["BG"].GContext, 1, rectangles);
|
|
|
|
|
|
|
|
// Draw workspaces
|
|
|
|
int drawnWorkspaces = 0;
|
2021-11-26 20:20:11 +01:00
|
|
|
for (long unsigned int i = 0; i < openWorkspaces.size(); ++i) {
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-21 22:24:38 +01:00
|
|
|
const auto WORKSPACE = openWorkspaces[i];
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-21 20:21:58 +01:00
|
|
|
// The LastWindow may be on a different one. This is where the mouse is.
|
2021-11-21 22:24:38 +01:00
|
|
|
const auto MOUSEWORKSPACEID = m_iCurrentWorkspace;
|
2021-11-21 20:21:58 +01:00
|
|
|
|
2021-11-21 11:25:26 +01:00
|
|
|
if (!WORKSPACE)
|
|
|
|
continue;
|
|
|
|
|
2021-11-21 22:24:38 +01:00
|
|
|
std::string workspaceName = std::to_string(openWorkspaces[i]);
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
xcb_rectangle_t rectangleActive[] = { { 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);
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
drawText(Vector2D(m_vecSize.y * drawnWorkspaces + m_vecSize.y / 2.f - getTextWidth(workspaceName) / 2.f, m_vecSize.y - (m_vecSize.y - 9) / 2.f),
|
|
|
|
workspaceName, WORKSPACE == MOUSEWORKSPACEID ? 0xFF111111 : 0xFFFFFFFF);
|
2021-11-21 11:25:26 +01:00
|
|
|
|
|
|
|
drawnWorkspaces++;
|
|
|
|
}
|
|
|
|
|
2021-11-24 19:17:13 +01:00
|
|
|
// Draw STATUS to the right
|
|
|
|
std::string STATUS = exec(m_szStatusCommand.c_str());
|
|
|
|
STATUS = STATUS.substr(0, (STATUS.length() > 0 ? STATUS.length() - 1 : 9999999));
|
|
|
|
if (STATUS != "") {
|
2021-11-26 20:20:11 +01:00
|
|
|
drawText(Vector2D(m_vecSize.x - getTextWidth(STATUS), m_vecSize.y - (m_vecSize.y - 9) / 2.f),
|
|
|
|
STATUS, 0xFFFFFFFF);
|
2021-11-24 19:17:13 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 11:25:26 +01:00
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
cairo_surface_flush(m_pCairoSurface);
|
|
|
|
|
|
|
|
// clear before copying
|
|
|
|
//xcb_clear_area(g_pWindowManager->DisplayConnection, 0, m_iWindowID, 0, 0, m_vecSize.x, m_vecSize.y);
|
|
|
|
//xcb_flush(g_pWindowManager->DisplayConnection);
|
2021-11-21 11:25:26 +01:00
|
|
|
|
|
|
|
xcb_copy_area(g_pWindowManager->DisplayConnection, m_iPixmap, m_iWindowID, m_mContexts["BG"].GContext,
|
|
|
|
0, 0, 0, 0, m_vecSize.x, m_vecSize.y);
|
2021-11-26 20:20:11 +01:00
|
|
|
|
|
|
|
xcb_flush(g_pWindowManager->DisplayConnection);
|
2021-11-21 11:25:26 +01:00
|
|
|
}
|