aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2020-12-31 16:45:41 +0000
committerKyle Evans <kevans@FreeBSD.org>2020-12-31 17:10:11 +0000
commitbe46634337248029333a434c235c8424279b30b4 (patch)
tree75aad00bed785b30933fc62fabae0cbefe6951d8
parent72cf7db3aaf17db412183886f19320e5074dc8b7 (diff)
downloadsrc-be46634337248029333a434c235c8424279b30b4.tar.gz
src-be46634337248029333a434c235c8424279b30b4.zip
vt: more carefully handle vt_allocate_keyboard grab work
vt_allocate_keyboard only needs to unwind the effects of keyboard-grabbing, rather than any associated vt window action that may have also happened. Split out the bits that do the keyboard work into *_noswitch equivalents, and use those in keyboard allocation. This will be less error-prone when a later change will offer up different window state behavior when the console is ungrabbed. Reviewed by: ray Differential Revision: https://reviews.freebsd.org/D27110
-rw-r--r--sys/dev/vt/vt_core.c79
1 files changed, 55 insertions, 24 deletions
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index f840f7ba37f6..c273b703de93 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -63,6 +63,9 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#endif
+static int vtterm_cngrab_noswitch(struct vt_device *, struct vt_window *);
+static int vtterm_cnungrab_noswitch(struct vt_device *, struct vt_window *);
+
static tc_bell_t vtterm_bell;
static tc_cursor_t vtterm_cursor;
static tc_putchar_t vtterm_putchar;
@@ -1030,7 +1033,7 @@ vt_allocate_keyboard(struct vt_device *vd)
if (vd->vd_curwindow == &vt_conswindow) {
grabbed = vd->vd_curwindow->vw_grabbed;
for (i = 0; i < grabbed; ++i)
- vtterm_cnungrab(vd->vd_curwindow->vw_terminal);
+ vtterm_cnungrab_noswitch(vd, vd->vd_curwindow);
}
idx0 = kbd_allocate("kbdmux", -1, vd, vt_kbdevent, vd);
@@ -1068,7 +1071,7 @@ vt_allocate_keyboard(struct vt_device *vd)
if (vd->vd_curwindow == &vt_conswindow) {
for (i = 0; i < grabbed; ++i)
- vtterm_cngrab(vd->vd_curwindow->vw_terminal);
+ vtterm_cngrab_noswitch(vd, vd->vd_curwindow);
}
return (idx0);
@@ -1740,24 +1743,24 @@ vtterm_cngetc(struct terminal *tm)
return (-1);
}
-static void
-vtterm_cngrab(struct terminal *tm)
+/*
+ * These two do most of what we want to do in vtterm_cnungrab, but without
+ * actually switching windows. This is necessary for, e.g.,
+ * vt_allocate_keyboard() to get the current keyboard into the state it needs to
+ * be in without damaging the device's window state.
+ *
+ * Both return the current grab count, though it's only used in vtterm_cnungrab.
+ */
+static int
+vtterm_cngrab_noswitch(struct vt_device *vd, struct vt_window *vw)
{
- struct vt_device *vd;
- struct vt_window *vw;
keyboard_t *kbd;
- vw = tm->tm_softc;
- vd = vw->vw_device;
-
- if (!cold)
- vt_window_switch(vw);
+ if (vw->vw_grabbed++ > 0)
+ return (vw->vw_grabbed);
if ((kbd = vd->vd_keyboard) == NULL)
- return;
-
- if (vw->vw_grabbed++ > 0)
- return;
+ return (1);
/*
* Make sure the keyboard is accessible even when the kbd device
@@ -1771,29 +1774,57 @@ vtterm_cngrab(struct terminal *tm)
vt_update_kbd_mode(vw, kbd);
kbdd_poll(kbd, TRUE);
+ return (1);
+}
+
+static int
+vtterm_cnungrab_noswitch(struct vt_device *vd, struct vt_window *vw)
+{
+ keyboard_t *kbd;
+
+ if (--vw->vw_grabbed > 0)
+ return (vw->vw_grabbed);
+
+ if ((kbd = vd->vd_keyboard) == NULL)
+ return (0);
+
+ kbdd_poll(kbd, FALSE);
+
+ vw->vw_kbdmode = vw->vw_prev_kbdmode;
+ vt_update_kbd_mode(vw, kbd);
+ kbdd_disable(kbd);
+ return (0);
}
static void
-vtterm_cnungrab(struct terminal *tm)
+vtterm_cngrab(struct terminal *tm)
{
struct vt_device *vd;
struct vt_window *vw;
- keyboard_t *kbd;
vw = tm->tm_softc;
vd = vw->vw_device;
- if ((kbd = vd->vd_keyboard) == NULL)
- return;
- if (--vw->vw_grabbed > 0)
+ if (!cold)
+ vt_window_switch(vw);
+
+ vtterm_cngrab_noswitch(vd, vw);
+}
+
+static void
+vtterm_cnungrab(struct terminal *tm)
+{
+ struct vt_device *vd;
+ struct vt_window *vw;
+
+ vw = tm->tm_softc;
+ vd = vw->vw_device;
+
+ if (vtterm_cnungrab_noswitch(vd, vw) != 0)
return;
- kbdd_poll(kbd, FALSE);
- vw->vw_kbdmode = vw->vw_prev_kbdmode;
- vt_update_kbd_mode(vw, kbd);
- kbdd_disable(kbd);
}
static void