Thanks for the pointers. Based off of what you said, I've created a
patch which implements the features I mentioned. Two things I'm not
sure about: 1) it seems like the control mode client will receive
these notifications for all sessions/windows/panes, as opposed to
notifications for the current session only. Should I revise the patch
to add in filtes for this? 2) For the pane-mode-changed notification,
it looks like I only get the pane-id which means the notification
doesn't report much and I'll probably have to perform a list-panes
query in response to get more information. Neither of these issues
seem very problematic, though, so perhaps its best to just leave the
patch as it is.

With regards to the client_session_changed callback, what I'd like is
to have a notification for when any client changes sessions (not just
the one running Control Mode). I thought that client_session_changed
was called every time a client changed sessions, but in testing this
appears not to be the case (I'm not even quite sure when it does get
called). Should this be a new control mode notification like the ones
I just implemented, or should this be handled in a different way?

Thanks,
Joshua

On 5/2/17, Nicholas Marriott <nicholas.marri...@gmail.com> wrote:
> Hi
>
> What have you got so far?
>
> Control mode should already get updated for client-session-changed, if
> you look at notify.c:notify_callback there is already a check that
> passes it into control_notify_client_session_changed.
>
> For new ones you will need to add a notify_add call somewhere and then
> add a control-notify.c function and a check in notify_callback, for
> active pane it'll probably need a notify_add call in
> window.c:window_set_active_pane.
>
> Mode changes you can do in window_pane_set_mode and
> window_pane_reset_mode.
>
>
> On Tue, May 02, 2017 at 02:27:57AM -0500, Joshua Brot wrote:
>> Hi!
>>
>> I???m currently in the process of writing a Wayland Compositor with the
>> goal of using tmux as a tiling window manager. Basically, the compositor
>> provides an interface similar to the TTY with tmux running. When the user
>> launches a visual application, the compositor will then overlay it on the
>> pane from which it was launched. My current strategy for implementing this
>> is to launch an internal tmux client in control mode to every session on
>> the server in order to track what actions the client is taking and respond
>> accordingly.
>>
>> In its current state, tmux???s control mode looks like it provides almost
>> enough capabilities to make this project work. The biggest thing it is
>> missing are notifications for when the user switches active panes within a
>> window and when the user switches active windows in a session. It would
>> also be nice to have a notification for when the user switches into and
>> out of copy mode, but this isn???t essential. Finally, it would be nice to
>> get notifications on the ???client-session-changed??? hook, but since
>> there is a hook already I can very easily work around this.
>>
>> I have begun to look through tmux???s source in order to implement these
>> features myself, but I haven???t made much progress yet as the project is
>> quite large and I???m not familiar enough with all of the use cases needed
>>  to make these notifications always work. Any advice on how to implement
>> these features would be much appreciated (or if someone is willing to
>> implement the features themself, that would be great too :). Finally, any
>> feedback on my general strategy would be appreciated as I???m not entirely
>> sure if I???m going about this in a reasonable way.
>>
>> Thanks!
>> ???Joshua Brot
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "tmux-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to tmux-users+unsubscr...@googlegroups.com.
>> To post to this group, send an email to tmux-users@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"tmux-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to tmux-users+unsubscr...@googlegroups.com.
To post to this group, send an email to tmux-users@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
From c830ea1e227b73888f51961eb7517deac2f93981 Mon Sep 17 00:00:00 2001
From: Joshua Brot <jb...@umich.edu>
Date: Tue, 2 May 2017 20:12:16 -0500
Subject: [PATCH] Added several features to command mode.

Signed-off-by: Joshua Brot <jb...@umich.edu>
---
 control-notify.c | 41 +++++++++++++++++++++++++++++++++++++++++
 notify.c         |  6 ++++++
 session.c        |  1 +
 tmux.1           | 14 ++++++++++++++
 tmux.h           |  3 +++
 window.c         | 13 +++++++++++--
 6 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/control-notify.c b/control-notify.c
index 230bce61..056e1992 100644
--- a/control-notify.c
+++ b/control-notify.c
@@ -60,6 +60,19 @@ control_notify_input(struct client *c, struct window_pane *wp,
 }
 
 void
+control_notify_pane_mode_changed(int pane)
+{
+	struct client	*c;
+
+	TAILQ_FOREACH(c, &clients, entry) {
+		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
+			continue;
+
+		control_write(c, "%%pane-mode-changed %%%u", pane);
+	}
+}
+
+void
 control_notify_window_layout_changed(struct window *w)
 {
 	struct client		*c;
@@ -97,6 +110,20 @@ control_notify_window_layout_changed(struct window *w)
 }
 
 void
+control_notify_window_pane_changed(struct window *w)
+{
+	struct client	*c;
+
+	TAILQ_FOREACH(c, &clients, entry) {
+		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
+			continue;
+
+		control_write(c, "%%window-pane-changed @%u %%%u", 
+		              w->id, w->active->id);
+	}
+}
+
+void
 control_notify_window_unlinked(__unused struct session *s, struct window *w)
 {
 	struct client	*c;
@@ -203,3 +230,17 @@ control_notify_session_closed(__unused struct session *s)
 		control_write(c, "%%sessions-changed");
 	}
 }
+
+void
+control_notify_session_window_changed(struct session *s)
+{
+	struct client	*c;
+
+	TAILQ_FOREACH(c, &clients, entry) {
+		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
+			continue;
+
+		control_write(c, "%%session-window-changed $%u @%u", 
+		              s->id, s->curw->window->id);
+	}
+}
diff --git a/notify.c b/notify.c
index 0241fa60..31284127 100644
--- a/notify.c
+++ b/notify.c
@@ -78,8 +78,12 @@ notify_callback(struct cmdq_item *item, void *data)
 
 	log_debug("%s: %s", __func__, ne->name);
 
+	if (strcmp(ne->name, "pane-mode-changed") == 0)
+		control_notify_pane_mode_changed(ne->pane);
 	if (strcmp(ne->name, "window-layout-changed") == 0)
 		control_notify_window_layout_changed(ne->window);
+	if (strcmp(ne->name, "window-pane-changed") == 0)
+		control_notify_window_pane_changed(ne->window);
 	if (strcmp(ne->name, "window-unlinked") == 0)
 		control_notify_window_unlinked(ne->session, ne->window);
 	if (strcmp(ne->name, "window-linked") == 0)
@@ -94,6 +98,8 @@ notify_callback(struct cmdq_item *item, void *data)
 		control_notify_session_created(ne->session);
 	if (strcmp(ne->name, "session-closed") == 0)
 		control_notify_session_closed(ne->session);
+	if (strcmp(ne->name, "session-window-changed") == 0)
+		control_notify_session_window_changed(ne->session);
 
 	notify_hook(item, ne);
 
diff --git a/session.c b/session.c
index b52b0274..b9f30428 100644
--- a/session.c
+++ b/session.c
@@ -552,6 +552,7 @@ session_set_current(struct session *s, struct winlink *wl)
 	s->curw = wl;
 	winlink_clear_flags(wl);
 	window_update_activity(wl->window);
+	notify_session("session-window-changed", s);
 	return (0);
 }
 
diff --git a/tmux.1 b/tmux.1
index cb069e5e..12bd3509 100644
--- a/tmux.1
+++ b/tmux.1
@@ -4258,6 +4258,10 @@ and the window flags are
 A window pane produced output.
 .Ar value
 escapes non-printable characters and backslash as octal \\xxx.
+.It Ic %pane-mode-changed Ar pane-id
+The pane with ID
+.Ar pane-id
+has changed mode.
 .It Ic %session-changed Ar session-id Ar name
 The client is now attached to the session with ID
 .Ar session-id ,
@@ -4266,6 +4270,11 @@ which is named
 .It Ic %session-renamed Ar name
 The current session was renamed to
 .Ar name .
+.It Ic %session-window-changed Ar session-id Ar window-id
+The session with ID
+.Ar session-id
+changed its active window to the window with ID
+.Ar window-id .
 .It Ic %sessions-changed
 A session was created or destroyed.
 .It Ic %unlinked-window-add Ar window-id
@@ -4280,6 +4289,11 @@ was linked to the current session.
 The window with ID
 .Ar window-id
 closed.
+.It Ic %window-pane-changed Ar window-id Ar pane-id
+The active pane in the window with ID
+.Ar window-id
+changed to the pane with ID
+.Ar pane-id .
 .It Ic %window-renamed Ar window-id Ar name
 The window with ID
 .Ar window-id
diff --git a/tmux.h b/tmux.h
index 417145f1..1139d6ba 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2211,7 +2211,9 @@ void	control_write_buffer(struct client *, struct evbuffer *);
 /* control-notify.c */
 void	control_notify_input(struct client *, struct window_pane *,
 	    struct evbuffer *);
+void	control_notify_pane_mode_changed(int pane);
 void	control_notify_window_layout_changed(struct window *);
+void	control_notify_window_pane_changed(struct window *);
 void	control_notify_window_unlinked(struct session *, struct window *);
 void	control_notify_window_linked(struct session *, struct window *);
 void	control_notify_window_renamed(struct window *);
@@ -2219,6 +2221,7 @@ void	control_notify_client_session_changed(struct client *);
 void	control_notify_session_renamed(struct session *);
 void	control_notify_session_created(struct session *);
 void	control_notify_session_closed(struct session *);
+void	control_notify_session_window_changed(struct session *s);
 
 /* session.c */
 extern struct sessions sessions;
diff --git a/window.c b/window.c
index ed73050e..92742685 100644
--- a/window.c
+++ b/window.c
@@ -355,6 +355,8 @@ window_create_spawn(const char *name, int argc, char **argv, const char *path,
 	} else
 		w->name = default_window_name(w);
 
+	notify_window("window-pane-changed", w);
+
 	return (w);
 }
 
@@ -441,11 +443,14 @@ window_set_active_pane(struct window *w, struct window_pane *wp)
 		w->active = TAILQ_PREV(w->active, window_panes, entry);
 		if (w->active == NULL)
 			w->active = TAILQ_LAST(&w->panes, window_panes);
-		if (w->active == wp)
+		if (w->active == wp) {
+			notify_window("window-pane-changed", w);
 			return (1);
+		}
 	}
 	w->active->active_point = next_active_point++;
 	w->active->flags |= PANE_CHANGED;
+	notify_window("window-pane-changed", w);
 	return (1);
 }
 
@@ -621,8 +626,10 @@ window_lost_pane(struct window *w, struct window_pane *wp)
 			if (w->active == NULL)
 				w->active = TAILQ_NEXT(wp, entry);
 		}
-		if (w->active != NULL)
+		if (w->active != NULL) {
 			w->active->flags |= PANE_CHANGED;
+			notify_window("window-pane-changed", w);
+		}
 	} else if (wp == w->last)
 		w->last = NULL;
 }
@@ -1196,6 +1203,7 @@ window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
 	wp->flags |= (PANE_REDRAW|PANE_CHANGED);
 
 	server_status_window(wp->window);
+	notify_pane("pane-mode-changed", wp);
 	return (0);
 }
 
@@ -1215,6 +1223,7 @@ window_pane_reset_mode(struct window_pane *wp)
 	wp->flags |= (PANE_REDRAW|PANE_CHANGED);
 
 	server_status_window(wp->window);
+	notify_pane("pane-mode-changed", wp);
 }
 
 void
-- 
2.12.2

Reply via email to