Skip to content

Commit 37850e2

Browse files
committed
notifications: added manual offsetX and offsetY + fixed surface not being destroyed when the last notification disappear
1 parent 5b2f5c7 commit 37850e2

6 files changed

Lines changed: 53 additions & 13 deletions

File tree

assets/translations/en.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,6 +1906,14 @@
19061906
"label": "Toast Opacity",
19071907
"description": "Background opacity of notification toasts"
19081908
},
1909+
"offset-x": {
1910+
"label": "Horizontal Offset",
1911+
"description": "Extra horizontal offset from the screen edge"
1912+
},
1913+
"offset-y": {
1914+
"label": "Vertical Offset",
1915+
"description": "Extra vertical offset from the screen edge"
1916+
},
19091917
"monitors": {
19101918
"label": "Displays",
19111919
"description": "Choose which displays show notification toasts; leave empty to show on all displays"

src/config/config_overrides.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ namespace {
318318

319319
bool notificationConfigEqual(const NotificationConfig& a, const NotificationConfig& b) {
320320
return a.enableDaemon == b.enableDaemon && a.position == b.position && a.layer == b.layer &&
321-
nearlyEqual(a.backgroundOpacity, b.backgroundOpacity) && a.monitors == b.monitors;
321+
nearlyEqual(a.backgroundOpacity, b.backgroundOpacity) && a.offsetX == b.offsetX && a.offsetY == b.offsetY &&
322+
a.monitors == b.monitors;
322323
}
323324

324325
bool audioConfigEqual(const AudioConfig& a, const AudioConfig& b) {

src/config/config_service.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,10 @@ void ConfigService::parseTableInto(const toml::table& tbl, Config& config, bool
14611461
notif.layer = *v;
14621462
if (auto v = notifTable["background_opacity"].value<double>())
14631463
notif.backgroundOpacity = std::clamp(static_cast<float>(*v), 0.0f, 1.0f);
1464+
if (auto v = notifTable["offset_x"].value<int64_t>())
1465+
notif.offsetX = static_cast<int>(*v);
1466+
if (auto v = notifTable["offset_y"].value<int64_t>())
1467+
notif.offsetY = static_cast<int>(*v);
14641468
if (const auto* v = notifTable.get("monitors")) {
14651469
notif.monitors = readStringArray(*v);
14661470
}

src/config/config_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,8 @@ struct NotificationConfig {
358358
std::string position = "top_right";
359359
std::string layer = "top"; // top | overlay
360360
float backgroundOpacity = 0.97f; // toast card background alpha (0.0–1.0)
361+
int offsetX = 0;
362+
int offsetY = 0;
361363
std::vector<std::string> monitors;
362364
};
363365

src/shell/notification/notification_toast.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -896,18 +896,16 @@ void NotificationToast::dismissCardFromInstance(Instance& inst, std::size_t entr
896896
const float targetY = card->y();
897897
const uint32_t removingId = (entryIndex < m_entries.size()) ? m_entries[entryIndex].notificationId : 0;
898898

899-
// Only the first instance drives finishRemoval
900-
bool isDriver = (m_instances.size() > 0 && m_instances[0].get() == &inst);
901899
cs.exitAnimId = inst.animations.animate(
902900
startReveal, 0.0f, Style::animNormal, Easing::EaseInOutQuad,
903901
[this, card, content, foreground, targetY](float v) {
904902
applyCardRevealNodes(card, content, foreground, v, targetY, revealFromLeftEdge());
905903
},
906-
[this, &inst, entryIndex, isDriver, removingId]() {
904+
[this, &inst, entryIndex, removingId]() {
907905
if (entryIndex < inst.cards.size()) {
908906
inst.cards[entryIndex].exitAnimId = 0;
909907
}
910-
if (isDriver && removingId != 0) {
908+
if (removingId != 0) {
911909
DeferredCall::callLater([this, removingId]() { finishRemoval(removingId); });
912910
}
913911
},
@@ -1338,25 +1336,40 @@ void NotificationToast::ensureSurfaces() {
13381336
inst->output = output.output;
13391337
inst->scale = output.scale;
13401338

1339+
const auto& notifCfg = m_config->config().notification;
1340+
const int offX = notifCfg.offsetX;
1341+
const int offY = notifCfg.offsetY;
1342+
13411343
std::uint32_t anchor = LayerShellAnchor::Top | LayerShellAnchor::Bottom | LayerShellAnchor::Right;
13421344
std::int32_t marginTop = kSurfaceMargin;
13431345
std::int32_t marginRight = kSurfaceMargin;
13441346
std::int32_t marginBottom = kSurfaceMargin;
13451347
std::int32_t marginLeft = kSurfaceMargin;
1346-
if (position == "top_left") {
1348+
if (position == "top_right") {
1349+
marginTop += offY;
1350+
marginRight += offX;
1351+
} else if (position == "top_left") {
13471352
anchor = LayerShellAnchor::Top | LayerShellAnchor::Bottom | LayerShellAnchor::Left;
1353+
marginTop += offY;
1354+
marginLeft += offX;
13481355
} else if (position == "top_center") {
13491356
anchor = LayerShellAnchor::Top | LayerShellAnchor::Bottom;
1357+
marginTop += offY;
13501358
marginLeft = 0;
13511359
marginRight = 0;
1360+
} else if (position == "bottom_right") {
1361+
anchor = LayerShellAnchor::Top | LayerShellAnchor::Bottom | LayerShellAnchor::Right;
1362+
marginBottom += offY;
1363+
marginRight += offX;
13521364
} else if (position == "bottom_left") {
13531365
anchor = LayerShellAnchor::Top | LayerShellAnchor::Bottom | LayerShellAnchor::Left;
1366+
marginBottom += offY;
1367+
marginLeft += offX;
13541368
} else if (position == "bottom_center") {
13551369
anchor = LayerShellAnchor::Top | LayerShellAnchor::Bottom;
1370+
marginBottom += offY;
13561371
marginLeft = 0;
13571372
marginRight = 0;
1358-
} else if (position == "bottom_right") {
1359-
anchor = LayerShellAnchor::Top | LayerShellAnchor::Bottom | LayerShellAnchor::Right;
13601373
}
13611374

13621375
auto surfaceConfig = LayerSurfaceConfig{

src/shell/settings/settings_registry.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,12 @@ namespace settings {
10881088
tr("settings.schema.notifications.daemon.description"),
10891089
{"notification", "enable_daemon"}, ToggleSetting{cfg.notification.enableDaemon},
10901090
"dbus"));
1091+
entries.push_back(makeEntry(
1092+
"notifications", "toasts", tr("settings.schema.notifications.layer.label"),
1093+
tr("settings.schema.notifications.layer.description"), {"notification", "layer"},
1094+
asSegmented(plainSelect({{"top", "settings.options.layer.top"}, {"overlay", "settings.options.layer.overlay"}},
1095+
cfg.notification.layer)),
1096+
"toast layer shell z-order"));
10911097
entries.push_back(makeEntry("notifications", "toasts", tr("settings.schema.notifications.position.label"),
10921098
tr("settings.schema.notifications.position.description"), {"notification", "position"},
10931099
plainSelect({{"top_right", "settings.options.screen-position.top-right"},
@@ -1099,11 +1105,17 @@ namespace settings {
10991105
cfg.notification.position),
11001106
"toast popup placement anchor"));
11011107
entries.push_back(makeEntry(
1102-
"notifications", "toasts", tr("settings.schema.notifications.layer.label"),
1103-
tr("settings.schema.notifications.layer.description"), {"notification", "layer"},
1104-
asSegmented(plainSelect({{"top", "settings.options.layer.top"}, {"overlay", "settings.options.layer.overlay"}},
1105-
cfg.notification.layer)),
1106-
"toast layer shell z-order"));
1108+
"notifications", "toasts", tr("settings.schema.notifications.offset-x.label"),
1109+
tr("settings.schema.notifications.offset-x.description"), {"notification", "offset_x"},
1110+
StepperSetting{
1111+
.value = cfg.notification.offsetX, .minValue = 0, .maxValue = 200, .step = 1, .valueSuffix = "px"},
1112+
"offset margin horizontal"));
1113+
entries.push_back(makeEntry(
1114+
"notifications", "toasts", tr("settings.schema.notifications.offset-y.label"),
1115+
tr("settings.schema.notifications.offset-y.description"), {"notification", "offset_y"},
1116+
StepperSetting{
1117+
.value = cfg.notification.offsetY, .minValue = 0, .maxValue = 200, .step = 1, .valueSuffix = "px"},
1118+
"offset margin vertical"));
11071119
entries.push_back(makeEntry("notifications", "toasts", tr("settings.schema.notifications.toast-opacity.label"),
11081120
tr("settings.schema.notifications.toast-opacity.description"),
11091121
{"notification", "background_opacity"},

0 commit comments

Comments
 (0)