Thanks, some comments inline.

On Sat, Jan 07, 2017 at 11:34:37AM +0000, Thomas Adam wrote:
> On Tue, Jan 03, 2017 at 12:33:42PM +0000, Nicholas Marriott wrote:
> > It can be in w->flags, or alternatively just walk the sessions, a flag
> > would be faster though.
> 
> Have a look at the patch attached; seems to work for me, including using
> grouped sessions.
> 
> I've removed session_is_linked() as a result.  There's no longer a need for
> it.
> 
> Kindly,
> Thomas

> commit 925a266a68c6c7473ce8d40077b373628c021f4c
> Author: Thomas Adam <[email protected]>
> Date:   Fri Jan 6 17:32:16 2017 +0000
> 
>     Handle linked windows with a dedicated flag
> 
> diff --git a/cmd-kill-window.c b/cmd-kill-window.c
> index 6365aecb..a2a2d18e 100644
> --- a/cmd-kill-window.c
> +++ b/cmd-kill-window.c
> @@ -61,7 +61,7 @@ cmd_kill_window_exec(struct cmd *self, struct cmdq_item 
> *item)
>       struct session          *s = item->state.tflag.s;
>  
>       if (self->entry == &cmd_unlink_window_entry) {
> -             if (!args_has(self->args, 'k') && !session_is_linked(s, w)) {
> +             if (!args_has(self->args, 'k') && !(w->flags & WINDOW_LINKED)) {
>                       cmdq_error(item, "window only linked to one session");
>                       return (CMD_RETURN_ERROR);
>               }
> diff --git a/format.c b/format.c
> index 70704f01..11b1a89f 100644
> --- a/format.c
> +++ b/format.c
> @@ -1164,7 +1164,7 @@ format_defaults_winlink(struct format_tree *ft, struct 
> session *s,
>           !!(wl->flags & WINLINK_SILENCE));
>       format_add(ft, "window_last_flag", "%d",
>           !!(wl == TAILQ_FIRST(&s->lastw)));
> -     format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
> +     format_add(ft, "window_linked", "%d", w->flags & WINDOW_LINKED);

This need to be !!(w->flags & WINDOW_LINKED):

>  
>       free(flags);
>  }
> diff --git a/server-fn.c b/server-fn.c
> index 83b3fe86..fcc2b08f 100644
> --- a/server-fn.c
> +++ b/server-fn.c
> @@ -233,7 +233,7 @@ server_link_window(struct session *src, struct winlink 
> *srcwl,
>      struct session *dst, int dstidx, int killflag, int selectflag,
>      char **cause)
>  {
> -     struct winlink          *dstwl;
> +     struct winlink          *dstwl, *wl;
>       struct session_group    *srcsg, *dstsg;
>  
>       srcsg = session_group_find(src);
> @@ -276,6 +276,9 @@ server_link_window(struct session *src, struct winlink 
> *srcwl,
>       if (dstwl == NULL)
>               return (-1);
>  
> +     if ((wl = winlink_find_by_window(&dst->windows, dstwl->window)) != NULL)
> +             wl->window->flags |= WINDOW_LINKED;
> +
>       if (selectflag)
>               session_select(dst, dstwl->idx);
>       server_redraw_session_group(dst);
> @@ -286,10 +289,17 @@ server_link_window(struct session *src, struct winlink 
> *srcwl,
>  void
>  server_unlink_window(struct session *s, struct winlink *wl)
>  {
> +     struct winlink  *wl1;
> +
>       if (session_detach(s, wl))
>               server_destroy_session_group(s);
>       else
>               server_redraw_session_group(s);
> +
> +     wl->window->flags &= ~WINDOW_LINKED;

I think this is a use-after-free of wl if the window only had one link,
it needs to happen before session_detach().

server_unlink_window should only remove the flag when there are no
remaining links, so it should only remove the flag if
TAILQ_NEXT(TAILQ_FIRST(&wl->window->winlinks)) == NULL.

> +
> +     TAILQ_FOREACH(wl1, &wl->window->winlinks, wentry)
> +             wl1->window->flags &= ~WINDOW_LINKED;

All the winlinks will point to the same window so you don't need to
clear the flags on each.

>  }
>  
>  void
> diff --git a/session.c b/session.c
> index d89bc6a0..49254c28 100644
> --- a/session.c
> +++ b/session.c
> @@ -417,20 +417,6 @@ session_has(struct session *s, struct window *w)
>       return (0);
>  }
>  
> -/*
> - * Return 1 if a window is linked outside this session (not including session
> - * groups). The window must be in this session!
> - */
> -int
> -session_is_linked(struct session *s, struct window *w)
> -{
> -     struct session_group    *sg;
> -
> -     if ((sg = session_group_find(s)) != NULL)
> -             return (w->references != session_group_count(sg));
> -     return (w->references != 1);
> -}
> -
>  static struct winlink *
>  session_next_alert(struct winlink *wl)
>  {
> diff --git a/tmux.h b/tmux.h
> index faf5688e..57a12b8a 100644
> --- a/tmux.h
> +++ b/tmux.h
> @@ -892,6 +892,7 @@ struct window {
>  #define WINDOW_FORCEWIDTH 0x2000
>  #define WINDOW_FORCEHEIGHT 0x4000
>  #define WINDOW_STYLECHANGED 0x8000
> +#define WINDOW_LINKED 0x10000
>  #define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
>  
>       int              alerts_queued;
> @@ -2265,7 +2266,6 @@ struct winlink  *session_attach(struct session *, 
> struct window *, int,
>                    char **);
>  int           session_detach(struct session *, struct winlink *);
>  int           session_has(struct session *, struct window *);
> -int           session_is_linked(struct session *, struct window *);
>  int           session_next(struct session *, int);
>  int           session_previous(struct session *, int);
>  int           session_select(struct session *, int);

-- 
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 [email protected].
To post to this group, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to