Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37889696
en ru br
ALT Linux repos
S:5.69-alt1
5.0: 5.27-alt10.M50.1
4.1: 5.27-alt5.M41.1
4.0: 5.27-alt8.M40.1.1

Group :: Graphical desktop/Other
RPM: xlockmore

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: xlockmore-5.46-kbdmon.patch
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);
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin