tmux: cannot select pane after prefix-b q

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

tmux: cannot select pane after prefix-b q

Denis Fondras
As discovered and reported by solene@, since a few day selecting a pane after
C-b q (display pane index) does not work.

From what I understand, the number entered is sent after the select-pane
command, too late...

Here is a diff :

Index: cmd-queue.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-queue.c,v
retrieving revision 1.65
diff -u -p -r1.65 cmd-queue.c
--- cmd-queue.c 3 May 2019 18:59:58 -0000 1.65
+++ cmd-queue.c 6 May 2019 18:40:55 -0000
@@ -72,6 +72,26 @@ cmdq_append(struct client *c, struct cmd
  } while (item != NULL);
 }
 
+/* Prepend an item. */
+void
+cmdq_prepend(struct client *c, struct cmdq_item *item)
+{
+ struct cmdq_list *queue = cmdq_get(c);
+ struct cmdq_item *next;
+
+ next = item->next;
+ item->next = NULL;
+ if (c != NULL)
+ c->references++;
+ item->client = c;
+
+ item->queue = queue;
+ TAILQ_INSERT_HEAD(queue, item, entry);
+ log_debug("%s %s: %s inserted", __func__, cmdq_name(c), item->name);
+ if (next)
+ cmdq_insert_after(item, next);
+}
+
 /* Insert an item. */
 void
 cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
Index: tmux.h
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
retrieving revision 1.887
diff -u -p -r1.887 tmux.h
--- tmux.h 3 May 2019 20:44:24 -0000 1.887
+++ tmux.h 6 May 2019 18:40:55 -0000
@@ -1949,6 +1949,7 @@ struct cmdq_item *cmdq_get_command(struc
 struct cmdq_item *cmdq_get_callback1(const char *, cmdq_cb, void *);
 void cmdq_insert_after(struct cmdq_item *, struct cmdq_item *);
 void cmdq_append(struct client *, struct cmdq_item *);
+void cmdq_prepend(struct client *, struct cmdq_item *);
 void cmdq_insert_hook(struct session *, struct cmdq_item *,
      struct cmd_find_state *, const char *, ...);
 void printflike(3, 4) cmdq_format(struct cmdq_item *, const char *,
Index: tty-keys.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tty-keys.c,v
retrieving revision 1.112
diff -u -p -r1.112 tty-keys.c
--- tty-keys.c 3 May 2019 18:00:19 -0000 1.112
+++ tty-keys.c 6 May 2019 18:40:55 -0000
@@ -734,7 +734,7 @@ complete_key:
  memcpy(&event->m, &m, sizeof event->m);
 
  item = cmdq_get_callback(server_client_key_callback, event);
- cmdq_append(c, item);
+ cmdq_prepend(c, item);
  }
 
  return (1);

Reply | Threaded
Open this post in threaded view
|

Re: tmux: cannot select pane after prefix-b q

Nicholas Marriott-2
Hi

You have the right idea general idea of the problem. display-panes
blocks the queue until it is finished, so the key press isn't processed
until then, which is too late.

But your change defeats the purpose, the idea is that new key presses
should be queued after the commands inserted by previous key presses,
not before them.

Identify mode (display-panes) can just be treated specially I think.

Please try the diff below.

Thanks!


Index: server-client.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/server-client.c,v
retrieving revision 1.279
diff -u -p -r1.279 server-client.c
--- server-client.c 3 May 2019 20:44:24 -0000 1.279
+++ server-client.c 7 May 2019 10:50:07 -0000
@@ -986,7 +986,7 @@ server_client_assume_paste(struct sessio
  * Handle data key input from client. This owns and can modify the key event it
  * is given and is responsible for freeing it.
  */
-enum cmd_retval
+static enum cmd_retval
 server_client_key_callback(struct cmdq_item *item, void *data)
 {
  struct client *c = item->client;
@@ -1204,6 +1204,44 @@ forward_key:
 out:
  free(event);
  return (CMD_RETURN_NORMAL);
+}
+
+/* Handle a key event. */
+int
+server_client_handle_key(struct client *c, struct key_event *event)
+{
+ struct session *s = c->session;
+ struct window *w;
+ struct window_pane *wp = NULL;
+ struct cmdq_item *item;
+
+ /* Check the client is good to accept input. */
+ if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
+ return (0);
+ w = s->curw->window;
+
+ /*
+ * Key presses in identify mode are a special case. The queue might be
+ * blocked so they need to processed immediately rather than queued.
+ */
+ if (c->flags & CLIENT_IDENTIFY) {
+ if (c->flags & CLIENT_READONLY)
+ return (0);
+ if (event->key >= '0' && event->key <= '9') {
+ window_unzoom(w);
+ wp = window_pane_at_index(w, event->key - '0');
+ }
+ server_client_clear_identify(c, wp);
+ return (0);
+ }
+
+ /*
+ * Add the key to the queue so it happens after any commands queued by
+ * previous keys.
+ */
+ item = cmdq_get_callback(server_client_key_callback, event);
+ cmdq_append(c, item);
+ return (1);
 }
 
 /* Client functions that need to happen every loop. */
Index: tmux.h
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
retrieving revision 1.888
diff -u -p -r1.888 tmux.h
--- tmux.h 7 May 2019 10:25:15 -0000 1.888
+++ tmux.h 7 May 2019 10:50:09 -0000
@@ -2012,7 +2012,7 @@ void server_client_set_identify(struct
 void server_client_set_key_table(struct client *, const char *);
 const char *server_client_get_key_table(struct client *);
 int server_client_check_nested(struct client *);
-enum cmd_retval server_client_key_callback(struct cmdq_item *, void *);
+int server_client_handle_key(struct client *, struct key_event *);
 struct client *server_client_create(int);
 int server_client_open(struct client *, char **);
 void server_client_unref(struct client *);
Index: tty-keys.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tty-keys.c,v
retrieving revision 1.112
diff -u -p -r1.112 tty-keys.c
--- tty-keys.c 3 May 2019 18:00:19 -0000 1.112
+++ tty-keys.c 7 May 2019 10:50:09 -0000
@@ -573,7 +573,6 @@ tty_keys_next(struct tty *tty)
  cc_t bspace;
  int delay, expired = 0, n;
  key_code key;
- struct cmdq_item *item;
  struct mouse_event m = { 0 };
  struct key_event *event;
 
@@ -732,9 +731,8 @@ complete_key:
  event = xmalloc(sizeof *event);
  event->key = key;
  memcpy(&event->m, &m, sizeof event->m);
-
- item = cmdq_get_callback(server_client_key_callback, event);
- cmdq_append(c, item);
+ if (!server_client_handle_key(c, event))
+ free(event);
  }
 
  return (1);

Reply | Threaded
Open this post in threaded view
|

Re: tmux: cannot select pane after prefix-b q

Solene Rapenne
On Tue, May 07, 2019 at 11:55:51AM +0100, Nicholas Marriott wrote:

> Hi
>
> You have the right idea general idea of the problem. display-panes
> blocks the queue until it is finished, so the key press isn't processed
> until then, which is too late.
>
> But your change defeats the purpose, the idea is that new key presses
> should be queued after the commands inserted by previous key presses,
> not before them.
>
> Identify mode (display-panes) can just be treated specially I think.
>
> Please try the diff below.
>
> Thanks!
>
>
> Index: server-client.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/tmux/server-client.c,v
> retrieving revision 1.279
> diff -u -p -r1.279 server-client.c
> --- server-client.c 3 May 2019 20:44:24 -0000 1.279
> +++ server-client.c 7 May 2019 10:50:07 -0000
> @@ -986,7 +986,7 @@ server_client_assume_paste(struct sessio
>   * Handle data key input from client. This owns and can modify the key event it
>   * is given and is responsible for freeing it.
>   */
> -enum cmd_retval
> +static enum cmd_retval
>  server_client_key_callback(struct cmdq_item *item, void *data)
>  {
>   struct client *c = item->client;
> @@ -1204,6 +1204,44 @@ forward_key:
>  out:
>   free(event);
>   return (CMD_RETURN_NORMAL);
> +}
> +
> +/* Handle a key event. */
> +int
> +server_client_handle_key(struct client *c, struct key_event *event)
> +{
> + struct session *s = c->session;
> + struct window *w;
> + struct window_pane *wp = NULL;
> + struct cmdq_item *item;
> +
> + /* Check the client is good to accept input. */
> + if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
> + return (0);
> + w = s->curw->window;
> +
> + /*
> + * Key presses in identify mode are a special case. The queue might be
> + * blocked so they need to processed immediately rather than queued.
> + */
> + if (c->flags & CLIENT_IDENTIFY) {
> + if (c->flags & CLIENT_READONLY)
> + return (0);
> + if (event->key >= '0' && event->key <= '9') {
> + window_unzoom(w);
> + wp = window_pane_at_index(w, event->key - '0');
> + }
> + server_client_clear_identify(c, wp);
> + return (0);
> + }
> +
> + /*
> + * Add the key to the queue so it happens after any commands queued by
> + * previous keys.
> + */
> + item = cmdq_get_callback(server_client_key_callback, event);
> + cmdq_append(c, item);
> + return (1);
>  }
>  
>  /* Client functions that need to happen every loop. */
> Index: tmux.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
> retrieving revision 1.888
> diff -u -p -r1.888 tmux.h
> --- tmux.h 7 May 2019 10:25:15 -0000 1.888
> +++ tmux.h 7 May 2019 10:50:09 -0000
> @@ -2012,7 +2012,7 @@ void server_client_set_identify(struct
>  void server_client_set_key_table(struct client *, const char *);
>  const char *server_client_get_key_table(struct client *);
>  int server_client_check_nested(struct client *);
> -enum cmd_retval server_client_key_callback(struct cmdq_item *, void *);
> +int server_client_handle_key(struct client *, struct key_event *);
>  struct client *server_client_create(int);
>  int server_client_open(struct client *, char **);
>  void server_client_unref(struct client *);
> Index: tty-keys.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/tmux/tty-keys.c,v
> retrieving revision 1.112
> diff -u -p -r1.112 tty-keys.c
> --- tty-keys.c 3 May 2019 18:00:19 -0000 1.112
> +++ tty-keys.c 7 May 2019 10:50:09 -0000
> @@ -573,7 +573,6 @@ tty_keys_next(struct tty *tty)
>   cc_t bspace;
>   int delay, expired = 0, n;
>   key_code key;
> - struct cmdq_item *item;
>   struct mouse_event m = { 0 };
>   struct key_event *event;
>  
> @@ -732,9 +731,8 @@ complete_key:
>   event = xmalloc(sizeof *event);
>   event->key = key;
>   memcpy(&event->m, &m, sizeof event->m);
> -
> - item = cmdq_get_callback(server_client_key_callback, event);
> - cmdq_append(c, item);
> + if (!server_client_handle_key(c, event))
> + free(event);
>   }
>  
>   return (1);

Works for me!
ok solene@

Reply | Threaded
Open this post in threaded view
|

Re: tmux: cannot select pane after prefix-b q

Denis Fondras
In reply to this post by Nicholas Marriott-2
On Tue, May 07, 2019 at 11:55:51AM +0100, Nicholas Marriott wrote:

> Hi
>
> You have the right idea general idea of the problem. display-panes
> blocks the queue until it is finished, so the key press isn't processed
> until then, which is too late.
>
> But your change defeats the purpose, the idea is that new key presses
> should be queued after the commands inserted by previous key presses,
> not before them.
>
> Identify mode (display-panes) can just be treated specially I think.
>
> Please try the diff below.
>

Thank you Nicholas, it works like a charm !