2323#include < string>
2424#include < thread>
2525#include < chrono>
26+ #include < vector>
2627
2728#include " dialogs.h"
2829
30+ #include " ../../../../CompilerSource/OS_Switchboard.h"
31+
2932#include " Widget_Systems/widgets_mandatory.h"
3033#include " Widget_Systems/General/WSdialogs.h"
3134
3235#include " Universal_System/estring.h"
3336#include " Platforms/General/PFwindow.h"
3437
35- #include < X11/Xlib.h>
36- #include < X11/Xatom.h>
37- #include < X11/Xutil.h>
38-
3938#include < sys/types.h>
4039#include < sys/wait.h>
4140#include < sys/stat.h>
4241
42+ #include < pthread.h>
4343#include < libgen.h>
4444#include < unistd.h>
4545#include < fcntl.h>
4646
47+ #include < X11/Xlib.h>
48+ #include < X11/Xatom.h>
49+ #include < X11/Xutil.h>
50+
51+ #if CURRENT_PLATFORM_ID == OS_MACOSX
52+ #include < sys/proc_info.h>
53+ #include < libproc.h>
54+ #elif CURRENT_PLATFORM_ID == OS_LINUX
55+ #include < proc/readproc.h>
56+ #elif CURRENT_PLATFORM_ID == OS_FREEBSD
57+ #include < sys/user.h>
58+ #include < libutil.h>
59+ #endif
60+
4761using std::string;
62+ using std::vector;
4863
4964namespace enigma {
5065
@@ -72,10 +87,10 @@ static bool kwin_running() {
7287 return bKWinRunning;
7388}
7489
75- static unsigned long get_wid_or_pid (Display *display, Window window, bool wid) {
90+ static unsigned long GetActiveWidOrWindowPid (Display *display, Window window, bool wid) {
7691 SetErrorHandlers ();
7792 unsigned char *prop;
78- unsigned long property;
93+ unsigned long property = 0 ;
7994 Atom actual_type, filter_atom;
8095 int actual_format, status;
8196 unsigned long nitems, bytes_after;
@@ -89,19 +104,19 @@ static unsigned long get_wid_or_pid(Display *display, Window window, bool wid) {
89104 return property;
90105}
91106
92- static Window wid_from_top (Display *display) {
107+ static Window WidFromTop (Display *display) {
93108 SetErrorHandlers ();
94109 int screen = XDefaultScreen (display);
95110 Window window = RootWindow (display, screen);
96- return (Window)get_wid_or_pid (display, window, true );
111+ return (Window)GetActiveWidOrWindowPid (display, window, true );
97112}
98113
99- static pid_t pid_from_wid (Display *display, Window window) {
100- return (pid_t )get_wid_or_pid (display, window, false );
114+ static pid_t PidFromWid (Display *display, Window window) {
115+ return (pid_t )GetActiveWidOrWindowPid (display, window, false );
101116}
102117
103118// create dialog process
104- static pid_t process_execute (const char *command, int *infp, int *outfp) {
119+ static pid_t ProcessCreate (const char *command, int *infp, int *outfp) {
105120 int p_stdin[2 ];
106121 int p_stdout[2 ];
107122 pid_t pid;
@@ -146,14 +161,79 @@ static pid_t process_execute(const char *command, int *infp, int *outfp) {
146161 return pid;
147162}
148163
149- // set dialog transient.
150- static void force_window_of_pid_to_be_transient (Display *display, pid_t pid) {
164+ #if CURRENT_PLATFORM_ID == OS_MACOSX
165+ static void PpidFromPid (pid_t procId, pid_t *parentProcId) {
166+ proc_bsdinfo proc_info;
167+ if (proc_pidinfo (procId, PROC_PIDTBSDINFO, 0 , &proc_info, sizeof (proc_info)) > 0 ) {
168+ *parentProcId = proc_info.pbi_ppid ;
169+ }
170+ }
171+ #endif
172+
173+ static std::vector<pid_t > PidFromPpid (pid_t parentProcId) {
174+ std::vector<pid_t > vec;
175+ #if CURRENT_PLATFORM_ID == OS_MACOSX
176+ int cntp = proc_listpids (PROC_ALL_PIDS, 0 , nullptr , 0 );
177+ std::vector<pid_t > proc_info (cntp);
178+ std::fill (proc_info.begin (), proc_info.end (), 0 );
179+ proc_listpids (PROC_ALL_PIDS, 0 , &proc_info[0 ], sizeof (pid_t ) * cntp);
180+ for (int j = cntp; j > 0 ; j--) {
181+ if (proc_info[j] == 0 ) { continue ; }
182+ pid_t ppid; PpidFromPid (proc_info[j], &ppid);
183+ if (ppid == parentProcId) {
184+ vec.push_back (proc_info[j]);
185+ }
186+ }
187+ #elif CURRENT_PLATFORM_ID == OS_LINUX
188+ PROCTAB *proc = openproc (PROC_FILLSTAT);
189+ while (proc_t *proc_info = readproc (proc, nullptr )) {
190+ if (proc_info->ppid == parentProcId) {
191+ vec.push_back (proc_info->tgid );
192+ }
193+ freeproc (proc_info);
194+ }
195+ closeproc (proc);
196+ #elif CURRENT_PLATFORM_ID == OS_FREEBSD
197+ int cntp; if (kinfo_proc *proc_info = kinfo_getallproc (&cntp)) {
198+ for (int j = 0 ; j < cntp; j++) {
199+ if (proc_info[j].ki_ppid == parentProcId) {
200+ vec.push_back (proc_info[j].ki_pid );
201+ }
202+ }
203+ free (proc_info);
204+ }
205+ #endif
206+ return vec;
207+ }
208+
209+ static pid_t PidFromPpidRecursive (pid_t parentProcId) {
210+ std::vector<pid_t > pidVec = PidFromPpid (parentProcId);
211+ if (pidVec.size ()) {
212+ parentProcId = PidFromPpidRecursive (pidVec[0 ]);
213+ }
214+ return parentProcId;
215+ }
216+
217+ // set dialog transient; set title caption.
218+ static void *modify_shell_dialog (void *pid) {
151219 SetErrorHandlers ();
152- Window wid = wid_from_top (display);
153- while (pid_from_wid (display, wid) != pid) {
154- wid = wid_from_top (display);
220+ Display *display = XOpenDisplay (nullptr ); Window wid;
221+ pid_t child = PidFromPpidRecursive ((pid_t )(std::intptr_t )pid);
222+ while (true ) {
223+ std::this_thread::sleep_for (std::chrono::milliseconds (5 ));
224+ wid = WidFromTop (display);
225+ if (PidFromWid (display, wid) == child) {
226+ break ;
227+ }
155228 }
156- XSetTransientForHint (display, wid, (Window)enigma_user::window_handle ());
229+ XSetTransientForHint (display, wid, (Window)(std::intptr_t )enigma_user::window_handle ());
230+ int len = enigma_user::message_get_caption ().length () + 1 ; char *buffer = new char [len]();
231+ strcpy (buffer, enigma_user::message_get_caption ().c_str ()); XChangeProperty (display, wid,
232+ XInternAtom (display, " _NET_WM_NAME" , false ),
233+ XInternAtom (display, " UTF8_STRING" , false ),
234+ 8 , PropModeReplace, (unsigned char *)buffer, len);
235+ delete[] buffer; XCloseDisplay (display);
236+ return nullptr ;
157237}
158238
159239bool widget_system_initialize () {
@@ -166,26 +246,14 @@ bool widget_system_initialize() {
166246string create_shell_dialog (string command) {
167247 string output; char buffer[BUFSIZ];
168248 int outfp = 0 , infp = 0 ; ssize_t nRead = 0 ;
169- pid_t pid = process_execute (command.c_str (), &infp, &outfp);
170- pid_t fpid = 0 ; if ((fpid = fork ()) == 0 ) {
171- SetErrorHandlers ();
172- Display *display = XOpenDisplay (nullptr );
173- force_window_of_pid_to_be_transient (display, pid);
174- XCloseDisplay (display);
175- exit (0 );
176- }
249+ pid_t pid = ProcessCreate (command.c_str (), &infp, &outfp);
250+ std::this_thread::sleep_for (std::chrono::milliseconds (100 )); pthread_t thread;
251+ pthread_create (&thread, nullptr , modify_shell_dialog, (void *)(std::intptr_t )pid);
177252 while ((nRead = read (outfp, buffer, BUFSIZ)) > 0 ) {
178253 buffer[nRead] = ' \0 ' ;
179254 output.append (buffer, nRead);
180255 }
181- kill (fpid, SIGTERM);
182- bool died = false ;
183- for (unsigned i = 0 ; !died && i < 4 ; i++) {
184- int status;
185- std::this_thread::sleep_for (std::chrono::milliseconds (250 ));
186- if (waitpid (fpid, &status, WNOHANG) == fpid) died = true ;
187- }
188- if (!died) kill (fpid, SIGKILL);
256+ pthread_cancel (thread);
189257 while (output.back () == ' \r ' || output.back () == ' \n ' )
190258 output.pop_back ();
191259 return output;
0 commit comments