From 2aed03566ca5d106db7764e61fe9c4d112128963 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Fri, 21 Nov 2025 00:39:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=82=B9=E5=87=BB=E5=88=87?= =?UTF-8?q?=E6=8D=A2=20tag=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 1 + src/event.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ src/event.h | 3 ++ src/monitor.c | 13 +++++++++ src/wm.c | 6 ++++ 5 files changed, 91 insertions(+) create mode 100644 src/event.c create mode 100644 src/event.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e70fa69..d04d8c9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,7 @@ add_executable(${APP_NAME} color.c xcursor.c xwindow.c + event.c ) # use C23 diff --git a/src/event.c b/src/event.c new file mode 100644 index 0000000..149db30 --- /dev/null +++ b/src/event.c @@ -0,0 +1,68 @@ +#include "event.h" + +#include +#include +#include +#include +#include +#include + +#include "monitor.h" +#include "types.h" +#include "utils.h" +#include "wm.h" + +static void button_press(xcb_button_press_event_t *ev) { + if (ev->event == wm.current_monitor->bar_window) { + if (ev->event_x >= wm.current_monitor->tag_extent.start && + ev->event_x <= wm.current_monitor->tag_extent.end) { + for (tag_t *tag = wm.current_monitor->tag_list; tag; tag = tag->next) { + if (ev->event_x >= tag->bar_extent.start && + ev->event_x <= tag->bar_extent.end) { + monitor_select_tag(wm.current_monitor, tag->mask); + break; + } + } + } + } +} + +static void handle_xcb_event(xcb_generic_event_t *event) { + uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(event); + + switch (event_type) { +#define EVENT(type, callback) \ + case type: \ + callback((void *)event); \ + break + + EVENT(XCB_BUTTON_PRESS, button_press); + +#undef EVENT + } +} + +static gboolean xcb_event_loop(GIOChannel *channel, GIOCondition condition, + gpointer user_data) { + if (condition & (G_IO_HUP | G_IO_ERR)) { + wm_quit(); + return false; + } + + xcb_generic_event_t *event = nullptr; + while ((event = xcb_poll_for_event(wm.xcb_conn))) { + handle_xcb_event(event); + p_delete(&event); + } + + return true; +} + +void setup_event_loop(void) { + int fd = xcb_get_file_descriptor(wm.xcb_conn); + GIOChannel *channel = g_io_channel_unix_new(fd); + g_io_channel_set_encoding(channel, nullptr, nullptr); + GIOCondition cond = G_IO_IN | G_IO_HUP | G_IO_ERR; + g_io_add_watch(channel, cond, xcb_event_loop, nullptr); + g_io_channel_unref(channel); +} diff --git a/src/event.h b/src/event.h new file mode 100644 index 0000000..ebe8685 --- /dev/null +++ b/src/event.h @@ -0,0 +1,3 @@ +#pragma once + +void setup_event_loop(void); diff --git a/src/monitor.c b/src/monitor.c index f552e8f..3767804 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -41,6 +41,19 @@ uint32_t monitor_initialize_tag(monitor_t *monitor, const char **tags, return tag_count; } +void monitor_select_tag(monitor_t *monitor, uint32_t tag_mask) { + if (monitor->selected_tag->mask == tag_mask) return; + + for (tag_t *tag = monitor->tag_list; tag; tag = tag->next) { + if (tag->mask == tag_mask) { + monitor->selected_tag = tag; + monitor_draw_bar(monitor); + xcb_flush(wm.xcb_conn); + break; + } + } +} + static void tag_clean(tag_t *tag) { tag_t *next_tag = nullptr; for (tag_t *t = tag; t; t = next_tag) { diff --git a/src/wm.c b/src/wm.c index f326eca..980a3f0 100644 --- a/src/wm.c +++ b/src/wm.c @@ -20,6 +20,7 @@ #include "buffer.h" #include "color.h" #include "default_config.h" +#include "event.h" #include "monitor.h" #include "text.h" #include "types.h" @@ -176,6 +177,7 @@ static bool wm_detect_monitor_by_randr(void) { prev_monitor->next = monitor; } else { wm.monitor_list = monitor; + wm.current_monitor = monitor; } prev_monitor = monitor; @@ -224,6 +226,7 @@ static bool wm_detect_monitor_by_xinerama(void) { prev_monitor->next = monitor; } else { wm.monitor_list = monitor; + wm.current_monitor = monitor; } prev_monitor = monitor; @@ -246,6 +249,7 @@ void wm_detect_monitor(void) { monitor->geometry.height = wm.screen->height_in_pixels; wm.monitor_list = monitor; + wm.current_monitor = monitor; } void wm_scan_clients(void) {} @@ -333,6 +337,8 @@ int main(int argc, char *argv[]) { debug_show_monitor_list(); + setup_event_loop(); + if (wm.loop == nullptr) { wm.loop = g_main_loop_new(nullptr, FALSE); g_main_loop_run(wm.loop);