1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
diff --git a/README.md b/README.md
index c5e6492..7cddb47 100644
--- a/README.md
+++ b/README.md
@@ -190,3 +190,16 @@ See the [Configuration] document for information on the options.
## Running
Run [`wayfire`][Manual] from a TTY, or via a Wayland-compatible login manager.
+
+
+## 0.11.0-r78 (Hedron Sprint 3)
+
+The launcher selects the optional Hedron-owned seed for new accounts, preserving
+existing configs and the Wayfire fallback. Versioned launcher/desktop/helper
+inputs leave older ebuilds unchanged. Compatibility helpers prefer Hedron and
+fall back to legacy implementations. Login says Hedronfire; DesktopNames=Wayfire
+stays. No dependency on the shell is introduced.
+
+`wayfire/exit` schedules shutdown of this compositor after its response, with
+core/exit's inhibited-output guard. Config monitoring follows atomically
+replaced symlink targets again.
diff --git a/plugins/ipc/ipc.cpp b/plugins/ipc/ipc.cpp
index fd4f63f..3c12577 100644
--- a/plugins/ipc/ipc.cpp
+++ b/plugins/ipc/ipc.cpp
@@ -3,6 +3,9 @@
#include <climits>
#include <wayfire/util/log.hpp>
#include <wayfire/core.hpp>
+#include <wayfire/seat.hpp>
+#include <wayfire/output.hpp>
+#include <wayfire/plugins/ipc/ipc-helpers.hpp>
#include <wayfire/plugin.hpp>
#include <fcntl.h>
@@ -406,6 +409,8 @@ class ipc_plugin_t : public wf::plugin_interface_t
{
private:
shared_data::ref_ptr_t<ipc::server_t> server;
+ shared_data::ref_ptr_t<ipc::method_repository_t> methods;
+ wl_event_source* exit_idle = nullptr;
public:
void init() override
@@ -429,6 +434,29 @@ class ipc_plugin_t : public wf::plugin_interface_t
setenv("WAYFIRE_SOCKET", socket.c_str(), 1);
server->init(socket);
+ // Graceful logout is scoped to this IPC server's compositor. Defer
+ // shutdown until the response is sent; preserve core/exit's lock guard.
+ methods->register_method("wayfire/exit", [this] (const wf::json_t&)
+ {
+ auto output = wf::get_core().seat->get_active_output();
+ if (!output || output->is_inhibited()) return ipc::json_error("Session is inhibited");
+ if (!exit_idle) exit_idle = wl_event_loop_add_idle(wl_display_get_event_loop(wf::get_core().display),
+ [] (void* data)
+ {
+ auto self = static_cast<ipc_plugin_t*>(data);
+ self->exit_idle = nullptr;
+ auto output = wf::get_core().seat->get_active_output();
+ if (output && !output->is_inhibited()) wf::get_core().shutdown();
+ }, this);
+ return exit_idle ? ipc::json_ok() : ipc::json_error("Cannot schedule logout");
+ });
+ }
+
+ void fini() override
+ {
+ methods->unregister_method("wayfire/exit");
+ if (exit_idle) wl_event_source_remove(exit_idle);
+ exit_idle = nullptr;
}
bool is_unloadable() override
diff --git a/src/default-config-backend.cpp b/src/default-config-backend.cpp
index fb5b287..4b89ddf 100644
--- a/src/default-config-backend.cpp
+++ b/src/default-config-backend.cpp
@@ -23,7 +23,7 @@ static int wd_cfg_dir, wd_cfg_file;
static void add_watch(int fd)
{
wd_cfg_dir = inotify_add_watch(fd, config_dir.c_str(), IN_CREATE | IN_MOVED_TO);
- wd_cfg_file = inotify_add_watch(fd, config_file.c_str(), IN_CLOSE_WRITE);
+ wd_cfg_file = inotify_add_watch(fd, config_file.c_str(), IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MOVE_SELF);
}
static const char *CONFIG_FILE_ENV = "WAYFIRE_CONFIG_FILE";
@@ -189,7 +189,17 @@ static int handle_config_updated(int fd, uint32_t mask, void *data)
// We reload in two cases:
//
// 1. The config file itself was modified, or...
- should_reload |= event->wd == wd_cfg_file;
+ if (event->wd == wd_cfg_file)
+ {
+ should_reload = true;
+ // Atomic saves may replace a symlink's target in a different
+ // directory. Follow the configured path again after replacement.
+ if (event->mask & (IN_DELETE_SELF | IN_MOVE_SELF))
+ {
+ if (!(event->mask & IN_DELETE_SELF)) inotify_rm_watch(fd, wd_cfg_file);
+ wd_cfg_file = inotify_add_watch(fd, config_file.c_str(), IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MOVE_SELF);
+ }
+ }
// 2. The config file was moved nto or created inside the parent directory.
if (event->len > 0)
{
@@ -200,7 +210,7 @@ static int handle_config_updated(int fd, uint32_t mask, void *data)
{
inotify_rm_watch(fd, wd_cfg_file);
wd_cfg_file =
- inotify_add_watch(fd, (config_dir + "/" + cfg_file_basename).c_str(), IN_CLOSE_WRITE);
+ inotify_add_watch(fd, (config_dir + "/" + cfg_file_basename).c_str(), IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MOVE_SELF);
}
should_reload |= name_matches;
|