Group :: Graphical desktop/Other
RPM: xlockmore
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: xlockmore-5.46-kbdmon.patch
Download
Download
config.h.in | 6 ++
configure.in | 20 ++++++
xlock/XLock.ad | 4 +
xlock/mode.h | 13 ++++
xlock/resource-msg-en.h | 2 +
xlock/resource.c | 17 ++++++
xlock/xlock.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 210 insertions(+), 0 deletions(-)
diff --git a/.gear/tags/list b/.gear/tags/list
new file mode 100644
index 0000000..e69de29
diff --git a/config.h.in b/config.h.in
index 10f1fbb..7ae7dce 100644
--- a/config.h.in
+++ b/config.h.in
@@ -400,3 +400,9 @@
/* Define next line if you do not like the time in password window */
#undef NO_TIME
+
+/* Define to enable keyboard monitor */
+#undef USE_KBD_MON
+
+/* Define to enable double buffer rendering */
+#undef USE_DBE
diff --git a/configure.ac b/configure.ac
index cac489c..bcf4f37 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4524,6 +4524,26 @@ else
AC_MSG_RESULT([no setuid/setgid install])
fi
+AC_ARG_ENABLE(kbdmon, [ --enable-kbdmon enable keyboard state monitor (experimental)],kbdmon=$enableval,kbdmon=no)
+if test "$kbdmon" = yes; then
+ AC_CHECK_HEADER(X11/XKBlib.h,
+ [AC_MSG_RESULT([enabling keyboard state monitor])
+ AC_DEFINE(USE_KBD_MON)],
+ AC_MSG_RESULT([XKB X11 extension not found -- not enabling keyboard state monitor]))
+fi
+
+AC_ARG_ENABLE(dbe, [ --enable-dbe enable X11 double-buffer extension],dbe=$enableval,dbe=yes)
+if test "$dbe" = yes; then
+ AC_CHECK_HEADERS(X11/Xlib.h X11/extensions/Xdbe.h,
+ [AC_MSG_RESULT([enabling double buffer X11 extension])
+ AC_DEFINE(USE_DBE)],
+ AC_MSG_RESULT([Xdbe X11 extension not found]),
+ [[#if HAVE_X11_XLIB_H
+ # include <X11/Xlib.h>
+ #endif
+ ]])
+fi
+
DEPEND=makedepend
DEPEND_FLAGS=
DEPEND_DEFINES=
diff --git a/xlock/XLock.ad b/xlock/XLock.ad
index 0dc2b6b..444a6c5 100644
--- a/xlock/XLock.ad
+++ b/xlock/XLock.ad
@@ -92,12 +92,16 @@ XLock.logoutAuto: 0
! 0 defaults to maximum defined value
XLock.logoutButton: 0
+! Enables the keyboard monitor.
+XLock.enablekbdmon: on
+
XLock.username: Name:
XLock.password: Password:
XLock.info: Enter password to unlock; select icon to lock.
XLock.validate: Validating login...
XLock.invalid: Invalid login.
XLock.invalidCapsLock: Invalid login, Caps Lock on.
+XLock.kbdmonLabel: Keyboard state:
XLock.logoutButtonLabel: Click here to logout
XLock.logoutButtonHelp: \
You may log out this session if no terminals are available.\n\
diff --git a/xlock/mode.h b/xlock/mode.h
index 9fde092..f2b662d 100644
--- a/xlock/mode.h
+++ b/xlock/mode.h
@@ -245,6 +245,10 @@ typedef struct {
GC mbgc;
} mboxInfo;
+#ifdef USE_DBE
+#include <X11/extensions/Xdbe.h>
+#endif
+
typedef struct {
Visual *visual;
int visualclass; /* visual class name of current window */
@@ -258,6 +262,15 @@ typedef struct {
#ifdef USE_BUTTON_LOGOUT
Window button;
#endif
+#ifdef USE_KBD_MON
+ Window kbdmonw; /* window for keyboard monitor */
+ int kbdmonww; /* keyboard monitor window width */
+ int kbdmonwh; /* keyboard monitor window height */
+#ifdef USE_DBE
+ XdbeBackBuffer kbdmonbb; /* keyboard monitor window back buffer */
+ XdbeSwapInfo kbdmonswp; /* data for swapping keyboard monitor back buffer */
+#endif
+#endif
GC gc; /* graphics context for animation */
GC textgc; /* graphics context used for text rendering */
GC plantextgc; /* graphics context for plan message rendering */
diff --git a/xlock/resource-msg-en.h b/xlock/resource-msg-en.h
index 61a5782..7a58108 100644
--- a/xlock/resource-msg-en.h
+++ b/xlock/resource-msg-en.h
@@ -31,4 +31,6 @@
*/
#define DEF_FAIL "Auto-logout failed"
+#define DEF_KBD_MON "Keyboard state: "
+
#endif /* __RESOURCE_MSG_EN__ */
diff --git a/xlock/resource.c b/xlock/resource.c
index 1f72d73..074d67d 100644
--- a/xlock/resource.c
+++ b/xlock/resource.c
@@ -398,6 +398,11 @@ static XrmOptionDescRec genTable[] =
{(char *) "-invalidCapsLock", (char *) ".invalidCapsLock", XrmoptionSepArg, (caddr_t) NULL},
{(char *) "-geometry", (char *) ".geometry", XrmoptionSepArg, (caddr_t) NULL},
{(char *) "-icongeometry", (char *) ".icongeometry", XrmoptionSepArg, (caddr_t) NULL},
+#ifdef USE_KBD_MON
+ {(char *) "-enablekbdmon", (char *) ".enablekbdmon", XrmoptionNoArg, (caddr_t) "on"},
+ {(char *) "+enablekbdmon", (char *) ".enablekbdmon", XrmoptionNoArg, (caddr_t) "off"},
+ {(char *) "-kbdmonLabel", (char *) ".kbdmonLabel", XrmoptionSepArg, (caddr_t) NULL},
+#endif
#ifdef FX
{(char *) "-glgeometry", (char *) ".glgeometry", XrmoptionSepArg, (caddr_t) NULL},
#endif
@@ -826,6 +835,10 @@ char *logoutButtonHelp;
char *logoutFailedString;
#endif
+#ifdef USE_KBD_MON
+Bool enable_kbdmon = True;
+char *kbdmon_label;
+#endif
#ifdef USE_DTSAVER
Bool dtsaver;
@@ -960,6 +973,10 @@ static argtype genvars[] =
{(void *) & logoutFailedString, (char *) "logoutFailedString",
"LogoutFailedString", (char *) DEF_FAIL, t_String},
#endif
+#ifdef USE_KBD_MON
+ {(void *) & enable_kbdmon, (char *) "enablekbdmon", (char *) "EnableKbdMon", (char *) "off", t_Bool},
+ {(void *) & kbdmon_label, (char *) "kbdmonLabel", "kbdmonLabel", (char *) DEF_KBD_MON, t_String},
+#endif
#ifdef USE_SOUND
{(void *) & locksound, (char *) "locksound", (char *) "LockSound", (char *) DEF_LOCKSOUND, t_String},
{(void *) & infosound, (char *) "infosound", (char *) "InfoSound", (char *) DEF_INFOSOUND, t_String},
diff --git a/xlock/xlock.c b/xlock/xlock.c
index 9fa2970..63db08e 100644
--- a/xlock/xlock.c
+++ b/xlock/xlock.c
@@ -859,6 +859,11 @@ extern char *logoutFailedString;
#endif
+#ifdef USE_KBD_MON
+extern Bool enable_kbdmon;
+extern char *kbdmon_label;
+#endif
+
#ifdef USE_DTSAVER
extern Bool dtsaver;
@@ -994,6 +999,9 @@ extern int checkDynamic();
#endif
+#include <X11/XKBlib.h>
+#include <X11/extensions/Xdbe.h>
+
#if defined( HAVE_SYSLOG_H ) && defined( USE_SYSLOG )
static void
syslogStart(void)
@@ -1990,6 +1998,102 @@ runMainLoop(int maxtime, int iconscreen)
#endif /* !USE_OLD_EVENT_LOOP */
+#ifdef USE_KBD_MON
+void putKeyboardIndicator(const char *name, int *inv, Drawable dr, int *x, int *y)
+{
+ char delim[] = " + ";
+ int namelen = strlen(name);
+ int namew = XTextWidth(planfont, name, strlen(name));
+ int delimlen = strlen(delim);
+ int delimw = XTextWidth(planfont, " + ", strlen(delim));
+
+ if (*inv) {
+ XSetForeground(dsp, Scr[screen].plantextgc, Scr[screen].fg_pixel);
+ XDrawString(dsp, dr, Scr[screen].plantextgc, *x, *y, delim, delimlen);
+ *x += delimw;
+ }
+ XSetForeground(dsp, Scr[screen].gc, Scr[screen].fg_pixel);
+ XFillRectangle(dsp, dr, Scr[screen].gc,
+ *x, *y - planFontHeight + 1, namew + 2, planFontHeight + 2);
+ XSetForeground(dsp, Scr[screen].plantextgc, Scr[screen].bg_pixel);
+ XDrawString(dsp, dr, Scr[screen].plantextgc, *x + 1, *y, name, namelen);
+ *x += namew + 2;
+ *inv = 1;
+ XSetForeground(dsp, Scr[screen].plantextgc, Scr[screen].fg_pixel);
+}
+
+void updateKeyboardMonitor()
+{
+ XkbDescPtr kbd_desc = NULL;
+ XkbStateRec kbd_state;
+ char *group = NULL;
+ int lablen = strlen(kbdmon_label);
+ int x = 0;
+ int y = planFontHeight - 1;
+ int inv = 0;
+ Drawable dr;
+#ifdef USE_MB
+ XFontSet backfontset;
+#endif
+
+#ifdef USE_DBE
+ if (Scr[screen].kbdmonbb) {
+ dr = Scr[screen].kbdmonbb;
+ } else {
+ dr = Scr[screen].kbdmonw;
+ }
+#else
+ dr = Scr[screen].kbdmonw;
+#endif
+#ifdef USE_MB
+ backfontset = fontset;
+ fontset = planfontset;
+#endif
+
+ {
+ int opcode_rtrn, error_rtrn, major, minor, event;
+ XSetForeground(dsp, Scr[screen].gc, Scr[screen].bg_pixel);
+ XFillRectangle(dsp, dr, Scr[screen].gc,
+ 0, 0, Scr[screen].kbdmonww, Scr[screen].kbdmonwh);
+ XDrawString(dsp, dr, Scr[screen].plantextgc,
+ x, y, kbdmon_label, lablen);
+ x += XTextWidth(planfont, kbdmon_label, lablen);
+ if (XkbQueryExtension(dsp, &opcode_rtrn, &event, &error_rtrn,
+ &major, &minor))
+ {
+ XkbSelectEventDetails(dsp, XkbUseCoreKbd, XkbStateNotify,
+ XkbGroupStateMask, XkbGroupStateMask);
+ XkbGetState(dsp, XkbUseCoreKbd, &kbd_state);
+ kbd_desc = XkbGetKeyboard(dsp, XkbAllComponentsMask, XkbUseCoreKbd);
+ if (kbd_desc != NULL) {
+ if (kbd_desc->names != NULL) {
+ group = XGetAtomName(dsp, kbd_desc->names->groups[kbd_state.group]);
+ /* TODO: convert county names to codes
+ * (/usr/share/X11/xkb/rules/xorg.xml might help). */
+ }
+ }
+ }
+ if (group != NULL) {
+ putKeyboardIndicator(group, &inv, dr, &x, &y);
+ }
+ if ((kbd_state.mods & LockMask) > 0) {
+ putKeyboardIndicator("CL", &inv, dr, &x, &y);
+ }
+ if (kbd_desc != NULL) {
+ XkbFreeKeyboard(kbd_desc, 0, 1);
+ }
+ }
+#ifdef USE_DBE
+ if (Scr[screen].kbdmonswp.swap_window) {
+ XdbeSwapBuffers(dsp, &Scr[screen].kbdmonswp, 1);
+ }
+#endif
+#ifdef USE_MB
+ fontset = backfontset;
+#endif
+}
+#endif /* USE_KBD_MON */
+
static int
ReadXString(char *s, int slen, Bool *capsLock
#ifdef GLOBAL_UNLOCK
@@ -2238,6 +2342,12 @@ ReadXString(char *s, int slen, Bool *capsLock
break;
}
first_key = 0;
+#ifdef USE_KBD_MON
+ /* If we should indicate keyboard modes */
+ if (enable_kbdmon) {
+ updateKeyboardMonitor();
+ }
+#endif
}
}
@@ -2448,6 +2558,15 @@ getPassword(void)
putText(dsp, Scr[screen].window, Scr[screen].textgc, text_krbinfo, False, left, &x, &y);
else
#endif /* HAVE_KRB5 */
+#ifdef USE_KBD_MON
+ if (enable_kbdmon) {
+ XMoveWindow(dsp, Scr[screen].kbdmonw, x, y - fontHeight + planFontHeight/2 + 1);
+ y += planFontHeight + 8;
+ XMapWindow(dsp, Scr[screen].kbdmonw);
+ XRaiseWindow(dsp, Scr[screen].kbdmonw);
+ updateKeyboardMonitor();
+ }
+#endif
putText(dsp, Scr[screen].window, Scr[screen].textgc, text_info, False, left, &x, &y);
putText(dsp, Scr[screen].window, Scr[screen].textgc, "\n", False, left, &x, &y);
if (count_failed > 0) {
@@ -2751,6 +2870,11 @@ getPassword(void)
#ifdef USE_BUTTON_LOGOUT
XUnmapWindow(dsp, Scr[screen].button);
#endif
+#ifdef USE_KBD_MON
+ if (enable_kbdmon) {
+ XUnmapWindow(dsp, Scr[screen].kbdmonw);
+ }
+#endif
if (!fullscreen)
XConfigureWindow(dsp, Scr[screen].window, sizeconfiguremask,
&minisizeconfigure);
@@ -3808,6 +3932,30 @@ main(int argc, char **argv)
CIMASK, &xswa);
}
#endif
+#ifdef USE_KBD_MON
+ if (enable_kbdmon) {
+ Scr[screen].kbdmonww = DisplayWidth(dsp, screen) - Scr[screen].iconpos.x - \
+ iconwidth - font->max_bounds.width;
+ Scr[screen].kbdmonwh = planFontHeight + 2;
+ Scr[screen].kbdmonw = XCreateWindow(dsp, Scr[screen].window,
+ Scr[screen].iconpos.x + iconwidth + font->max_bounds.width,
+ 0, Scr[screen].kbdmonww, Scr[screen].kbdmonwh, 0, (int) CopyFromParent,
+ InputOutput, CopyFromParent, CIMASK, &xswa);
+#ifdef USE_DBE
+ Scr[screen].kbdmonswp.swap_window = 0;
+ {
+ int major, minor;
+ if (XdbeQueryExtension(dsp, &major, &minor)) {
+ Scr[screen].kbdmonswp.swap_window = Scr[screen].kbdmonw;
+ Scr[screen].kbdmonswp.swap_action = 0;
+ Scr[screen].kbdmonbb = XdbeAllocateBackBufferName(dsp,
+ Scr[screen].kbdmonswp.swap_window,
+ Scr[screen].kbdmonswp.swap_action);
+ }
+ }
+#endif
+ }
+#endif /* USE_KBD_MON */
}
XMapWindow(dsp, Scr[screen].window);
XRaiseWindow(dsp, Scr[screen].window);