feat: 添加屏幕去重功能并调整测试用例目录结构
This commit is contained in:
@@ -6,7 +6,6 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
|||||||
set(CMAKE_C_EXTENSIONS ON)
|
set(CMAKE_C_EXTENSIONS ON)
|
||||||
|
|
||||||
set(APP_NAME "zdwm")
|
set(APP_NAME "zdwm")
|
||||||
set(TEST_APP_NAME "zdwm-tests")
|
|
||||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||||
set(BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
set(BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ project(${APP_NAME}
|
|||||||
LANGUAGES C
|
LANGUAGES C
|
||||||
)
|
)
|
||||||
|
|
||||||
enable_testing()
|
option(BUILD_TESTING "Build tests" OFF)
|
||||||
|
|
||||||
add_executable(${APP_NAME}
|
add_executable(${APP_NAME}
|
||||||
${SOURCE_DIR}/wm.c
|
${SOURCE_DIR}/wm.c
|
||||||
@@ -54,15 +53,6 @@ add_executable(${APP_NAME}
|
|||||||
${SOURCE_DIR}/tray.c
|
${SOURCE_DIR}/tray.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${TEST_APP_NAME}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/main.c
|
|
||||||
${SOURCE_DIR}/utils.c
|
|
||||||
${SOURCE_DIR}/backend/x11/backend.c
|
|
||||||
${SOURCE_DIR}/core/layout.c
|
|
||||||
${SOURCE_DIR}/core/runtime.c
|
|
||||||
${SOURCE_DIR}/core/state.c
|
|
||||||
)
|
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
pkg_check_modules(deps REQUIRED
|
pkg_check_modules(deps REQUIRED
|
||||||
@@ -98,29 +88,11 @@ target_include_directories(${APP_NAME}
|
|||||||
PRIVATE ${BUILD_DIR}
|
PRIVATE ${BUILD_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${TEST_APP_NAME} SYSTEM
|
|
||||||
PRIVATE ${deps_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
target_include_directories(${TEST_APP_NAME}
|
|
||||||
PRIVATE ${SOURCE_DIR}
|
|
||||||
PRIVATE ${BUILD_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(${APP_NAME}
|
target_link_libraries(${APP_NAME}
|
||||||
PRIVATE m
|
PRIVATE m
|
||||||
PRIVATE ${deps_LIBRARIES}
|
PRIVATE ${deps_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${TEST_APP_NAME}
|
|
||||||
PRIVATE m
|
|
||||||
PRIVATE ${deps_LIBRARIES}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_test(NAME ${TEST_APP_NAME} COMMAND $<TARGET_FILE:${TEST_APP_NAME}>)
|
|
||||||
set_tests_properties(${TEST_APP_NAME} PROPERTIES
|
|
||||||
ENVIRONMENT "DISPLAY=:3"
|
|
||||||
)
|
|
||||||
|
|
||||||
## 配置项
|
## 配置项
|
||||||
# Check for backtrace_symbols()
|
# Check for backtrace_symbols()
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
@@ -130,7 +102,6 @@ if(NOT HAS_EXECINFO)
|
|||||||
if(LIB_EXECINFO)
|
if(LIB_EXECINFO)
|
||||||
set(HAS_EXECINFO TRUE)
|
set(HAS_EXECINFO TRUE)
|
||||||
target_link_libraries(${APP_NAME} ${LIB_EXECINFO})
|
target_link_libraries(${APP_NAME} ${LIB_EXECINFO})
|
||||||
target_link_libraries(${TEST_APP_NAME} ${LIB_EXECINFO})
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(HAS_EXECINFO)
|
if(HAS_EXECINFO)
|
||||||
@@ -168,3 +139,8 @@ add_custom_target(generate_atoms
|
|||||||
DEPENDS ${BUILD_DIR}/atoms-extern.h ${BUILD_DIR}/atoms-intern.h
|
DEPENDS ${BUILD_DIR}/atoms-extern.h ${BUILD_DIR}/atoms-intern.h
|
||||||
)
|
)
|
||||||
add_dependencies(${APP_NAME} generate_atoms)
|
add_dependencies(${APP_NAME} generate_atoms)
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -39,7 +39,9 @@ build: prepare
|
|||||||
@cmake --build $(BUILD_DIR)
|
@cmake --build $(BUILD_DIR)
|
||||||
@cp $(BUILD_DIR)/$(TARGET_NAME) $(TARGET)
|
@cp $(BUILD_DIR)/$(TARGET_NAME) $(TARGET)
|
||||||
|
|
||||||
test: build
|
test:
|
||||||
@ctest --test-dir $(BUILD_DIR)
|
cmake -S $(SRC_DIR) -B $(BUILD_DIR) -DBUILD_TESTING=ON
|
||||||
|
cmake --build $(BUILD_DIR)
|
||||||
|
ctest --test-dir $(BUILD_DIR)
|
||||||
|
|
||||||
.PHONY: clean run wm prepare build install uninstall reinstall test
|
.PHONY: clean run wm prepare build install uninstall reinstall test
|
||||||
|
|||||||
56
src/backend/output_utils.c
Normal file
56
src/backend/output_utils.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "backend/output_utils.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "core/backend.h"
|
||||||
|
#include "core/types.h"
|
||||||
|
#include "core/wm_desc.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
static inline int32_t right(wm_rect_t a) { return a.x + a.width; }
|
||||||
|
static inline int32_t bottom(wm_rect_t a) { return a.y + a.height; }
|
||||||
|
static inline bool fully_contains(wm_rect_t outer, wm_rect_t inner) {
|
||||||
|
return inner.x >= outer.x && inner.y >= outer.y &&
|
||||||
|
right(inner) <= right(outer) && bottom(inner) <= bottom(outer);
|
||||||
|
}
|
||||||
|
|
||||||
|
wm_backend_detect_t *output_remove_duplication(const wm_output_info_t *output,
|
||||||
|
const size_t count) {
|
||||||
|
if (!output || count < 1) return nullptr;
|
||||||
|
|
||||||
|
bool *remove = p_new(bool, count);
|
||||||
|
|
||||||
|
for (int32_t i = (int32_t)count - 1; i >= 0; i--) {
|
||||||
|
if (remove[i]) continue;
|
||||||
|
for (int32_t j = i - 1; j >= 0; j--) {
|
||||||
|
if (remove[j]) continue;
|
||||||
|
if (fully_contains(output[j].geometry, output[i].geometry)) {
|
||||||
|
remove[i] = true;
|
||||||
|
} else if (fully_contains(output[i].geometry, output[j].geometry)) {
|
||||||
|
remove[j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t amount = 0;
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
if (!remove[i]) amount++;
|
||||||
|
}
|
||||||
|
if (!amount) {
|
||||||
|
p_delete(&remove);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm_output_info_t *list = p_new(wm_output_info_t, amount);
|
||||||
|
amount = 0;
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
if (remove[i]) continue;
|
||||||
|
list[amount++] = output[i];
|
||||||
|
}
|
||||||
|
p_delete(&remove);
|
||||||
|
wm_backend_detect_t *detect = p_new(wm_backend_detect_t, 1);
|
||||||
|
detect->outputs = list;
|
||||||
|
detect->output_count = amount;
|
||||||
|
return detect;
|
||||||
|
}
|
||||||
9
src/backend/output_utils.h
Normal file
9
src/backend/output_utils.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "core/backend.h"
|
||||||
|
#include "core/wm_desc.h"
|
||||||
|
|
||||||
|
wm_backend_detect_t *output_remove_duplication(const wm_output_info_t *output,
|
||||||
|
const size_t count);
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "core/backend.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -9,7 +11,7 @@
|
|||||||
#include <xcb/xinerama.h>
|
#include <xcb/xinerama.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "core/backend.h"
|
#include "backend/output_utils.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/wm_desc.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
@@ -215,28 +217,30 @@ static bool detect_monitor_by_xinerama(const wm_backend_t *backend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wm_backend_detect_t *wm_backend_detect(wm_backend_t *backend) {
|
wm_backend_detect_t *wm_backend_detect(wm_backend_t *backend) {
|
||||||
wm_backend_detect_t *detect = p_new(wm_backend_detect_t, 1);
|
|
||||||
|
|
||||||
wm_output_info_t *outputs = nullptr;
|
wm_output_info_t *outputs = nullptr;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
|
||||||
if (detect_monitor_by_randr(backend, &outputs, &count)) {
|
if (detect_monitor_by_randr(backend, &outputs, &count)) {
|
||||||
detect->output_count = count;
|
wm_backend_detect_t *detect = output_remove_duplication(outputs, count);
|
||||||
detect->outputs = outputs;
|
p_delete(&outputs);
|
||||||
} else if (detect_monitor_by_xinerama(backend, &outputs, &count)) {
|
return detect;
|
||||||
detect->output_count = count;
|
|
||||||
detect->outputs = outputs;
|
|
||||||
} else {
|
|
||||||
wm_output_info_t *output = p_new(wm_output_info_t, 1);
|
|
||||||
output->geometry.x = 0;
|
|
||||||
output->geometry.y = 0;
|
|
||||||
output->geometry.width = backend->screen->width_in_pixels;
|
|
||||||
output->geometry.height = backend->screen->height_in_pixels;
|
|
||||||
|
|
||||||
detect->outputs = output;
|
|
||||||
detect->output_count = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (detect_monitor_by_xinerama(backend, &outputs, &count)) {
|
||||||
|
wm_backend_detect_t *detect = output_remove_duplication(outputs, count);
|
||||||
|
p_delete(&outputs);
|
||||||
|
return detect;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm_output_info_t *output = p_new(wm_output_info_t, 1);
|
||||||
|
output->geometry.x = 0;
|
||||||
|
output->geometry.y = 0;
|
||||||
|
output->geometry.width = backend->screen->width_in_pixels;
|
||||||
|
output->geometry.height = backend->screen->height_in_pixels;
|
||||||
|
|
||||||
|
wm_backend_detect_t *detect = p_new(wm_backend_detect_t, 1);
|
||||||
|
detect->outputs = output;
|
||||||
|
detect->output_count = 1;
|
||||||
return detect;
|
return detect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
tests/CMakeLists.txt
Normal file
2
tests/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
add_subdirectory(backend)
|
||||||
|
add_subdirectory(core)
|
||||||
19
tests/backend/CMakeLists.txt
Normal file
19
tests/backend/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
set(OUTPUT_UTILS_TEST_APP_NAME "zdwm-output-utils-tests")
|
||||||
|
|
||||||
|
add_executable(${OUTPUT_UTILS_TEST_APP_NAME}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/output_utils_test.c
|
||||||
|
${SOURCE_DIR}/backend/output_utils.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${OUTPUT_UTILS_TEST_APP_NAME}
|
||||||
|
PRIVATE ${SOURCE_DIR}
|
||||||
|
PRIVATE ${BUILD_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${OUTPUT_UTILS_TEST_APP_NAME}
|
||||||
|
PRIVATE m
|
||||||
|
)
|
||||||
|
|
||||||
|
add_test(NAME ${OUTPUT_UTILS_TEST_APP_NAME}
|
||||||
|
COMMAND $<TARGET_FILE:${OUTPUT_UTILS_TEST_APP_NAME}>
|
||||||
|
)
|
||||||
63
tests/backend/output_utils_test.c
Normal file
63
tests/backend/output_utils_test.c
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "backend/output_utils.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
static void assert_output_geometry(const wm_output_info_t *output, int32_t x,
|
||||||
|
int32_t y, int32_t width,
|
||||||
|
int32_t height) {
|
||||||
|
assert(output);
|
||||||
|
assert(output->geometry.x == x);
|
||||||
|
assert(output->geometry.y == y);
|
||||||
|
assert(output->geometry.width == width);
|
||||||
|
assert(output->geometry.height == height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_detect_result(wm_backend_detect_t *detect) {
|
||||||
|
assert(detect);
|
||||||
|
for (size_t i = 0; i < detect->output_count; i++) {
|
||||||
|
p_delete(&detect->outputs[i].name);
|
||||||
|
}
|
||||||
|
p_delete(&detect->outputs);
|
||||||
|
free(detect);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_output_remove_duplication_invalid_input(void) {
|
||||||
|
wm_output_info_t output = {0};
|
||||||
|
|
||||||
|
assert(output_remove_duplication(nullptr, 0) == nullptr);
|
||||||
|
assert(output_remove_duplication(&output, 0) == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_output_remove_duplication_keeps_non_nested_outputs(void) {
|
||||||
|
wm_output_info_t outputs[] = {
|
||||||
|
{
|
||||||
|
.geometry = {.x = 0, .y = 0, .width = 3840, .height = 1080},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.geometry = {.x = 0, .y = 0, .width = 1920, .height = 1080},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.geometry = {.x = 1920, .y = 0, .width = 1920, .height = 1080},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.geometry = {.x = 3840, .y = 0, .width = 1280, .height = 1024},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
wm_backend_detect_t *detect =
|
||||||
|
output_remove_duplication(outputs, countof(outputs));
|
||||||
|
assert(detect);
|
||||||
|
assert(detect->output_count == 2);
|
||||||
|
assert_output_geometry(&detect->outputs[0], 0, 0, 3840, 1080);
|
||||||
|
assert_output_geometry(&detect->outputs[1], 3840, 0, 1280, 1024);
|
||||||
|
|
||||||
|
destroy_detect_result(detect);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
test_output_remove_duplication_invalid_input();
|
||||||
|
test_output_remove_duplication_keeps_non_nested_outputs();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
34
tests/core/CMakeLists.txt
Normal file
34
tests/core/CMakeLists.txt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
set(TEST_APP_NAME "zdwm-tests")
|
||||||
|
|
||||||
|
add_executable(${TEST_APP_NAME}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/main.c
|
||||||
|
${SOURCE_DIR}/utils.c
|
||||||
|
${SOURCE_DIR}/backend/output_utils.c
|
||||||
|
${SOURCE_DIR}/backend/x11/backend.c
|
||||||
|
${SOURCE_DIR}/core/layout.c
|
||||||
|
${SOURCE_DIR}/core/runtime.c
|
||||||
|
${SOURCE_DIR}/core/state.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${TEST_APP_NAME} SYSTEM
|
||||||
|
PRIVATE ${deps_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
target_include_directories(${TEST_APP_NAME}
|
||||||
|
PRIVATE ${SOURCE_DIR}
|
||||||
|
PRIVATE ${BUILD_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${TEST_APP_NAME}
|
||||||
|
PRIVATE m
|
||||||
|
PRIVATE ${deps_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(HAS_EXECINFO AND LIB_EXECINFO)
|
||||||
|
target_link_libraries(${TEST_APP_NAME} PRIVATE ${LIB_EXECINFO})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_test(NAME ${TEST_APP_NAME} COMMAND $<TARGET_FILE:${TEST_APP_NAME}>)
|
||||||
|
|
||||||
|
set_tests_properties(${TEST_APP_NAME} PROPERTIES
|
||||||
|
ENVIRONMENT "DISPLAY=:3"
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user