|
6 | 6 | #include <glibmm/spawn.h> |
7 | 7 | #include <iostream> |
8 | 8 | #include <gtk4-layer-shell.h> |
| 9 | +#include <sys/wait.h> |
9 | 10 |
|
10 | 11 | #include "menu.hpp" |
11 | 12 | #include "gtk-utils.hpp" |
@@ -189,6 +190,45 @@ void WfMenuCategoryButton::on_click() |
189 | 190 | menu->set_category(category); |
190 | 191 | } |
191 | 192 |
|
| 193 | +/* Double forks to launch the grandchild as a child of PID 1. */ |
| 194 | +void double_fork(const std::function<void()>& action) |
| 195 | +{ |
| 196 | + pid_t pid = fork(); |
| 197 | + if (pid < 0) |
| 198 | + { |
| 199 | + return; /* Failed */ |
| 200 | + } |
| 201 | + |
| 202 | + if (pid > 0) |
| 203 | + { |
| 204 | + /* Main process. Wait briefly for the intermediate child to clean up and exit */ |
| 205 | + waitpid(pid, nullptr, 0); |
| 206 | + return; |
| 207 | + } |
| 208 | + |
| 209 | + /*Intermediate child process. Disavow parent */ |
| 210 | + setsid(); |
| 211 | + |
| 212 | + pid_t grandchild_pid = fork(); |
| 213 | + if (grandchild_pid < 0) |
| 214 | + { |
| 215 | + _exit(EXIT_FAILURE); /* Failed */ |
| 216 | + } |
| 217 | + |
| 218 | + if (grandchild_pid > 0) |
| 219 | + { |
| 220 | + _exit(EXIT_SUCCESS); /* Intermediate child ends, disavowing parent and child */ |
| 221 | + } |
| 222 | + |
| 223 | + /* End child process, perform action */ |
| 224 | + try { |
| 225 | + action(); |
| 226 | + } catch (...) |
| 227 | + {} |
| 228 | + |
| 229 | + _exit(EXIT_SUCCESS); |
| 230 | +} |
| 231 | + |
192 | 232 | WfMenuItem::WfMenuItem(WayfireMenu *_menu, Glib::RefPtr<Gio::DesktopAppInfo> app) : |
193 | 233 | Gtk::FlowBoxChild(), menu(_menu), app_info(app) |
194 | 234 | { |
@@ -304,8 +344,11 @@ WfMenuItem::WfMenuItem(WayfireMenu *_menu, Glib::RefPtr<Gio::DesktopAppInfo> app |
304 | 344 | signals.push_back(action_obj->signal_activate().connect( |
305 | 345 | [this, action] (Glib::VariantBase vb) |
306 | 346 | { |
307 | | - auto ctx = Gdk::Display::get_default()->get_app_launch_context(); |
308 | | - app_info->launch_action(action, ctx); |
| 347 | + double_fork([this, action] () |
| 348 | + { |
| 349 | + auto context = Gio::AppLaunchContext::create(); |
| 350 | + app_info->launch_action(action, context); |
| 351 | + }); |
309 | 352 | menu->hide_menu(); |
310 | 353 | })); |
311 | 354 | m_menu->append_item(menu_item); |
@@ -337,8 +380,12 @@ WfMenuItem::~WfMenuItem() |
337 | 380 |
|
338 | 381 | void WfMenuItem::on_click() |
339 | 382 | { |
340 | | - auto ctx = Gdk::Display::get_default()->get_app_launch_context(); |
341 | | - app_info->launch(std::vector<Glib::RefPtr<Gio::File>>(), ctx); |
| 383 | + double_fork([this] () |
| 384 | + { |
| 385 | + auto context = Gio::AppLaunchContext::create(); |
| 386 | + std::vector<Glib::RefPtr<Gio::File>> no_files; |
| 387 | + app_info->launch(no_files, context); |
| 388 | + }); |
342 | 389 | menu->hide_menu(); |
343 | 390 | } |
344 | 391 |
|
|
0 commit comments