diff --git a/README.md b/README.md index 6f081861f..fbb0b4f85 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-banner +banner
diff --git a/assets/header.svg b/assets/header.svg index 922313bea..c8cf82221 100644 --- a/assets/header.svg +++ b/assets/header.svg @@ -1,10 +1,10 @@ - +
- +

Hyprland

-

ハイパーランド

diff --git a/assets/hyprland.png b/assets/hyprland.png index 27d24edc1..ea307455b 100644 Binary files a/assets/hyprland.png and b/assets/hyprland.png differ diff --git a/assets/wall_2K.png b/assets/wall_2K.png index 9f7cabc08..5aea012a9 100644 Binary files a/assets/wall_2K.png and b/assets/wall_2K.png differ diff --git a/assets/wall_4K.png b/assets/wall_4K.png index 925b44762..f835a9786 100644 Binary files a/assets/wall_4K.png and b/assets/wall_4K.png differ diff --git a/assets/wall_8K.png b/assets/wall_8K.png index 132276c5e..539aa97da 100644 Binary files a/assets/wall_8K.png and b/assets/wall_8K.png differ diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 8d9b6d968..4ff1aade5 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -202,6 +204,10 @@ std::deque splitArgs(int argc, char** argv) { return result; } +bool isNumber(const std::string& str, bool allowfloat) { + return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); }); +} + int main(int argc, char** argv) { int bflag = 0, sflag = 0, index, c; @@ -215,7 +221,7 @@ int main(int argc, char** argv) { const auto ARGS = splitArgs(argc, argv); for (auto i = 0; i < ARGS.size(); ++i) { - if (ARGS[i][0] == '-') { + if (ARGS[i][0] == '-' && !isNumber(ARGS[i], true) /* For stuff like -2 */) { // parse if (ARGS[i] == "-j" && !fullArgs.contains("j")) { fullArgs += "j"; diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 14726df80..99a46dfa3 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -174,11 +174,16 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLRCursor->events.swipe_begin, &Events::listen_swipeBegin, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.swipe_update, &Events::listen_swipeUpdate, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.swipe_end, &Events::listen_swipeEnd, m_sWLRCursor, "WLRCursor"); + addWLSignal(&m_sWLRCursor->events.pinch_begin, &Events::listen_pinchBegin, m_sWLRCursor, "WLRCursor"); + addWLSignal(&m_sWLRCursor->events.pinch_update, &Events::listen_pinchUpdate, m_sWLRCursor, "WLRCursor"); + addWLSignal(&m_sWLRCursor->events.pinch_end, &Events::listen_pinchEnd, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend"); addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat"); addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); addWLSignal(&m_sSeat.seat->events.request_start_drag, &Events::listen_requestDrag, &m_sSeat, "Seat"); addWLSignal(&m_sSeat.seat->events.start_drag, &Events::listen_startDrag, &m_sSeat, "Seat"); + addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat"); + addWLSignal(&m_sSeat.seat->events.request_set_primary_selection, &Events::listen_requestSetPrimarySel, &m_sSeat, "Seat"); addWLSignal(&m_sWLRLayerShell->events.new_surface, &Events::listen_newLayerSurface, m_sWLRLayerShell, "LayerShell"); addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout"); addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr"); @@ -227,6 +232,9 @@ void CCompositor::startCompositor() { Debug::log(LOG, "Creating the AnimationManager!"); g_pAnimationManager = std::make_unique(); + Debug::log(LOG, "Creating the LayoutManager!"); + g_pLayoutManager = std::make_unique(); + Debug::log(LOG, "Creating the ConfigManager!"); g_pConfigManager = std::make_unique(); @@ -245,9 +253,6 @@ void CCompositor::startCompositor() { Debug::log(LOG, "Creating the XWaylandManager!"); g_pXWaylandManager = std::make_unique(); - Debug::log(LOG, "Creating the LayoutManager!"); - g_pLayoutManager = std::make_unique(); - Debug::log(LOG, "Creating the EventManager!"); g_pEventManager = std::make_unique(); g_pEventManager->startThread(); @@ -641,7 +646,7 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { updateWindowAnimatedDecorationValues(pWindow); // Send an event - g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle)); + g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle}); if (pWindow->m_phForeignToplevel) wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true); @@ -658,7 +663,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { if (!pSurface) { wlr_seat_keyboard_clear_focus(m_sSeat.seat); - g_pEventManager->postEvent(SHyprIPCEvent("activewindow", ",")); // unfocused + g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // unfocused return; } @@ -814,6 +819,9 @@ CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) { } void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) { + // not needed anymore + return; + const auto ISVISIBLE = isWorkspaceVisible(id); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); @@ -1201,10 +1209,14 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { } // shadow - if (pWindow == m_pLastWindow) { - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); + if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) { + if (pWindow == m_pLastWindow) { + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); + } else { + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); + } } else { - pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); + pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow } } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 005508786..deca2fcd6 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -24,6 +24,7 @@ CConfigManager::CConfigManager() { configPaths.emplace_back(CONFIGPATH); Debug::disableLogs = &configValues["debug:disable_logs"].intValue; + Debug::disableTime = &configValues["debug:disable_time"].intValue; } void CConfigManager::setDefaultVars() { @@ -43,6 +44,8 @@ void CConfigManager::setDefaultVars() { configValues["general:col.active_border"].intValue = 0xffffffff; configValues["general:col.inactive_border"].intValue = 0xff444444; configValues["general:cursor_inactive_timeout"].intValue = 0; + + configValues["general:layout"].strValue = "dwindle"; configValues["misc:disable_hyprland_logo"].intValue = 0; configValues["misc:disable_splash_rendering"].intValue = 0; @@ -53,6 +56,7 @@ void CConfigManager::setDefaultVars() { configValues["debug:overlay"].intValue = 0; configValues["debug:damage_blink"].intValue = 0; configValues["debug:disable_logs"].intValue = 0; + configValues["debug:disable_time"].intValue = 1; configValues["decoration:rounding"].intValue = 1; configValues["decoration:blur"].intValue = 1; @@ -80,6 +84,10 @@ void CConfigManager::setDefaultVars() { configValues["dwindle:special_scale_factor"].floatValue = 0.8f; configValues["dwindle:split_width_multiplier"].floatValue = 1.0f; + configValues["master:special_scale_factor"].floatValue = 0.8f; + configValues["master:new_is_master"].intValue = 1; + configValues["master:new_on_top"].intValue = 0; + configValues["animations:enabled"].intValue = 1; configValues["animations:speed"].floatValue = 7.f; configValues["animations:curve"].strValue = "default"; @@ -100,6 +108,7 @@ void CConfigManager::setDefaultVars() { configValues["animations:workspaces_speed"].floatValue = 0.f; configValues["animations:workspaces"].intValue = 1; + configValues["input:sensitivity"].floatValue = 0.f; configValues["input:kb_layout"].strValue = "us"; configValues["input:kb_variant"].strValue = STRVAL_EMPTY; configValues["input:kb_options"].strValue = STRVAL_EMPTY; @@ -118,6 +127,7 @@ void CConfigManager::setDefaultVars() { configValues["input:touchpad:drag_lock"].intValue = 0; configValues["gestures:workspace_swipe"].intValue = 0; + configValues["gestures:workspace_swipe_fingers"].intValue = 3; configValues["gestures:workspace_swipe_distance"].intValue = 300; configValues["gestures:workspace_swipe_invert"].intValue = 1; configValues["gestures:workspace_swipe_min_speed_to_force"].intValue = 30; @@ -131,6 +141,7 @@ void CConfigManager::setDefaultVars() { void CConfigManager::setDeviceDefaultVars(const std::string& dev) { auto& cfgValues = deviceConfigs[dev]; + cfgValues["sensitivity"].floatValue = 0.f; cfgValues["kb_layout"].strValue = "us"; cfgValues["kb_variant"].strValue = STRVAL_EMPTY; cfgValues["kb_options"].strValue = STRVAL_EMPTY; @@ -495,9 +506,25 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri configSetValueSafe("animations:" + ANIMNAME + "_style", curitem); } -void CConfigManager::handleBind(const std::string& command, const std::string& value, bool locked) { +void CConfigManager::handleBind(const std::string& command, const std::string& value) { // example: - // bind=SUPER,G,exec,dmenu_run + // bind[fl]=SUPER,G,exec,dmenu_run + + // flags + bool locked = false; + bool release = false; + const auto ARGS = command.substr(4); + + for (auto& arg : ARGS) { + if (arg == 'l') { + locked = true; + } else if (arg == 'r') { + release = true; + } else { + parseError = "bind: invalid flag"; + return; + } + } auto valueCopy = value; @@ -529,9 +556,9 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v if (KEY != "") { if (isNumber(KEY) && std::stoi(KEY) > 9) - g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap}); + g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release}); else - g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap}); + g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release}); } } @@ -566,6 +593,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str && RULE.find("monitor") != 0 && RULE != "nofocus" && RULE != "noblur" + && RULE != "center" && RULE != "fullscreen" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 @@ -698,8 +726,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: } } else if (COMMAND == "monitor") handleMonitor(COMMAND, VALUE); - else if (COMMAND == "bind") handleBind(COMMAND, VALUE); - else if (COMMAND == "bindl") handleBind(COMMAND, VALUE, true); + else if (COMMAND.find("bind") == 0) handleBind(COMMAND, VALUE); else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE); else if (COMMAND == "workspace") handleDefaultWorkspace(COMMAND, VALUE); else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE); @@ -892,8 +919,10 @@ void CConfigManager::loadConfigLoadVars() { g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); // Update the keyboard layout to the cfg'd one if this is not the first launch - if (!isFirstLaunch) + if (!isFirstLaunch) { g_pInputManager->setKeyboardLayout(); + g_pInputManager->setMouseConfigs(); + } // Calculate the internal vars configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue); @@ -923,6 +952,9 @@ void CConfigManager::loadConfigLoadVars() { // Update window border colors g_pCompositor->updateAllWindowsAnimatedDecorationValues(); + // update layout + g_pLayoutManager->switchToLayout(configValues["general:layout"].strValue); + // Force the compositor to fully re-render all monitors for (auto& m : g_pCompositor->m_vMonitors) m->forceFullFrames = 2; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 1d281c401..7f51f7e7f 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -121,7 +121,7 @@ private: void handleDeviceConfig(const std::string&, const std::string&); void handleRawExec(const std::string&, const std::string&); void handleMonitor(const std::string&, const std::string&); - void handleBind(const std::string&, const std::string&, bool locked = false); + void handleBind(const std::string&, const std::string&); void handleUnbind(const std::string&, const std::string&); void handleWindowRule(const std::string&, const std::string&); void handleDefaultWorkspace(const std::string&, const std::string&); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 1e6a8e323..9832a22d8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -38,11 +38,11 @@ R"#({ "active": "%s" },)#", m->ID, - m->szName.c_str(), + escapeJSONStrings(m->szName).c_str(), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, - m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), + m->activeWorkspace, escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, @@ -86,14 +86,14 @@ R"#({ "title": "%s", "pid": %i },)#", - &w, + w.get(), (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) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), + w->m_iWorkspaceID, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))).c_str(), (int)w->m_bIsFloating, w->m_iMonitorID, - g_pXWaylandManager->getAppIDClass(w.get()).c_str(), - g_pXWaylandManager->getTitle(w.get()).c_str(), + escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(), + escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(), w->getPID() ); } @@ -107,7 +107,7 @@ R"#({ for (auto& w : g_pCompositor->m_vWindows) { if (w->m_bIsMapped) { result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %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) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID()); + w.get(), 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) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID()); } } @@ -130,8 +130,8 @@ R"#({ "hasfullscreen": %i },)#", w->m_iID, - w->m_szName.c_str(), - g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), + escapeJSONStrings(w->m_szName).c_str(), + escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow ); @@ -175,11 +175,11 @@ R"#({ PWINDOW, (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()), + PWINDOW->m_iWorkspaceID, escapeJSONStrings(PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName).c_str(), (int)PWINDOW->m_bIsFloating, PWINDOW->m_iMonitorID, - g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), - g_pXWaylandManager->getTitle(PWINDOW).c_str(), + escapeJSONStrings(g_pXWaylandManager->getAppIDClass(PWINDOW)).c_str(), + escapeJSONStrings(g_pXWaylandManager->getTitle(PWINDOW)).c_str(), PWINDOW->getPID() ); } else { @@ -199,7 +199,7 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) { R"#("%s": { "levels": { )#", - mon->szName.c_str() + escapeJSONStrings(mon->szName).c_str() ); int layerLevel = 0; @@ -225,7 +225,7 @@ R"#( { layer->geometry.y, layer->geometry.width, layer->geometry.height, - layer->szNamespace.c_str() + escapeJSONStrings(layer->szNamespace).c_str() ); } @@ -285,7 +285,7 @@ R"#( { "name": "%s" },)#", &m, - m.mouse->name + escapeJSONStrings(m.mouse->name).c_str() ); } @@ -308,13 +308,13 @@ R"#( { "active_keymap": "%s" },)#", &k, - k.keyboard->name, - k.currentRules.rules.c_str(), - k.currentRules.model.c_str(), - k.currentRules.layout.c_str(), - k.currentRules.variant.c_str(), - k.currentRules.options.c_str(), - KM + escapeJSONStrings(k.keyboard->name).c_str(), + escapeJSONStrings(k.currentRules.rules).c_str(), + escapeJSONStrings(k.currentRules.model).c_str(), + escapeJSONStrings(k.currentRules.layout).c_str(), + escapeJSONStrings(k.currentRules.variant).c_str(), + escapeJSONStrings(k.currentRules.options).c_str(), + escapeJSONStrings(KM).c_str() ); } @@ -336,7 +336,7 @@ R"#( { },)#", &d, d.pTabletParent, - d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "" + escapeJSONStrings(d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "").c_str() ); } @@ -347,7 +347,7 @@ R"#( { "name": "%s" },)#", &d, - d.wlrDevice ? d.wlrDevice->name : "" + escapeJSONStrings(d.wlrDevice ? d.wlrDevice->name : "").c_str() ); } @@ -456,6 +456,9 @@ std::string dispatchKeyword(std::string in) { if (COMMAND.contains("input")) g_pInputManager->setKeyboardLayout(); // update kb layout + if (COMMAND.contains("general:layout")) + g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout + Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str()); if (retval == "") diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 2fa4a127b..59d2d2391 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -41,6 +41,23 @@ void Debug::log(LogLevel level, const char* fmt, ...) { break; } + // print date and time to the ofs + if (disableTime && !*disableTime) { + auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + const auto MILLIS = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() % 1000; + + ofs << std::put_time(std::localtime(&timet), "[%H:%M:%S:"); + + if (MILLIS > 99) + ofs << MILLIS; + else if (MILLIS > 9) + ofs << "0" << MILLIS; + else + ofs << "00" << MILLIS; + + ofs << "] "; + } + char buf[LOGMESSAGESIZE] = ""; char* outputStr; int logLen; diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index bde9b8209..4001d9961 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -18,4 +18,5 @@ namespace Debug { inline std::string logFile; inline int64_t* disableLogs = nullptr; + inline int64_t* disableTime = nullptr; }; \ No newline at end of file diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index 4b8762ba8..948e7aba1 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -175,3 +175,18 @@ void Events::listener_swipeEnd(wl_listener* listener, void* data) { g_pInputManager->onSwipeEnd(EVENT); } + +void Events::listener_pinchBegin(wl_listener* listener, void* data) { + const auto EV = (wlr_pointer_pinch_begin_event*)data; + wlr_pointer_gestures_v1_send_pinch_begin(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->fingers); +} + +void Events::listener_pinchUpdate(wl_listener* listener, void* data) { + const auto EV = (wlr_pointer_pinch_update_event*)data; + wlr_pointer_gestures_v1_send_pinch_update(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->dx, EV->dy, EV->scale, EV->rotation); +} + +void Events::listener_pinchEnd(wl_listener* listener, void* data) { + const auto EV = (wlr_pointer_pinch_end_event*)data; + wlr_pointer_gestures_v1_send_pinch_end(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->cancelled); +} \ No newline at end of file diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 320feaa4c..ba8088a83 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -120,10 +120,14 @@ namespace Events { LISTENER(newIdleInhibitor); + // session + LISTENER(sessionActive); + + // Touchpad shit LISTENER(swipeBegin); LISTENER(swipeEnd); LISTENER(swipeUpdate); - - // session - LISTENER(sessionActive); + LISTENER(pinchBegin); + LISTENER(pinchUpdate); + LISTENER(pinchEnd); }; \ No newline at end of file diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index 0e2f49d56..431ebef15 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -72,6 +72,8 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) { layersurface->fadingOut = true; } + layersurface->noProcess = true; + layersurface->hyprListener_commitLayerSurface.removeCallback(); layersurface->hyprListener_destroyLayerSurface.removeCallback(); layersurface->hyprListener_mapLayerSurface.removeCallback(); diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 24a8faa71..9604dc69d 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -120,7 +120,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1; newDefaultWorkspaceName = std::to_string(WORKSPACEID); - Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace); + Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str()); } auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); @@ -157,7 +157,7 @@ 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_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName)); + g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", PNEWMONITOR->szName}); // ready to process cuz we have a monitor g_pCompositor->m_bReadyToProcess = true; @@ -393,7 +393,7 @@ 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_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", pMonitor->szName}); g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::unique_ptr& el) { return el.get() == pMonitor; })); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index afedcf34c..3cd111ba4 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -49,6 +49,8 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWINDOW->m_iX11Type == 2) g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW); + g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); + // Set all windows tiled regardless of anything g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM); @@ -224,6 +226,8 @@ void Events::listener_mapWindow(void* owner, void* data) { } catch (...) { Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); } + } else if (r.szRule == "center") { + PWINDOW->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f - PWINDOW->m_vRealSize.goalv() / 2.f; } } @@ -434,7 +438,7 @@ void Events::listener_setTitleWindow(void* owner, void* data) { PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW); if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others - g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle)); + g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle}); if (PWINDOW->m_phForeignToplevel) wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str()); @@ -501,6 +505,8 @@ void Events::listener_configureX11(void* owner, void* data) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); + PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace; + g_pCompositor->moveWindowToTop(PWINDOW); PWINDOW->m_bCreatedOverFullscreen = true; @@ -519,14 +525,17 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { const auto POS = PWINDOW->m_vRealPosition.goalv(); const auto SIZ = PWINDOW->m_vRealSize.goalv(); - if (abs(floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) { + if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) { + Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y, (int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height); + g_pHyprRenderer->damageWindow(PWINDOW); PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y)); - if (abs(floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) + if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height)); - - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.vec()); + + PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace; + g_pCompositor->moveWindowToTop(PWINDOW); PWINDOW->updateWindowDecos(); g_pHyprRenderer->damageWindow(PWINDOW); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index cf4158474..3fc6d20e8 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -3,6 +3,7 @@ #include #include "../Compositor.hpp" #include +#include static const float transforms[][9] = {{ 1.0f, 0.0f, 0.0f, @@ -113,6 +114,29 @@ std::string getFormat(const char *fmt, ...) { return output; } +std::string escapeJSONStrings(const std::string& str) { + std::ostringstream oss; + for (auto &c : str) { + switch (c) { + case '"': oss << "\\\""; break; + case '\\': oss << "\\\\"; break; + case '\b': oss << "\\b"; break; + case '\f': oss << "\\f"; break; + case '\n': oss << "\\n"; break; + case '\r': oss << "\\r"; break; + case '\t': oss << "\\t"; break; + default: + if ('\x00' <= c && c <= '\x1f') { + oss << "\\u" + << std::hex << std::setw(4) << std::setfill('0') << static_cast(c); + } else { + oss << c; + } + } + } + return oss.str(); +} + void scaleBox(wlr_box* box, float scale) { box->width = std::round(box->width * scale); box->height = std::round(box->height * scale); diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 108ac7f70..a40471a97 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -5,6 +5,7 @@ void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString); void wlr_signal_emit_safe(struct wl_signal *signal, void *data); std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string +std::string escapeJSONStrings(const std::string& str); void scaleBox(wlr_box*, float); std::string removeBeginEndSpacesTabs(std::string); bool isNumber(const std::string&, bool allowfloat = false); diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index c511b9001..376153f5a 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -171,12 +171,14 @@ void Events::listener_unmapSubsurface(void* owner, void* data) { addSurfaceGlobalOffset(PNODE, &lx, &ly); wlr_box extents = {0}; - wlr_surface_get_extends(PNODE->pSurface, &extents); + if (PNODE->pSurface) { + wlr_surface_get_extends(PNODE->pSurface, &extents); - extents.x += lx; - extents.y += ly; + extents.x += lx; + extents.y += ly; - g_pHyprRenderer->damageBox(&extents); + g_pHyprRenderer->damageBox(&extents); + } SubsurfaceTree::destroySurfaceTree(subsurface->pChild); subsurface->pChild = nullptr; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 58b6ce720..768dcb45f 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -30,6 +30,7 @@ struct SLayerSurface { CAnimatedVariable alpha; bool fadingOut = false; bool readyToDelete = false; + bool noProcess = false; bool forceBlur = false; diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp index adaab2884..117e16eb9 100644 --- a/src/helpers/WLListener.cpp +++ b/src/helpers/WLListener.cpp @@ -23,7 +23,7 @@ CHyprWLListener::~CHyprWLListener() { void CHyprWLListener::removeCallback() { if (m_bIsConnected) { - Debug::log(LOG, "Callback %x -> %x, %s removed.", m_pCallback, m_pOwner, m_szAuthor.c_str()); + Debug::log(LOG, "Callback %x -> %x, %s removed.", &m_pCallback, &m_pOwner, m_szAuthor.c_str()); wl_list_remove(&m_sListener.link); } diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c356c8cc0..c1bd09964 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -217,7 +217,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) { OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace); } else - OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace); + OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID); Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID); @@ -548,7 +548,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree pWindow->m_bIsFullscreen = on; PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; - g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)on))); + g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)}); if (!pWindow->m_bIsFullscreen) { // if it got its fullscreen disabled, set back its node if it had one @@ -864,3 +864,16 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) { std::string CHyprDwindleLayout::getLayoutName() { return "dwindle"; } + +void CHyprDwindleLayout::onEnable() { + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden) + continue; + + onWindowCreatedTiling(w.get()); + } +} + +void CHyprDwindleLayout::onDisable() { + m_lDwindleNodesData.clear(); +} \ No newline at end of file diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index bd73a3155..b60b87e05 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -55,6 +55,9 @@ public: virtual void alterSplitRatioBy(CWindow*, float); virtual std::string getLayoutName(); + virtual void onEnable(); + virtual void onDisable(); + private: std::list m_lDwindleNodesData; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 9f258b446..f5d87068e 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -32,11 +32,16 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { return; } - if (desiredGeometry.width <= 0 || desiredGeometry.height <= 0) { + if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow); pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height); - pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.vec().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.vec().y) / 2.f); + + // reject any windows with size <= 5x5 + if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5) { + pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; + } + pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f); } else { // we respect the size. pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index d214bf73d..29f474057 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -16,6 +16,8 @@ enum eFullscreenMode : uint8_t; interface IHyprLayout { public: + virtual void onEnable() = 0; + virtual void onDisable() = 0; /* Called when a window is created (mapped) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp new file mode 100644 index 000000000..6521ae803 --- /dev/null +++ b/src/layout/MasterLayout.cpp @@ -0,0 +1,423 @@ +#include "MasterLayout.hpp" +#include "../Compositor.hpp" + +SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) { + for (auto& nd : m_lMasterNodesData) { + if (nd.pWindow == pWindow) + return &nd; + } + + return nullptr; +} + +int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) { + int no = 0; + for (auto& n : m_lMasterNodesData) { + if (n.workspaceID == ws) + no++; + } + + return no; +} + +std::string CHyprMasterLayout::getLayoutName() { + return "Master"; +} + +SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) { + for (auto& n : m_lMasterNodesData) { + if (n.isMaster && n.workspaceID == ws) + return &n; + } + + return nullptr; +} + +void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) { + if (pWindow->m_bIsFloating) + return; + + static auto *const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue; + + const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back(); + + PNODE->workspaceID = pWindow->m_iWorkspaceID; + PNODE->pWindow = pWindow; + + static auto *const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue; + + const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID); + float lastSplitPercent = 0.5f; + + if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) { + for (auto& nd : m_lMasterNodesData) { + if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { + nd.isMaster = false; + lastSplitPercent = nd.percMaster; + break; + } + } + + PNODE->isMaster = true; + PNODE->percMaster = lastSplitPercent; + } else { + PNODE->isMaster = false; + } + + // recalc + recalculateMonitor(pWindow->m_iMonitorID); +} + +void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) { + const auto PNODE = getNodeFromWindow(pWindow); + + if (!PNODE) + return; + + if (PNODE->isMaster) { + // find new one + for (auto& nd : m_lMasterNodesData) { + if (!nd.isMaster) { + nd.isMaster = true; + break; + } + } + } + + m_lMasterNodesData.remove(*PNODE); + + recalculateMonitor(pWindow->m_iMonitorID); +} + +void CHyprMasterLayout::recalculateMonitor(const int& monid) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); + + if (!PWORKSPACE) + return; + + g_pHyprRenderer->damageMonitor(PMONITOR); + + if (PMONITOR->specialWorkspaceOpen) { + calculateWorkspace(SPECIAL_WORKSPACE_ID); + } + + if (PWORKSPACE->m_bHasFullscreenWindow) { + if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) + return; + + // massive hack from the fullscreen func + const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + + SMasterNodeData fakeNode; + fakeNode.pWindow = PFULLWINDOW; + fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + fakeNode.workspaceID = PWORKSPACE->m_iID; + PFULLWINDOW->m_vPosition = fakeNode.position; + PFULLWINDOW->m_vSize = fakeNode.size; + + applyNodeDataToWindow(&fakeNode); + + return; + } + + // calc the WS + calculateWorkspace(PWORKSPACE->m_iID); +} + +void CHyprMasterLayout::calculateWorkspace(const int& ws) { + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(ws); + + if (!PWORKSPACE) + return; + + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + + const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID); + + if (!PMASTERNODE) + return; + + if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2) { + PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition; + PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y); + applyNodeDataToWindow(PMASTERNODE); + return; + } else { + PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition; + PMASTERNODE->size = Vector2D((PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y); + } + + const auto SLAVESIZE = 1.f / (getNodesOnWorkspace(PWORKSPACE->m_iID) - 1) * (PMASTERNODE->size.y); + int slavesDone = 0; + + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID != PWORKSPACE->m_iID) + continue; + + if (nd == *PMASTERNODE) { + applyNodeDataToWindow(PMASTERNODE); + continue; + } + + nd.position = Vector2D(PMASTERNODE->size.x + PMASTERNODE->position.x, slavesDone * SLAVESIZE + PMASTERNODE->position.y); + nd.size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x, SLAVESIZE); + + slavesDone++; + + applyNodeDataToWindow(&nd); + } +} + +void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { + SMonitor* PMONITOR = nullptr; + + if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) { + for (auto& m : g_pCompositor->m_vMonitors) { + if (m->specialWorkspaceOpen) { + PMONITOR = m.get(); + break; + } + } + } else { + PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID); + } + + if (!PMONITOR) { + Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID); + return; + } + + // for gaps outer + const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); + const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); + const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y); + const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y); + + const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size"); + const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in"); + const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out"); + + const auto PWINDOW = pNode->pWindow; + + if (!g_pCompositor->windowValidMapped(PWINDOW)) { + Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW); + return; + } + + PWINDOW->m_vSize = pNode->size; + PWINDOW->m_vPosition = pNode->position; + + // TODO: special + + auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE); + auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE); + + const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN, + DISPLAYTOP ? GAPSOUT : GAPSIN); + + const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN, + DISPLAYBOTTOM ? GAPSOUT : GAPSIN); + + calcPos = calcPos + OFFSETTOPLEFT; + calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; + + if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) { + static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue; + + PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f; + PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR; + + g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR); + } else { + PWINDOW->m_vRealSize = calcSize; + PWINDOW->m_vRealPosition = calcPos; + + g_pXWaylandManager->setWindowSize(PWINDOW, calcSize); + } + + PWINDOW->updateWindowDecos(); +} + +bool CHyprMasterLayout::isWindowTiled(CWindow* pWindow) { + return getNodeFromWindow(pWindow) != nullptr; +} + +void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) { + const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow; + + if (!g_pCompositor->windowValidMapped(PWINDOW)) + return; + + const auto PNODE = getNodeFromWindow(PWINDOW); + + if (!PNODE) { + PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999)); + PWINDOW->updateWindowDecos(); + return; + } + + // get master + const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + + if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) < 2) + return; + + float delta = pixResize.x / PMONITOR->vecSize.x; + + PMASTER->percMaster += delta; + + std::clamp(PMASTER->percMaster, 0.05f, 0.95f); + + recalculateMonitor(PMONITOR->ID); +} + +void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) { + if (!g_pCompositor->windowValidMapped(pWindow)) + return; + + if (on == pWindow->m_bIsFullscreen) + return; // ignore + + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); + + if (PWORKSPACE->m_bHasFullscreenWindow && on) { + // if the window wants to be fullscreen but there already is one, + // ignore the request. + return; + } + + // otherwise, accept it. + pWindow->m_bIsFullscreen = on; + PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; + + g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)}); + + if (!pWindow->m_bIsFullscreen) { + // if it got its fullscreen disabled, set back its node if it had one + const auto PNODE = getNodeFromWindow(pWindow); + if (PNODE) + applyNodeDataToWindow(PNODE); + else { + // get back its' dimensions from position and size + pWindow->m_vRealPosition = pWindow->m_vPosition; + pWindow->m_vRealSize = pWindow->m_vSize; + } + } else { + // if it now got fullscreen, make it fullscreen + + PWORKSPACE->m_efFullscreenMode = fullscreenMode; + + // save position and size if floating + if (pWindow->m_bIsFloating) { + pWindow->m_vPosition = pWindow->m_vRealPosition.vec(); + pWindow->m_vSize = pWindow->m_vRealSize.vec(); + } + + // apply new pos and size being monitors' box + if (fullscreenMode == FULLSCREEN_FULL) { + pWindow->m_vRealPosition = PMONITOR->vecPosition; + pWindow->m_vRealSize = PMONITOR->vecSize; + } else { + // This is a massive hack. + // We make a fake "only" node and apply + // To keep consistent with the settings without C+P code + + SMasterNodeData fakeNode; + fakeNode.pWindow = pWindow; + fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + fakeNode.workspaceID = pWindow->m_iWorkspaceID; + pWindow->m_vPosition = fakeNode.position; + pWindow->m_vSize = fakeNode.size; + + applyNodeDataToWindow(&fakeNode); + } + } + + g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); + + g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); + + g_pCompositor->moveWindowToTop(pWindow); + + // we need to fix XWayland windows by sending them to NARNIA + // because otherwise they'd still be recieving mouse events + g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace); + + recalculateMonitor(PMONITOR->ID); +} + +void CHyprMasterLayout::recalculateWindow(CWindow* pWindow) { + const auto PNODE = getNodeFromWindow(pWindow); + + if (!PNODE) + return; + + recalculateMonitor(pWindow->m_iMonitorID); +} + +SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(CWindow* pWindow) { + // window should be valid, insallah + + SWindowRenderLayoutHints hints; + + return hints; // master doesnt have any hints +} + +void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { + // windows should be valid, insallah + + const auto PNODE = getNodeFromWindow(pWindow); + const auto PNODE2 = getNodeFromWindow(pWindow2); + + if (!PNODE2 || !PNODE) + return; + + if (PNODE->workspaceID != PNODE2->workspaceID) { + Debug::log(ERR, "Master: Rejecting a swap between workspaces"); + return; + } + + // massive hack: just swap window pointers, lol + const auto PWINDOW1 = PNODE->pWindow; + PNODE->pWindow = PNODE2->pWindow; + PNODE2->pWindow = PWINDOW1; + + recalculateMonitor(PWINDOW1->m_iMonitorID); +} + +void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) { + // window should be valid, insallah + + const auto PNODE = getNodeFromWindow(pWindow); + + if (!PNODE) + return; + + const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID); + + PMASTER->percMaster = std::clamp(PMASTER->percMaster + ratio, 0.05f, 0.95f); + + recalculateMonitor(pWindow->m_iMonitorID); +} + +std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) { + return ""; +} + +void CHyprMasterLayout::onEnable() { + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden) + continue; + + onWindowCreatedTiling(w.get()); + } +} + +void CHyprMasterLayout::onDisable() { + m_lMasterNodesData.clear(); +} \ No newline at end of file diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp new file mode 100644 index 000000000..318f8940b --- /dev/null +++ b/src/layout/MasterLayout.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "IHyprLayout.hpp" +#include +#include + +enum eFullscreenMode : uint8_t; + +struct SMasterNodeData { + bool isMaster = false; + float percMaster = 0.5f; + + CWindow* pWindow = nullptr; + + Vector2D position; + Vector2D size; + + int workspaceID = -1; + + bool operator==(const SMasterNodeData& rhs) { + return pWindow == rhs.pWindow; + } +}; + +class CHyprMasterLayout : public IHyprLayout { +public: + virtual void onWindowCreatedTiling(CWindow*); + virtual void onWindowRemovedTiling(CWindow*); + virtual bool isWindowTiled(CWindow*); + virtual void recalculateMonitor(const int&); + virtual void recalculateWindow(CWindow*); + virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr); + virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool); + virtual std::any layoutMessage(SLayoutMessageHeader, std::string); + virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); + virtual void switchWindows(CWindow*, CWindow*); + virtual void alterSplitRatioBy(CWindow*, float); + virtual std::string getLayoutName(); + + virtual void onEnable(); + virtual void onDisable(); + +private: + + std::list m_lMasterNodesData; + + int getNodesOnWorkspace(const int&); + void applyNodeDataToWindow(SMasterNodeData*); + SMasterNodeData* getNodeFromWindow(CWindow*); + SMasterNodeData* getMasterNodeOnWorkspace(const int&); + void calculateWorkspace(const int&); + + friend struct SMasterNodeData; +}; \ No newline at end of file diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index a8743afd1..5d3027c9a 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -191,7 +191,6 @@ void CAnimationManager::tick() { } case AVARDAMAGE_SHADOW: { RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!"); - static auto* const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue; static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue; const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 3aecc3b6c..cf8206118 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -82,7 +82,53 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { return modMask; } -bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& key, const xkb_keysym_t& keysym, const int& keycode) { +bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) { + const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput + + const xkb_keysym_t keysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE); + + const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); + + + bool found = false; + if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + m_dPressedKeycodes.push_back(KEYCODE); + m_dPressedKeysyms.push_back(keysym); + + found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, true, e->time_msec) || found; + + found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, true, e->time_msec) || found; + } else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) { + + m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE)); + m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym)); + + found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found; + + found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, false, e->time_msec) || found; + + shadowKeybinds(); + } + + return !found; +} + +bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) { + const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); + + bool found = false; + if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) { + if (e->delta < 0) { + found = g_pKeybindManager->handleKeybinds(MODS, "mouse_down", 0, 0, false, 0); + } else { + found = g_pKeybindManager->handleKeybinds(MODS, "mouse_up", 0, 0, false, 0); + } + } + + return !found; +} + +bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& key, const xkb_keysym_t& keysym, const int& keycode, bool pressed, uint32_t time) { bool found = false; if (handleInternalKeybinds(keysym)) @@ -91,8 +137,14 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& if (g_pCompositor->m_sSeat.exclusiveClient) Debug::log(LOG, "Keybind handling only locked (inhibitor)"); + if (pressed && m_kHeldBack) { + // release the held back event + wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, time, m_kHeldBack, WL_KEYBOARD_KEY_STATE_PRESSED); + m_kHeldBack = 0; + } + for (auto& k : m_lKeybinds) { - if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap) + if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release) || k.shadowed) continue; if (!key.empty()) { @@ -115,6 +167,12 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& continue; } + if (pressed && k.release) { + // suppress down event + m_kHeldBack = key; + return true; + } + const auto DISPATCHER = m_mDispatchers.find(k.handler); // Should never happen, as we check in the ConfigManager, but oh well @@ -126,12 +184,40 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& DISPATCHER->second(k.arg); } + shadowKeybinds(); + found = true; } return found; } +void CKeybindManager::shadowKeybinds() { + // shadow disables keybinds after one has been triggered + + for (auto& k : m_lKeybinds) { + + bool shadow = false; + + const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); + const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY); + + for (auto& pk : m_dPressedKeysyms) { + if ((pk == KBKEY || pk == KBKEYUPPER)) { + shadow = true; + } + } + + for (auto& pk : m_dPressedKeycodes) { + if (pk == (unsigned int)k.keycode) { + shadow = true; + } + } + + k.shadowed = shadow; + } +} + bool CKeybindManager::handleVT(xkb_keysym_t keysym) { // Handles the CTRL+ALT+FX TTY keybinds if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12)) @@ -231,7 +317,7 @@ void CKeybindManager::killActive(std::string args) { g_pXWaylandManager->sendCloseWindow(g_pCompositor->m_pLastWindow); g_pCompositor->m_pLastFocus = nullptr; g_pCompositor->m_pLastWindow = nullptr; - g_pEventManager->postEvent(SHyprIPCEvent("activewindow", ",")); // post an activewindow event to empty, as we are currently unfocused + g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // post an activewindow event to empty, as we are currently unfocused } g_pCompositor->focusWindow(g_pCompositor->windowFromCursor()); @@ -326,7 +412,7 @@ void CKeybindManager::changeworkspace(std::string args) { // start anim on new workspace PWORKSPACETOCHANGETO->startAnim(true, ANIMTOLEFT); - g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName)); + g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACETOCHANGETO->m_szName}); } // If the monitor is not the one our cursor's at, warp to it. @@ -399,7 +485,7 @@ void CKeybindManager::changeworkspace(std::string args) { g_pInputManager->refocus(); // Event - g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACE->m_szName)); + g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACE->m_szName}); Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo); } @@ -430,6 +516,9 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { return; } + auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec(); + auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec(); + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); g_pKeybindManager->changeworkspace(args); @@ -457,20 +546,21 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { PWORKSPACE->m_bHasFullscreenWindow = false; } + if (PWINDOW->m_bIsFullscreen) { + PWINDOW->m_bIsFullscreen = false; + PSAVEDPOS = PSAVEDPOS + Vector2D(10, 10); + PSAVEDSIZE = PSAVEDSIZE - Vector2D(20, 20); + } + // Hack: So that the layout doesnt find our window at the cursor PWINDOW->m_vPosition = Vector2D(-42069, -42069); - // Save the real position and size because the layout might set its own - const auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec(); - const auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec(); g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); - // and restore it - PWINDOW->m_vRealPosition.setValue(PSAVEDPOS); - PWINDOW->m_vRealSize.setValue(PSAVEDSIZE); + // and restore it if (PWINDOW->m_bIsFloating) { - PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition); - PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition); + PWINDOW->m_vRealSize.setValue(PSAVEDSIZE); + PWINDOW->m_vRealPosition.setValueAndWarp(PSAVEDPOS - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition); PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec(); } @@ -1048,6 +1138,11 @@ void CKeybindManager::circleNext(std::string arg) { if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow)) return; + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID); + + if (PWORKSPACE->m_bHasFullscreenWindow) + return; + if (arg == "last" || arg == "l" || arg == "prev" || arg == "p") g_pCompositor->focusWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow)); else @@ -1059,28 +1154,57 @@ void CKeybindManager::circleNext(std::string arg) { } void CKeybindManager::focusWindow(std::string regexp) { - bool titleRegex = false; + eFocusWindowMode mode = MODE_CLASS_REGEX; + std::regex regexCheck(regexp); + std::string matchCheck; if (regexp.find("title:") == 0) { - titleRegex = true; + mode = MODE_TITLE_REGEX; regexCheck = std::regex(regexp.substr(6)); } + else if (regexp.find("address:") == 0) { + mode = MODE_ADDRESS; + matchCheck = regexp.substr(8); + } + else if (regexp.find("pid:") == 0) { + mode = MODE_PID; + matchCheck = regexp.substr(4); + } for (auto& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped || w->m_bHidden) continue; - if (titleRegex) { - const auto windowTitle = g_pXWaylandManager->getTitle(w.get()); - if (!std::regex_search(windowTitle, regexCheck)) - continue; - } - else { - const auto windowClass = g_pXWaylandManager->getAppIDClass(w.get()); - if (!std::regex_search(windowClass, regexCheck)) - continue; + switch (mode) { + case MODE_CLASS_REGEX: { + const auto windowClass = g_pXWaylandManager->getAppIDClass(w.get()); + if (!std::regex_search(g_pXWaylandManager->getAppIDClass(w.get()), regexCheck)) + continue; + break; + } + case MODE_TITLE_REGEX: { + const auto windowTitle = g_pXWaylandManager->getTitle(w.get()); + if (!std::regex_search(windowTitle, regexCheck)) + continue; + break; + } + case MODE_ADDRESS: { + std::string addr = getFormat("0x%x", w.get()); + if (matchCheck != addr) + continue; + break; + } + case MODE_PID: { + std::string pid = getFormat("%d", w->getPID()); + if (matchCheck != pid) + continue; + break; + } + default: + break; } + Debug::log(LOG, "Focusing to window name: %s", w->m_szTitle.c_str()); changeworkspace("[internal]" + std::to_string(w->m_iWorkspaceID)); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 049568a68..4fa314a99 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -14,13 +14,19 @@ struct SKeybind { std::string arg = ""; bool locked = false; std::string submap = ""; + bool release = false; + + // DO NOT INITIALIZE + bool shadowed = false; }; class CKeybindManager { public: CKeybindManager(); - bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&); + bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*); + bool onAxisEvent(wlr_pointer_axis_event*); + void addKeybind(SKeybind); void removeKeybind(uint32_t, const std::string&); uint32_t stringToModMask(std::string); @@ -30,9 +36,17 @@ public: private: std::list m_lKeybinds; + std::deque m_dPressedKeysyms; + std::deque m_dPressedKeycodes; inline static std::string m_szCurrentSelectedSubmap = ""; + xkb_keysym_t m_kHeldBack = 0; + + bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&, bool, uint32_t); + + void shadowKeybinds(); + bool handleInternalKeybinds(xkb_keysym_t); bool handleVT(xkb_keysym_t); @@ -66,6 +80,13 @@ private: static void setSubmap(std::string); friend class CCompositor; + + enum eFocusWindowMode { + MODE_CLASS_REGEX = 0, + MODE_TITLE_REGEX, + MODE_ADDRESS, + MODE_PID + }; }; -inline std::unique_ptr g_pKeybindManager; \ No newline at end of file +inline std::unique_ptr g_pKeybindManager; diff --git a/src/managers/LayoutManager.cpp b/src/managers/LayoutManager.cpp index ec723350f..8e7e397bb 100644 --- a/src/managers/LayoutManager.cpp +++ b/src/managers/LayoutManager.cpp @@ -4,8 +4,28 @@ IHyprLayout* CLayoutManager::getCurrentLayout() { switch (m_iCurrentLayoutID) { case DWINDLE: return &m_cDwindleLayout; + case MASTER: + return &m_cMasterLayout; } // fallback return &m_cDwindleLayout; +} + +void CLayoutManager::switchToLayout(std::string layout) { + if (layout == "dwindle") { + if (m_iCurrentLayoutID != DWINDLE) { + getCurrentLayout()->onDisable(); + m_iCurrentLayoutID = DWINDLE; + getCurrentLayout()->onEnable(); + } + } else if (layout == "master") { + if (m_iCurrentLayoutID != MASTER) { + getCurrentLayout()->onDisable(); + m_iCurrentLayoutID = MASTER; + getCurrentLayout()->onEnable(); + } + } else { + Debug::log(ERR, "Unknown layout %s!", layout.c_str()); + } } \ No newline at end of file diff --git a/src/managers/LayoutManager.hpp b/src/managers/LayoutManager.hpp index 20f1f7f9f..aa340e798 100644 --- a/src/managers/LayoutManager.hpp +++ b/src/managers/LayoutManager.hpp @@ -1,20 +1,25 @@ #pragma once #include "../layout/DwindleLayout.hpp" +#include "../layout/MasterLayout.hpp" class CLayoutManager { public: IHyprLayout* getCurrentLayout(); + void switchToLayout(std::string); + private: enum HYPRLAYOUTS { DWINDLE = 0, + MASTER }; HYPRLAYOUTS m_iCurrentLayoutID = DWINDLE; CHyprDwindleLayout m_cDwindleLayout; + CHyprMasterLayout m_cMasterLayout; }; inline std::unique_ptr g_pLayoutManager; \ No newline at end of file diff --git a/src/managers/ThreadManager.cpp b/src/managers/ThreadManager.cpp index fa3d0d4ef..3ca4d550f 100644 --- a/src/managers/ThreadManager.cpp +++ b/src/managers/ThreadManager.cpp @@ -1,34 +1,29 @@ #include "ThreadManager.hpp" #include "../debug/HyprCtl.hpp" - -CThreadManager::CThreadManager() { - m_tMainThread = new std::thread([&]() { - // Call the handle method. - this->handle(); - }); - - m_tMainThread->detach(); // detach and continue. -} - -CThreadManager::~CThreadManager() { - // -} +#include "../Compositor.hpp" int slowUpdate = 0; -void CThreadManager::handle() { +int handleTimer(void* data) { + const auto PTM = (CThreadManager*)data; + g_pConfigManager->tick(); + + wl_event_source_timer_update(PTM->m_esConfigTimer, 1000); + + return 0; +} + +CThreadManager::CThreadManager() { g_pConfigManager->init(); HyprCtl::startHyprCtlSocket(); - while (3.1415f) { - slowUpdate++; - if (slowUpdate >= g_pConfigManager->getInt("general:max_fps")){ - g_pConfigManager->tick(); - slowUpdate = 0; - } + m_esConfigTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this); - std::this_thread::sleep_for(std::chrono::microseconds(1000000 / g_pConfigManager->getInt("general:max_fps"))); - } + wl_event_source_timer_update(m_esConfigTimer, 1000); +} + +CThreadManager::~CThreadManager() { + // } \ No newline at end of file diff --git a/src/managers/ThreadManager.hpp b/src/managers/ThreadManager.hpp index 40ed88d61..0a716e0be 100644 --- a/src/managers/ThreadManager.hpp +++ b/src/managers/ThreadManager.hpp @@ -9,11 +9,9 @@ public: CThreadManager(); ~CThreadManager(); -private: + wl_event_source* m_esConfigTimer; - void handle(); - - std::thread* m_tMainThread; + private: }; inline std::unique_ptr g_pThreadManager; \ No newline at end of file diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index c7fcfb7a0..e1f2e98f1 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -117,7 +117,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { ACTIVEWORKSPACE->setActive(true); // event - g_pEventManager->postEvent(SHyprIPCEvent("activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName)); + g_pEventManager->postEvent(SHyprIPCEvent{"activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName}); } Vector2D surfaceCoords; @@ -233,6 +233,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } else if (*PFOLLOWMOUSE == 2) { wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); } + + if (pFoundWindow == g_pCompositor->m_pLastWindow && foundSurface != g_pCompositor->m_pLastFocus) { + // we changed the subsurface + wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); + } + wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y); return; // don't enter any new surfaces } else { @@ -376,18 +382,11 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) { } void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { - const auto MODS = accumulateModsFromAllKBs(); + bool passEvent = g_pKeybindManager->onAxisEvent(e); - bool found = false; - if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) { - if (e->delta < 0) { - found = g_pKeybindManager->handleKeybinds(MODS, "mouse_down", 0, 0); - } else { - found = g_pKeybindManager->handleKeybinds(MODS, "mouse_up", 0, 0); - } - } + wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat); - if (!found) { + if (passEvent) { wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, e->delta, e->delta_discrete, e->source); } } @@ -533,47 +532,14 @@ void CInputManager::newMouse(wlr_input_device* mouse, bool virt) { Debug::log(ERR, "Mouse had no name???"); // logic error } - const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PMOUSE->name); - if (wlr_input_device_is_libinput(mouse)) { const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse); - if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "clickfinger_behavior") : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) == 0) // toggle software buttons or clickfinger - libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); - else - libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - - if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed - if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "middle_button_emulation") : g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1) - libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED); - else - libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); - } - - if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "drag_lock") : g_pConfigManager->getInt("input:touchpad:drag_lock")) == 0) - libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); - else - libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); - - if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop) - if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "tap-to-click") : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1) - libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED); - - if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) { - double w = 0, h = 0; - - if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad - libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll"))); - else - libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:natural_scroll"))); - } - - if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) { - const auto DWT = static_cast((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "disable_while_typing") : g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0); - libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT); - } + Debug::log(LOG, "New mouse has libinput sens %.2f (%.2f) with accel profile %i (%i)", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), libinput_device_config_accel_get_profile(LIBINPUTDEV), libinput_device_config_accel_get_default_profile(LIBINPUTDEV)); } + setMouseConfigs(); + PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse"); wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse); @@ -585,6 +551,60 @@ void CInputManager::newMouse(wlr_input_device* mouse, bool virt) { Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse); } +void CInputManager::setMouseConfigs() { + for (auto& m : m_lMice) { + const auto PMOUSE = &m; + + const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PMOUSE->name); + + if (wlr_input_device_is_libinput(m.mouse)) { + const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse); + + if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "clickfinger_behavior") : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) == 0) // toggle software buttons or clickfinger + libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + else + libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + + if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed + if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "middle_button_emulation") : g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1) + libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED); + else + libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); + } + + if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "drag_lock") : g_pConfigManager->getInt("input:touchpad:drag_lock")) == 0) + libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + else + libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); + + if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop) + if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "tap-to-click") : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1) + libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED); + + if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) { + double w = 0, h = 0; + + if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad + libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll"))); + else + libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:natural_scroll"))); + } + + if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) { + const auto DWT = static_cast((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "disable_while_typing") : g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0); + libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT); + } + + const auto LIBINPUTSENS = std::clamp((HASCONFIG ? g_pConfigManager->getDeviceFloat(PMOUSE->name, "sensitivity") : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f); + + libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE); + libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS); + + Debug::log(LOG, "Applied config to mouse %s, sens %.2f", m.name.c_str(), LIBINPUTSENS); + } + } +} + void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) { pKeyboard->hyprListener_keyboardDestroy.removeCallback(); pKeyboard->hyprListener_keyboardMod.removeCallback(); @@ -619,26 +639,11 @@ void CInputManager::destroyMouse(wlr_input_device* mouse) { } void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) { - const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput - - const xkb_keysym_t* keysyms; - int syms = xkb_state_key_get_syms(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE, &keysyms); - - const auto MODS = accumulateModsFromAllKBs(); + bool passEvent = g_pKeybindManager->onKeyEvent(e, pKeyboard); wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat); - bool found = false; - if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { - for (int i = 0; i < syms; ++i) - found = g_pKeybindManager->handleKeybinds(MODS, "", keysyms[i], 0) || found; - - found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE) || found; - } else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) { - // hee hee - } - - if (!found) { + if (passEvent) { wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard)); wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state); } diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 5e0c86b1e..da821dfc8 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -33,6 +33,7 @@ public: void refocus(); void setKeyboardLayout(); + void setMouseConfigs(); void updateDragIcon(); void updateCapabilities(wlr_input_device*); @@ -76,6 +77,9 @@ public: CTimer m_tmrLastCursorMovement; + // for shared mods + uint32_t accumulateModsFromAllKBs(); + private: // for click behavior override @@ -92,9 +96,6 @@ private: STabletTool* ensureTabletToolPresent(wlr_tablet_tool*); void applyConfigToKeyboard(SKeyboard*); - - // for shared mods - uint32_t accumulateModsFromAllKBs(); }; inline std::unique_ptr g_pInputManager; \ No newline at end of file diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 98f31945e..74783f42d 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -4,8 +4,9 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) { static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue; + static auto *const PSWIPEFINGERS = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers")->intValue; - if (e->fingers < 3 || *PSWIPE == 0) + if (e->fingers != *PSWIPEFINGERS|| *PSWIPE == 0) return; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace); @@ -58,6 +59,10 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { PWORKSPACEL->m_vRenderOffset.setValue(RENDEROFFSET); PWORKSPACEL->m_fAlpha.setValueAndWarp(255.f); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0); + m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f); + Debug::log(LOG, "Ended swipe to the left"); } else { // switch to right @@ -68,12 +73,13 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET); PWORKSPACER->m_fAlpha.setValueAndWarp(255.f); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0); + m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f); + Debug::log(LOG, "Ended swipe to the right"); } - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); - m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f); - PWORKSPACEL->m_bForceRendering = false; PWORKSPACER->m_bForceRendering = false; m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 07e4dfff1..91d6b0c54 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -388,14 +388,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { - const float verts[] = { - m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right - m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left - m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right - m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left - }; + const float verts[] = { + m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right + m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left + m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right + m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left + }; + if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts); } else { glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -698,7 +698,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { // this is temporary, doesnt mess with the actual wlr damage pixman_region32_t fakeDamage; pixman_region32_init(&fakeDamage); - pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y); + pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y); begin(PMONITOR, &fakeDamage, true); @@ -715,6 +715,8 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { const auto BLURVAL = g_pConfigManager->getInt("decoration:blur"); g_pConfigManager->setInt("decoration:blur", 0); + m_bEndFrame = true; + g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL); g_pConfigManager->setInt("decoration:blur", BLURVAL); @@ -731,8 +733,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { clear(CColor(0, 0, 0, 0)); // JIC - wlr_box fullMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; + wlr_box fullMonBox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; + renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &fullMonBox, 255.f, 0); + m_bEndFrame = false; // restore original fb #ifndef GLES2 @@ -757,7 +761,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { // this is temporary, doesnt mess with the actual wlr damage pixman_region32_t fakeDamage; pixman_region32_init(&fakeDamage); - pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y); + pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y); begin(PMONITOR, &fakeDamage, true); @@ -774,9 +778,13 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); + m_bEndFrame = true; + // draw the layer g_pHyprRenderer->renderLayer(pLayer, PMONITOR, &now); + m_bEndFrame = false; + // TODO: WARN: // revise if any stencil-requiring rendering is done to the layers. @@ -815,13 +823,15 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { // the originalClosedPos is relative to the monitor's pos Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.vec().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), (PMONITOR->scale * PWINDOW->m_vRealSize.vec().y / (PWINDOW->m_vOriginalClosedSize.y * PMONITOR->scale))); - windowBox.width = PMONITOR->vecPixelSize.x * scaleXY.x; - windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y; + // TODO: this is wrong on scaled. + + windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x; + windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y; windowBox.x = ((PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x); windowBox.y = ((PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y); pixman_region32_t fakeDamage; - pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y); renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha.fl(), &fakeDamage, 0); @@ -844,10 +854,10 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID); - wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; + wlr_box windowBox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; pixman_region32_t fakeDamage; - pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y); renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PLAYER->alpha.fl(), &fakeDamage, 0); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index e3e67a652..79b3a8b51 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -40,12 +40,6 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding); else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); - - if (RDATA->decorate) { - auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col(); - col.a *= RDATA->fadeAlpha * RDATA->alpha / 255.f; - g_pHyprOpenGL->renderBorder(&windowBox, col, rounding); - } } else { if (RDATA->surface && wlr_surface_is_xdg_surface(RDATA->surface)) { @@ -241,6 +235,21 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata); + if (renderdata.decorate) { + static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; + + float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding; + + auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col(); + col.a *= renderdata.fadeAlpha * renderdata.alpha / 255.f; + + wlr_box windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; + + scaleBox(&windowBox, pMonitor->scale); + + g_pHyprOpenGL->renderBorder(&windowBox, col, rounding); + } + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); } @@ -499,7 +508,7 @@ void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::listvecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; for (auto& ls : layerSurfaces) { - if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface) + if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess) continue; const auto PLAYER = ls->layerSurface; @@ -643,12 +652,12 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) { pixman_region32_translate(&damageBox, -lx, -ly); } - pixman_region32_fini(&damageBox); - static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue; if (*PLOGDAMAGE) Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, damageBox.extents.y2 - damageBox.extents.y1); + + pixman_region32_fini(&damageBox); } void CHyprRenderer::damageWindow(CWindow* pWindow) { diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 400519425..a03181c0f 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -53,6 +53,9 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) { if (!g_pCompositor->windowValidMapped(m_pWindow)) return; + if (m_pWindow->m_cRealShadowColor.col() == CColor(0, 0, 0, 0)) + return; // don't draw invisible shadows + static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue; static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index d01e77755..13cdc92a2 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -34,8 +34,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar distances = distances / 4.0; - gl_FragColor = )#" + colorVarName + R"#( * distances; - return; + )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances; } } } else if (pixCoord[1] > bottomRight[1]) { @@ -66,8 +65,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar distances = distances / 4.0; - gl_FragColor = )#" + colorVarName + R"#( * distances; - return; + )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances; } } } @@ -102,8 +100,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar distances = distances / 4.0; - gl_FragColor = )#" + colorVarName + R"#( * distances; - return; + )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances; } } } else if (pixCoord[1] > bottomRight[1]) { @@ -134,8 +131,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar distances = distances / 4.0; - gl_FragColor = )#" + colorVarName + R"#( * distances; - return; + )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances; } } } @@ -176,11 +172,13 @@ void main() { return; } + vec4 pixColor = v_color; + vec2 pixCoord = fullSize * v_texcoord; - )#" + ROUNDED_SHADER_FUNC("v_color") + R"#( + )#" + ROUNDED_SHADER_FUNC("pixColor") + R"#( - gl_FragColor = v_color; + gl_FragColor = pixColor; })#"; inline const std::string TEXVERTSRC = R"#(