Compare commits

..

12 Commits

Author SHA1 Message Date
vaxerski
0f8712ed64 fix crash in moveWorkspaceToMonitor 2022-05-31 18:47:32 +02:00
vaxerski
3e28a8b690 added slidevert for workspaces 2022-05-31 17:56:33 +02:00
vaxerski
8de7cc5a8d opacity windowrule support 2 values 2022-05-31 17:35:50 +02:00
vaxerski
e73df80782 Add mon in mon out events and fix crash 2022-05-31 17:17:44 +02:00
vaxerski
0d7131d30e fix typo in hyprctl clients and activewindow 2022-05-31 16:52:28 +02:00
vaxerski
d2e0b7c22a render special over fullscreen 2022-05-31 14:20:41 +02:00
vaxerski
c1193ee483 updated readme features 2022-05-31 14:15:28 +02:00
vaxerski
042e79b888 fix fatal crash 2022-05-31 14:04:11 +02:00
vaxerski
0055efc4f1 Added a special workspace 2022-05-31 14:01:00 +02:00
vaxerski
df722cbb86 Added relative monitor workspace offset 2022-05-31 12:33:08 +02:00
vaxerski
68f7e565e6 Use existing default mon workspace if available on connect 2022-05-31 12:10:34 +02:00
vaxerski
48a3b1c514 fix oopsie 2022-05-31 11:02:54 +02:00
19 changed files with 365 additions and 55 deletions

View File

@@ -126,4 +126,4 @@ config:
cd wlroots && meson ./build --prefix=/usr --buildtype=release
cd wlroots && ninja -C build/
cd wlroots && sudo cp ./build/libwlroots.so.11032 /usr/lib/
cd wlroots && sudo ninja -C build/ install

View File

@@ -51,17 +51,18 @@ Try it out and report bugs / suggestions!
- Easily expandable and readable codebase
- Config reloaded instantly upon saving
- Bezier-curve window animations
- Custom bezier curve based animations
- Workspaces protocol support
- wlr_ext workspaces protocol support
- Dual Kawase blur
- Window fade in / out
- Fully dynamic workspaces
- Window / layer fade in / out
- Tiling/floating/fullscreen windows
- Special Workspace (Scratchpad)
- Window/monitor rules
- Socket-based IPC
- Event System for bash scripts
- Rounded corners
- Damage tracking(*Experimental*)
- Moving/resizing
- Full Damage tracking
- Docks support
<br>

View File

@@ -314,6 +314,15 @@ bool CCompositor::windowExists(CWindow* pWindow) {
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && !w.m_bHidden)
return &w;
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
@@ -332,6 +341,15 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && !w.m_bHidden)
return &w;
}
}
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden)
@@ -343,6 +361,16 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
// special workspace
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bHidden)
return &w;
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
@@ -362,6 +390,14 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor();
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped)
return &w;
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
@@ -576,6 +612,9 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
for (auto& m : m_lMonitors) {
if (m.activeWorkspace == w)
return true;
if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
return true;
}
return false;
@@ -595,6 +634,14 @@ void CCompositor::sanityCheckWorkspaces() {
if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) {
it = m_lWorkspaces.erase(it);
}
if (it->m_iID == SPECIAL_WORKSPACE_ID && getWindowsOnWorkspace(it->m_iID) == 0) {
for (auto& m : m_lMonitors) {
m.specialWorkspaceOpen = false;
}
it = m_lWorkspaces.erase(it);
}
}
}
@@ -1006,8 +1053,9 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't.
Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active %d -> %d", pMonitor->activeWorkspace, pWorkspace->m_iID);
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
if (const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace); PWORKSPACE)
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
pMonitor->activeWorkspace = pWorkspace->m_iID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
@@ -1021,4 +1069,19 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
g_pInputManager->refocus();
}
bool CCompositor::workspaceIDOutOfBounds(const int& id) {
int lowestID = 99999;
int highestID = -99999;
for (auto& w : m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
}
return std::clamp(id, lowestID, highestID) != id;
}

View File

@@ -129,6 +129,7 @@ public:
void moveWindowToWorkspace(CWindow*, const std::string&);
int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
bool workspaceIDOutOfBounds(const int&);
private:
void initAllSignals();

View File

@@ -9,6 +9,7 @@
struct SWindowSpecialRenderData {
float alpha = 1.f;
float alphaInactive = -1.f; // -1 means unset
};
struct SWindowAdditionalConfigData {

View File

@@ -26,7 +26,7 @@ std::string monitorsRequest() {
std::string clientsRequest() {
std::string result = "";
for (auto& w : g_pCompositor->m_lWindows) {
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i, %i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str()), (int)w.m_bIsFloating, w.m_iMonitorID);
}
return result;
@@ -47,7 +47,7 @@ std::string activeWindowRequest() {
if (!g_pCompositor->windowValidMapped(PWINDOW))
return "Invalid";
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i, %i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID);
}

View File

@@ -64,4 +64,6 @@
#endif
#ifndef GIT_DIRTY
#define GIT_DIRTY "?"
#endif
#endif
#define SPECIAL_WORKSPACE_ID -99

View File

@@ -110,18 +110,27 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
wlr_ext_workspace_group_handle_v1_output_enter(PNEWMONITOR->pWLRWorkspaceGroupHandle, PNEWMONITOR->output);
// Workspace
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 && !g_pCompositor->getWorkspaceByID(monitorRule.defaultWorkspaceID) ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
const auto PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
if (PNEWWORKSPACE) {
// workspace exists, move it to the newly connected monitor
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, PNEWMONITOR);
} else {
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
PNEWWORKSPACE->m_iID = WORKSPACEID;
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
PNEWWORKSPACE->m_iID = WORKSPACEID;
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
}
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
PNEWMONITOR->scale = monitorRule.scale;
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
@@ -132,7 +141,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
//
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
g_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName));
// ready to process cuz we have a monitor
g_pCompositor->m_bReadyToProcess = true;
@@ -332,6 +343,8 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
g_pCompositor->m_lMonitors.remove(*pMonitor);
// update the pMostHzMonitor

View File

@@ -25,10 +25,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
PWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace;
PWINDOW->m_bIsMapped = true;
PWINDOW->m_bReadyToDelete = false;
PWINDOW->m_bFadingOut = false;
@@ -114,7 +114,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
} else if (r.szRule.find("opacity") == 0) {
try {
PWINDOW->m_sSpecialRenderData.alpha = std::stof(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
if (alphaPart.find_first_of(' ') != std::string::npos) {
// we have a comma, 2 values
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
} else {
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart);
}
} catch(std::exception& e) {
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}

View File

@@ -149,8 +149,6 @@ public:
return false; // unreachable
}
private:
void warp() {
switch (m_eVarType) {
case AVARTYPE_FLOAT: {
@@ -170,6 +168,8 @@ private:
}
}
private:
Vector2D m_vValue = Vector2D(0,0);
float m_fValue = 0;
CColor m_cValue;

View File

@@ -125,7 +125,10 @@ bool isDirection(const std::string& arg) {
int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
int result = INT_MAX;
if (in.find("name:") == 0) {
if (in.find("special") == 0) {
outName = "special";
return SPECIAL_WORKSPACE_ID;
} else if (in.find("name:") == 0) {
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
if (!WORKSPACE) {
@@ -135,8 +138,59 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
}
outName = WORKSPACENAME;
} else {
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
outName = std::to_string(result);
if (in[0] == 'm') {
// monitor relative
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
// result now has +/- what we should move on mon
int remains = (int)result;
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
int searchID = currentID;
while (remains != 0) {
if (remains < 0)
searchID--;
else
searchID++;
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
// means we need to wrap around
int lowestID = 99999;
int highestID = -99999;
for (auto& w : g_pCompositor->m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
}
if (remains < 0)
searchID = highestID;
else
searchID = lowestID;
}
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE) {
if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
currentID = PWORKSPACE->m_iID;
if (remains < 0)
remains++;
else
remains--;
}
}
}
result = currentID;
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
} else {
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
outName = std::to_string(result);
}
}
return result;

View File

@@ -29,6 +29,9 @@ struct SMonitor {
wlr_output_damage* damage = nullptr;
bool needsFrameSkip = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
// for the special workspace
bool specialWorkspaceOpen = false;
// Double-linked list because we need to have constant mem addresses for signals
// We have to store pointers and use raw new/delete because they might be moved between them

View File

@@ -1,7 +1,7 @@
#include "Workspace.hpp"
#include "../Compositor.hpp"
CWorkspace::CWorkspace(int monitorID) {
CWorkspace::CWorkspace(int monitorID, bool special) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
if (!PMONITOR) {
@@ -10,16 +10,20 @@ CWorkspace::CWorkspace(int monitorID) {
}
m_iMonitorID = monitorID;
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
// set geometry here cuz we can
wl_array_init(&m_wlrCoordinateArr);
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
m_bIsSpecialWorkspace = special;
if (!special) {
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
// set geometry here cuz we can
wl_array_init(&m_wlrCoordinateArr);
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
}
m_vRenderOffset.m_pWorkspace = this;
m_vRenderOffset.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
@@ -53,6 +57,18 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
m_fAlpha.setValueAndWarp(255.f);
m_fAlpha = 0.f;
}
} else if ("slidevert") {
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
m_vRenderOffset = Vector2D(0, 0);
} else {
m_vRenderOffset = Vector2D(0, left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y);
}
} else {
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
@@ -82,7 +98,7 @@ void CWorkspace::setActive(bool on) {
void CWorkspace::moveToMonitor(const int& id) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(id);
if (!PMONITOR)
if (!PMONITOR || m_bIsSpecialWorkspace)
return;
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false);

View File

@@ -10,7 +10,7 @@ enum eFullscreenMode : uint8_t {
class CWorkspace {
public:
CWorkspace(int monitorID);
CWorkspace(int monitorID, bool special = false);
~CWorkspace();
// Workspaces ID-based have IDs > 0
@@ -29,6 +29,9 @@ public:
CAnimatedVariable m_vRenderOffset;
CAnimatedVariable m_fAlpha;
// "scratchpad"
bool m_bIsSpecialWorkspace = false;
// user-set
bool m_bDefaultFloating = false;
bool m_bDefaultPseudo = false;

View File

@@ -160,10 +160,20 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
}
}
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
if (PWORKSPACE->m_bIsSpecialWorkspace) {
// if special, we adjust the coords a bit
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * 0.8f) / 2.f;
PWINDOW->m_vRealSize = calcSize * 0.8f;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * 0.8f);
} else {
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
}
}
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
@@ -184,7 +194,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
SDwindleNodeData* OPENINGON;
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
if (PMONITOR->ID == MONFROMCURSOR->ID && PNODE->workspaceID == PMONITOR->activeWorkspace) {
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen))) {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
// happens on reserved area
@@ -196,6 +206,11 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID);
if (OPENINGON && OPENINGON->workspaceID != PNODE->workspaceID) {
// special workspace handling
OPENINGON = getFirstNodeOnWorkspace(PNODE->workspaceID);
}
// if it's the first, it's easy. Make it fullscreen.
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
@@ -356,8 +371,21 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (!PWORKSPACE)
return;
if (PMONITOR->specialWorkspaceOpen) {
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
if (TOPNODE && PMONITOR) {
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
TOPNODE->recalcSizePosRecursive();
}
}
// Ignore any recalc events if we have a fullscreen window.
if (!PWORKSPACE || PWORKSPACE->m_bHasFullscreenWindow)
if (PWORKSPACE->m_bHasFullscreenWindow)
return;
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);

View File

@@ -105,7 +105,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// then, we check if the workspace doesnt have a fullscreen window
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface) {
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
@@ -113,7 +113,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) {
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
if (((w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen) || (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
pFoundWindow = &(*w);
if (!pFoundWindow->m_bIsX11) {

View File

@@ -23,6 +23,7 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["exit"] = exitHyprland;
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
}
void CKeybindManager::addKeybind(SKeybind kb) {
@@ -153,6 +154,10 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace));
}
ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
@@ -191,12 +196,20 @@ void CKeybindManager::changeworkspace(std::string args) {
const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
if (workspaceToChangeTo == SPECIAL_WORKSPACE_ID)
PWORKSPACETOCHANGETO->m_iMonitorID = PMONITOR->ID;
// if it's not visible, make it visible.
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
// change it
PMONITOR->activeWorkspace = workspaceToChangeTo;
PMONITOR->specialWorkspaceOpen = false;
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
PMONITOR->specialWorkspaceOpen = true;
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
// and that'd be annoying as hell
@@ -219,7 +232,6 @@ void CKeybindManager::changeworkspace(std::string args) {
if (!m_bSuppressWorkspaceChangeEvents)
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
}
// If the monitor is not the one our cursor's at, warp to it.
if (PMONITOR != g_pCompositor->getMonitorFromCursor()) {
@@ -260,20 +272,26 @@ void CKeybindManager::changeworkspace(std::string args) {
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID);
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceToChangeTo == SPECIAL_WORKSPACE_ID);
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
// start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT);
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
PWORKSPACE->m_iID = workspaceToChangeTo;
PWORKSPACE->m_iMonitorID = PMONITOR->ID;
PWORKSPACE->m_szName = workspaceName;
PMONITOR->activeWorkspace = workspaceToChangeTo;
PMONITOR->specialWorkspaceOpen = false;
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
PMONITOR->specialWorkspaceOpen = true;
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
// and that'd be annoying as hell
@@ -368,6 +386,17 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
}
// undo the damage if we are moving to the special workspace
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) {
changeworkspace(std::to_string(OLDWORKSPACE->m_iID));
OLDWORKSPACE->startAnim(true, true, true);
toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
for (auto& m : g_pCompositor->m_lMonitors)
m.specialWorkspaceOpen = false;
}
}
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
@@ -746,5 +775,50 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
if (!PWORKSPACE) {
Debug::log(ERR, "moveWorkspaceToMonitor workspace doesn't exist!");
return;
}
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
}
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
if (g_pCompositor->getWindowsOnWorkspace(SPECIAL_WORKSPACE_ID) == 0) {
Debug::log(LOG, "Can't open empty special workspace!");
return;
}
bool open = false;
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen) {
open = true;
break;
}
}
if (open)
Debug::log(LOG, "Toggling special workspace to closed");
else
Debug::log(LOG, "Toggling special workspace to open");
if (open) {
for (auto& m : g_pCompositor->m_lMonitors) {
if (m.specialWorkspaceOpen != !open) {
m.specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
}
}
} else {
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(true, true);
}
g_pInputManager->refocus();
}

View File

@@ -53,6 +53,7 @@ private:
static void exitHyprland(std::string);
static void moveCurrentWorkspaceToMonitor(std::string);
static void moveWorkspaceToMonitor(std::string);
static void toggleSpecialWorkspace(std::string);
friend class CCompositor;
};

View File

@@ -46,6 +46,9 @@ bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
return true;
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true;
return false;
}
@@ -70,6 +73,21 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
renderWindow(&w, pMonitor, time, true);
}
// and then special windows
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, pMonitor))
continue;
// render the bad boy
renderWindow(&w, pMonitor, time, true);
}
// and the overlay layers
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
// on non-full we draw the bar and shit
@@ -112,7 +130,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
// apply window special data
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
else
renderdata.alpha *= pWindow == g_pCompositor->m_pLastWindow ? pWindow->m_sSpecialRenderData.alpha : pWindow->m_sSpecialRenderData.alphaInactive;
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
@@ -176,7 +197,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
continue;
if (w.m_bIsFloating)
continue; // floating are in second pass
continue; // floating are in the second pass
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; // special are in the third pass
if (!shouldRenderWindow(&w, PMONITOR))
continue;
@@ -193,6 +217,24 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
if (!w.m_bIsFloating)
continue;
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR))
continue;
// render the bad boy
renderWindow(&w, PMONITOR, time, true);
}
// and then special
for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue;
if (!shouldRenderWindow(&w, PMONITOR))
continue;