添加快捷键设置

This commit is contained in:
2025-08-19 21:37:57 +08:00
parent bb61bfcd2e
commit ef450d3c53
8 changed files with 114 additions and 6 deletions

6
src/action.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include "types.h"
void spawn(const user_action_arg_t *arg);
void quit(const user_action_arg_t *arg);

View File

@@ -1,14 +1,16 @@
#pragma once
#include <X11/keysym.h>
#include <stdint.h>
#include <stdio.h>
#include <xcb/xproto.h>
#include "action.h"
#include "types.h"
/* 壁纸列表,支持通配符和 shell 环境变量拼接,最后以 NULL 结尾 */
const char *wallpapers[] = {};
const char *wallpapers[] = {"~/bg/", "~/Downloads/bg/*"};
/* 壁纸切换间隔单位0 表示不切换 */
const uint32_t wallpaper_interval = 0;
const uint32_t wallpaper_interval = 3;
/**
* @brief 屏幕 tags 设置
@@ -59,6 +61,19 @@ const rule_t rules[] = {
{.class = "Emacs", .monitor_amount = 2, .monitor_index = 0, .tags = 1 << 1},
};
#define SUPER XCB_MOD_MASK_4
#define ALT XCB_MOD_MASK_1
#define CTRL XCB_MOD_MASK_CONTROL
#define SHIFT XCB_MOD_MASK_SHIFT
const char launcher[] =
"rofi -show combi -modes window,drun,run,ssh,combi,windowcd";
const keybinding_t keys[] = {
{SUPER, XK_p, spawn, {.ptr = launcher}},
{SUPER, XK_q, quit, {.b = false}},
{SUPER, XK_r, quit, {.b = true}},
};
const char *const bar_bg = "#222222";
const char *const tag_bg = "#222222";
const char *const active_tag_bg = "#005577";

View File

@@ -25,7 +25,7 @@ typedef struct mapping_notify_event_t {
typedef struct key_press_event_t {
event_type_t type;
uint32_t key_symbols;
uint32_t key_symbol;
uint32_t modifiers;
} key_press_event_t;

View File

@@ -73,6 +73,21 @@ typedef struct rule_t {
bool floating;
} rule_t;
typedef union user_action_arg_t {
bool b;
int32_t i;
uint32_t ui;
float f;
const void *ptr;
} user_action_arg_t;
typedef struct keybinding_t {
uint32_t modifiers;
uint32_t key_symbol;
void (*func)(const user_action_arg_t *);
const user_action_arg_t arg;
} keybinding_t;
typedef struct color_t {
uint32_t rgba;
uint32_t argb;

View File

@@ -2,8 +2,10 @@
#include <X11/cursorfont.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <xcb/xproto.h>
#include "types.h"
bool has_other_wm_running(void);
int get_xcb_connection_fd(void);
@@ -56,6 +58,8 @@ window_list_t *scan_window_list(void);
void free_window_list(window_list_t *window_list);
void clean_xcb(void);
void grab_keybindings(const keybinding_t *keys, const size_t length);
bool get_xresource_uint32(const char *name, uint32_t *value);
void get_xresource_string(const char *name, char **value, const char *fallback);
void clean_xresource(void);

View File

@@ -8,8 +8,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wordexp.h>
#include "action.h"
#include "config.h"
#include "event-adapter.h"
#include "renderer.h"
@@ -30,6 +32,8 @@ static void init_monitor_bar(void);
static void get_xresource_config(void);
static void update_bars(void);
static void init_xcb_event_loop(void);
static void xcb_event_handler(generic_event_t *event, void *user_data);
static void key_press(key_press_event_t *event);
static gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
gpointer userdata);
static void cleanup(void);
@@ -47,6 +51,16 @@ static uint32_t bar_y_pad = bar_y_padding;
static uint32_t tag_x_pad = tag_x_padding;
static uint32_t bar_height = 0;
static bool need_restart = false;
void spawn(const user_action_arg_t *arg) {
g_spawn_command_line_async(arg->ptr, NULL);
}
void quit(const user_action_arg_t *arg) {
need_restart = arg->b;
g_main_loop_quit(loop);
}
/* 调试函数,开发完成后删除 */
static void print_monitor_list_info(monitor_t *monitor_list) {
printf("========================= monitor info =========================\n");
@@ -359,6 +373,7 @@ void update_bars(void) {
void init_xcb_event_loop(void) {
adapter = create_event_adapter();
event_adapter_set_handler(adapter, xcb_event_handler, NULL);
GIOChannel *channel = g_io_channel_unix_new(get_xcb_connection_fd());
g_io_channel_set_encoding(channel, NULL, NULL);
GIOCondition cond = G_IO_IN | G_IO_HUP | G_IO_ERR;
@@ -366,6 +381,27 @@ void init_xcb_event_loop(void) {
g_io_channel_unref(channel);
}
void xcb_event_handler(generic_event_t *event, void *user_data) {
switch (event->type) {
case EVENT_TYPE_KEY_PRESS:
key_press((key_press_event_t *)event);
break;
default:
break;
}
}
void key_press(key_press_event_t *event) {
const keybinding_t *key = NULL;
for (int i = 0; i < LENGTH(keys); i++) {
key = &keys[i];
if (key->key_symbol == event->key_symbol &&
key->modifiers == event->modifiers && key->func) {
key->func(&key->arg);
}
}
}
gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
gpointer userdata) {
if (condition & (G_IO_HUP | G_IO_ERR)) {
@@ -434,6 +470,8 @@ int main(int argc, char *argv[]) {
free_window_list(window_list);
grab_keybindings(keys, LENGTH(keys));
init_xcb_event_loop();
loop = g_main_loop_new(NULL, FALSE);
@@ -441,5 +479,10 @@ int main(int argc, char *argv[]) {
cleanup();
if (need_restart) {
need_restart = false;
execvp(argv[0], argv);
}
return 0;
}

View File

@@ -29,7 +29,7 @@ static void convert_event(xcb_generic_event_t *xcb_event,
int col = ev->state & XCB_MOD_MASK_2 ? 1 : 0;
xcb_keysym_t keysym = xcb_key_press_lookup_keysym(key_symbols, ev, col);
event->key_press.type = EVENT_TYPE_KEY_PRESS;
event->key_press.key_symbols = keysym;
event->key_press.key_symbol = keysym;
event->key_press.modifiers = ev->state;
break;
}

View File

@@ -297,3 +297,28 @@ void clean_xcb(void) {
conn = NULL;
screen = NULL;
}
void grab_keybindings(const keybinding_t *keys, const size_t length) {
xcb_window_t root = screen->root;
xcb_keycode_t key = XCB_GRAB_ANY;
xcb_ungrab_key(conn, key, root, XCB_MOD_MASK_ANY);
key_symbols = xcb_key_symbols_alloc(conn);
xcb_grab_mode_t mode = XCB_GRAB_MODE_ASYNC;
xcb_keycode_t *keycode = NULL;
xcb_mod_mask_t modifiers;
xcb_void_cookie_t cookie;
xcb_generic_error_t *error = NULL;
for (int i = 0; i < length; i++) {
xcb_keysym_t keysym = keys[i].key_symbol;
keycode = xcb_key_symbols_get_keycode(key_symbols, keysym);
modifiers = keys[i].modifiers;
cookie = xcb_grab_key(conn, key, root, modifiers, *keycode, mode, mode);
error = xcb_request_check(conn, cookie);
if (error) {
clean_xcb();
die("%scannot grap key", APP_NAME);
}
}
}