Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
thunar
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
280
Issues
280
List
Boards
Labels
Service Desk
Milestones
Custom Issue Tracker
Custom Issue Tracker
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Xfce
thunar
Commits
8990efaf
Commit
8990efaf
authored
Oct 17, 2009
by
Nick Schermer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use the spawn code from libxfce4ui.
parent
90b3d9fe
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
3 additions
and
384 deletions
+3
-384
thunar/thunar-exec.c
thunar/thunar-exec.c
+0
-369
thunar/thunar-exec.h
thunar/thunar-exec.h
+0
-13
thunar/thunar-file.c
thunar/thunar-file.c
+3
-2
No files found.
thunar/thunar-exec.c
View file @
8990efaf
...
...
@@ -24,42 +24,12 @@
#include <config.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <glib.h>
#include <gio/gio.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h>
#include <thunar/thunar-exec.h>
#include <thunar/thunar-private.h>
#ifdef GDK_WINDOWING_X11
#include <X11/Xatom.h>
#include <gdk/gdkx.h>
#endif
static
void
te_string_append_quoted
(
GString
*
string
,
...
...
@@ -240,342 +210,3 @@ done:
g_string_free
(
command_line
,
TRUE
);
return
result
;
}
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
#include <libsn/sn.h>
/* the max. timeout for an application to startup */
#define TSN_STARTUP_TIMEOUT (30 * 1000)
typedef
struct
{
SnLauncherContext
*
sn_launcher
;
guint
timeout_id
;
guint
watch_id
;
GPid
pid
;
}
TsnStartupData
;
static
gboolean
tvsn_startup_timeout
(
gpointer
data
)
{
TsnStartupData
*
startup_data
=
data
;
GTimeVal
now
;
gdouble
elapsed
;
glong
tv_sec
;
glong
tv_usec
;
GDK_THREADS_ENTER
();
/* determine the amount of elapsed time */
g_get_current_time
(
&
now
);
sn_launcher_context_get_last_active_time
(
startup_data
->
sn_launcher
,
&
tv_sec
,
&
tv_usec
);
elapsed
=
(((
gdouble
)
now
.
tv_sec
-
tv_sec
)
*
G_USEC_PER_SEC
+
(
now
.
tv_usec
-
tv_usec
))
/
1000
.
0
;
/* check if the timeout was reached */
if
(
elapsed
>=
TSN_STARTUP_TIMEOUT
)
{
/* abort the startup notification */
sn_launcher_context_complete
(
startup_data
->
sn_launcher
);
sn_launcher_context_unref
(
startup_data
->
sn_launcher
);
startup_data
->
sn_launcher
=
NULL
;
}
GDK_THREADS_LEAVE
();
/* keep the startup timeout if not elapsed */
return
(
elapsed
<
TSN_STARTUP_TIMEOUT
);
}
static
void
tvsn_startup_timeout_destroy
(
gpointer
data
)
{
TsnStartupData
*
startup_data
=
data
;
_thunar_return_if_fail
(
startup_data
->
sn_launcher
==
NULL
);
/* cancel the watch (if any) */
if
(
startup_data
->
watch_id
!=
0
)
g_source_remove
(
startup_data
->
watch_id
);
/* make sure we don't leave zombies (see bug #2983 for details) */
g_child_watch_add_full
(
G_PRIORITY_LOW
,
startup_data
->
pid
,
(
GChildWatchFunc
)
g_spawn_close_pid
,
NULL
,
NULL
);
/* release the startup data */
g_slice_free
(
TsnStartupData
,
startup_data
);
}
static
void
tvsn_startup_watch
(
GPid
pid
,
gint
status
,
gpointer
data
)
{
TsnStartupData
*
startup_data
=
data
;
_thunar_return_if_fail
(
startup_data
->
sn_launcher
!=
NULL
);
_thunar_return_if_fail
(
startup_data
->
watch_id
!=
0
);
_thunar_return_if_fail
(
startup_data
->
pid
==
pid
);
/* abort the startup notification (application exited) */
sn_launcher_context_complete
(
startup_data
->
sn_launcher
);
sn_launcher_context_unref
(
startup_data
->
sn_launcher
);
startup_data
->
sn_launcher
=
NULL
;
/* cancel the startup notification timeout */
g_source_remove
(
startup_data
->
timeout_id
);
}
static
gint
tvsn_get_active_workspace_number
(
GdkScreen
*
screen
)
{
GdkWindow
*
root
;
gulong
bytes_after_ret
=
0
;
gulong
nitems_ret
=
0
;
guint
*
prop_ret
=
NULL
;
Atom
_NET_CURRENT_DESKTOP
;
Atom
_WIN_WORKSPACE
;
Atom
type_ret
=
None
;
gint
format_ret
;
gint
ws_num
=
0
;
gdk_error_trap_push
();
root
=
gdk_screen_get_root_window
(
screen
);
/* determine the X atom values */
_NET_CURRENT_DESKTOP
=
XInternAtom
(
GDK_WINDOW_XDISPLAY
(
root
),
"_NET_CURRENT_DESKTOP"
,
False
);
_WIN_WORKSPACE
=
XInternAtom
(
GDK_WINDOW_XDISPLAY
(
root
),
"_WIN_WORKSPACE"
,
False
);
if
(
XGetWindowProperty
(
GDK_WINDOW_XDISPLAY
(
root
),
GDK_WINDOW_XWINDOW
(
root
),
_NET_CURRENT_DESKTOP
,
0
,
32
,
False
,
XA_CARDINAL
,
&
type_ret
,
&
format_ret
,
&
nitems_ret
,
&
bytes_after_ret
,
(
gpointer
)
&
prop_ret
)
!=
Success
)
{
if
(
XGetWindowProperty
(
GDK_WINDOW_XDISPLAY
(
root
),
GDK_WINDOW_XWINDOW
(
root
),
_WIN_WORKSPACE
,
0
,
32
,
False
,
XA_CARDINAL
,
&
type_ret
,
&
format_ret
,
&
nitems_ret
,
&
bytes_after_ret
,
(
gpointer
)
&
prop_ret
)
!=
Success
)
{
if
(
G_UNLIKELY
(
prop_ret
!=
NULL
))
{
XFree
(
prop_ret
);
prop_ret
=
NULL
;
}
}
}
if
(
G_LIKELY
(
prop_ret
!=
NULL
))
{
if
(
G_LIKELY
(
type_ret
!=
None
&&
format_ret
!=
0
))
ws_num
=
*
prop_ret
;
XFree
(
prop_ret
);
}
gdk_error_trap_pop
();
return
ws_num
;
}
#endif
/**
* thunar_exec_on_screen:
* @screen : a #GdkScreen.
* @working_directory : child's current working directory or %NULL to inherit parent's.
* @argv : child's argument vector.
* @envp : child's environment vector or %NULL to inherit parent's.
* @flags : flags from #GSpawnFlags.
* @startup_notify : whether to use startup notification.
* @icon_name : application icon or %NULL.
* @error : return location for errors or %NULL.
*
* Like gdk_spawn_on_screen(), but also supports startup notification
* (if Thunar was built with startup notification support).
*
* Return value: %TRUE on success, %FALSE if @error is set.
**/
gboolean
thunar_exec_on_screen
(
GdkScreen
*
screen
,
const
gchar
*
working_directory
,
gchar
**
argv
,
gchar
**
envp
,
GSpawnFlags
flags
,
gboolean
startup_notify
,
const
gchar
*
icon_name
,
GError
**
error
)
{
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
SnLauncherContext
*
sn_launcher
=
NULL
;
TsnStartupData
*
startup_data
;
SnDisplay
*
sn_display
=
NULL
;
gint
sn_workspace
;
#endif
#ifndef HAVE_UNISTD_H
extern
gchar
**
environ
;
#endif
gboolean
succeed
;
gchar
*
display_name
;
gchar
**
cenvp
=
envp
;
gint
n_cenvp
,
n
;
GPid
pid
;
/* setup the child environment (stripping $DESKTOP_STARTUP_ID and $DISPLAY) */
if
(
G_LIKELY
(
envp
==
NULL
))
envp
=
(
gchar
**
)
environ
;
for
(
n
=
0
;
envp
[
n
]
!=
NULL
;
++
n
)
;
cenvp
=
g_new0
(
gchar
*
,
n
+
3
);
for
(
n_cenvp
=
n
=
0
;
envp
[
n
]
!=
NULL
;
++
n
)
if
(
strncmp
(
envp
[
n
],
"DESKTOP_STARTUP_ID"
,
18
)
!=
0
&&
strncmp
(
envp
[
n
],
"DISPLAY"
,
7
)
!=
0
)
cenvp
[
n_cenvp
++
]
=
g_strdup
(
envp
[
n
]);
/* add the real display name for the screen */
display_name
=
gdk_screen_make_display_name
(
screen
);
cenvp
[
n_cenvp
++
]
=
g_strconcat
(
"DISPLAY="
,
display_name
,
NULL
);
g_free
(
display_name
);
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
/* initialize the sn launcher context */
if
(
G_LIKELY
(
startup_notify
))
{
sn_display
=
sn_display_new
(
GDK_SCREEN_XDISPLAY
(
screen
),
(
SnDisplayErrorTrapPush
)
gdk_error_trap_push
,
(
SnDisplayErrorTrapPop
)
gdk_error_trap_pop
);
if
(
G_LIKELY
(
sn_display
!=
NULL
))
{
sn_launcher
=
sn_launcher_context_new
(
sn_display
,
GDK_SCREEN_XNUMBER
(
screen
));
if
(
G_LIKELY
(
sn_launcher
!=
NULL
&&
!
sn_launcher_context_get_initiated
(
sn_launcher
)))
{
/* initiate the sn launcher context */
sn_workspace
=
tvsn_get_active_workspace_number
(
screen
);
sn_launcher_context_set_binary_name
(
sn_launcher
,
argv
[
0
]);
sn_launcher_context_set_workspace
(
sn_launcher
,
sn_workspace
);
sn_launcher_context_set_icon_name
(
sn_launcher
,
(
icon_name
!=
NULL
)
?
icon_name
:
"applications-other"
);
sn_launcher_context_initiate
(
sn_launcher
,
g_get_prgname
(),
argv
[
0
],
gtk_get_current_event_time
());
/* add the real startup id to the child environment */
cenvp
[
n_cenvp
++
]
=
g_strconcat
(
"DESKTOP_STARTUP_ID="
,
sn_launcher_context_get_startup_id
(
sn_launcher
),
NULL
);
/* we want to watch the child process */
flags
|=
G_SPAWN_DO_NOT_REAP_CHILD
;
}
}
}
#endif
/* try to spawn the new process */
succeed
=
g_spawn_async
(
working_directory
,
argv
,
cenvp
,
flags
,
NULL
,
NULL
,
&
pid
,
error
);
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
/* handle the sn launcher context */
if
(
G_LIKELY
(
sn_launcher
!=
NULL
))
{
if
(
G_UNLIKELY
(
!
succeed
))
{
/* abort the sn sequence */
sn_launcher_context_complete
(
sn_launcher
);
sn_launcher_context_unref
(
sn_launcher
);
}
else
{
/* schedule a startup notification timeout */
startup_data
=
g_slice_new
(
TsnStartupData
);
startup_data
->
sn_launcher
=
sn_launcher
;
startup_data
->
timeout_id
=
g_timeout_add_full
(
G_PRIORITY_LOW
,
TSN_STARTUP_TIMEOUT
,
tvsn_startup_timeout
,
startup_data
,
tvsn_startup_timeout_destroy
);
startup_data
->
watch_id
=
g_child_watch_add_full
(
G_PRIORITY_LOW
,
pid
,
tvsn_startup_watch
,
startup_data
,
NULL
);
startup_data
->
pid
=
pid
;
}
}
else
if
(
G_LIKELY
(
succeed
))
{
/* make sure we don't leave zombies (see bug #2983 for details) */
g_child_watch_add_full
(
G_PRIORITY_LOW
,
pid
,
(
GChildWatchFunc
)
g_spawn_close_pid
,
NULL
,
NULL
);
}
/* release the sn display */
if
(
G_LIKELY
(
sn_display
!=
NULL
))
sn_display_unref
(
sn_display
);
#endif
/* release the child environment */
g_strfreev
(
cenvp
);
return
succeed
;
}
/**
* thunar_exec_sync:
* @command_fmt : the command to execute (can be a printf
* format string).
* @error : return location for errors or %NULL.
* @... : additional parameters to fill into
* @command_fmt.
*
* Executes the given @command_fmt and returns %TRUE if the
* command terminated successfully. Else, the @error is set
* to the standard error output.
*
* Return value: %TRUE if the @command_line was executed
* successfully, %FALSE if @error is set.
**/
gboolean
thunar_exec_sync
(
const
gchar
*
command_fmt
,
GError
**
error
,
...)
{
gboolean
result
;
va_list
args
;
gchar
*
standard_error
;
gchar
*
command_line
;
gint
exit_status
;
g_return_val_if_fail
(
error
==
NULL
||
*
error
==
NULL
,
FALSE
);
g_return_val_if_fail
(
command_fmt
!=
NULL
,
FALSE
);
/* determine the command line */
va_start
(
args
,
error
);
command_line
=
g_strdup_vprintf
(
command_fmt
,
args
);
va_end
(
args
);
/* try to execute the command line */
result
=
g_spawn_command_line_sync
(
command_line
,
NULL
,
&
standard_error
,
&
exit_status
,
error
);
if
(
G_UNLIKELY
(
result
))
{
/* check if the command failed */
if
(
G_UNLIKELY
(
exit_status
!=
0
))
{
/* drop additional whitespace from the stderr output */
g_strstrip
(
standard_error
);
/* strip all trailing dots from the stderr output */
while
(
*
standard_error
!=
'\0'
&&
standard_error
[
strlen
(
standard_error
)
-
1
]
==
'.'
)
standard_error
[
strlen
(
standard_error
)
-
1
]
=
'\0'
;
/* generate an error from the stderr output */
if
(
G_LIKELY
(
*
standard_error
!=
'\0'
))
g_set_error
(
error
,
G_FILE_ERROR
,
G_FILE_ERROR_FAILED
,
"%s"
,
standard_error
);
else
g_set_error
(
error
,
G_FILE_ERROR
,
G_FILE_ERROR_FAILED
,
_
(
"Unknown error"
));
/* and yes, we failed */
result
=
FALSE
;
}
/* release the stderr output */
g_free
(
standard_error
);
}
/* cleanup */
g_free
(
command_line
);
return
result
;
}
thunar/thunar-exec.h
View file @
8990efaf
...
...
@@ -36,19 +36,6 @@ gboolean thunar_exec_parse (const gchar *exec,
gchar
***
argv
,
GError
**
error
);
gboolean
thunar_exec_on_screen
(
GdkScreen
*
screen
,
const
gchar
*
working_directory
,
gchar
**
argv
,
gchar
**
envp
,
GSpawnFlags
flags
,
gboolean
startup_notify
,
const
gchar
*
icon_name
,
GError
**
error
);
gboolean
thunar_exec_sync
(
const
gchar
*
command_line
,
GError
**
error
,
...);
G_END_DECLS
;
#endif
/* !__THUNAR_EXEC_H__ */
thunar/thunar-file.c
View file @
8990efaf
...
...
@@ -50,6 +50,7 @@
#endif
#include <gio/gio.h>
#include <libxfce4ui/libxfce4ui.h>
#include <thunarx/thunarx.h>
...
...
@@ -1090,8 +1091,8 @@ thunar_file_execute (ThunarFile *file,
}
/* execute the command */
result
=
thunar_exec
_on_screen
(
screen
,
directory
,
argv
,
NULL
,
G_SPAWN_SEARCH_PATH
,
snotify
,
icon
,
error
);
result
=
xfce_spawn
_on_screen
(
screen
,
directory
,
argv
,
NULL
,
G_SPAWN_SEARCH_PATH
,
snotify
,
gtk_get_current_event_time
()
,
icon
,
error
);
/* release the working directory */
g_free
(
directory
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment