From 8d1b5c760098961501d3ece510a417a44fecd212 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 28 Mar 2018 00:04:32 -0400 Subject: backend/x11: correctly update keyboard modifiers --- backend/x11/backend.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'backend/x11/backend.c') diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 36d72d9e..79b896fe 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef __linux__ #include #elif __FreeBSD__ @@ -30,6 +31,10 @@ static const struct wlr_backend_impl backend_impl; static const struct wlr_output_impl output_impl; static const struct wlr_input_device_impl input_device_impl = { 0 }; +// TODO: remove global state +static uint8_t xkb_base_event; +static uint8_t xkb_base_error; + static uint32_t xcb_button_to_wl(uint32_t button) { switch (button) { case XCB_BUTTON_INDEX_1: return BTN_LEFT; @@ -157,6 +162,12 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e break; } default: + if (event->response_type == xkb_base_event) { + xcb_xkb_state_notify_event_t *ev = + (xcb_xkb_state_notify_event_t *)event; + wlr_keyboard_notify_modifiers(&x11->keyboard, ev->baseMods, + ev->latchedMods, ev->lockedMods, ev->lockedGroup); + } break; } @@ -225,6 +236,28 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { x11->screen->root, 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, x11->screen->root_visual, mask, values); + const xcb_query_extension_reply_t *reply = + xcb_get_extension_data(x11->xcb_conn, &xcb_xkb_id); + if (reply->present) { + xkb_base_event = reply->first_event; + xkb_base_error = reply->first_error; + + xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension( + x11->xcb_conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); + xcb_xkb_use_extension_reply_t *reply = + xcb_xkb_use_extension_reply(x11->xcb_conn, cookie, NULL); + if (reply && reply->supported) { + xcb_xkb_select_events(x11->xcb_conn, + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY, + 0, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY, + 0, + 0, + 0); + } + } + output->surf = wlr_egl_create_surface(&x11->egl, &output->win); if (!output->surf) { wlr_log(L_ERROR, "Failed to create EGL surface"); -- cgit v1.2.3 From f033f717a27b1ea0974db43118312c8b05587fec Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 28 Mar 2018 00:26:15 -0400 Subject: backend/x11: make xcb-xkb optional, remove global state --- backend/x11/backend.c | 61 ++++++++++++++++++++++++++++----------------------- include/backend/x11.h | 6 +++++ meson.build | 6 ++++- 3 files changed, 44 insertions(+), 29 deletions(-) (limited to 'backend/x11/backend.c') diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 79b896fe..7d560d97 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -16,12 +17,14 @@ #include #include #include -#include #ifdef __linux__ #include #elif __FreeBSD__ #include #endif +#ifdef WLR_HAS_XCB_XKB +#include +#endif #include "backend/x11.h" #include "util/signal.h" @@ -31,10 +34,6 @@ static const struct wlr_backend_impl backend_impl; static const struct wlr_output_impl output_impl; static const struct wlr_input_device_impl input_device_impl = { 0 }; -// TODO: remove global state -static uint8_t xkb_base_event; -static uint8_t xkb_base_error; - static uint32_t xcb_button_to_wl(uint32_t button) { switch (button) { case XCB_BUTTON_INDEX_1: return BTN_LEFT; @@ -162,12 +161,14 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e break; } default: - if (event->response_type == xkb_base_event) { +#ifdef WLR_HAS_XCB_XKB + if (x11->xkb_supported && event->response_type == x11->xkb_base_event) { xcb_xkb_state_notify_event_t *ev = (xcb_xkb_state_notify_event_t *)event; wlr_keyboard_notify_modifiers(&x11->keyboard, ev->baseMods, ev->latchedMods, ev->lockedMods, ev->lockedGroup); } +#endif break; } @@ -236,28 +237,6 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { x11->screen->root, 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, x11->screen->root_visual, mask, values); - const xcb_query_extension_reply_t *reply = - xcb_get_extension_data(x11->xcb_conn, &xcb_xkb_id); - if (reply->present) { - xkb_base_event = reply->first_event; - xkb_base_error = reply->first_error; - - xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension( - x11->xcb_conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); - xcb_xkb_use_extension_reply_t *reply = - xcb_xkb_use_extension_reply(x11->xcb_conn, cookie, NULL); - if (reply && reply->supported) { - xcb_xkb_select_events(x11->xcb_conn, - XCB_XKB_ID_USE_CORE_KBD, - XCB_XKB_EVENT_TYPE_STATE_NOTIFY, - 0, - XCB_XKB_EVENT_TYPE_STATE_NOTIFY, - 0, - 0, - 0); - } - } - output->surf = wlr_egl_create_surface(&x11->egl, &output->win); if (!output->surf) { wlr_log(L_ERROR, "Failed to create EGL surface"); @@ -315,6 +294,32 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { strlen(title), title); } +#ifdef WLR_HAS_XCB_XKB + const xcb_query_extension_reply_t *reply = + xcb_get_extension_data(x11->xcb_conn, &xcb_xkb_id); + if (reply != NULL && reply->present) { + x11->xkb_base_event = reply->first_event; + x11->xkb_base_error = reply->first_error; + + xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension( + x11->xcb_conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); + xcb_xkb_use_extension_reply_t *reply = + xcb_xkb_use_extension_reply(x11->xcb_conn, cookie, NULL); + if (reply != NULL && reply->supported) { + x11->xkb_supported = true; + + xcb_xkb_select_events(x11->xcb_conn, + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY, + 0, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY, + 0, + 0, + 0); + } + } +#endif + xcb_map_window(x11->xcb_conn, output->win); xcb_flush(x11->xcb_conn); wlr_output_update_enabled(&output->wlr_output, true); diff --git a/include/backend/x11.h b/include/backend/x11.h index 840509bf..72710f6c 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -48,6 +48,12 @@ struct wlr_x11_backend { // The time we last received an event xcb_timestamp_t time; +#ifdef WLR_HAS_XCB_XKB + bool xkb_supported; + uint8_t xkb_base_event; + uint8_t xkb_base_error; +#endif + struct wl_listener display_destroy; }; diff --git a/meson.build b/meson.build index a48984c1..04c93817 100644 --- a/meson.build +++ b/meson.build @@ -85,18 +85,22 @@ if get_option('enable_x11_backend') or get_option('enable_xwayland') xcb = dependency('xcb') xcb_composite = dependency('xcb-composite') xcb_xfixes = dependency('xcb-xfixes') - xcb_xkb = dependency('xcb-xkb') # TODO: make this optional xcb_image = dependency('xcb-image') xcb_render = dependency('xcb-render') x11_xcb = dependency('x11-xcb') xcb_icccm = dependency('xcb-icccm', required: false) + xcb_xkb = dependency('xcb-xkb', required: false) xcb_errors = dependency('xcb-errors', required: get_option('enable_xcb_errors') == 'true') if xcb_icccm.found() conf_data.set('WLR_HAS_XCB_ICCCM', true) endif + if xcb_xkb.found() + conf_data.set('WLR_HAS_XCB_XKB', true) + endif + if xcb_errors.found() and get_option('enable_xcb_errors') != 'false' conf_data.set('WLR_HAS_XCB_ERRORS', true) endif -- cgit v1.2.3 From a35a5786b0e40cb1ffa87344d3cb21dff9fd99f4 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 10:46:50 -0400 Subject: Remove width_mm from wlr_pointer events --- backend/libinput/pointer.c | 5 ++--- backend/wayland/wl_seat.c | 6 ++---- backend/x11/backend.c | 12 ++++-------- examples/multi-pointer.c | 3 +-- examples/pointer.c | 6 +++--- examples/support/shared.c | 4 ++-- include/wlr/types/wlr_cursor.h | 2 +- include/wlr/types/wlr_pointer.h | 4 ++-- rootston/cursor.c | 4 ++-- types/wlr_cursor.c | 6 +++--- 10 files changed, 22 insertions(+), 30 deletions(-) (limited to 'backend/x11/backend.c') diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 8a31d312..9ccda634 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -53,9 +53,8 @@ void handle_pointer_motion_abs(struct libinput_event *event, wlr_event.device = wlr_dev; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); - wlr_event.x_mm = libinput_event_pointer_get_absolute_x(pevent); - wlr_event.y_mm = libinput_event_pointer_get_absolute_y(pevent); - libinput_device_get_size(libinput_dev, &wlr_event.width_mm, &wlr_event.height_mm); + wlr_event.x = libinput_event_pointer_get_absolute_x_transformed(pevent, 1); + wlr_event.y = libinput_event_pointer_get_absolute_y_transformed(pevent, 1); wlr_signal_emit_safe(&wlr_dev->pointer->events.motion_absolute, &wlr_event); } diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c index 6ca59130..2d4f76de 100644 --- a/backend/wayland/wl_seat.c +++ b/backend/wayland/wl_seat.c @@ -80,10 +80,8 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, struct wlr_event_pointer_motion_absolute wlr_event; wlr_event.device = dev; wlr_event.time_msec = time; - wlr_event.width_mm = layout_box.width; - wlr_event.height_mm = layout_box.height; - wlr_event.x_mm = transformed.x + wlr_output->lx - layout_box.x; - wlr_event.y_mm = transformed.y + wlr_output->ly - layout_box.y; + wlr_event.x = transformed.x / layout_box.width; + wlr_event.y = transformed.y / layout_box.height; wlr_signal_emit_safe(&dev->pointer->events.motion_absolute, &wlr_event); } diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 36d72d9e..f534676d 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -108,10 +108,8 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e struct wlr_event_pointer_motion_absolute abs = { .device = &x11->pointer_dev, .time_msec = ev->time, - .x_mm = ev->event_x, - .y_mm = ev->event_y, - .width_mm = output->wlr_output.width, - .height_mm = output->wlr_output.height, + .x = (double)ev->event_x / output->wlr_output.width, + .y = (double)ev->event_y / output->wlr_output.height, }; wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs); @@ -136,10 +134,8 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e struct wlr_event_pointer_motion_absolute abs = { .device = &x11->pointer_dev, .time_msec = x11->time, - .x_mm = pointer->root_x, - .y_mm = pointer->root_y, - .width_mm = output->wlr_output.width, - .height_mm = output->wlr_output.height, + .x = (double)pointer->root_x / output->wlr_output.width, + .y = (double)pointer->root_y / output->wlr_output.height, }; wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs); diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c index 1f869f50..46f0e78f 100644 --- a/examples/multi-pointer.c +++ b/examples/multi-pointer.c @@ -118,8 +118,7 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, struct sample_cursor *cursor = wl_container_of(listener, cursor, cursor_motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; - wlr_cursor_warp_absolute(cursor->cursor, event->device, - event->x_mm / event->width_mm, event->y_mm / event->height_mm); + wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); } static void handle_input_add(struct compositor_state *state, diff --git a/examples/pointer.c b/examples/pointer.c index 9794e6e5..12312092 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -154,8 +154,8 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, wl_container_of(listener, sample, cursor_motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; - sample->cur_x = event->x_mm; - sample->cur_y = event->y_mm; + sample->cur_x = event->x; + sample->cur_y = event->y; wlr_cursor_warp_absolute(sample->cursor, event->device, sample->cur_x, sample->cur_y); @@ -252,7 +252,7 @@ static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) && (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { wlr_cursor_warp_absolute(sample->cursor, event->device, - event->x_mm / event->width_mm, event->y_mm / event->height_mm); + event->x_mm / event->width_mm, event->y_mm / event->height_mm); } } diff --git a/examples/support/shared.c b/examples/support/shared.c index e6233206..c6460374 100644 --- a/examples/support/shared.c +++ b/examples/support/shared.c @@ -108,8 +108,8 @@ static void pointer_motion_absolute_notify(struct wl_listener *listener, void *d struct wlr_event_pointer_motion_absolute *event = data; struct pointer_state *pstate = wl_container_of(listener, pstate, motion_absolute); if (pstate->compositor->pointer_motion_absolute_cb) { - pstate->compositor->pointer_motion_absolute_cb(pstate, - event->x_mm, event->y_mm); + pstate->compositor->pointer_motion_absolute_cb( + pstate, event->x, event->y); } } diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 70dca9f7..ffe149c9 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -73,7 +73,7 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, double x, double y); void wlr_cursor_warp_absolute(struct wlr_cursor *cur, - struct wlr_input_device *dev, double x_mm, double y_mm); + struct wlr_input_device *dev, double x, double y); /** * Move the cursor in the direction of the given x and y coordinates. diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index e7ac9b46..a8969b9e 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -29,8 +29,8 @@ struct wlr_event_pointer_motion { struct wlr_event_pointer_motion_absolute { struct wlr_input_device *device; uint32_t time_msec; - double x_mm, y_mm; - double width_mm, height_mm; + // From 0..1 + double x, y; }; struct wlr_event_pointer_button { diff --git a/rootston/cursor.c b/rootston/cursor.c index 52439dff..c1fd7d31 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -288,8 +288,8 @@ void roots_cursor_handle_motion(struct roots_cursor *cursor, void roots_cursor_handle_motion_absolute(struct roots_cursor *cursor, struct wlr_event_pointer_motion_absolute *event) { - wlr_cursor_warp_absolute(cursor->cursor, event->device, - event->x_mm / event->width_mm, event->y_mm / event->height_mm); + wlr_cursor_warp_absolute(cursor->cursor, + event->device, event->x, event->y); roots_cursor_update_position(cursor, event->time_msec); } diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 20acebf1..ed1a67da 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -254,7 +254,7 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, } void wlr_cursor_warp_absolute(struct wlr_cursor *cur, - struct wlr_input_device *dev, double x_mm, double y_mm) { + struct wlr_input_device *dev, double x, double y) { assert(cur->state->layout); struct wlr_box *mapping = get_mapping(cur, dev); @@ -262,8 +262,8 @@ void wlr_cursor_warp_absolute(struct wlr_cursor *cur, mapping = wlr_output_layout_get_box(cur->state->layout, NULL); } - double x = x_mm > 0 ? mapping->width * x_mm + mapping->x : cur->x; - double y = y_mm > 0 ? mapping->height * y_mm + mapping->y : cur->y; + x = x > 0 ? mapping->width * x + mapping->x : cur->x; + y = y > 0 ? mapping->height * y + mapping->y : cur->y; wlr_cursor_warp_unchecked(cur, x, y); } -- cgit v1.2.3 From d4f7ced6e260961f701f73f672fffa87ee333c3d Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 21:40:43 -0400 Subject: backend/x11: refactor, prepare support for multiple outputs --- backend/meson.build | 6 +- backend/x11/backend.c | 300 +++++++-------------------------------------- backend/x11/input_device.c | 122 ++++++++++++++++++ backend/x11/output.c | 170 +++++++++++++++++++++++++ include/backend/x11.h | 24 +++- 5 files changed, 365 insertions(+), 257 deletions(-) create mode 100644 backend/x11/input_device.c create mode 100644 backend/x11/output.c (limited to 'backend/x11/backend.c') diff --git a/backend/meson.build b/backend/meson.build index df12d703..52abe64d 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -50,7 +50,11 @@ if conf_data.get('WLR_HAS_SYSTEMD', false) endif if conf_data.get('WLR_HAS_X11_BACKEND', false) - backend_files += files('x11/backend.c') + backend_files += files( + 'x11/backend.c', + 'x11/input_device.c', + 'x11/output.c', + ) backend_deps += xcb_xkb endif diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 8abc5d84..c72cdcac 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -1,5 +1,4 @@ #define _POSIX_C_SOURCE 200112L -#include #include #include #include @@ -10,162 +9,66 @@ #include #include #include -#include #include #include #include #include #include #include -#ifdef __linux__ -#include -#elif __FreeBSD__ -#include -#endif #ifdef WLR_HAS_XCB_XKB #include #endif #include "backend/x11.h" #include "util/signal.h" -#define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f - -static const struct wlr_backend_impl backend_impl; -static const struct wlr_output_impl output_impl; -static const struct wlr_input_device_impl input_device_impl = { 0 }; - -static uint32_t xcb_button_to_wl(uint32_t button) { - switch (button) { - case XCB_BUTTON_INDEX_1: return BTN_LEFT; - case XCB_BUTTON_INDEX_2: return BTN_MIDDLE; - case XCB_BUTTON_INDEX_3: return BTN_RIGHT; - // XXX: I'm not sure the scroll-wheel direction is right - case XCB_BUTTON_INDEX_4: return BTN_GEAR_UP; - case XCB_BUTTON_INDEX_5: return BTN_GEAR_DOWN; - default: return 0; +struct wlr_x11_output *x11_output_from_window_id(struct wlr_x11_backend *x11, + xcb_window_t window) { + struct wlr_x11_output *output; + wl_list_for_each(output, &x11->outputs, link) { + if (output->win == window) { + return output; + } } + return NULL; } -static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *event) { - struct wlr_x11_output *output = &x11->output; +static bool handle_x11_event(struct wlr_x11_backend *x11, + xcb_generic_event_t *event) { + if (x11_handle_input_event(x11, event)) { + return false; + } switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { case XCB_EXPOSE: { - wlr_output_send_frame(&output->wlr_output); - break; - } - case XCB_KEY_PRESS: - case XCB_KEY_RELEASE: { - xcb_key_press_event_t *ev = (xcb_key_press_event_t *)event; - struct wlr_event_keyboard_key key = { - .time_msec = ev->time, - .keycode = ev->detail - 8, - .state = event->response_type == XCB_KEY_PRESS ? - WLR_KEY_PRESSED : WLR_KEY_RELEASED, - .update_state = true, - }; - - // TODO use xcb-xkb for more precise modifiers state? - wlr_keyboard_notify_key(&x11->keyboard, &key); - x11->time = ev->time; - break; - } - case XCB_BUTTON_PRESS: { - xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; - - if (ev->detail == XCB_BUTTON_INDEX_4 || - ev->detail == XCB_BUTTON_INDEX_5) { - double delta = (ev->detail == XCB_BUTTON_INDEX_4 ? -15 : 15); - struct wlr_event_pointer_axis axis = { - .device = &x11->pointer_dev, - .time_msec = ev->time, - .source = WLR_AXIS_SOURCE_WHEEL, - .orientation = WLR_AXIS_ORIENTATION_VERTICAL, - .delta = delta, - }; - wlr_signal_emit_safe(&x11->pointer.events.axis, &axis); - x11->time = ev->time; - break; - } - } - /* fallthrough */ - case XCB_BUTTON_RELEASE: { - xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; - - if (ev->detail != XCB_BUTTON_INDEX_4 && - ev->detail != XCB_BUTTON_INDEX_5) { - struct wlr_event_pointer_button button = { - .device = &x11->pointer_dev, - .time_msec = ev->time, - .button = xcb_button_to_wl(ev->detail), - .state = event->response_type == XCB_BUTTON_PRESS ? - WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED, - }; - - wlr_signal_emit_safe(&x11->pointer.events.button, &button); + xcb_expose_event_t *ev = (xcb_expose_event_t *)event; + struct wlr_x11_output *output = + x11_output_from_window_id(x11, ev->window); + if (output != NULL) { + wlr_output_send_frame(&output->wlr_output); } - x11->time = ev->time; - break; - } - case XCB_MOTION_NOTIFY: { - xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event; - struct wlr_event_pointer_motion_absolute abs = { - .device = &x11->pointer_dev, - .time_msec = ev->time, - .x = (double)ev->event_x / output->wlr_output.width, - .y = (double)ev->event_y / output->wlr_output.height, - }; - - wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs); - x11->time = ev->time; break; } case XCB_CONFIGURE_NOTIFY: { - xcb_configure_notify_event_t *ev = (xcb_configure_notify_event_t *)event; - - wlr_output_update_custom_mode(&output->wlr_output, ev->width, - ev->height, 0); - - // Move the pointer to its new location - xcb_query_pointer_cookie_t cookie = - xcb_query_pointer(x11->xcb_conn, output->win); - xcb_query_pointer_reply_t *pointer = - xcb_query_pointer_reply(x11->xcb_conn, cookie, NULL); - if (!pointer) { - break; + xcb_configure_notify_event_t *ev = + (xcb_configure_notify_event_t *)event; + struct wlr_x11_output *output = + x11_output_from_window_id(x11, ev->window); + if (output != NULL) { + x11_output_handle_configure_notify(output, ev); } - - struct wlr_event_pointer_motion_absolute abs = { - .device = &x11->pointer_dev, - .time_msec = x11->time, - .x = (double)pointer->root_x / output->wlr_output.width, - .y = (double)pointer->root_y / output->wlr_output.height, - }; - - wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs); - free(pointer); break; } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t *ev = (xcb_client_message_event_t *)event; - if (ev->data.data32[0] == x11->atoms.wm_delete_window) { - wl_display_terminate(x11->wl_display); - return true; + struct wlr_x11_output *output = + x11_output_from_window_id(x11, ev->window); + if (output != NULL) { + wlr_output_destroy(&output->wlr_output); + } } - break; } - default: -#ifdef WLR_HAS_XCB_XKB - if (x11->xkb_supported && event->response_type == x11->xkb_base_event) { - xcb_xkb_state_notify_event_t *ev = - (xcb_xkb_state_notify_event_t *)event; - wlr_keyboard_notify_modifiers(&x11->keyboard, ev->baseMods, - ev->latchedMods, ev->lockedMods, ev->lockedGroup); - } -#endif - break; } return false; @@ -180,64 +83,19 @@ static int x11_event(int fd, uint32_t mask, void *data) { } xcb_generic_event_t *e; - bool quit = false; - while (!quit && (e = xcb_poll_for_event(x11->xcb_conn))) { - quit = handle_x11_event(x11, e); + while ((e = xcb_poll_for_event(x11->xcb_conn))) { + bool quit = handle_x11_event(x11, e); free(e); + if (quit) { + break; + } } return 0; } -static int signal_frame(void *data) { - struct wlr_x11_backend *x11 = data; - wlr_output_send_frame(&x11->output.wlr_output); - wl_event_source_timer_update(x11->frame_timer, 16); - return 0; -} - -static void parse_xcb_setup(struct wlr_output *output, xcb_connection_t *xcb_conn) { - const xcb_setup_t *xcb_setup = xcb_get_setup(xcb_conn); - - snprintf(output->make, sizeof(output->make), "%.*s", - xcb_setup_vendor_length(xcb_setup), - xcb_setup_vendor(xcb_setup)); - snprintf(output->model, sizeof(output->model), "%"PRIu16".%"PRIu16, - xcb_setup->protocol_major_version, - xcb_setup->protocol_minor_version); -} - static bool wlr_x11_backend_start(struct wlr_backend *backend) { struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend; - struct wlr_x11_output *output = &x11->output; - - uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - uint32_t values[2] = { - x11->screen->white_pixel, - XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | - XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | - XCB_EVENT_MASK_POINTER_MOTION | - XCB_EVENT_MASK_STRUCTURE_NOTIFY - }; - - output->x11 = x11; - - wlr_output_init(&output->wlr_output, &x11->backend, &output_impl, - x11->wl_display); - snprintf(output->wlr_output.name, sizeof(output->wlr_output.name), "X11-1"); - parse_xcb_setup(&output->wlr_output, x11->xcb_conn); - - output->win = xcb_generate_id(x11->xcb_conn); - xcb_create_window(x11->xcb_conn, XCB_COPY_FROM_PARENT, output->win, - x11->screen->root, 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, - x11->screen->root_visual, mask, values); - - output->surf = wlr_egl_create_surface(&x11->egl, &output->win); - if (!output->surf) { - wlr_log(L_ERROR, "Failed to create EGL surface"); - return false; - } struct { const char *name; @@ -279,17 +137,6 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { } } - xcb_change_property(x11->xcb_conn, XCB_PROP_MODE_REPLACE, output->win, - x11->atoms.wm_protocols, XCB_ATOM_ATOM, 32, 1, - &x11->atoms.wm_delete_window); - - char title[32]; - if (snprintf(title, sizeof(title), "wlroots - %s", output->wlr_output.name)) { - xcb_change_property(x11->xcb_conn, XCB_PROP_MODE_REPLACE, output->win, - x11->atoms.net_wm_name, x11->atoms.utf8_string, 8, - strlen(title), title); - } - #ifdef WLR_HAS_XCB_XKB const xcb_query_extension_reply_t *reply = xcb_get_extension_data(x11->xcb_conn, &xcb_xkb_id); @@ -316,15 +163,12 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { } #endif - xcb_map_window(x11->xcb_conn, output->win); - xcb_flush(x11->xcb_conn); - wlr_output_update_enabled(&output->wlr_output, true); - - wlr_signal_emit_safe(&x11->backend.events.new_output, output); wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard_dev); wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->pointer_dev); - wl_event_source_timer_update(x11->frame_timer, 16); + for (size_t i = 0; i < x11->requested_outputs; ++i) { + x11_output_create(x11); + } return true; } @@ -336,8 +180,10 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) { struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend; - struct wlr_x11_output *output = &x11->output; - wlr_output_destroy(&output->wlr_output); + struct wlr_x11_output *output, *tmp; + wl_list_for_each_safe(output, tmp, &x11->outputs, link) { + wlr_output_destroy(&output->wlr_output); + } wlr_signal_emit_safe(&x11->pointer_dev.events.destroy, &x11->pointer_dev); wlr_signal_emit_safe(&x11->keyboard_dev.events.destroy, &x11->keyboard_dev); @@ -357,7 +203,6 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) { } wl_list_remove(&x11->display_destroy.link); - wl_event_source_remove(x11->frame_timer); wlr_egl_finish(&x11->egl); if (x11->xlib_conn) { @@ -403,6 +248,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, wlr_backend_init(&x11->backend, &backend_impl); x11->wl_display = display; + x11->requested_outputs = 1; + wl_list_init(&x11->outputs); x11->xlib_conn = XOpenDisplay(x11_display); if (!x11->xlib_conn) { @@ -427,8 +274,6 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, goto error_x11; } - x11->frame_timer = wl_event_loop_add_timer(ev, signal_frame, x11); - x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb_conn)).data; if (!wlr_egl_init(&x11->egl, EGL_PLATFORM_X11_KHR, x11->xlib_conn, NULL, @@ -439,6 +284,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, x11->renderer = wlr_gles2_renderer_create(&x11->backend); if (x11->renderer == NULL) { wlr_log(L_ERROR, "Failed to create renderer"); + goto error_egl; } wlr_input_device_init(&x11->keyboard_dev, WLR_INPUT_DEVICE_KEYBOARD, @@ -456,6 +302,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, return &x11->backend; +error_egl: + wlr_egl_finish(&x11->egl); error_event: wl_event_source_remove(x11->event_source); error_x11: @@ -463,59 +311,3 @@ error_x11: free(x11); return NULL; } - -static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width, - int32_t height, int32_t refresh) { - struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; - struct wlr_x11_backend *x11 = output->x11; - - const uint32_t values[] = { width, height }; - xcb_configure_window(x11->xcb_conn, output->win, - XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); - return true; -} - -static void output_transform(struct wlr_output *wlr_output, enum wl_output_transform transform) { - struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; - output->wlr_output.transform = transform; -} - -static void output_destroy(struct wlr_output *wlr_output) { - struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; - struct wlr_x11_backend *x11 = output->x11; - - eglDestroySurface(x11->egl.display, output->surf); - xcb_destroy_window(x11->xcb_conn, output->win); - // output has been allocated on the stack, do not free it -} - -static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age) { - struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; - struct wlr_x11_backend *x11 = output->x11; - - return wlr_egl_make_current(&x11->egl, output->surf, buffer_age); -} - -static bool output_swap_buffers(struct wlr_output *wlr_output, - pixman_region32_t *damage) { - struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; - struct wlr_x11_backend *x11 = output->x11; - - return wlr_egl_swap_buffers(&x11->egl, output->surf, damage); -} - -static const struct wlr_output_impl output_impl = { - .set_custom_mode = output_set_custom_mode, - .transform = output_transform, - .destroy = output_destroy, - .make_current = output_make_current, - .swap_buffers = output_swap_buffers, -}; - -bool wlr_output_is_x11(struct wlr_output *wlr_output) { - return wlr_output->impl == &output_impl; -} - -bool wlr_input_device_is_x11(struct wlr_input_device *wlr_dev) { - return wlr_dev->impl == &input_device_impl; -} diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c new file mode 100644 index 00000000..fb7f8b85 --- /dev/null +++ b/backend/x11/input_device.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#elif __FreeBSD__ +#include +#endif +#include "backend/x11.h" +#include "util/signal.h" + +static uint32_t xcb_button_to_wl(uint32_t button) { + switch (button) { + case XCB_BUTTON_INDEX_1: return BTN_LEFT; + case XCB_BUTTON_INDEX_2: return BTN_MIDDLE; + case XCB_BUTTON_INDEX_3: return BTN_RIGHT; + // XXX: I'm not sure the scroll-wheel direction is right + case XCB_BUTTON_INDEX_4: return BTN_GEAR_UP; + case XCB_BUTTON_INDEX_5: return BTN_GEAR_DOWN; + default: return 0; + } +} + +bool x11_handle_input_event(struct wlr_x11_backend *x11, + xcb_generic_event_t *event) { + switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { + case XCB_KEY_PRESS: + case XCB_KEY_RELEASE: { + xcb_key_press_event_t *ev = (xcb_key_press_event_t *)event; + struct wlr_event_keyboard_key key = { + .time_msec = ev->time, + .keycode = ev->detail - 8, + .state = event->response_type == XCB_KEY_PRESS ? + WLR_KEY_PRESSED : WLR_KEY_RELEASED, + .update_state = true, + }; + + // TODO use xcb-xkb for more precise modifiers state? + wlr_keyboard_notify_key(&x11->keyboard, &key); + x11->time = ev->time; + return true; + } + case XCB_BUTTON_PRESS: { + xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; + + if (ev->detail == XCB_BUTTON_INDEX_4 || + ev->detail == XCB_BUTTON_INDEX_5) { + double delta = (ev->detail == XCB_BUTTON_INDEX_4 ? -15 : 15); + struct wlr_event_pointer_axis axis = { + .device = &x11->pointer_dev, + .time_msec = ev->time, + .source = WLR_AXIS_SOURCE_WHEEL, + .orientation = WLR_AXIS_ORIENTATION_VERTICAL, + .delta = delta, + }; + wlr_signal_emit_safe(&x11->pointer.events.axis, &axis); + x11->time = ev->time; + break; + } + } + /* fallthrough */ + case XCB_BUTTON_RELEASE: { + xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; + + if (ev->detail != XCB_BUTTON_INDEX_4 && + ev->detail != XCB_BUTTON_INDEX_5) { + struct wlr_event_pointer_button button = { + .device = &x11->pointer_dev, + .time_msec = ev->time, + .button = xcb_button_to_wl(ev->detail), + .state = event->response_type == XCB_BUTTON_PRESS ? + WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED, + }; + + wlr_signal_emit_safe(&x11->pointer.events.button, &button); + } + x11->time = ev->time; + return true; + } + case XCB_MOTION_NOTIFY: { + xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event; + + struct wlr_x11_output *output = + x11_output_from_window_id(x11, ev->event); + if (output == NULL) { + return false; + } + + struct wlr_event_pointer_motion_absolute abs = { + .device = &x11->pointer_dev, + .time_msec = ev->time, + .x = (double)ev->event_x / output->wlr_output.width, + .y = (double)ev->event_y / output->wlr_output.height, + }; + + wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs); + x11->time = ev->time; + return true; + } + default: +#ifdef WLR_HAS_XCB_XKB + if (x11->xkb_supported && event->response_type == x11->xkb_base_event) { + xcb_xkb_state_notify_event_t *ev = + (xcb_xkb_state_notify_event_t *)event; + wlr_keyboard_notify_modifiers(&x11->keyboard, ev->baseMods, + ev->latchedMods, ev->lockedMods, ev->lockedGroup); + return true; + } +#endif + break; + } + + return false; +} + +const struct wlr_input_device_impl input_device_impl = { 0 }; + +bool wlr_input_device_is_x11(struct wlr_input_device *wlr_dev) { + return wlr_dev->impl == &input_device_impl; +} diff --git a/backend/x11/output.c b/backend/x11/output.c new file mode 100644 index 00000000..f039baad --- /dev/null +++ b/backend/x11/output.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include "backend/x11.h" +#include "util/signal.h" + +static int signal_frame(void *data) { + struct wlr_x11_output *output = data; + wlr_output_send_frame(&output->wlr_output); + wl_event_source_timer_update(output->frame_timer, output->frame_delay); + return 0; +} + +static void parse_xcb_setup(struct wlr_output *output, xcb_connection_t *xcb_conn) { + const xcb_setup_t *xcb_setup = xcb_get_setup(xcb_conn); + + snprintf(output->make, sizeof(output->make), "%.*s", + xcb_setup_vendor_length(xcb_setup), + xcb_setup_vendor(xcb_setup)); + snprintf(output->model, sizeof(output->model), "%"PRIu16".%"PRIu16, + xcb_setup->protocol_major_version, + xcb_setup->protocol_minor_version); +} + +static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width, + int32_t height, int32_t refresh) { + struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; + struct wlr_x11_backend *x11 = output->x11; + + wlr_output_update_custom_mode(&output->wlr_output, wlr_output->width, + wlr_output->height, refresh); + output->frame_delay = 1000000 / refresh; + + const uint32_t values[] = { width, height }; + xcb_configure_window(x11->xcb_conn, output->win, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); + return true; +} + +static void output_transform(struct wlr_output *wlr_output, + enum wl_output_transform transform) { + struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; + output->wlr_output.transform = transform; +} + +static void output_destroy(struct wlr_output *wlr_output) { + struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; + struct wlr_x11_backend *x11 = output->x11; + + wl_list_remove(&output->link); + wl_event_source_remove(output->frame_timer); + eglDestroySurface(x11->egl.display, output->surf); + xcb_destroy_window(x11->xcb_conn, output->win); + free(output); +} + +static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age) { + struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; + struct wlr_x11_backend *x11 = output->x11; + + return wlr_egl_make_current(&x11->egl, output->surf, buffer_age); +} + +static bool output_swap_buffers(struct wlr_output *wlr_output, + pixman_region32_t *damage) { + struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; + struct wlr_x11_backend *x11 = output->x11; + + return wlr_egl_swap_buffers(&x11->egl, output->surf, damage); +} + +static const struct wlr_output_impl output_impl = { + .set_custom_mode = output_set_custom_mode, + .transform = output_transform, + .destroy = output_destroy, + .make_current = output_make_current, + .swap_buffers = output_swap_buffers, +}; + +struct wlr_x11_output *x11_output_create(struct wlr_x11_backend *x11) { + struct wlr_x11_output *output = calloc(1, sizeof(struct wlr_x11_output)); + if (output == NULL) { + return NULL; + } + output->x11 = x11; + output->frame_delay = 16; // 60 Hz + + struct wlr_output *wlr_output = &output->wlr_output; + wlr_output_init(wlr_output, &x11->backend, &output_impl, x11->wl_display); + + snprintf(wlr_output->name, sizeof(wlr_output->name), "X11-1"); + parse_xcb_setup(wlr_output, x11->xcb_conn); + + uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + uint32_t values[2] = { + x11->screen->white_pixel, + XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_POINTER_MOTION | + XCB_EVENT_MASK_STRUCTURE_NOTIFY + }; + output->win = xcb_generate_id(x11->xcb_conn); + xcb_create_window(x11->xcb_conn, XCB_COPY_FROM_PARENT, output->win, + x11->screen->root, 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, + x11->screen->root_visual, mask, values); + + output->surf = wlr_egl_create_surface(&x11->egl, &output->win); + if (!output->surf) { + wlr_log(L_ERROR, "Failed to create EGL surface"); + free(output); + return NULL; + } + + xcb_change_property(x11->xcb_conn, XCB_PROP_MODE_REPLACE, output->win, + x11->atoms.wm_protocols, XCB_ATOM_ATOM, 32, 1, + &x11->atoms.wm_delete_window); + + char title[32]; + if (snprintf(title, sizeof(title), "wlroots - %s", wlr_output->name)) { + xcb_change_property(x11->xcb_conn, XCB_PROP_MODE_REPLACE, output->win, + x11->atoms.net_wm_name, x11->atoms.utf8_string, 8, + strlen(title), title); + } + + xcb_map_window(x11->xcb_conn, output->win); + xcb_flush(x11->xcb_conn); + + struct wl_event_loop *ev = wl_display_get_event_loop(x11->wl_display); + output->frame_timer = wl_event_loop_add_timer(ev, signal_frame, output); + + wl_event_source_timer_update(output->frame_timer, output->frame_delay); + wlr_output_update_enabled(wlr_output, true); + + wl_list_insert(&x11->outputs, &output->link); + wlr_signal_emit_safe(&x11->backend.events.new_output, wlr_output); + + return output; +} + +void x11_output_handle_configure_notify(struct wlr_x11_output *output, + xcb_configure_notify_event_t *ev) { + struct wlr_x11_backend *x11 = output->x11; + + wlr_output_update_custom_mode(&output->wlr_output, ev->width, + ev->height, output->wlr_output.refresh); + + // Move the pointer to its new location + xcb_query_pointer_cookie_t cookie = + xcb_query_pointer(x11->xcb_conn, output->win); + xcb_query_pointer_reply_t *pointer = + xcb_query_pointer_reply(x11->xcb_conn, cookie, NULL); + if (!pointer) { + return; + } + + struct wlr_event_pointer_motion_absolute abs = { + .device = &x11->pointer_dev, + .time_msec = x11->time, + .x = (double)pointer->root_x / output->wlr_output.width, + .y = (double)pointer->root_y / output->wlr_output.height, + }; + + wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs); + free(pointer); +} + +bool wlr_output_is_x11(struct wlr_output *wlr_output) { + return wlr_output->impl == &output_impl; +} diff --git a/include/backend/x11.h b/include/backend/x11.h index 72710f6c..92a29725 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -6,15 +6,23 @@ #include #include #include +#include +#include + +#define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f struct wlr_x11_backend; struct wlr_x11_output { struct wlr_output wlr_output; struct wlr_x11_backend *x11; + struct wl_list link; // wlr_x11_backend::outputs xcb_window_t win; EGLSurface surf; + + struct wl_event_source *frame_timer; + int frame_delay; }; struct wlr_x11_backend { @@ -25,7 +33,8 @@ struct wlr_x11_backend { xcb_connection_t *xcb_conn; xcb_screen_t *screen; - struct wlr_x11_output output; + size_t requested_outputs; + struct wl_list outputs; // wlr_x11_output::link struct wlr_keyboard keyboard; struct wlr_input_device keyboard_dev; @@ -36,7 +45,6 @@ struct wlr_x11_backend { struct wlr_egl egl; struct wlr_renderer *renderer; struct wl_event_source *event_source; - struct wl_event_source *frame_timer; struct { xcb_atom_t wm_protocols; @@ -57,4 +65,16 @@ struct wlr_x11_backend { struct wl_listener display_destroy; }; +struct wlr_x11_output *x11_output_from_window_id(struct wlr_x11_backend *x11, + xcb_window_t window); + +const struct wlr_input_device_impl input_device_impl; + +bool x11_handle_input_event(struct wlr_x11_backend *x11, + xcb_generic_event_t *event); + +struct wlr_x11_output *x11_output_create(struct wlr_x11_backend *x11); +void x11_output_handle_configure_notify(struct wlr_x11_output *output, + xcb_configure_notify_event_t *event); + #endif -- cgit v1.2.3 From 0a7a8cbd1c64e50978e846d8cf1bf8b1f6868655 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 22:09:06 -0400 Subject: backend/x11: add WLR_X11_OUTPUTS support --- backend/backend.c | 67 ++++++++++++++++++++++++++++++++--------------- backend/x11/backend.c | 3 ++- backend/x11/output.c | 20 +++++++++++--- include/backend/x11.h | 7 ++--- include/wlr/backend/x11.h | 1 + 5 files changed, 69 insertions(+), 29 deletions(-) (limited to 'backend/x11/backend.c') diff --git a/backend/backend.c b/backend/backend.c index 52344dac..ff5603bd 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -61,26 +61,48 @@ struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend) { return NULL; } +static int parse_outputs_env(const char *name) { + const char *outputs_str = getenv(name); + if (outputs_str == NULL) { + return 1; + } + + char *end; + int outputs = (int)strtol(outputs_str, &end, 10); + if (*end || outputs < 0) { + wlr_log(L_ERROR, "%s specified with invalid integer, ignoring", name); + return 1; + } + + return outputs; +} + static struct wlr_backend *attempt_wl_backend(struct wl_display *display) { struct wlr_backend *backend = wlr_wl_backend_create(display, NULL); - if (backend) { - int outputs = 1; - const char *_outputs = getenv("WLR_WL_OUTPUTS"); - if (_outputs) { - char *end; - outputs = (int)strtol(_outputs, &end, 10); - if (*end) { - wlr_log(L_ERROR, "WLR_WL_OUTPUTS specified with invalid integer, ignoring"); - outputs = 1; - } else if (outputs < 0) { - wlr_log(L_ERROR, "WLR_WL_OUTPUTS specified with negative outputs, ignoring"); - outputs = 1; - } - } - while (outputs--) { - wlr_wl_output_create(backend); - } + if (backend == NULL) { + return NULL; + } + + int outputs = parse_outputs_env("WLR_WL_OUTPUTS"); + for (int i = 0; i < outputs; ++i) { + wlr_wl_output_create(backend); } + + return backend; +} + +static struct wlr_backend *attempt_x11_backend(struct wl_display *display, + const char *x11_display) { + struct wlr_backend *backend = wlr_x11_backend_create(display, x11_display); + if (backend == NULL) { + return NULL; + } + + int outputs = parse_outputs_env("WLR_X11_OUTPUTS"); + for (int i = 0; i < outputs; ++i) { + wlr_x11_output_create(backend); + } + return backend; } @@ -91,7 +113,8 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { return NULL; } - if (getenv("WAYLAND_DISPLAY") || getenv("_WAYLAND_DISPLAY")) { + if (getenv("WAYLAND_DISPLAY") || getenv("_WAYLAND_DISPLAY") || + getenv("WAYLAND_SOCKET")) { struct wlr_backend *wl_backend = attempt_wl_backend(display); if (wl_backend) { wlr_multi_backend_add(backend, wl_backend); @@ -103,9 +126,11 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { const char *x11_display = getenv("DISPLAY"); if (x11_display) { struct wlr_backend *x11_backend = - wlr_x11_backend_create(display, x11_display); - wlr_multi_backend_add(backend, x11_backend); - return backend; + attempt_x11_backend(display, x11_display); + if (x11_backend) { + wlr_multi_backend_add(backend, x11_backend); + return backend; + } } #endif diff --git a/backend/x11/backend.c b/backend/x11/backend.c index c72cdcac..80998f3f 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -96,6 +96,7 @@ static int x11_event(int fd, uint32_t mask, void *data) { static bool wlr_x11_backend_start(struct wlr_backend *backend) { struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend; + x11->started = true; struct { const char *name; @@ -167,7 +168,7 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->pointer_dev); for (size_t i = 0; i < x11->requested_outputs; ++i) { - x11_output_create(x11); + wlr_x11_output_create(&x11->backend); } return true; diff --git a/backend/x11/output.c b/backend/x11/output.c index f039baad..9e7424d8 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -77,18 +78,29 @@ static const struct wlr_output_impl output_impl = { .swap_buffers = output_swap_buffers, }; -struct wlr_x11_output *x11_output_create(struct wlr_x11_backend *x11) { +struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { + assert(wlr_backend_is_x11(backend)); + struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend; + + if (!x11->started) { + ++x11->requested_outputs; + return NULL; + } + struct wlr_x11_output *output = calloc(1, sizeof(struct wlr_x11_output)); if (output == NULL) { return NULL; } output->x11 = x11; - output->frame_delay = 16; // 60 Hz struct wlr_output *wlr_output = &output->wlr_output; wlr_output_init(wlr_output, &x11->backend, &output_impl, x11->wl_display); - snprintf(wlr_output->name, sizeof(wlr_output->name), "X11-1"); + wlr_output->refresh = 60 * 1000000; + output->frame_delay = 16; // 60 Hz + + snprintf(wlr_output->name, sizeof(wlr_output->name), "X11-%d", + wl_list_length(&x11->outputs) + 1); parse_xcb_setup(wlr_output, x11->xcb_conn); uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; @@ -135,7 +147,7 @@ struct wlr_x11_output *x11_output_create(struct wlr_x11_backend *x11) { wl_list_insert(&x11->outputs, &output->link); wlr_signal_emit_safe(&x11->backend.events.new_output, wlr_output); - return output; + return wlr_output; } void x11_output_handle_configure_notify(struct wlr_x11_output *output, diff --git a/include/backend/x11.h b/include/backend/x11.h index 92a29725..aa058882 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -3,11 +3,12 @@ #include #include +#include +#include +#include #include #include #include -#include -#include #define XCB_EVENT_RESPONSE_TYPE_MASK 0x7f @@ -28,6 +29,7 @@ struct wlr_x11_output { struct wlr_x11_backend { struct wlr_backend backend; struct wl_display *wl_display; + bool started; Display *xlib_conn; xcb_connection_t *xcb_conn; @@ -73,7 +75,6 @@ const struct wlr_input_device_impl input_device_impl; bool x11_handle_input_event(struct wlr_x11_backend *x11, xcb_generic_event_t *event); -struct wlr_x11_output *x11_output_create(struct wlr_x11_backend *x11); void x11_output_handle_configure_notify(struct wlr_x11_output *output, xcb_configure_notify_event_t *event); diff --git a/include/wlr/backend/x11.h b/include/wlr/backend/x11.h index b22d7f68..7bc1f891 100644 --- a/include/wlr/backend/x11.h +++ b/include/wlr/backend/x11.h @@ -9,6 +9,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, const char *x11_display); +struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend); bool wlr_backend_is_x11(struct wlr_backend *backend); bool wlr_input_device_is_x11(struct wlr_input_device *device); -- cgit v1.2.3 From aa6ae710f70a1b57a71c8a900b0ef4268f60bb4b Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 22:36:04 -0400 Subject: backend/x11: fix input events --- backend/x11/backend.c | 33 +++++++++++++++++++++++++++++++++ backend/x11/input_device.c | 22 ++++++++++++++++++---- include/backend/x11.h | 2 ++ 3 files changed, 53 insertions(+), 4 deletions(-) (limited to 'backend/x11/backend.c') diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 80998f3f..82004058 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200112L +#include #include #include #include @@ -32,6 +33,38 @@ struct wlr_x11_output *x11_output_from_window_id(struct wlr_x11_backend *x11, return NULL; } +void x11_output_layout_get_box(struct wlr_x11_backend *backend, + struct wlr_box *box) { + int min_x = INT_MAX, min_y = INT_MAX; + int max_x = INT_MIN, max_y = INT_MIN; + + struct wlr_x11_output *output; + wl_list_for_each(output, &backend->outputs, link) { + struct wlr_output *wlr_output = &output->wlr_output; + + int width, height; + wlr_output_effective_resolution(wlr_output, &width, &height); + + if (wlr_output->lx < min_x) { + min_x = wlr_output->lx; + } + if (wlr_output->ly < min_y) { + min_y = wlr_output->ly; + } + if (wlr_output->lx + width > max_x) { + max_x = wlr_output->lx + width; + } + if (wlr_output->ly + height > max_y) { + max_y = wlr_output->ly + height; + } + } + + box->x = min_x; + box->y = min_y; + box->width = max_x - min_x; + box->height = max_y - min_y; +} + static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *event) { if (x11_handle_input_event(x11, event)) { diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index fb7f8b85..32b1a1ac 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -87,15 +87,29 @@ bool x11_handle_input_event(struct wlr_x11_backend *x11, if (output == NULL) { return false; } + struct wlr_output *wlr_output = &output->wlr_output; - struct wlr_event_pointer_motion_absolute abs = { + struct wlr_box box = { .x = ev->event_x, .y = ev->event_y }; + wlr_box_transform(&box, wlr_output->transform, wlr_output->width, + wlr_output->height, &box); + box.x /= wlr_output->scale; + box.y /= wlr_output->scale; + + struct wlr_box layout_box; + x11_output_layout_get_box(x11, &layout_box); + + double ox = wlr_output->lx / (double)layout_box.width; + double oy = wlr_output->ly / (double)layout_box.height; + + struct wlr_event_pointer_motion_absolute wlr_event = { .device = &x11->pointer_dev, .time_msec = ev->time, - .x = (double)ev->event_x / output->wlr_output.width, - .y = (double)ev->event_y / output->wlr_output.height, + .x = box.x / (double)layout_box.width + ox, + .y = box.y / (double)layout_box.height + oy, }; - wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs); + wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &wlr_event); + x11->time = ev->time; return true; } diff --git a/include/backend/x11.h b/include/backend/x11.h index aa058882..0426e481 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -69,6 +69,8 @@ struct wlr_x11_backend { struct wlr_x11_output *x11_output_from_window_id(struct wlr_x11_backend *x11, xcb_window_t window); +void x11_output_layout_get_box(struct wlr_x11_backend *backend, + struct wlr_box *box); const struct wlr_input_device_impl input_device_impl; -- cgit v1.2.3 From 5111f7df84cea46e1e30cc5b460568e5d46e584a Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 30 Mar 2018 23:36:05 -0400 Subject: backend/x11: fix extra output --- backend/backend.c | 10 +++++----- backend/x11/backend.c | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'backend/x11/backend.c') diff --git a/backend/backend.c b/backend/backend.c index ff5603bd..93d7e0df 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -61,7 +61,7 @@ struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend) { return NULL; } -static int parse_outputs_env(const char *name) { +static size_t parse_outputs_env(const char *name) { const char *outputs_str = getenv(name); if (outputs_str == NULL) { return 1; @@ -83,8 +83,8 @@ static struct wlr_backend *attempt_wl_backend(struct wl_display *display) { return NULL; } - int outputs = parse_outputs_env("WLR_WL_OUTPUTS"); - for (int i = 0; i < outputs; ++i) { + size_t outputs = parse_outputs_env("WLR_WL_OUTPUTS"); + for (size_t i = 0; i < outputs; ++i) { wlr_wl_output_create(backend); } @@ -98,8 +98,8 @@ static struct wlr_backend *attempt_x11_backend(struct wl_display *display, return NULL; } - int outputs = parse_outputs_env("WLR_X11_OUTPUTS"); - for (int i = 0; i < outputs; ++i) { + size_t outputs = parse_outputs_env("WLR_X11_OUTPUTS"); + for (size_t i = 0; i < outputs; ++i) { wlr_x11_output_create(backend); } diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 82004058..90658f26 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -282,7 +282,6 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, wlr_backend_init(&x11->backend, &backend_impl); x11->wl_display = display; - x11->requested_outputs = 1; wl_list_init(&x11->outputs); x11->xlib_conn = XOpenDisplay(x11_display); -- cgit v1.2.3 From 7b88ace557f6aae4b7aa41b72263c628e637a892 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 12:07:58 -0400 Subject: backend/x11: hide cursor --- backend/x11/backend.c | 12 ++++++++++++ backend/x11/output.c | 4 ++++ include/backend/x11.h | 3 +++ 3 files changed, 19 insertions(+) (limited to 'backend/x11/backend.c') diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 90658f26..225fc49d 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -171,6 +171,15 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { } } + // create a blank cursor + xcb_pixmap_t pix = xcb_generate_id(x11->xcb_conn); + xcb_create_pixmap(x11->xcb_conn, 1, pix, x11->screen->root, 1, 1); + + x11->cursor = xcb_generate_id(x11->xcb_conn); + xcb_create_cursor(x11->xcb_conn, x11->cursor, pix, pix, 0, 0, 0, 0, 0, 0, + 0, 0); + xcb_free_pixmap(x11->xcb_conn, pix); + #ifdef WLR_HAS_XCB_XKB const xcb_query_extension_reply_t *reply = xcb_get_extension_data(x11->xcb_conn, &xcb_xkb_id); @@ -239,6 +248,9 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) { wlr_egl_finish(&x11->egl); + if (x11->cursor) { + xcb_free_cursor(x11->xcb_conn, x11->cursor); + } if (x11->xlib_conn) { XCloseDisplay(x11->xlib_conn); } diff --git a/backend/x11/output.c b/backend/x11/output.c index 9e7424d8..2220bc2e 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -135,6 +135,10 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { strlen(title), title); } + uint32_t cursor_values[] = { x11->cursor }; + xcb_change_window_attributes(x11->xcb_conn, output->win, XCB_CW_CURSOR, + cursor_values); + xcb_map_window(x11->xcb_conn, output->win); xcb_flush(x11->xcb_conn); diff --git a/include/backend/x11.h b/include/backend/x11.h index 0426e481..33c9a427 100644 --- a/include/backend/x11.h +++ b/include/backend/x11.h @@ -58,6 +58,9 @@ struct wlr_x11_backend { // The time we last received an event xcb_timestamp_t time; + // A blank cursor + xcb_cursor_t cursor; + #ifdef WLR_HAS_XCB_XKB bool xkb_supported; uint8_t xkb_base_event; -- cgit v1.2.3 From 33a2eb4b7775d1a3ab2b767739c1f1f054683d22 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 18:49:43 -0400 Subject: Untie wlr_backend from wlr_renderer --- backend/drm/renderer.c | 2 +- backend/headless/backend.c | 2 +- backend/wayland/backend.c | 2 +- backend/x11/backend.c | 2 +- examples/output-layout.c | 3 ++- examples/rotation.c | 3 ++- examples/tablet.c | 3 ++- examples/touch.c | 3 ++- include/wlr/render/gles2.h | 3 ++- render/gles2/renderer.c | 5 ++--- 10 files changed, 16 insertions(+), 12 deletions(-) (limited to 'backend/x11/backend.c') diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index c1531ce3..f06de1ee 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -31,7 +31,7 @@ bool wlr_drm_renderer_init(struct wlr_drm_backend *drm, goto error_gbm; } - renderer->wlr_rend = wlr_gles2_renderer_create(&drm->backend); + renderer->wlr_rend = wlr_gles2_renderer_create(&renderer->egl); if (!renderer->wlr_rend) { wlr_log(L_ERROR, "Failed to create WLR renderer"); goto error_egl; diff --git a/backend/headless/backend.c b/backend/headless/backend.c index 663bc13b..5bc48240 100644 --- a/backend/headless/backend.c +++ b/backend/headless/backend.c @@ -114,7 +114,7 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_display *display) { return NULL; } - backend->renderer = wlr_gles2_renderer_create(&backend->backend); + backend->renderer = wlr_gles2_renderer_create(&backend->egl); if (backend->renderer == NULL) { wlr_log(L_ERROR, "Failed to create renderer"); } diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index abb25df5..0135f7c5 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -212,7 +212,7 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, const char backend->remote_display, NULL, WL_SHM_FORMAT_ARGB8888); wlr_egl_bind_display(&backend->egl, backend->local_display); - backend->renderer = wlr_gles2_renderer_create(&backend->backend); + backend->renderer = wlr_gles2_renderer_create(&backend->egl); if (backend->renderer == NULL) { wlr_log_errno(L_ERROR, "Could not create renderer"); } diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 90658f26..f598aea1 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -314,7 +314,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, goto error_event; } - x11->renderer = wlr_gles2_renderer_create(&x11->backend); + x11->renderer = wlr_gles2_renderer_create(&x11->egl); if (x11->renderer == NULL) { wlr_log(L_ERROR, "Failed to create renderer"); goto error_egl; diff --git a/examples/output-layout.c b/examples/output-layout.c index c1392a30..53aae7f0 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -196,7 +196,8 @@ int main(int argc, char *argv[]) { compositor.keyboard_key_cb = handle_keyboard_key; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); state.cat_texture = wlr_texture_from_pixels(state.renderer, WL_SHM_FORMAT_ABGR8888, cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data); diff --git a/examples/rotation.c b/examples/rotation.c index dfafeeca..37873797 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -137,7 +137,8 @@ int main(int argc, char *argv[]) { compositor.keyboard_key_cb = handle_keyboard_key; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); if (!state.renderer) { wlr_log(L_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); diff --git a/examples/tablet.c b/examples/tablet.c index be428f86..d80b4b2f 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -192,7 +192,8 @@ int main(int argc, char *argv[]) { }; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); if (!state.renderer) { wlr_log(L_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); diff --git a/examples/touch.c b/examples/touch.c index e9dcf29c..16024fc8 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -108,7 +108,8 @@ int main(int argc, char *argv[]) { }; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); if (!state.renderer) { wlr_log(L_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); diff --git a/include/wlr/render/gles2.h b/include/wlr/render/gles2.h index b3b43ab2..a59956bd 100644 --- a/include/wlr/render/gles2.h +++ b/include/wlr/render/gles2.h @@ -5,6 +5,7 @@ #include struct wlr_egl; -struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend); + +struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl); #endif diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index c8094847..77af0ab7 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -400,7 +399,7 @@ extern const GLchar tex_fragment_src_rgba[]; extern const GLchar tex_fragment_src_rgbx[]; extern const GLchar tex_fragment_src_external[]; -struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) { +struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { struct wlr_gles2_renderer *renderer = calloc(1, sizeof(struct wlr_gles2_renderer)); if (renderer == NULL) { @@ -408,7 +407,7 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) { } wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl); - renderer->egl = wlr_backend_get_egl(backend); + renderer->egl = egl; wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); renderer->exts_str = (const char*) glGetString(GL_EXTENSIONS); -- cgit v1.2.3