mirror of
https://github.com/hyprwm/Hypr.git
synced 2024-11-22 13:35:57 +01:00
added intelligent transients
This commit is contained in:
parent
786fa73c8c
commit
1421d42cae
8 changed files with 92 additions and 15 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -129,3 +129,42 @@ void EWMH::updateWindow(xcb_window_t win) {
|
||||||
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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
@ -46,3 +46,29 @@ void CWindow::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);
|
||||||
|
}
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue