mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-02 19:05:58 +01:00
windows: add misc:initial_workspace_tracking
By default enabled, will track the initial opened workspace of a window spawned for 2 minutes or until it's moved to a different workspace. For example: you run a launcher and open an app on workspace 1, but quickly switch to workspace 2. The app will now open on workspace 1 regardless of your switch.
This commit is contained in:
parent
7778f01194
commit
29308b94ca
5 changed files with 110 additions and 12 deletions
|
@ -350,6 +350,7 @@ CConfigManager::CConfigManager() {
|
||||||
m_pConfig->addConfigValue("misc:new_window_takes_over_fullscreen", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("misc:new_window_takes_over_fullscreen", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("misc:enable_hyprcursor", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("misc:enable_hyprcursor", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("misc:hide_cursor_on_key_press", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("misc:hide_cursor_on_key_press", Hyprlang::INT{0});
|
||||||
|
m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1});
|
||||||
|
|
||||||
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1});
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "../render/decorations/CHyprBorderDecoration.hpp"
|
#include "../render/decorations/CHyprBorderDecoration.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
#include <any>
|
#include <any>
|
||||||
|
#include "../managers/TokenManager.hpp"
|
||||||
|
|
||||||
CWindow::CWindow() {
|
CWindow::CWindow() {
|
||||||
m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), this, AVARDAMAGE_ENTIRE);
|
m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), this, AVARDAMAGE_ENTIRE);
|
||||||
|
@ -384,6 +385,11 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
||||||
if (m_pWorkspace == pWorkspace)
|
if (m_pWorkspace == pWorkspace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!m_szInitialWorkspaceToken.empty()) {
|
||||||
|
g_pTokenManager->removeToken(g_pTokenManager->getToken(m_szInitialWorkspaceToken));
|
||||||
|
m_szInitialWorkspaceToken = "";
|
||||||
|
}
|
||||||
|
|
||||||
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
|
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
|
||||||
|
|
||||||
const auto OLDWORKSPACE = m_pWorkspace;
|
const auto OLDWORKSPACE = m_pWorkspace;
|
||||||
|
@ -1241,3 +1247,42 @@ int CWindow::workspaceID() {
|
||||||
bool CWindow::onSpecialWorkspace() {
|
bool CWindow::onSpecialWorkspace() {
|
||||||
return m_pWorkspace ? m_pWorkspace->m_bIsSpecialWorkspace : g_pCompositor->isWorkspaceSpecial(m_iLastWorkspace);
|
return m_pWorkspace ? m_pWorkspace->m_bIsSpecialWorkspace : g_pCompositor->isWorkspaceSpecial(m_iLastWorkspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::string> CWindow::getEnv() {
|
||||||
|
|
||||||
|
const auto PID = getPID();
|
||||||
|
|
||||||
|
if (PID <= 1)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::string> results;
|
||||||
|
|
||||||
|
//
|
||||||
|
std::string environFile = "/proc/" + std::to_string(PID) + "/environ";
|
||||||
|
std::ifstream ifs(environFile, std::ios::binary);
|
||||||
|
|
||||||
|
if (!ifs.good())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::vector<char> buffer;
|
||||||
|
size_t needle = 0;
|
||||||
|
buffer.resize(512, '\0');
|
||||||
|
while (ifs.read(buffer.data() + needle, 512)) {
|
||||||
|
buffer.resize(buffer.size() + 512, '\0');
|
||||||
|
needle += 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::replace(buffer.begin(), buffer.end() - 1, '\0', '\n');
|
||||||
|
|
||||||
|
CVarList envs(std::string{buffer.data(), needle - 1}, 0, '\n', true);
|
||||||
|
|
||||||
|
for (auto& e : envs) {
|
||||||
|
if (!e.contains('='))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto EQ = e.find_first_of('=');
|
||||||
|
results[e.substr(0, EQ)] = e.substr(EQ + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
|
@ -357,6 +357,9 @@ class CWindow {
|
||||||
// for idle inhibiting windows
|
// for idle inhibiting windows
|
||||||
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||||
|
|
||||||
|
// initial token. Will be unregistered on workspace change or timeout of 2 minutes
|
||||||
|
std::string m_szInitialWorkspaceToken = "";
|
||||||
|
|
||||||
// for groups
|
// for groups
|
||||||
struct SGroupData {
|
struct SGroupData {
|
||||||
CWindow* pNextWindow = nullptr; // nullptr means no grouping. Self means single group.
|
CWindow* pNextWindow = nullptr; // nullptr means no grouping. Self means single group.
|
||||||
|
@ -437,6 +440,9 @@ class CWindow {
|
||||||
void setAnimationsToMove();
|
void setAnimationsToMove();
|
||||||
void onWorkspaceAnimUpdate();
|
void onWorkspaceAnimUpdate();
|
||||||
|
|
||||||
|
//
|
||||||
|
std::unordered_map<std::string, std::string> getEnv();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For hidden windows and stuff
|
// For hidden windows and stuff
|
||||||
bool m_bHidden = false;
|
bool m_bHidden = false;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/input/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
|
#include "../managers/TokenManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
|
||||||
|
@ -44,13 +45,14 @@ void setAnimToMove(void* data) {
|
||||||
void Events::listener_mapWindow(void* owner, void* data) {
|
void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
CWindow* PWINDOW = (CWindow*)owner;
|
CWindow* PWINDOW = (CWindow*)owner;
|
||||||
|
|
||||||
static auto PINACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:inactive_opacity");
|
static auto PINACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:inactive_opacity");
|
||||||
static auto PACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:active_opacity");
|
static auto PACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:active_opacity");
|
||||||
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
||||||
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
|
static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
|
||||||
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
|
static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
|
||||||
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
|
static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
|
||||||
static auto PNEWTAKESOVERFS = CConfigValue<Hyprlang::INT>("misc:new_window_takes_over_fullscreen");
|
static auto PNEWTAKESOVERFS = CConfigValue<Hyprlang::INT>("misc:new_window_takes_over_fullscreen");
|
||||||
|
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
||||||
|
|
||||||
auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||||
if (!g_pCompositor->m_pLastMonitor) {
|
if (!g_pCompositor->m_pLastMonitor) {
|
||||||
|
@ -67,6 +69,28 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_iX11Type = PWINDOW->m_bIsX11 ? (PWINDOW->m_uSurface.xwayland->override_redirect ? 2 : 1) : 1;
|
PWINDOW->m_iX11Type = PWINDOW->m_bIsX11 ? (PWINDOW->m_uSurface.xwayland->override_redirect ? 2 : 1) : 1;
|
||||||
PWINDOW->m_bFirstMap = true;
|
PWINDOW->m_bFirstMap = true;
|
||||||
|
|
||||||
|
// check for token
|
||||||
|
std::string requestedWorkspace = "";
|
||||||
|
bool workspaceSilent = false;
|
||||||
|
|
||||||
|
if (*PINITIALWSTRACKING) {
|
||||||
|
const auto WINDOWENV = PWINDOW->getEnv();
|
||||||
|
if (WINDOWENV.contains("HL_INITIAL_WORKSPACE_TOKEN")) {
|
||||||
|
const auto SZTOKEN = WINDOWENV.at("HL_INITIAL_WORKSPACE_TOKEN");
|
||||||
|
Debug::log(LOG, "New window contains HL_INITIAL_WORKSPACE_TOKEN: {}", SZTOKEN);
|
||||||
|
const auto TOKEN = g_pTokenManager->getToken(SZTOKEN);
|
||||||
|
if (TOKEN) {
|
||||||
|
// find workspace and use it
|
||||||
|
std::string WS = std::any_cast<std::string>(TOKEN->data);
|
||||||
|
|
||||||
|
Debug::log(LOG, "HL_INITIAL_WORKSPACE_TOKEN {} -> {}", SZTOKEN, WS);
|
||||||
|
|
||||||
|
requestedWorkspace = WS;
|
||||||
|
workspaceSilent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_pInputManager->m_bLastFocusOnLS) // waybar fix
|
if (g_pInputManager->m_bLastFocusOnLS) // waybar fix
|
||||||
g_pInputManager->releaseAllMouseButtons();
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
|
||||||
|
@ -108,10 +132,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// window rules
|
// window rules
|
||||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
||||||
std::string requestedWorkspace = "";
|
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
|
||||||
bool workspaceSilent = false;
|
|
||||||
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
|
|
||||||
(!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen) ||
|
(!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen) ||
|
||||||
(PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
|
(PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
|
||||||
bool requestsFakeFullscreen = false;
|
bool requestsFakeFullscreen = false;
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
#include "debug/Log.hpp"
|
#include "debug/Log.hpp"
|
||||||
#include "helpers/VarList.hpp"
|
#include "helpers/VarList.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
#include "TokenManager.hpp"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -17,6 +19,23 @@
|
||||||
#include <sys/consio.h>
|
#include <sys/consio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static std::vector<std::pair<std::string, std::string>> getHyprlandLaunchEnv() {
|
||||||
|
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
||||||
|
|
||||||
|
if (!*PINITIALWSTRACKING)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||||
|
if (!PMONITOR || !PMONITOR->activeWorkspace)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> result;
|
||||||
|
|
||||||
|
result.push_back(std::make_pair<>("HL_INITIAL_WORKSPACE_TOKEN", g_pTokenManager->registerNewToken(PMONITOR->activeWorkspace->getConfigName(), std::chrono::minutes(2))));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
CKeybindManager::CKeybindManager() {
|
CKeybindManager::CKeybindManager() {
|
||||||
// initialize all dispatchers
|
// initialize all dispatchers
|
||||||
|
|
||||||
|
@ -774,7 +793,9 @@ void CKeybindManager::spawn(std::string args) {
|
||||||
uint64_t CKeybindManager::spawnRaw(std::string args) {
|
uint64_t CKeybindManager::spawnRaw(std::string args) {
|
||||||
Debug::log(LOG, "Executing {}", args);
|
Debug::log(LOG, "Executing {}", args);
|
||||||
|
|
||||||
int socket[2];
|
const auto HLENV = getHyprlandLaunchEnv();
|
||||||
|
|
||||||
|
int socket[2];
|
||||||
if (pipe(socket) != 0) {
|
if (pipe(socket) != 0) {
|
||||||
Debug::log(LOG, "Unable to create pipe for fork");
|
Debug::log(LOG, "Unable to create pipe for fork");
|
||||||
}
|
}
|
||||||
|
@ -797,6 +818,9 @@ uint64_t CKeybindManager::spawnRaw(std::string args) {
|
||||||
grandchild = fork();
|
grandchild = fork();
|
||||||
if (grandchild == 0) {
|
if (grandchild == 0) {
|
||||||
// run in grandchild
|
// run in grandchild
|
||||||
|
for (auto& e : HLENV) {
|
||||||
|
setenv(e.first.c_str(), e.second.c_str(), 1);
|
||||||
|
}
|
||||||
close(socket[0]);
|
close(socket[0]);
|
||||||
close(socket[1]);
|
close(socket[1]);
|
||||||
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
||||||
|
|
Loading…
Reference in a new issue