Merge branch 'hyprwm:main' into gowno

This commit is contained in:
Honkazel 2025-11-12 13:00:18 +05:00 committed by GitHub
commit c4af9d0ce5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 141 additions and 93 deletions

View file

@ -34,6 +34,17 @@ static bool checkFlag() {
return exists; return exists;
} }
static bool attemptCheckFlag(int attempts, int intervalMs) {
for (int i = 0; i < attempts; i++) {
if (checkFlag())
return true;
std::this_thread::sleep_for(std::chrono::milliseconds(intervalMs));
}
return false;
}
static std::string readKittyOutput() { static std::string readKittyOutput() {
std::string output = Tests::execAndGet("kitten @ --to unix:/tmp/hyprtester-kitty.sock get-text --extent all"); std::string output = Tests::execAndGet("kitten @ --to unix:/tmp/hyprtester-kitty.sock get-text --extent all");
// chop off shell prompt // chop off shell prompt
@ -443,6 +454,34 @@ static void testSubmap() {
Tests::killAllWindows(); Tests::killAllWindows();
} }
static void testSubmapUniversal() {
NLog::log("{}Testing submap universal", Colors::GREEN);
EXPECT(checkFlag(), false);
EXPECT(getFromSocket("/keyword bindu SUPER,Y,exec,touch " + flagFile), "ok");
EXPECT_CONTAINS(getFromSocket("/submap"), "default");
// keybind works on default submap
OK(getFromSocket("/dispatch plugin:test:keybind 1,7,29"));
OK(getFromSocket("/dispatch plugin:test:keybind 0,7,29"));
EXPECT(attemptCheckFlag(30, 5), true);
// keybind works on submap1
getFromSocket("/dispatch plugin:test:keybind 1,7,30");
getFromSocket("/dispatch plugin:test:keybind 0,7,30");
EXPECT_CONTAINS(getFromSocket("/submap"), "submap1");
OK(getFromSocket("/dispatch plugin:test:keybind 1,7,29"));
OK(getFromSocket("/dispatch plugin:test:keybind 0,7,29"));
EXPECT(attemptCheckFlag(30, 5), true);
// reset to default submap
getFromSocket("/dispatch plugin:test:keybind 1,0,33");
getFromSocket("/dispatch plugin:test:keybind 0,0,33");
EXPECT_CONTAINS(getFromSocket("/submap"), "default");
EXPECT(getFromSocket("/keyword unbind SUPER,Y"), "ok");
}
static bool test() { static bool test() {
NLog::log("{}Testing keybinds", Colors::GREEN); NLog::log("{}Testing keybinds", Colors::GREEN);
@ -462,8 +501,8 @@ static bool test() {
testShortcutLongPressKeyRelease(); testShortcutLongPressKeyRelease();
testShortcutRepeat(); testShortcutRepeat();
testShortcutRepeatKeyRelease(); testShortcutRepeatKeyRelease();
testSubmap(); testSubmap();
testSubmapUniversal();
clearFlag(); clearFlag();
return !ret; return !ret;

View file

@ -2539,52 +2539,45 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
// bind[fl]=SUPER,G,exec,dmenu_run <args> // bind[fl]=SUPER,G,exec,dmenu_run <args>
// flags // flags
bool locked = false; bool locked = false;
bool release = false; bool release = false;
bool repeat = false; bool repeat = false;
bool mouse = false; bool mouse = false;
bool nonConsuming = false; bool nonConsuming = false;
bool transparent = false; bool transparent = false;
bool ignoreMods = false; bool ignoreMods = false;
bool multiKey = false; bool multiKey = false;
bool longPress = false; bool longPress = false;
bool hasDescription = false; bool hasDescription = false;
bool dontInhibit = false; bool dontInhibit = false;
bool click = false; bool click = false;
bool drag = false; bool drag = false;
const auto BINDARGS = command.substr(4); bool submapUniversal = false;
const auto BINDARGS = command.substr(4);
for (auto const& arg : BINDARGS) { for (auto const& arg : BINDARGS) {
if (arg == 'l') { switch (arg) {
locked = true; case 'l': locked = true; break;
} else if (arg == 'r') { case 'r': release = true; break;
release = true; case 'e': repeat = true; break;
} else if (arg == 'e') { case 'm': mouse = true; break;
repeat = true; case 'n': nonConsuming = true; break;
} else if (arg == 'm') { case 't': transparent = true; break;
mouse = true; case 'i': ignoreMods = true; break;
} else if (arg == 'n') { case 's': multiKey = true; break;
nonConsuming = true; case 'o': longPress = true; break;
} else if (arg == 't') { case 'd': hasDescription = true; break;
transparent = true; case 'p': dontInhibit = true; break;
} else if (arg == 'i') { case 'c':
ignoreMods = true; click = true;
} else if (arg == 's') { release = true;
multiKey = true; break;
} else if (arg == 'o') { case 'g':
longPress = true; drag = true;
} else if (arg == 'd') { release = true;
hasDescription = true; break;
} else if (arg == 'p') { case 'u': submapUniversal = true; break;
dontInhibit = true; default: return "bind: invalid flag";
} else if (arg == 'c') {
click = true;
release = true;
} else if (arg == 'g') {
drag = true;
release = true;
} else {
return "bind: invalid flag";
} }
} }
@ -2657,7 +2650,7 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER, g_pKeybindManager->addKeybind(SKeybind{parsedKey.key, KEYSYMS, parsedKey.keycode, parsedKey.catchAll, MOD, MODS, HANDLER,
COMMAND, locked, m_currentSubmap, DESCRIPTION, release, repeat, longPress, COMMAND, locked, m_currentSubmap, DESCRIPTION, release, repeat, longPress,
mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit, mouse, nonConsuming, transparent, ignoreMods, multiKey, hasDescription, dontInhibit,
click, drag}); click, drag, submapUniversal});
} }
return {}; return {};

View file

@ -1025,6 +1025,7 @@ static std::string bindsRequest(eHyprCtlOutputFormat format, std::string request
"has_description": {}, "has_description": {},
"modmask": {}, "modmask": {},
"submap": "{}", "submap": "{}",
"submap_universal": "{}",
"key": "{}", "key": "{}",
"keycode": {}, "keycode": {},
"catch_all": {}, "catch_all": {},
@ -1033,8 +1034,9 @@ static std::string bindsRequest(eHyprCtlOutputFormat format, std::string request
"arg": "{}" "arg": "{}"
}},)#", }},)#",
kb->locked ? "true" : "false", kb->mouse ? "true" : "false", kb->release ? "true" : "false", kb->repeat ? "true" : "false", kb->longPress ? "true" : "false", kb->locked ? "true" : "false", kb->mouse ? "true" : "false", kb->release ? "true" : "false", kb->repeat ? "true" : "false", kb->longPress ? "true" : "false",
kb->nonConsuming ? "true" : "false", kb->hasDescription ? "true" : "false", kb->modmask, escapeJSONStrings(kb->submap.name), escapeJSONStrings(kb->key), kb->nonConsuming ? "true" : "false", kb->hasDescription ? "true" : "false", kb->modmask, escapeJSONStrings(kb->submap.name), kb->submapUniversal,
kb->keycode, kb->catchAll ? "true" : "false", escapeJSONStrings(kb->description), escapeJSONStrings(kb->handler), escapeJSONStrings(kb->arg)); escapeJSONStrings(kb->key), kb->keycode, kb->catchAll ? "true" : "false", escapeJSONStrings(kb->description), escapeJSONStrings(kb->handler),
escapeJSONStrings(kb->arg));
} }
trimTrailingComma(ret); trimTrailingComma(ret);
ret += "]"; ret += "]";

View file

@ -680,7 +680,7 @@ SDispatchResult CKeybindManager::handleKeybinds(const uint32_t modmask, const SP
if (!k->locked && g_pSessionLockManager->isSessionLocked()) if (!k->locked && g_pSessionLockManager->isSessionLocked())
continue; continue;
if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || k->submap != m_currentSelectedSubmap || k->shadowed)) if (!IGNORECONDITIONS && ((modmask != k->modmask && !k->ignoreMods) || (k->submap != m_currentSelectedSubmap && !k->submapUniversal) || k->shadowed))
continue; continue;
if (k->multiKey) { if (k->multiKey) {

View file

@ -26,29 +26,30 @@ struct SSubmap {
}; };
struct SKeybind { struct SKeybind {
std::string key = ""; std::string key = "";
std::set<xkb_keysym_t> sMkKeys = {}; std::set<xkb_keysym_t> sMkKeys = {};
uint32_t keycode = 0; uint32_t keycode = 0;
bool catchAll = false; bool catchAll = false;
uint32_t modmask = 0; uint32_t modmask = 0;
std::set<xkb_keysym_t> sMkMods = {}; std::set<xkb_keysym_t> sMkMods = {};
std::string handler = ""; std::string handler = "";
std::string arg = ""; std::string arg = "";
bool locked = false; bool locked = false;
SSubmap submap = {}; SSubmap submap = {};
std::string description = ""; std::string description = "";
bool release = false; bool release = false;
bool repeat = false; bool repeat = false;
bool longPress = false; bool longPress = false;
bool mouse = false; bool mouse = false;
bool nonConsuming = false; bool nonConsuming = false;
bool transparent = false; bool transparent = false;
bool ignoreMods = false; bool ignoreMods = false;
bool multiKey = false; bool multiKey = false;
bool hasDescription = false; bool hasDescription = false;
bool dontInhibit = false; bool dontInhibit = false;
bool click = false; bool click = false;
bool drag = false; bool drag = false;
bool submapUniversal = false;
// DO NOT INITIALIZE // DO NOT INITIALIZE
bool shadowed = false; bool shadowed = false;

View file

@ -120,11 +120,18 @@ void CInputPopup::updateBox() {
CBox cursorBoxLocal({-popupOffset.x, -popupOffset.y}, cursorBoxParent.size()); CBox cursorBoxLocal({-popupOffset.x, -popupOffset.y}, cursorBoxParent.size());
m_popup->sendInputRectangle(cursorBoxLocal); m_popup->sendInputRectangle(cursorBoxLocal);
CBox popupBoxParent(cursorBoxParent.pos() + popupOffset, currentPopupSize); CBox popupBoxParent(cursorBoxParent.pos() + popupOffset, currentPopupSize);
if (popupBoxParent != m_lastBoxLocal) { const bool boxChanged = popupBoxParent != m_lastBoxLocal;
if (boxChanged)
damageEntire(); // damage the old location before updating
m_lastBoxLocal = popupBoxParent;
// Since a redraw request is not always sent when only the position is updated,
// a manual redraw may be required in some cases.
if (boxChanged)
damageEntire(); damageEntire();
m_lastBoxLocal = popupBoxParent;
}
damageSurface(); damageSurface();
if (const auto PM = g_pCompositor->getMonitorFromCursor(); PM && PM->m_id != m_lastMonitor) { if (const auto PM = g_pCompositor->getMonitorFromCursor(); PM && PM->m_id != m_lastMonitor) {

View file

@ -211,6 +211,24 @@ void CScreencopyFrame::renderMon() {
g_pHyprOpenGL->setRenderModifEnabled(true); g_pHyprOpenGL->setRenderModifEnabled(true);
g_pHyprOpenGL->popMonitorTransformEnabled(); g_pHyprOpenGL->popMonitorTransformEnabled();
auto hidePopups = [&](Vector2D popupBaseOffset) {
return [&, popupBaseOffset](WP<CPopup> popup, void*) {
if (!popup->m_wlSurface || !popup->m_wlSurface->resource() || !popup->m_mapped)
return;
const auto popRel = popup->coordsRelativeToParent();
popup->m_wlSurface->resource()->breadthfirst(
[&](SP<CWLSurfaceResource> surf, const Vector2D& localOff, void*) {
const auto size = surf->m_current.size;
const auto surfBox = CBox{popupBaseOffset + popRel + localOff, size}.translate(m_monitor->m_position).scale(m_monitor->m_scale).translate(-m_box.pos());
if LIKELY (surfBox.w > 0 && surfBox.h > 0)
g_pHyprOpenGL->renderRect(surfBox, Colors::BLACK, {});
},
nullptr);
};
};
for (auto const& l : g_pCompositor->m_layers) { for (auto const& l : g_pCompositor->m_layers) {
if (!l->m_noScreenShare) if (!l->m_noScreenShare)
continue; continue;
@ -225,6 +243,10 @@ void CScreencopyFrame::renderMon() {
CBox{REALPOS.x, REALPOS.y, std::max(REALSIZE.x, 5.0), std::max(REALSIZE.y, 5.0)}.translate(-m_monitor->m_position).scale(m_monitor->m_scale).translate(-m_box.pos()); CBox{REALPOS.x, REALPOS.y, std::max(REALSIZE.x, 5.0), std::max(REALSIZE.y, 5.0)}.translate(-m_monitor->m_position).scale(m_monitor->m_scale).translate(-m_box.pos());
g_pHyprOpenGL->renderRect(noScreenShareBox, Colors::BLACK, {}); g_pHyprOpenGL->renderRect(noScreenShareBox, Colors::BLACK, {});
const auto geom = l->m_geometry;
const Vector2D popupBaseOffset = REALPOS - Vector2D{geom.pos().x, geom.pos().y};
l->m_popupHead->breadthfirst(hidePopups(popupBaseOffset), nullptr);
} }
for (auto const& w : g_pCompositor->m_windows) { for (auto const& w : g_pCompositor->m_windows) {
@ -261,23 +283,7 @@ void CScreencopyFrame::renderMon() {
const auto geom = w->m_xdgSurface->m_current.geometry; const auto geom = w->m_xdgSurface->m_current.geometry;
const Vector2D popupBaseOffset = REALPOS - Vector2D{geom.pos().x, geom.pos().y}; const Vector2D popupBaseOffset = REALPOS - Vector2D{geom.pos().x, geom.pos().y};
w->m_popupHead->breadthfirst( w->m_popupHead->breadthfirst(hidePopups(popupBaseOffset), nullptr);
[&](WP<CPopup> popup, void*) {
if (!popup->m_wlSurface || !popup->m_wlSurface->resource() || !popup->m_mapped)
return;
const auto popRel = popup->coordsRelativeToParent();
popup->m_wlSurface->resource()->breadthfirst(
[&](SP<CWLSurfaceResource> surf, const Vector2D& localOff, void*) {
const auto size = surf->m_current.size;
const auto surfBox = CBox{popupBaseOffset + popRel + localOff, size}.translate(-m_monitor->m_position).scale(m_monitor->m_scale).translate(-m_box.pos());
if LIKELY (surfBox.w > 0 && surfBox.h > 0)
g_pHyprOpenGL->renderRect(surfBox, Colors::BLACK, {});
},
nullptr);
},
nullptr);
} }
if (m_overlayCursor) if (m_overlayCursor)