Initial commit: Added current work
This commit is contained in:
commit
3fa9c8d193
10 changed files with 637 additions and 0 deletions
25
.clang-format
Normal file
25
.clang-format
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
BasedOnStyle: Microsoft
|
||||||
|
|
||||||
|
UseTab: ForIndentation
|
||||||
|
TabWidth: 4
|
||||||
|
BreakBeforeBraces: Linux
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||||
|
PointerAlignment: Left
|
||||||
|
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
|
||||||
|
|
||||||
|
AlignArrayOfStructures: Right
|
||||||
|
AlignArrayOfStructures: Right
|
||||||
|
AlignConsecutiveAssignments: Consecutive
|
||||||
|
AlignConsecutiveBitFields: Consecutive
|
||||||
|
AlignConsecutiveDeclarations: Consecutive
|
||||||
|
AlignConsecutiveMacros: Consecutive
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: AlignAfterOperator
|
||||||
|
AlignTrailingComments: true
|
||||||
|
|
||||||
|
ColumnLimit: 80
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
protocol/*.c
|
||||||
|
protocol/*.h
|
||||||
|
protocol/*.xml
|
||||||
|
*~
|
||||||
|
miix-wlr
|
162
accel_monitor.c
Normal file
162
accel_monitor.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
#include "accel_monitor.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static char* sensor_get_axis_path(char const* const base, char axis)
|
||||||
|
{
|
||||||
|
// TODO: Be smarter about the buffer size
|
||||||
|
char buffer[128];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%s/in_accel_%c_raw", base, axis);
|
||||||
|
return strdup(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int monitor_thread(void* data)
|
||||||
|
{
|
||||||
|
struct accel_monitor* monitor = data;
|
||||||
|
|
||||||
|
while (!monitor->monitoring_thread_is_ready)
|
||||||
|
;
|
||||||
|
|
||||||
|
char* x_axis_path = sensor_get_axis_path(monitor->sysfs_device_path, 'x');
|
||||||
|
FILE* x_axis_fp = fopen(x_axis_path, "r");
|
||||||
|
free(x_axis_path);
|
||||||
|
|
||||||
|
char* y_axis_path = sensor_get_axis_path(monitor->sysfs_device_path, 'y');
|
||||||
|
FILE* y_axis_fp = fopen(y_axis_path, "r");
|
||||||
|
free(y_axis_path);
|
||||||
|
|
||||||
|
char* z_axis_path = sensor_get_axis_path(monitor->sysfs_device_path, 'z');
|
||||||
|
FILE* z_axis_fp = fopen(z_axis_path, "r");
|
||||||
|
free(z_axis_path);
|
||||||
|
|
||||||
|
while (!monitor->monitoring_thread_should_exit) {
|
||||||
|
fseek(x_axis_fp, 0, SEEK_SET);
|
||||||
|
fseek(y_axis_fp, 0, SEEK_SET);
|
||||||
|
fseek(z_axis_fp, 0, SEEK_SET);
|
||||||
|
|
||||||
|
int16_t x_axis;
|
||||||
|
int16_t y_axis;
|
||||||
|
int16_t z_axis;
|
||||||
|
|
||||||
|
fscanf(x_axis_fp, "%hd\n", &x_axis);
|
||||||
|
fscanf(y_axis_fp, "%hd\n", &y_axis);
|
||||||
|
fscanf(z_axis_fp, "%hd\n", &z_axis);
|
||||||
|
|
||||||
|
if (mtx_lock(&monitor->current_data_lock) != thrd_success) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Can't lock data from data monitoring thread. Something is "
|
||||||
|
"going wrong. Giving up on monitoring sensor data.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->current_data.x = x_axis;
|
||||||
|
monitor->current_data.y = y_axis;
|
||||||
|
monitor->current_data.z = z_axis;
|
||||||
|
|
||||||
|
if (mtx_unlock(&monitor->current_data_lock) != thrd_success) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Can't unlock data from data monitoring thread. Something "
|
||||||
|
"is going wrong. Giving up on monitoring sensor data.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->data_is_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(x_axis_fp);
|
||||||
|
fclose(y_axis_fp);
|
||||||
|
fclose(z_axis_fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct accel_monitor* accel_start_monitor(
|
||||||
|
char const* const sysfs_device_path)
|
||||||
|
{
|
||||||
|
mtx_t current_data_lock;
|
||||||
|
if (mtx_init(¤t_data_lock, mtx_plain) != thrd_success) return 0;
|
||||||
|
|
||||||
|
if (mtx_lock(¤t_data_lock) != thrd_success) return 0;
|
||||||
|
|
||||||
|
struct accel_monitor* monitor = calloc(1, sizeof(struct accel_monitor));
|
||||||
|
|
||||||
|
monitor->monitoring_thread_is_ready = false;
|
||||||
|
monitor->data_is_ready = false;
|
||||||
|
|
||||||
|
thrd_t monitoring_thread;
|
||||||
|
if (thrd_create(&monitoring_thread, &monitor_thread, monitor) !=
|
||||||
|
thrd_success) {
|
||||||
|
free(monitor);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->sysfs_device_path = sysfs_device_path;
|
||||||
|
monitor->monitoring_thread = monitoring_thread;
|
||||||
|
monitor->current_data_lock = current_data_lock;
|
||||||
|
|
||||||
|
monitor->current_data.x = 0;
|
||||||
|
monitor->current_data.y = 0;
|
||||||
|
monitor->current_data.z = 0;
|
||||||
|
|
||||||
|
monitor->monitoring_thread_should_exit = false;
|
||||||
|
|
||||||
|
if (mtx_unlock(&monitor->current_data_lock) != thrd_success)
|
||||||
|
fprintf(stderr,
|
||||||
|
"Unable to unlock the data after initialisation. We are in UB "
|
||||||
|
"territory. Something must've went very wrong\n");
|
||||||
|
|
||||||
|
monitor->monitoring_thread_is_ready = true;
|
||||||
|
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool axis_is_near_0(int16_t axis)
|
||||||
|
{
|
||||||
|
return (axis > -500) && (axis < 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool axis_is_mostly_positive(int16_t axis)
|
||||||
|
{
|
||||||
|
return axis >= 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool axis_is_mostly_negative(int16_t axis)
|
||||||
|
{
|
||||||
|
return axis <= -500;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum accel_rotation accel_get_current_rotation(
|
||||||
|
struct accel_monitor* monitor)
|
||||||
|
{
|
||||||
|
if (mtx_lock(&monitor->current_data_lock) != thrd_success)
|
||||||
|
return ACCEL_ROTATION_NO_CHANGE;
|
||||||
|
struct accel_data data = monitor->current_data;
|
||||||
|
if (mtx_unlock(&monitor->current_data_lock) != thrd_success)
|
||||||
|
fprintf(stderr, "Can't unlock data, this is going to cause issues.\n");
|
||||||
|
|
||||||
|
if (axis_is_near_0(data.x)) {
|
||||||
|
if (axis_is_mostly_positive(data.y)) return ACCEL_ROTATION_0DEG;
|
||||||
|
if (axis_is_mostly_negative(data.y)) return ACCEL_ROTATION_180DEG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (axis_is_mostly_positive(data.x)) return ACCEL_ROTATION_90DEG;
|
||||||
|
|
||||||
|
if (axis_is_mostly_negative(data.x)) return ACCEL_ROTATION_270DEG;
|
||||||
|
|
||||||
|
return ACCEL_ROTATION_NO_CHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void accel_stop_monitor(struct accel_monitor* monitor)
|
||||||
|
{
|
||||||
|
monitor->monitoring_thread_should_exit = true;
|
||||||
|
|
||||||
|
if (thrd_join(monitor->monitoring_thread, NULL) != thrd_success)
|
||||||
|
fprintf(stderr,
|
||||||
|
"Can't join monitoring thread. The program may not exit "
|
||||||
|
"cleanly.\n");
|
||||||
|
|
||||||
|
mtx_destroy(&monitor->current_data_lock);
|
||||||
|
free(monitor);
|
||||||
|
}
|
36
accel_monitor.h
Normal file
36
accel_monitor.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <threads.h>
|
||||||
|
|
||||||
|
struct accel_data {
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
|
int16_t z;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum accel_rotation : uint8_t {
|
||||||
|
ACCEL_ROTATION_0DEG = 0,
|
||||||
|
ACCEL_ROTATION_90DEG,
|
||||||
|
ACCEL_ROTATION_180DEG,
|
||||||
|
ACCEL_ROTATION_270DEG,
|
||||||
|
ACCEL_ROTATION_NO_CHANGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct accel_monitor {
|
||||||
|
atomic_bool monitoring_thread_should_exit;
|
||||||
|
atomic_bool monitoring_thread_is_ready;
|
||||||
|
thrd_t monitoring_thread;
|
||||||
|
|
||||||
|
char const* sysfs_device_path;
|
||||||
|
|
||||||
|
mtx_t current_data_lock;
|
||||||
|
struct accel_data current_data;
|
||||||
|
atomic_bool data_is_ready;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct accel_monitor* accel_start_monitor(
|
||||||
|
char const* const sysfs_device_path);
|
||||||
|
enum accel_rotation accel_get_current_rotation(struct accel_monitor*);
|
||||||
|
void accel_stop_monitor(struct accel_monitor*);
|
10
build.sh
Executable file
10
build.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -ex;
|
||||||
|
|
||||||
|
SOURCES="main.c output_manager.c accel_monitor.c"
|
||||||
|
CFLAGS="-std=c2x -Wall -Wextra -pedantic $CFLAGS"
|
||||||
|
LIBS="-lwayland-client protocol/wlr-output-management-unstable-v1.c"
|
||||||
|
OUTPUT=miix-wlr
|
||||||
|
|
||||||
|
clang $CFLAGS $LIBS $SOURCES -o $OUTPUT
|
45
main.c
Normal file
45
main.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "output_manager.h"
|
||||||
|
|
||||||
|
#include "accel_monitor.h"
|
||||||
|
|
||||||
|
static enum wl_output_transform const SENSOR_TO_OUTPUT_ROTATION[] = {
|
||||||
|
[ACCEL_ROTATION_0DEG] = WL_OUTPUT_TRANSFORM_270,
|
||||||
|
[ACCEL_ROTATION_90DEG] = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||||
|
[ACCEL_ROTATION_180DEG] = WL_OUTPUT_TRANSFORM_90,
|
||||||
|
[ACCEL_ROTATION_270DEG] = WL_OUTPUT_TRANSFORM_180,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char const* const DEFAULT_OUTPUT = "DSI-1";
|
||||||
|
static char const* const DEFAULT_MOTION_SENSOR =
|
||||||
|
"/sys/bus/iio/devices/iio:device0";
|
||||||
|
|
||||||
|
static enum accel_rotation last_accel_rotation = ACCEL_ROTATION_NO_CHANGE;
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
struct accel_monitor* monitor =
|
||||||
|
accel_start_monitor(DEFAULT_MOTION_SENSOR);
|
||||||
|
|
||||||
|
if (!monitor) {
|
||||||
|
fprintf(stderr, "Failed to start iio motion monitoring\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct miix_wlr_state* state = miix_wlr_init();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!monitor->data_is_ready) continue;
|
||||||
|
|
||||||
|
enum accel_rotation rotation = accel_get_current_rotation(monitor);
|
||||||
|
if (rotation == ACCEL_ROTATION_NO_CHANGE || rotation == last_accel_rotation) continue;
|
||||||
|
miix_wlr_head_set_transform(
|
||||||
|
state, DEFAULT_OUTPUT, SENSOR_TO_OUTPUT_ROTATION[rotation]);
|
||||||
|
last_accel_rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
accel_stop_monitor(monitor);
|
||||||
|
miix_wlr_cleanup(state);
|
||||||
|
}
|
311
output_manager.c
Normal file
311
output_manager.c
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
// NOTE: Most of this code was stolen from wlr-randr, available at
|
||||||
|
// https://git.sr.ht/~emersion/wlr-randr/tree/master/item/main.c
|
||||||
|
|
||||||
|
#include "output_manager.h"
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "protocol/wlr-output-management-unstable-v1.h"
|
||||||
|
|
||||||
|
static void head_handle_name(void* data,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
const char* name)
|
||||||
|
{
|
||||||
|
struct miix_wlr_head* head = data;
|
||||||
|
head->name = strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_description(void*,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
const char*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_physical_size(void*,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
int32_t,
|
||||||
|
int32_t)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_mode(void*,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
struct zwlr_output_mode_v1*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_enabled(void*, struct zwlr_output_head_v1*, int32_t)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_current_mode(void*,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
struct zwlr_output_mode_v1*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_position(void*,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
int32_t,
|
||||||
|
int32_t)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_transform(void*, struct zwlr_output_head_v1*, int32_t)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_scale(void*, struct zwlr_output_head_v1*, wl_fixed_t)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_finished(void*, struct zwlr_output_head_v1*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_make(void*, struct zwlr_output_head_v1*, const char*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_model(void*, struct zwlr_output_head_v1*, const char*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_serial_number(void*,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
const char*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void head_handle_adaptive_sync(void*,
|
||||||
|
struct zwlr_output_head_v1*,
|
||||||
|
uint32_t)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwlr_output_head_v1_listener head_listener = {
|
||||||
|
.name = head_handle_name,
|
||||||
|
.description = head_handle_description,
|
||||||
|
.physical_size = head_handle_physical_size,
|
||||||
|
.mode = head_handle_mode,
|
||||||
|
.enabled = head_handle_enabled,
|
||||||
|
.current_mode = head_handle_current_mode,
|
||||||
|
.position = head_handle_position,
|
||||||
|
.transform = head_handle_transform,
|
||||||
|
.scale = head_handle_scale,
|
||||||
|
.finished = head_handle_finished,
|
||||||
|
.make = head_handle_make,
|
||||||
|
.model = head_handle_model,
|
||||||
|
.serial_number = head_handle_serial_number,
|
||||||
|
.adaptive_sync = head_handle_adaptive_sync,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void output_manager_handle_head(void* data,
|
||||||
|
struct zwlr_output_manager_v1*,
|
||||||
|
struct zwlr_output_head_v1* wlr_head)
|
||||||
|
{
|
||||||
|
struct miix_wlr_state* state = data;
|
||||||
|
|
||||||
|
struct miix_wlr_head* head = calloc(1, sizeof(*head));
|
||||||
|
head->wlr_head = wlr_head;
|
||||||
|
wl_list_insert(state->heads.prev, &head->link);
|
||||||
|
zwlr_output_head_v1_add_listener(wlr_head, &head_listener, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_manager_handle_done(void* data,
|
||||||
|
struct zwlr_output_manager_v1*,
|
||||||
|
uint32_t serial)
|
||||||
|
{
|
||||||
|
struct miix_wlr_state* state = data;
|
||||||
|
state->serial = serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_manager_handle_finished(void*,
|
||||||
|
struct zwlr_output_manager_v1*)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwlr_output_manager_v1_listener output_manager_listener = {
|
||||||
|
.head = output_manager_handle_head,
|
||||||
|
.done = output_manager_handle_done,
|
||||||
|
.finished = output_manager_handle_finished,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void registry_handle_global(void* data,
|
||||||
|
struct wl_registry* registry,
|
||||||
|
uint32_t name,
|
||||||
|
const char* interface,
|
||||||
|
uint32_t)
|
||||||
|
{
|
||||||
|
struct miix_wlr_state* state = data;
|
||||||
|
|
||||||
|
if (strcmp(interface, zwlr_output_manager_v1_interface.name) == 0) {
|
||||||
|
// TODO: Don't always bind version 4?
|
||||||
|
state->output_manager = wl_registry_bind(
|
||||||
|
registry, name, &zwlr_output_manager_v1_interface, 4);
|
||||||
|
zwlr_output_manager_v1_add_listener(
|
||||||
|
state->output_manager, &output_manager_listener, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void registry_handle_global_remove(void*, struct wl_registry*, uint32_t)
|
||||||
|
{
|
||||||
|
// NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_handle_succeeded(void* data,
|
||||||
|
struct zwlr_output_configuration_v1* config)
|
||||||
|
{
|
||||||
|
struct miix_wlr_state* state = data;
|
||||||
|
state->is_working = false;
|
||||||
|
zwlr_output_configuration_v1_destroy(config);
|
||||||
|
printf("Applied configuration successfully!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_handle_failed(void* data,
|
||||||
|
struct zwlr_output_configuration_v1* config)
|
||||||
|
{
|
||||||
|
struct miix_wlr_state* state = data;
|
||||||
|
state->is_working = false;
|
||||||
|
zwlr_output_configuration_v1_destroy(config);
|
||||||
|
fprintf(stderr, "Failed to apply configuration\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_handle_cancelled(void* data,
|
||||||
|
struct zwlr_output_configuration_v1* config)
|
||||||
|
{
|
||||||
|
struct miix_wlr_state* state = data;
|
||||||
|
state->is_working = false;
|
||||||
|
zwlr_output_configuration_v1_destroy(config);
|
||||||
|
fprintf(stderr, "Configuration cancelled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwlr_output_configuration_v1_listener config_listener = {
|
||||||
|
.succeeded = config_handle_succeeded,
|
||||||
|
.failed = config_handle_failed,
|
||||||
|
.cancelled = config_handle_cancelled,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct miix_wlr_state* miix_wlr_init()
|
||||||
|
{
|
||||||
|
struct wl_display* display = wl_display_connect(NULL);
|
||||||
|
if (!display) {
|
||||||
|
fprintf(stderr, "Couldn't connect to display\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_registry* registry = wl_display_get_registry(display);
|
||||||
|
if (!registry) {
|
||||||
|
fprintf(stderr, "Couldn't get display registry\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct miix_wlr_state* state = calloc(1, sizeof(struct miix_wlr_state));
|
||||||
|
|
||||||
|
state->is_working = false;
|
||||||
|
state->display = display;
|
||||||
|
|
||||||
|
wl_list_init(&state->heads);
|
||||||
|
|
||||||
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
.global = registry_handle_global,
|
||||||
|
.global_remove = registry_handle_global_remove,
|
||||||
|
};
|
||||||
|
wl_registry_add_listener(registry, ®istry_listener, state);
|
||||||
|
|
||||||
|
wl_display_dispatch(display);
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
wl_registry_destroy(registry);
|
||||||
|
|
||||||
|
if (!state->output_manager) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Couldn't get output manager. Does your compositor support "
|
||||||
|
"wlr-outpput-management-unstable-v1?\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
char** miix_wlr_get_head_names(struct miix_wlr_state const* state)
|
||||||
|
{
|
||||||
|
int head_count = wl_list_length(&state->heads);
|
||||||
|
char** head_name_list = calloc(head_count + 1, sizeof(char*));
|
||||||
|
size_t head_index = 0;
|
||||||
|
|
||||||
|
struct miix_wlr_head *head, *tmp_head;
|
||||||
|
wl_list_for_each_safe(head, tmp_head, &state->heads, link)
|
||||||
|
{
|
||||||
|
head_name_list[head_index] = head->name;
|
||||||
|
++head_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
head_name_list[head_index] = 0;
|
||||||
|
return head_name_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void miix_wlr_head_set_transform(struct miix_wlr_state* state,
|
||||||
|
char const* const head_name,
|
||||||
|
enum wl_output_transform transform)
|
||||||
|
{
|
||||||
|
struct zwlr_output_configuration_v1* output_config =
|
||||||
|
zwlr_output_manager_v1_create_configuration(state->output_manager,
|
||||||
|
state->serial);
|
||||||
|
|
||||||
|
zwlr_output_configuration_v1_add_listener(
|
||||||
|
output_config, &config_listener, state);
|
||||||
|
|
||||||
|
struct miix_wlr_head* head;
|
||||||
|
struct miix_wlr_head* tmp_head;
|
||||||
|
wl_list_for_each_safe(head, tmp_head, &state->heads, link)
|
||||||
|
{
|
||||||
|
if (strcmp(head->name, head_name) != 0) continue;
|
||||||
|
|
||||||
|
printf("Found head %s\n", head->name);
|
||||||
|
|
||||||
|
struct zwlr_output_configuration_head_v1* config_head =
|
||||||
|
zwlr_output_configuration_v1_enable_head(output_config,
|
||||||
|
head->wlr_head);
|
||||||
|
|
||||||
|
state->is_working = true;
|
||||||
|
|
||||||
|
zwlr_output_configuration_head_v1_set_transform(config_head, transform);
|
||||||
|
zwlr_output_configuration_v1_apply(output_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (state->is_working && wl_display_dispatch(state->display) > 0)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void miix_wlr_cleanup(struct miix_wlr_state* state)
|
||||||
|
{
|
||||||
|
struct miix_wlr_head* head;
|
||||||
|
struct miix_wlr_head* tmp_head;
|
||||||
|
wl_list_for_each_safe(head, tmp_head, &state->heads, link)
|
||||||
|
{
|
||||||
|
zwlr_output_head_v1_destroy(head->wlr_head);
|
||||||
|
free(head->name);
|
||||||
|
free(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
zwlr_output_manager_v1_destroy(state->output_manager);
|
||||||
|
wl_display_disconnect(state->display);
|
||||||
|
}
|
32
output_manager.h
Normal file
32
output_manager.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "protocol/wlr-output-management-unstable-v1.h"
|
||||||
|
|
||||||
|
struct miix_wlr_head {
|
||||||
|
struct zwlr_output_head_v1* wlr_head;
|
||||||
|
char* name;
|
||||||
|
struct wl_list link;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct miix_wlr_state {
|
||||||
|
bool is_working;
|
||||||
|
|
||||||
|
struct zwlr_output_manager_v1* output_manager;
|
||||||
|
struct wl_display* display;
|
||||||
|
uint32_t serial;
|
||||||
|
|
||||||
|
struct wl_list heads; // struct miix_wlr_head
|
||||||
|
};
|
||||||
|
|
||||||
|
struct miix_wlr_state* miix_wlr_init();
|
||||||
|
|
||||||
|
char** miix_wlr_get_head_names(struct miix_wlr_state const*);
|
||||||
|
void miix_wlr_head_set_transform(struct miix_wlr_state*,
|
||||||
|
char const* const head_name,
|
||||||
|
enum wl_output_transform);
|
||||||
|
|
||||||
|
void miix_wlr_cleanup(struct miix_wlr_state*);
|
6
protocol/codegen.sh
Executable file
6
protocol/codegen.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
PROTO_NAME=wlr-output-management-unstable-v1
|
||||||
|
|
||||||
|
wayland-scanner private-code $PROTO_NAME.xml $PROTO_NAME.c
|
||||||
|
wayland-scanner client-header $PROTO_NAME.xml $PROTO_NAME.h
|
5
protocol/download_protocols.sh
Executable file
5
protocol/download_protocols.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
URL="https://gitlab.freedesktop.org/wlroots/wlr-protocols/-/raw/master/unstable/wlr-output-management-unstable-v1.xml"
|
||||||
|
|
||||||
|
curl $URL > wlr-output-management-unstable-v1.xml
|
Loading…
Reference in a new issue