TODO list, in order of importance:
* freely resizable (e.g. using your mouse, for now) percentage of rows/cols
- * fullscreen (handling of applications)
+ * fullscreen (handling of applications, mplayer, firefox, xpdf, wmctrl)
* fullscreen (implementing a mode, like default, stacked)
* xinerama
* document stuff!
extern TAILQ_HEAD(bindings_head, Binding) bindings;
extern xcb_event_handlers_t evenths;
extern char *pattern;
-extern char **environment;
extern int num_screens;
#endif
#ifndef _UTIL_H
#define _UTIL_H
-void start_application(const char *path, const char *args);
+void start_application(const char *command);
void check_error(xcb_connection_t *connection, xcb_void_cookie_t cookie, char *err_message);
#endif
/* Is it an <exec>? */
if (strncmp(command, "exec ", strlen("exec ")) == 0) {
printf("starting \"%s\"\n", command + strlen("exec "));
- start_application(command+strlen("exec "), NULL);
+ start_application(command+strlen("exec "));
return;
}
static const int BOTTOM = 5;
static const int RIGHT = 5;
-/* This is the filtered environment which will be passed to opened applications.
- * It contains DISPLAY (naturally) and locales stuff (LC_*, LANG) */
-char **environment;
-
/* hm, xcb_wm wants us to implement this. */
table_t *byChild = 0;
table_t *byParent = 0;
}
int main(int argc, char *argv[], char *env[]) {
- int i, e = 0;
-
- for (i = 0; (env[i] != NULL); i++)
- if (strncmp(env[i], "LC_", strlen("LC_")) == 0 ||
- strncmp(env[i], "LANG=", strlen("LANG=")) == 0 ||
- strncmp(env[i], "DISPLAY=", strlen("DISPLAY=")) == 0) {
- printf("Passing environment \"%s\"\n", env[i]);
- environment = realloc(environment, sizeof(char*) * ++e);
- environment[e-1] = env[i];
- }
-
- /* environment has to be NULL-terminated */
- environment = realloc(environment, sizeof(char*) * ++e);
- environment[e-1] = NULL;
-
- init_table();
-
+ int i, screens;
xcb_connection_t *c;
xcb_property_handlers_t prophs;
xcb_window_t root;
- int screens;
+ /* Initialize the table data structures for each workspace */
+ init_table();
memset(&evenths, 0, sizeof(xcb_event_handlers_t));
memset(&prophs, 0, sizeof(xcb_property_handlers_t));
c = xcb_connect(NULL, &screens);
- printf("x screen is %d\n", screens);
-
/* TODO: this has to be more beautiful somewhen */
int major, minor, error;
printf("Checking for Xinerama...\n");
initialize_xinerama(c);
- start_application(TERMINAL, NULL);
+ start_application(TERMINAL);
xcb_flush(c);
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <sys/wait.h>
#include "i3.h"
/*
- * Starts the given application with the given args.
+ * Starts the given application by passing it through a shell. We use double fork
+ * to avoid zombie processes. As the started application’s parent exits (immediately),
+ * the application is reparented to init (process-id 1), which correctly handles
+ * childs, so we don’t have to do it :-).
+ *
+ * The shell is determined by looking for the SHELL environment variable. If it
+ * does not exist, /bin/sh is used.
*
*/
-void start_application(const char *path, const char *args) {
- pid_t pid;
- if ((pid = vfork()) == 0) {
- /* This is the child */
- char *argv[2];
- /* TODO: For now, we ignore args. Later on, they should be parsed
- correctly (like in the shell?) */
- argv[0] = strdup(path);
- argv[1] = NULL;
- execve(path, argv, environment);
- /* not reached */
+void start_application(const char *command) {
+ if (fork() == 0) {
+ /* Child process */
+ if (fork() == 0) {
+ /* Stores the path of the shell */
+ static const char *shell = NULL;
+
+ if (shell == NULL)
+ if ((shell = getenv("SHELL")) == NULL)
+ shell = "/bin/sh";
+
+ /* This is the child */
+ execl(shell, shell, "-c", command, NULL);
+ /* not reached */
+ }
+ exit(0);
}
+ wait(0);
}
/*