Implement support for startup notifications

This only sets up startup notifications for the 'exec' commands and directives.

Monitoring startups follows later.
This commit is contained in:
Michael Stapelberg 2011-10-09 18:21:59 +01:00
parent 2a29d9c2c1
commit b9db72dc8a
4 changed files with 43 additions and 0 deletions

View File

@ -57,6 +57,7 @@ CFLAGS += $(call cflags_for_lib, x11)
CFLAGS += $(call cflags_for_lib, yajl) CFLAGS += $(call cflags_for_lib, yajl)
CFLAGS += $(call cflags_for_lib, libev) CFLAGS += $(call cflags_for_lib, libev)
CFLAGS += $(call cflags_for_lib, libpcre) CFLAGS += $(call cflags_for_lib, libpcre)
CFLAGS += $(call cflags_for_lib, libstartup-notification-1.0)
CPPFLAGS += -DI3_VERSION=\"${GIT_VERSION}\" CPPFLAGS += -DI3_VERSION=\"${GIT_VERSION}\"
CPPFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\" CPPFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\"
CPPFLAGS += -DTERM_EMU=\"$(TERM_EMU)\" CPPFLAGS += -DTERM_EMU=\"$(TERM_EMU)\"
@ -84,6 +85,7 @@ LIBS += $(call ldflags_for_lib, x11,X11)
LIBS += $(call ldflags_for_lib, yajl,yajl) LIBS += $(call ldflags_for_lib, yajl,yajl)
LIBS += $(call ldflags_for_lib, libev,ev) LIBS += $(call ldflags_for_lib, libev,ev)
LIBS += $(call ldflags_for_lib, libpcre,pcre) LIBS += $(call ldflags_for_lib, libpcre,pcre)
LIBS += $(call ldflags_for_lib, libstartup-notification-1.0,startup-notification-1)
# Please test if -Wl,--as-needed works on your platform and send me a patch. # Please test if -Wl,--as-needed works on your platform and send me a patch.
# it is known not to work on Darwin (Mac OS X) # it is known not to work on Darwin (Mac OS X)

View File

@ -12,6 +12,9 @@
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-launcher.h>
#include "queue.h" #include "queue.h"
#include "data.h" #include "data.h"
#include "xcb.h" #include "xcb.h"
@ -21,6 +24,11 @@
extern xcb_connection_t *conn; extern xcb_connection_t *conn;
extern int conn_screen; extern int conn_screen;
/** The last timestamp we got from X11 (timestamps are included in some events
* and are used for some things, like determining a unique ID in startup
* notification). */
extern xcb_timestamp_t last_timestamp;
extern SnDisplay *sndisplay;
extern xcb_key_symbols_t *keysyms; extern xcb_key_symbols_t *keysyms;
extern char **start_argv; extern char **start_argv;
extern Display *xlibdpy, *xkbdpy; extern Display *xlibdpy, *xkbdpy;

View File

@ -22,6 +22,14 @@ xcb_connection_t *conn;
/* The screen (0 when you are using DISPLAY=:0) of the connection 'conn' */ /* The screen (0 when you are using DISPLAY=:0) of the connection 'conn' */
int conn_screen; int conn_screen;
/* Display handle for libstartup-notification */
SnDisplay *sndisplay;
/* The last timestamp we got from X11 (timestamps are included in some events
* and are used for some things, like determining a unique ID in startup
* notification). */
xcb_timestamp_t last_timestamp = XCB_CURRENT_TIME;
xcb_screen_t *root_screen; xcb_screen_t *root_screen;
xcb_window_t root; xcb_window_t root;
uint8_t root_depth; uint8_t root_depth;
@ -362,6 +370,8 @@ int main(int argc, char *argv[]) {
if (xcb_connection_has_error(conn)) if (xcb_connection_has_error(conn))
errx(EXIT_FAILURE, "Cannot open display\n"); errx(EXIT_FAILURE, "Cannot open display\n");
sndisplay = sn_xcb_display_new(conn, NULL, NULL);
/* Initialize the libev event loop. This needs to be done before loading /* Initialize the libev event loop. This needs to be done before loading
* the config file because the parser will install an ev_child watcher * the config file because the parser will install an ev_child watcher
* for the nagbar when config errors are found. */ * for the nagbar when config errors are found. */

View File

@ -21,6 +21,9 @@
#include <yajl/yajl_version.h> #include <yajl/yajl_version.h>
#include <libgen.h> #include <libgen.h>
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-launcher.h>
#include "all.h" #include "all.h"
static iconv_t conversion_descriptor = 0; static iconv_t conversion_descriptor = 0;
@ -69,11 +72,31 @@ bool update_if_necessary(uint32_t *destination, const uint32_t new_value) {
* *
*/ */
void start_application(const char *command) { void start_application(const char *command) {
/* Create a startup notification context to monitor the progress of this
* startup. */
SnLauncherContext *context;
context = sn_launcher_context_new(sndisplay, conn_screen);
sn_launcher_context_set_name(context, "i3");
sn_launcher_context_set_description(context, "exec command in i3");
/* Chop off everything starting from the first space (if there are any
* spaces in the command), since we dont want the parameters. */
char *first_word = sstrdup(command);
char *space = strchr(first_word, ' ');
if (space)
*space = '\0';
sn_launcher_context_initiate(context, "i3", first_word, last_timestamp);
free(first_word);
LOG("startup id = %s\n", sn_launcher_context_get_startup_id(context));
LOG("executing: %s\n", command); LOG("executing: %s\n", command);
if (fork() == 0) { if (fork() == 0) {
/* Child process */ /* Child process */
setsid(); setsid();
if (fork() == 0) { if (fork() == 0) {
/* Setup the environment variable(s) */
sn_launcher_context_setup_child_process(context);
/* Stores the path of the shell */ /* Stores the path of the shell */
static const char *shell = NULL; static const char *shell = NULL;