From d47051a2de7de773c74b234eae606b3eabfc79d5 Mon Sep 17 00:00:00 2001
From: Daniel Mueller <deso@posteo.net>
Date: Sat, 18 Nov 2017 16:16:09 -0800
Subject: [PATCH 09/14] Honor current output in startup ID infrastructure

Currently, the startup ID infrastructure (used for 'exec' statements
without the --no-startup-id switch) does not honor the current output.
This can lead to problems in scenarios where workspace names are
ambiguous. For example, in a multi monitor setup an application started
on workspace 3 on the second monitor may actually spawn on workspace 3
on the first monitor, provided that the first monitor is currently
containing the focused container.
This change adjusts the startup module to store the current output name
along with the workspace name, which resolves this problem.
---
 include/data.h    |  2 ++
 include/startup.h |  2 +-
 src/manage.c      | 10 ++++++++--
 src/startup.c     | 10 +++++++---
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/include/data.h b/include/data.h
index f448d2..5afc3b 100644
--- a/include/data.h
+++ b/include/data.h
@@ -257,6 +257,8 @@ struct Ignore_Event {
 struct Startup_Sequence {
     /** startup ID for this sequence, generated by libstartup-notification */
     char *id;
+    /** output on which this startup was initiated */
+    char *output;
     /** workspace on which this startup was initiated */
     char *workspace;
     /** libstartup-notification context for this launch */
diff --git a/include/startup.h b/include/startup.h
index a2b52c..0031dc 100644
--- a/include/startup.h
+++ b/include/startup.h
@@ -68,7 +68,7 @@ struct Startup_Sequence *startup_sequence_get(const i3Window *cwindow,
  * Returns NULL otherwise.
  *
  */
-char *startup_workspace_for_window(const i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply);
+char *startup_workspace_for_window(const i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply, char **output);
 
 /**
  * Deletes the startup sequence for a window if it exists.
diff --git a/src/manage.c b/src/manage.c
index 3347d5..19a9fa 100644
--- a/src/manage.c
+++ b/src/manage.c
@@ -223,7 +223,8 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
 
     xcb_get_property_reply_t *startup_id_reply;
     startup_id_reply = xcb_get_property_reply(conn, startup_id_cookie, NULL);
-    char *startup_ws = startup_workspace_for_window(cwindow, startup_id_reply);
+    char *startup_out;
+    char *startup_ws = startup_workspace_for_window(cwindow, startup_id_reply, &startup_out);
     DLOG("startup workspace = %s\n", startup_ws);
 
     /* Get _NET_WM_DESKTOP if it was set. */
@@ -331,9 +332,14 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
                 nc = tree_open_con(nc->parent, cwindow);
             }
         } else if (startup_ws) {
+            Output *output;
+            assert(startup_out != NULL);
+            output = get_output_by_name(startup_out, true);
+            assert(output != NULL);
+
             /* If it was started on a specific workspace, we want to open it there. */
             DLOG("Using workspace on which this application was started (%s)\n", startup_ws);
-            nc = con_descend_tiling_focused(workspace_get(startup_ws));
+            nc = con_descend_tiling_focused(workspace_get_on_output(output->con, startup_ws));
             DLOG("focused on ws %s: %p / %s\n", startup_ws, nc, nc->name);
             if (nc->type == CT_WORKSPACE) {
                 nc = tree_open_con(nc, cwindow);
diff --git a/src/startup.c b/src/startup.c
index 08377f..d03510 100644
--- a/src/startup.c
+++ b/src/startup.c
@@ -114,6 +114,7 @@ void startup_sequence_delete(struct Startup_Sequence *sequence) {
     TAILQ_REMOVE(&startup_sequences, sequence, sequences);
 
     free(sequence->id);
+    free(sequence->output);
     free(sequence->workspace);
     FREE(sequence);
 }
@@ -157,11 +158,13 @@ void start_application(const char *command, bool no_startup_id) {
 
         LOG("startup id = %s\n", sn_launcher_context_get_startup_id(context));
 
-        /* Save the ID and current workspace in our internal list of startup
-         * sequences */
+        /* Save the ID and current output and workspace in our internal list
+         * of startup sequences */
+        Con *out = con_get_output(focused);
         Con *ws = con_get_workspace(focused);
         struct Startup_Sequence *sequence = scalloc(1, sizeof(struct Startup_Sequence));
         sequence->id = sstrdup(sn_launcher_context_get_startup_id(context));
+        sequence->output = sstrdup(out->name);
         sequence->workspace = sstrdup(ws->name);
         sequence->context = context;
         TAILQ_INSERT_TAIL(&startup_sequences, sequence, sequences);
@@ -343,7 +346,7 @@ struct Startup_Sequence *startup_sequence_get(const i3Window *cwindow,
  * Returns NULL otherwise.
  *
  */
-char *startup_workspace_for_window(const i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply) {
+char *startup_workspace_for_window(const i3Window *cwindow, xcb_get_property_reply_t *startup_id_reply, char **output) {
     struct Startup_Sequence *sequence = startup_sequence_get(cwindow, startup_id_reply, false);
     if (sequence == NULL) {
         return NULL;
@@ -357,6 +360,7 @@ char *startup_workspace_for_window(const i3Window *cwindow, xcb_get_property_rep
         return NULL;
     }
 
+    *output = sequence->output;
     return sequence->workspace;
 }
 
-- 
2.52.0

