添加快捷键设置
This commit is contained in:
6
src/action.h
Normal file
6
src/action.h
Normal 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);
|
||||
19
src/config.h
19
src/config.h
@@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "action.h"
|
||||
#include "types.h"
|
||||
|
||||
/* 壁纸列表,支持通配符和 shell 环境变量拼接,最后以 NULL 结尾 */
|
||||
/* 壁纸列表,支持通配符和 shell 环境变量拼接 */
|
||||
const char *wallpapers[] = {};
|
||||
/* 壁纸切换间隔(单位:秒),0 表示不切换 */
|
||||
const uint32_t wallpaper_interval = 0;
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ struct monitor_t {
|
||||
|
||||
/* 为了避免引入 cairo 相关头文件,这里用 void *
|
||||
* 指针代替实际的指针类型,使用时强转为相应指针类型使用即可 */
|
||||
void *cr; /* cairo_t */
|
||||
void *cr; /* cairo_t */
|
||||
|
||||
const layout_t *layout;
|
||||
monitor_t *next;
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
43
src/main.c
43
src/main.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user