added intelligent transients

This commit is contained in:
vaxerski 2021-12-21 12:22:41 +01:00
parent 786fa73c8c
commit 1421d42cae
8 changed files with 92 additions and 15 deletions

View File

@ -11,6 +11,7 @@ max_fps=60 # max fps for updates of config & animations
layout=0 # 0 - dwindle (default), 1 - master layout=0 # 0 - dwindle (default), 1 - master
focus_when_hover=1 # 0 - do not switch the focus when hover (only for tiling) focus_when_hover=1 # 0 - do not switch the focus when hover (only for tiling)
main_mod=SUPER # For moving, resizing main_mod=SUPER # For moving, resizing
intelligent_transients=1 # keeps transients always on top.
# Execs # Execs

View File

@ -15,6 +15,7 @@ void ConfigManager::init() {
configValues["gaps_out"].intValue = 20; configValues["gaps_out"].intValue = 20;
configValues["rounding"].intValue = 5; configValues["rounding"].intValue = 5;
configValues["main_mod"].strValue = "SUPER"; configValues["main_mod"].strValue = "SUPER";
configValues["intelligent_transients"].intValue = 1;
configValues["focus_when_hover"].intValue = 1; configValues["focus_when_hover"].intValue = 1;

View File

@ -303,9 +303,6 @@ CWindow* Events::remapFloatingWindow(int windowID, int forcemonitor) {
g_pWindowManager->Values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; g_pWindowManager->Values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE;
xcb_change_window_attributes_checked(g_pWindowManager->DisplayConnection, windowID, XCB_CW_EVENT_MASK, g_pWindowManager->Values); xcb_change_window_attributes_checked(g_pWindowManager->DisplayConnection, windowID, XCB_CW_EVENT_MASK, g_pWindowManager->Values);
// Make all floating windows above
g_pWindowManager->setAllFloatingWindowsTop();
// Fix docks // Fix docks
if (window.getDock()) if (window.getDock())
g_pWindowManager->recalcAllDocks(); g_pWindowManager->recalcAllDocks();
@ -432,9 +429,6 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
// Focus // Focus
g_pWindowManager->setFocusedWindow(windowID); g_pWindowManager->setFocusedWindow(windowID);
// Make all floating windows above
g_pWindowManager->setAllFloatingWindowsTop();
return PWINDOWINARR; return PWINDOWINARR;
} }
@ -481,6 +475,12 @@ void Events::eventMapWindow(xcb_generic_event_t* event) {
// Do ICCCM // Do ICCCM
g_pWindowManager->getICCCMWMProtocols(pNewWindow); g_pWindowManager->getICCCMWMProtocols(pNewWindow);
// Do transient checks
EWMH::checkTransient(E->window);
// Make all floating windows above
g_pWindowManager->setAllFloatingWindowsTop();
// Set not under // Set not under
pNewWindow->setUnderFullscreen(false); pNewWindow->setUnderFullscreen(false);
pNewWindow->setDirty(true); pNewWindow->setDirty(true);

View File

@ -128,4 +128,43 @@ void EWMH::updateWindow(xcb_window_t win) {
long data[] = {XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE}; long data[] = {XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE};
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, win, HYPRATOMS["WM_STATE"], HYPRATOMS["WM_STATE"], 32, 2, data); xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, win, HYPRATOMS["WM_STATE"], HYPRATOMS["WM_STATE"], 32, 2, data);
} }
}
void EWMH::checkTransient(xcb_window_t window) {
const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(window);
if (!PWINDOW)
return;
// Check if it's a transient
const auto TRANSIENTCOOKIE = xcb_get_property(g_pWindowManager->DisplayConnection, false, window, 68 /* TRANSIENT_FOR */, XCB_GET_PROPERTY_TYPE_ANY, 0, UINT32_MAX);
const auto TRANSIENTREPLY = xcb_get_property_reply(g_pWindowManager->DisplayConnection, TRANSIENTCOOKIE, NULL);
if (!TRANSIENTREPLY || xcb_get_property_value_length(TRANSIENTREPLY) == 0) {
Debug::log(WARN, "Transient check failed.");
return;
}
xcb_window_t transientWindow;
if (!xcb_icccm_get_wm_transient_for_from_reply(&transientWindow, TRANSIENTREPLY)) {
Debug::log(WARN, "Transient reply failed.");
free(TRANSIENTREPLY);
return;
}
// set the flags
const auto PPARENTWINDOW = g_pWindowManager->getWindowFromDrawable(transientWindow);
if (!PPARENTWINDOW) {
free(TRANSIENTREPLY);
Debug::log(LOG, "Transient set for a nonexistent window, ignoring.");
return;
}
PPARENTWINDOW->addTransientChild(window);
Debug::log(LOG, "Added a transient child to " + std::to_string(transientWindow) + ".");
free(TRANSIENTREPLY);
} }

View File

@ -10,6 +10,7 @@ namespace EWMH {
void setFrameExtents(xcb_window_t); void setFrameExtents(xcb_window_t);
void refreshAllExtents(); void refreshAllExtents();
void updateDesktops(); void updateDesktops();
void checkTransient(xcb_window_t);
namespace DesktopInfo { namespace DesktopInfo {
inline int lastid = 0; inline int lastid = 0;

View File

@ -1,7 +1,7 @@
#include "window.hpp" #include "window.hpp"
#include "windowManager.hpp" #include "windowManager.hpp"
CWindow::CWindow() { this->setLastUpdatePosition(Vector2D(0,0)); this->setLastUpdateSize(Vector2D(0,0)); this->setDock(false); this->setUnderFullscreen(false); this->setIsSleeping(true); this->setFirstAnimFrame(true); this->setIsAnimated(false); this->setDead(false); this->setMasterChildIndex(0); this->setMaster(false); this->setCanKill(false); this->setImmovable(false); this->setNoInterventions(false); this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); this->setName(""); } CWindow::CWindow() { this->setTransient(false); this->setLastUpdatePosition(Vector2D(0,0)); this->setLastUpdateSize(Vector2D(0,0)); this->setDock(false); this->setUnderFullscreen(false); this->setIsSleeping(true); this->setFirstAnimFrame(true); this->setIsAnimated(false); this->setDead(false); this->setMasterChildIndex(0); this->setMaster(false); this->setCanKill(false); this->setImmovable(false); this->setNoInterventions(false); this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); this->setName(""); }
CWindow::~CWindow() { } CWindow::~CWindow() { }
void CWindow::generateNodeID() { void CWindow::generateNodeID() {
@ -45,4 +45,30 @@ void CWindow::recalcSizePosRecursive() {
g_pWindowManager->getWindowFromDrawable(m_iChildNodeBID)->recalcSizePosRecursive(); g_pWindowManager->getWindowFromDrawable(m_iChildNodeBID)->recalcSizePosRecursive();
} }
} }
}
void CWindow::bringTopRecursiveTransients() {
// check if its enabled
if (ConfigManager::getInt("intelligent_transients") != 1)
return;
// first top all the children if floating
for (auto& c : m_vecChildren) {
if (const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(c); PWINDOW) {
if (PWINDOW->getIsFloating())
g_pWindowManager->setAWindowTop(c);
}
}
// THEN top their children
for (auto& c : m_vecChildren) {
if (const auto PCHILD = g_pWindowManager->getWindowFromDrawable(c); PCHILD) {
// recurse
PCHILD->bringTopRecursiveTransients();
}
}
}
void CWindow::addTransientChild(xcb_window_t w) {
m_vecChildren.push_back(w);
} }

View File

@ -39,7 +39,9 @@ public:
// Tells the window manager to reload the window's params // Tells the window manager to reload the window's params
EXPOSED_MEMBER(Dirty, bool, b); EXPOSED_MEMBER(Dirty, bool, b);
void bringTopRecursiveTransients();
void setDirtyRecursive(bool); void setDirtyRecursive(bool);
void addTransientChild(xcb_drawable_t);
// ONLY for dwindle layout! // ONLY for dwindle layout!
void recalcSizePosRecursive(); void recalcSizePosRecursive();
@ -95,7 +97,9 @@ public:
EXPOSED_MEMBER(Dock, bool, b); EXPOSED_MEMBER(Dock, bool, b);
EXPOSED_MEMBER(DockAlign, EDockAlign, e); EXPOSED_MEMBER(DockAlign, EDockAlign, e);
// todo: Transients // Transient
EXPOSED_MEMBER(Children, std::vector<int64_t>, vec);
EXPOSED_MEMBER(Transient, bool, b);
private: private:

View File

@ -460,11 +460,6 @@ void CWindowManager::setFocusedWindow(xcb_drawable_t window) {
float values[1]; float values[1];
if (const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(window); PWINDOW) { if (const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(window); PWINDOW) {
if (PWINDOW->getIsFloating()) {
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window(g_pWindowManager->DisplayConnection, window, XCB_CONFIG_WINDOW_STACK_MODE, values);
}
// Apply rounded corners, does all the checks inside. // Apply rounded corners, does all the checks inside.
// The border changed so let's not make it rectangular maybe // The border changed so let's not make it rectangular maybe
applyShapeToWindow(PWINDOW); applyShapeToWindow(PWINDOW);
@ -472,9 +467,15 @@ void CWindowManager::setFocusedWindow(xcb_drawable_t window) {
LastWindow = window; LastWindow = window;
if (g_pWindowManager->getWindowFromDrawable(window)) const auto PNEWFOCUS = g_pWindowManager->getWindowFromDrawable(window);
if (PNEWFOCUS) {
applyShapeToWindow(g_pWindowManager->getWindowFromDrawable(window)); applyShapeToWindow(g_pWindowManager->getWindowFromDrawable(window));
// Transients
PNEWFOCUS->bringTopRecursiveTransients();
}
// set focus in X11 // set focus in X11
xcb_set_input_focus(DisplayConnection, XCB_INPUT_FOCUS_POINTER_ROOT, window, XCB_CURRENT_TIME); xcb_set_input_focus(DisplayConnection, XCB_INPUT_FOCUS_POINTER_ROOT, window, XCB_CURRENT_TIME);
@ -1557,9 +1558,13 @@ void CWindowManager::updateBarInfo() {
void CWindowManager::setAllFloatingWindowsTop() { void CWindowManager::setAllFloatingWindowsTop() {
for (auto& window : windows) { for (auto& window : windows) {
if (window.getIsFloating()) { if (window.getIsFloating() && !window.getTransient()) {
Values[0] = XCB_STACK_MODE_ABOVE; Values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window(g_pWindowManager->DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_STACK_MODE, Values); xcb_configure_window(g_pWindowManager->DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_STACK_MODE, Values);
window.bringTopRecursiveTransients();
} else if (window.getChildren().size() > 0) {
window.bringTopRecursiveTransients();
} }
} }
} }