]> git.sur5r.net Git - i3/i3/blobdiff - i3-nagbar/main.c
Merge branch 'release-4.16.1'
[i3/i3] / i3-nagbar / main.c
index 6ec4294f0078adff6b348ee373cac913b4319a44..4ce7493961caf7ed5e35674cbc441843aed0d1eb 100644 (file)
@@ -32,6 +32,9 @@
 #include <xcb/randr.h>
 #include <xcb/xcb_cursor.h>
 
+#define SN_API_NOT_YET_FROZEN 1
+#include <libsn/sn-launchee.h>
+
 #include "i3-nagbar.h"
 
 /** This is the equivalent of XC_left_ptr. I’m not sure why xcb doesn’t have a
@@ -50,9 +53,9 @@ static char *argv0 = NULL;
 typedef struct {
     i3String *label;
     char *action;
-    bool exec_in_terminal;
     int16_t x;
     uint16_t width;
+    bool terminal;
 } button_t;
 
 static xcb_window_t win;
@@ -100,10 +103,10 @@ void debuglog(char *fmt, ...) {
 }
 
 /*
- * 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 :-).
+ * 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 children, 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.
@@ -116,7 +119,7 @@ static void start_application(const char *command) {
         setsid();
         if (fork() == 0) {
             /* This is the child */
-            execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, (void *)NULL);
+            execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, NULL);
             /* not reached */
         }
         exit(0);
@@ -124,7 +127,35 @@ static void start_application(const char *command) {
     wait(0);
 }
 
-static void execute_in_terminal(const char *command) {
+static button_t *get_button_at(int16_t x, int16_t y) {
+    for (int c = 0; c < buttoncnt; c++)
+        if (x >= (buttons[c].x) && x <= (buttons[c].x + buttons[c].width))
+            return &buttons[c];
+
+    return NULL;
+}
+
+static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t *event) {
+    printf("button pressed on x = %d, y = %d\n",
+           event->event_x, event->event_y);
+    /* TODO: set a flag for the button, re-render */
+}
+
+/*
+ * Called when the user releases the mouse button. Checks whether the
+ * coordinates are over a button and executes the appropriate action.
+ *
+ */
+static void handle_button_release(xcb_connection_t *conn, xcb_button_release_event_t *event) {
+    printf("button released on x = %d, y = %d\n",
+           event->event_x, event->event_y);
+    /* If the user hits the close button, we exit(0) */
+    if (event->event_x >= btn_close.x && event->event_x < btn_close.x + btn_close.width)
+        exit(0);
+    button_t *button = get_button_at(event->event_x, event->event_y);
+    if (!button)
+        return;
+
     /* We need to create a custom script containing our actual command
      * since not every terminal emulator which is contained in
      * i3-sensible-terminal supports -e with multiple arguments (and not
@@ -145,7 +176,7 @@ static void execute_in_terminal(const char *command) {
         warn("Could not fdopen() temporary script to store the nagbar command");
         return;
     }
-    fprintf(script, "#!/bin/sh\nrm %s\n%s", script_path, command);
+    fprintf(script, "#!/bin/sh\nrm %s\n%s", script_path, button->action);
     /* Also closes fd */
     fclose(script);
 
@@ -157,7 +188,11 @@ static void execute_in_terminal(const char *command) {
     }
 
     char *terminal_cmd;
-    sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path);
+    if (button->terminal) {
+        sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path);
+    } else {
+        terminal_cmd = sstrdup(link_path);
+    }
     printf("argv0 = %s\n", argv0);
     printf("terminal_cmd = %s\n", terminal_cmd);
 
@@ -167,43 +202,6 @@ static void execute_in_terminal(const char *command) {
     free(terminal_cmd);
     free(script_path);
     free(exe_path);
-}
-
-static button_t *get_button_at(int16_t x, int16_t y) {
-    for (int c = 0; c < buttoncnt; c++)
-        if (x >= (buttons[c].x) && x <= (buttons[c].x + buttons[c].width))
-            return &buttons[c];
-
-    return NULL;
-}
-
-static void handle_button_press(xcb_connection_t *conn, xcb_button_press_event_t *event) {
-    printf("button pressed on x = %d, y = %d\n",
-           event->event_x, event->event_y);
-    /* TODO: set a flag for the button, re-render */
-}
-
-/*
- * Called when the user releases the mouse button. Checks whether the
- * coordinates are over a button and executes the appropriate action.
- *
- */
-static void handle_button_release(xcb_connection_t *conn, xcb_button_release_event_t *event) {
-    printf("button released on x = %d, y = %d\n",
-           event->event_x, event->event_y);
-    /* If the user hits the close button, we exit(0) */
-    if (event->event_x >= btn_close.x && event->event_x < btn_close.x + btn_close.width)
-        exit(0);
-    button_t *button = get_button_at(event->event_x, event->event_y);
-    if (!button) {
-        return;
-    }
-
-    if (button->exec_in_terminal) {
-        execute_in_terminal(button->action);
-    } else {
-        start_application(button->action);
-    }
 
     /* TODO: unset flag, re-render */
 }
@@ -368,13 +366,13 @@ int main(int argc, char *argv[]) {
         {"version", no_argument, 0, 'v'},
         {"font", required_argument, 0, 'f'},
         {"button", required_argument, 0, 'b'},
-        {"button-sh", required_argument, 0, 'B'},
+        {"button-no-terminal", required_argument, 0, 'B'},
         {"help", no_argument, 0, 'h'},
         {"message", required_argument, 0, 'm'},
         {"type", required_argument, 0, 't'},
         {0, 0, 0, 0}};
 
-    char *options_string = "B:b:f:m:t:vh";
+    char *options_string = "b:B:f:m:t:vh";
 
     prompt = i3string_from_utf8("Please do not run this program.");
 
@@ -396,26 +394,17 @@ int main(int argc, char *argv[]) {
                 break;
             case 'h':
                 printf("i3-nagbar " I3_VERSION "\n");
-                printf("i3-nagbar [-m <message>] [-b <button> <terminal-action>] "
-                       "[-B <button> <shell-action> [-t warning|error] [-f <font>] [-v]\n");
+                printf("i3-nagbar [-m <message>] [-b <button> <action>] [-B <button> <action>] [-t warning|error] [-f <font>] [-v]\n");
                 return 0;
-            /* falls through */
-            case 'B':
             case 'b':
+            case 'B':
                 buttons = srealloc(buttons, sizeof(button_t) * (buttoncnt + 1));
                 buttons[buttoncnt].label = i3string_from_utf8(optarg);
                 buttons[buttoncnt].action = argv[optind];
-                if (o == 'b') {
-                    buttons[buttoncnt].exec_in_terminal = true;
-                    printf("button with label *%s* and terminal action *%s*\n",
-                           i3string_as_utf8(buttons[buttoncnt].label),
-                           buttons[buttoncnt].action);
-                } else {
-                    buttons[buttoncnt].exec_in_terminal = false;
-                    printf("button with label *%s* and shell action *%s*\n",
-                           i3string_as_utf8(buttons[buttoncnt].label),
-                           buttons[buttoncnt].action);
-                }
+                buttons[buttoncnt].terminal = (o == 'b');
+                printf("button with label *%s* and action *%s*\n",
+                       i3string_as_utf8(buttons[buttoncnt].label),
+                       buttons[buttoncnt].action);
                 buttoncnt++;
                 printf("now %d buttons\n", buttoncnt);
                 if (optind < argc)
@@ -437,6 +426,11 @@ int main(int argc, char *argv[]) {
 #include "atoms.xmacro"
 #undef xmacro
 
+    /* Init startup notification. */
+    SnDisplay *sndisplay = sn_xcb_display_new(conn, NULL, NULL);
+    SnLauncheeContext *sncontext = sn_launchee_context_new_from_environment(sndisplay, screens);
+    sn_display_unref(sndisplay);
+
     root_screen = xcb_aux_get_screen(conn, screens);
     root = root_screen->root;
 
@@ -506,6 +500,9 @@ int main(int argc, char *argv[]) {
                 XCB_EVENT_MASK_BUTTON_PRESS |
                 XCB_EVENT_MASK_BUTTON_RELEASE,
             cursor});
+    if (sncontext) {
+        sn_launchee_context_setup_window(sncontext, win);
+    }
 
     /* Map the window (make it visible) */
     xcb_map_window(conn, win);
@@ -566,6 +563,12 @@ int main(int argc, char *argv[]) {
     /* Initialize the drawable bar */
     draw_util_surface_init(conn, &bar, win, get_visualtype(root_screen), win_pos.width, win_pos.height);
 
+    /* Startup complete. */
+    if (sncontext) {
+        sn_launchee_context_complete(sncontext);
+        sn_launchee_context_unref(sncontext);
+    }
+
     /* Grab the keyboard to get all input */
     xcb_flush(conn);
 
@@ -597,7 +600,9 @@ int main(int argc, char *argv[]) {
 
             case XCB_CONFIGURE_NOTIFY: {
                 xcb_configure_notify_event_t *configure_notify = (xcb_configure_notify_event_t *)event;
-                draw_util_surface_set_size(&bar, configure_notify->width, configure_notify->height);
+                if (configure_notify->width > 0 && configure_notify->height > 0) {
+                    draw_util_surface_set_size(&bar, configure_notify->width, configure_notify->height);
+                }
                 break;
             }
         }