Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
showkeys: showkeys.c showkeys.h keystack.o
gcc -g -Wall showkeys.c keystack.o -o showkeys -lX11 -lxosd -lpthread -lXext -lX11 -lXinerama -lXtst
LDFLAGS = -lX11 -lxosd -lpthread -lXext -lX11 -lXinerama -lXtst
SOURCES = keystack.c showkeys.c
HEADERS = config.h keystack.h showkeys.h die.h
CC = gcc
CFLAGS = -g -Wall -Wextra -fdiagnostics-color=auto
LD = gcc


keystack.o: keystack.c keystack.h
gcc -c -g keystack.c
all: showkeys

clean:
rm showkeys keystack.o record-attempt record-example
rm -f showkeys *.o

check-syntax:
gcc -Wall -o nul -S ${CHK_SOURCES}
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<

record-attempt: record-attempt.c
gcc -g -Wall record-attempt.c -L/usr/lib -lXtst -lxosd -lpthread -lXext -lX11 -lXinerama -o record-attempt
$(SOURCES:.c=.o): $(HEADERS)

record-example: record-example.c
gcc -g -Wall record-example.c -L/usr/lib -lXtst -lxosd -lpthread -lXext -lX11 -lXinerama -o record-example
showkeys: $(SOURCES:.c=.o)
$(LD) -o $@ $^ $(LDFLAGS)
16 changes: 15 additions & 1 deletion config.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
/*
Config header for showkeys.c
*/
#ifndef CONFIG_H
#define CONFIG_H

/* Number of OSD lines on the screen */
#define NKEYS 10

/* Maximum length of one OSD line */
#define OSDLEN 15

/* Display font, select a font using 'xfontsel -scaled' */
#define SK_FONT "-*-courier*-*-*-*-*-60-*-*-*-*-*-*-*"
#define SK_FONT "-*-latin modern sans-*-r-*-*-60-*-*-*-*-*-*-*"

/* Display position, possible values: XOSD_top, XOSD_bottom */
#define SK_POS XOSD_bottom
Expand Down Expand Up @@ -36,3 +44,9 @@
to: #undef SK_NO_REPEATS. */
#define SK_NO_REPEATS

/* Define CAPS_IS_CONTROL if the caps lock key should be understood as a control
* modifier. */
#define CAPS_IS_CONTROL


#endif
14 changes: 14 additions & 0 deletions die.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* Showkeys
Copyright Noufal Ibrahim <[email protected]> 2011
Copyright Raphael Poss <[email protected]> 2020

Licensed under the GPLv3 : http://www.gnu.org/licenses/gpl.txt

Please see LICENSE file for complete license.
*/
#ifndef DIE_H
#define DIE_H

extern void die(const char*);

#endif
117 changes: 77 additions & 40 deletions keystack.c
Original file line number Diff line number Diff line change
@@ -1,73 +1,111 @@
/* Showkeys
/* Showkeys
Copyright Noufal Ibrahim <[email protected]> 2011

Licensed under the GPLv3 : http://www.gnu.org/licenses/gpl.txt

Please see LICENSE file for complete license.
*/

#define _GNU_SOURCE
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "keystack.h"
#include "die.h"
#include "config.h"

// push_back frees up the spot in the stack at the specified index,
// by pulling all the entries before that by one spot.
// The first entry is popped (and its string deallocated).
static void
push_back(KeyStack *stack, int index)
{
int i;
free(stack->keystrokes[0].keyname);
for (i=0; i<index; i++)
stack->keystrokes[i] = stack->keystrokes[i+1];
free(stack->keystrokes[0].keyname);
free(stack->keystrokes[0].buf);

for (int i = 0; i < index; i++)
stack->keystrokes[i] = stack->keystrokes[i+1];

stack->keystrokes[index].keyname = 0;
}

void
clear_stack(KeyStack *stack)
{
for (int i = 0; i < stack->pos; i++) {
free(stack->keystrokes[i].keyname);
free(stack->keystrokes[i].buf);
stack->keystrokes[i].keyname = 0;
}
stack->pos = -1;
}

KeyStack *
create_keystack(int size)
create_keystack(int size)
{
int i;
KeyStack *retval = NULL;
KeyStroke *stack = NULL;

stack = (KeyStroke *)malloc(sizeof(KeyStroke) * size);
for (i=0; i<size; i++) {
stack[i].keyname = NULL;
stack[i].times = 0;
}
KeyStack *retval = NULL;
KeyStroke *stack = NULL;

retval = (KeyStack *)malloc(sizeof(KeyStack));
retval->size = size;
retval->pos = -1;
retval->keystrokes = stack;
stack = (KeyStroke *)malloc(sizeof(KeyStroke) * size);
if (!stack)
die("malloc");

return retval;
for (int i = 0; i < size; i++) {
stack[i].keyname = NULL;
stack[i].times = 0;
}

retval = (KeyStack *)malloc(sizeof(KeyStack));
if (!retval)
die("malloc");

retval->size = size;
retval->pos = -1;
retval->keystrokes = stack;

return retval;
}

void
push(KeyStack *stack, char *keyname)
{
int index;
KeyStroke *last;
char *last_key;

last = &stack->keystrokes[stack->pos];
last_key = last->keyname;
index = stack->pos + 1;
int index = stack->pos + 1;

#ifdef SK_NO_REPEATS
if (index && ! strcmp (last_key, keyname)) {
/* If the same as the top of the stack, increment count */
last->times ++;
if (index >= 1 && !strcmp(stack->keystrokes[index-1].keyname, keyname)) {
/* If the same as the top of the stack, increment count */
stack->keystrokes[index-1].times++;
} else {
#endif
/* Add a new entry */
if (index == stack->size) {
push_back(stack, stack->pos);
index = stack->size-1;
}
stack->keystrokes[index].keyname = keyname;
stack->keystrokes[index].times = 1;
stack->pos = index;
/* Add a new entry. */
// Can we add it to the previous line?
if (index >= 1 && // We have a previous line already.
stack->keystrokes[index-1].times < 2 && // Not more than one press of the last key.
strcmp(stack->keystrokes[index-1].keyname, "Ret") != 0 && // Only if the last key was not "Enter".
strlen(stack->keystrokes[index-1].buf) + strlen(keyname) + 1 < OSDLEN // The combination fits.
) {
char *newbuf;
if (-1 == asprintf(&newbuf, "%s %s", stack->keystrokes[index-1].buf, keyname))
die("asprintf");
free(stack->keystrokes[index-1].keyname);
free(stack->keystrokes[index-1].buf);
stack->keystrokes[index-1].buf = newbuf;
stack->keystrokes[index-1].keyname = keyname;
} else {
// Adding to the last line? scroll everything first up.
if (index == stack->size) {
push_back(stack, stack->pos);
index = stack->size - 1;
}

// Now create a new line.
stack->keystrokes[index].buf = strdup(keyname);
stack->keystrokes[index].keyname = keyname;
stack->keystrokes[index].times = 1;
stack->pos = index;
}
#ifdef SK_NO_REPEATS
}
#endif
Expand All @@ -77,9 +115,8 @@ push(KeyStack *stack, char *keyname)
void
display_keystack(KeyStack *stack)
{
int i;
printf("---- Keystack ----\n");
for (i = 0; i <= stack->pos; i++) {
for (int i = 0; i <= stack->pos; i++) {
printf("%s %d times\n", stack->keystrokes[i].keyname, stack->keystrokes[i].times);
}
printf("---- -------- ----\n\n");
Expand Down
39 changes: 29 additions & 10 deletions keystack.h
Original file line number Diff line number Diff line change
@@ -1,27 +1,46 @@
/* Showkeys
/* Showkeys
Copyright Noufal Ibrahim <[email protected]> 2011
Copyright Raphael Poss <[email protected]> 2020

Licensed under the GPLv3 : http://www.gnu.org/licenses/gpl.txt

Please see LICENSE file for complete license.
*/
#define NKEYS 10
#ifndef KEYSTACK_H
#define KEYSTACK_H

#include "config.h"

// KeyStroke represents one line in the OSD output.
typedef struct {
char *keyname;
int times;
// keyname is the string returned by the X lookup function for the
// last key, possibly prefixed by a representation of modifiers.
// It identifies the last key event.
char *keyname;
// buf is the string to be printed on the screen.
char *buf;

// times is the number of times the last key has been pressed.
int times;
} KeyStroke;

typedef struct {
int size;
int pos;
KeyStroke *keystrokes;
// size is the total (allocated) number of entries in keystrokes
// below.
int size;
// pos is the index of the last used entry in
// keystrokes. Initially -1 to indicate no entry has been used
// yet.
int pos;
// keystrokes is the array of allocated keystrokes struct.
// There is one entry per OSD line, up to and including the
// entry pointed to by pos.
KeyStroke *keystrokes;
} KeyStack;



KeyStack *create_keystack();
void push(KeyStack *, char *);
void clear_stack(KeyStack *);
void display_keystack(KeyStack *);


#endif
Loading