diff --git a/example/hypr.conf b/example/hypr.conf index 6171f54..bd065b0 100644 --- a/example/hypr.conf +++ b/example/hypr.conf @@ -52,6 +52,7 @@ Animations { speed=5 cheap=1 # highly recommended borders=0 + workspaces=0 # not really recommended } # example window rules diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1b1033c..7e2e32e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -43,6 +43,7 @@ void ConfigManager::init() { configValues["anim:enabled"].intValue = 0; configValues["anim:cheap"].intValue = 1; configValues["anim:borders"].intValue = 1; + configValues["anim:workspaces"].intValue = 1; if (!g_pWindowManager->statusBar) { isFirstLaunch = true; diff --git a/src/utilities/AnimationUtil.cpp b/src/utilities/AnimationUtil.cpp index 1ababbc..96dd2c2 100644 --- a/src/utilities/AnimationUtil.cpp +++ b/src/utilities/AnimationUtil.cpp @@ -88,6 +88,40 @@ void AnimationUtil::move() { } } + for (auto& work : g_pWindowManager->workspaces) { + work.setAnimationInProgress(false); + if (VECTORDELTANONZERO(work.getCurrentOffset(), work.getGoalOffset())) { + work.setAnimationInProgress(true); + work.setCurrentOffset(Vector2D(parabolic(work.getCurrentOffset().x, work.getGoalOffset().x, ANIMATIONSPEED), parabolic(work.getCurrentOffset().y, work.getGoalOffset().y, ANIMATIONSPEED))); + + updateRequired = true; + g_pWindowManager->setAllWorkspaceWindowsDirtyByID(work.getID()); + + if (ConfigManager::getInt("anim:workspaces") == 0) + work.setAnimationInProgress(false); + } + + if (!work.getAnimationInProgress()) { + if (!g_pWindowManager->isWorkspaceVisible(work.getID())) { + if (work.getCurrentOffset().x != 1500000) { + g_pWindowManager->setAllWorkspaceWindowsDirtyByID(work.getID()); + updateRequired = true; + } + + work.setCurrentOffset(Vector2D(1500000, 1500000)); + work.setGoalOffset(Vector2D(1500000, 1500000)); + } else { + if (work.getCurrentOffset().x != 0) { + g_pWindowManager->setAllWorkspaceWindowsDirtyByID(work.getID()); + updateRequired = true; + } + + work.setCurrentOffset(Vector2D(0, 0)); + work.setGoalOffset(Vector2D(0, 0)); + } + } + } + if (updateRequired) emptyEvent(); // send a fake request to update dirty windows } \ No newline at end of file diff --git a/src/utilities/Workspace.cpp b/src/utilities/Workspace.cpp index c75ef42..d0cc971 100644 --- a/src/utilities/Workspace.cpp +++ b/src/utilities/Workspace.cpp @@ -1,4 +1,4 @@ #include "Workspace.hpp" -CWorkspace::CWorkspace() { this->m_bHasFullscreenWindow = false; } +CWorkspace::CWorkspace() { this->m_bHasFullscreenWindow = false; this->m_bAnimationInProgress = false; } CWorkspace::~CWorkspace() { } \ No newline at end of file diff --git a/src/utilities/Workspace.hpp b/src/utilities/Workspace.hpp index fd7d74e..2a61459 100644 --- a/src/utilities/Workspace.hpp +++ b/src/utilities/Workspace.hpp @@ -13,4 +13,9 @@ public: EXPOSED_MEMBER(Monitor, int, i); EXPOSED_MEMBER(HasFullscreenWindow, bool, b); + + // Wipe animations + EXPOSED_MEMBER(AnimationInProgress, bool, b); + EXPOSED_MEMBER(CurrentOffset, Vector2D, vec); + EXPOSED_MEMBER(GoalOffset, Vector2D, vec); }; diff --git a/src/windowManager.cpp b/src/windowManager.cpp index 8f4903e..8983d7d 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -133,21 +133,13 @@ void CWindowManager::setupRandrMonitors() { } xcb_flush(DisplayConnection); -} - -void CWindowManager::setupManager() { - setupColormapAndStuff(); - EWMH::setupInitEWMH(); - - // ---- RANDR ----- // - setupRandrMonitors(); if (monitors.size() == 0) { // RandR failed! Debug::log(WARN, "RandR failed!"); monitors.clear(); -#define TESTING_MON_AMOUNT 3 +#define TESTING_MON_AMOUNT 2 for (int i = 0; i < TESTING_MON_AMOUNT /* Testing on 3 monitors, RandR shouldnt fail on a real desktop */; ++i) { monitors.push_back(SMonitor()); monitors[i].vecPosition = Vector2D(i * Screen->width_in_pixels / TESTING_MON_AMOUNT, 0); @@ -156,6 +148,14 @@ void CWindowManager::setupManager() { monitors[i].szName = "Screen" + std::to_string(i); } } +} + +void CWindowManager::setupManager() { + setupColormapAndStuff(); + EWMH::setupInitEWMH(); + + // ---- RANDR ----- // + setupRandrMonitors(); Debug::log(LOG, "RandR done."); @@ -360,13 +360,20 @@ void CWindowManager::refreshDirtyWindows() { // Fullscreen flag bool bHasFullscreenWindow = getWorkspaceByID(window.getWorkspaceID())->getHasFullscreenWindow(); + const auto PWORKSPACE = getWorkspaceByID(window.getWorkspaceID()); + + if (!PWORKSPACE) + continue; + // 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 thats under + // or an animated workspace if (!isWorkspaceVisible(window.getWorkspaceID()) - || (bHasFullscreenWindow && !window.getFullscreen() && (window.getUnderFullscreen() || !window.getIsFloating()))) { - // Move it to hades - Values[0] = (int)1500000; // hmu when monitors actually have that many pixels - Values[1] = (int)1500000; // and we are still using xorg =) + || (bHasFullscreenWindow && !window.getFullscreen() && (window.getUnderFullscreen() || !window.getIsFloating())) + || PWORKSPACE->getAnimationInProgress()) { + + Values[0] = (int)window.getRealPosition().x + (int)PWORKSPACE->getCurrentOffset().x; + Values[1] = (int)window.getRealPosition().y + (int)PWORKSPACE->getCurrentOffset().y; if (VECTORDELTANONZERO(window.getLastUpdatePosition(), Vector2D(Values[0], Values[1]))) { xcb_configure_window(DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, Values); window.setLastUpdatePosition(Vector2D(Values[0], Values[1])); @@ -380,6 +387,8 @@ void CWindowManager::refreshDirtyWindows() { window.setLastUpdateSize(Vector2D(Values[0], Values[1])); } + applyShapeToWindow(&window); + continue; } @@ -699,6 +708,25 @@ void CWindowManager::applyShapeToWindow(CWindow* pWindow) { xcb_poly_fill_rectangle(DisplayConnection, PIXMAP2, WHITE, 2, CLIPPINGRECTS); xcb_poly_fill_arc(DisplayConnection, PIXMAP2, WHITE, 4, CLIPPINGARCS); + const auto WORKSPACE = getWorkspaceByID(pWindow->getWorkspaceID()); + if (WORKSPACE->getAnimationInProgress()) { + // if it's animated we draw 2 more black rects to clip it. (if it goes out of the monitor) + + if (W + (pWindow->getRealPosition().x + WORKSPACE->getCurrentOffset().x - MONITOR->vecPosition.x) > MONITOR->vecSize.x) { + // clip right + xcb_rectangle_t rect[] = {{MONITOR->vecSize.x - (pWindow->getRealPosition().x + WORKSPACE->getCurrentOffset().x - MONITOR->vecPosition.x), -100, W + 100, H + 100}}; + xcb_poly_fill_rectangle(DisplayConnection, PIXMAP1, BLACK, 1, rect); + xcb_poly_fill_rectangle(DisplayConnection, PIXMAP2, BLACK, 1, rect); + } + + if (pWindow->getRealPosition().x + WORKSPACE->getCurrentOffset().x - MONITOR->vecPosition.x < 0) { + // clip left + xcb_rectangle_t rect[] = {{-100, -100, - (pWindow->getRealPosition().x + WORKSPACE->getCurrentOffset().x - MONITOR->vecPosition.x), H + 100}}; + xcb_poly_fill_rectangle(DisplayConnection, PIXMAP1, BLACK, 1, rect); + xcb_poly_fill_rectangle(DisplayConnection, PIXMAP2, BLACK, 1, rect); + } + } + // Draw done // Shape @@ -1383,12 +1411,16 @@ void CWindowManager::changeWorkspaceByID(int ID) { // mark old workspace dirty setAllWorkspaceWindowsDirtyByID(activeWorkspaces[MONITOR->ID]); + // save old workspace for anim + auto OLDWORKSPACE = activeWorkspaces[MONITOR->ID]; + for (auto& workspace : workspaces) { if (workspace.getID() == ID) { // set workspaces dirty setAllWorkspaceWindowsDirtyByID(activeWorkspaces[workspace.getMonitor()]); setAllWorkspaceWindowsDirtyByID(ID); + OLDWORKSPACE = activeWorkspaces[workspace.getMonitor()]; activeWorkspaces[workspace.getMonitor()] = workspace.getID(); // if not fullscreen set the focus to any window on that workspace @@ -1411,6 +1443,9 @@ void CWindowManager::changeWorkspaceByID(int ID) { // Update bar info updateBarInfo(); + + // Wipe animation + startWipeAnimOnWorkspace(OLDWORKSPACE, ID); return; } @@ -1427,6 +1462,9 @@ void CWindowManager::changeWorkspaceByID(int ID) { // Update bar info updateBarInfo(); + // Wipe animation + startWipeAnimOnWorkspace(OLDWORKSPACE, ID); + // no need for the new dirty, it's empty } @@ -1934,4 +1972,20 @@ void CWindowManager::recalcAllDocks() { Values[1] = w.getDefaultSize().y; xcb_configure_window(DisplayConnection, w.getDrawable(), XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, Values); } +} + +void CWindowManager::startWipeAnimOnWorkspace(const int& oldwork, const int& newwork) { + const auto PMONITOR = getMonitorFromWorkspace(newwork); + + for (auto& work : workspaces) { + if (work.getID() == oldwork) { + work.setCurrentOffset(Vector2D(0,0)); + work.setGoalOffset(Vector2D(PMONITOR->vecSize.x, 0)); + work.setAnimationInProgress(true); + } else if (work.getID() == newwork) { + work.setCurrentOffset(Vector2D(-PMONITOR->vecSize.x, 0)); + work.setGoalOffset(Vector2D(0, 0)); + work.setAnimationInProgress(true); + } + } } \ No newline at end of file diff --git a/src/windowManager.hpp b/src/windowManager.hpp index cfc8b43..74a5741 100644 --- a/src/windowManager.hpp +++ b/src/windowManager.hpp @@ -152,6 +152,7 @@ private: SMonitor* getMonitorFromWorkspace(const int&); void recalcEntireWorkspace(const int&); void fixMasterWorkspaceOnClosed(CWindow* pWindow); + void startWipeAnimOnWorkspace(const int&, const int&); }; inline std::unique_ptr g_pWindowManager = std::make_unique();