mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Merge branch 'libinput' into wayland-backend
This commit is contained in:
		
						commit
						41a477375c
					
				
					 45 changed files with 5386 additions and 2033 deletions
				
			
		
							
								
								
									
										19
									
								
								CMake/FindXKBCommon.cmake
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								CMake/FindXKBCommon.cmake
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					# - Find XKBCommon
 | 
				
			||||||
 | 
					# Once done, this will define
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   XKBCOMMON_FOUND - System has XKBCommon
 | 
				
			||||||
 | 
					#   XKBCOMMON_INCLUDE_DIRS - The XKBCommon include directories
 | 
				
			||||||
 | 
					#   XKBCOMMON_LIBRARIES - The libraries needed to use XKBCommon
 | 
				
			||||||
 | 
					#   XKBCOMMON_DEFINITIONS - Compiler switches required for using XKBCommon
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_package(PkgConfig)
 | 
				
			||||||
 | 
					pkg_check_modules(PC_XKBCOMMON QUIET xkbcommon)
 | 
				
			||||||
 | 
					find_path(XKBCOMMON_INCLUDE_DIRS NAMES xkbcommon/xkbcommon.h HINTS ${PC_XKBCOMMON_INCLUDE_DIRS})
 | 
				
			||||||
 | 
					find_library(XKBCOMMON_LIBRARIES NAMES xkbcommon HINTS ${PC_XKBCOMMON_LIBRARY_DIRS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(XKBCOMMON_DEFINITIONS ${PC_XKBCOMMON_CFLAGS_OTHER})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(FindPackageHandleStandardArgs)
 | 
				
			||||||
 | 
					find_package_handle_standard_args(XKBCOMMON DEFAULT_MSG XKBCOMMON_LIBRARIES XKBCOMMON_INCLUDE_DIRS)
 | 
				
			||||||
 | 
					mark_as_advanced(XKBCOMMON_LIBRARIES XKBCOMMON_INCLUDE_DIRS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
project(wlroots C)
 | 
					project(wlroots C)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (CMAKE_BUILD_TYPE EQUAL "Debug")
 | 
					 | 
				
			||||||
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
 | 
					 | 
				
			||||||
endif()
 | 
					 | 
				
			||||||
set(CMAKE_C_STANDARD 99)
 | 
					set(CMAKE_C_STANDARD 99)
 | 
				
			||||||
set(CMAKE_C_EXTENSIONS OFF)
 | 
					set(CMAKE_C_EXTENSIONS OFF)
 | 
				
			||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 | 
					set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 | 
				
			||||||
| 
						 | 
					@ -51,6 +48,7 @@ find_package(GLESv2 REQUIRED)
 | 
				
			||||||
find_package(DRM REQUIRED)
 | 
					find_package(DRM REQUIRED)
 | 
				
			||||||
find_package(GBM REQUIRED)
 | 
					find_package(GBM REQUIRED)
 | 
				
			||||||
find_package(LibInput REQUIRED)
 | 
					find_package(LibInput REQUIRED)
 | 
				
			||||||
 | 
					find_package(XKBCommon REQUIRED)
 | 
				
			||||||
find_package(Udev REQUIRED)
 | 
					find_package(Udev REQUIRED)
 | 
				
			||||||
find_package(Systemd)
 | 
					find_package(Systemd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ include_directories(
 | 
				
			||||||
	${PROTOCOLS_INCLUDE_DIRS}
 | 
						${PROTOCOLS_INCLUDE_DIRS}
 | 
				
			||||||
	${WAYLAND_INCLUDE_DIR}
 | 
						${WAYLAND_INCLUDE_DIR}
 | 
				
			||||||
	${DRM_INCLUDE_DIRS}
 | 
						${DRM_INCLUDE_DIRS}
 | 
				
			||||||
 | 
					    ${LIBINPUT_INCLUDE_DIRS}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_library(wlr-backend
 | 
					add_library(wlr-backend
 | 
				
			||||||
| 
						 | 
					@ -11,9 +12,18 @@ add_library(wlr-backend
 | 
				
			||||||
    wayland/wl_output.c
 | 
					    wayland/wl_output.c
 | 
				
			||||||
    drm/backend.c
 | 
					    drm/backend.c
 | 
				
			||||||
    drm/drm.c
 | 
					    drm/drm.c
 | 
				
			||||||
    udev.c
 | 
					
 | 
				
			||||||
 | 
					    libinput/backend.c
 | 
				
			||||||
 | 
					    libinput/events.c
 | 
				
			||||||
 | 
					    libinput/keyboard.c
 | 
				
			||||||
 | 
					    libinput/pointer.c
 | 
				
			||||||
 | 
					    libinput/touch.c
 | 
				
			||||||
 | 
					    libinput/tablet_tool.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    multi/backend.c
 | 
				
			||||||
    backend.c
 | 
					    backend.c
 | 
				
			||||||
    egl.c
 | 
					    egl.c
 | 
				
			||||||
 | 
					    udev.c
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(wlr-backend
 | 
					target_link_libraries(wlr-backend
 | 
				
			||||||
| 
						 | 
					@ -26,5 +36,6 @@ target_link_libraries(wlr-backend
 | 
				
			||||||
    ${EGL_LIBRARIES}
 | 
					    ${EGL_LIBRARIES}
 | 
				
			||||||
    ${SYSTEMD_LIBRARIES}
 | 
					    ${SYSTEMD_LIBRARIES}
 | 
				
			||||||
    ${UDEV_LIBRARIES}
 | 
					    ${UDEV_LIBRARIES}
 | 
				
			||||||
 | 
					    ${LIBINPUT_LIBRARIES}
 | 
				
			||||||
    ${GBM_LIBRARIES}
 | 
					    ${GBM_LIBRARIES}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,15 @@
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
#include <wlr/session.h>
 | 
					#include <wlr/session.h>
 | 
				
			||||||
#include <wlr/backend/interface.h>
 | 
					#include <wlr/backend/interface.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/drm.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/multi.h>
 | 
				
			||||||
 | 
					#include "backend/libinput.h"
 | 
				
			||||||
 | 
					#include "backend/udev.h"
 | 
				
			||||||
#include "common/log.h"
 | 
					#include "common/log.h"
 | 
				
			||||||
#include "backend/drm.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_backend *wlr_backend_create(const struct wlr_backend_impl *impl,
 | 
					struct wlr_backend *wlr_backend_create(const struct wlr_backend_impl *impl,
 | 
				
			||||||
		struct wlr_backend_state *state) {
 | 
							struct wlr_backend_state *state) {
 | 
				
			||||||
| 
						 | 
					@ -17,14 +22,10 @@ struct wlr_backend *wlr_backend_create(const struct wlr_backend_impl *impl,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	backend->state = state;
 | 
						backend->state = state;
 | 
				
			||||||
	backend->impl = impl;
 | 
						backend->impl = impl;
 | 
				
			||||||
 | 
						wl_signal_init(&backend->events.input_add);
 | 
				
			||||||
 | 
						wl_signal_init(&backend->events.input_remove);
 | 
				
			||||||
	wl_signal_init(&backend->events.output_add);
 | 
						wl_signal_init(&backend->events.output_add);
 | 
				
			||||||
	wl_signal_init(&backend->events.output_remove);
 | 
						wl_signal_init(&backend->events.output_remove);
 | 
				
			||||||
	wl_signal_init(&backend->events.keyboard_add);
 | 
					 | 
				
			||||||
	wl_signal_init(&backend->events.keyboard_remove);
 | 
					 | 
				
			||||||
	wl_signal_init(&backend->events.pointer_add);
 | 
					 | 
				
			||||||
	wl_signal_init(&backend->events.pointer_remove);
 | 
					 | 
				
			||||||
	wl_signal_init(&backend->events.touch_add);
 | 
					 | 
				
			||||||
	wl_signal_init(&backend->events.touch_remove);
 | 
					 | 
				
			||||||
	return backend;
 | 
						return backend;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,12 +52,27 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
 | 
				
			||||||
		wlr_log(L_ERROR, "Failed to open DRM device");
 | 
							wlr_log(L_ERROR, "Failed to open DRM device");
 | 
				
			||||||
		goto error_udev;
 | 
							goto error_udev;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct wlr_backend *wlr;
 | 
						struct wlr_backend *multi = wlr_multi_backend_create();
 | 
				
			||||||
	wlr = wlr_drm_backend_create(display, session, udev, gpu);
 | 
						if (!multi) {
 | 
				
			||||||
	if (!wlr) {
 | 
					 | 
				
			||||||
		goto error_gpu;
 | 
							goto error_gpu;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return wlr;
 | 
						struct wlr_backend *libinput =
 | 
				
			||||||
 | 
							wlr_libinput_backend_create(display, session, udev);
 | 
				
			||||||
 | 
						if (!libinput) {
 | 
				
			||||||
 | 
							goto error_multi;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct wlr_backend *drm =
 | 
				
			||||||
 | 
							wlr_drm_backend_create(display, session, udev, gpu);
 | 
				
			||||||
 | 
						if (!drm) {
 | 
				
			||||||
 | 
							goto error_libinput;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_multi_backend_add(multi, libinput);
 | 
				
			||||||
 | 
						wlr_multi_backend_add(multi, drm);
 | 
				
			||||||
 | 
						return multi;
 | 
				
			||||||
 | 
					error_libinput:
 | 
				
			||||||
 | 
						wlr_backend_destroy(libinput);
 | 
				
			||||||
 | 
					error_multi:
 | 
				
			||||||
 | 
						wlr_backend_destroy(multi);
 | 
				
			||||||
error_gpu:
 | 
					error_gpu:
 | 
				
			||||||
	close(gpu);
 | 
						close(gpu);
 | 
				
			||||||
error_udev:
 | 
					error_udev:
 | 
				
			||||||
| 
						 | 
					@ -64,3 +80,7 @@ error_udev:
 | 
				
			||||||
error:
 | 
					error:
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct libinput_device *wlr_libinput_get_device_handle(struct wlr_input_device *dev) {
 | 
				
			||||||
 | 
						return dev->state->handle;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,8 +112,8 @@ static void wlr_drm_output_end(struct wlr_output_state *output) {
 | 
				
			||||||
	drmModePageFlip(renderer->fd, output->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output);
 | 
						drmModePageFlip(renderer->fd, output->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output);
 | 
				
			||||||
	output->pageflip_pending = true;
 | 
						output->pageflip_pending = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->bo_last = output->bo_current;
 | 
						output->bo[1] = output->bo[0];
 | 
				
			||||||
	output->bo_current = bo;
 | 
						output->bo[0] = bo;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_drm_output_start_renderer(struct wlr_output_state *output) {
 | 
					void wlr_drm_output_start_renderer(struct wlr_output_state *output) {
 | 
				
			||||||
| 
						 | 
					@ -141,8 +141,8 @@ void wlr_drm_output_start_renderer(struct wlr_output_state *output) {
 | 
				
			||||||
	drmModePageFlip(renderer->fd, output->crtc, fb_id,
 | 
						drmModePageFlip(renderer->fd, output->crtc, fb_id,
 | 
				
			||||||
			DRM_MODE_PAGE_FLIP_EVENT, output);
 | 
								DRM_MODE_PAGE_FLIP_EVENT, output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->bo_last = NULL;
 | 
						output->bo[1] = NULL;
 | 
				
			||||||
	output->bo_current = bo;
 | 
						output->bo[0] = bo;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool display_init_renderer(struct wlr_drm_renderer *renderer,
 | 
					static bool display_init_renderer(struct wlr_drm_renderer *renderer,
 | 
				
			||||||
| 
						 | 
					@ -280,6 +280,59 @@ static void wlr_drm_output_transform(struct wlr_output_state *output,
 | 
				
			||||||
	output->wlr_output->transform = transform;
 | 
						output->wlr_output->transform = transform;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void wlr_drm_cursor_bo_update(struct wlr_output_state *output,
 | 
				
			||||||
 | 
							uint32_t width, uint32_t height) {
 | 
				
			||||||
 | 
						if (output->cursor_width == width && output->cursor_height == height) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(L_DEBUG, "Allocating new cursor bos");
 | 
				
			||||||
 | 
						struct wlr_backend_state *state =
 | 
				
			||||||
 | 
							wl_container_of(output->renderer, state, renderer);
 | 
				
			||||||
 | 
						for (size_t i = 0; i < 2; ++i) {
 | 
				
			||||||
 | 
							output->cursor_bo[i] = gbm_bo_create(state->renderer.gbm,
 | 
				
			||||||
 | 
									width, height, GBM_FORMAT_ARGB8888,
 | 
				
			||||||
 | 
									GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
 | 
				
			||||||
 | 
							if (!output->cursor_bo[i]) {
 | 
				
			||||||
 | 
								wlr_log(L_ERROR, "Failed to create cursor bo");
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool wlr_drm_output_set_cursor(struct wlr_output_state *output,
 | 
				
			||||||
 | 
							const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) {
 | 
				
			||||||
 | 
						struct wlr_backend_state *state =
 | 
				
			||||||
 | 
							wl_container_of(output->renderer, state, renderer);
 | 
				
			||||||
 | 
						if (!buf) {
 | 
				
			||||||
 | 
							drmModeSetCursor(state->fd, output->crtc, 0, 0, 0);
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_drm_cursor_bo_update(output, width, height);
 | 
				
			||||||
 | 
						struct gbm_bo *bo;
 | 
				
			||||||
 | 
						output->current_cursor ^= 1;
 | 
				
			||||||
 | 
						bo = output->cursor_bo[output->current_cursor];
 | 
				
			||||||
 | 
						uint32_t _buf[width * height];
 | 
				
			||||||
 | 
						memset(_buf, 0, sizeof(_buf));
 | 
				
			||||||
 | 
						for (size_t i = 0; i < height; ++i) {
 | 
				
			||||||
 | 
							memcpy(_buf + i * width,
 | 
				
			||||||
 | 
									buf + i * stride,
 | 
				
			||||||
 | 
									width * 4);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (gbm_bo_write(bo, _buf, sizeof(_buf)) < 0) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Failed to write cursor to bo");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return !drmModeSetCursor(state->fd, output->crtc,
 | 
				
			||||||
 | 
								gbm_bo_get_handle(bo).s32, width, height);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool wlr_drm_output_move_cursor(struct wlr_output_state *output,
 | 
				
			||||||
 | 
							int x, int y) {
 | 
				
			||||||
 | 
						struct wlr_backend_state *state =
 | 
				
			||||||
 | 
							wl_container_of(output->renderer, state, renderer);
 | 
				
			||||||
 | 
						return !drmModeMoveCursor(state->fd, output->crtc, x, y);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void wlr_drm_output_destroy(struct wlr_output_state *output) {
 | 
					static void wlr_drm_output_destroy(struct wlr_output_state *output) {
 | 
				
			||||||
	wlr_drm_output_cleanup(output, true);
 | 
						wlr_drm_output_cleanup(output, true);
 | 
				
			||||||
	free(output);
 | 
						free(output);
 | 
				
			||||||
| 
						 | 
					@ -289,6 +342,8 @@ static struct wlr_output_impl output_impl = {
 | 
				
			||||||
	.enable = wlr_drm_output_enable,
 | 
						.enable = wlr_drm_output_enable,
 | 
				
			||||||
	.set_mode = wlr_drm_output_set_mode,
 | 
						.set_mode = wlr_drm_output_set_mode,
 | 
				
			||||||
	.transform = wlr_drm_output_transform,
 | 
						.transform = wlr_drm_output_transform,
 | 
				
			||||||
 | 
						.set_cursor = wlr_drm_output_set_cursor,
 | 
				
			||||||
 | 
						.move_cursor = wlr_drm_output_move_cursor,
 | 
				
			||||||
	.destroy = wlr_drm_output_destroy,
 | 
						.destroy = wlr_drm_output_destroy,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -457,6 +512,29 @@ void wlr_drm_scan_connectors(struct wlr_backend_state *state) {
 | 
				
			||||||
			snprintf(wlr_output->name, sizeof(wlr_output->name), "%s-%"PRIu32,
 | 
								snprintf(wlr_output->name, sizeof(wlr_output->name), "%s-%"PRIu32,
 | 
				
			||||||
				 conn_name[conn->connector_type],
 | 
									 conn_name[conn->connector_type],
 | 
				
			||||||
				 conn->connector_type_id);
 | 
									 conn->connector_type_id);
 | 
				
			||||||
 | 
								wlr_output->phys_width = conn->mmWidth;
 | 
				
			||||||
 | 
								wlr_output->phys_height = conn->mmHeight;
 | 
				
			||||||
 | 
								switch (conn->subpixel) {
 | 
				
			||||||
 | 
								case DRM_MODE_SUBPIXEL_UNKNOWN:
 | 
				
			||||||
 | 
									wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
 | 
				
			||||||
 | 
									wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
 | 
				
			||||||
 | 
									wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
 | 
				
			||||||
 | 
									wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
 | 
				
			||||||
 | 
									wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case DRM_MODE_SUBPIXEL_NONE:
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									wlr_output->subpixel = WL_OUTPUT_SUBPIXEL_NONE;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			drmModeEncoder *curr_enc = drmModeGetEncoder(state->fd, conn->encoder_id);
 | 
								drmModeEncoder *curr_enc = drmModeGetEncoder(state->fd, conn->encoder_id);
 | 
				
			||||||
			if (curr_enc) {
 | 
								if (curr_enc) {
 | 
				
			||||||
| 
						 | 
					@ -519,9 +597,9 @@ static void page_flip_handler(int fd, unsigned seq,
 | 
				
			||||||
	struct wlr_backend_state *state =
 | 
						struct wlr_backend_state *state =
 | 
				
			||||||
		wl_container_of(output->renderer, state, renderer);
 | 
							wl_container_of(output->renderer, state, renderer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (output->bo_last) {
 | 
						if (output->bo[1]) {
 | 
				
			||||||
		gbm_surface_release_buffer(output->gbm, output->bo_last);
 | 
							gbm_surface_release_buffer(output->gbm, output->bo[1]);
 | 
				
			||||||
		output->bo_last = NULL;
 | 
							output->bo[1] = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->pageflip_pending = false;
 | 
						output->pageflip_pending = false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										121
									
								
								backend/libinput/backend.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								backend/libinput/backend.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,121 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/interface.h>
 | 
				
			||||||
 | 
					#include "backend/udev.h"
 | 
				
			||||||
 | 
					#include "backend/libinput.h"
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int wlr_libinput_open_restricted(const char *path,
 | 
				
			||||||
 | 
							int flags, void *_state) {
 | 
				
			||||||
 | 
						struct wlr_backend_state *state = _state;
 | 
				
			||||||
 | 
						return wlr_session_open_file(state->session, path);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void wlr_libinput_close_restricted(int fd, void *_state) {
 | 
				
			||||||
 | 
						struct wlr_backend_state *state = _state;
 | 
				
			||||||
 | 
						wlr_session_close_file(state->session, fd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct libinput_interface libinput_impl = {
 | 
				
			||||||
 | 
						.open_restricted = wlr_libinput_open_restricted,
 | 
				
			||||||
 | 
						.close_restricted = wlr_libinput_close_restricted
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int wlr_libinput_readable(int fd, uint32_t mask, void *_state) {
 | 
				
			||||||
 | 
						struct wlr_backend_state *state = _state;
 | 
				
			||||||
 | 
						if (libinput_dispatch(state->libinput) != 0) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Failed to dispatch libinput");
 | 
				
			||||||
 | 
							// TODO: some kind of abort?
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event *event;
 | 
				
			||||||
 | 
						while ((event = libinput_get_event(state->libinput))) {
 | 
				
			||||||
 | 
							wlr_libinput_event(state, event);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void wlr_libinput_log(struct libinput *libinput,
 | 
				
			||||||
 | 
							enum libinput_log_priority priority, const char *fmt, va_list args) {
 | 
				
			||||||
 | 
						_wlr_vlog(L_ERROR, fmt, args);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool wlr_libinput_backend_init(struct wlr_backend_state *state) {
 | 
				
			||||||
 | 
						wlr_log(L_DEBUG, "Initializing libinput");
 | 
				
			||||||
 | 
						state->libinput = libinput_udev_create_context(&libinput_impl, state,
 | 
				
			||||||
 | 
								state->udev->udev);
 | 
				
			||||||
 | 
						if (!state->libinput) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Failed to create libinput context");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Let user customize seat used
 | 
				
			||||||
 | 
						if (libinput_udev_assign_seat(state->libinput, "seat0") != 0) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Failed to assign libinput seat");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: More sophisticated logging
 | 
				
			||||||
 | 
						libinput_log_set_handler(state->libinput, wlr_libinput_log);
 | 
				
			||||||
 | 
						libinput_log_set_priority(state->libinput, LIBINPUT_LOG_PRIORITY_ERROR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_event_loop *event_loop =
 | 
				
			||||||
 | 
							wl_display_get_event_loop(state->display);
 | 
				
			||||||
 | 
						if (state->input_event) {
 | 
				
			||||||
 | 
							wl_event_source_remove(state->input_event);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						state->input_event = wl_event_loop_add_fd(event_loop,
 | 
				
			||||||
 | 
								libinput_get_fd(state->libinput), WL_EVENT_READABLE,
 | 
				
			||||||
 | 
								wlr_libinput_readable, state);
 | 
				
			||||||
 | 
						if (!state->input_event) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Failed to create input event on event loop");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(L_DEBUG, "libinput sucessfully initialized");
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void wlr_libinput_backend_destroy(struct wlr_backend_state *state) {
 | 
				
			||||||
 | 
						// TODO
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wlr_backend_impl backend_impl = {
 | 
				
			||||||
 | 
						.init = wlr_libinput_backend_init,
 | 
				
			||||||
 | 
						.destroy = wlr_libinput_backend_destroy
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
 | 
				
			||||||
 | 
							struct wlr_session *session, struct wlr_udev *udev) {
 | 
				
			||||||
 | 
						assert(display && session && udev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_backend_state *state = calloc(1, sizeof(struct wlr_backend_state));
 | 
				
			||||||
 | 
						if (!state) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_backend *backend = wlr_backend_create(&backend_impl, state);
 | 
				
			||||||
 | 
						if (!backend) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
 | 
				
			||||||
 | 
							goto error_state;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(state->devices = list_create())) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
 | 
				
			||||||
 | 
							goto error_backend;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state->backend = backend;
 | 
				
			||||||
 | 
						state->session = session;
 | 
				
			||||||
 | 
						state->udev = udev;
 | 
				
			||||||
 | 
						state->display = display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return backend;
 | 
				
			||||||
 | 
					error_state:
 | 
				
			||||||
 | 
						free(state);
 | 
				
			||||||
 | 
					error_backend:
 | 
				
			||||||
 | 
						wlr_backend_destroy(backend);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										176
									
								
								backend/libinput/events.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								backend/libinput/events.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,176 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "backend/libinput.h"
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device *get_appropriate_device(
 | 
				
			||||||
 | 
							enum wlr_input_device_type desired_type,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						list_t *devices = libinput_device_get_user_data(device);
 | 
				
			||||||
 | 
						if (!devices) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (size_t i = 0; i < devices->length; ++i) {
 | 
				
			||||||
 | 
							struct wlr_input_device *dev = devices->items[i];
 | 
				
			||||||
 | 
							if (dev->type == desired_type) {
 | 
				
			||||||
 | 
								return dev;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void wlr_libinput_device_destroy(struct wlr_input_device_state *state) {
 | 
				
			||||||
 | 
						libinput_device_unref(state->handle);
 | 
				
			||||||
 | 
						free(state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wlr_input_device_impl input_device_impl = {
 | 
				
			||||||
 | 
						.destroy = wlr_libinput_device_destroy
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wlr_input_device *allocate_device(
 | 
				
			||||||
 | 
							struct wlr_backend_state *state, struct libinput_device *device,
 | 
				
			||||||
 | 
							list_t *devices, enum wlr_input_device_type type) {
 | 
				
			||||||
 | 
						int vendor = libinput_device_get_id_vendor(device);
 | 
				
			||||||
 | 
						int product = libinput_device_get_id_product(device);
 | 
				
			||||||
 | 
						const char *name = libinput_device_get_name(device);
 | 
				
			||||||
 | 
						struct wlr_input_device_state *devstate =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_input_device_state));
 | 
				
			||||||
 | 
						devstate->handle = device;
 | 
				
			||||||
 | 
						libinput_device_ref(device);
 | 
				
			||||||
 | 
						struct wlr_input_device *wlr_device = wlr_input_device_create(
 | 
				
			||||||
 | 
							type, &input_device_impl, devstate,
 | 
				
			||||||
 | 
							name, vendor, product);
 | 
				
			||||||
 | 
						list_add(devices, wlr_device);
 | 
				
			||||||
 | 
						list_add(state->devices, wlr_device);
 | 
				
			||||||
 | 
						return wlr_device;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_device_added(struct wlr_backend_state *state,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						assert(state && device);
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Note: the wlr API exposes only devices with a single capability, because
 | 
				
			||||||
 | 
						 * that meshes better with how Wayland does things and is a bit simpler.
 | 
				
			||||||
 | 
						 * However, libinput devices often have multiple capabilities - in such
 | 
				
			||||||
 | 
						 * cases we have to create several devices.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						int vendor = libinput_device_get_id_vendor(device);
 | 
				
			||||||
 | 
						int product = libinput_device_get_id_product(device);
 | 
				
			||||||
 | 
						const char *name = libinput_device_get_name(device);
 | 
				
			||||||
 | 
						list_t *devices = list_create();
 | 
				
			||||||
 | 
						wlr_log(L_DEBUG, "Added %s [%d:%d]", name, vendor, product);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) {
 | 
				
			||||||
 | 
							struct wlr_input_device *wlr_device = allocate_device(state,
 | 
				
			||||||
 | 
									device, devices, WLR_INPUT_DEVICE_KEYBOARD);
 | 
				
			||||||
 | 
							wlr_device->keyboard = wlr_libinput_keyboard_create(device);
 | 
				
			||||||
 | 
							wl_signal_emit(&state->backend->events.input_add, wlr_device);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) {
 | 
				
			||||||
 | 
							struct wlr_input_device *wlr_device = allocate_device(state,
 | 
				
			||||||
 | 
									device, devices, WLR_INPUT_DEVICE_POINTER);
 | 
				
			||||||
 | 
							wlr_device->pointer = wlr_libinput_pointer_create(device);
 | 
				
			||||||
 | 
							wl_signal_emit(&state->backend->events.input_add, wlr_device);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) {
 | 
				
			||||||
 | 
							struct wlr_input_device *wlr_device = allocate_device(state,
 | 
				
			||||||
 | 
									device, devices, WLR_INPUT_DEVICE_TOUCH);
 | 
				
			||||||
 | 
							wlr_device->touch = wlr_libinput_touch_create(device);
 | 
				
			||||||
 | 
							wl_signal_emit(&state->backend->events.input_add, wlr_device);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) {
 | 
				
			||||||
 | 
							struct wlr_input_device *wlr_device = allocate_device(state,
 | 
				
			||||||
 | 
									device, devices, WLR_INPUT_DEVICE_TABLET_TOOL);
 | 
				
			||||||
 | 
							wlr_device->tablet_tool = wlr_libinput_tablet_tool_create(device);
 | 
				
			||||||
 | 
							wl_signal_emit(&state->backend->events.input_add, wlr_device);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
 | 
				
			||||||
 | 
							// TODO
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) {
 | 
				
			||||||
 | 
							// TODO
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_SWITCH)) {
 | 
				
			||||||
 | 
							// TODO
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (devices->length > 0) {
 | 
				
			||||||
 | 
							libinput_device_set_user_data(device, devices);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							list_free(devices);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_device_removed(struct wlr_backend_state *state,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						wlr_log(L_DEBUG, "libinput device removed");
 | 
				
			||||||
 | 
						// TODO
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_libinput_event(struct wlr_backend_state *state,
 | 
				
			||||||
 | 
							struct libinput_event *event) {
 | 
				
			||||||
 | 
						assert(state && event);
 | 
				
			||||||
 | 
						struct libinput *context = libinput_event_get_context(event);
 | 
				
			||||||
 | 
						struct libinput_device *device = libinput_event_get_device(event);
 | 
				
			||||||
 | 
						enum libinput_event_type event_type = libinput_event_get_type(event);
 | 
				
			||||||
 | 
						(void)context;
 | 
				
			||||||
 | 
						switch (event_type) {
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_DEVICE_ADDED:
 | 
				
			||||||
 | 
							handle_device_added(state, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_DEVICE_REMOVED:
 | 
				
			||||||
 | 
							handle_device_removed(state, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_KEYBOARD_KEY:
 | 
				
			||||||
 | 
							handle_keyboard_key(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_POINTER_MOTION:
 | 
				
			||||||
 | 
							handle_pointer_motion(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
 | 
				
			||||||
 | 
							handle_pointer_motion_abs(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_POINTER_BUTTON:
 | 
				
			||||||
 | 
							handle_pointer_button(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_POINTER_AXIS:
 | 
				
			||||||
 | 
							handle_pointer_axis(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TOUCH_DOWN:
 | 
				
			||||||
 | 
							handle_touch_down(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TOUCH_UP:
 | 
				
			||||||
 | 
							handle_touch_up(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TOUCH_MOTION:
 | 
				
			||||||
 | 
							handle_touch_motion(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TOUCH_CANCEL:
 | 
				
			||||||
 | 
							handle_touch_cancel(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TOUCH_FRAME:
 | 
				
			||||||
 | 
							// no-op (at least for now)
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
 | 
				
			||||||
 | 
							handle_tablet_tool_axis(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
 | 
				
			||||||
 | 
							handle_tablet_tool_proximity(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TABLET_TOOL_TIP:
 | 
				
			||||||
 | 
							handle_tablet_tool_tip(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
 | 
				
			||||||
 | 
							handle_tablet_tool_button(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Unknown libinput event %d", event_type);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								backend/libinput/keyboard.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								backend/libinput/keyboard.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "backend/libinput.h"
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard *wlr_libinput_keyboard_create(
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						assert(device);
 | 
				
			||||||
 | 
						libinput_device_led_update(device, 0);
 | 
				
			||||||
 | 
						return wlr_keyboard_create(NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_keyboard_key(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_KEYBOARD, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a keyboard event for a device with no keyboards?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_keyboard *kbevent =
 | 
				
			||||||
 | 
							libinput_event_get_keyboard_event(event);
 | 
				
			||||||
 | 
						struct wlr_keyboard_key *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_keyboard_key));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_keyboard_get_time(kbevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_keyboard_get_time_usec(kbevent);
 | 
				
			||||||
 | 
						wlr_event->keycode = libinput_event_keyboard_get_key(kbevent);
 | 
				
			||||||
 | 
						enum libinput_key_state state = 
 | 
				
			||||||
 | 
							libinput_event_keyboard_get_key_state(kbevent);
 | 
				
			||||||
 | 
						switch (state) {
 | 
				
			||||||
 | 
						case LIBINPUT_KEY_STATE_RELEASED:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_KEY_RELEASED;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_KEY_STATE_PRESSED:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_KEY_PRESSED;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->keyboard->events.key, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										129
									
								
								backend/libinput/pointer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								backend/libinput/pointer.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,129 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "backend/libinput.h"
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer *wlr_libinput_pointer_create(
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						assert(device);
 | 
				
			||||||
 | 
						return wlr_pointer_create(NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_pointer_motion(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_pointer *pevent =
 | 
				
			||||||
 | 
							libinput_event_get_pointer_event(event);
 | 
				
			||||||
 | 
						struct wlr_pointer_motion *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_pointer_motion));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_pointer_get_time_usec(pevent);
 | 
				
			||||||
 | 
						wlr_event->delta_x = libinput_event_pointer_get_dx(pevent);
 | 
				
			||||||
 | 
						wlr_event->delta_y = libinput_event_pointer_get_dy(pevent);
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->pointer->events.motion, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_pointer_motion_abs(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_pointer *pevent =
 | 
				
			||||||
 | 
							libinput_event_get_pointer_event(event);
 | 
				
			||||||
 | 
						struct wlr_pointer_motion_absolute *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_pointer_motion_absolute));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = 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(device, &wlr_event->width_mm, &wlr_event->height_mm);
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->pointer->events.motion_absolute, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_pointer_button(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_pointer *pevent =
 | 
				
			||||||
 | 
							libinput_event_get_pointer_event(event);
 | 
				
			||||||
 | 
						struct wlr_pointer_button *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_pointer_button));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_pointer_get_time_usec(pevent);
 | 
				
			||||||
 | 
						wlr_event->button = libinput_event_pointer_get_button(pevent);
 | 
				
			||||||
 | 
						switch (libinput_event_pointer_get_button_state(pevent)) {
 | 
				
			||||||
 | 
						case LIBINPUT_BUTTON_STATE_PRESSED:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_BUTTON_PRESSED;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_BUTTON_STATE_RELEASED:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_BUTTON_RELEASED;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->pointer->events.button, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_pointer_axis(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_pointer *pevent =
 | 
				
			||||||
 | 
							libinput_event_get_pointer_event(event);
 | 
				
			||||||
 | 
						struct wlr_pointer_axis *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_pointer_axis));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_pointer_get_time_usec(pevent);
 | 
				
			||||||
 | 
						switch (libinput_event_pointer_get_axis_source(pevent)) {
 | 
				
			||||||
 | 
						case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
 | 
				
			||||||
 | 
							wlr_event->source = WLR_AXIS_SOURCE_WHEEL;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
 | 
				
			||||||
 | 
							wlr_event->source = WLR_AXIS_SOURCE_FINGER;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
 | 
				
			||||||
 | 
							wlr_event->source = WLR_AXIS_SOURCE_CONTINUOUS;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
 | 
				
			||||||
 | 
							wlr_event->source = WLR_AXIS_SOURCE_WHEEL_TILT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						enum libinput_pointer_axis axies[] = {
 | 
				
			||||||
 | 
							LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
 | 
				
			||||||
 | 
							LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						for (size_t i = 0; i < sizeof(axies) / sizeof(axies[0]); ++i) {
 | 
				
			||||||
 | 
							if (libinput_event_pointer_has_axis(pevent, axies[i])) {
 | 
				
			||||||
 | 
								switch (axies[i]) {
 | 
				
			||||||
 | 
								case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
 | 
				
			||||||
 | 
									wlr_event->orientation = WLR_AXIS_ORIENTATION_VERTICAL;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
 | 
				
			||||||
 | 
									wlr_event->orientation = WLR_AXIS_ORIENTATION_HORIZONTAL;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								wlr_event->delta = libinput_event_pointer_get_axis_value(
 | 
				
			||||||
 | 
										pevent, axies[i]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wl_signal_emit(&dev->pointer->events.axis, wlr_event);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										150
									
								
								backend/libinput/tablet_tool.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								backend/libinput/tablet_tool.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,150 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "backend/libinput.h"
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool *wlr_libinput_tablet_tool_create(
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						assert(device);
 | 
				
			||||||
 | 
						return wlr_tablet_tool_create(NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_tablet_tool_axis(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_tablet_tool *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_tablet_tool_event(event);
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_axis *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_tablet_tool_axis));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
 | 
				
			||||||
 | 
						libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm);
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_x_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_X;
 | 
				
			||||||
 | 
							wlr_event->x_mm = libinput_event_tablet_tool_get_x(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_y_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_Y;
 | 
				
			||||||
 | 
							wlr_event->y_mm = libinput_event_tablet_tool_get_y(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_pressure_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_PRESSURE;
 | 
				
			||||||
 | 
							wlr_event->pressure = libinput_event_tablet_tool_get_pressure(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_distance_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_DISTANCE;
 | 
				
			||||||
 | 
							wlr_event->distance = libinput_event_tablet_tool_get_distance(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_tilt_x_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_TILT_X;
 | 
				
			||||||
 | 
							wlr_event->tilt_x = libinput_event_tablet_tool_get_tilt_x(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_tilt_y_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_TILT_Y;
 | 
				
			||||||
 | 
							wlr_event->tilt_y = libinput_event_tablet_tool_get_tilt_y(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_rotation_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_ROTATION;
 | 
				
			||||||
 | 
							wlr_event->rotation = libinput_event_tablet_tool_get_rotation(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_slider_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_SLIDER;
 | 
				
			||||||
 | 
							wlr_event->slider = libinput_event_tablet_tool_get_slider_position(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (libinput_event_tablet_tool_wheel_has_changed(tevent)) {
 | 
				
			||||||
 | 
							wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_WHEEL;
 | 
				
			||||||
 | 
							wlr_event->wheel_delta = libinput_event_tablet_tool_get_wheel_delta(tevent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->tablet_tool->events.axis, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_tablet_tool_proximity(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_tablet_tool *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_tablet_tool_event(event);
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_proximity *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_tablet_tool_proximity));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
 | 
				
			||||||
 | 
						switch (libinput_event_tablet_tool_get_proximity_state(tevent)) {
 | 
				
			||||||
 | 
						case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_TABLET_TOOL_PROXIMITY_OUT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_TABLET_TOOL_PROXIMITY_IN;
 | 
				
			||||||
 | 
							handle_tablet_tool_axis(event, device);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->tablet_tool->events.proximity, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_tablet_tool_tip(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						handle_tablet_tool_axis(event, device);
 | 
				
			||||||
 | 
						struct libinput_event_tablet_tool *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_tablet_tool_event(event);
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_tip *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_tablet_tool_tip));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
 | 
				
			||||||
 | 
						switch (libinput_event_tablet_tool_get_tip_state(tevent)) {
 | 
				
			||||||
 | 
						case LIBINPUT_TABLET_TOOL_TIP_UP:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_TABLET_TOOL_TIP_UP;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_TABLET_TOOL_TIP_DOWN:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_TABLET_TOOL_TIP_DOWN;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->tablet_tool->events.tip, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_tablet_tool_button(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Tip events contain axis information. We update this information
 | 
				
			||||||
 | 
						// before we send the proximity event
 | 
				
			||||||
 | 
						handle_tablet_tool_axis(event, device);
 | 
				
			||||||
 | 
						struct libinput_event_tablet_tool *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_tablet_tool_event(event);
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_button *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_tablet_tool_button));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
 | 
				
			||||||
 | 
						wlr_event->button = libinput_event_tablet_tool_get_button(tevent);
 | 
				
			||||||
 | 
						switch (libinput_event_tablet_tool_get_button_state(tevent)) {
 | 
				
			||||||
 | 
						case LIBINPUT_BUTTON_STATE_RELEASED:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_BUTTON_RELEASED;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case LIBINPUT_BUTTON_STATE_PRESSED:
 | 
				
			||||||
 | 
							wlr_event->state = WLR_BUTTON_PRESSED;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->tablet_tool->events.button, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										93
									
								
								backend/libinput/touch.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								backend/libinput/touch.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,93 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "backend/libinput.h"
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch *wlr_libinput_touch_create(
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						assert(device);
 | 
				
			||||||
 | 
						return wlr_touch_create(NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_touch_down(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_touch *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_touch_event(event);
 | 
				
			||||||
 | 
						struct wlr_touch_down *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_touch_down));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_touch_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
 | 
				
			||||||
 | 
						wlr_event->slot = libinput_event_touch_get_slot(tevent);
 | 
				
			||||||
 | 
						wlr_event->x_mm = libinput_event_touch_get_x(tevent);
 | 
				
			||||||
 | 
						wlr_event->y_mm = libinput_event_touch_get_y(tevent);
 | 
				
			||||||
 | 
						libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm);
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->touch->events.down, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_touch_up(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_touch *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_touch_event(event);
 | 
				
			||||||
 | 
						struct wlr_touch_up *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_touch_up));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_touch_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
 | 
				
			||||||
 | 
						wlr_event->slot = libinput_event_touch_get_slot(tevent);
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->touch->events.up, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_touch_motion(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_touch *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_touch_event(event);
 | 
				
			||||||
 | 
						struct wlr_touch_motion *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_touch_motion));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_touch_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
 | 
				
			||||||
 | 
						wlr_event->slot = libinput_event_touch_get_slot(tevent);
 | 
				
			||||||
 | 
						wlr_event->x_mm = libinput_event_touch_get_x(tevent);
 | 
				
			||||||
 | 
						wlr_event->y_mm = libinput_event_touch_get_y(tevent);
 | 
				
			||||||
 | 
						libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm);
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->touch->events.motion, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void handle_touch_cancel(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev =
 | 
				
			||||||
 | 
							get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct libinput_event_touch *tevent =
 | 
				
			||||||
 | 
							libinput_event_get_touch_event(event);
 | 
				
			||||||
 | 
						struct wlr_touch_cancel *wlr_event =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_touch_cancel));
 | 
				
			||||||
 | 
						wlr_event->time_sec = libinput_event_touch_get_time(tevent);
 | 
				
			||||||
 | 
						wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
 | 
				
			||||||
 | 
						wlr_event->slot = libinput_event_touch_get_slot(tevent);
 | 
				
			||||||
 | 
						wl_signal_emit(&dev->touch->events.cancel, wlr_event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										107
									
								
								backend/multi/backend.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								backend/multi/backend.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,107 @@
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/interface.h>
 | 
				
			||||||
 | 
					#include <wlr/common/log.h>
 | 
				
			||||||
 | 
					#include "backend/multi.h"
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct subbackend_state {
 | 
				
			||||||
 | 
						struct wlr_backend *backend;
 | 
				
			||||||
 | 
						struct wlr_backend *container;
 | 
				
			||||||
 | 
						struct wl_listener input_add;
 | 
				
			||||||
 | 
						struct wl_listener input_remove;
 | 
				
			||||||
 | 
						struct wl_listener output_add;
 | 
				
			||||||
 | 
						struct wl_listener output_remove;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool multi_backend_init(struct wlr_backend_state *state) {
 | 
				
			||||||
 | 
						for (size_t i = 0; i < state->backends->length; ++i) {
 | 
				
			||||||
 | 
							struct subbackend_state *sub = state->backends->items[i];
 | 
				
			||||||
 | 
							if (!wlr_backend_init(sub->backend)) {
 | 
				
			||||||
 | 
								wlr_log(L_ERROR, "Failed to initialize backend %zd", i);
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void multi_backend_destroy(struct wlr_backend_state *state) {
 | 
				
			||||||
 | 
						for (size_t i = 0; i < state->backends->length; ++i) {
 | 
				
			||||||
 | 
							struct subbackend_state *sub = state->backends->items[i];
 | 
				
			||||||
 | 
							wlr_backend_destroy(sub->backend);
 | 
				
			||||||
 | 
							free(sub);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						list_free(state->backends);
 | 
				
			||||||
 | 
						free(state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend_impl backend_impl = {
 | 
				
			||||||
 | 
						.init = multi_backend_init,
 | 
				
			||||||
 | 
						.destroy = multi_backend_destroy
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend *wlr_multi_backend_create() {
 | 
				
			||||||
 | 
						struct wlr_backend_state *state =
 | 
				
			||||||
 | 
							calloc(1, sizeof(struct wlr_backend_state));
 | 
				
			||||||
 | 
						if (!state) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Backend allocation failed");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						state->backends = list_create();
 | 
				
			||||||
 | 
						if (!state->backends) {
 | 
				
			||||||
 | 
							free(state);
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Backend allocation failed");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct wlr_backend *backend = wlr_backend_create(&backend_impl, state);
 | 
				
			||||||
 | 
						state->backend = backend;
 | 
				
			||||||
 | 
						return backend;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void input_add_reemit(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct subbackend_state *state = wl_container_of(listener,
 | 
				
			||||||
 | 
								state, input_add);
 | 
				
			||||||
 | 
						wl_signal_emit(&state->container->events.input_add, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void input_remove_reemit(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct subbackend_state *state = wl_container_of(listener,
 | 
				
			||||||
 | 
								state, input_remove);
 | 
				
			||||||
 | 
						wl_signal_emit(&state->container->events.input_remove, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void output_add_reemit(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct subbackend_state *state = wl_container_of(listener,
 | 
				
			||||||
 | 
								state, output_add);
 | 
				
			||||||
 | 
						wl_signal_emit(&state->container->events.output_add, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void output_remove_reemit(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct subbackend_state *state = wl_container_of(listener,
 | 
				
			||||||
 | 
								state, output_remove);
 | 
				
			||||||
 | 
						wl_signal_emit(&state->container->events.output_remove, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_multi_backend_add(struct wlr_backend *multi,
 | 
				
			||||||
 | 
							struct wlr_backend *backend) {
 | 
				
			||||||
 | 
						struct subbackend_state *sub = calloc(1, sizeof(struct subbackend_state));
 | 
				
			||||||
 | 
						sub->backend = backend;
 | 
				
			||||||
 | 
						sub->container = multi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sub->input_add.notify = input_add_reemit;
 | 
				
			||||||
 | 
						sub->input_remove.notify = input_remove_reemit;
 | 
				
			||||||
 | 
						sub->output_add.notify = output_add_reemit;
 | 
				
			||||||
 | 
						sub->output_remove.notify = output_remove_reemit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_init(&sub->input_add.link);
 | 
				
			||||||
 | 
						wl_list_init(&sub->input_remove.link);
 | 
				
			||||||
 | 
						wl_list_init(&sub->output_add.link);
 | 
				
			||||||
 | 
						wl_list_init(&sub->output_remove.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_signal_add(&backend->events.input_add, &sub->input_add);
 | 
				
			||||||
 | 
						wl_signal_add(&backend->events.input_remove, &sub->input_remove);
 | 
				
			||||||
 | 
						wl_signal_add(&backend->events.output_add, &sub->output_add);
 | 
				
			||||||
 | 
						wl_signal_add(&backend->events.output_remove, &sub->output_remove);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_add(multi->state->backends, sub);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,23 @@
 | 
				
			||||||
include_directories(
 | 
					include_directories(
 | 
				
			||||||
	${DRM_INCLUDE_DIRS}
 | 
						${DRM_INCLUDE_DIRS}
 | 
				
			||||||
    ${CMAKE_CURRENT_SOURCE_DIR}
 | 
					    ${CMAKE_CURRENT_SOURCE_DIR}
 | 
				
			||||||
 | 
					    ${XKBCOMMON_INCLUDE_DIRS}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable(simple
 | 
					add_executable(simple
 | 
				
			||||||
    simple.c
 | 
					    simple.c
 | 
				
			||||||
 | 
					    shared.c
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(simple
 | 
					target_link_libraries(simple
 | 
				
			||||||
    wlr-backend
 | 
					    wlr-backend
 | 
				
			||||||
    wlr-session
 | 
					    wlr-session
 | 
				
			||||||
 | 
					    ${XKBCOMMON_LIBRARIES}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable(rotation
 | 
					add_executable(rotation
 | 
				
			||||||
    rotation.c
 | 
					    rotation.c
 | 
				
			||||||
 | 
					    shared.c
 | 
				
			||||||
    cat.c
 | 
					    cat.c
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,4 +25,43 @@ target_link_libraries(rotation
 | 
				
			||||||
    wlr-backend
 | 
					    wlr-backend
 | 
				
			||||||
    wlr-session
 | 
					    wlr-session
 | 
				
			||||||
    wlr-render
 | 
					    wlr-render
 | 
				
			||||||
 | 
					    ${XKBCOMMON_LIBRARIES}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(pointer
 | 
				
			||||||
 | 
					    pointer.c
 | 
				
			||||||
 | 
					    shared.c
 | 
				
			||||||
 | 
					    cat.c
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(pointer
 | 
				
			||||||
 | 
					    wlr-backend
 | 
				
			||||||
 | 
					    wlr-session
 | 
				
			||||||
 | 
					    wlr-render
 | 
				
			||||||
 | 
					    ${XKBCOMMON_LIBRARIES}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(touch
 | 
				
			||||||
 | 
					    touch.c
 | 
				
			||||||
 | 
					    shared.c
 | 
				
			||||||
 | 
					    cat.c
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(touch
 | 
				
			||||||
 | 
					    wlr-backend
 | 
				
			||||||
 | 
					    wlr-session
 | 
				
			||||||
 | 
					    wlr-render
 | 
				
			||||||
 | 
					    ${XKBCOMMON_LIBRARIES}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(tablet
 | 
				
			||||||
 | 
					    tablet.c
 | 
				
			||||||
 | 
					    shared.c
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(tablet
 | 
				
			||||||
 | 
					    wlr-backend
 | 
				
			||||||
 | 
					    wlr-session
 | 
				
			||||||
 | 
					    wlr-render
 | 
				
			||||||
 | 
					    ${XKBCOMMON_LIBRARIES}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4381
									
								
								example/cat.c
									
										
									
									
									
								
							
							
						
						
									
										4381
									
								
								example/cat.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										132
									
								
								example/pointer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								example/pointer.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,132 @@
 | 
				
			||||||
 | 
					#define _POSIX_C_SOURCE 199309L
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wayland-server-protocol.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					#include <GLES3/gl3.h>
 | 
				
			||||||
 | 
					#include <wlr/render/matrix.h>
 | 
				
			||||||
 | 
					#include <wlr/render/gles3.h>
 | 
				
			||||||
 | 
					#include <wlr/render.h>
 | 
				
			||||||
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include "shared.h"
 | 
				
			||||||
 | 
					#include "cat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct sample_state {
 | 
				
			||||||
 | 
						struct wlr_renderer *renderer;
 | 
				
			||||||
 | 
						struct wlr_surface *cat_texture;
 | 
				
			||||||
 | 
						int cur_x, cur_y;
 | 
				
			||||||
 | 
						float default_color[4];
 | 
				
			||||||
 | 
						float clear_color[4];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_output_frame(struct output_state *output, struct timespec *ts) {
 | 
				
			||||||
 | 
						struct compositor_state *state = output->compositor;
 | 
				
			||||||
 | 
						struct sample_state *sample = state->data;
 | 
				
			||||||
 | 
						struct wlr_output *wlr_output = output->output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_renderer_begin(sample->renderer, wlr_output);
 | 
				
			||||||
 | 
						glClearColor(sample->clear_color[0], sample->clear_color[1],
 | 
				
			||||||
 | 
								sample->clear_color[2], sample->clear_color[3]);
 | 
				
			||||||
 | 
						glClear(GL_COLOR_BUFFER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float matrix[16];
 | 
				
			||||||
 | 
						wlr_surface_get_matrix(sample->cat_texture, &matrix,
 | 
				
			||||||
 | 
							&wlr_output->transform_matrix, sample->cur_x, sample->cur_y);
 | 
				
			||||||
 | 
						wlr_render_with_matrix(sample->renderer,
 | 
				
			||||||
 | 
								sample->cat_texture, &matrix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_renderer_end(sample->renderer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_keyboard_key(struct keyboard_state *kbstate,
 | 
				
			||||||
 | 
							xkb_keysym_t sym, enum wlr_key_state key_state) {
 | 
				
			||||||
 | 
						if (sym == XKB_KEY_Escape) {
 | 
				
			||||||
 | 
							kbstate->compositor->exit = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_pointer_motion(struct pointer_state *pstate,
 | 
				
			||||||
 | 
							double d_x, double d_y) {
 | 
				
			||||||
 | 
						struct sample_state *state = pstate->compositor->data;
 | 
				
			||||||
 | 
						state->cur_x += d_x;
 | 
				
			||||||
 | 
						state->cur_y += d_y;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_pointer_button(struct pointer_state *pstate,
 | 
				
			||||||
 | 
							uint32_t button, enum wlr_button_state state) {
 | 
				
			||||||
 | 
						struct sample_state *sample = pstate->compositor->data;
 | 
				
			||||||
 | 
						float (*color)[4];
 | 
				
			||||||
 | 
						if (state == WLR_BUTTON_RELEASED) {
 | 
				
			||||||
 | 
							color = &sample->default_color;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							float red[4] = { 0.25f, 0.25f, 0.25f, 1 };
 | 
				
			||||||
 | 
							red[button % 3] = 1;
 | 
				
			||||||
 | 
							color = &red;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						memcpy(&sample->clear_color, color, sizeof(*color));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_pointer_axis(struct pointer_state *pstate,
 | 
				
			||||||
 | 
						enum wlr_axis_source source,
 | 
				
			||||||
 | 
						enum wlr_axis_orientation orientation,
 | 
				
			||||||
 | 
						double delta) {
 | 
				
			||||||
 | 
						struct sample_state *sample = pstate->compositor->data;
 | 
				
			||||||
 | 
						for (size_t i = 0; i < 3; ++i) {
 | 
				
			||||||
 | 
							sample->default_color[i] += delta > 0 ? -0.05f : 0.05f;
 | 
				
			||||||
 | 
							if (sample->default_color[i] > 1.0f) {
 | 
				
			||||||
 | 
								sample->default_color[i] = 1.0f;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (sample->default_color[i] < 0.0f) {
 | 
				
			||||||
 | 
								sample->default_color[i] = 0.0f;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						memcpy(&sample->clear_color, &sample->default_color,
 | 
				
			||||||
 | 
								sizeof(sample->clear_color));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_output_add(struct output_state *ostate) {
 | 
				
			||||||
 | 
						struct wlr_output *wlr_output = ostate->output;
 | 
				
			||||||
 | 
						if (!wlr_output_set_cursor(wlr_output, cat_tex.pixel_data,
 | 
				
			||||||
 | 
								cat_tex.width * 4, cat_tex.width, cat_tex.height)) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to set cursor\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!wlr_output_move_cursor(wlr_output, 0, 0)) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to move cursor\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
 | 
						struct sample_state state = {
 | 
				
			||||||
 | 
							.default_color = { 0.25f, 0.25f, 0.25f, 1 },
 | 
				
			||||||
 | 
							.clear_color = { 0.25f, 0.25f, 0.25f, 1 }
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct compositor_state compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						compositor_init(&compositor);
 | 
				
			||||||
 | 
						compositor.output_add_cb = handle_output_add;
 | 
				
			||||||
 | 
						compositor.output_frame_cb = handle_output_frame;
 | 
				
			||||||
 | 
						compositor.keyboard_key_cb = handle_keyboard_key;
 | 
				
			||||||
 | 
						compositor.pointer_motion_cb = handle_pointer_motion;
 | 
				
			||||||
 | 
						compositor.pointer_button_cb = handle_pointer_button;
 | 
				
			||||||
 | 
						compositor.pointer_axis_cb = handle_pointer_axis;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state.renderer = wlr_gles3_renderer_init();
 | 
				
			||||||
 | 
						state.cat_texture = wlr_render_surface_init(state.renderer);
 | 
				
			||||||
 | 
						wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
 | 
				
			||||||
 | 
							cat_tex.width, cat_tex.height, cat_tex.pixel_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						compositor.data = &state;
 | 
				
			||||||
 | 
						compositor_run(&compositor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_surface_destroy(state.cat_texture);
 | 
				
			||||||
 | 
						wlr_renderer_destroy(state.renderer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <wayland-server.h>
 | 
					#include <wayland-server.h>
 | 
				
			||||||
#include <wayland-server-protocol.h>
 | 
					#include <wayland-server-protocol.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
#include <GLES3/gl3.h>
 | 
					#include <GLES3/gl3.h>
 | 
				
			||||||
#include <wlr/render/matrix.h>
 | 
					#include <wlr/render/matrix.h>
 | 
				
			||||||
#include <wlr/render/gles3.h>
 | 
					#include <wlr/render/gles3.h>
 | 
				
			||||||
| 
						 | 
					@ -15,24 +16,18 @@
 | 
				
			||||||
#include <wlr/session.h>
 | 
					#include <wlr/session.h>
 | 
				
			||||||
#include <wlr/types.h>
 | 
					#include <wlr/types.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include "shared.h"
 | 
				
			||||||
#include "cat.h"
 | 
					#include "cat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct state {
 | 
					struct sample_state {
 | 
				
			||||||
	struct wl_listener output_add;
 | 
					 | 
				
			||||||
	struct wl_listener output_remove;
 | 
					 | 
				
			||||||
	struct wl_list outputs;
 | 
					 | 
				
			||||||
	struct wl_list config;
 | 
						struct wl_list config;
 | 
				
			||||||
	struct wlr_renderer *renderer;
 | 
						struct wlr_renderer *renderer;
 | 
				
			||||||
	struct wlr_surface *cat_texture;
 | 
						struct wlr_surface *cat_texture;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct output_state {
 | 
					struct output_data {
 | 
				
			||||||
	struct timespec last_frame;
 | 
					 | 
				
			||||||
	struct wl_list link;
 | 
					 | 
				
			||||||
	struct wlr_output *output;
 | 
					 | 
				
			||||||
	struct state *state;
 | 
					 | 
				
			||||||
	struct wl_listener frame;
 | 
					 | 
				
			||||||
	float x_offs, y_offs;
 | 
						float x_offs, y_offs;
 | 
				
			||||||
 | 
						float x_vel, y_vel;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct output_config {
 | 
					struct output_config {
 | 
				
			||||||
| 
						 | 
					@ -41,86 +36,93 @@ struct output_config {
 | 
				
			||||||
	struct wl_list link;
 | 
						struct wl_list link;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void output_frame(struct wl_listener *listener, void *data) {
 | 
					static void handle_output_frame(struct output_state *output, struct timespec *ts) {
 | 
				
			||||||
	struct output_state *ostate = wl_container_of(listener, ostate, frame);
 | 
						struct compositor_state *state = output->compositor;
 | 
				
			||||||
	struct wlr_output *output = ostate->output;
 | 
						struct sample_state *sample = state->data;
 | 
				
			||||||
	struct state *s = ostate->state;
 | 
						struct output_data *odata = output->data;
 | 
				
			||||||
 | 
						struct wlr_output *wlr_output = output->output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int32_t width, height;
 | 
						int32_t width, height;
 | 
				
			||||||
	wlr_output_effective_resolution(output, &width, &height);
 | 
						wlr_output_effective_resolution(wlr_output, &width, &height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_renderer_begin(s->renderer, output);
 | 
						wlr_renderer_begin(sample->renderer, wlr_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float matrix[16];
 | 
						float matrix[16];
 | 
				
			||||||
	for (int y = -128 + (int)ostate->y_offs; y < height; y += 128) {
 | 
						for (int y = -128 + (int)odata->y_offs; y < height; y += 128) {
 | 
				
			||||||
		for (int x = -128 + (int)ostate->x_offs; x < width; x += 128) {
 | 
							for (int x = -128 + (int)odata->x_offs; x < width; x += 128) {
 | 
				
			||||||
			wlr_surface_get_matrix(s->cat_texture, &matrix,
 | 
								wlr_surface_get_matrix(sample->cat_texture, &matrix,
 | 
				
			||||||
				&output->transform_matrix, x, y);
 | 
									&wlr_output->transform_matrix, x, y);
 | 
				
			||||||
			wlr_render_with_matrix(s->renderer, s->cat_texture, &matrix);
 | 
								wlr_render_with_matrix(sample->renderer,
 | 
				
			||||||
 | 
										sample->cat_texture, &matrix);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_renderer_end(s->renderer);
 | 
						wlr_renderer_end(sample->renderer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct timespec now;
 | 
						long ms = (ts->tv_sec - output->last_frame.tv_sec) * 1000 +
 | 
				
			||||||
	clock_gettime(CLOCK_MONOTONIC, &now);
 | 
							(ts->tv_nsec - output->last_frame.tv_nsec) / 1000000;
 | 
				
			||||||
	long ms = (now.tv_sec - ostate->last_frame.tv_sec) * 1000 +
 | 
					 | 
				
			||||||
		(now.tv_nsec - ostate->last_frame.tv_nsec) / 1000000;
 | 
					 | 
				
			||||||
	float seconds = ms / 1000.0f;
 | 
						float seconds = ms / 1000.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ostate->x_offs += 128 * seconds;
 | 
						odata->x_offs += odata->x_vel * seconds;
 | 
				
			||||||
	ostate->y_offs += 128 * seconds;
 | 
						odata->y_offs += odata->y_vel * seconds;
 | 
				
			||||||
	if (ostate->x_offs > 128) ostate->x_offs = 0;
 | 
						if (odata->x_offs > 128) odata->x_offs = 0;
 | 
				
			||||||
	if (ostate->y_offs > 128) ostate->y_offs = 0;
 | 
						if (odata->y_offs > 128) odata->y_offs = 0;
 | 
				
			||||||
	ostate->last_frame = now;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void output_add(struct wl_listener *listener, void *data) {
 | 
					static void handle_output_add(struct output_state *output) {
 | 
				
			||||||
	struct wlr_output *output = data;
 | 
						struct output_data *odata = calloc(1, sizeof(struct output_data));
 | 
				
			||||||
	struct state *state = wl_container_of(listener, state, output_add);
 | 
						odata->x_offs = odata->y_offs = 0;
 | 
				
			||||||
 | 
						odata->x_vel = odata->y_vel = 128;
 | 
				
			||||||
	fprintf(stderr, "Output '%s' added\n", output->name);
 | 
						output->data = odata;
 | 
				
			||||||
	wlr_output_set_mode(output, output->modes->items[0]);
 | 
						struct sample_state *state = output->compositor->data;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct output_state *ostate = calloc(1, sizeof(struct output_state));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	clock_gettime(CLOCK_MONOTONIC, &ostate->last_frame);
 | 
					 | 
				
			||||||
	ostate->output = output;
 | 
					 | 
				
			||||||
	ostate->state = state;
 | 
					 | 
				
			||||||
	ostate->frame.notify = output_frame;
 | 
					 | 
				
			||||||
	ostate->x_offs = ostate->y_offs = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct output_config *conf;
 | 
						struct output_config *conf;
 | 
				
			||||||
	wl_list_for_each(conf, &state->config, link) {
 | 
						wl_list_for_each(conf, &state->config, link) {
 | 
				
			||||||
		if (strcmp(conf->name, output->name) == 0) {
 | 
							if (strcmp(conf->name, output->output->name) == 0) {
 | 
				
			||||||
			wlr_output_transform(ostate->output, conf->transform);
 | 
								wlr_output_transform(output->output, conf->transform);
 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_list_init(&ostate->frame.link);
 | 
					 | 
				
			||||||
	wl_signal_add(&output->events.frame, &ostate->frame);
 | 
					 | 
				
			||||||
	wl_list_insert(&state->outputs, &ostate->link);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void output_remove(struct wl_listener *listener, void *data) {
 | 
					 | 
				
			||||||
	struct wlr_output *output = data;
 | 
					 | 
				
			||||||
	struct state *state = wl_container_of(listener, state, output_remove);
 | 
					 | 
				
			||||||
	struct output_state *ostate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_list_for_each(ostate, &state->outputs, link) {
 | 
					 | 
				
			||||||
		if (ostate->output == output) {
 | 
					 | 
				
			||||||
			wl_list_remove(&ostate->link);
 | 
					 | 
				
			||||||
			wl_list_remove(&ostate->frame.link);
 | 
					 | 
				
			||||||
			free(ostate);
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int timer_done(void *data) {
 | 
					static void handle_output_remove(struct output_state *output) {
 | 
				
			||||||
	*(bool *)data = true;
 | 
						free(output->data);
 | 
				
			||||||
	return 1;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void update_velocities(struct compositor_state *state,
 | 
				
			||||||
 | 
							float x_diff, float y_diff) {
 | 
				
			||||||
 | 
						struct output_state *output;
 | 
				
			||||||
 | 
						wl_list_for_each(output, &state->outputs, link) {
 | 
				
			||||||
 | 
							struct output_data *odata = output->data;
 | 
				
			||||||
 | 
							odata->x_vel += x_diff;
 | 
				
			||||||
 | 
							odata->y_vel += y_diff;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_keyboard_key(struct keyboard_state *kbstate,
 | 
				
			||||||
 | 
							xkb_keysym_t sym, enum wlr_key_state key_state) {
 | 
				
			||||||
 | 
						// NOTE: It may be better to simply refer to our key state during each frame
 | 
				
			||||||
 | 
						// and make this change in pixels/sec^2
 | 
				
			||||||
 | 
						// Also, key repeat
 | 
				
			||||||
 | 
						if (key_state == WLR_KEY_PRESSED) {
 | 
				
			||||||
 | 
							switch (sym) {
 | 
				
			||||||
 | 
							case XKB_KEY_Escape:
 | 
				
			||||||
 | 
								kbstate->compositor->exit = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XKB_KEY_Left:
 | 
				
			||||||
 | 
								update_velocities(kbstate->compositor, -16, 0);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XKB_KEY_Right:
 | 
				
			||||||
 | 
								update_velocities(kbstate->compositor, 16, 0);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XKB_KEY_Up:
 | 
				
			||||||
 | 
								update_velocities(kbstate->compositor, 0, -16);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case XKB_KEY_Down:
 | 
				
			||||||
 | 
								update_velocities(kbstate->compositor, 0, 16);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usage(const char *name, int ret) {
 | 
					static void usage(const char *name, int ret) {
 | 
				
			||||||
| 
						 | 
					@ -190,59 +192,27 @@ static void parse_args(int argc, char *argv[], struct wl_list *config) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[]) {
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
	struct state state = {
 | 
						struct sample_state state = { 0 };
 | 
				
			||||||
		.output_add = { .notify = output_add },
 | 
						struct compositor_state compositor;
 | 
				
			||||||
		.output_remove = { .notify = output_remove }
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_list_init(&state.outputs);
 | 
					 | 
				
			||||||
	wl_list_init(&state.config);
 | 
						wl_list_init(&state.config);
 | 
				
			||||||
	wl_list_init(&state.output_add.link);
 | 
					 | 
				
			||||||
	wl_list_init(&state.output_remove.link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parse_args(argc, argv, &state.config);
 | 
						parse_args(argc, argv, &state.config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_display *display = wl_display_create();
 | 
						compositor_init(&compositor);
 | 
				
			||||||
	struct wl_event_loop *event_loop = wl_display_get_event_loop(display);
 | 
						compositor.output_add_cb = handle_output_add;
 | 
				
			||||||
 | 
						compositor.output_remove_cb = handle_output_remove;
 | 
				
			||||||
	struct wlr_session *session = wlr_session_start(display);
 | 
						compositor.output_frame_cb = handle_output_frame;
 | 
				
			||||||
	if (!session) {
 | 
						compositor.keyboard_key_cb = handle_keyboard_key;
 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct wlr_backend *wlr = wlr_backend_autocreate(display, session);
 | 
					 | 
				
			||||||
	if (!wlr) {
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_signal_add(&wlr->events.output_add, &state.output_add);
 | 
					 | 
				
			||||||
	wl_signal_add(&wlr->events.output_remove, &state.output_remove);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!wlr_backend_init(wlr)) {
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	state.renderer = wlr_gles3_renderer_init();
 | 
						state.renderer = wlr_gles3_renderer_init();
 | 
				
			||||||
	state.cat_texture = wlr_render_surface_init(state.renderer);
 | 
						state.cat_texture = wlr_render_surface_init(state.renderer);
 | 
				
			||||||
	wlr_surface_attach_pixels(state.cat_texture, GL_RGB,
 | 
						wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
 | 
				
			||||||
		cat_tex.width, cat_tex.height, cat_tex.pixel_data);
 | 
							cat_tex.width, cat_tex.height, cat_tex.pixel_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool done = false;
 | 
						compositor.data = &state;
 | 
				
			||||||
	struct wl_event_source *timer = wl_event_loop_add_timer(event_loop,
 | 
						compositor_run(&compositor);
 | 
				
			||||||
		timer_done, &done);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_event_source_timer_update(timer, 30000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (!done) {
 | 
					 | 
				
			||||||
		wl_event_loop_dispatch(event_loop, 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_event_source_remove(timer);
 | 
					 | 
				
			||||||
	wlr_backend_destroy(wlr);
 | 
					 | 
				
			||||||
	wlr_session_finish(session);
 | 
					 | 
				
			||||||
	wlr_surface_destroy(state.cat_texture);
 | 
						wlr_surface_destroy(state.cat_texture);
 | 
				
			||||||
	wlr_renderer_destroy(state.renderer);
 | 
						wlr_renderer_destroy(state.renderer);
 | 
				
			||||||
	wl_display_destroy(display);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct output_config *ptr, *tmp;
 | 
						struct output_config *ptr, *tmp;
 | 
				
			||||||
	wl_list_for_each_safe(ptr, tmp, &state.config, link) {
 | 
						wl_list_for_each_safe(ptr, tmp, &state.config, link) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										432
									
								
								example/shared.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										432
									
								
								example/shared.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,432 @@
 | 
				
			||||||
 | 
					#define _POSIX_C_SOURCE 199309L
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					#include <wayland-server-protocol.h>
 | 
				
			||||||
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include "shared.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void keyboard_key_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_keyboard_key *event = data;
 | 
				
			||||||
 | 
						struct keyboard_state *kbstate = wl_container_of(listener, kbstate, key);
 | 
				
			||||||
 | 
						uint32_t keycode = event->keycode + 8;
 | 
				
			||||||
 | 
						enum wlr_key_state key_state = event->state;
 | 
				
			||||||
 | 
						const xkb_keysym_t *syms;
 | 
				
			||||||
 | 
						int nsyms = xkb_state_key_get_syms(kbstate->xkb_state, keycode, &syms);
 | 
				
			||||||
 | 
						for (int i = 0; i < nsyms; ++i) {
 | 
				
			||||||
 | 
							xkb_keysym_t sym = syms[i];
 | 
				
			||||||
 | 
							char name[64];
 | 
				
			||||||
 | 
							int l = xkb_keysym_get_name(sym, name, sizeof(name));
 | 
				
			||||||
 | 
							if (l != -1 && l != sizeof(name)) {
 | 
				
			||||||
 | 
								fprintf(stderr, "Key event: %s %s\n", name,
 | 
				
			||||||
 | 
										key_state == WLR_KEY_PRESSED ? "pressed" : "released");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (kbstate->compositor->keyboard_key_cb) {
 | 
				
			||||||
 | 
								kbstate->compositor->keyboard_key_cb(kbstate, sym, key_state);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						xkb_state_update_key(kbstate->xkb_state, keycode,
 | 
				
			||||||
 | 
							event->state == WLR_KEY_PRESSED ?  XKB_KEY_DOWN : XKB_KEY_UP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void keyboard_add(struct wlr_input_device *device, struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct keyboard_state *kbstate = calloc(sizeof(struct keyboard_state), 1);
 | 
				
			||||||
 | 
						kbstate->device = device;
 | 
				
			||||||
 | 
						kbstate->compositor = state;
 | 
				
			||||||
 | 
						wl_list_init(&kbstate->key.link);
 | 
				
			||||||
 | 
						kbstate->key.notify = keyboard_key_notify;
 | 
				
			||||||
 | 
						wl_signal_add(&device->keyboard->events.key, &kbstate->key);
 | 
				
			||||||
 | 
						wl_list_insert(&state->keyboards, &kbstate->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct xkb_rule_names rules;
 | 
				
			||||||
 | 
						memset(&rules, 0, sizeof(rules));
 | 
				
			||||||
 | 
						rules.rules = getenv("XKB_DEFAULT_RULES");
 | 
				
			||||||
 | 
						rules.model = getenv("XKB_DEFAULT_MODEL");
 | 
				
			||||||
 | 
						rules.layout = getenv("XKB_DEFAULT_LAYOUT");
 | 
				
			||||||
 | 
						rules.variant = getenv("XKB_DEFAULT_VARIANT");
 | 
				
			||||||
 | 
						rules.options = getenv("XKB_DEFAULT_OPTIONS");
 | 
				
			||||||
 | 
						struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
 | 
				
			||||||
 | 
						if (!context) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to create XKB context\n");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						kbstate->keymap = xkb_map_new_from_names(
 | 
				
			||||||
 | 
								context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
				
			||||||
 | 
						if (!kbstate->keymap) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to create XKB keymap\n");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						xkb_context_unref(context);
 | 
				
			||||||
 | 
						kbstate->xkb_state = xkb_state_new(kbstate->keymap);
 | 
				
			||||||
 | 
						if (!kbstate->xkb_state) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to create XKB state\n");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pointer_motion_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_pointer_motion *event = data;
 | 
				
			||||||
 | 
						struct pointer_state *pstate = wl_container_of(listener, pstate, motion);
 | 
				
			||||||
 | 
						if (pstate->compositor->pointer_motion_cb) {
 | 
				
			||||||
 | 
							pstate->compositor->pointer_motion_cb(pstate,
 | 
				
			||||||
 | 
									event->delta_x, event->delta_y);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pointer_button_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_pointer_button *event = data;
 | 
				
			||||||
 | 
						struct pointer_state *pstate = wl_container_of(listener, pstate, button);
 | 
				
			||||||
 | 
						if (pstate->compositor->pointer_button_cb) {
 | 
				
			||||||
 | 
							pstate->compositor->pointer_button_cb(pstate,
 | 
				
			||||||
 | 
									event->button, event->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pointer_axis_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_pointer_axis *event = data;
 | 
				
			||||||
 | 
						struct pointer_state *pstate = wl_container_of(listener, pstate, axis);
 | 
				
			||||||
 | 
						if (pstate->compositor->pointer_axis_cb) {
 | 
				
			||||||
 | 
							pstate->compositor->pointer_axis_cb(pstate,
 | 
				
			||||||
 | 
									event->source, event->orientation, event->delta);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pointer_add(struct wlr_input_device *device, struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct pointer_state *pstate = calloc(sizeof(struct pointer_state), 1);
 | 
				
			||||||
 | 
						pstate->device = device;
 | 
				
			||||||
 | 
						pstate->compositor = state;
 | 
				
			||||||
 | 
						wl_list_init(&pstate->motion.link);
 | 
				
			||||||
 | 
						wl_list_init(&pstate->motion_absolute.link);
 | 
				
			||||||
 | 
						wl_list_init(&pstate->button.link);
 | 
				
			||||||
 | 
						wl_list_init(&pstate->axis.link);
 | 
				
			||||||
 | 
						pstate->motion.notify = pointer_motion_notify;
 | 
				
			||||||
 | 
						pstate->button.notify = pointer_button_notify;
 | 
				
			||||||
 | 
						pstate->axis.notify = pointer_axis_notify;
 | 
				
			||||||
 | 
						wl_signal_add(&device->pointer->events.motion, &pstate->motion);
 | 
				
			||||||
 | 
						wl_signal_add(&device->pointer->events.button, &pstate->button);
 | 
				
			||||||
 | 
						wl_signal_add(&device->pointer->events.axis, &pstate->axis);
 | 
				
			||||||
 | 
						wl_list_insert(&state->pointers, &pstate->link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void touch_down_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_touch_down *event = data;
 | 
				
			||||||
 | 
						struct touch_state *tstate = wl_container_of(listener, tstate, down);
 | 
				
			||||||
 | 
						if (tstate->compositor->touch_down_cb) {
 | 
				
			||||||
 | 
							tstate->compositor->touch_down_cb(tstate, event->slot,
 | 
				
			||||||
 | 
								event->x_mm, event->y_mm, event->width_mm, event->height_mm);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void touch_motion_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_touch_motion *event = data;
 | 
				
			||||||
 | 
						struct touch_state *tstate = wl_container_of(listener, tstate, motion);
 | 
				
			||||||
 | 
						if (tstate->compositor->touch_motion_cb) {
 | 
				
			||||||
 | 
							tstate->compositor->touch_motion_cb(tstate, event->slot,
 | 
				
			||||||
 | 
								event->x_mm, event->y_mm, event->width_mm, event->height_mm);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void touch_up_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_touch_up *event = data;
 | 
				
			||||||
 | 
						struct touch_state *tstate = wl_container_of(listener, tstate, up);
 | 
				
			||||||
 | 
						if (tstate->compositor->touch_up_cb) {
 | 
				
			||||||
 | 
							tstate->compositor->touch_up_cb(tstate, event->slot);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void touch_cancel_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_touch_cancel *event = data;
 | 
				
			||||||
 | 
						struct touch_state *tstate = wl_container_of(listener, tstate, cancel);
 | 
				
			||||||
 | 
						if (tstate->compositor->touch_cancel_cb) {
 | 
				
			||||||
 | 
							tstate->compositor->touch_cancel_cb(tstate, event->slot);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void touch_add(struct wlr_input_device *device, struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct touch_state *tstate = calloc(sizeof(struct touch_state), 1);
 | 
				
			||||||
 | 
						tstate->device = device;
 | 
				
			||||||
 | 
						tstate->compositor = state;
 | 
				
			||||||
 | 
						wl_list_init(&tstate->down.link);
 | 
				
			||||||
 | 
						wl_list_init(&tstate->motion.link);
 | 
				
			||||||
 | 
						wl_list_init(&tstate->up.link);
 | 
				
			||||||
 | 
						wl_list_init(&tstate->cancel.link);
 | 
				
			||||||
 | 
						tstate->down.notify = touch_down_notify;
 | 
				
			||||||
 | 
						tstate->motion.notify = touch_motion_notify;
 | 
				
			||||||
 | 
						tstate->up.notify = touch_up_notify;
 | 
				
			||||||
 | 
						tstate->cancel.notify = touch_cancel_notify;
 | 
				
			||||||
 | 
						wl_signal_add(&device->touch->events.down, &tstate->down);
 | 
				
			||||||
 | 
						wl_signal_add(&device->touch->events.motion, &tstate->motion);
 | 
				
			||||||
 | 
						wl_signal_add(&device->touch->events.up, &tstate->up);
 | 
				
			||||||
 | 
						wl_signal_add(&device->touch->events.cancel, &tstate->cancel);
 | 
				
			||||||
 | 
						wl_list_insert(&state->touch, &tstate->link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tablet_tool_axis_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_axis *event = data;
 | 
				
			||||||
 | 
						struct tablet_tool_state *tstate = wl_container_of(listener, tstate, axis);
 | 
				
			||||||
 | 
						if (tstate->compositor->tool_axis_cb) {
 | 
				
			||||||
 | 
							tstate->compositor->tool_axis_cb(tstate, event);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tablet_tool_proximity_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_proximity *event = data;
 | 
				
			||||||
 | 
						struct tablet_tool_state *tstate = wl_container_of(listener, tstate, proximity);
 | 
				
			||||||
 | 
						if (tstate->compositor->tool_proximity_cb) {
 | 
				
			||||||
 | 
							tstate->compositor->tool_proximity_cb(tstate, event->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tablet_tool_button_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_button *event = data;
 | 
				
			||||||
 | 
						struct tablet_tool_state *tstate = wl_container_of(listener, tstate, button);
 | 
				
			||||||
 | 
						if (tstate->compositor->tool_button_cb) {
 | 
				
			||||||
 | 
							tstate->compositor->tool_button_cb(tstate, event->button, event->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tablet_tool_add(struct wlr_input_device *device,
 | 
				
			||||||
 | 
							struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct tablet_tool_state *tstate = calloc(sizeof(struct tablet_tool_state), 1);
 | 
				
			||||||
 | 
						tstate->device = device;
 | 
				
			||||||
 | 
						tstate->compositor = state;
 | 
				
			||||||
 | 
						wl_list_init(&tstate->axis.link);
 | 
				
			||||||
 | 
						wl_list_init(&tstate->proximity.link);
 | 
				
			||||||
 | 
						wl_list_init(&tstate->tip.link);
 | 
				
			||||||
 | 
						wl_list_init(&tstate->button.link);
 | 
				
			||||||
 | 
						tstate->axis.notify = tablet_tool_axis_notify;
 | 
				
			||||||
 | 
						tstate->proximity.notify = tablet_tool_proximity_notify;
 | 
				
			||||||
 | 
						//tstate->tip.notify = tablet_tool_tip_notify;
 | 
				
			||||||
 | 
						tstate->button.notify = tablet_tool_button_notify;
 | 
				
			||||||
 | 
						wl_signal_add(&device->tablet_tool->events.axis, &tstate->axis);
 | 
				
			||||||
 | 
						wl_signal_add(&device->tablet_tool->events.proximity, &tstate->proximity);
 | 
				
			||||||
 | 
						//wl_signal_add(&device->tablet_tool->events.tip, &tstate->tip);
 | 
				
			||||||
 | 
						wl_signal_add(&device->tablet_tool->events.button, &tstate->button);
 | 
				
			||||||
 | 
						wl_list_insert(&state->tablet_tools, &tstate->link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void input_add_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_input_device *device = data;
 | 
				
			||||||
 | 
						struct compositor_state *state = wl_container_of(listener, state, input_add);
 | 
				
			||||||
 | 
						switch (device->type) {
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_KEYBOARD:
 | 
				
			||||||
 | 
							keyboard_add(device, state);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_POINTER:
 | 
				
			||||||
 | 
							pointer_add(device, state);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_TOUCH:
 | 
				
			||||||
 | 
							touch_add(device, state);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_TABLET_TOOL:
 | 
				
			||||||
 | 
							tablet_tool_add(device, state);
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void keyboard_remove(struct wlr_input_device *device, struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct keyboard_state *kbstate = NULL, *_kbstate;
 | 
				
			||||||
 | 
						wl_list_for_each(_kbstate, &state->keyboards, link) {
 | 
				
			||||||
 | 
							if (_kbstate->device == device) {
 | 
				
			||||||
 | 
								kbstate = _kbstate;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!kbstate) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&kbstate->link);
 | 
				
			||||||
 | 
						wl_list_remove(&kbstate->key.link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pointer_remove(struct wlr_input_device *device, struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct pointer_state *pstate = NULL, *_pstate;
 | 
				
			||||||
 | 
						wl_list_for_each(_pstate, &state->pointers, link) {
 | 
				
			||||||
 | 
							if (_pstate->device == device) {
 | 
				
			||||||
 | 
								pstate = _pstate;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!pstate) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&pstate->link);
 | 
				
			||||||
 | 
						wl_list_remove(&pstate->motion.link);
 | 
				
			||||||
 | 
						//wl_list_remove(&pstate->motion_absolute.link);
 | 
				
			||||||
 | 
						wl_list_remove(&pstate->button.link);
 | 
				
			||||||
 | 
						wl_list_remove(&pstate->axis.link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void touch_remove(struct wlr_input_device *device, struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct touch_state *tstate = NULL, *_tstate;
 | 
				
			||||||
 | 
						wl_list_for_each(_tstate, &state->touch, link) {
 | 
				
			||||||
 | 
							if (_tstate->device == device) {
 | 
				
			||||||
 | 
								tstate = _tstate;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!tstate) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->link);
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->down.link);
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->motion.link);
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->up.link);
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->cancel.link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tablet_tool_remove(struct wlr_input_device *device, struct compositor_state *state) {
 | 
				
			||||||
 | 
						struct tablet_tool_state *tstate = NULL, *_tstate;
 | 
				
			||||||
 | 
						wl_list_for_each(_tstate, &state->tablet_tools, link) {
 | 
				
			||||||
 | 
							if (_tstate->device == device) {
 | 
				
			||||||
 | 
								tstate = _tstate;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!tstate) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->link);
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->axis.link);
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->proximity.link);
 | 
				
			||||||
 | 
						//wl_list_remove(&tstate->tip.link);
 | 
				
			||||||
 | 
						wl_list_remove(&tstate->button.link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void input_remove_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_input_device *device = data;
 | 
				
			||||||
 | 
						struct compositor_state *state = wl_container_of(listener, state, input_add);
 | 
				
			||||||
 | 
						switch (device->type) {
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_KEYBOARD:
 | 
				
			||||||
 | 
							keyboard_remove(device, state);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_POINTER:
 | 
				
			||||||
 | 
							pointer_remove(device, state);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_TOUCH:
 | 
				
			||||||
 | 
							touch_remove(device, state);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WLR_INPUT_DEVICE_TABLET_TOOL:
 | 
				
			||||||
 | 
							tablet_tool_remove(device, state);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void output_frame_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct output_state *output = wl_container_of(listener, output, frame);
 | 
				
			||||||
 | 
						struct compositor_state *compositor = output->compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct timespec now;
 | 
				
			||||||
 | 
						clock_gettime(CLOCK_MONOTONIC, &now);
 | 
				
			||||||
 | 
						if (compositor->output_frame_cb) {
 | 
				
			||||||
 | 
							compositor->output_frame_cb(output, &now);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output->last_frame = now;
 | 
				
			||||||
 | 
						compositor->last_frame = now;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void output_add_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_output *output = data;
 | 
				
			||||||
 | 
						struct compositor_state *state = wl_container_of(listener, state, output_add);
 | 
				
			||||||
 | 
						fprintf(stderr, "Output '%s' added\n", output->name);
 | 
				
			||||||
 | 
						fprintf(stderr, "%s %s %"PRId32"mm x %"PRId32"mm\n", output->make, output->model,
 | 
				
			||||||
 | 
							output->phys_width, output->phys_height);
 | 
				
			||||||
 | 
						wlr_output_set_mode(output, output->modes->items[0]);
 | 
				
			||||||
 | 
						struct output_state *ostate = calloc(1, sizeof(struct output_state));
 | 
				
			||||||
 | 
						clock_gettime(CLOCK_MONOTONIC, &ostate->last_frame);
 | 
				
			||||||
 | 
						ostate->output = output;
 | 
				
			||||||
 | 
						ostate->compositor = state;
 | 
				
			||||||
 | 
						ostate->frame.notify = output_frame_notify;
 | 
				
			||||||
 | 
						wl_list_init(&ostate->frame.link);
 | 
				
			||||||
 | 
						wl_signal_add(&output->events.frame, &ostate->frame);
 | 
				
			||||||
 | 
						wl_list_insert(&state->outputs, &ostate->link);
 | 
				
			||||||
 | 
						if (state->output_add_cb) {
 | 
				
			||||||
 | 
							state->output_add_cb(ostate);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void output_remove_notify(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_output *output = data;
 | 
				
			||||||
 | 
						struct compositor_state *state = wl_container_of(listener, state, output_remove);
 | 
				
			||||||
 | 
						struct output_state *ostate = NULL, *_ostate;
 | 
				
			||||||
 | 
						wl_list_for_each(_ostate, &state->outputs, link) {
 | 
				
			||||||
 | 
							if (_ostate->output == output) {
 | 
				
			||||||
 | 
								ostate = _ostate;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!ostate) {
 | 
				
			||||||
 | 
							return; // We are unfamiliar with this output
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (state->output_remove_cb) {
 | 
				
			||||||
 | 
							state->output_remove_cb(ostate);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&ostate->link);
 | 
				
			||||||
 | 
						wl_list_remove(&ostate->frame.link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void compositor_init(struct compositor_state *state) {
 | 
				
			||||||
 | 
						memset(state, 0, sizeof(struct compositor_state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state->display = wl_display_create();
 | 
				
			||||||
 | 
						state->event_loop = wl_display_get_event_loop(state->display);
 | 
				
			||||||
 | 
						state->session = wlr_session_start(state->display);
 | 
				
			||||||
 | 
						if (!state->session
 | 
				
			||||||
 | 
								|| !state->display
 | 
				
			||||||
 | 
								|| !state->event_loop) {
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_init(&state->keyboards);
 | 
				
			||||||
 | 
						wl_list_init(&state->pointers);
 | 
				
			||||||
 | 
						wl_list_init(&state->touch);
 | 
				
			||||||
 | 
						wl_list_init(&state->tablet_tools);
 | 
				
			||||||
 | 
						wl_list_init(&state->input_add.link);
 | 
				
			||||||
 | 
						state->input_add.notify = input_add_notify;
 | 
				
			||||||
 | 
						wl_list_init(&state->input_remove.link);
 | 
				
			||||||
 | 
						state->input_remove.notify = input_remove_notify;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_init(&state->outputs);
 | 
				
			||||||
 | 
						wl_list_init(&state->output_add.link);
 | 
				
			||||||
 | 
						state->output_add.notify = output_add_notify;
 | 
				
			||||||
 | 
						wl_list_init(&state->output_remove.link);
 | 
				
			||||||
 | 
						state->output_remove.notify = output_remove_notify;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_backend *wlr = wlr_backend_autocreate(
 | 
				
			||||||
 | 
								state->display, state->session);
 | 
				
			||||||
 | 
						if (!wlr) {
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_signal_add(&wlr->events.input_add, &state->input_add);
 | 
				
			||||||
 | 
						wl_signal_add(&wlr->events.input_remove, &state->input_remove);
 | 
				
			||||||
 | 
						wl_signal_add(&wlr->events.output_add, &state->output_add);
 | 
				
			||||||
 | 
						wl_signal_add(&wlr->events.output_remove, &state->output_remove);
 | 
				
			||||||
 | 
						state->backend = wlr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clock_gettime(CLOCK_MONOTONIC, &state->last_frame);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void compositor_run(struct compositor_state *state) {
 | 
				
			||||||
 | 
						if (!wlr_backend_init(state->backend)) {
 | 
				
			||||||
 | 
							fprintf(stderr, "Failed to initialize backend\n");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!state->exit) {
 | 
				
			||||||
 | 
							wl_event_loop_dispatch(state->event_loop, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_backend_destroy(state->backend);
 | 
				
			||||||
 | 
						wlr_session_finish(state->session);
 | 
				
			||||||
 | 
						wl_display_destroy(state->display);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										119
									
								
								example/shared.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								example/shared.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,119 @@
 | 
				
			||||||
 | 
					#ifndef _EXAMPLE_SHARED_H
 | 
				
			||||||
 | 
					#define _EXAMPLE_SHARED_H
 | 
				
			||||||
 | 
					#define _POSIX_C_SOURCE 199309L
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					#include <wayland-server-protocol.h>
 | 
				
			||||||
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct output_state {
 | 
				
			||||||
 | 
						struct compositor_state *compositor;
 | 
				
			||||||
 | 
						struct wlr_output *output;
 | 
				
			||||||
 | 
						struct wl_listener frame;
 | 
				
			||||||
 | 
						struct timespec last_frame;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct keyboard_state {
 | 
				
			||||||
 | 
						struct compositor_state *compositor;
 | 
				
			||||||
 | 
						struct wlr_input_device *device;
 | 
				
			||||||
 | 
						struct wl_listener key;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
						struct xkb_keymap *keymap;
 | 
				
			||||||
 | 
						struct xkb_state *xkb_state;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct pointer_state {
 | 
				
			||||||
 | 
						struct compositor_state *compositor;
 | 
				
			||||||
 | 
						struct wlr_input_device *device;
 | 
				
			||||||
 | 
						struct wl_listener motion;
 | 
				
			||||||
 | 
						struct wl_listener motion_absolute;
 | 
				
			||||||
 | 
						struct wl_listener button;
 | 
				
			||||||
 | 
						struct wl_listener axis;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct touch_state {
 | 
				
			||||||
 | 
						struct compositor_state *compositor;
 | 
				
			||||||
 | 
						struct wlr_input_device *device;
 | 
				
			||||||
 | 
						struct wl_listener down;
 | 
				
			||||||
 | 
						struct wl_listener up;
 | 
				
			||||||
 | 
						struct wl_listener motion;
 | 
				
			||||||
 | 
						struct wl_listener cancel;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct tablet_tool_state {
 | 
				
			||||||
 | 
						struct compositor_state *compositor;
 | 
				
			||||||
 | 
						struct wlr_input_device *device;
 | 
				
			||||||
 | 
						struct wl_listener axis;
 | 
				
			||||||
 | 
						struct wl_listener proximity;
 | 
				
			||||||
 | 
						struct wl_listener tip;
 | 
				
			||||||
 | 
						struct wl_listener button;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct compositor_state {
 | 
				
			||||||
 | 
						void (*output_add_cb)(struct output_state *s);
 | 
				
			||||||
 | 
						void (*keyboard_add_cb)(struct keyboard_state *s);
 | 
				
			||||||
 | 
						void (*output_frame_cb)(struct output_state *s, struct timespec *ts);
 | 
				
			||||||
 | 
						void (*output_remove_cb)(struct output_state *s);
 | 
				
			||||||
 | 
						void (*keyboard_remove_cb)(struct keyboard_state *s);
 | 
				
			||||||
 | 
						void (*keyboard_key_cb)(struct keyboard_state *s, xkb_keysym_t sym,
 | 
				
			||||||
 | 
								enum wlr_key_state key_state);
 | 
				
			||||||
 | 
						void (*pointer_motion_cb)(struct pointer_state *s,
 | 
				
			||||||
 | 
								double d_x, double d_y);
 | 
				
			||||||
 | 
						void (*pointer_button_cb)(struct pointer_state *s,
 | 
				
			||||||
 | 
								uint32_t button, enum wlr_button_state state);
 | 
				
			||||||
 | 
						void (*pointer_axis_cb)(struct pointer_state *s,
 | 
				
			||||||
 | 
							enum wlr_axis_source source,
 | 
				
			||||||
 | 
							enum wlr_axis_orientation orientation,
 | 
				
			||||||
 | 
							double delta);
 | 
				
			||||||
 | 
						void (*touch_down_cb)(struct touch_state *s, int32_t slot,
 | 
				
			||||||
 | 
							double x, double y, double width, double height);
 | 
				
			||||||
 | 
						void (*touch_motion_cb)(struct touch_state *s, int32_t slot,
 | 
				
			||||||
 | 
							double x, double y, double width, double height);
 | 
				
			||||||
 | 
						void (*touch_up_cb)(struct touch_state *s, int32_t slot);
 | 
				
			||||||
 | 
						void (*touch_cancel_cb)(struct touch_state *s, int32_t slot);
 | 
				
			||||||
 | 
						void (*tool_axis_cb)(struct tablet_tool_state *s,
 | 
				
			||||||
 | 
								struct wlr_tablet_tool_axis *event);
 | 
				
			||||||
 | 
						void (*tool_proximity_cb)(struct tablet_tool_state *s,
 | 
				
			||||||
 | 
								enum wlr_tablet_tool_proximity_state proximity);
 | 
				
			||||||
 | 
						void (*tool_tip_cb)(struct tablet_tool_state *s,
 | 
				
			||||||
 | 
								enum wlr_tablet_tool_tip_state state);
 | 
				
			||||||
 | 
						void (*tool_button_cb)(struct tablet_tool_state *s,
 | 
				
			||||||
 | 
								uint32_t button, enum wlr_button_state state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_display *display;
 | 
				
			||||||
 | 
						struct wl_event_loop *event_loop;
 | 
				
			||||||
 | 
						struct wlr_backend *backend;
 | 
				
			||||||
 | 
						struct wlr_session *session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_list keyboards;
 | 
				
			||||||
 | 
						struct wl_list pointers;
 | 
				
			||||||
 | 
						struct wl_list touch;
 | 
				
			||||||
 | 
						struct wl_list tablet_tools;
 | 
				
			||||||
 | 
						struct wl_listener input_add;
 | 
				
			||||||
 | 
						struct wl_listener input_remove;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct timespec last_frame;
 | 
				
			||||||
 | 
						struct wl_listener output_add;
 | 
				
			||||||
 | 
						struct wl_listener output_remove;
 | 
				
			||||||
 | 
						struct wl_list outputs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool exit;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void compositor_init(struct compositor_state *state);
 | 
				
			||||||
 | 
					void compositor_run(struct compositor_state *state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										155
									
								
								example/simple.c
									
										
									
									
									
								
							
							
						
						
									
										155
									
								
								example/simple.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
#define _POSIX_C_SOURCE 199309L
 | 
					#define _POSIX_C_SOURCE 199309L
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
| 
						 | 
					@ -8,152 +9,52 @@
 | 
				
			||||||
#include <wlr/backend.h>
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
#include <wlr/session.h>
 | 
					#include <wlr/session.h>
 | 
				
			||||||
#include <wlr/types.h>
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					#include "shared.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct state {
 | 
					struct sample_state {
 | 
				
			||||||
	float color[3];
 | 
						float color[3];
 | 
				
			||||||
	int dec;
 | 
						int dec;
 | 
				
			||||||
	struct timespec last_frame;
 | 
					 | 
				
			||||||
	struct wl_listener output_add;
 | 
					 | 
				
			||||||
	struct wl_listener output_remove;
 | 
					 | 
				
			||||||
	struct wl_list outputs;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct output_state {
 | 
					void handle_output_frame(struct output_state *output, struct timespec *ts) {
 | 
				
			||||||
	struct wl_list link;
 | 
						struct compositor_state *state = output->compositor;
 | 
				
			||||||
	struct wlr_output *output;
 | 
						struct sample_state *sample = state->data;
 | 
				
			||||||
	struct state *state;
 | 
					 | 
				
			||||||
	struct wl_listener frame;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void output_frame(struct wl_listener *listener, void *data) {
 | 
						long ms = (ts->tv_sec - state->last_frame.tv_sec) * 1000 +
 | 
				
			||||||
	struct output_state *ostate = wl_container_of(listener, ostate, frame);
 | 
							(ts->tv_nsec - state->last_frame.tv_nsec) / 1000000;
 | 
				
			||||||
	struct state *s = ostate->state;
 | 
						int inc = (sample->dec + 1) % 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct timespec now;
 | 
						sample->color[inc] += ms / 2000.0f;
 | 
				
			||||||
	clock_gettime(CLOCK_MONOTONIC, &now);
 | 
						sample->color[sample->dec] -= ms / 2000.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	long ms = (now.tv_sec - s->last_frame.tv_sec) * 1000 +
 | 
						if (sample->color[sample->dec] < 0.0f) {
 | 
				
			||||||
		(now.tv_nsec - s->last_frame.tv_nsec) / 1000000;
 | 
							sample->color[inc] = 1.0f;
 | 
				
			||||||
	int inc = (s->dec + 1) % 3;
 | 
							sample->color[sample->dec] = 0.0f;
 | 
				
			||||||
 | 
							sample->dec = inc;
 | 
				
			||||||
	s->color[inc] += ms / 2000.0f;
 | 
					 | 
				
			||||||
	s->color[s->dec] -= ms / 2000.0f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (s->color[s->dec] < 0.0f) {
 | 
					 | 
				
			||||||
		s->color[inc] = 1.0f;
 | 
					 | 
				
			||||||
		s->color[s->dec] = 0.0f;
 | 
					 | 
				
			||||||
		s->dec = inc;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s->last_frame = now;
 | 
						glClearColor(sample->color[0], sample->color[1], sample->color[2], 1.0);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	glClearColor(s->color[0], s->color[1], s->color[2], 1.0);
 | 
					 | 
				
			||||||
	glClear(GL_COLOR_BUFFER_BIT);
 | 
						glClear(GL_COLOR_BUFFER_BIT);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void output_add(struct wl_listener *listener, void *data) {
 | 
					static void handle_keyboard_key(struct keyboard_state *kbstate,
 | 
				
			||||||
	struct wlr_output *output = data;
 | 
							xkb_keysym_t sym, enum wlr_key_state key_state) {
 | 
				
			||||||
	struct state *state = wl_container_of(listener, state, output_add);
 | 
						if (sym == XKB_KEY_Escape) {
 | 
				
			||||||
	fprintf(stderr, "Output '%s' added\n", output->name);
 | 
							kbstate->compositor->exit = true;
 | 
				
			||||||
	fprintf(stderr, "%s %s %"PRId32"mm x %"PRId32"mm\n", output->make, output->model,
 | 
					 | 
				
			||||||
		output->phys_width, output->phys_height);
 | 
					 | 
				
			||||||
	wlr_output_set_mode(output, output->modes->items[0]);
 | 
					 | 
				
			||||||
	struct output_state *ostate = calloc(1, sizeof(struct output_state));
 | 
					 | 
				
			||||||
	ostate->output = output;
 | 
					 | 
				
			||||||
	ostate->state = state;
 | 
					 | 
				
			||||||
	ostate->frame.notify = output_frame;
 | 
					 | 
				
			||||||
	wl_list_init(&ostate->frame.link);
 | 
					 | 
				
			||||||
	wl_signal_add(&output->events.frame, &ostate->frame);
 | 
					 | 
				
			||||||
	wl_list_insert(&state->outputs, &ostate->link);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void output_remove(struct wl_listener *listener, void *data) {
 | 
					 | 
				
			||||||
	struct wlr_output *output = data;
 | 
					 | 
				
			||||||
	struct state *state = wl_container_of(listener, state, output_remove);
 | 
					 | 
				
			||||||
	struct output_state *ostate = NULL, *_ostate;
 | 
					 | 
				
			||||||
	wl_list_for_each(_ostate, &state->outputs, link) {
 | 
					 | 
				
			||||||
		if (_ostate->output == output) {
 | 
					 | 
				
			||||||
			ostate = _ostate;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!ostate) {
 | 
					 | 
				
			||||||
		return; // We are unfamiliar with this output
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	wl_list_remove(&ostate->link);
 | 
					 | 
				
			||||||
	wl_list_remove(&ostate->frame.link);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int timer_done(void *data) {
 | 
					 | 
				
			||||||
	*(bool *)data = true;
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int enable_outputs(void *data) {
 | 
					 | 
				
			||||||
	struct state *state = data;
 | 
					 | 
				
			||||||
	struct output_state *ostate;
 | 
					 | 
				
			||||||
	wl_list_for_each(ostate, &state->outputs, link) {
 | 
					 | 
				
			||||||
		struct wlr_output *output = ostate->output;
 | 
					 | 
				
			||||||
		wlr_output_enable(output, true);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int disable_outputs(void *data) {
 | 
					 | 
				
			||||||
	struct state *state = data;
 | 
					 | 
				
			||||||
	struct output_state *ostate;
 | 
					 | 
				
			||||||
	wl_list_for_each(ostate, &state->outputs, link) {
 | 
					 | 
				
			||||||
		struct wlr_output *output = ostate->output;
 | 
					 | 
				
			||||||
		wlr_output_enable(output, false);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main() {
 | 
					int main() {
 | 
				
			||||||
	struct state state = {
 | 
						struct sample_state state = {
 | 
				
			||||||
		.color = { 1.0, 0.0, 0.0 },
 | 
							.color = { 1.0, 0.0, 0.0 },
 | 
				
			||||||
		.dec = 0,
 | 
							.dec = 0,
 | 
				
			||||||
		.output_add = { .notify = output_add },
 | 
					 | 
				
			||||||
		.output_remove = { .notify = output_remove }
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						struct compositor_state compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_init(&state.outputs);
 | 
						compositor_init(&compositor);
 | 
				
			||||||
	wl_list_init(&state.output_add.link);
 | 
						compositor.output_frame_cb = handle_output_frame;
 | 
				
			||||||
	wl_list_init(&state.output_remove.link);
 | 
						compositor.keyboard_key_cb = handle_keyboard_key;
 | 
				
			||||||
	clock_gettime(CLOCK_MONOTONIC, &state.last_frame);
 | 
						compositor.data = &state;
 | 
				
			||||||
 | 
						compositor_run(&compositor);
 | 
				
			||||||
	struct wl_display *display = wl_display_create();
 | 
					 | 
				
			||||||
	struct wl_event_loop *event_loop = wl_display_get_event_loop(display);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct wlr_session *session = wlr_session_start(display);
 | 
					 | 
				
			||||||
	if (!session) {
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct wlr_backend *wlr = wlr_backend_autocreate(display, session);
 | 
					 | 
				
			||||||
	wl_signal_add(&wlr->events.output_add, &state.output_add);
 | 
					 | 
				
			||||||
	wl_signal_add(&wlr->events.output_remove, &state.output_remove);
 | 
					 | 
				
			||||||
	if (!wlr || !wlr_backend_init(wlr)) {
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool done = false;
 | 
					 | 
				
			||||||
	struct wl_event_source *timer = wl_event_loop_add_timer(event_loop,
 | 
					 | 
				
			||||||
		timer_done, &done);
 | 
					 | 
				
			||||||
	struct wl_event_source *timer_disable_outputs =
 | 
					 | 
				
			||||||
		wl_event_loop_add_timer(event_loop, disable_outputs, &state);
 | 
					 | 
				
			||||||
	struct wl_event_source *timer_enable_outputs =
 | 
					 | 
				
			||||||
		wl_event_loop_add_timer(event_loop, enable_outputs, &state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_event_source_timer_update(timer, 20000);
 | 
					 | 
				
			||||||
	wl_event_source_timer_update(timer_disable_outputs, 5000);
 | 
					 | 
				
			||||||
	wl_event_source_timer_update(timer_enable_outputs, 10000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (!done) {
 | 
					 | 
				
			||||||
		wl_event_loop_dispatch(event_loop, 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_event_source_remove(timer);
 | 
					 | 
				
			||||||
	wlr_backend_destroy(wlr);
 | 
					 | 
				
			||||||
	wl_display_destroy(display);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										143
									
								
								example/tablet.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								example/tablet.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,143 @@
 | 
				
			||||||
 | 
					#define _POSIX_C_SOURCE 199309L
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wayland-server-protocol.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					#include <GLES3/gl3.h>
 | 
				
			||||||
 | 
					#include <wlr/render/matrix.h>
 | 
				
			||||||
 | 
					#include <wlr/render/gles3.h>
 | 
				
			||||||
 | 
					#include <wlr/render.h>
 | 
				
			||||||
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include "shared.h"
 | 
				
			||||||
 | 
					#include "cat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct sample_state {
 | 
				
			||||||
 | 
						struct wlr_renderer *renderer;
 | 
				
			||||||
 | 
						bool proximity, tap;
 | 
				
			||||||
 | 
						double distance;
 | 
				
			||||||
 | 
						double pressure;
 | 
				
			||||||
 | 
						double x_mm, y_mm;
 | 
				
			||||||
 | 
						double width_mm, height_mm;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
						float tool_color[4];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_output_frame(struct output_state *output, struct timespec *ts) {
 | 
				
			||||||
 | 
						struct compositor_state *state = output->compositor;
 | 
				
			||||||
 | 
						struct sample_state *sample = state->data;
 | 
				
			||||||
 | 
						struct wlr_output *wlr_output = output->output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int32_t width, height;
 | 
				
			||||||
 | 
						wlr_output_effective_resolution(wlr_output, &width, &height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_renderer_begin(sample->renderer, wlr_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float matrix[16], view[16];
 | 
				
			||||||
 | 
						float pad_color[4] = { 0.75, 0.75, 0.75, 1.0 };
 | 
				
			||||||
 | 
						float distance = 0.8f * (1 - sample->distance);
 | 
				
			||||||
 | 
						float tool_color[4] = { distance, distance, distance, 1 };
 | 
				
			||||||
 | 
						for (size_t i = 0; i < 4; ++i) {
 | 
				
			||||||
 | 
							tool_color[i] *= sample->tool_color[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						float scale = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float pad_width = sample->width_mm * scale;
 | 
				
			||||||
 | 
						float pad_height = sample->height_mm * scale;
 | 
				
			||||||
 | 
						float left = width / 2.0f - pad_width / 2.0f;
 | 
				
			||||||
 | 
						float top = height / 2.0f - pad_height / 2.0f;
 | 
				
			||||||
 | 
						wlr_matrix_translate(&matrix, left, top, 0);
 | 
				
			||||||
 | 
						wlr_matrix_scale(&view, pad_width, pad_height, 1);
 | 
				
			||||||
 | 
						wlr_matrix_mul(&matrix, &view, &view);
 | 
				
			||||||
 | 
						wlr_matrix_mul(&wlr_output->transform_matrix, &view, &matrix);
 | 
				
			||||||
 | 
						wlr_render_colored_quad(sample->renderer, &pad_color, &matrix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sample->proximity) {
 | 
				
			||||||
 | 
							wlr_matrix_translate(&matrix,
 | 
				
			||||||
 | 
									sample->x_mm * scale - 8 * (sample->pressure + 1) + left,
 | 
				
			||||||
 | 
									sample->y_mm * scale - 8 * (sample->pressure + 1) + top, 0);
 | 
				
			||||||
 | 
							wlr_matrix_scale(&view,
 | 
				
			||||||
 | 
									16 * (sample->pressure + 1),
 | 
				
			||||||
 | 
									16 * (sample->pressure + 1), 1);
 | 
				
			||||||
 | 
							wlr_matrix_mul(&matrix, &view, &view);
 | 
				
			||||||
 | 
							wlr_matrix_mul(&wlr_output->transform_matrix, &view, &matrix);
 | 
				
			||||||
 | 
							wlr_render_colored_ellipse(sample->renderer, &tool_color, &matrix);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_renderer_end(sample->renderer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_keyboard_key(struct keyboard_state *kbstate,
 | 
				
			||||||
 | 
							xkb_keysym_t sym, enum wlr_key_state key_state) {
 | 
				
			||||||
 | 
						if (sym == XKB_KEY_Escape) {
 | 
				
			||||||
 | 
							kbstate->compositor->exit = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_tool_axis(struct tablet_tool_state *tstate,
 | 
				
			||||||
 | 
								struct wlr_tablet_tool_axis *event) {
 | 
				
			||||||
 | 
						struct sample_state *sample = tstate->compositor->data;
 | 
				
			||||||
 | 
						sample->width_mm = event->width_mm;
 | 
				
			||||||
 | 
						sample->height_mm = event->height_mm;
 | 
				
			||||||
 | 
						if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) {
 | 
				
			||||||
 | 
							sample->x_mm = event->x_mm;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
 | 
				
			||||||
 | 
							sample->y_mm = event->y_mm;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE)) {
 | 
				
			||||||
 | 
							sample->distance = event->distance;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE)) {
 | 
				
			||||||
 | 
							sample->pressure = event->pressure;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_tool_proximity(struct tablet_tool_state *tstate,
 | 
				
			||||||
 | 
							enum wlr_tablet_tool_proximity_state state) {
 | 
				
			||||||
 | 
						struct sample_state *sample = tstate->compositor->data;
 | 
				
			||||||
 | 
						sample->proximity = state == WLR_TABLET_TOOL_PROXIMITY_IN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_tool_button(struct tablet_tool_state *tstate,
 | 
				
			||||||
 | 
							uint32_t button, enum wlr_button_state state) {
 | 
				
			||||||
 | 
						struct sample_state *sample = tstate->compositor->data;
 | 
				
			||||||
 | 
						if (state == WLR_BUTTON_RELEASED) {
 | 
				
			||||||
 | 
							float default_color[4] = { 1, 1, 1, 1 };
 | 
				
			||||||
 | 
							memcpy(sample->tool_color, default_color, 4);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							for (size_t i = 0; i < 3; ++i) {
 | 
				
			||||||
 | 
								if (button % 3 != i) {
 | 
				
			||||||
 | 
									sample->tool_color[button % 3] = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
 | 
						struct sample_state state = {
 | 
				
			||||||
 | 
							.tool_color = { 1, 1, 1, 1 }
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct compositor_state compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						compositor_init(&compositor);
 | 
				
			||||||
 | 
						compositor.output_frame_cb = handle_output_frame;
 | 
				
			||||||
 | 
						compositor.keyboard_key_cb = handle_keyboard_key;
 | 
				
			||||||
 | 
						compositor.tool_axis_cb = handle_tool_axis;
 | 
				
			||||||
 | 
						compositor.tool_proximity_cb = handle_tool_proximity;
 | 
				
			||||||
 | 
						compositor.tool_button_cb = handle_tool_button;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state.renderer = wlr_gles3_renderer_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						compositor.data = &state;
 | 
				
			||||||
 | 
						compositor_run(&compositor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_renderer_destroy(state.renderer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										122
									
								
								example/touch.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								example/touch.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,122 @@
 | 
				
			||||||
 | 
					#define _POSIX_C_SOURCE 199309L
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wayland-server-protocol.h>
 | 
				
			||||||
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
 | 
					#include <GLES3/gl3.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include <wlr/render/matrix.h>
 | 
				
			||||||
 | 
					#include <wlr/render/gles3.h>
 | 
				
			||||||
 | 
					#include <wlr/render.h>
 | 
				
			||||||
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include "shared.h"
 | 
				
			||||||
 | 
					#include "cat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct sample_state {
 | 
				
			||||||
 | 
						struct wlr_renderer *renderer;
 | 
				
			||||||
 | 
						struct wlr_surface *cat_texture;
 | 
				
			||||||
 | 
						list_t *touch_points;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct touch_point {
 | 
				
			||||||
 | 
						int32_t slot;
 | 
				
			||||||
 | 
						double x, y;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_output_frame(struct output_state *output, struct timespec *ts) {
 | 
				
			||||||
 | 
						struct compositor_state *state = output->compositor;
 | 
				
			||||||
 | 
						struct sample_state *sample = state->data;
 | 
				
			||||||
 | 
						struct wlr_output *wlr_output = output->output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int32_t width, height;
 | 
				
			||||||
 | 
						wlr_output_effective_resolution(wlr_output, &width, &height);
 | 
				
			||||||
 | 
						wlr_renderer_begin(sample->renderer, wlr_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float matrix[16];
 | 
				
			||||||
 | 
						for (size_t i = 0; i < sample->touch_points->length; ++i) {
 | 
				
			||||||
 | 
							struct touch_point *p = sample->touch_points->items[i];
 | 
				
			||||||
 | 
							wlr_surface_get_matrix(sample->cat_texture, &matrix,
 | 
				
			||||||
 | 
								&wlr_output->transform_matrix,
 | 
				
			||||||
 | 
								(int)(p->x * width) - sample->cat_texture->width / 2,
 | 
				
			||||||
 | 
								(int)(p->y * height) - sample->cat_texture->height / 2);
 | 
				
			||||||
 | 
							wlr_render_with_matrix(sample->renderer,
 | 
				
			||||||
 | 
									sample->cat_texture, &matrix);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_renderer_end(sample->renderer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_keyboard_key(struct keyboard_state *kbstate,
 | 
				
			||||||
 | 
							xkb_keysym_t sym, enum wlr_key_state key_state) {
 | 
				
			||||||
 | 
						if (sym == XKB_KEY_Escape) {
 | 
				
			||||||
 | 
							kbstate->compositor->exit = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_touch_down(struct touch_state *tstate, int32_t slot,
 | 
				
			||||||
 | 
							double x, double y, double width, double height) {
 | 
				
			||||||
 | 
						struct sample_state *sample = tstate->compositor->data;
 | 
				
			||||||
 | 
						struct touch_point *point = calloc(1, sizeof(struct touch_state));
 | 
				
			||||||
 | 
						point->slot = slot;
 | 
				
			||||||
 | 
						point->x = x / width;
 | 
				
			||||||
 | 
						point->y = y / height;
 | 
				
			||||||
 | 
						list_add(sample->touch_points, point);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_touch_up(struct touch_state *tstate, int32_t slot) {
 | 
				
			||||||
 | 
						struct sample_state *sample = tstate->compositor->data;
 | 
				
			||||||
 | 
						for (size_t i = 0; i < sample->touch_points->length; ++i) {
 | 
				
			||||||
 | 
							struct touch_point *point = sample->touch_points->items[i];
 | 
				
			||||||
 | 
							if (point->slot == slot) {
 | 
				
			||||||
 | 
								list_del(sample->touch_points, i);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_touch_motion(struct touch_state *tstate, int32_t slot,
 | 
				
			||||||
 | 
							double x, double y, double width, double height) {
 | 
				
			||||||
 | 
						struct sample_state *sample = tstate->compositor->data;
 | 
				
			||||||
 | 
						for (size_t i = 0; i < sample->touch_points->length; ++i) {
 | 
				
			||||||
 | 
							struct touch_point *point = sample->touch_points->items[i];
 | 
				
			||||||
 | 
							if (point->slot == slot) {
 | 
				
			||||||
 | 
								point->x = x / width;
 | 
				
			||||||
 | 
								point->y = y / height;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
 | 
						struct sample_state state = {
 | 
				
			||||||
 | 
							.touch_points = list_create()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct compositor_state compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						compositor_init(&compositor);
 | 
				
			||||||
 | 
						compositor.output_frame_cb = handle_output_frame;
 | 
				
			||||||
 | 
						compositor.keyboard_key_cb = handle_keyboard_key;
 | 
				
			||||||
 | 
						compositor.touch_down_cb = handle_touch_down;
 | 
				
			||||||
 | 
						compositor.touch_up_cb = handle_touch_up;
 | 
				
			||||||
 | 
						compositor.touch_motion_cb = handle_touch_motion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state.renderer = wlr_gles3_renderer_init();
 | 
				
			||||||
 | 
						state.cat_texture = wlr_render_surface_init(state.renderer);
 | 
				
			||||||
 | 
						wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
 | 
				
			||||||
 | 
							cat_tex.width, cat_tex.height, cat_tex.pixel_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						compositor.data = &state;
 | 
				
			||||||
 | 
						compositor_run(&compositor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_surface_destroy(state.cat_texture);
 | 
				
			||||||
 | 
						wlr_renderer_destroy(state.renderer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -73,10 +73,12 @@ struct wlr_output_state {
 | 
				
			||||||
	drmModeCrtc *old_crtc;
 | 
						drmModeCrtc *old_crtc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_drm_renderer *renderer;
 | 
						struct wlr_drm_renderer *renderer;
 | 
				
			||||||
	struct gbm_surface *gbm;
 | 
					 | 
				
			||||||
	struct gbm_bo *bo_last;
 | 
					 | 
				
			||||||
	struct gbm_bo *bo_current;
 | 
					 | 
				
			||||||
	EGLSurface *egl;
 | 
						EGLSurface *egl;
 | 
				
			||||||
 | 
						struct gbm_surface *gbm;
 | 
				
			||||||
 | 
						struct gbm_bo *bo[2];
 | 
				
			||||||
 | 
						struct gbm_bo *cursor_bo[2];
 | 
				
			||||||
 | 
						int current_cursor;
 | 
				
			||||||
 | 
						uint32_t cursor_width, cursor_height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool pageflip_pending;
 | 
						bool pageflip_pending;
 | 
				
			||||||
	bool cleanup;
 | 
						bool cleanup;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										71
									
								
								include/backend/libinput.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								include/backend/libinput.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,71 @@
 | 
				
			||||||
 | 
					#ifndef _WLR_BACKEND_LIBINPUT_INTERNAL_H
 | 
				
			||||||
 | 
					#define _WLR_BACKEND_LIBINPUT_INTERNAL_H
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/interface.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include <wayland-server-core.h>
 | 
				
			||||||
 | 
					#include "backend/udev.h"
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend_state {
 | 
				
			||||||
 | 
						struct wlr_backend *backend;
 | 
				
			||||||
 | 
						struct wlr_session *session;
 | 
				
			||||||
 | 
						struct wlr_udev *udev;
 | 
				
			||||||
 | 
						struct wl_display *display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct libinput *libinput;
 | 
				
			||||||
 | 
						struct wl_event_source *input_event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_t *devices;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device_state {
 | 
				
			||||||
 | 
						struct libinput_device *handle;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_libinput_event(struct wlr_backend_state *state,
 | 
				
			||||||
 | 
							struct libinput_event *event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device *get_appropriate_device(
 | 
				
			||||||
 | 
							enum wlr_input_device_type desired_type,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard *wlr_libinput_keyboard_create(
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_keyboard_key(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer *wlr_libinput_pointer_create(
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_pointer_motion(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_pointer_motion_abs(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_pointer_button(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_pointer_axis(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch *wlr_libinput_touch_create(
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_touch_down(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_touch_up(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_touch_motion(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_touch_cancel(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool *wlr_libinput_tablet_tool_create(
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_tablet_tool_axis(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_tablet_tool_proximity(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_tablet_tool_tip(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					void handle_tablet_tool_button(struct libinput_event *event,
 | 
				
			||||||
 | 
							struct libinput_device *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										13
									
								
								include/backend/multi.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								include/backend/multi.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					#ifndef _WLR_MULTI_BACKEND_INTERNAL
 | 
				
			||||||
 | 
					#define _WLR_MULTI_BACKEND_INTERNAL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <wlr/backend/interface.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/multi.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend_state {
 | 
				
			||||||
 | 
						struct wlr_backend *backend;
 | 
				
			||||||
 | 
						list_t *backends;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,9 @@ struct wlr_surface_state {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_surface *gles3_surface_init();
 | 
					struct wlr_surface *gles3_surface_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const GLchar quad_vertex_src[];
 | 
				
			||||||
 | 
					extern const GLchar quad_fragment_src[];
 | 
				
			||||||
 | 
					extern const GLchar ellipse_fragment_src[];
 | 
				
			||||||
extern const GLchar vertex_src[];
 | 
					extern const GLchar vertex_src[];
 | 
				
			||||||
extern const GLchar fragment_src_RGB[];
 | 
					extern const GLchar fragment_src_RGB[];
 | 
				
			||||||
extern const GLchar fragment_src_RGBA[];
 | 
					extern const GLchar fragment_src_RGBA[];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,9 @@ struct wlr_output_impl {
 | 
				
			||||||
			struct wlr_output_mode *mode);
 | 
								struct wlr_output_mode *mode);
 | 
				
			||||||
	void (*transform)(struct wlr_output_state *state,
 | 
						void (*transform)(struct wlr_output_state *state,
 | 
				
			||||||
			enum wl_output_transform transform);
 | 
								enum wl_output_transform transform);
 | 
				
			||||||
 | 
						bool (*set_cursor)(struct wlr_output_state *state,
 | 
				
			||||||
 | 
							const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height);
 | 
				
			||||||
 | 
						bool (*move_cursor)(struct wlr_output_state *state, int x, int y);
 | 
				
			||||||
	void (*destroy)(struct wlr_output_state *state);
 | 
						void (*destroy)(struct wlr_output_state *state);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,4 +21,47 @@ struct wlr_output *wlr_output_create(struct wlr_output_impl *impl,
 | 
				
			||||||
		struct wlr_output_state *state);
 | 
							struct wlr_output_state *state);
 | 
				
			||||||
void wlr_output_free(struct wlr_output *output);
 | 
					void wlr_output_free(struct wlr_output *output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard_impl {
 | 
				
			||||||
 | 
						void (*destroy)(struct wlr_keyboard_state *state);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard *wlr_keyboard_create(struct wlr_keyboard_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_keyboard_state *state);
 | 
				
			||||||
 | 
					void wlr_keyboard_destroy(struct wlr_keyboard *keyboard);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer_impl {
 | 
				
			||||||
 | 
						void (*destroy)(struct wlr_pointer_state *state);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer *wlr_pointer_create(struct wlr_pointer_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_pointer_state *state);
 | 
				
			||||||
 | 
					void wlr_pointer_destroy(struct wlr_pointer *pointer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch_impl {
 | 
				
			||||||
 | 
						void (*destroy)(struct wlr_touch_state *state);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch *wlr_touch_create(struct wlr_touch_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_touch_state *state);
 | 
				
			||||||
 | 
					void wlr_touch_destroy(struct wlr_touch *touch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool_impl {
 | 
				
			||||||
 | 
						void (*destroy)(struct wlr_tablet_tool_state *tool);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool *wlr_tablet_tool_create(struct wlr_tablet_tool_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_tablet_tool_state *state);
 | 
				
			||||||
 | 
					void wlr_tablet_tool_destroy(struct wlr_tablet_tool *tool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device_impl {
 | 
				
			||||||
 | 
						void (*destroy)(struct wlr_input_device_state *state);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device *wlr_input_device_create(
 | 
				
			||||||
 | 
							enum wlr_input_device_type type,
 | 
				
			||||||
 | 
							struct wlr_input_device_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_input_device_state *state,
 | 
				
			||||||
 | 
							const char *name, int vendor, int product);
 | 
				
			||||||
 | 
					void wlr_input_device_destroy(struct wlr_input_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,14 +12,10 @@ struct wlr_backend {
 | 
				
			||||||
	struct wlr_backend_state *state;
 | 
						struct wlr_backend_state *state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
 | 
							struct wl_signal input_add;
 | 
				
			||||||
 | 
							struct wl_signal input_remove;
 | 
				
			||||||
		struct wl_signal output_add;
 | 
							struct wl_signal output_add;
 | 
				
			||||||
		struct wl_signal output_remove;
 | 
							struct wl_signal output_remove;
 | 
				
			||||||
		struct wl_signal keyboard_add;
 | 
					 | 
				
			||||||
		struct wl_signal keyboard_remove;
 | 
					 | 
				
			||||||
		struct wl_signal pointer_add;
 | 
					 | 
				
			||||||
		struct wl_signal pointer_remove;
 | 
					 | 
				
			||||||
		struct wl_signal touch_add;
 | 
					 | 
				
			||||||
		struct wl_signal touch_remove;
 | 
					 | 
				
			||||||
	} events;
 | 
						} events;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								include/wlr/backend/libinput.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/wlr/backend/libinput.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					#ifndef WLR_BACKEND_LIBINPUT_H
 | 
				
			||||||
 | 
					#define WLR_BACKEND_LIBINPUT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <libinput.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wlr/session.h>
 | 
				
			||||||
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
 | 
					#include <wlr/backend/udev.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
 | 
				
			||||||
 | 
							struct wlr_session *session, struct wlr_udev *udev);
 | 
				
			||||||
 | 
					struct libinput_device *wlr_libinput_get_device_handle(struct wlr_input_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										10
									
								
								include/wlr/backend/multi.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								include/wlr/backend/multi.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					#ifndef _WLR_BACKEND_MULTI_H
 | 
				
			||||||
 | 
					#define _WLR_BACKEND_MULTI_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <wlr/backend.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend *wlr_multi_backend_create();
 | 
				
			||||||
 | 
					void wlr_multi_backend_add(struct wlr_backend *multi,
 | 
				
			||||||
 | 
							struct wlr_backend *backend);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,16 @@ struct wlr_surface *wlr_render_surface_init(struct wlr_renderer *r);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool wlr_render_with_matrix(struct wlr_renderer *r,
 | 
					bool wlr_render_with_matrix(struct wlr_renderer *r,
 | 
				
			||||||
		struct wlr_surface *surface, const float (*matrix)[16]);
 | 
							struct wlr_surface *surface, const float (*matrix)[16]);
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Renders a solid quad in the specified color.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void wlr_render_colored_quad(struct wlr_renderer *r,
 | 
				
			||||||
 | 
							const float (*color)[4], const float (*matrix)[16]);
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Renders a solid ellipse in the specified color.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void wlr_render_colored_ellipse(struct wlr_renderer *r,
 | 
				
			||||||
 | 
							const float (*color)[4], const float (*matrix)[16]);
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Destroys this wlr_renderer. Surfaces must be destroyed separately.
 | 
					 * Destroys this wlr_renderer. Surfaces must be destroyed separately.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,10 @@ struct wlr_renderer_impl {
 | 
				
			||||||
	struct wlr_surface *(*surface_init)(struct wlr_renderer_state *state);
 | 
						struct wlr_surface *(*surface_init)(struct wlr_renderer_state *state);
 | 
				
			||||||
	bool (*render_with_matrix)(struct wlr_renderer_state *state,
 | 
						bool (*render_with_matrix)(struct wlr_renderer_state *state,
 | 
				
			||||||
		struct wlr_surface *surface, const float (*matrix)[16]);
 | 
							struct wlr_surface *surface, const float (*matrix)[16]);
 | 
				
			||||||
 | 
						void (*render_quad)(struct wlr_renderer_state *state,
 | 
				
			||||||
 | 
								const float (*color)[4], const float (*matrix)[16]);
 | 
				
			||||||
 | 
						void (*render_ellipse)(struct wlr_renderer_state *state,
 | 
				
			||||||
 | 
								const float (*color)[4], const float (*matrix)[16]);
 | 
				
			||||||
	void (*destroy)(struct wlr_renderer_state *state);
 | 
						void (*destroy)(struct wlr_renderer_state *state);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,8 +46,245 @@ bool wlr_output_set_mode(struct wlr_output *output,
 | 
				
			||||||
		struct wlr_output_mode *mode);
 | 
							struct wlr_output_mode *mode);
 | 
				
			||||||
void wlr_output_transform(struct wlr_output *output,
 | 
					void wlr_output_transform(struct wlr_output *output,
 | 
				
			||||||
		enum wl_output_transform transform);
 | 
							enum wl_output_transform transform);
 | 
				
			||||||
 | 
					bool wlr_output_set_cursor(struct wlr_output *output,
 | 
				
			||||||
 | 
							const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height);
 | 
				
			||||||
 | 
					bool wlr_output_move_cursor(struct wlr_output *output, int x, int y);
 | 
				
			||||||
void wlr_output_destroy(struct wlr_output *output);
 | 
					void wlr_output_destroy(struct wlr_output *output);
 | 
				
			||||||
void wlr_output_effective_resolution(struct wlr_output *output,
 | 
					void wlr_output_effective_resolution(struct wlr_output *output,
 | 
				
			||||||
		int *width, int *height);
 | 
							int *width, int *height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard_state;
 | 
				
			||||||
 | 
					struct wlr_keyboard_impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard {
 | 
				
			||||||
 | 
						struct wlr_keyboard_state *state;
 | 
				
			||||||
 | 
						struct wlr_keyboard_impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct wl_signal key;
 | 
				
			||||||
 | 
						} events;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_key_state {
 | 
				
			||||||
 | 
						WLR_KEY_RELEASED,
 | 
				
			||||||
 | 
						WLR_KEY_PRESSED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard_key {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						uint32_t keycode;
 | 
				
			||||||
 | 
						enum wlr_key_state state;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer_state;
 | 
				
			||||||
 | 
					struct wlr_pointer_impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer {
 | 
				
			||||||
 | 
						struct wlr_pointer_state *state;
 | 
				
			||||||
 | 
						struct wlr_pointer_impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct wl_signal motion;
 | 
				
			||||||
 | 
							struct wl_signal motion_absolute;
 | 
				
			||||||
 | 
							struct wl_signal button;
 | 
				
			||||||
 | 
							struct wl_signal axis;
 | 
				
			||||||
 | 
						} events;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer_motion {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						double delta_x, delta_y;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer_motion_absolute {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						double x_mm, y_mm;
 | 
				
			||||||
 | 
						double width_mm, height_mm;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_button_state {
 | 
				
			||||||
 | 
						WLR_BUTTON_RELEASED,
 | 
				
			||||||
 | 
						WLR_BUTTON_PRESSED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer_button {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						uint32_t button;
 | 
				
			||||||
 | 
						enum wlr_button_state state;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_axis_source {
 | 
				
			||||||
 | 
						WLR_AXIS_SOURCE_WHEEL,
 | 
				
			||||||
 | 
						WLR_AXIS_SOURCE_FINGER,
 | 
				
			||||||
 | 
						WLR_AXIS_SOURCE_CONTINUOUS,
 | 
				
			||||||
 | 
						WLR_AXIS_SOURCE_WHEEL_TILT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_axis_orientation {
 | 
				
			||||||
 | 
						WLR_AXIS_ORIENTATION_VERTICAL,
 | 
				
			||||||
 | 
						WLR_AXIS_ORIENTATION_HORIZONTAL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer_axis {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						enum wlr_axis_source source;
 | 
				
			||||||
 | 
						enum wlr_axis_orientation orientation;
 | 
				
			||||||
 | 
						double delta;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch_state;
 | 
				
			||||||
 | 
					struct wlr_touch_impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch {
 | 
				
			||||||
 | 
						struct wlr_touch_state *state;
 | 
				
			||||||
 | 
						struct wlr_touch_impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct wl_signal down;
 | 
				
			||||||
 | 
							struct wl_signal up;
 | 
				
			||||||
 | 
							struct wl_signal motion;
 | 
				
			||||||
 | 
							struct wl_signal cancel;
 | 
				
			||||||
 | 
						} events;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch_down {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						int32_t slot;
 | 
				
			||||||
 | 
						double x_mm, y_mm;
 | 
				
			||||||
 | 
						double width_mm, height_mm;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch_up {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						int32_t slot;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch_motion {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						int32_t slot;
 | 
				
			||||||
 | 
						double x_mm, y_mm;
 | 
				
			||||||
 | 
						double width_mm, height_mm;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch_cancel {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						int32_t slot;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool_impl;
 | 
				
			||||||
 | 
					struct wlr_tablet_tool_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool {
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_impl *impl;
 | 
				
			||||||
 | 
						struct wlr_tablet_tool_state *state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct wl_signal axis;
 | 
				
			||||||
 | 
							struct wl_signal proximity;
 | 
				
			||||||
 | 
							struct wl_signal tip;
 | 
				
			||||||
 | 
							struct wl_signal button;
 | 
				
			||||||
 | 
						} events;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_tablet_tool_axes {
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_X = 1,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_Y = 2,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_DISTANCE = 4,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_PRESSURE = 8,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_TILT_X = 16,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_TILT_Y = 32,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_ROTATION = 64,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_SLIDER = 128,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_AXIS_WHEEL = 256,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool_axis {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						uint32_t updated_axes;
 | 
				
			||||||
 | 
						double x_mm, y_mm;
 | 
				
			||||||
 | 
						double width_mm, height_mm;
 | 
				
			||||||
 | 
						double pressure;
 | 
				
			||||||
 | 
						double distance;
 | 
				
			||||||
 | 
						double tilt_x, tilt_y;
 | 
				
			||||||
 | 
						double rotation;
 | 
				
			||||||
 | 
						double slider;
 | 
				
			||||||
 | 
						double wheel_delta;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_tablet_tool_proximity_state {
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_PROXIMITY_OUT,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_PROXIMITY_IN,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool_proximity {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						double x, y;
 | 
				
			||||||
 | 
						double width_mm, height_mm;
 | 
				
			||||||
 | 
						enum wlr_tablet_tool_proximity_state state;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_tablet_tool_tip_state {
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_TIP_UP,
 | 
				
			||||||
 | 
						WLR_TABLET_TOOL_TIP_DOWN,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool_tip {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						double x, y;
 | 
				
			||||||
 | 
						double width_mm, height_mm;
 | 
				
			||||||
 | 
						enum wlr_tablet_tool_tip_state state;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool_button {
 | 
				
			||||||
 | 
						uint32_t time_sec;
 | 
				
			||||||
 | 
						uint64_t time_usec;
 | 
				
			||||||
 | 
						uint32_t button;
 | 
				
			||||||
 | 
						enum wlr_button_state state;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: tablet pad
 | 
				
			||||||
 | 
					// TODO: switch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_input_device_type {
 | 
				
			||||||
 | 
						WLR_INPUT_DEVICE_KEYBOARD,
 | 
				
			||||||
 | 
						WLR_INPUT_DEVICE_POINTER,
 | 
				
			||||||
 | 
						WLR_INPUT_DEVICE_TOUCH,
 | 
				
			||||||
 | 
						WLR_INPUT_DEVICE_TABLET_TOOL,
 | 
				
			||||||
 | 
						WLR_INPUT_DEVICE_TABLET_PAD,
 | 
				
			||||||
 | 
						WLR_INPUT_DEVICE_GESTURE,
 | 
				
			||||||
 | 
						WLR_INPUT_DEVICE_SWITCH,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device_state;
 | 
				
			||||||
 | 
					struct wlr_input_device_impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device {
 | 
				
			||||||
 | 
						struct wlr_input_device_state *state;
 | 
				
			||||||
 | 
						struct wlr_input_device_impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum wlr_input_device_type type;
 | 
				
			||||||
 | 
						int vendor, product;
 | 
				
			||||||
 | 
						char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							void *_device;
 | 
				
			||||||
 | 
							struct wlr_keyboard *keyboard;
 | 
				
			||||||
 | 
							struct wlr_pointer *pointer;
 | 
				
			||||||
 | 
							struct wlr_touch *touch;
 | 
				
			||||||
 | 
							struct wlr_tablet_tool *tablet_tool;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,8 @@
 | 
				
			||||||
static struct {
 | 
					static struct {
 | 
				
			||||||
	bool initialized;
 | 
						bool initialized;
 | 
				
			||||||
	GLuint rgb, rgba;
 | 
						GLuint rgb, rgba;
 | 
				
			||||||
 | 
						GLuint quad;
 | 
				
			||||||
 | 
						GLuint ellipse;
 | 
				
			||||||
} shaders;
 | 
					} shaders;
 | 
				
			||||||
static GLuint vao, vbo, ebo;
 | 
					static GLuint vao, vbo, ebo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +30,9 @@ static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) {
 | 
				
			||||||
		GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen));
 | 
							GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen));
 | 
				
			||||||
		GLchar msg[loglen];
 | 
							GLchar msg[loglen];
 | 
				
			||||||
		GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg));
 | 
							GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg));
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Shader compilation failed");
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "%s", msg);
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
| 
						 | 
					@ -60,6 +65,12 @@ static void init_default_shaders() {
 | 
				
			||||||
	if (!compile_program(vertex_src, fragment_src_RGBA, &shaders.rgba)) {
 | 
						if (!compile_program(vertex_src, fragment_src_RGBA, &shaders.rgba)) {
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) {
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!compile_program(quad_vertex_src, ellipse_fragment_src, &shaders.ellipse)) {
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
error:
 | 
					error:
 | 
				
			||||||
	wlr_log(L_ERROR, "Failed to set up default shaders!");
 | 
						wlr_log(L_ERROR, "Failed to set up default shaders!");
 | 
				
			||||||
| 
						 | 
					@ -141,6 +152,28 @@ static bool wlr_gles3_render_surface(struct wlr_renderer_state *state,
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void wlr_gles3_render_quad(struct wlr_renderer_state *state,
 | 
				
			||||||
 | 
							const float (*color)[4], const float (*matrix)[16]) {
 | 
				
			||||||
 | 
						GL_CALL(glUseProgram(shaders.quad));
 | 
				
			||||||
 | 
						GL_CALL(glBindVertexArray(vao));
 | 
				
			||||||
 | 
						GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo));
 | 
				
			||||||
 | 
						GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo));
 | 
				
			||||||
 | 
						GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix));
 | 
				
			||||||
 | 
						GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3]));
 | 
				
			||||||
 | 
						GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void wlr_gles3_render_ellipse(struct wlr_renderer_state *state,
 | 
				
			||||||
 | 
							const float (*color)[4], const float (*matrix)[16]) {
 | 
				
			||||||
 | 
						GL_CALL(glUseProgram(shaders.ellipse));
 | 
				
			||||||
 | 
						GL_CALL(glBindVertexArray(vao));
 | 
				
			||||||
 | 
						GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo));
 | 
				
			||||||
 | 
						GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo));
 | 
				
			||||||
 | 
						GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix));
 | 
				
			||||||
 | 
						GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3]));
 | 
				
			||||||
 | 
						GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void wlr_gles3_destroy(struct wlr_renderer_state *state) {
 | 
					static void wlr_gles3_destroy(struct wlr_renderer_state *state) {
 | 
				
			||||||
	// no-op
 | 
						// no-op
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -150,6 +183,8 @@ static struct wlr_renderer_impl wlr_renderer_impl = {
 | 
				
			||||||
	.end = wlr_gles3_end,
 | 
						.end = wlr_gles3_end,
 | 
				
			||||||
	.surface_init = wlr_gles3_surface_init,
 | 
						.surface_init = wlr_gles3_surface_init,
 | 
				
			||||||
	.render_with_matrix = wlr_gles3_render_surface,
 | 
						.render_with_matrix = wlr_gles3_render_surface,
 | 
				
			||||||
 | 
						.render_quad = wlr_gles3_render_quad,
 | 
				
			||||||
 | 
						.render_ellipse = wlr_gles3_render_ellipse,
 | 
				
			||||||
	.destroy = wlr_gles3_destroy
 | 
						.destroy = wlr_gles3_destroy
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,28 +1,63 @@
 | 
				
			||||||
#include "render/gles3.h"
 | 
					#include "render/gles3.h"
 | 
				
			||||||
#include <GLES3/gl3.h>
 | 
					#include <GLES3/gl3.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Colored quads
 | 
				
			||||||
 | 
					const GLchar quad_vertex_src[] =
 | 
				
			||||||
 | 
					"uniform mat4 proj;"
 | 
				
			||||||
 | 
					"uniform vec4 color;"
 | 
				
			||||||
 | 
					"attribute vec2 pos;"
 | 
				
			||||||
 | 
					"attribute vec2 texcoord;"
 | 
				
			||||||
 | 
					"varying vec4 v_color;"
 | 
				
			||||||
 | 
					"varying vec2 v_texcoord;"
 | 
				
			||||||
 | 
					"void main() {"
 | 
				
			||||||
 | 
					"  gl_Position = proj * vec4(pos, 0.0, 1.0);"
 | 
				
			||||||
 | 
					"  v_color = color;"
 | 
				
			||||||
 | 
					"  v_texcoord = texcoord;"
 | 
				
			||||||
 | 
					"}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GLchar quad_fragment_src[] =
 | 
				
			||||||
 | 
					"precision mediump float;"
 | 
				
			||||||
 | 
					"varying vec4 v_color;"
 | 
				
			||||||
 | 
					"varying vec2 v_texcoord;"
 | 
				
			||||||
 | 
					"void main() {"
 | 
				
			||||||
 | 
					"  gl_FragColor = v_color;"
 | 
				
			||||||
 | 
					"}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Colored ellipses (TODO)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GLchar ellipse_fragment_src[] =
 | 
				
			||||||
 | 
					"precision mediump float;"
 | 
				
			||||||
 | 
					"varying vec4 v_color;"
 | 
				
			||||||
 | 
					"varying vec2 v_texcoord;"
 | 
				
			||||||
 | 
					"void main() {"
 | 
				
			||||||
 | 
					"  float l = length(v_texcoord - vec2(0.5, 0.5));"
 | 
				
			||||||
 | 
					"  if (l > 0.5) discard;"
 | 
				
			||||||
 | 
					"  gl_FragColor = v_color;"
 | 
				
			||||||
 | 
					"}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Textured quads
 | 
				
			||||||
const GLchar vertex_src[] =
 | 
					const GLchar vertex_src[] =
 | 
				
			||||||
"uniform mat4 proj;\n"
 | 
					"uniform mat4 proj;"
 | 
				
			||||||
"attribute vec2 pos;\n"
 | 
					"attribute vec2 pos;"
 | 
				
			||||||
"attribute vec2 texcoord;\n"
 | 
					"attribute vec2 texcoord;"
 | 
				
			||||||
"varying vec2 v_texcoord;\n"
 | 
					"varying vec2 v_texcoord;"
 | 
				
			||||||
"void main() {\n"
 | 
					"void main() {"
 | 
				
			||||||
"	gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
 | 
					"	gl_Position = proj * vec4(pos, 0.0, 1.0);"
 | 
				
			||||||
"	v_texcoord = texcoord;\n"
 | 
					"	v_texcoord = texcoord;"
 | 
				
			||||||
"}\n";
 | 
					"}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GLchar fragment_src_RGB[] =
 | 
					const GLchar fragment_src_RGB[] =
 | 
				
			||||||
"precision mediump float;\n"
 | 
					"precision mediump float;"
 | 
				
			||||||
"varying vec2 v_texcoord;\n"
 | 
					"varying vec2 v_texcoord;"
 | 
				
			||||||
"uniform sampler2D tex;\n"
 | 
					"uniform sampler2D tex;"
 | 
				
			||||||
"void main() {\n"
 | 
					"void main() {"
 | 
				
			||||||
"	gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);\n"
 | 
					"	gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);"
 | 
				
			||||||
"}\n";
 | 
					"}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GLchar fragment_src_RGBA[] =
 | 
					const GLchar fragment_src_RGBA[] =
 | 
				
			||||||
"precision mediump float;\n"
 | 
					"precision mediump float;"
 | 
				
			||||||
"varying vec2 v_texcoord;\n"
 | 
					"varying vec2 v_texcoord;"
 | 
				
			||||||
"uniform sampler2D tex;\n"
 | 
					"uniform sampler2D tex;"
 | 
				
			||||||
"void main() {\n"
 | 
					"void main() {"
 | 
				
			||||||
"	gl_FragColor = texture2D(tex, v_texcoord);\n"
 | 
					"	gl_FragColor = texture2D(tex, v_texcoord);"
 | 
				
			||||||
"}\n";
 | 
					"}";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,3 +31,13 @@ bool wlr_render_with_matrix(struct wlr_renderer *r,
 | 
				
			||||||
		struct wlr_surface *surface, const float (*matrix)[16]) {
 | 
							struct wlr_surface *surface, const float (*matrix)[16]) {
 | 
				
			||||||
	return r->impl->render_with_matrix(r->state, surface, matrix);
 | 
						return r->impl->render_with_matrix(r->state, surface, matrix);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_render_colored_quad(struct wlr_renderer *r,
 | 
				
			||||||
 | 
							const float (*color)[4], const float (*matrix)[16]) {
 | 
				
			||||||
 | 
						r->impl->render_quad(r->state, color, matrix);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_render_colored_ellipse(struct wlr_renderer *r,
 | 
				
			||||||
 | 
							const float (*color)[4], const float (*matrix)[16]) {
 | 
				
			||||||
 | 
						r->impl->render_ellipse(r->state, color, matrix);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,6 @@ struct logind_session {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int logind_take_device(struct wlr_session *restrict base,
 | 
					static int logind_take_device(struct wlr_session *restrict base,
 | 
				
			||||||
		const char *restrict path) {
 | 
							const char *restrict path) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct logind_session *session = wl_container_of(base, session, base);
 | 
						struct logind_session *session = wl_container_of(base, session, base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,11 @@ include_directories(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_library(wlr-types
 | 
					add_library(wlr-types
 | 
				
			||||||
    wlr_output.c
 | 
					    wlr_output.c
 | 
				
			||||||
 | 
					    wlr_input_device.c
 | 
				
			||||||
 | 
					    wlr_keyboard.c
 | 
				
			||||||
 | 
					    wlr_pointer.c
 | 
				
			||||||
 | 
					    wlr_touch.c
 | 
				
			||||||
 | 
					    wlr_tablet_tool.c
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(wlr-types
 | 
					target_link_libraries(wlr-types
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										43
									
								
								types/wlr_input_device.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								types/wlr_input_device.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "common/log.h"
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_input_device *wlr_input_device_create(
 | 
				
			||||||
 | 
							enum wlr_input_device_type type,
 | 
				
			||||||
 | 
							struct wlr_input_device_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_input_device_state *state,
 | 
				
			||||||
 | 
							const char *name, int vendor, int product) {
 | 
				
			||||||
 | 
						struct wlr_input_device *dev = calloc(1, sizeof(struct wlr_input_device));
 | 
				
			||||||
 | 
						dev->type = type;
 | 
				
			||||||
 | 
						dev->impl = impl;
 | 
				
			||||||
 | 
						dev->state = state;
 | 
				
			||||||
 | 
						dev->name = strdup(name);
 | 
				
			||||||
 | 
						dev->vendor = vendor;
 | 
				
			||||||
 | 
						dev->product = product;
 | 
				
			||||||
 | 
						return dev;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_input_device_destroy(struct wlr_input_device *dev) {
 | 
				
			||||||
 | 
						if (!dev) return;
 | 
				
			||||||
 | 
						if (dev->impl && dev->impl->destroy && dev->state) {
 | 
				
			||||||
 | 
							dev->impl->destroy(dev->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (dev->_device) {
 | 
				
			||||||
 | 
							switch (dev->type) {
 | 
				
			||||||
 | 
							case WLR_INPUT_DEVICE_KEYBOARD:
 | 
				
			||||||
 | 
								wlr_keyboard_destroy(dev->keyboard);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								wlr_log(L_DEBUG, "Warning: leaking memory %p %p %d",
 | 
				
			||||||
 | 
										dev->_device, dev, dev->type);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(dev->name);
 | 
				
			||||||
 | 
						free(dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								types/wlr_keyboard.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								types/wlr_keyboard.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_keyboard *wlr_keyboard_create(struct wlr_keyboard_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_keyboard_state *state) {
 | 
				
			||||||
 | 
						struct wlr_keyboard *kb = calloc(1, sizeof(struct wlr_keyboard));
 | 
				
			||||||
 | 
						kb->impl = impl;
 | 
				
			||||||
 | 
						kb->state = state;
 | 
				
			||||||
 | 
						wl_signal_init(&kb->events.key);
 | 
				
			||||||
 | 
						return kb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_keyboard_destroy(struct wlr_keyboard *kb) {
 | 
				
			||||||
 | 
						if (!kb) return;
 | 
				
			||||||
 | 
						if (kb->impl) {
 | 
				
			||||||
 | 
							kb->impl->destroy(kb->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(kb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -91,6 +91,15 @@ void wlr_output_transform(struct wlr_output *output,
 | 
				
			||||||
	output->impl->transform(output->state, transform);
 | 
						output->impl->transform(output->state, transform);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool wlr_output_set_cursor(struct wlr_output *output,
 | 
				
			||||||
 | 
							const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) {
 | 
				
			||||||
 | 
						return output->impl->set_cursor(output->state, buf, stride, width, height);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool wlr_output_move_cursor(struct wlr_output *output, int x, int y) {
 | 
				
			||||||
 | 
						return output->impl->move_cursor(output->state, x, y);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_output_destroy(struct wlr_output *output) {
 | 
					void wlr_output_destroy(struct wlr_output *output) {
 | 
				
			||||||
	if (!output) return;
 | 
						if (!output) return;
 | 
				
			||||||
	output->impl->destroy(output->state);
 | 
						output->impl->destroy(output->state);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								types/wlr_pointer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								types/wlr_pointer.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_pointer *wlr_pointer_create(struct wlr_pointer_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_pointer_state *state) {
 | 
				
			||||||
 | 
						struct wlr_pointer *pointer = calloc(1, sizeof(struct wlr_pointer));
 | 
				
			||||||
 | 
						pointer->impl = impl;
 | 
				
			||||||
 | 
						pointer->state = state;
 | 
				
			||||||
 | 
						wl_signal_init(&pointer->events.motion);
 | 
				
			||||||
 | 
						wl_signal_init(&pointer->events.motion_absolute);
 | 
				
			||||||
 | 
						wl_signal_init(&pointer->events.button);
 | 
				
			||||||
 | 
						wl_signal_init(&pointer->events.axis);
 | 
				
			||||||
 | 
						return pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_pointer_destroy(struct wlr_pointer *pointer) {
 | 
				
			||||||
 | 
						if (!pointer) return;
 | 
				
			||||||
 | 
						if (pointer->impl) {
 | 
				
			||||||
 | 
							pointer->impl->destroy(pointer->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(pointer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								types/wlr_tablet_tool.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								types/wlr_tablet_tool.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_tablet_tool *wlr_tablet_tool_create(struct wlr_tablet_tool_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_tablet_tool_state *state) {
 | 
				
			||||||
 | 
						struct wlr_tablet_tool *tool = calloc(1, sizeof(struct wlr_tablet_tool));
 | 
				
			||||||
 | 
						tool->impl = impl;
 | 
				
			||||||
 | 
						tool->state = state;
 | 
				
			||||||
 | 
						wl_signal_init(&tool->events.axis);
 | 
				
			||||||
 | 
						wl_signal_init(&tool->events.proximity);
 | 
				
			||||||
 | 
						wl_signal_init(&tool->events.tip);
 | 
				
			||||||
 | 
						wl_signal_init(&tool->events.button);
 | 
				
			||||||
 | 
						return tool;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_tablet_tool_destroy(struct wlr_tablet_tool *tool) {
 | 
				
			||||||
 | 
						if (!tool) return;
 | 
				
			||||||
 | 
						if (tool->impl) {
 | 
				
			||||||
 | 
							tool->impl->destroy(tool->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(tool);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								types/wlr_touch.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								types/wlr_touch.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					#include <wlr/types.h>
 | 
				
			||||||
 | 
					#include <wlr/common/list.h>
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_touch *wlr_touch_create(struct wlr_touch_impl *impl,
 | 
				
			||||||
 | 
							struct wlr_touch_state *state) {
 | 
				
			||||||
 | 
						struct wlr_touch *touch = calloc(1, sizeof(struct wlr_touch));
 | 
				
			||||||
 | 
						touch->impl = impl;
 | 
				
			||||||
 | 
						touch->state = state;
 | 
				
			||||||
 | 
						wl_signal_init(&touch->events.down);
 | 
				
			||||||
 | 
						wl_signal_init(&touch->events.up);
 | 
				
			||||||
 | 
						wl_signal_init(&touch->events.motion);
 | 
				
			||||||
 | 
						wl_signal_init(&touch->events.cancel);
 | 
				
			||||||
 | 
						return touch;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_touch_destroy(struct wlr_touch *touch) {
 | 
				
			||||||
 | 
						if (!touch) return;
 | 
				
			||||||
 | 
						if (touch->impl) {
 | 
				
			||||||
 | 
							touch->impl->destroy(touch->state);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(touch);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue