summaryrefslogtreecommitdiff
path: root/source/base/base_platform_linux_wayland_input.cpp
blob: 0d66fb4ce0541a4b9e94ded6306a287e9f831d2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
internal void wayland_keyboard_keymap(void *data, struct wl_keyboard *keyboard, u32 format, s32 fd, u32 size) {
    Log("<- wl_keyboard.keymap: format=%u fd=%d size=%u\n", format, fd, size);
    close(fd);
}

internal void wayland_keyboard_enter(void *data, struct wl_keyboard *keyboard, u32 serial,
                                     struct wl_surface *surface, struct wl_array *keys) {
    WaylandState *state = (WaylandState *)data;
    Log("<- wl_keyboard.enter\n");

    // wl_array is just { size_t size; size_t alloc; void *data; }. here data is a list of u32.
    u32 *key = (u32 *)keys->data;
    u32 key_count = keys->size / sizeof(u32);
    for (u32 i = 0; i < key_count; ++i) {
        if (key[i] < sizeof(state->keys_down) / sizeof(state->keys_down[0])) {
            state->keys_down[key[i]] = true;
        }
    }
}

// leave: we lost focus. after this we will NOT receive release events for keys that
// are still held, so we release everything ourselves. otherwise keys get "stuck".
internal void wayland_keyboard_leave(void *data, struct wl_keyboard *keyboard, u32 serial,
                                     struct wl_surface *surface) {
    WaylandState *state = (WaylandState *)data;
    Log("<- wl_keyboard.leave\n");

    MemSetZero(state->keys_down, sizeof(state->keys_down));
}

internal void wayland_keyboard_key(void *data, struct wl_keyboard *keyboard, u32 serial,
                                   u32 time, u32 key, u32 key_state) {
    WaylandState *state = (WaylandState *)data;
    b32 pressed = (key_state == WL_KEYBOARD_KEY_STATE_PRESSED);

    Log("<- wl_keyboard.key: key=%u %s\n", key, pressed ? "pressed" : "released");

    if (key < sizeof(state->keys_down) / sizeof(state->keys_down[0])) {
        state->keys_down[key] = pressed;
    }

    if (key == KEY_ESC && pressed) {
        state->should_close = true;
    }
}

internal void wayland_keyboard_modifiers(void *data, struct wl_keyboard *keyboard, u32 serial, u32 mods_depressed, u32 mods_latched,
                                         u32 mods_locked, u32 group) {
}

internal void wayland_keyboard_repeat_info(void *data, struct wl_keyboard *keyboard,
                                           s32 rate, s32 delay) {
    Log("<- wl_keyboard.repeat_info: rate=%d delay=%d\n", rate, delay);
}

// the listener: a struct of function pointers, one per event, in the order the events
// are declared in wayland.xml (which is also their opcode). libwayland indexes into this
// struct with the opcode it reads from the message header.
global_variable const struct wl_keyboard_listener wayland_keyboard_listener = {
    wayland_keyboard_keymap,      // opcode 0
    wayland_keyboard_enter,       // opcode 1
    wayland_keyboard_leave,       // opcode 2
    wayland_keyboard_key,         // opcode 3
    wayland_keyboard_modifiers,   // opcode 4
    wayland_keyboard_repeat_info, // opcode 5
};

//- mouse (pointer) input

enum wayland_mouse_button_pressed: b32 {

PRESSED,
RELEASED,

};

internal void wayland_button_event(void *data, struct wl_pointer *pointer,
 u32 serial, u32 time, u32 button, u32 state) {


}


internal void wayland_pointer_enter(void *data, struct wl_pointer *pointer,
 u32 serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
WaylandState *state = (WaylandState *)data;
Log("<- pointer enteirng window");
state->mouse_in_window = true;
state->x_offset = surface_x;
state->y_offset = surface_y;


}
internal void wayland_pointer_motion(void *data, struct wl_pointer *pointer, u32 time,
                                     wl_fixed_t surface_x, wl_fixed_t surface_y) {
    WaylandState *state = (WaylandState *)data;
    state->x_offset = (f32)wl_fixed_to_double(surface_x);
    state->y_offset = (f32)wl_fixed_to_double(surface_y);
}

internal void wayland_pointer_leave(void *data, struct wl_pointer *pointer, u32 serial, wl_surface *surface) {
WaylandState *state = (WaylandState *)data;
state->mouse_in_window = false;
Log("<- pointer leaving window");
}



global_variable const struct wl_pointer_listener wayland_pointer_listener = {
wayland_pointer_enter,
wayland_pointer_leave,
wayland_pointer_motion,
  wayland_button_event,
};





//- wl_seat events

// capabilities: tells us which devices this seat has, as a bitmask:
//   WL_SEAT_CAPABILITY_POINTER = 1, WL_SEAT_CAPABILITY_KEYBOARD = 2, WL_SEAT_CAPABILITY_TOUCH = 4
// this can be sent again later (keyboard unplugged / plugged in), so we handle both directions.
internal void wayland_seat_capabilities(void *data, struct wl_seat *seat, u32 capabilities) {

    WaylandState *state = (WaylandState *)data;
    b32 has_keyboard = (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0;


    Log("<- wl_seat.capabilities: %u\n", capabilities);

    if (has_keyboard && state->keyboard == NULL) {
        // get_keyboard is a request that creates a new object (a "new_id" argument).
        // libwayland allocates the id, sends the message, and hands us the proxy.
        state->keyboard = wl_seat_get_keyboard(seat);
        wl_keyboard_add_listener(state->keyboard, &wayland_keyboard_listener, state);
    } else if (!has_keyboard && state->keyboard != NULL) {
        // keyboard went away: tell the compositor we're done with the object, free the proxy.
        // the `release` request only exists since wl_seat version 3; before that we can
        // only free our side of it with destroy.
        if (wl_keyboard_get_version(state->keyboard) >= WL_KEYBOARD_RELEASE_SINCE_VERSION) {
            wl_keyboard_release(state->keyboard);
        } else {
            wl_keyboard_destroy(state->keyboard);
        }
        state->keyboard = NULL;
    }
}

// name: a human readable seat name like "seat0". only useful for multi-seat setups.
internal void wayland_seat_name(void *data, struct wl_seat *seat, const char *name) {
    Log("<- wl_seat.name: %s\n", name);
}

global_variable const struct wl_seat_listener wayland_seat_listener = {
    wayland_seat_capabilities, // opcode 0
    wayland_seat_name,         // opcode 1 (since version 2)
};