very basic text input
This commit is contained in:
parent
601a0c3f06
commit
9302ac91b7
7 changed files with 349 additions and 9 deletions
6
Makefile
6
Makefile
|
@ -1,6 +1,6 @@
|
||||||
CC=clang
|
CC?=cc
|
||||||
LIBS:=`pkg-config --libs xcb cairo pangocairo` -lm
|
LIBS:=`pkg-config --libs xcb xcb-xkb cairo pangocairo xkbcommon xkbcommon-x11` -lm
|
||||||
CFLAGS:=$(CFLAGS) -pipe -Wall -Wextra -Wshadow -std=gnu99 -pedantic `pkg-config --cflags xcb cairo pangocairo`
|
CFLAGS:=$(CFLAGS) -pipe -Wall -Wextra -Wshadow -std=gnu99 -pedantic `pkg-config --cflags xcb xcb-xkb cairo pangocairo xkbcommon xkbcommon-x11`
|
||||||
|
|
||||||
BUILD=build
|
BUILD=build
|
||||||
OBJ=$(BUILD)
|
OBJ=$(BUILD)
|
||||||
|
|
14
src/main.c
14
src/main.c
|
@ -6,6 +6,7 @@
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "scrollable-node.h"
|
#include "scrollable-node.h"
|
||||||
|
#include "text-input-node.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "text-node.h"
|
#include "text-node.h"
|
||||||
#include "background-node.h"
|
#include "background-node.h"
|
||||||
|
@ -102,6 +103,19 @@ int app_handle(struct UINode *node, void *data, int event_type, size_t d, void *
|
||||||
dispatcher_new(button, UI_EVENT_UNPRESSED, DECREMENT_COUNT, state, app_handle);
|
dispatcher_new(button, UI_EVENT_UNPRESSED, DECREMENT_COUNT, state, app_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* text input test */
|
||||||
|
{
|
||||||
|
|
||||||
|
UITextInputNode *text_input = text_input_new(node);
|
||||||
|
box_layout_new(&text_input->node, UI_DIRECTION_HORIZONTAL);
|
||||||
|
background_node_new(&text_input->node, UIZinc800, 6);
|
||||||
|
text_input->node.width_policy = UI_SIZE_POLICY_STATIC;
|
||||||
|
text_input->node.height_policy = UI_SIZE_POLICY_STATIC;
|
||||||
|
text_input->node.rect.w = 120;
|
||||||
|
text_input->node.rect.h = 32;
|
||||||
|
text_input->text_node = text_node_new(&text_input->node, state->font, UINeutral50, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIDEBAR_BEGIN_ANIMATE: {
|
case SIDEBAR_BEGIN_ANIMATE: {
|
||||||
|
|
|
@ -22,6 +22,7 @@ enum UIEvent {
|
||||||
UI_EVENT_BUTTON_LEFT_UPDATE, // d == 1 if pressed, d == 0 if released
|
UI_EVENT_BUTTON_LEFT_UPDATE, // d == 1 if pressed, d == 0 if released
|
||||||
UI_EVENT_BUTTON_RIGHT_UPDATE, // d == 1 if pressed, d == 0 if released
|
UI_EVENT_BUTTON_RIGHT_UPDATE, // d == 1 if pressed, d == 0 if released
|
||||||
UI_EVENT_SCROLL, // p (double*) = delta
|
UI_EVENT_SCROLL, // p (double*) = delta
|
||||||
|
UI_EVENT_KEY_DOWN, // d (unsigned int) = keycode, p (struct xkb_state*) = xkb state
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UISizePolicy {
|
enum UISizePolicy {
|
||||||
|
@ -37,6 +38,7 @@ enum UIDirection {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define UI_NODE_COMPONENT (1 << 0)
|
#define UI_NODE_COMPONENT (1 << 0)
|
||||||
|
#define UI_NODE_RETAINS_PRESS (1 << 1)
|
||||||
|
|
||||||
typedef struct UINode {
|
typedef struct UINode {
|
||||||
const char *text;
|
const char *text;
|
||||||
|
|
47
src/text-input-node.c
Normal file
47
src/text-input-node.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include "node.h"
|
||||||
|
#include "text-node.h"
|
||||||
|
#include "text-input-node.h"
|
||||||
|
|
||||||
|
UITextInputNode *text_input_new(UINode *parent)
|
||||||
|
{
|
||||||
|
UITextInputNode *n = malloc(sizeof(UITextInputNode));
|
||||||
|
node_init(&n->node);
|
||||||
|
n->text_node = NULL;
|
||||||
|
n->node.flags = UI_NODE_RETAINS_PRESS;
|
||||||
|
n->node.text = "text_input";
|
||||||
|
n->node.handle_proto = text_input_handle;
|
||||||
|
n->text = calloc(1, 1);
|
||||||
|
n->text_size = 1;
|
||||||
|
node_attach(parent, (UINode*)n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int text_input_handle(UINode *node, enum UIEvent ev, size_t d, void *p)
|
||||||
|
{
|
||||||
|
UITextInputNode *n = (UITextInputNode *)node;
|
||||||
|
|
||||||
|
switch (ev) {
|
||||||
|
case UI_EVENT_KEY_DOWN: {
|
||||||
|
unsigned int keycode = d;
|
||||||
|
struct xkb_state *xkb_state = (struct xkb_state*)p;
|
||||||
|
|
||||||
|
size_t key_size = xkb_state_key_get_utf8(xkb_state, keycode, NULL, 0) + 1;
|
||||||
|
size_t new_text_size = n->text_size + key_size - 1;
|
||||||
|
n->text = realloc(n->text, new_text_size);
|
||||||
|
xkb_state_key_get_utf8(xkb_state, keycode, n->text + n->text_size - 1, key_size);
|
||||||
|
n->text_size = new_text_size;
|
||||||
|
|
||||||
|
if (n->text_node) {
|
||||||
|
n->text_node->pending_text = n->text;
|
||||||
|
node_request_relayout(&n->text_node->node);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
17
src/text-input-node.h
Normal file
17
src/text-input-node.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _UI__TEXT_INPUT_NODE_H
|
||||||
|
#define _UI__TEXT_INPUT_NODE_H
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
#include "text-node.h"
|
||||||
|
|
||||||
|
typedef struct UITextInputNode {
|
||||||
|
UINode node;
|
||||||
|
UITextNode *text_node;
|
||||||
|
char *text;
|
||||||
|
size_t text_size;
|
||||||
|
} UITextInputNode;
|
||||||
|
|
||||||
|
UITextInputNode *text_input_new(UINode *parent);
|
||||||
|
int text_input_handle(UINode *node, enum UIEvent ev, size_t d, void *p);
|
||||||
|
|
||||||
|
#endif // _UI__TEXT_INPUT_NODE_H
|
262
src/window.c
262
src/window.c
|
@ -4,6 +4,7 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#ifdef _UI_DEBUG
|
#ifdef _UI_DEBUG
|
||||||
#define PROF
|
#define PROF
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,8 +16,16 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
#include <xcb/xkb.h>
|
||||||
|
#include <xkbcommon/xkbcommon-x11.h>
|
||||||
|
|
||||||
void _window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event);
|
static void window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event);
|
||||||
|
static int window_select_xkb_events_for_device(UIWindow *window, int32_t device_id);
|
||||||
|
static int window_keyboard_update_keymap(UIWindow *window, UIWindowXKBKeyboard *kb);
|
||||||
|
static int window_keyboard_init(UIWindow *window, UIWindowXKBKeyboard *kb, uint8_t first_xkb_event, int32_t device_id, struct xkb_context *ctx);
|
||||||
|
static int window_init_core_xkb_keyboard(UIWindow *window);
|
||||||
|
static void window_keyboard_process_event(UIWindow *window, UIWindowXKBKeyboard *kb, xcb_generic_event_t *gevent);
|
||||||
|
static void window_keyboard_deinit(UIWindowXKBKeyboard *kb);
|
||||||
|
|
||||||
int window_invalidate_node(UIWindow *window, UINode *node)
|
int window_invalidate_node(UIWindow *window, UINode *node)
|
||||||
{
|
{
|
||||||
|
@ -43,6 +52,7 @@ void window_free(UIWindow *window)
|
||||||
if (window->_cairo_surface) cairo_surface_destroy(window->_cairo_surface);
|
if (window->_cairo_surface) cairo_surface_destroy(window->_cairo_surface);
|
||||||
if (window->drw) cairo_destroy(window->drw);
|
if (window->drw) cairo_destroy(window->drw);
|
||||||
if (window->_xcb_connection) xcb_disconnect(window->_xcb_connection);
|
if (window->_xcb_connection) xcb_disconnect(window->_xcb_connection);
|
||||||
|
window_keyboard_deinit(window->xkb_core_keyboard);
|
||||||
|
|
||||||
node_free(window->root);
|
node_free(window->root);
|
||||||
free(window);
|
free(window);
|
||||||
|
@ -112,7 +122,7 @@ UIWindow *window_new(int width, int height)
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
|
||||||
screen->root_visual, // visual
|
screen->root_visual, // visual
|
||||||
XCB_CW_EVENT_MASK, // value mask
|
XCB_CW_EVENT_MASK, // value mask
|
||||||
(uint32_t[]){ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE } // value list
|
(uint32_t[]){ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_KEY_PRESS } // value list
|
||||||
);
|
);
|
||||||
xcb_map_window(window->_xcb_connection, window->_xcb_window_id);
|
xcb_map_window(window->_xcb_connection, window->_xcb_window_id);
|
||||||
if (xcb_flush(window->_xcb_connection) <= 0) {
|
if (xcb_flush(window->_xcb_connection) <= 0) {
|
||||||
|
@ -131,6 +141,10 @@ UIWindow *window_new(int width, int height)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window_init_core_xkb_keyboard(window) < 0) {
|
||||||
|
fprintf(stderr, "err: window_new: failed to initialize keyboard (_window_init_core_xkb_keyboard failed). Keyboard input may not be available.\n");
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (fail) {
|
if (fail) {
|
||||||
window_free(window);
|
window_free(window);
|
||||||
|
@ -171,7 +185,222 @@ int window_attach_root(UIWindow *window, UINode *root)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event)
|
// Thanks: https://github.com/xkbcommon/libxkbcommon/blob/003fdee1378382d4fef77089f5f4652cd2422c6a/tools/interactive-x11.c#L67
|
||||||
|
static int window_select_xkb_events_for_device(UIWindow *window, int32_t device_id)
|
||||||
|
{
|
||||||
|
if (!window->_xcb_connection) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
required_events =
|
||||||
|
(XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
|
||||||
|
XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
|
||||||
|
XCB_XKB_EVENT_TYPE_STATE_NOTIFY),
|
||||||
|
|
||||||
|
required_nkn_details =
|
||||||
|
(XCB_XKB_NKN_DETAIL_KEYCODES),
|
||||||
|
|
||||||
|
required_map_parts =
|
||||||
|
(XCB_XKB_MAP_PART_KEY_TYPES |
|
||||||
|
XCB_XKB_MAP_PART_KEY_SYMS |
|
||||||
|
XCB_XKB_MAP_PART_MODIFIER_MAP |
|
||||||
|
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
|
||||||
|
XCB_XKB_MAP_PART_KEY_ACTIONS |
|
||||||
|
XCB_XKB_MAP_PART_VIRTUAL_MODS |
|
||||||
|
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP),
|
||||||
|
|
||||||
|
required_state_details =
|
||||||
|
(XCB_XKB_STATE_PART_MODIFIER_BASE |
|
||||||
|
XCB_XKB_STATE_PART_MODIFIER_LATCH |
|
||||||
|
XCB_XKB_STATE_PART_MODIFIER_LOCK |
|
||||||
|
XCB_XKB_STATE_PART_GROUP_BASE |
|
||||||
|
XCB_XKB_STATE_PART_GROUP_LATCH |
|
||||||
|
XCB_XKB_STATE_PART_GROUP_LOCK),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const xcb_xkb_select_events_details_t details = {
|
||||||
|
.affectNewKeyboard = required_nkn_details,
|
||||||
|
.newKeyboardDetails = required_nkn_details,
|
||||||
|
.affectState = required_state_details,
|
||||||
|
.stateDetails = required_state_details,
|
||||||
|
};
|
||||||
|
|
||||||
|
xcb_void_cookie_t cookie = xcb_xkb_select_events_aux_checked(
|
||||||
|
window->_xcb_connection,
|
||||||
|
device_id,
|
||||||
|
required_events, /* affectWhich */
|
||||||
|
0, /* clear */
|
||||||
|
0, /* selectAll */
|
||||||
|
required_map_parts, /* affectMap */
|
||||||
|
required_map_parts, /* map */
|
||||||
|
&details /* details */
|
||||||
|
);
|
||||||
|
|
||||||
|
xcb_generic_error_t *error = xcb_request_check(window->_xcb_connection, cookie);
|
||||||
|
if (error) {
|
||||||
|
free(error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int window_keyboard_update_keymap(UIWindow *window, UIWindowXKBKeyboard *kb)
|
||||||
|
{
|
||||||
|
struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device(kb->ctx, window->_xcb_connection, kb->device_id, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
if (!keymap) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xkb_state *state = xkb_x11_state_new_from_device(keymap, window->_xcb_connection, kb->device_id);
|
||||||
|
if (!state) {
|
||||||
|
xkb_keymap_unref(keymap);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xkb_state_unref(kb->state);
|
||||||
|
xkb_keymap_unref(kb->keymap);
|
||||||
|
kb->state = state;
|
||||||
|
kb->keymap = keymap;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int window_keyboard_init(UIWindow *window, UIWindowXKBKeyboard *kb, uint8_t first_xkb_event, int32_t device_id, struct xkb_context *ctx)
|
||||||
|
{
|
||||||
|
kb->first_xkb_event = first_xkb_event;
|
||||||
|
kb->device_id = device_id;
|
||||||
|
kb->ctx = ctx;
|
||||||
|
kb->keymap = NULL;
|
||||||
|
kb->state = NULL;
|
||||||
|
|
||||||
|
if (window_keyboard_update_keymap(window, kb) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_select_xkb_events_for_device(window, device_id) < 0) {
|
||||||
|
xkb_state_unref(kb->state);
|
||||||
|
xkb_keymap_unref(kb->keymap);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int window_init_core_xkb_keyboard(UIWindow *window)
|
||||||
|
{
|
||||||
|
uint8_t first_xkb_event;
|
||||||
|
int ret = 0;
|
||||||
|
UIWindowXKBKeyboard *kb = NULL;
|
||||||
|
struct xkb_context *ctx = NULL;
|
||||||
|
|
||||||
|
if (!xkb_x11_setup_xkb_extension(
|
||||||
|
window->_xcb_connection,
|
||||||
|
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||||
|
XKB_X11_MIN_MINOR_XKB_VERSION,
|
||||||
|
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
|
||||||
|
NULL, NULL, &first_xkb_event, NULL
|
||||||
|
)) {
|
||||||
|
fprintf(stderr, "err: _window_init_core_xkb_keyboard: failed to set up xkb extension (xkb_x11_setup_xkb_extension)\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
kb = malloc(sizeof(UIWindowXKBKeyboard));
|
||||||
|
if (!kb) {
|
||||||
|
fprintf(stderr, "err: _window_init_core_xkb_keyboard: failed to malloc keyboard struct\n");
|
||||||
|
ret = -1;
|
||||||
|
goto defer_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
if (!ctx) {
|
||||||
|
fprintf(stderr, "err: _window_init_core_xkb_keyboard: failed to create xkb context\n");
|
||||||
|
ret = -1;
|
||||||
|
goto defer_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t core_kbd_device_id = xkb_x11_get_core_keyboard_device_id(window->_xcb_connection);
|
||||||
|
if (core_kbd_device_id < 0) {
|
||||||
|
fprintf(stderr, "err: _window_init_core_xkb_keyboard: failed to find xkb core keyboard device_id\n");
|
||||||
|
ret = -1;
|
||||||
|
goto defer_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_keyboard_init(window, kb, first_xkb_event, core_kbd_device_id, ctx) < 0) {
|
||||||
|
fprintf(stderr, "err: _window_init_core_xkb_keyboard: failed to initialize keyboard (_window_keyboard_init)\n");
|
||||||
|
ret = -1;
|
||||||
|
goto defer_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto success;
|
||||||
|
|
||||||
|
defer_error:
|
||||||
|
free(kb);
|
||||||
|
xkb_context_unref(ctx);
|
||||||
|
return ret;
|
||||||
|
success:
|
||||||
|
window->xkb_core_keyboard = kb;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_keyboard_deinit(UIWindowXKBKeyboard *kb)
|
||||||
|
{
|
||||||
|
if (!kb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xkb_state_unref(kb->state);
|
||||||
|
xkb_keymap_unref(kb->keymap);
|
||||||
|
free(kb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_keyboard_process_event(UIWindow *window, UIWindowXKBKeyboard *kb, xcb_generic_event_t *gevent)
|
||||||
|
{
|
||||||
|
union xkb_event {
|
||||||
|
struct {
|
||||||
|
uint8_t response_type;
|
||||||
|
uint8_t xkbType;
|
||||||
|
uint16_t sequence;
|
||||||
|
xcb_timestamp_t time;
|
||||||
|
uint8_t deviceID;
|
||||||
|
} any;
|
||||||
|
xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify;
|
||||||
|
xcb_xkb_map_notify_event_t map_notify;
|
||||||
|
xcb_xkb_state_notify_event_t state_notify;
|
||||||
|
} *event = (union xkb_event *) gevent;
|
||||||
|
|
||||||
|
if (event->any.deviceID != kb->device_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event->any.xkbType) {
|
||||||
|
case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
|
||||||
|
if (event->new_keyboard_notify.changed && XCB_XKB_NKN_DETAIL_KEYCODES) {
|
||||||
|
window_keyboard_update_keymap(window, kb);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_XKB_MAP_NOTIFY: {
|
||||||
|
window_keyboard_update_keymap(window, kb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XCB_XKB_STATE_NOTIFY: {
|
||||||
|
xkb_state_update_mask(
|
||||||
|
kb->state,
|
||||||
|
event->state_notify.baseMods,
|
||||||
|
event->state_notify.latchedMods,
|
||||||
|
event->state_notify.lockedMods,
|
||||||
|
event->state_notify.baseGroup,
|
||||||
|
event->state_notify.latchedGroup,
|
||||||
|
event->state_notify.lockedGroup
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event)
|
||||||
{
|
{
|
||||||
begin_clock("Process XCB event");
|
begin_clock("Process XCB event");
|
||||||
uint8_t event_type = event->response_type & ~0x80;
|
uint8_t event_type = event->response_type & ~0x80;
|
||||||
|
@ -221,6 +450,24 @@ void _window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case XCB_KEY_PRESS: {
|
||||||
|
begin_clock("XCB_KEY_PRESS");
|
||||||
|
xcb_key_press_event_t *ev = (xcb_key_press_event_t*)event;
|
||||||
|
|
||||||
|
if (window->xkb_core_keyboard) {
|
||||||
|
UINode *n = window->pressed;
|
||||||
|
while (n) {
|
||||||
|
if (node_dispatch(n, UI_EVENT_KEY_DOWN, ev->detail, window->xkb_core_keyboard->state) > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n = n->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end_clock();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case XCB_BUTTON_RELEASE: /* through */
|
case XCB_BUTTON_RELEASE: /* through */
|
||||||
case XCB_BUTTON_PRESS: {
|
case XCB_BUTTON_PRESS: {
|
||||||
begin_clock("XCB_BUTTON_PRESS");
|
begin_clock("XCB_BUTTON_PRESS");
|
||||||
|
@ -267,8 +514,8 @@ void _window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event)
|
||||||
node_dispatch(node, UI_EVENT_PRESSED, 0, NULL);
|
node_dispatch(node, UI_EVENT_PRESSED, 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
UINode *previously_pressed = window->pressed;
|
UINode *previously_pressed = window->pressed;
|
||||||
window->pressed = NULL;
|
if (previously_pressed && !(previously_pressed->flags & UI_NODE_RETAINS_PRESS)) {
|
||||||
if (previously_pressed) {
|
window->pressed = NULL;
|
||||||
node_dispatch(previously_pressed, UI_EVENT_UNPRESSED, 0, NULL);
|
node_dispatch(previously_pressed, UI_EVENT_UNPRESSED, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,6 +526,9 @@ void _window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
|
if (window->xkb_core_keyboard && event->response_type == window->xkb_core_keyboard->first_xkb_event) {
|
||||||
|
window_keyboard_process_event(window, window->xkb_core_keyboard, event);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,7 +618,7 @@ int window_turn(UIWindow *window)
|
||||||
if ((i == 0 && fds[i].revents & POLLIN) || !has_looped_once) {
|
if ((i == 0 && fds[i].revents & POLLIN) || !has_looped_once) {
|
||||||
xcb_generic_event_t *xcb_event;
|
xcb_generic_event_t *xcb_event;
|
||||||
while ((xcb_event = xcb_poll_for_event(window->_xcb_connection))) {
|
while ((xcb_event = xcb_poll_for_event(window->_xcb_connection))) {
|
||||||
_window_process_xcb_event(window, xcb_event);
|
window_process_xcb_event(window, xcb_event);
|
||||||
free(xcb_event);
|
free(xcb_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/window.h
10
src/window.h
|
@ -18,6 +18,15 @@ typedef struct UIWindowTimer {
|
||||||
UINode *target; // TODO: what if the node gets deleted while the timer is still running?
|
UINode *target; // TODO: what if the node gets deleted while the timer is still running?
|
||||||
} UIWindowTimer;
|
} UIWindowTimer;
|
||||||
|
|
||||||
|
typedef struct UIWindowXKBKeyboard {
|
||||||
|
uint8_t first_xkb_event;
|
||||||
|
struct xkb_context *ctx;
|
||||||
|
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
struct xkb_state *state;
|
||||||
|
int32_t device_id;
|
||||||
|
} UIWindowXKBKeyboard;
|
||||||
|
|
||||||
#define UI_WINDOW_MAX_TIMERS 4
|
#define UI_WINDOW_MAX_TIMERS 4
|
||||||
#define UI_WINDOW_MAX_POLL (1)
|
#define UI_WINDOW_MAX_POLL (1)
|
||||||
|
|
||||||
|
@ -30,6 +39,7 @@ typedef struct UIWindow {
|
||||||
cairo_surface_t *_cairo_surface;
|
cairo_surface_t *_cairo_surface;
|
||||||
cairo_t *drw;
|
cairo_t *drw;
|
||||||
UIWindowTimer timers[UI_WINDOW_MAX_TIMERS];
|
UIWindowTimer timers[UI_WINDOW_MAX_TIMERS];
|
||||||
|
UIWindowXKBKeyboard *xkb_core_keyboard;
|
||||||
} UIWindow;
|
} UIWindow;
|
||||||
|
|
||||||
int window_invalidate_node(UIWindow *window, UINode *node);
|
int window_invalidate_node(UIWindow *window, UINode *node);
|
||||||
|
|
Loading…
Reference in a new issue