23
23
#include < string>
24
24
#include < thread>
25
25
#include < chrono>
26
+ #include < vector>
26
27
27
28
#include " dialogs.h"
28
29
30
+ #include " ../../../../CompilerSource/OS_Switchboard.h"
31
+
29
32
#include " Widget_Systems/widgets_mandatory.h"
30
33
#include " Widget_Systems/General/WSdialogs.h"
31
34
32
35
#include " Universal_System/estring.h"
33
36
#include " Platforms/General/PFwindow.h"
34
37
35
- #include < X11/Xlib.h>
36
- #include < X11/Xatom.h>
37
- #include < X11/Xutil.h>
38
-
39
38
#include < sys/types.h>
40
39
#include < sys/wait.h>
41
40
#include < sys/stat.h>
42
41
42
+ #include < pthread.h>
43
43
#include < libgen.h>
44
44
#include < unistd.h>
45
45
#include < fcntl.h>
46
46
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
+
47
61
using std::string;
62
+ using std::vector;
48
63
49
64
namespace enigma {
50
65
@@ -72,10 +87,10 @@ static bool kwin_running() {
72
87
return bKWinRunning;
73
88
}
74
89
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) {
76
91
SetErrorHandlers ();
77
92
unsigned char *prop;
78
- unsigned long property;
93
+ unsigned long property = 0 ;
79
94
Atom actual_type, filter_atom;
80
95
int actual_format, status;
81
96
unsigned long nitems, bytes_after;
@@ -89,19 +104,19 @@ static unsigned long get_wid_or_pid(Display *display, Window window, bool wid) {
89
104
return property;
90
105
}
91
106
92
- static Window wid_from_top (Display *display) {
107
+ static Window WidFromTop (Display *display) {
93
108
SetErrorHandlers ();
94
109
int screen = XDefaultScreen (display);
95
110
Window window = RootWindow (display, screen);
96
- return (Window)get_wid_or_pid (display, window, true );
111
+ return (Window)GetActiveWidOrWindowPid (display, window, true );
97
112
}
98
113
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 );
101
116
}
102
117
103
118
// 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) {
105
120
int p_stdin[2 ];
106
121
int p_stdout[2 ];
107
122
pid_t pid;
@@ -146,14 +161,79 @@ static pid_t process_execute(const char *command, int *infp, int *outfp) {
146
161
return pid;
147
162
}
148
163
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) {
151
219
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
+ }
155
228
}
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 ;
157
237
}
158
238
159
239
bool widget_system_initialize () {
@@ -166,26 +246,14 @@ bool widget_system_initialize() {
166
246
string create_shell_dialog (string command) {
167
247
string output; char buffer[BUFSIZ];
168
248
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);
177
252
while ((nRead = read (outfp, buffer, BUFSIZ)) > 0 ) {
178
253
buffer[nRead] = ' \0 ' ;
179
254
output.append (buffer, nRead);
180
255
}
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);
189
257
while (output.back () == ' \r ' || output.back () == ' \n ' )
190
258
output.pop_back ();
191
259
return output;
0 commit comments