aboutsummaryrefslogtreecommitdiff
path: root/src/platform/gui/xcb
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-09-09 19:10:14 +0800
committerYuqian Yang <crupest@crupest.life>2025-09-09 19:10:14 +0800
commitf761d4ef25ab0e695c79ae5c2ede1f850f1607af (patch)
treee6b674fd33d7ef3660e8c114473aa290ea3c3a4c /src/platform/gui/xcb
parent2f1ea611385b5bf8985a5b0571eb71976b9a8e52 (diff)
downloadcru-f761d4ef25ab0e695c79ae5c2ede1f850f1607af.tar.gz
cru-f761d4ef25ab0e695c79ae5c2ede1f850f1607af.tar.bz2
cru-f761d4ef25ab0e695c79ae5c2ede1f850f1607af.zip
Develop some xcb window.
Diffstat (limited to 'src/platform/gui/xcb')
-rw-r--r--src/platform/gui/xcb/UiApplication.cpp26
-rw-r--r--src/platform/gui/xcb/Window.cpp180
2 files changed, 199 insertions, 7 deletions
diff --git a/src/platform/gui/xcb/UiApplication.cpp b/src/platform/gui/xcb/UiApplication.cpp
index 139a5422..619e71ef 100644
--- a/src/platform/gui/xcb/UiApplication.cpp
+++ b/src/platform/gui/xcb/UiApplication.cpp
@@ -1,8 +1,9 @@
-#include <cru/platform/gui/xcb/UiApplication.h>
+#include "cru/platform/gui/xcb/UiApplication.h"
+
+#include "cru/platform/gui/xcb/Window.h"
#include <poll.h>
#include <xcb/xcb.h>
-#include "cru/base/Base.h"
namespace cru::platform::gui::xcb {
XcbUiApplication::XcbUiApplication() {
@@ -20,14 +21,20 @@ XcbUiApplication::XcbUiApplication() {
this->screen_ = iter.data;
}
-XcbUiApplication::~XcbUiApplication() { xcb_disconnect(this->xcb_); }
+XcbUiApplication::~XcbUiApplication() { xcb_disconnect(this->xcb_connection_); }
void XcbUiApplication::CheckXcbConnectionError() {
- if (xcb_connection_has_error(this->xcb_)) {
+ if (xcb_connection_has_error(this->xcb_connection_)) {
throw XcbException("xcb_connection_has_error returned non-zero.");
}
}
+xcb_connection_t *XcbUiApplication::GetXcbConnection() {
+ return xcb_connection_;
+}
+
+xcb_screen_t *XcbUiApplication::GetFirstXcbScreen() { return screen_; }
+
int XcbUiApplication::Run() {
auto exit_code = event_loop_.Run();
@@ -75,8 +82,15 @@ void XcbUiApplication::CancelTimer(long long id) {
void XcbUiApplication::HandleXEvents() {
xcb_generic_event_t *event;
- while ((event = xcb_poll_for_event(xcb_))) {
- NotImplemented();
+ while ((event = xcb_poll_for_event(xcb_connection_))) {
+ auto event_xcb_window = XcbWindow::GetEventWindow(event);
+ for (auto window : windows_) {
+ if (window->GetXcbWindow() == event_xcb_window) {
+ window->HandleEvent(event);
+ break;
+ }
+ }
+ ::free(event);
}
}
diff --git a/src/platform/gui/xcb/Window.cpp b/src/platform/gui/xcb/Window.cpp
index cf4e059d..3494bc7d 100644
--- a/src/platform/gui/xcb/Window.cpp
+++ b/src/platform/gui/xcb/Window.cpp
@@ -1,11 +1,189 @@
#include "cru/platform/gui/xcb/Window.h"
+#include "cru/platform/gui/Window.h"
#include "cru/platform/gui/xcb/UiApplication.h"
+#include <xcb/xcb.h>
+#include <cinttypes>
+#include <cstdint>
+
+namespace {
+// TODO: Remove this demo function.
+/* print names of modifiers present in mask */
+void print_modifiers(uint32_t mask) {
+ const char *MODIFIERS[] = {
+ "Shift", "Lock", "Ctrl", "Alt", "Mod2", "Mod3", "Mod4",
+ "Mod5", "Button1", "Button2", "Button3", "Button4", "Button5"};
+
+ printf("Modifier mask: ");
+ for (const char **modifier = MODIFIERS; mask; mask >>= 1, ++modifier) {
+ if (mask & 1) {
+ printf("%s", *modifier);
+ }
+ }
+ printf("\n");
+}
+
+} // namespace
+
namespace cru::platform::gui::xcb {
-XcbWindow::XcbWindow(XcbUiApplication* application)
+XcbWindow::XcbWindow(XcbUiApplication *application)
: application_(application) {
application->RegisterWindow(this);
}
XcbWindow::~XcbWindow() { application_->UnregisterWindow(this); }
+
+IEvent<MouseEnterLeaveType> *XcbWindow::MouseEnterLeaveEvent() {
+ return &mouse_enter_leave_event_;
+}
+
+IEvent<Point> *XcbWindow::MouseMoveEvent() { return &mouse_move_event_; }
+
+std::optional<xcb_window_t> XcbWindow::GetXcbWindow() { return xcb_window_; }
+
+xcb_window_t XcbWindow::DoCreateWindow() {
+ auto connection = application_->GetXcbConnection();
+ auto screen = application_->GetFirstXcbScreen();
+
+ auto xcb_window = xcb_generate_id(connection);
+
+ uint32_t mask = XCB_CW_EVENT_MASK;
+ uint32_t values[1] = {
+ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
+ XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
+ XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
+ XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE};
+
+ xcb_create_window(connection, XCB_COPY_FROM_PARENT, xcb_window, screen->root,
+ 100, 100, 400, 200, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ screen->root_visual, mask, values);
+
+ return xcb_window;
+}
+
+void XcbWindow::HandleEvent(xcb_generic_event_t *event) {
+ switch (event->response_type & ~0x80) {
+ case XCB_EXPOSE: {
+ xcb_expose_event_t *expose = (xcb_expose_event_t *)event;
+
+ printf("Window %" PRIu32
+ " exposed. Region to be redrawn at location (%" PRIu16 ",%" PRIu16
+ "), with dimension (%" PRIu16 ",%" PRIu16 ")\n",
+ expose->window, expose->x, expose->y, expose->width,
+ expose->height);
+ break;
+ }
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *bp = (xcb_button_press_event_t *)event;
+ print_modifiers(bp->state);
+
+ switch (bp->detail) {
+ case 4:
+ printf("Wheel Button up in window %" PRIu32
+ ", at coordinates (%" PRIi16 ",%" PRIi16 ")\n",
+ bp->event, bp->event_x, bp->event_y);
+ break;
+ case 5:
+ printf("Wheel Button down in window %" PRIu32
+ ", at coordinates (%" PRIi16 ",%" PRIi16 ")\n",
+ bp->event, bp->event_x, bp->event_y);
+ break;
+ default:
+ printf("Button %" PRIu8 " pressed in window %" PRIu32
+ ", at coordinates (%" PRIi16 ",%" PRIi16 ")\n",
+ bp->detail, bp->event, bp->event_x, bp->event_y);
+ break;
+ }
+ break;
+ }
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *br = (xcb_button_release_event_t *)event;
+ print_modifiers(br->state);
+
+ printf("Button %" PRIu8 " released in window %" PRIu32
+ ", at coordinates (%" PRIi16 ",%" PRIi16 ")\n",
+ br->detail, br->event, br->event_x, br->event_y);
+ break;
+ }
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event;
+ Point point(motion->event_x, motion->event_y);
+ mouse_move_event_.Raise(point);
+ break;
+ }
+ case XCB_ENTER_NOTIFY: {
+ xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
+ mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Enter);
+ Point point(enter->event_x, enter->event_y);
+ mouse_move_event_.Raise(point);
+ break;
+ }
+ case XCB_LEAVE_NOTIFY: {
+ xcb_leave_notify_event_t *leave = (xcb_leave_notify_event_t *)event;
+ // Should we do this?
+ // Point point(leave->event_x, leave->event_y);
+ // mouse_move_event_.Raise(point);
+ mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Leave);
+ break;
+ }
+ case XCB_KEY_PRESS: {
+ xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event;
+ print_modifiers(kp->state);
+
+ printf("Key pressed in window %" PRIu32 "\n", kp->event);
+ break;
+ }
+ case XCB_KEY_RELEASE: {
+ xcb_key_release_event_t *kr = (xcb_key_release_event_t *)event;
+ print_modifiers(kr->state);
+
+ printf("Key released in window %" PRIu32 "\n", kr->event);
+ break;
+ }
+ default:
+ /* Unknown event type, ignore it */
+ printf("Unknown event: %" PRIu8 "\n", event->response_type);
+ break;
+ }
+}
+
+std::optional<xcb_window_t> XcbWindow::GetEventWindow(
+ xcb_generic_event_t *event) {
+ switch (event->response_type & ~0x80) {
+ case XCB_EXPOSE: {
+ xcb_expose_event_t *expose = (xcb_expose_event_t *)event;
+ return expose->window;
+ }
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *bp = (xcb_button_press_event_t *)event;
+ return bp->event;
+ }
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *br = (xcb_button_release_event_t *)event;
+ return br->event;
+ }
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event;
+ return motion->event;
+ }
+ case XCB_ENTER_NOTIFY: {
+ xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
+ return enter->event;
+ }
+ case XCB_LEAVE_NOTIFY: {
+ xcb_leave_notify_event_t *leave = (xcb_leave_notify_event_t *)event;
+ return leave->event;
+ }
+ case XCB_KEY_PRESS: {
+ xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event;
+ return kp->event;
+ }
+ case XCB_KEY_RELEASE: {
+ xcb_key_release_event_t *kr = (xcb_key_release_event_t *)event;
+ return kr->event;
+ }
+ default:
+ return std::nullopt;
+ }
+}
} // namespace cru::platform::gui::xcb