mirror of
https://github.com/tmux/tmux.git
synced 2026-09-05 13:10:45 +00:00
Add a way to make a modal pane capture all key presses and use for
display-popup compatibility.
This commit is contained in:
@@ -502,6 +502,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
||||
window_pop_modal_zoom(w);
|
||||
goto fail;
|
||||
}
|
||||
new_wp->flags |= PANE_CAPTUREALLKEYS;
|
||||
|
||||
options_set_number(new_wp->options, "pane-border-lines", lines);
|
||||
if (args_has(args, 'E') > 1)
|
||||
|
||||
@@ -40,8 +40,8 @@ const struct cmd_entry cmd_new_pane_entry = {
|
||||
.name = "new-pane",
|
||||
.alias = "newp",
|
||||
|
||||
.args = { "bB:Cc:de:EfF:hIkl:LMm:Op:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
||||
.usage = "[-bCdefhIklMOPvWZ] [-B border-lines] "
|
||||
.args = { "bB:Cc:de:EfF:hIkl:KLMm:Op:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
||||
.usage = "[-bCdefhIkKLMOPvWZ] [-B border-lines] "
|
||||
"[-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||
"[-s style] [-S active-border-style] "
|
||||
@@ -202,6 +202,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
*/
|
||||
goto fail;
|
||||
}
|
||||
if (args_has(args, 'K') && args_has(args, 'O'))
|
||||
new_wp->flags |= PANE_CAPTUREALLKEYS;
|
||||
if (args_has(args, 'C') && args_has(args, 'O'))
|
||||
new_wp->flags |= PANE_CLOSEONCLICK;
|
||||
|
||||
|
||||
@@ -105,6 +105,24 @@ drag()
|
||||
sleep 1
|
||||
}
|
||||
|
||||
meta_drag()
|
||||
{
|
||||
scol="$1"
|
||||
srow="$2"
|
||||
ecol="$3"
|
||||
erow="$4"
|
||||
|
||||
seq=$(printf '\033[<8;%s;%sM' "$scol" "$srow")
|
||||
$TMUX2 send-keys -t "$OUTER" -l "$seq" 2>/dev/null
|
||||
sleep 0.2
|
||||
seq=$(printf '\033[<40;%s;%sM' "$ecol" "$erow")
|
||||
$TMUX2 send-keys -t "$OUTER" -l "$seq" 2>/dev/null
|
||||
sleep 0.2
|
||||
seq=$(printf '\033[<8;%s;%sm' "$ecol" "$erow")
|
||||
$TMUX2 send-keys -t "$OUTER" -l "$seq" 2>/dev/null
|
||||
sleep 1
|
||||
}
|
||||
|
||||
cleanup
|
||||
|
||||
check_ok new-session -d -s modal -x 80 -y 24 'cat'
|
||||
@@ -304,5 +322,61 @@ sleep 1
|
||||
must_equal "$(fmt modal:0 '#{window_modal_pane}')" ''
|
||||
must_equal "$(fmt modal:0 '#{pane_id}')" "$p0"
|
||||
|
||||
ignored=$($TMUX new-pane -KdPF '#{pane_id}' -t "$p0" 'cat') ||
|
||||
fail "new-pane -K without -O failed"
|
||||
check_ok kill-pane -t "$ignored"
|
||||
|
||||
$TMUX set -g @modal-prefix no
|
||||
$TMUX set -g @modal-root no
|
||||
$TMUX bind -n z set -g @modal-root yes
|
||||
|
||||
modal=$($TMUX new-pane -OKPF '#{pane_id}' -t "$p0" \
|
||||
-x 20 -y 5 -X 20 -Y 10 'cat') ||
|
||||
fail "new-pane -OK failed"
|
||||
sleep 1
|
||||
$TMUX2 send-keys -t "$OUTER" C-b x z Enter
|
||||
sleep 1
|
||||
must_equal "$($TMUX show -gv @modal-prefix)" no
|
||||
must_equal "$($TMUX show -gv @modal-root)" no
|
||||
case "$($TMUX capture-pane -pt "$modal")" in
|
||||
*xz*) ;;
|
||||
*) fail "keys did not reach key-capturing modal pane" ;;
|
||||
esac
|
||||
left=$(fmt "$modal" '#{pane_left}')
|
||||
top=$(fmt "$modal" '#{pane_top}')
|
||||
meta_drag $((left + 2)) $((top + 2)) $((left + 7)) $((top + 4))
|
||||
new_left=$(fmt "$modal" '#{pane_left}')
|
||||
new_top=$(fmt "$modal" '#{pane_top}')
|
||||
[ "$new_left" -gt "$left" ] || [ "$new_top" -gt "$top" ] ||
|
||||
fail "key-capturing modal pane did not move"
|
||||
check_ok kill-pane -t "$modal"
|
||||
sleep 1
|
||||
|
||||
$TMUX bind P display-popup -E -t "$p0" -w 20 -h 5 'cat'
|
||||
$TMUX2 send-keys -t "$OUTER" C-b P
|
||||
sleep 1
|
||||
modal=$(fmt modal:0 '#{window_modal_pane}')
|
||||
[ -n "$modal" ] || fail "display-popup did not create a modal pane"
|
||||
$TMUX2 send-keys -t "$OUTER" C-b x z Enter
|
||||
sleep 1
|
||||
must_equal "$($TMUX show -gv @modal-prefix)" no
|
||||
must_equal "$($TMUX show -gv @modal-root)" no
|
||||
case "$($TMUX capture-pane -pt "$modal")" in
|
||||
*xz*) ;;
|
||||
*) fail "keys did not reach display-popup pane" ;;
|
||||
esac
|
||||
check_ok kill-pane -t "$modal"
|
||||
sleep 1
|
||||
|
||||
$TMUX bind D display-popup -t "$p0" -w 20 -h 5 'printf done'
|
||||
$TMUX2 send-keys -t "$OUTER" C-b D
|
||||
sleep 2
|
||||
modal=$(fmt modal:0 '#{window_modal_pane}')
|
||||
[ -n "$modal" ] || fail "retained display-popup was not created"
|
||||
must_equal "$(fmt "$modal" '#{pane_dead}')" 1
|
||||
$TMUX2 send-keys -t "$OUTER" a
|
||||
sleep 1
|
||||
must_equal "$(fmt modal:0 '#{window_modal_pane}')" ''
|
||||
|
||||
cleanup
|
||||
exit 0
|
||||
|
||||
@@ -45,6 +45,7 @@ static void server_client_set_path(struct client *);
|
||||
static void server_client_set_progress_bar(struct client *);
|
||||
static void server_client_reset_state(struct client *);
|
||||
static void server_client_update_latest(struct client *);
|
||||
static int server_client_handle_dead_key(struct window_pane *, key_code);
|
||||
static void server_client_dispatch(struct imsg *, void *);
|
||||
static int server_client_dispatch_command(struct client *, struct imsg *);
|
||||
static int server_client_dispatch_identify(struct client *, struct imsg *);
|
||||
@@ -1270,6 +1271,21 @@ server_client_repeat_time(struct client *c, struct key_binding *bd)
|
||||
return (repeat);
|
||||
}
|
||||
|
||||
/* Handle a key press on a dead pane waiting for a key. */
|
||||
static int
|
||||
server_client_handle_dead_key(struct window_pane *wp, key_code key)
|
||||
{
|
||||
if (wp == NULL ||
|
||||
(~wp->flags & PANE_EXITED) ||
|
||||
KEYC_IS_MOUSE(key) ||
|
||||
KEYC_IS_PASTE(key) ||
|
||||
options_get_number(wp->options, "remain-on-exit") != 3)
|
||||
return (0);
|
||||
options_set_number(wp->options, "remain-on-exit", 0);
|
||||
server_destroy_pane(wp, 0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle data key input from client. This owns and can modify the key event it
|
||||
* is given and is responsible for freeing it.
|
||||
@@ -1355,6 +1371,14 @@ server_client_key_callback(struct cmdq_item *item, void *data)
|
||||
server_client_is_assume_paste(c))
|
||||
goto paste_key;
|
||||
|
||||
/* Forward keys directly if this pane is capturing all keys. */
|
||||
if (wp != NULL &&
|
||||
(wp->flags & PANE_CAPTUREALLKEYS) &&
|
||||
(~wp->flags & PANE_EXITED) &&
|
||||
!KEYC_IS_MOUSE(key) &&
|
||||
TAILQ_EMPTY(&wp->modes))
|
||||
goto forward_key;
|
||||
|
||||
/*
|
||||
* Work out the current key table. If the pane is in a mode, use
|
||||
* the mode table instead of the default key table.
|
||||
@@ -1519,15 +1543,8 @@ try_again:
|
||||
}
|
||||
|
||||
forward_key:
|
||||
if (wp != NULL &&
|
||||
(wp->flags & PANE_EXITED) &&
|
||||
!KEYC_IS_MOUSE(key) &&
|
||||
!KEYC_IS_PASTE(key) &&
|
||||
options_get_number(wp->options, "remain-on-exit") == 3) {
|
||||
options_set_number(wp->options, "remain-on-exit", 0);
|
||||
server_destroy_pane(wp, 0);
|
||||
if (server_client_handle_dead_key(wp, key))
|
||||
goto out;
|
||||
}
|
||||
if (c->flags & CLIENT_READONLY)
|
||||
goto out;
|
||||
if (wp != NULL)
|
||||
@@ -1611,9 +1628,9 @@ server_client_handle_key0(struct client *c, struct key_event *event,
|
||||
}
|
||||
|
||||
/*
|
||||
* Key presses in the command prompt are a special case. The queue might
|
||||
* be blocked so they need to be processed immediately rather than
|
||||
* queued.
|
||||
* Key presses for panes capturing all keys and in the command prompt are
|
||||
* a special case. The queue might be blocked so they need to be processed
|
||||
* immediately rather than queued.
|
||||
*/
|
||||
if (~c->flags & CLIENT_READONLY) {
|
||||
if (c->message_string != NULL) {
|
||||
@@ -1622,6 +1639,20 @@ server_client_handle_key0(struct client *c, struct key_event *event,
|
||||
status_message_clear(c);
|
||||
}
|
||||
|
||||
wp = s->curw->window->active;
|
||||
if (wp != NULL &&
|
||||
(wp->flags & PANE_CAPTUREALLKEYS) &&
|
||||
TAILQ_EMPTY(&wp->modes) &&
|
||||
!KEYC_IS_MOUSE(event->key)) {
|
||||
if (server_client_handle_dead_key(wp, event->key))
|
||||
return (0);
|
||||
if (~wp->flags & PANE_EXITED) {
|
||||
window_pane_key(wp, c, s, s->curw, event->key,
|
||||
&event->m);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
if (server_client_handle_menu_key(c, event))
|
||||
return (0);
|
||||
if (c->prompt != NULL) {
|
||||
|
||||
5
tmux.1
5
tmux.1
@@ -3644,7 +3644,7 @@ but a different format may be specified with
|
||||
.Fl F .
|
||||
.Tg newp
|
||||
.It Xo Ic new\-pane
|
||||
.Op Fl bCdefhIkLMOPvWZ
|
||||
.Op Fl bCdefhIkKLMOPvWZ
|
||||
.Op Fl B Ar border\-lines
|
||||
.Op Fl c Ar start\-directory
|
||||
.Op Fl e Ar environment
|
||||
@@ -3701,6 +3701,9 @@ A modal pane is always the active pane and prevents interaction with any other
|
||||
panes while it is active.
|
||||
A window can only have one modal pane and it must be a floating pane.
|
||||
With
|
||||
.Fl K ,
|
||||
all keys, including the prefix key, are passed directly to the modal pane.
|
||||
With
|
||||
.Fl C ,
|
||||
the modal pane is closed when the mouse is clicked outside it.
|
||||
.Pp
|
||||
|
||||
Reference in New Issue
Block a user