mirror of https://github.com/hyprwm/Hypr.git
Multi monitor support
This commit is contained in:
parent
0c842d35be
commit
b66200013a
|
@ -135,19 +135,29 @@ void KeybindManager::changeworkspace(std::string arg) {
|
||||||
if (ID != -1) {
|
if (ID != -1) {
|
||||||
Debug::log(LOG, "Changing the current workspace to " + std::to_string(ID));
|
Debug::log(LOG, "Changing the current workspace to " + std::to_string(ID));
|
||||||
|
|
||||||
|
const auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow);
|
||||||
|
SMonitor* MONITOR = nullptr;
|
||||||
|
if (PLASTWINDOW) {
|
||||||
|
MONITOR = g_pWindowManager->getMonitorFromWindow(PLASTWINDOW);
|
||||||
|
} else {
|
||||||
|
MONITOR = g_pWindowManager->getMonitorFromCursor();
|
||||||
|
}
|
||||||
|
|
||||||
// vvvv shouldn't be nullptr wallah
|
// vvvv shouldn't be nullptr wallah
|
||||||
g_pWindowManager->setAllWorkspaceWindowsDirtyByID(g_pWindowManager->activeWorkspace->getID());
|
g_pWindowManager->setAllWorkspaceWindowsDirtyByID(g_pWindowManager->activeWorkspaces[MONITOR->ID]->getID());
|
||||||
g_pWindowManager->changeWorkspaceByID(ID);
|
g_pWindowManager->changeWorkspaceByID(ID);
|
||||||
g_pWindowManager->setAllWorkspaceWindowsDirtyByID(ID);
|
g_pWindowManager->setAllWorkspaceWindowsDirtyByID(ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeybindManager::toggleActiveWindowFullscreen(std::string unusedArg) {
|
void KeybindManager::toggleActiveWindowFullscreen(std::string unusedArg) {
|
||||||
g_pWindowManager->setAllWorkspaceWindowsDirtyByID(g_pWindowManager->activeWorkspace->getID());
|
const auto MONITOR = g_pWindowManager->getMonitorFromWindow(g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow));
|
||||||
|
|
||||||
|
g_pWindowManager->setAllWorkspaceWindowsDirtyByID(g_pWindowManager->activeWorkspaces[MONITOR->ID]->getID());
|
||||||
|
|
||||||
if (auto WINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow) ; WINDOW) {
|
if (auto WINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow) ; WINDOW) {
|
||||||
WINDOW->setFullscreen(!WINDOW->getFullscreen());
|
WINDOW->setFullscreen(!WINDOW->getFullscreen());
|
||||||
g_pWindowManager->activeWorkspace->setHasFullscreenWindow(WINDOW->getFullscreen());
|
g_pWindowManager->activeWorkspaces[MONITOR->ID]->setHasFullscreenWindow(WINDOW->getFullscreen());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ int getTextWidth(std::string text, xcb_font_t font) {
|
||||||
|
|
||||||
void CStatusBar::draw() {
|
void CStatusBar::draw() {
|
||||||
|
|
||||||
if (g_pWindowManager->activeWorkspace->getHasFullscreenWindow())
|
if (g_pWindowManager->activeWorkspaces[m_iMonitorID]->getHasFullscreenWindow())
|
||||||
return; // Do not draw a bar on a fullscreen window.
|
return; // Do not draw a bar on a fullscreen window.
|
||||||
|
|
||||||
xcb_rectangle_t rectangles[] = {{m_vecPosition.x, m_vecPosition.y, m_vecSize.x + m_vecPosition.x, m_vecPosition.y + m_vecSize.y}};
|
xcb_rectangle_t rectangles[] = {{m_vecPosition.x, m_vecPosition.y, m_vecSize.x + m_vecPosition.x, m_vecPosition.y + m_vecSize.y}};
|
||||||
|
@ -140,13 +140,13 @@ void CStatusBar::draw() {
|
||||||
|
|
||||||
std::string workspaceName = std::to_string(i);
|
std::string workspaceName = std::to_string(i);
|
||||||
|
|
||||||
if (WORKSPACE->getID() == g_pWindowManager->activeWorkspace->getID()) {
|
if (WORKSPACE->getID() == g_pWindowManager->activeWorkspaces[m_iMonitorID]->getID()) {
|
||||||
xcb_rectangle_t rectangleActive[] = { { m_vecSize.y * drawnWorkspaces, 0, m_vecSize.y, m_vecSize.y } };
|
xcb_rectangle_t rectangleActive[] = { { m_vecSize.y * drawnWorkspaces, 0, m_vecSize.y, m_vecSize.y } };
|
||||||
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, m_mContexts["MEDBG"].GContext, 1, rectangleActive);
|
xcb_poly_fill_rectangle(g_pWindowManager->DisplayConnection, m_iPixmap, m_mContexts["MEDBG"].GContext, 1, rectangleActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_image_text_8(g_pWindowManager->DisplayConnection, workspaceName.length(), m_iPixmap,
|
xcb_image_text_8(g_pWindowManager->DisplayConnection, workspaceName.length(), m_iPixmap,
|
||||||
WORKSPACE->getID() == g_pWindowManager->activeWorkspace->getID() ? m_mContexts["HITEXT"].GContext : m_mContexts["BASETEXT"].GContext,
|
WORKSPACE->getID() == g_pWindowManager->activeWorkspaces[m_iMonitorID]->getID() ? m_mContexts["HITEXT"].GContext : m_mContexts["BASETEXT"].GContext,
|
||||||
m_vecSize.y * drawnWorkspaces + m_vecSize.y / 2.f - 2, m_vecSize.y - (m_vecSize.y - 10) / 2, workspaceName.c_str());
|
m_vecSize.y * drawnWorkspaces + m_vecSize.y / 2.f - 2, m_vecSize.y - (m_vecSize.y - 10) / 2, workspaceName.c_str());
|
||||||
|
|
||||||
drawnWorkspaces++;
|
drawnWorkspaces++;
|
||||||
|
|
|
@ -13,6 +13,7 @@ class CStatusBar {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
EXPOSED_MEMBER(WindowID, xcb_window_t, i);
|
EXPOSED_MEMBER(WindowID, xcb_window_t, i);
|
||||||
|
EXPOSED_MEMBER(MonitorID, int, i);
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void setup(Vector2D, Vector2D);
|
void setup(Vector2D, Vector2D);
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <xcb/randr.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_ewmh.h>
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xcb_keysyms.h>
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "./helpers/Vector.hpp"
|
#include "./helpers/Vector.hpp"
|
||||||
|
|
||||||
#include "./utilities/Debug.hpp"
|
#include "./utilities/Debug.hpp"
|
||||||
|
|
||||||
#define EXPOSED_MEMBER(var, type, prefix) \
|
#define EXPOSED_MEMBER(var, type, prefix) \
|
||||||
|
@ -23,3 +26,5 @@
|
||||||
void event##name(xcb_generic_event_t* event);
|
void event##name(xcb_generic_event_t* event);
|
||||||
|
|
||||||
#define STICKS(a, b) abs((a) - (b)) < 2
|
#define STICKS(a, b) abs((a) - (b)) < 2
|
||||||
|
|
||||||
|
#define VECINRECT(vec, x1, y1, x2, y2) (vec.x >= (x1) && vec.x <= (x2) && vec.y >= (y1) && vec.y <= (y2))
|
|
@ -62,7 +62,9 @@ void Events::eventMapWindow(xcb_generic_event_t* event) {
|
||||||
window.setDrawable(E->window);
|
window.setDrawable(E->window);
|
||||||
window.setIsFloating(false);
|
window.setIsFloating(false);
|
||||||
window.setDirty(true);
|
window.setDirty(true);
|
||||||
window.setWorkspaceID(g_pWindowManager->activeWorkspace->getID());
|
const auto CURRENTSCREEN = g_pWindowManager->getMonitorFromCursor()->ID;
|
||||||
|
window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]->getID());
|
||||||
|
window.setMonitor(CURRENTSCREEN);
|
||||||
|
|
||||||
window.setDefaultPosition(Vector2D(0,0));
|
window.setDefaultPosition(Vector2D(0,0));
|
||||||
window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels/2.f,g_pWindowManager->Screen->height_in_pixels/2.f));
|
window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels/2.f,g_pWindowManager->Screen->height_in_pixels/2.f));
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
|
||||||
|
struct SMonitor {
|
||||||
|
Vector2D vecPosition = Vector2D(0,0);
|
||||||
|
Vector2D vecSize = Vector2D(0,0);
|
||||||
|
|
||||||
|
bool hasABar = false;
|
||||||
|
bool primary = false;
|
||||||
|
|
||||||
|
int ID = -1;
|
||||||
|
|
||||||
|
std::string szName = "";
|
||||||
|
};
|
|
@ -10,5 +10,7 @@ public:
|
||||||
EXPOSED_MEMBER(ID, int, i);
|
EXPOSED_MEMBER(ID, int, i);
|
||||||
EXPOSED_MEMBER(LastWindow, xcb_drawable_t, i);
|
EXPOSED_MEMBER(LastWindow, xcb_drawable_t, i);
|
||||||
|
|
||||||
|
EXPOSED_MEMBER(Monitor, int, i);
|
||||||
|
|
||||||
EXPOSED_MEMBER(HasFullscreenWindow, bool, b);
|
EXPOSED_MEMBER(HasFullscreenWindow, bool, b);
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,6 +36,9 @@ public:
|
||||||
EXPOSED_MEMBER(DefaultSize, Vector2D, vec);
|
EXPOSED_MEMBER(DefaultSize, Vector2D, vec);
|
||||||
EXPOSED_MEMBER(DefaultPosition, Vector2D, vec);
|
EXPOSED_MEMBER(DefaultPosition, Vector2D, vec);
|
||||||
|
|
||||||
|
// Monitors
|
||||||
|
EXPOSED_MEMBER(Monitor, int, i);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "windowManager.hpp"
|
#include "windowManager.hpp"
|
||||||
#include "./events/events.hpp"
|
#include "./events/events.hpp"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
xcb_visualtype_t* CWindowManager::setupColors() {
|
xcb_visualtype_t* CWindowManager::setupColors() {
|
||||||
auto depthIter = xcb_screen_allowed_depths_iterator(Screen);
|
auto depthIter = xcb_screen_allowed_depths_iterator(Screen);
|
||||||
|
@ -14,8 +15,77 @@ xcb_visualtype_t* CWindowManager::setupColors() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWindowManager::setupRandrMonitors() {
|
||||||
|
auto ScreenResReply = xcb_randr_get_screen_resources_current_reply(DisplayConnection, xcb_randr_get_screen_resources_current(DisplayConnection, Screen->root), NULL);
|
||||||
|
if (!ScreenResReply) {
|
||||||
|
Debug::log(ERR, "ScreenResReply NULL!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto MONITORNUM = xcb_randr_get_screen_resources_current_outputs_length(ScreenResReply);
|
||||||
|
auto OUTPUTS = xcb_randr_get_screen_resources_current_outputs(ScreenResReply);
|
||||||
|
|
||||||
|
xcb_randr_get_output_info_reply_t* outputReply;
|
||||||
|
xcb_randr_get_crtc_info_reply_t* crtcReply;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < MONITORNUM; i++) {
|
||||||
|
outputReply = xcb_randr_get_output_info_reply(DisplayConnection, xcb_randr_get_output_info(DisplayConnection, OUTPUTS[i], XCB_CURRENT_TIME), NULL);
|
||||||
|
if (outputReply->crtc == XCB_NONE)
|
||||||
|
continue;
|
||||||
|
crtcReply = xcb_randr_get_crtc_info_reply(DisplayConnection, xcb_randr_get_crtc_info(DisplayConnection, outputReply->crtc, XCB_CURRENT_TIME), NULL);
|
||||||
|
if (!crtcReply)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
monitors.push_back(SMonitor());
|
||||||
|
|
||||||
|
monitors[i].vecPosition = Vector2D(crtcReply->x, crtcReply->y);
|
||||||
|
monitors[i].vecSize = Vector2D(crtcReply->width, crtcReply->height);
|
||||||
|
|
||||||
|
monitors[i].ID = i;
|
||||||
|
|
||||||
|
char* name = (char*)xcb_randr_get_output_info_name(outputReply);
|
||||||
|
int nameLen = xcb_randr_get_output_info_name_length(outputReply);
|
||||||
|
|
||||||
|
for (int j = 0; j < nameLen; ++j) {
|
||||||
|
monitors[i].szName += name[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto EXTENSIONREPLY = xcb_get_extension_data(DisplayConnection, &xcb_randr_id);
|
||||||
|
if (!EXTENSIONREPLY->present)
|
||||||
|
Debug::log(ERR, "RandR extension missing");
|
||||||
|
else {
|
||||||
|
//listen for screen change events
|
||||||
|
xcb_randr_select_input(DisplayConnection, Screen->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CWindowManager::setupManager() {
|
void CWindowManager::setupManager() {
|
||||||
ConfigManager::init();
|
ConfigManager::init();
|
||||||
|
setupRandrMonitors();
|
||||||
|
|
||||||
|
if (monitors.size() == 0) {
|
||||||
|
// RandR failed!
|
||||||
|
Debug::log(WARN, "RandR failed!");
|
||||||
|
|
||||||
|
monitors.push_back(SMonitor());
|
||||||
|
monitors[0].vecPosition = Vector2D(0,0);
|
||||||
|
monitors[0].vecSize = Vector2D(Screen->width_in_pixels, Screen->height_in_pixels);
|
||||||
|
monitors[0].ID = 0;
|
||||||
|
monitors[0].szName = "Screen";
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: get it normally.
|
||||||
|
if (monitors.size() > 1) {
|
||||||
|
monitors[1].primary = true;
|
||||||
|
monitors[1].hasABar = true;
|
||||||
|
} else {
|
||||||
|
monitors[0].primary = true;
|
||||||
|
monitors[0].hasABar = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
Values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
||||||
xcb_change_window_attributes_checked(DisplayConnection, Screen->root,
|
xcb_change_window_attributes_checked(DisplayConnection, Screen->root,
|
||||||
|
@ -42,11 +112,14 @@ void CWindowManager::setupManager() {
|
||||||
|
|
||||||
xcb_flush(DisplayConnection);
|
xcb_flush(DisplayConnection);
|
||||||
|
|
||||||
// Add a workspace to the monitor
|
// Add workspaces to the monitors
|
||||||
|
for (int i = 0; i < monitors.size(); ++i) {
|
||||||
CWorkspace protoWorkspace;
|
CWorkspace protoWorkspace;
|
||||||
protoWorkspace.setID(1);
|
protoWorkspace.setID(i + 1);
|
||||||
|
protoWorkspace.setMonitor(i);
|
||||||
workspaces.push_back(protoWorkspace);
|
workspaces.push_back(protoWorkspace);
|
||||||
activeWorkspace = &workspaces[0];
|
activeWorkspaces.push_back(&workspaces[i]);
|
||||||
|
}
|
||||||
//
|
//
|
||||||
|
|
||||||
// init visual type, default 32 bit depth
|
// init visual type, default 32 bit depth
|
||||||
|
@ -60,7 +133,12 @@ void CWindowManager::setupManager() {
|
||||||
|
|
||||||
// ---- INIT THE BAR ---- //
|
// ---- INIT THE BAR ---- //
|
||||||
|
|
||||||
statusBar.setup(Vector2D(0, 0), Vector2D(Screen->width_in_pixels, ConfigManager::getInt("bar_height")));
|
for (auto& monitor : monitors) {
|
||||||
|
if (monitor.primary) {
|
||||||
|
statusBar.setup(Vector2D(monitor.vecPosition.x, monitor.vecPosition.y), Vector2D(monitor.vecSize.x, ConfigManager::getInt("bar_height")));
|
||||||
|
statusBar.setMonitorID(monitor.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// start its' update thread
|
// start its' update thread
|
||||||
Events::setThread();
|
Events::setThread();
|
||||||
|
@ -128,7 +206,7 @@ void CWindowManager::cleanupUnusedWorkspaces() {
|
||||||
workspaces.clear();
|
workspaces.clear();
|
||||||
|
|
||||||
for (auto& work : temp) {
|
for (auto& work : temp) {
|
||||||
if (work.getID() != activeWorkspace->getID()) {
|
if (!isWorkspaceVisible(work.getID())) {
|
||||||
// check if it has any children
|
// check if it has any children
|
||||||
bool hasChildren = false;
|
bool hasChildren = false;
|
||||||
for (auto& window : windows) {
|
for (auto& window : windows) {
|
||||||
|
@ -156,11 +234,12 @@ void CWindowManager::refreshDirtyWindows() {
|
||||||
setEffectiveSizePosUsingConfig(&window);
|
setEffectiveSizePosUsingConfig(&window);
|
||||||
|
|
||||||
// Fullscreen flag
|
// Fullscreen flag
|
||||||
bool bHasFullscreenWindow = activeWorkspace->getHasFullscreenWindow();
|
bool bHasFullscreenWindow = getWorkspaceByID(window.getWorkspaceID())->getHasFullscreenWindow();
|
||||||
|
|
||||||
// first and foremost, let's check if the window isn't on a different workspace
|
// first and foremost, let's check if the window isn't on a hidden workspace
|
||||||
// or that it is not a non-fullscreen window in a fullscreen workspace
|
// or that it is not a non-fullscreen window in a fullscreen workspace
|
||||||
if ((window.getWorkspaceID() != activeWorkspace->getID()) || (bHasFullscreenWindow && !window.getFullscreen())) {
|
if (!isWorkspaceVisible(window.getWorkspaceID())
|
||||||
|
|| (bHasFullscreenWindow && !window.getFullscreen())) {
|
||||||
// Move it to hades
|
// Move it to hades
|
||||||
Values[0] = (int)1500000; // hmu when monitors actually have that many pixels
|
Values[0] = (int)1500000; // hmu when monitors actually have that many pixels
|
||||||
Values[1] = (int)1500000; // and we are still using xorg =)
|
Values[1] = (int)1500000; // and we are still using xorg =)
|
||||||
|
@ -310,8 +389,10 @@ CWindow* CWindowManager::findWindowAtCursor() {
|
||||||
|
|
||||||
free(pointerreply);
|
free(pointerreply);
|
||||||
|
|
||||||
|
const auto WORKSPACE = activeWorkspaces[getMonitorFromCursor()->ID];
|
||||||
|
|
||||||
for (auto& window : windows) {
|
for (auto& window : windows) {
|
||||||
if (window.getWorkspaceID() == activeWorkspace->getID() && !window.getIsFloating()) {
|
if (window.getWorkspaceID() == WORKSPACE->getID() && !window.getIsFloating()) {
|
||||||
|
|
||||||
if (cursorPos.x >= window.getPosition().x
|
if (cursorPos.x >= window.getPosition().x
|
||||||
&& cursorPos.x <= window.getPosition().x + window.getSize().x
|
&& cursorPos.x <= window.getPosition().x + window.getSize().x
|
||||||
|
@ -322,6 +403,8 @@ CWindow* CWindowManager::findWindowAtCursor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
||||||
|
@ -349,8 +432,9 @@ void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
||||||
PLASTWINDOW->setDirty(true);
|
PLASTWINDOW->setDirty(true);
|
||||||
} else {
|
} else {
|
||||||
// Open a fullscreen window
|
// Open a fullscreen window
|
||||||
pWindow->setSize(Vector2D(Screen->width_in_pixels, Screen->height_in_pixels));
|
const auto MONITOR = getMonitorFromCursor();
|
||||||
pWindow->setPosition(Vector2D(0, 0));
|
pWindow->setSize(Vector2D(MONITOR->vecSize.x, MONITOR->vecSize.y));
|
||||||
|
pWindow->setPosition(Vector2D(MONITOR->vecPosition.x, MONITOR->vecPosition.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +462,7 @@ void CWindowManager::calculateNewWindowParams(CWindow* pWindow) {
|
||||||
|
|
||||||
bool CWindowManager::isNeighbor(CWindow* a, CWindow* b) {
|
bool CWindowManager::isNeighbor(CWindow* a, CWindow* b) {
|
||||||
|
|
||||||
if (a->getWorkspaceID() != b->getWorkspaceID())
|
if (a->getWorkspaceID() != b->getWorkspaceID() || getMonitorFromWindow(a) != getMonitorFromWindow(b))
|
||||||
return false; // Different workspaces
|
return false; // Different workspaces
|
||||||
|
|
||||||
const auto POSA = a->getPosition();
|
const auto POSA = a->getPosition();
|
||||||
|
@ -431,7 +515,8 @@ bool CWindowManager::canEatWindow(CWindow* a, CWindow* toEat) {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto& w : windows) {
|
for (auto& w : windows) {
|
||||||
if (w.getDrawable() == a->getDrawable() || w.getDrawable() == toEat->getDrawable() || w.getWorkspaceID() != toEat->getWorkspaceID() || w.getIsFloating())
|
if (w.getDrawable() == a->getDrawable() || w.getDrawable() == toEat->getDrawable() || w.getWorkspaceID() != toEat->getWorkspaceID()
|
||||||
|
|| w.getIsFloating() || getMonitorFromWindow(&w) != getMonitorFromWindow(toEat))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (doOverlap(&w))
|
if (doOverlap(&w))
|
||||||
|
@ -457,14 +542,16 @@ void CWindowManager::fixWindowOnClose(CWindow* pClosedWindow) {
|
||||||
if (!pClosedWindow)
|
if (!pClosedWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const auto WORKSPACE = activeWorkspaces[getMonitorFromWindow(pClosedWindow)->ID];
|
||||||
|
|
||||||
// Fix if was fullscreen
|
// Fix if was fullscreen
|
||||||
if (pClosedWindow->getFullscreen())
|
if (pClosedWindow->getFullscreen())
|
||||||
activeWorkspace->setHasFullscreenWindow(false);
|
WORKSPACE->setHasFullscreenWindow(false);
|
||||||
|
|
||||||
// get the first neighboring window
|
// get the first neighboring window
|
||||||
CWindow* neighbor = nullptr;
|
CWindow* neighbor = nullptr;
|
||||||
for(auto& w : windows) {
|
for(auto& w : windows) {
|
||||||
if (w.getDrawable() == pClosedWindow->getDrawable())
|
if (w.getDrawable() == pClosedWindow->getDrawable() || getMonitorFromWindow(&w) != getMonitorFromWindow(pClosedWindow))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (isNeighbor(&w, pClosedWindow) && canEatWindow(&w, pClosedWindow)) {
|
if (isNeighbor(&w, pClosedWindow) && canEatWindow(&w, pClosedWindow)) {
|
||||||
|
@ -568,19 +655,29 @@ void CWindowManager::moveActiveWindowTo(char dir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindowManager::changeWorkspaceByID(int ID) {
|
void CWindowManager::changeWorkspaceByID(int ID) {
|
||||||
|
|
||||||
|
const auto MONITOR = getMonitorFromCursor();
|
||||||
|
|
||||||
for (auto& workspace : workspaces) {
|
for (auto& workspace : workspaces) {
|
||||||
if (workspace.getID() == ID) {
|
if (workspace.getID() == ID) {
|
||||||
activeWorkspace = &workspace;
|
if (workspace.getMonitor() == MONITOR->ID) {
|
||||||
|
activeWorkspaces[MONITOR->ID] = &workspace;
|
||||||
LastWindow = -1;
|
LastWindow = -1;
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
activeWorkspaces[workspace.getMonitor()] = &workspace;
|
||||||
|
LastWindow = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are here it means the workspace is new. Let's create it.
|
// If we are here it means the workspace is new. Let's create it.
|
||||||
CWorkspace newWorkspace;
|
CWorkspace newWorkspace;
|
||||||
newWorkspace.setID(ID);
|
newWorkspace.setID(ID);
|
||||||
|
newWorkspace.setMonitor(MONITOR->ID);
|
||||||
workspaces.push_back(newWorkspace);
|
workspaces.push_back(newWorkspace);
|
||||||
activeWorkspace = &workspaces[workspaces.size() - 1];
|
activeWorkspaces[MONITOR->ID] = &workspaces[workspaces.size() - 1];
|
||||||
LastWindow = -1;
|
LastWindow = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,3 +725,38 @@ CWorkspace* CWindowManager::getWorkspaceByID(int ID) {
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SMonitor* CWindowManager::getMonitorFromWindow(CWindow* pWindow) {
|
||||||
|
return &monitors[pWindow->getMonitor()];
|
||||||
|
}
|
||||||
|
|
||||||
|
SMonitor* CWindowManager::getMonitorFromCursor() {
|
||||||
|
const auto POINTERCOOKIE = xcb_query_pointer(DisplayConnection, Screen->root);
|
||||||
|
|
||||||
|
xcb_query_pointer_reply_t* pointerreply = xcb_query_pointer_reply(DisplayConnection, POINTERCOOKIE, NULL);
|
||||||
|
if (!pointerreply) {
|
||||||
|
Debug::log(ERR, "Couldn't query pointer.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto CURSORPOS = Vector2D(pointerreply->root_x, pointerreply->root_y);
|
||||||
|
free(pointerreply);
|
||||||
|
|
||||||
|
for (auto& monitor : monitors) {
|
||||||
|
if (VECINRECT(CURSORPOS, monitor.vecPosition.x, monitor.vecPosition.y, monitor.vecPosition.x + monitor.vecSize.x, monitor.vecPosition.y + monitor.vecSize.y))
|
||||||
|
return &monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// should never happen tho, I'm using >= and the cursor cant get outside the screens, i hope.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWindowManager::isWorkspaceVisible(int workspaceID) {
|
||||||
|
|
||||||
|
for (auto& workspace : activeWorkspaces) {
|
||||||
|
if (workspace->getID() == workspaceID)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "utilities/Workspace.hpp"
|
#include "utilities/Workspace.hpp"
|
||||||
#include "bar/Bar.hpp"
|
#include "bar/Bar.hpp"
|
||||||
#include "config/ConfigManager.hpp"
|
#include "config/ConfigManager.hpp"
|
||||||
|
#include "utilities/Monitor.hpp"
|
||||||
|
|
||||||
class CWindowManager {
|
class CWindowManager {
|
||||||
public:
|
public:
|
||||||
|
@ -19,6 +20,8 @@ public:
|
||||||
xcb_drawable_t Drawable;
|
xcb_drawable_t Drawable;
|
||||||
uint32_t Values[3];
|
uint32_t Values[3];
|
||||||
|
|
||||||
|
std::vector<SMonitor> monitors;
|
||||||
|
|
||||||
bool modKeyDown = false;
|
bool modKeyDown = false;
|
||||||
|
|
||||||
uint8_t Depth = 32;
|
uint8_t Depth = 32;
|
||||||
|
@ -28,7 +31,7 @@ public:
|
||||||
xcb_drawable_t LastWindow = -1;
|
xcb_drawable_t LastWindow = -1;
|
||||||
|
|
||||||
std::vector<CWorkspace> workspaces;
|
std::vector<CWorkspace> workspaces;
|
||||||
CWorkspace* activeWorkspace = nullptr;
|
std::vector<CWorkspace*> activeWorkspaces;
|
||||||
|
|
||||||
CStatusBar statusBar;
|
CStatusBar statusBar;
|
||||||
std::thread* barThread;
|
std::thread* barThread;
|
||||||
|
@ -56,10 +59,15 @@ public:
|
||||||
|
|
||||||
void setAllWindowsDirty();
|
void setAllWindowsDirty();
|
||||||
|
|
||||||
|
SMonitor* getMonitorFromWindow(CWindow*);
|
||||||
|
SMonitor* getMonitorFromCursor();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Internal WM functions that don't have to be exposed
|
// Internal WM functions that don't have to be exposed
|
||||||
|
|
||||||
|
void setupRandrMonitors();
|
||||||
|
|
||||||
CWindow* getNeighborInDir(char dir);
|
CWindow* getNeighborInDir(char dir);
|
||||||
void eatWindow(CWindow* a, CWindow* toEat);
|
void eatWindow(CWindow* a, CWindow* toEat);
|
||||||
bool canEatWindow(CWindow* a, CWindow* toEat);
|
bool canEatWindow(CWindow* a, CWindow* toEat);
|
||||||
|
@ -70,6 +78,7 @@ private:
|
||||||
void setEffectiveSizePosUsingConfig(CWindow* pWindow);
|
void setEffectiveSizePosUsingConfig(CWindow* pWindow);
|
||||||
void cleanupUnusedWorkspaces();
|
void cleanupUnusedWorkspaces();
|
||||||
xcb_visualtype_t* setupColors();
|
xcb_visualtype_t* setupColors();
|
||||||
|
bool isWorkspaceVisible(int workspaceID);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue