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
focus_when_hover=1 # 0 - do not switch the focus when hover (only for tiling)
main_mod=SUPER # For moving, resizing
intelligent_transients=1 # keeps transients always on top.
# Execs

View File

@ -15,6 +15,7 @@ void ConfigManager::init() {
configValues["gaps_out"].intValue = 20;
configValues["rounding"].intValue = 5;
configValues["main_mod"].strValue = "SUPER";
configValues["intelligent_transients"].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;
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
if (window.getDock())
g_pWindowManager->recalcAllDocks();
@ -432,9 +429,6 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
// Focus
g_pWindowManager->setFocusedWindow(windowID);
// Make all floating windows above
g_pWindowManager->setAllFloatingWindowsTop();
return PWINDOWINARR;
}
@ -481,6 +475,12 @@ void Events::eventMapWindow(xcb_generic_event_t* event) {
// Do ICCCM
g_pWindowManager->getICCCMWMProtocols(pNewWindow);
// Do transient checks
EWMH::checkTransient(E->window);
// Make all floating windows above
g_pWindowManager->setAllFloatingWindowsTop();
// Set not under
pNewWindow->setUnderFullscreen(false);
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};
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 refreshAllExtents();
void updateDesktops();
void checkTransient(xcb_window_t);
namespace DesktopInfo {
inline int lastid = 0;

View File

@ -1,7 +1,7 @@
#include "window.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() { }
void CWindow::generateNodeID() {
@ -45,4 +45,30 @@ void CWindow::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
EXPOSED_MEMBER(Dirty, bool, b);
void bringTopRecursiveTransients();
void setDirtyRecursive(bool);
void addTransientChild(xcb_drawable_t);
// ONLY for dwindle layout!
void recalcSizePosRecursive();
@ -95,7 +97,9 @@ public:
EXPOSED_MEMBER(Dock, bool, b);
EXPOSED_MEMBER(DockAlign, EDockAlign, e);
// todo: Transients
// Transient
EXPOSED_MEMBER(Children, std::vector<int64_t>, vec);
EXPOSED_MEMBER(Transient, bool, b);
private:

View File

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