Skip to content

Commit

Permalink
Implement Evdev
Browse files Browse the repository at this point in the history
  • Loading branch information
ItzSelenux authored and ItzSelenux committed Sep 17, 2024
1 parent b240f61 commit f82c314
Show file tree
Hide file tree
Showing 12 changed files with 328 additions and 60 deletions.
14 changes: 11 additions & 3 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,24 @@ jobs:
libgtk-3-dev \
libayatana-appindicator3-dev \
pkg-config \
libudev-dev \
libinput-dev \
libevdev-dev \
clang
- name: Build with GCC
run: |
make CC=gcc
make CC=gcc
strip gxcapindicator
mv gxcapindicator ${{ env.GH_RELEASE_FILE }}
mv gxcapindicator ${{ env.GH_RELEASE_FILE }}-Evdev
make CC=gcc WITHX11=1
strip gxcapindicator
mv gxcapindicator ${{ env.GH_RELEASE_FILE }}-X11
- name: Build with Clang
run: |
make CC=clang
make CC=clang WITHX11=1
continue-on-error: true

- name: Build with -Werror
Expand All @@ -54,4 +61,5 @@ jobs:
body: ${{ github.event.head_commit.message }}
tag_name: ${{ env.GH_RELEASE_VERSION }}
files: |
${{ env.GH_RELEASE_FILE }}
${{ env.GH_RELEASE_FILE }}-Evdev
${{ env.GH_RELEASE_FILE }}-X11
15 changes: 12 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
WITHX11 ?= 0

ifeq ($(WITHX11), 0)
XLIB = -ludev -linput -levdev -I/usr/include/libevdev-1.0/
else
XLIB = -lX11
FLAGS +=-DWITHX11
endif

CC = cc
CFLAGS = `pkg-config --cflags gtk+-3.0 ayatana-appindicator3-0.1` -Wall
LIBS = `pkg-config --libs gtk+-3.0 ayatana-appindicator3-0.1` -lpthread -lX11
CFLAGS = `pkg-config --cflags gtk+-3.0 ayatana-appindicator3-0.1` $(FLAGS) $(XLIB)
LIBS = `pkg-config --libs gtk+-3.0 ayatana-appindicator3-0.1` -lpthread $(XLIB)

SRC = gxcapindicator.c
OBJ = $(SRC:.c=.o)
Expand Down Expand Up @@ -34,4 +43,4 @@ uninstall:
rm -f /usr/local/share/icons/hicolor/32x32/devices/keyboard-caps-disabled.svg
rm -f /usr/local/share/icons/hicolor/32x32/devices/keyboard-caps-enabled.svg
rm -f /usr/local/share/icons/hicolor/32x32/devices/keyboard-num-disabled.svg
rm -f /usr/local/share/icons/hicolor/32x32/devices/keyboard-num-enabled.svg
rm -f /usr/local/share/icons/hicolor/32x32/devices/keyboard-num-enabled.svg
64 changes: 46 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
# gxcapindicator
# GXCapIndicator

<img src="https://raw.githubusercontent.com/ItzSelenux/ItzSelenux.github.io/main/res/projects/gxcapindicator.svg" alt="Description of Image" width="111px" />
<img src="https://raw.githubusercontent.com/ItzSelenux/ItzSelenux.github.io/main/res/projects/gxcapindicator.svg" alt="GXCapIndicator Logo" width="111px" />

**GXCapIndicator** is a simple tool for indicating the status of Caps Lock and Num Lock keys in the system tray.

Simple Cap/Num lock key indicator for x11 tray
## Features

## Features:
- [x] Monitor Caps Lock and Num Lock keys
- [x] Toggle Caps Lock and Num Lock with an on-screen button
- [x] Hideable indicators
- [x] Adjustable update rate
- [x] Wayland support (with `Evdev`)

- [x] Monitor Cap/Num Keys
- [x] Toggle Cap/Num Keys with a on-screen button
- [x] Hiddeable indicators
- [x] Choose update rate
- [ ] Wayland support
## Installation

## Configuration

| Item | Description | Possible values| Default Value| example
| --- | --- | --- | --- | --- |
| showcap | Enables "Caps Lock" key indicator | 0, 1 | 1 | showcap=1|
| shownum | Enables "Num Lock" key indicator | 0, 1 | 1 | shownum=1 |
| updrate | Set update rate | (Number) | 0 | updrate=0 |
To build GXCapIndicator, choose the backend you want to use:

## Build
### With Evdev Backend

```sh
make
```
make gxcapindicator

### With X11 Backend

```sh
make WITHX11=1
```

## Backend Differences

GXCapIndicator supports two backends for fetching key status: X11 and Evdev. Each backend has its own capabilities and limitations.

### X11 Backend
- Uses `XkbGetState` to fetch the key status.
- Some options are not available:
- **Initial Visual State**: Cannot set the initial visual state of Caps Lock/Num Lock (unnecessary with XkbGetState).

### Evdev Backend
- Uses `libinput_event_get_keyboard_event` to fetch the key status.
- Some options are not available:
- **Update Rate**: Polling rate is fixed and cannot be adjusted.
- **Toggle Functionality**: Can't be implemented without root access.

## Configuration

You can configure GXCapIndicator with the integrated GUI (`settings` in indicator menu) or by editing` $HOME/.config/gxcapindicator` using the following options:

| Item | Description | Possible Values | Default Value | Example | Scope |
|-------------|--------------------------------------|-----------------|---------------|-------------|---------|
| `showcap` | Enables the Caps Lock key indicator | `0`, `1` | `1` | `showcap=1` | All |
| `shownum` | Enables the Num Lock key indicator | `0`, `1` | `1` | `shownum=1` | All |
| `updrate` | Sets the update rate | (Number) | `0` | `updrate=0` | X11 |
| `vcapstate` | Sets the initial visual state of Caps Lock | `0`, `1` | `0` | `vcapstate=0` | Evdev |
| `vnumstate` | Sets the initial visual state of Num Lock | `0`, `1` | `0` | `vnumstate=0` | Evdev |
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1
1.2
11 changes: 11 additions & 0 deletions cfgmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ void on_preferences(GtkWidget *button, gpointer data)

gshowcap = gtk_check_button_new();
gshownum = gtk_check_button_new();
gcapstate = gtk_check_button_new();
gnumstate = gtk_check_button_new();
gupdrate = gtk_entry_new();

btn_cancel = gtk_button_new_with_label("cancel");
Expand All @@ -37,13 +39,22 @@ void on_preferences(GtkWidget *button, gpointer data)
gtk_grid_attach(GTK_GRID(grid), gshowcap, 1, 0, 1, 1);
gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Show Num Lock:"), 0, 1, 1, 1);
gtk_grid_attach(GTK_GRID(grid), gshownum, 1, 1, 1, 1);
#ifdef WITHX11
gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Update rate (seconds):"), 0, 2, 1, 1);
gtk_grid_attach(GTK_GRID(grid), gupdrate, 1, 2, 1, 1);
#else
gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Start with caps lock \n visually enabled:"), 0, 2, 1, 1);
gtk_grid_attach(GTK_GRID(grid), gcapstate, 1, 2, 1, 1);
gtk_grid_attach(GTK_GRID(grid), gtk_label_new("Start with num lock \n visually enabled:"), 0, 3, 1, 1);
gtk_grid_attach(GTK_GRID(grid), gnumstate, 1, 3, 1, 1);
#endif
gtk_grid_attach(GTK_GRID(grid), btn_cancel, 0, 6, 1, 1);
gtk_grid_attach(GTK_GRID(grid), btn_savesettings, 1, 6, 1, 1);

gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gshowcap), !!showcap);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gshownum), !!shownum);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gcapstate), !!vcapstate);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gnumstate), !!vnumstate);

char buffer[32];
snprintf(buffer, sizeof(buffer), "%d", updrate);
Expand Down
77 changes: 77 additions & 0 deletions evdevintegrity.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Restricted file access functions for libinput
int open_restricted(const char *path, int flags, void *user_data)
{
int fd = open(path, flags);
if (fd < 0)
{
perror("Failed to open restricted path");
}
return fd < 0 ? -errno : fd;
}

void close_restricted(int fd, void *user_data)
{
close(fd);
}

const struct libinput_interface interface =
{
.open_restricted = open_restricted,
.close_restricted = close_restricted,
};

void check_udev()
{
struct udev *udev = udev_new();
if (udev == NULL)
{
g_error("Failed to initialize udev.");
return;
}

libinput = libinput_udev_create_context(&interface, NULL, udev);
if (!libinput)
{
g_error("Failed to initialize libinput from udev.");
udev_unref(udev);
return;
}

if (libinput_udev_assign_seat(libinput, "seat0") != 0)
{
g_error("Failed to set seat.");
libinput_unref(libinput);
udev_unref(udev);
return;
}
}

gboolean check_permissions(const gchar* group_name)
{
gid_t *groups;
int ngroups;
struct group *grp;
gid_t gid;

ngroups = getgroups(0, NULL);
groups = g_malloc(ngroups * sizeof(gid_t));
getgroups(ngroups, groups);

grp = getgrnam(group_name);
if (!grp) {
g_free(groups);
return FALSE;
}
gid = grp->gr_gid;

for (int i = 0; i < ngroups; i++) {
if (groups[i] == gid) {
g_free(groups);
return TRUE;
}
}

g_free(groups);
g_error("User is likely not in input group, please add your user to input group or compile this program with -DWITHX11 if you're running X11");
return FALSE;
}
11 changes: 11 additions & 0 deletions gxcapindicator.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@

int main(int argc, char *argv[])
{
isx11 = (strcmp(getenv("XDG_SESSION_TYPE"), "wayland") != 0);
readconf();

#ifdef WITHX11
g_print("Running with X11 backend");
#else
g_print("Running with Evdev backend");

check_udev();
check_permissions("input");
#endif

gtk_init(&argc, &argv);
create_window();
}
6 changes: 4 additions & 2 deletions gxcapindicator.conf
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[GXCapIndicator Configuration File, place default on /etc/gxcapindicator.conf]
[GXCapIndicator Configuration File]
showcap=1
shownum=1
updrate=0
vcapstate=1
vnumstate=1
updrate=1
30 changes: 22 additions & 8 deletions gxcapindicator.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
#include <gtk/gtk.h>
#include <libayatana-appindicator/app-indicator.h>
#include <X11/XKBlib.h>
#include <X11/Xlib.h>

#ifdef WITHX11
#include <X11/XKBlib.h>
#include <X11/Xlib.h>
Display *d;
XkbStateRec xkbcapstate;
XkbStateRec xkbnumstate;
#else
#include <fcntl.h>
#include <libinput.h>
#include <libevdev/libevdev.h>
#include <grp.h>
#include <poll.h>
struct libinput *libinput;
#include "evdevintegrity.h"

#endif

#include <pthread.h>

#define ML 256

#define BUFFER_SIZE 1024

GtkIconTheme *theme;
GtkIconInfo *info;
GdkPixbuf *icon;
Expand All @@ -16,15 +33,12 @@ AppIndicator *capindicator, *numindicator;
GtkWidget *capmenu, *capmenu_item_toggle,*capmenu_item_settings, *capmenu_item_about, *capmenu_item_quit,
*nummenu, *nummenu_item_toggle,*nummenu_item_settings, *nummenu_item_about, *nummenu_item_quit,

*window, *gshowcap, *gshownum, *gupdrate, *dialog, *btn_savesettings, *grid, *btn_cancel;

Display *d;
*window, *gshowcap, *gshownum, *gupdrate, *gnumstate, *gcapstate, *dialog, *btn_savesettings, *grid, *btn_cancel;

pthread_t cap_threadid, num_threadid;
guint capstate=0, numstate=0, vcapstate=0, vnumstate=0, showcap=1, shownum=1, updrate=1, nohome=0, capvisible, numvisible, isx11;

guint capstate, numstate, showcap=1, shownum=1, updrate=1, nohome=0, capvisible, numvisible;

gchar *pver="1.1", config_file_path[ML];
gchar *pver="1.2", config_file_path[ML];

#include "threadmgr.h"
#include "keyhandler.h"
Expand Down
Loading

0 comments on commit f82c314

Please sign in to comment.