Skip to content

Commit 0ae8082

Browse files
committed
desktop: rewrite reserved area handling
1 parent bb963fb commit 0ae8082

File tree

29 files changed

+742
-387
lines changed

29 files changed

+742
-387
lines changed

.github/actions/setup_base/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ runs:
2424
glm \
2525
glslang \
2626
go \
27+
gtest \
2728
hyprlang \
2829
hyprcursor \
2930
jq \

.github/workflows/nix-ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,5 @@ jobs:
2525

2626
test:
2727
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
28-
needs: hyprland
2928
uses: ./.github/workflows/nix-test.yml
3029
secrets: inherit

CMakeLists.txt

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ message(
8080
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
8181
message(STATUS "Configuring Hyprland in Debug with CMake")
8282
add_compile_definitions(HYPRLAND_DEBUG)
83+
set(BUILD_TESTING ON)
8384
else()
8485
add_compile_options(-O3)
8586
message(STATUS "Configuring Hyprland in Release with CMake")
87+
set(BUILD_TESTING OFF)
8688
endif()
8789

8890
add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}")
@@ -251,14 +253,18 @@ pkg_check_modules(
251253
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
252254

253255
file(GLOB_RECURSE SRCFILES "src/*.cpp")
256+
get_filename_component(FULL_MAIN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ABSOLUTE)
257+
list(REMOVE_ITEM SRCFILES "${FULL_MAIN_PATH}")
254258

255259
set(TRACY_CPP_FILES "")
256260
if(USE_TRACY)
257261
set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp")
258262
message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES})
259263
endif()
260264

261-
add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES})
265+
add_library(hyprland_lib STATIC ${SRCFILES})
266+
add_executable(Hyprland src/main.cpp ${TRACY_CPP_FILES})
267+
target_link_libraries(Hyprland hyprland_lib)
262268

263269
set(USE_GPROF OFF)
264270

@@ -268,8 +274,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
268274
if(WITH_ASAN)
269275
message(STATUS "Enabling ASan")
270276

271-
target_link_libraries(Hyprland asan)
272-
target_compile_options(Hyprland PUBLIC -fsanitize=address)
277+
target_link_libraries(hyprland_lib asan)
278+
target_compile_options(hyprland_lib PUBLIC -fsanitize=address)
273279
endif()
274280

275281
if(USE_TRACY)
@@ -279,7 +285,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
279285
option(TRACY_ON_DEMAND "" ON)
280286
add_subdirectory(subprojects/tracy)
281287

282-
target_link_libraries(Hyprland Tracy::TracyClient)
288+
target_link_libraries(hyprland_lib Tracy::TracyClient)
283289

284290
if(USE_TRACY_GPU)
285291
message(STATUS "Tracy GPU Profiling is turned on")
@@ -304,19 +310,19 @@ endif()
304310
include(CheckLibraryExists)
305311
check_library_exists(execinfo backtrace "" HAVE_LIBEXECINFO)
306312
if(HAVE_LIBEXECINFO)
307-
target_link_libraries(Hyprland execinfo)
313+
target_link_libraries(hyprland_lib execinfo)
308314
endif()
309315

310316
check_include_file("sys/timerfd.h" HAS_TIMERFD)
311317
pkg_check_modules(epoll IMPORTED_TARGET epoll-shim)
312318
if(NOT HAS_TIMERFD AND epoll_FOUND)
313-
target_link_libraries(Hyprland PkgConfig::epoll)
319+
target_link_libraries(hyprland_lib PkgConfig::epoll)
314320
endif()
315321

316322
check_include_file("sys/inotify.h" HAS_INOTIFY)
317323
pkg_check_modules(inotify IMPORTED_TARGET libinotify)
318324
if(NOT HAS_INOTIFY AND inotify_FOUND)
319-
target_link_libraries(Hyprland PkgConfig::inotify)
325+
target_link_libraries(hyprland_lib PkgConfig::inotify)
320326
endif()
321327

322328
if(NO_XWAYLAND)
@@ -335,7 +341,7 @@ else()
335341
xcb-composite
336342
xcb-res
337343
xcb-errors)
338-
target_link_libraries(Hyprland PkgConfig::xdeps)
344+
target_link_libraries(hyprland_lib PkgConfig::xdeps)
339345
endif()
340346

341347
if(NO_SYSTEMD)
@@ -362,7 +368,7 @@ if(CMAKE_DISABLE_PRECOMPILE_HEADERS)
362368
message(STATUS "Not using precompiled headers")
363369
else()
364370
message(STATUS "Setting precompiled headers")
365-
target_precompile_headers(Hyprland PRIVATE
371+
target_precompile_headers(hyprland_lib PRIVATE
366372
$<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>)
367373
endif()
368374

@@ -371,22 +377,24 @@ message(STATUS "Setting link libraries")
371377
target_link_libraries(
372378
Hyprland
373379
${LIBRT}
380+
hyprland_lib
374381
PkgConfig::aquamarine_dep
375382
PkgConfig::hyprlang_dep
376383
PkgConfig::hyprutils_dep
377384
PkgConfig::hyprcursor_dep
378385
PkgConfig::hyprgraphics_dep
379386
PkgConfig::deps)
380387
if(udis_dep_FOUND)
381-
target_link_libraries(Hyprland PkgConfig::udis_dep)
388+
target_link_libraries(hyprland_lib PkgConfig::udis_dep)
382389
elseif(NOT("${udis_nopc}" MATCHES "udis_nopc-NOTFOUND"))
383-
target_link_libraries(Hyprland ${udis_nopc})
390+
target_link_libraries(hyprland_lib ${udis_nopc})
384391
else()
385-
target_link_libraries(Hyprland libudis86)
392+
target_link_libraries(hyprland_lib libudis86)
386393
endif()
387394

388395
# used by `make installheaders`, to ensure the headers are generated
389396
add_custom_target(generate-protocol-headers)
397+
set(PROTOCOL_SOURCES "")
390398

391399
function(protocolnew protoPath protoName external)
392400
if(external)
@@ -400,10 +408,15 @@ function(protocolnew protoPath protoName external)
400408
COMMAND hyprwayland-scanner ${path}/${protoName}.xml
401409
${CMAKE_SOURCE_DIR}/protocols/
402410
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
403-
target_sources(Hyprland PRIVATE protocols/${protoName}.cpp
411+
target_sources(hyprland_lib PRIVATE protocols/${protoName}.cpp
404412
protocols/${protoName}.hpp)
405413
target_sources(generate-protocol-headers
406414
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp)
415+
416+
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp")
417+
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
418+
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp")
419+
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
407420
endfunction()
408421
function(protocolWayland)
409422
add_custom_command(
@@ -413,12 +426,17 @@ function(protocolWayland)
413426
hyprwayland-scanner --wayland-enums
414427
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
415428
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
416-
target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
429+
target_sources(hyprland_lib PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
417430
target_sources(generate-protocol-headers
418431
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
432+
433+
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/wayland.hpp")
434+
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
435+
list(APPEND PROTOCOL_SOURCES "${CMAKE_SOURCE_DIR}/protocols/wayland.cpp")
436+
set(PROTOCOL_SOURCES "${PROTOCOL_SOURCES}" PARENT_SCOPE)
419437
endfunction()
420438

421-
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
439+
target_link_libraries(hyprland_lib OpenGL::EGL OpenGL::GL Threads::Threads)
422440

423441
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.4)
424442
if(hyprland_protocols_dep_FOUND)
@@ -563,10 +581,37 @@ install(
563581
PATTERN "*.hpp"
564582
PATTERN "*.inc")
565583

566-
if(BUILD_TESTING OR BUILD_HYPRTESTER)
567-
message(STATUS "Building hyprtester")
584+
if(BUILD_TESTING OR WITH_TESTS)
585+
message(STATUS "Building tests")
568586

587+
# hyprtester
569588
add_subdirectory(hyprtester)
589+
590+
# GTest
591+
find_package(GTest CONFIG REQUIRED)
592+
include(GoogleTest)
593+
file(GLOB_RECURSE TESTFILES "tests/*.cpp")
594+
add_executable(hyprland_gtests ${TESTFILES})
595+
target_compile_options(hyprland_gtests PRIVATE --coverage)
596+
target_link_options(hyprland_gtests PRIVATE --coverage)
597+
target_include_directories(
598+
hyprland_gtests
599+
PUBLIC "./include"
600+
PRIVATE "./src" "./src/include" "./protocols" "${CMAKE_BINARY_DIR}")
601+
602+
target_link_libraries(hyprland_gtests hyprland_lib GTest::gtest_main)
603+
604+
gtest_discover_tests(hyprland_gtests)
605+
606+
# Enable coverage in main hyprland lib
607+
target_compile_options(hyprland_lib PRIVATE --coverage)
608+
target_link_options(hyprland_lib PRIVATE --coverage)
609+
target_link_libraries(hyprland_lib gcov)
610+
611+
# Enable coverage in hyprland exe
612+
target_compile_options(Hyprland PRIVATE --coverage)
613+
target_link_options(Hyprland PRIVATE --coverage)
614+
target_link_libraries(Hyprland gcov)
570615
endif()
571616

572617
if(BUILD_TESTING)
@@ -575,12 +620,8 @@ if(BUILD_TESTING)
575620
enable_testing()
576621
add_custom_target(tests)
577622

578-
add_test(
579-
NAME "Main Test"
580-
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/hyprtester
581-
COMMAND hyprtester)
623+
add_dependencies(tests hyprland_gtests)
582624

583-
add_dependencies(tests hyprtester)
584625
else()
585626
message(STATUS "Testing is disabled")
586627
endif()

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
# hyprland-packages
153153
hyprland
154154
hyprland-unwrapped
155+
hyprland-with-tests
155156
# hyprland-extras
156157
xdg-desktop-portal-hyprland
157158
;

hyprtester/src/tests/main/window.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -364,22 +364,40 @@ static bool test() {
364364

365365
NLog::log("{}Testing window split ratios", Colors::YELLOW);
366366
{
367-
const double RATIO = 1.25;
368-
const double PERCENT = RATIO / 2.0 * 100.0;
369-
const int GAPSIN = 5;
370-
const int GAPSOUT = 20;
371-
const int BORDERS = 2 * 2;
372-
const int WTRIM = BORDERS + GAPSIN + GAPSOUT;
373-
const int HEIGHT = 1080 - (BORDERS + (GAPSOUT * 2));
374-
const int WIDTH1 = std::round(1920.0 / 2.0 * (2 - RATIO)) - WTRIM;
375-
const int WIDTH2 = std::round(1920.0 / 2.0 * RATIO) - WTRIM;
367+
const double INITIAL_RATIO = 1.25;
368+
const int GAPSIN = 5;
369+
const int GAPSOUT = 20;
370+
const int BORDERSIZE = 2;
371+
const int BORDERS = BORDERSIZE * 2;
372+
const int MONITOR_W = 1920;
373+
const int MONITOR_H = 1080;
374+
375+
const float totalAvailableHeight = MONITOR_H - (GAPSOUT * 2);
376+
const int HEIGHT = std::floor(totalAvailableHeight) - BORDERS;
377+
const float availableWidthForSplit = MONITOR_W - (GAPSOUT * 2) - GAPSIN;
378+
379+
auto calculateFinalWidth = [&](double boxWidth, bool isLeftWindow) {
380+
double gapLeft = isLeftWindow ? GAPSOUT : GAPSIN;
381+
double gapRight = isLeftWindow ? GAPSIN : GAPSOUT;
382+
return std::floor(boxWidth - gapLeft - gapRight - BORDERS);
383+
};
384+
385+
double geomBoxWidthA_R1 = (availableWidthForSplit * INITIAL_RATIO / 2.0) + GAPSOUT + (GAPSIN / 2.0);
386+
double geomBoxWidthB_R1 = MONITOR_W - geomBoxWidthA_R1;
387+
const int WIDTH1 = calculateFinalWidth(geomBoxWidthB_R1, false);
388+
389+
const double INVERTED_RATIO = 0.75;
390+
double geomBoxWidthA_R2 = (availableWidthForSplit * INVERTED_RATIO / 2.0) + GAPSOUT + (GAPSIN / 2.0);
391+
double geomBoxWidthB_R2 = MONITOR_W - geomBoxWidthA_R2;
392+
const int WIDTH2 = calculateFinalWidth(geomBoxWidthB_R2, false);
393+
const int WIDTH_A_FINAL = calculateFinalWidth(geomBoxWidthA_R2, true);
376394

377395
OK(getFromSocket("/keyword dwindle:default_split_ratio 1.25"));
378396

379397
if (!spawnKitty("kitty_B"))
380398
return false;
381399

382-
NLog::log("{}Expecting kitty_B to take up roughly {}% of screen width", Colors::YELLOW, 100 - PERCENT);
400+
NLog::log("{}Expecting kitty_B size: {},{}", Colors::YELLOW, WIDTH1, HEIGHT);
383401
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH1, HEIGHT));
384402

385403
OK(getFromSocket("/dispatch killwindow activewindow"));
@@ -391,12 +409,12 @@ static bool test() {
391409
if (!spawnKitty("kitty_B"))
392410
return false;
393411

394-
NLog::log("{}Expecting kitty_B to take up roughly {}% of screen width", Colors::YELLOW, PERCENT);
412+
NLog::log("{}Expecting kitty_B size: {},{}", Colors::YELLOW, WIDTH2, HEIGHT);
395413
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH2, HEIGHT));
396414

397415
OK(getFromSocket("/dispatch focuswindow class:kitty_A"));
398-
NLog::log("{}Expecting kitty_A to have the same width as the previous kitty_B", Colors::YELLOW);
399-
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH1, HEIGHT));
416+
NLog::log("{}Expecting kitty_A size: {},{}", Colors::YELLOW, WIDTH_A_FINAL, HEIGHT);
417+
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH_A_FINAL, HEIGHT));
400418

401419
OK(getFromSocket("/keyword dwindle:default_split_ratio 1"));
402420
}

0 commit comments

Comments
 (0)