2022-03-16 21:37:21 +01:00
|
|
|
#include "Compositor.hpp"
|
2022-07-10 15:41:26 +02:00
|
|
|
#include "helpers/Splashes.hpp"
|
2024-03-03 19:39:20 +01:00
|
|
|
#include "config/ConfigValue.hpp"
|
2024-03-09 17:52:59 +01:00
|
|
|
#include "managers/CursorManager.hpp"
|
2024-04-07 04:31:51 +02:00
|
|
|
#include "managers/eventLoop/EventLoopManager.hpp"
|
2022-07-10 15:41:26 +02:00
|
|
|
#include <random>
|
2023-07-09 23:08:40 +02:00
|
|
|
#include <unordered_set>
|
2022-07-31 00:27:32 +02:00
|
|
|
#include "debug/HyprCtl.hpp"
|
2023-02-19 14:45:56 +01:00
|
|
|
#include "debug/CrashReporter.hpp"
|
2023-01-05 20:17:55 +01:00
|
|
|
#ifdef USES_SYSTEMD
|
|
|
|
#include <systemd/sd-daemon.h> // for sd_notify
|
|
|
|
#endif
|
2023-03-01 15:06:52 +01:00
|
|
|
#include <ranges>
|
2024-03-31 01:48:39 +01:00
|
|
|
#include "helpers/VarList.hpp"
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2022-07-13 18:18:23 +02:00
|
|
|
int handleCritSignal(int signo, void* data) {
|
2023-09-06 12:51:36 +02:00
|
|
|
Debug::log(LOG, "Hyprland received signal {}", signo);
|
2022-07-13 18:18:23 +02:00
|
|
|
|
2023-08-19 19:24:48 +02:00
|
|
|
if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL)
|
2022-07-13 18:18:23 +02:00
|
|
|
g_pCompositor->cleanup();
|
|
|
|
|
2023-08-19 19:24:48 +02:00
|
|
|
return 0;
|
2022-07-13 18:18:23 +02:00
|
|
|
}
|
|
|
|
|
2023-03-01 16:08:44 +01:00
|
|
|
void handleUnrecoverableSignal(int sig) {
|
2023-02-27 13:32:38 +01:00
|
|
|
|
2023-03-01 22:55:30 +01:00
|
|
|
// remove our handlers
|
|
|
|
signal(SIGABRT, SIG_DFL);
|
|
|
|
signal(SIGSEGV, SIG_DFL);
|
|
|
|
|
2023-12-20 23:54:52 +01:00
|
|
|
if (g_pHookSystem && g_pHookSystem->m_bCurrentEventPlugin) {
|
2023-02-27 13:32:38 +01:00
|
|
|
longjmp(g_pHookSystem->m_jbHookFaultJumpBuf, 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-01 16:08:44 +01:00
|
|
|
CrashReporter::createAndSaveCrash(sig);
|
2023-03-01 22:55:30 +01:00
|
|
|
|
2023-02-20 12:02:44 +01:00
|
|
|
abort();
|
2023-02-19 14:45:56 +01:00
|
|
|
}
|
|
|
|
|
2023-09-29 17:38:13 +02:00
|
|
|
void handleUserSignal(int sig) {
|
|
|
|
if (sig == SIGUSR1) {
|
|
|
|
// means we have to unwind a timed out event
|
|
|
|
throw std::exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
CCompositor::CCompositor() {
|
2022-08-28 11:19:08 +02:00
|
|
|
m_iHyprlandPID = getpid();
|
|
|
|
|
2022-06-03 17:41:57 +02:00
|
|
|
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL));
|
2022-03-18 23:52:36 +01:00
|
|
|
|
2022-06-29 12:58:49 +02:00
|
|
|
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
|
|
|
|
|
2022-12-21 16:41:02 +01:00
|
|
|
if (!std::filesystem::exists("/tmp/hypr")) {
|
|
|
|
std::filesystem::create_directory("/tmp/hypr");
|
2023-12-20 12:56:15 +01:00
|
|
|
std::filesystem::permissions("/tmp/hypr", std::filesystem::perms::all | std::filesystem::perms::sticky_bit, std::filesystem::perm_options::replace);
|
2022-12-21 16:41:02 +01:00
|
|
|
}
|
|
|
|
|
2022-06-29 12:58:49 +02:00
|
|
|
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
|
2022-12-21 16:41:02 +01:00
|
|
|
std::filesystem::create_directory(INSTANCEPATH);
|
|
|
|
std::filesystem::permissions(INSTANCEPATH, std::filesystem::perms::group_all, std::filesystem::perm_options::replace);
|
|
|
|
std::filesystem::permissions(INSTANCEPATH, std::filesystem::perms::owner_all, std::filesystem::perm_options::add);
|
2022-06-29 12:58:49 +02:00
|
|
|
|
2022-06-03 17:48:07 +02:00
|
|
|
Debug::init(m_szInstanceSignature);
|
|
|
|
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(LOG, "Instance Signature: {}", m_szInstanceSignature);
|
2022-06-03 17:41:57 +02:00
|
|
|
|
2023-09-06 12:51:36 +02:00
|
|
|
Debug::log(LOG, "Hyprland PID: {}", m_iHyprlandPID);
|
2022-08-28 11:19:08 +02:00
|
|
|
|
2022-06-25 20:49:06 +02:00
|
|
|
Debug::log(LOG, "===== SYSTEM INFO: =====");
|
|
|
|
|
|
|
|
logSystemInfo();
|
|
|
|
|
|
|
|
Debug::log(LOG, "========================");
|
|
|
|
|
2022-06-25 21:16:52 +02:00
|
|
|
Debug::log(NONE, "\n\n"); // pad
|
|
|
|
|
2023-01-07 12:33:36 +01:00
|
|
|
Debug::log(INFO, "If you are crashing, or encounter any bugs, please consult https://wiki.hyprland.org/Crashes-and-Bugs/\n\n");
|
2022-06-25 21:16:52 +02:00
|
|
|
|
2022-07-10 15:41:26 +02:00
|
|
|
setRandomSplash();
|
|
|
|
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(LOG, "\nCurrent splash: {}\n\n", m_szCurrentSplash);
|
2023-03-05 14:37:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CCompositor::~CCompositor() {
|
|
|
|
cleanup();
|
|
|
|
}
|
2022-07-10 15:41:26 +02:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
void CCompositor::setRandomSplash() {
|
|
|
|
std::random_device dev;
|
|
|
|
std::mt19937 engine(dev());
|
|
|
|
std::uniform_int_distribution<> distribution(0, SPLASHES.size() - 1);
|
|
|
|
|
|
|
|
m_szCurrentSplash = SPLASHES[distribution(engine)];
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::initServer() {
|
2023-03-24 14:00:54 +01:00
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
m_sWLDisplay = wl_display_create();
|
|
|
|
|
2022-07-13 18:18:23 +02:00
|
|
|
m_sWLEventLoop = wl_display_get_event_loop(m_sWLDisplay);
|
|
|
|
|
|
|
|
// register crit signal handler
|
|
|
|
wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
|
2024-02-23 00:10:59 +01:00
|
|
|
|
|
|
|
if (!envEnabled("HYPRLAND_NO_CRASHREPORTER")) {
|
|
|
|
signal(SIGSEGV, handleUnrecoverableSignal);
|
|
|
|
signal(SIGABRT, handleUnrecoverableSignal);
|
|
|
|
}
|
2023-09-29 17:38:13 +02:00
|
|
|
signal(SIGUSR1, handleUserSignal);
|
2022-07-13 18:18:23 +02:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
initManagers(STAGE_PRIORITY);
|
|
|
|
|
2023-12-21 22:27:12 +01:00
|
|
|
if (envEnabled("HYPRLAND_TRACE"))
|
2023-08-21 19:36:09 +02:00
|
|
|
Debug::trace = true;
|
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
wlr_log_init(WLR_INFO, NULL);
|
|
|
|
|
2023-12-21 22:27:12 +01:00
|
|
|
if (envEnabled("HYPRLAND_LOG_WLR"))
|
2023-03-05 14:37:21 +01:00
|
|
|
wlr_log_init(WLR_DEBUG, Debug::wlrLog);
|
2023-09-30 14:07:20 +02:00
|
|
|
else
|
|
|
|
wlr_log_init(WLR_ERROR, Debug::wlrLog);
|
2023-03-05 14:37:21 +01:00
|
|
|
|
2024-01-27 14:58:13 +01:00
|
|
|
m_sWLRBackend = wlr_backend_autocreate(m_sWLEventLoop, &m_sWLRSession);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
|
|
|
if (!m_sWLRBackend) {
|
2024-01-22 09:46:41 +01:00
|
|
|
Debug::log(CRIT, "m_sWLRBackend was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
2023-08-20 11:47:06 +02:00
|
|
|
throwError("wlr_backend_autocreate() failed!");
|
2022-03-16 21:37:21 +01:00
|
|
|
}
|
|
|
|
|
2024-03-15 15:28:14 +01:00
|
|
|
bool isHeadlessOnly = true;
|
|
|
|
wlr_multi_for_each_backend(
|
|
|
|
m_sWLRBackend,
|
|
|
|
[](wlr_backend* backend, void* isHeadlessOnly) {
|
|
|
|
if (!wlr_backend_is_headless(backend))
|
|
|
|
*(bool*)isHeadlessOnly = false;
|
|
|
|
},
|
|
|
|
&isHeadlessOnly);
|
|
|
|
|
|
|
|
if (isHeadlessOnly) {
|
|
|
|
m_sWLRRenderer = wlr_renderer_autocreate(m_sWLRBackend);
|
|
|
|
} else {
|
|
|
|
m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend);
|
|
|
|
if (m_iDRMFD < 0) {
|
|
|
|
Debug::log(CRIT, "Couldn't query the DRM FD!");
|
|
|
|
throwError("wlr_backend_get_drm_fd() failed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
|
2022-03-24 15:57:46 +01:00
|
|
|
}
|
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
if (!m_sWLRRenderer) {
|
2024-01-22 09:46:41 +01:00
|
|
|
Debug::log(CRIT, "m_sWLRRenderer was NULL! This usually means wlroots could not find a GPU or enountered some issues.");
|
2023-08-20 11:47:06 +02:00
|
|
|
throwError("wlr_gles2_renderer_create_with_drm_fd() failed!");
|
2022-03-16 21:37:21 +01:00
|
|
|
}
|
|
|
|
|
2022-11-05 13:50:47 +01:00
|
|
|
wlr_renderer_init_wl_shm(m_sWLRRenderer, m_sWLDisplay);
|
|
|
|
|
|
|
|
if (wlr_renderer_get_dmabuf_texture_formats(m_sWLRRenderer)) {
|
2022-12-01 22:00:54 +01:00
|
|
|
if (wlr_renderer_get_drm_fd(m_sWLRRenderer) >= 0)
|
2022-11-05 13:50:47 +01:00
|
|
|
wlr_drm_create(m_sWLDisplay, m_sWLRRenderer);
|
|
|
|
|
2022-12-01 22:00:54 +01:00
|
|
|
m_sWLRLinuxDMABuf = wlr_linux_dmabuf_v1_create_with_renderer(m_sWLDisplay, 4, m_sWLRRenderer);
|
2022-11-05 13:50:47 +01:00
|
|
|
}
|
2022-03-17 19:03:15 +01:00
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
m_sWLRAllocator = wlr_allocator_autocreate(m_sWLRBackend, m_sWLRRenderer);
|
|
|
|
|
|
|
|
if (!m_sWLRAllocator) {
|
|
|
|
Debug::log(CRIT, "m_sWLRAllocator was NULL!");
|
2023-08-20 11:47:06 +02:00
|
|
|
throwError("wlr_allocator_autocreate() failed!");
|
2022-03-16 21:37:21 +01:00
|
|
|
}
|
|
|
|
|
2022-03-24 17:17:08 +01:00
|
|
|
m_sWLREGL = wlr_gles2_renderer_get_egl(m_sWLRRenderer);
|
|
|
|
|
|
|
|
if (!m_sWLREGL) {
|
|
|
|
Debug::log(CRIT, "m_sWLREGL was NULL!");
|
2023-08-20 11:47:06 +02:00
|
|
|
throwError("wlr_gles2_renderer_get_egl() failed!");
|
2022-03-24 17:17:08 +01:00
|
|
|
}
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2023-04-21 16:40:35 +02:00
|
|
|
m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, 6, m_sWLRRenderer);
|
2022-03-17 19:03:15 +01:00
|
|
|
m_sWLRSubCompositor = wlr_subcompositor_create(m_sWLDisplay);
|
2022-12-16 18:17:31 +01:00
|
|
|
m_sWLRDataDevMgr = wlr_data_device_manager_create(m_sWLDisplay);
|
2022-03-17 19:03:15 +01:00
|
|
|
|
2022-03-19 14:09:11 +01:00
|
|
|
wlr_export_dmabuf_manager_v1_create(m_sWLDisplay);
|
|
|
|
wlr_data_control_manager_v1_create(m_sWLDisplay);
|
|
|
|
wlr_primary_selection_v1_device_manager_create(m_sWLDisplay);
|
2022-08-28 10:14:43 +02:00
|
|
|
wlr_viewporter_create(m_sWLDisplay);
|
2022-03-19 14:09:11 +01:00
|
|
|
|
2023-06-14 13:26:47 +02:00
|
|
|
m_sWLRGammaCtrlMgr = wlr_gamma_control_manager_v1_create(m_sWLDisplay);
|
|
|
|
|
2023-11-30 02:18:55 +01:00
|
|
|
m_sWLROutputLayout = wlr_output_layout_create(m_sWLDisplay);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2022-07-30 22:41:24 +02:00
|
|
|
m_sWLROutputPowerMgr = wlr_output_power_manager_v1_create(m_sWLDisplay);
|
|
|
|
|
2023-12-23 22:30:49 +01:00
|
|
|
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 6);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
|
|
|
m_sWLRCursor = wlr_cursor_create();
|
|
|
|
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
|
|
|
|
2022-03-22 18:29:13 +01:00
|
|
|
m_sSeat.seat = wlr_seat_create(m_sWLDisplay, "seat0");
|
2022-03-17 19:03:15 +01:00
|
|
|
|
2022-03-17 20:22:29 +01:00
|
|
|
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
|
|
|
|
|
2023-07-13 18:05:34 +02:00
|
|
|
m_sWLRIdleNotifier = wlr_idle_notifier_v1_create(m_sWLDisplay);
|
2022-03-19 13:54:24 +01:00
|
|
|
|
2022-11-19 17:28:04 +01:00
|
|
|
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay, 4);
|
2022-03-19 13:54:24 +01:00
|
|
|
|
2022-05-10 11:01:03 +02:00
|
|
|
m_sWLRServerDecoMgr = wlr_server_decoration_manager_create(m_sWLDisplay);
|
2022-12-16 18:17:31 +01:00
|
|
|
m_sWLRXDGDecoMgr = wlr_xdg_decoration_manager_v1_create(m_sWLDisplay);
|
2022-05-10 11:01:03 +02:00
|
|
|
wlr_server_decoration_manager_set_default_mode(m_sWLRServerDecoMgr, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
|
2022-03-19 13:54:24 +01:00
|
|
|
|
2023-07-18 15:30:28 +02:00
|
|
|
m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay);
|
2022-03-22 18:29:13 +01:00
|
|
|
|
|
|
|
m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay);
|
2022-04-11 19:51:37 +02:00
|
|
|
|
2022-04-17 21:40:04 +02:00
|
|
|
m_sWLRPointerConstraints = wlr_pointer_constraints_v1_create(m_sWLDisplay);
|
|
|
|
|
|
|
|
m_sWLRRelPointerMgr = wlr_relative_pointer_manager_v1_create(m_sWLDisplay);
|
2022-04-27 17:29:33 +02:00
|
|
|
|
|
|
|
m_sWLRVKeyboardMgr = wlr_virtual_keyboard_manager_v1_create(m_sWLDisplay);
|
2022-05-12 12:13:02 +02:00
|
|
|
|
|
|
|
m_sWLRVirtPtrMgr = wlr_virtual_pointer_manager_v1_create(m_sWLDisplay);
|
2022-05-29 11:24:42 +02:00
|
|
|
|
|
|
|
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
|
2022-06-08 14:29:49 +02:00
|
|
|
|
2022-08-27 23:10:13 +02:00
|
|
|
m_sWRLDRMLeaseMgr = wlr_drm_lease_v1_manager_create(m_sWLDisplay, m_sWLRBackend);
|
2022-08-27 23:24:36 +02:00
|
|
|
if (!m_sWRLDRMLeaseMgr) {
|
|
|
|
Debug::log(INFO, "Failed to create wlr_drm_lease_v1_manager");
|
2022-08-27 23:10:13 +02:00
|
|
|
Debug::log(INFO, "VR will not be available");
|
2022-08-27 23:24:36 +02:00
|
|
|
}
|
2022-08-27 23:10:13 +02:00
|
|
|
|
2022-06-08 14:29:49 +02:00
|
|
|
m_sWLRTabletManager = wlr_tablet_v2_create(m_sWLDisplay);
|
2022-06-29 22:23:51 +02:00
|
|
|
|
|
|
|
m_sWLRForeignRegistry = wlr_xdg_foreign_registry_create(m_sWLDisplay);
|
|
|
|
|
2022-07-06 15:42:37 +02:00
|
|
|
m_sWLRIdleInhibitMgr = wlr_idle_inhibit_v1_create(m_sWLDisplay);
|
|
|
|
|
2022-06-29 22:23:51 +02:00
|
|
|
wlr_xdg_foreign_v1_create(m_sWLDisplay, m_sWLRForeignRegistry);
|
|
|
|
wlr_xdg_foreign_v2_create(m_sWLDisplay, m_sWLRForeignRegistry);
|
2022-07-07 11:52:12 +02:00
|
|
|
|
|
|
|
m_sWLRPointerGestures = wlr_pointer_gestures_v1_create(m_sWLDisplay);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2022-08-05 13:03:37 +02:00
|
|
|
m_sWLRTextInputMgr = wlr_text_input_manager_v3_create(m_sWLDisplay);
|
|
|
|
|
|
|
|
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
|
2022-10-22 17:43:47 +02:00
|
|
|
|
|
|
|
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
|
2022-11-05 19:04:44 +01:00
|
|
|
|
2024-01-27 14:58:13 +01:00
|
|
|
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop);
|
2022-11-05 19:04:44 +01:00
|
|
|
|
2023-02-03 12:58:55 +01:00
|
|
|
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
|
|
|
|
|
2023-07-24 18:50:17 +02:00
|
|
|
m_sWLRCursorShapeMgr = wlr_cursor_shape_manager_v1_create(m_sWLDisplay, 1);
|
|
|
|
|
2023-09-28 22:48:33 +02:00
|
|
|
m_sWLRTearingControlMgr = wlr_tearing_control_manager_v1_create(m_sWLDisplay, 1);
|
|
|
|
|
2022-11-05 19:04:44 +01:00
|
|
|
if (!m_sWLRHeadlessBackend) {
|
|
|
|
Debug::log(CRIT, "Couldn't create the headless backend");
|
2023-08-20 11:47:06 +02:00
|
|
|
throwError("wlr_headless_backend_create() failed!");
|
2022-11-05 19:04:44 +01:00
|
|
|
}
|
|
|
|
|
2023-02-16 13:55:46 +01:00
|
|
|
wlr_single_pixel_buffer_manager_v1_create(m_sWLDisplay);
|
|
|
|
|
2022-11-05 19:04:44 +01:00
|
|
|
wlr_multi_backend_add(m_sWLRBackend, m_sWLRHeadlessBackend);
|
2022-07-10 15:41:26 +02:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
initManagers(STAGE_LATE);
|
2022-07-10 15:41:26 +02:00
|
|
|
}
|
|
|
|
|
2022-03-18 23:52:36 +01:00
|
|
|
void CCompositor::initAllSignals() {
|
2022-03-28 16:10:30 +02:00
|
|
|
addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend");
|
2023-11-30 02:18:55 +01:00
|
|
|
addWLSignal(&m_sWLRXDGShell->events.new_toplevel, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell");
|
2022-03-28 16:10:30 +02:00
|
|
|
addWLSignal(&m_sWLRCursor->events.motion, &Events::listen_mouseMove, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.motion_absolute, &Events::listen_mouseMoveAbsolute, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.axis, &Events::listen_mouseAxis, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.frame, &Events::listen_mouseFrame, m_sWLRCursor, "WLRCursor");
|
2022-07-07 11:52:12 +02:00
|
|
|
addWLSignal(&m_sWLRCursor->events.swipe_begin, &Events::listen_swipeBegin, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.swipe_update, &Events::listen_swipeUpdate, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.swipe_end, &Events::listen_swipeEnd, m_sWLRCursor, "WLRCursor");
|
2022-07-16 16:12:31 +02:00
|
|
|
addWLSignal(&m_sWLRCursor->events.pinch_begin, &Events::listen_pinchBegin, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.pinch_update, &Events::listen_pinchUpdate, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.pinch_end, &Events::listen_pinchEnd, m_sWLRCursor, "WLRCursor");
|
2022-08-07 21:17:03 +02:00
|
|
|
addWLSignal(&m_sWLRCursor->events.touch_down, &Events::listen_touchBegin, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.touch_up, &Events::listen_touchEnd, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.touch_motion, &Events::listen_touchUpdate, m_sWLRCursor, "WLRCursor");
|
2022-09-22 22:14:02 +02:00
|
|
|
addWLSignal(&m_sWLRCursor->events.touch_frame, &Events::listen_touchFrame, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.hold_begin, &Events::listen_holdBegin, m_sWLRCursor, "WLRCursor");
|
|
|
|
addWLSignal(&m_sWLRCursor->events.hold_end, &Events::listen_holdEnd, m_sWLRCursor, "WLRCursor");
|
2022-03-28 16:10:30 +02:00
|
|
|
addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend");
|
|
|
|
addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat");
|
|
|
|
addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat");
|
|
|
|
addWLSignal(&m_sSeat.seat->events.request_start_drag, &Events::listen_requestDrag, &m_sSeat, "Seat");
|
2022-03-31 17:25:23 +02:00
|
|
|
addWLSignal(&m_sSeat.seat->events.start_drag, &Events::listen_startDrag, &m_sSeat, "Seat");
|
2022-07-17 18:56:01 +02:00
|
|
|
addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat");
|
|
|
|
addWLSignal(&m_sSeat.seat->events.request_set_primary_selection, &Events::listen_requestSetPrimarySel, &m_sSeat, "Seat");
|
2022-03-28 16:10:30 +02:00
|
|
|
addWLSignal(&m_sWLRLayerShell->events.new_surface, &Events::listen_newLayerSurface, m_sWLRLayerShell, "LayerShell");
|
|
|
|
addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout");
|
|
|
|
addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr");
|
|
|
|
addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr");
|
2022-04-17 21:40:04 +02:00
|
|
|
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
|
2022-05-10 11:01:03 +02:00
|
|
|
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
|
2022-05-12 12:13:02 +02:00
|
|
|
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
|
2022-08-05 16:21:08 +02:00
|
|
|
addWLSignal(&m_sWLRVKeyboardMgr->events.new_virtual_keyboard, &Events::listen_newVirtualKeyboard, m_sWLRVKeyboardMgr, "VKeyboardMgr");
|
2022-06-06 13:48:17 +02:00
|
|
|
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
|
2022-07-06 15:42:37 +02:00
|
|
|
addWLSignal(&m_sWLRIdleInhibitMgr->events.new_inhibitor, &Events::listen_newIdleInhibitor, m_sWLRIdleInhibitMgr, "WLRIdleInhibitMgr");
|
2022-07-30 22:41:24 +02:00
|
|
|
addWLSignal(&m_sWLROutputPowerMgr->events.set_mode, &Events::listen_powerMgrSetMode, m_sWLROutputPowerMgr, "PowerMgr");
|
2022-08-05 13:03:37 +02:00
|
|
|
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr");
|
|
|
|
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr");
|
2022-10-22 17:43:47 +02:00
|
|
|
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
|
2023-02-03 12:58:55 +01:00
|
|
|
addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr");
|
2023-06-14 13:26:47 +02:00
|
|
|
addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr");
|
2023-07-24 18:50:17 +02:00
|
|
|
addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr");
|
2023-09-28 22:48:33 +02:00
|
|
|
addWLSignal(&m_sWLRTearingControlMgr->events.new_object, &Events::listen_newTearingHint, m_sWLRTearingControlMgr, "TearingControlMgr");
|
2024-02-28 00:14:56 +01:00
|
|
|
addWLSignal(&m_sWLRKbShInhibitMgr->events.new_inhibitor, &Events::listen_newShortcutInhibitor, m_sWLRKbShInhibitMgr, "ShortcutInhibitMgr");
|
2022-08-05 13:03:37 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
if (m_sWRLDRMLeaseMgr)
|
2022-08-27 23:10:13 +02:00
|
|
|
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
|
|
|
|
|
2022-07-13 18:31:09 +02:00
|
|
|
if (m_sWLRSession)
|
|
|
|
addWLSignal(&m_sWLRSession->events.active, &Events::listen_sessionActive, m_sWLRSession, "Session");
|
2022-04-21 15:59:28 +02:00
|
|
|
}
|
|
|
|
|
2024-01-19 16:20:22 +01:00
|
|
|
void CCompositor::removeAllSignals() {
|
|
|
|
removeWLSignal(&Events::listen_newOutput);
|
|
|
|
removeWLSignal(&Events::listen_newXDGToplevel);
|
|
|
|
removeWLSignal(&Events::listen_mouseMove);
|
|
|
|
removeWLSignal(&Events::listen_mouseMoveAbsolute);
|
|
|
|
removeWLSignal(&Events::listen_mouseButton);
|
|
|
|
removeWLSignal(&Events::listen_mouseAxis);
|
|
|
|
removeWLSignal(&Events::listen_mouseFrame);
|
|
|
|
removeWLSignal(&Events::listen_swipeBegin);
|
|
|
|
removeWLSignal(&Events::listen_swipeUpdate);
|
|
|
|
removeWLSignal(&Events::listen_swipeEnd);
|
|
|
|
removeWLSignal(&Events::listen_pinchBegin);
|
|
|
|
removeWLSignal(&Events::listen_pinchUpdate);
|
|
|
|
removeWLSignal(&Events::listen_pinchEnd);
|
|
|
|
removeWLSignal(&Events::listen_touchBegin);
|
|
|
|
removeWLSignal(&Events::listen_touchEnd);
|
|
|
|
removeWLSignal(&Events::listen_touchUpdate);
|
|
|
|
removeWLSignal(&Events::listen_touchFrame);
|
|
|
|
removeWLSignal(&Events::listen_holdBegin);
|
|
|
|
removeWLSignal(&Events::listen_holdEnd);
|
|
|
|
removeWLSignal(&Events::listen_newInput);
|
|
|
|
removeWLSignal(&Events::listen_requestMouse);
|
|
|
|
removeWLSignal(&Events::listen_requestSetSel);
|
|
|
|
removeWLSignal(&Events::listen_requestDrag);
|
|
|
|
removeWLSignal(&Events::listen_startDrag);
|
|
|
|
removeWLSignal(&Events::listen_requestSetSel);
|
|
|
|
removeWLSignal(&Events::listen_requestSetPrimarySel);
|
|
|
|
removeWLSignal(&Events::listen_newLayerSurface);
|
|
|
|
removeWLSignal(&Events::listen_change);
|
|
|
|
removeWLSignal(&Events::listen_outputMgrApply);
|
|
|
|
removeWLSignal(&Events::listen_outputMgrTest);
|
|
|
|
removeWLSignal(&Events::listen_newConstraint);
|
|
|
|
removeWLSignal(&Events::listen_NewXDGDeco);
|
|
|
|
removeWLSignal(&Events::listen_newVirtPtr);
|
|
|
|
removeWLSignal(&Events::listen_newVirtualKeyboard);
|
|
|
|
removeWLSignal(&Events::listen_RendererDestroy);
|
|
|
|
removeWLSignal(&Events::listen_newIdleInhibitor);
|
|
|
|
removeWLSignal(&Events::listen_powerMgrSetMode);
|
|
|
|
removeWLSignal(&Events::listen_newIME);
|
|
|
|
removeWLSignal(&Events::listen_newTextInput);
|
|
|
|
removeWLSignal(&Events::listen_activateXDG);
|
|
|
|
removeWLSignal(&Events::listen_newSessionLock);
|
|
|
|
removeWLSignal(&Events::listen_setGamma);
|
|
|
|
removeWLSignal(&Events::listen_setCursorShape);
|
|
|
|
removeWLSignal(&Events::listen_newTearingHint);
|
2024-02-28 00:14:56 +01:00
|
|
|
removeWLSignal(&Events::listen_newShortcutInhibitor);
|
2024-01-19 16:20:22 +01:00
|
|
|
|
|
|
|
if (m_sWRLDRMLeaseMgr)
|
|
|
|
removeWLSignal(&Events::listen_leaseRequest);
|
|
|
|
|
|
|
|
if (m_sWLRSession)
|
|
|
|
removeWLSignal(&Events::listen_sessionActive);
|
|
|
|
}
|
|
|
|
|
2022-07-13 18:18:23 +02:00
|
|
|
void CCompositor::cleanup() {
|
2022-08-25 21:35:47 +02:00
|
|
|
if (!m_sWLDisplay || m_bIsShuttingDown)
|
2022-04-21 15:59:28 +02:00
|
|
|
return;
|
|
|
|
|
2024-02-23 17:48:27 +01:00
|
|
|
signal(SIGABRT, SIG_DFL);
|
|
|
|
signal(SIGSEGV, SIG_DFL);
|
|
|
|
|
2023-08-08 16:16:34 +02:00
|
|
|
removeLockFile();
|
|
|
|
|
2023-12-06 15:46:18 +01:00
|
|
|
m_bIsShuttingDown = true;
|
|
|
|
Debug::shuttingDown = true;
|
2022-10-24 01:14:42 +02:00
|
|
|
|
2023-07-06 15:24:49 +02:00
|
|
|
#ifdef USES_SYSTEMD
|
2023-12-21 22:27:12 +01:00
|
|
|
if (sd_booted() > 0 && !envEnabled("HYPRLAND_NO_SD_NOTIFY"))
|
2023-07-06 15:24:49 +02:00
|
|
|
sd_notify(0, "STOPPING=1");
|
|
|
|
#endif
|
|
|
|
|
2023-03-01 00:11:49 +01:00
|
|
|
// unload all remaining plugins while the compositor is
|
|
|
|
// still in a normal working state.
|
|
|
|
g_pPluginSystem->unloadAllPlugins();
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
m_pLastFocus = nullptr;
|
2022-05-29 00:07:31 +02:00
|
|
|
m_pLastWindow = nullptr;
|
|
|
|
|
2022-08-28 11:19:08 +02:00
|
|
|
// end threads
|
|
|
|
g_pEventManager->m_tThread = std::thread();
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
m_vWorkspaces.clear();
|
|
|
|
m_vWindows.clear();
|
2022-05-29 00:00:47 +02:00
|
|
|
|
2022-08-25 21:35:47 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
2022-08-22 14:17:25 +02:00
|
|
|
g_pHyprOpenGL->destroyMonitorResources(m.get());
|
|
|
|
|
2024-01-28 02:57:13 +01:00
|
|
|
wlr_output_state_set_enabled(m->state.wlr(), false);
|
|
|
|
m->state.commit();
|
2022-08-25 21:35:47 +02:00
|
|
|
}
|
|
|
|
|
2022-10-06 19:43:50 +02:00
|
|
|
m_vMonitors.clear();
|
|
|
|
|
2022-04-21 15:59:28 +02:00
|
|
|
if (g_pXWaylandManager->m_sWLRXWayland) {
|
|
|
|
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
|
|
|
|
g_pXWaylandManager->m_sWLRXWayland = nullptr;
|
|
|
|
}
|
|
|
|
|
2024-04-08 16:32:31 +02:00
|
|
|
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
2024-01-19 16:20:22 +01:00
|
|
|
removeAllSignals();
|
|
|
|
|
2024-02-24 03:50:54 +01:00
|
|
|
g_pInputManager.reset();
|
2024-01-19 16:20:22 +01:00
|
|
|
g_pDecorationPositioner.reset();
|
2024-03-09 17:52:59 +01:00
|
|
|
g_pCursorManager.reset();
|
2024-01-19 16:20:22 +01:00
|
|
|
g_pPluginSystem.reset();
|
|
|
|
g_pHyprNotificationOverlay.reset();
|
|
|
|
g_pDebugOverlay.reset();
|
|
|
|
g_pEventManager.reset();
|
|
|
|
g_pSessionLockManager.reset();
|
|
|
|
g_pProtocolManager.reset();
|
|
|
|
g_pHyprRenderer.reset();
|
|
|
|
g_pHyprOpenGL.reset();
|
|
|
|
g_pThreadManager.reset();
|
|
|
|
g_pConfigManager.reset();
|
|
|
|
g_pLayoutManager.reset();
|
|
|
|
g_pHyprError.reset();
|
|
|
|
g_pConfigManager.reset();
|
|
|
|
g_pAnimationManager.reset();
|
|
|
|
g_pKeybindManager.reset();
|
|
|
|
g_pHookSystem.reset();
|
|
|
|
g_pWatchdog.reset();
|
|
|
|
g_pXWaylandManager.reset();
|
|
|
|
|
2022-07-13 18:18:23 +02:00
|
|
|
wl_display_terminate(m_sWLDisplay);
|
2022-04-21 15:59:28 +02:00
|
|
|
|
2023-03-09 15:19:41 +01:00
|
|
|
m_sWLDisplay = nullptr;
|
2022-03-18 23:52:36 +01:00
|
|
|
}
|
2022-03-17 17:08:54 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
void CCompositor::initManagers(eManagersInitStage stage) {
|
|
|
|
switch (stage) {
|
|
|
|
case STAGE_PRIORITY: {
|
2024-04-07 04:31:51 +02:00
|
|
|
Debug::log(LOG, "Creating the EventLoopManager!");
|
|
|
|
g_pEventLoopManager = std::make_unique<CEventLoopManager>();
|
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the HookSystem!");
|
|
|
|
g_pHookSystem = std::make_unique<CHookSystemManager>();
|
2022-03-19 17:48:18 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the KeybindManager!");
|
|
|
|
g_pKeybindManager = std::make_unique<CKeybindManager>();
|
2022-04-23 21:47:16 +02:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the AnimationManager!");
|
|
|
|
g_pAnimationManager = std::make_unique<CAnimationManager>();
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the ConfigManager!");
|
|
|
|
g_pConfigManager = std::make_unique<CConfigManager>();
|
2022-03-17 17:08:54 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the CHyprError!");
|
|
|
|
g_pHyprError = std::make_unique<CHyprError>();
|
2023-01-20 20:48:07 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the LayoutManager!");
|
|
|
|
g_pLayoutManager = std::make_unique<CLayoutManager>();
|
2022-03-17 17:08:54 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
g_pConfigManager->init();
|
2023-09-29 18:04:20 +02:00
|
|
|
g_pWatchdog = std::make_unique<CWatchdog>(); // requires config
|
2023-03-05 14:37:21 +01:00
|
|
|
} break;
|
|
|
|
case STAGE_LATE: {
|
|
|
|
Debug::log(LOG, "Creating the ThreadManager!");
|
|
|
|
g_pThreadManager = std::make_unique<CThreadManager>();
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2024-02-05 02:43:45 +01:00
|
|
|
Debug::log(LOG, "Creating CHyprCtl");
|
|
|
|
g_pHyprCtl = std::make_unique<CHyprCtl>();
|
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the InputManager!");
|
|
|
|
g_pInputManager = std::make_unique<CInputManager>();
|
2022-04-04 19:44:25 +02:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the CHyprOpenGLImpl!");
|
|
|
|
g_pHyprOpenGL = std::make_unique<CHyprOpenGLImpl>();
|
2022-03-18 20:03:39 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the HyprRenderer!");
|
|
|
|
g_pHyprRenderer = std::make_unique<CHyprRenderer>();
|
2022-03-19 15:59:53 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the XWaylandManager!");
|
|
|
|
g_pXWaylandManager = std::make_unique<CHyprXWaylandManager>();
|
2022-12-05 18:05:15 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the ProtocolManager!");
|
|
|
|
g_pProtocolManager = std::make_unique<CProtocolManager>();
|
2023-02-03 12:58:55 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the SessionLockManager!");
|
|
|
|
g_pSessionLockManager = std::make_unique<CSessionLockManager>();
|
2022-05-28 17:32:19 +02:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the EventManager!");
|
|
|
|
g_pEventManager = std::make_unique<CEventManager>();
|
|
|
|
g_pEventManager->startThread();
|
2023-02-27 13:32:38 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the HyprDebugOverlay!");
|
|
|
|
g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
|
2023-02-27 13:32:38 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the HyprNotificationOverlay!");
|
|
|
|
g_pHyprNotificationOverlay = std::make_unique<CHyprNotificationOverlay>();
|
2022-03-17 17:08:54 +01:00
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
Debug::log(LOG, "Creating the PluginSystem!");
|
|
|
|
g_pPluginSystem = std::make_unique<CPluginSystem>();
|
2023-05-01 16:10:53 +02:00
|
|
|
g_pConfigManager->handlePluginLoads();
|
2023-11-11 15:37:17 +01:00
|
|
|
|
|
|
|
Debug::log(LOG, "Creating the DecorationPositioner!");
|
|
|
|
g_pDecorationPositioner = std::make_unique<CDecorationPositioner>();
|
2024-03-09 17:52:59 +01:00
|
|
|
|
|
|
|
Debug::log(LOG, "Creating the CursorManager!");
|
|
|
|
g_pCursorManager = std::make_unique<CCursorManager>();
|
2023-03-05 14:37:21 +01:00
|
|
|
} break;
|
|
|
|
default: UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
2022-08-01 23:31:25 +02:00
|
|
|
|
2023-08-08 16:16:34 +02:00
|
|
|
void CCompositor::createLockFile() {
|
|
|
|
const auto PATH = "/tmp/hypr/" + m_szInstanceSignature + ".lock";
|
|
|
|
|
|
|
|
std::ofstream ofs(PATH, std::ios::trunc);
|
|
|
|
|
|
|
|
ofs << m_iHyprlandPID << "\n" << m_szWLDisplaySocket << "\n";
|
|
|
|
|
|
|
|
ofs.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::removeLockFile() {
|
|
|
|
const auto PATH = "/tmp/hypr/" + m_szInstanceSignature + ".lock";
|
|
|
|
|
|
|
|
if (std::filesystem::exists(PATH))
|
|
|
|
std::filesystem::remove(PATH);
|
|
|
|
}
|
|
|
|
|
2023-11-01 19:53:36 +01:00
|
|
|
void CCompositor::prepareFallbackOutput() {
|
|
|
|
// create a backup monitor
|
|
|
|
wlr_backend* headless = nullptr;
|
|
|
|
wlr_multi_for_each_backend(
|
|
|
|
m_sWLRBackend,
|
|
|
|
[](wlr_backend* b, void* data) {
|
|
|
|
if (wlr_backend_is_headless(b))
|
|
|
|
*((wlr_backend**)data) = b;
|
|
|
|
},
|
|
|
|
&headless);
|
|
|
|
|
|
|
|
if (!headless) {
|
|
|
|
Debug::log(WARN, "Unsafe state will be ineffective, no fallback output");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wlr_headless_add_output(headless, 1920, 1080);
|
|
|
|
}
|
|
|
|
|
2023-03-05 14:37:21 +01:00
|
|
|
void CCompositor::startCompositor() {
|
2022-03-18 23:52:36 +01:00
|
|
|
initAllSignals();
|
|
|
|
|
2022-12-05 18:21:09 +01:00
|
|
|
// get socket, avoid using 0
|
|
|
|
for (int candidate = 1; candidate <= 32; candidate++) {
|
2023-01-19 16:44:23 +01:00
|
|
|
const auto CANDIDATESTR = ("wayland-" + std::to_string(candidate));
|
|
|
|
const auto RETVAL = wl_display_add_socket(m_sWLDisplay, CANDIDATESTR.c_str());
|
|
|
|
if (RETVAL >= 0) {
|
|
|
|
m_szWLDisplaySocket = CANDIDATESTR;
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(LOG, "wl_display_add_socket for {} succeeded with {}", CANDIDATESTR, RETVAL);
|
2022-12-05 18:21:09 +01:00
|
|
|
break;
|
2023-01-19 16:44:23 +01:00
|
|
|
} else {
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(WARN, "wl_display_add_socket for {} returned {}: skipping candidate {}", CANDIDATESTR, RETVAL, candidate);
|
2022-12-05 18:21:09 +01:00
|
|
|
}
|
|
|
|
}
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2023-01-19 16:44:23 +01:00
|
|
|
if (m_szWLDisplaySocket.empty()) {
|
|
|
|
Debug::log(WARN, "All candidates failed, trying wl_display_add_socket_auto");
|
|
|
|
const auto SOCKETSTR = wl_display_add_socket_auto(m_sWLDisplay);
|
|
|
|
if (SOCKETSTR)
|
|
|
|
m_szWLDisplaySocket = SOCKETSTR;
|
|
|
|
}
|
|
|
|
|
2022-12-05 18:21:09 +01:00
|
|
|
if (m_szWLDisplaySocket.empty()) {
|
2022-03-16 21:37:21 +01:00
|
|
|
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
|
2022-03-17 19:03:15 +01:00
|
|
|
wlr_backend_destroy(m_sWLRBackend);
|
2023-08-20 13:58:46 +02:00
|
|
|
throwError("m_szWLDisplaySocket was null! (wl_display_add_socket and wl_display_add_socket_auto failed)");
|
2022-03-16 21:37:21 +01:00
|
|
|
}
|
|
|
|
|
2022-12-05 18:21:09 +01:00
|
|
|
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
2023-12-26 18:16:59 +01:00
|
|
|
if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */) {
|
|
|
|
const auto CMD =
|
2023-04-15 21:03:09 +02:00
|
|
|
#ifdef USES_SYSTEMD
|
2023-12-26 18:16:59 +01:00
|
|
|
"systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash "
|
|
|
|
"dbus-update-activation-environment 2>/dev/null && "
|
2023-04-15 21:03:09 +02:00
|
|
|
#endif
|
2023-12-26 18:16:59 +01:00
|
|
|
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME";
|
|
|
|
g_pKeybindManager->spawn(CMD);
|
|
|
|
}
|
2022-11-04 11:37:14 +01:00
|
|
|
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket);
|
2022-03-16 21:37:21 +01:00
|
|
|
|
|
|
|
if (!wlr_backend_start(m_sWLRBackend)) {
|
|
|
|
Debug::log(CRIT, "Backend did not start!");
|
2022-03-17 19:03:15 +01:00
|
|
|
wlr_backend_destroy(m_sWLRBackend);
|
|
|
|
wl_display_destroy(m_sWLDisplay);
|
2023-08-20 13:58:46 +02:00
|
|
|
throwError("The backend could not start!");
|
2022-03-16 21:37:21 +01:00
|
|
|
}
|
|
|
|
|
2023-11-01 19:53:36 +01:00
|
|
|
prepareFallbackOutput();
|
|
|
|
|
2023-09-29 18:51:07 +02:00
|
|
|
g_pHyprRenderer->setCursorFromName("left_ptr");
|
2022-03-16 21:37:21 +01:00
|
|
|
|
2023-01-05 20:17:55 +01:00
|
|
|
#ifdef USES_SYSTEMD
|
2023-12-21 22:27:12 +01:00
|
|
|
if (sd_booted() > 0) {
|
2023-01-05 20:17:55 +01:00
|
|
|
// tell systemd that we are ready so it can start other bond, following, related units
|
2023-12-21 22:27:12 +01:00
|
|
|
if (!envEnabled("HYPRLAND_NO_SD_NOTIFY"))
|
|
|
|
sd_notify(0, "READY=1");
|
|
|
|
} else
|
2023-01-05 20:17:55 +01:00
|
|
|
Debug::log(LOG, "systemd integration is baked in but system itself is not booted à la systemd!");
|
|
|
|
#endif
|
|
|
|
|
2023-08-08 16:16:34 +02:00
|
|
|
createLockFile();
|
|
|
|
|
2022-03-16 21:37:21 +01:00
|
|
|
// This blocks until we are done.
|
|
|
|
Debug::log(LOG, "Hyprland is ready, running the event loop!");
|
2024-04-07 04:31:51 +02:00
|
|
|
g_pEventLoopManager->enterLoop(m_sWLDisplay, m_sWLEventLoop);
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* CCompositor::getMonitorFromID(const int& id) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
|
|
|
if (m->ID == (uint64_t)id) {
|
|
|
|
return m.get();
|
2022-03-17 20:22:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* CCompositor::getMonitorFromName(const std::string& name) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
|
|
|
if (m->szName == name) {
|
2023-07-09 23:10:35 +02:00
|
|
|
return m.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) {
|
|
|
|
for (auto& m : m_vMonitors) {
|
2023-11-30 02:48:10 +01:00
|
|
|
if (m->szDescription.starts_with(desc))
|
2022-06-30 15:44:26 +02:00
|
|
|
return m.get();
|
2022-05-29 20:15:34 +02:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* CCompositor::getMonitorFromCursor() {
|
2022-03-19 20:30:21 +01:00
|
|
|
const auto COORDS = Vector2D(m_sWLRCursor->x, m_sWLRCursor->y);
|
2022-03-17 20:22:29 +01:00
|
|
|
|
2022-05-25 18:40:03 +02:00
|
|
|
return getMonitorFromVector(COORDS);
|
2022-03-18 22:35:51 +01:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
|
2022-03-20 11:22:55 +01:00
|
|
|
const auto OUTPUT = wlr_output_layout_output_at(m_sWLROutputLayout, point.x, point.y);
|
|
|
|
|
|
|
|
if (!OUTPUT) {
|
2022-12-16 18:17:31 +01:00
|
|
|
float bestDistance = 0.f;
|
|
|
|
CMonitor* pBestMon = nullptr;
|
2022-05-25 18:40:03 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
|
|
|
float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize);
|
2022-05-25 18:40:03 +02:00
|
|
|
|
|
|
|
if (dist < bestDistance || !pBestMon) {
|
|
|
|
bestDistance = dist;
|
2022-12-16 18:17:31 +01:00
|
|
|
pBestMon = m.get();
|
2022-05-25 18:40:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pBestMon) { // ?????
|
|
|
|
Debug::log(WARN, "getMonitorFromVector no close mon???");
|
2022-06-30 15:44:26 +02:00
|
|
|
return m_vMonitors.front().get();
|
2022-05-25 18:40:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return pBestMon;
|
2022-03-20 11:22:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return getMonitorFromOutput(OUTPUT);
|
|
|
|
}
|
|
|
|
|
2022-03-18 22:35:51 +01:00
|
|
|
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
|
2024-04-06 15:51:35 +02:00
|
|
|
if (windowExists(pWindow) && !pWindow->m_bFadingOut) {
|
2022-12-07 15:32:24 +01:00
|
|
|
std::erase_if(m_vWindows, [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; });
|
2024-04-06 15:51:35 +02:00
|
|
|
std::erase_if(m_vWindowsFadingOut, [&](CWindow* el) { return el == pWindow; });
|
|
|
|
}
|
2022-03-18 22:53:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CCompositor::windowExists(CWindow* pWindow) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (w.get() == pWindow)
|
2022-03-18 22:53:27 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-04-02 02:15:58 +02:00
|
|
|
// FIXME: this is here only temporarily,
|
|
|
|
// remove this func altogether if no reports
|
|
|
|
// of this being hit.
|
|
|
|
RASSERT(!pWindow, "windowExists: attempted UAF");
|
|
|
|
|
2022-03-18 22:53:27 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-02-07 01:18:47 +01:00
|
|
|
bool CCompositor::monitorExists(CMonitor* pMonitor) {
|
|
|
|
for (auto& m : m_vRealMonitors) {
|
|
|
|
if (m.get() == pMonitor)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-02-04 16:40:20 +01:00
|
|
|
CWindow* CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t properties, CWindow* pIgnoreWindow) {
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto PMONITOR = getMonitorFromVector(pos);
|
|
|
|
static auto PRESIZEONBORDER = CConfigValue<Hyprlang::INT>("general:resize_on_border");
|
|
|
|
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
|
|
|
|
static auto PBORDERGRABEXTEND = CConfigValue<Hyprlang::INT>("general:extend_border_grab_area");
|
|
|
|
static auto PSPECIALFALLTHRU = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
|
|
|
|
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
2022-05-31 14:01:00 +02:00
|
|
|
|
2022-09-10 13:11:02 +02:00
|
|
|
// pinned windows on top of floating regardless
|
2024-02-04 16:40:20 +01:00
|
|
|
if (properties & ALLOW_FLOATING) {
|
|
|
|
for (auto& w : m_vWindows | std::views::reverse) {
|
|
|
|
const auto BB = w->getWindowBoxUnified(properties);
|
|
|
|
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
2024-02-13 19:07:19 +01:00
|
|
|
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
|
|
|
|
w.get() != pIgnoreWindow) {
|
2024-02-04 16:40:20 +01:00
|
|
|
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
|
2023-03-01 15:06:52 +01:00
|
|
|
return w.get();
|
2024-02-04 16:40:20 +01:00
|
|
|
|
|
|
|
if (!w->m_bIsX11) {
|
|
|
|
if (w->hasPopupAt(pos))
|
|
|
|
return w.get();
|
|
|
|
}
|
2022-09-10 13:11:02 +02:00
|
|
|
}
|
2022-09-25 20:07:48 +02:00
|
|
|
}
|
2022-09-10 13:11:02 +02:00
|
|
|
}
|
|
|
|
|
2023-11-18 18:00:24 +01:00
|
|
|
auto windowForWorkspace = [&](bool special) -> CWindow* {
|
2024-02-22 16:42:17 +01:00
|
|
|
auto floating = [&](bool aboveFullscreen) -> CWindow* {
|
2024-02-04 16:40:20 +01:00
|
|
|
for (auto& w : m_vWindows | std::views::reverse) {
|
2023-11-18 18:00:24 +01:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular
|
2023-11-18 18:00:24 +01:00
|
|
|
continue;
|
|
|
|
|
2024-03-03 18:04:39 +01:00
|
|
|
const auto BB = w->getWindowBoxUnified(properties);
|
|
|
|
const auto PWINDOWMONITOR = getMonitorFromID(w->m_iMonitorID);
|
|
|
|
|
|
|
|
// to avoid focusing windows behind special workspaces from other monitors
|
2024-04-02 21:32:39 +02:00
|
|
|
if (!*PSPECIALFALLTHRU && PWINDOWMONITOR && PWINDOWMONITOR->activeSpecialWorkspace && w->m_pWorkspace != PWINDOWMONITOR->activeSpecialWorkspace &&
|
2024-03-03 18:04:39 +01:00
|
|
|
BB.x >= PWINDOWMONITOR->vecPosition.x && BB.y >= PWINDOWMONITOR->vecPosition.y &&
|
|
|
|
BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
2024-04-03 11:09:42 +02:00
|
|
|
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sAdditionalConfigData.noFocus &&
|
2024-02-22 16:42:17 +01:00
|
|
|
w.get() != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) {
|
2024-02-04 16:40:20 +01:00
|
|
|
// OR windows should add focus to parent
|
|
|
|
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
|
|
|
|
continue;
|
2022-10-01 19:25:02 +02:00
|
|
|
|
2024-02-04 16:40:20 +01:00
|
|
|
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) {
|
2023-11-18 18:00:24 +01:00
|
|
|
|
2024-02-04 16:40:20 +01:00
|
|
|
if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) {
|
|
|
|
// Override Redirect
|
|
|
|
return g_pCompositor->m_pLastWindow; // we kinda trick everything here.
|
|
|
|
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
|
|
|
|
}
|
2022-10-01 19:25:02 +02:00
|
|
|
|
2023-11-18 18:00:24 +01:00
|
|
|
return w.get();
|
2024-02-04 16:40:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!w->m_bIsX11) {
|
|
|
|
if (w->hasPopupAt(pos))
|
|
|
|
return w.get();
|
|
|
|
}
|
2023-11-18 18:00:24 +01:00
|
|
|
}
|
2022-10-01 19:25:02 +02:00
|
|
|
}
|
2024-02-22 16:42:17 +01:00
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (properties & ALLOW_FLOATING) {
|
|
|
|
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
|
|
|
auto found = floating(true);
|
|
|
|
if (found)
|
|
|
|
return found;
|
2023-11-18 18:00:24 +01:00
|
|
|
}
|
2022-07-12 09:49:56 +02:00
|
|
|
|
2024-02-04 16:40:20 +01:00
|
|
|
if (properties & FLOATING_ONLY)
|
2024-02-22 16:42:17 +01:00
|
|
|
return floating(false);
|
2024-02-04 16:40:20 +01:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const int64_t WORKSPACEID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID();
|
2023-12-03 13:53:12 +01:00
|
|
|
const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID);
|
|
|
|
|
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow)
|
|
|
|
return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
|
|
|
|
2024-02-22 16:42:17 +01:00
|
|
|
auto found = floating(false);
|
|
|
|
if (found)
|
|
|
|
return found;
|
|
|
|
|
2023-11-18 18:00:24 +01:00
|
|
|
// for windows, we need to check their extensions too, first.
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (special != w->onSpecialWorkspace())
|
2023-11-18 18:00:24 +01:00
|
|
|
continue;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
2024-02-13 19:07:19 +01:00
|
|
|
!w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow) {
|
2023-12-03 13:53:12 +01:00
|
|
|
if (w->hasPopupAt(pos))
|
2023-03-01 15:06:52 +01:00
|
|
|
return w.get();
|
2022-07-12 09:49:56 +02:00
|
|
|
}
|
2022-09-25 20:07:48 +02:00
|
|
|
}
|
2023-12-03 13:53:12 +01:00
|
|
|
|
2023-11-18 18:00:24 +01:00
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (special != w->onSpecialWorkspace())
|
2023-11-18 18:00:24 +01:00
|
|
|
continue;
|
2022-03-20 11:14:24 +01:00
|
|
|
|
2024-02-04 16:40:20 +01:00
|
|
|
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize};
|
2024-04-02 21:32:39 +02:00
|
|
|
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
2024-02-13 19:07:19 +01:00
|
|
|
!w->m_sAdditionalConfigData.noFocus && w.get() != pIgnoreWindow)
|
2022-07-12 09:49:56 +02:00
|
|
|
return w.get();
|
|
|
|
}
|
2022-03-19 20:30:21 +01:00
|
|
|
|
2023-11-18 18:00:24 +01:00
|
|
|
return nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
// special workspace
|
2024-04-02 21:32:39 +02:00
|
|
|
if (PMONITOR->activeSpecialWorkspace && !*PSPECIALFALLTHRU)
|
2023-11-18 18:00:24 +01:00
|
|
|
return windowForWorkspace(true);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (PMONITOR->activeSpecialWorkspace) {
|
2024-01-09 13:17:55 +01:00
|
|
|
const auto PWINDOW = windowForWorkspace(true);
|
|
|
|
|
|
|
|
if (PWINDOW)
|
|
|
|
return PWINDOW;
|
|
|
|
}
|
|
|
|
|
2023-11-18 18:00:24 +01:00
|
|
|
return windowForWorkspace(false);
|
2022-03-19 20:30:21 +01:00
|
|
|
}
|
|
|
|
|
2022-04-02 13:02:16 +02:00
|
|
|
wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pWindow, Vector2D& sl) {
|
|
|
|
|
|
|
|
if (!windowValidMapped(pWindow))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
RASSERT(!pWindow->m_bIsX11, "Cannot call vectorWindowToSurface on an X11 window!");
|
|
|
|
|
|
|
|
const auto PSURFACE = pWindow->m_uSurface.xdg;
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
double subx, suby;
|
2022-04-02 13:02:16 +02:00
|
|
|
|
2022-06-22 15:45:56 +02:00
|
|
|
// calc for oversized windows... fucking bullshit, again.
|
2023-11-04 18:03:05 +01:00
|
|
|
CBox geom;
|
|
|
|
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
|
|
|
geom.applyFromWlr();
|
2022-06-22 15:45:56 +02:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
const auto PFOUND =
|
|
|
|
wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.value().x + geom.x, pos.y - pWindow->m_vRealPosition.value().y + geom.y, &subx, &suby);
|
2022-04-02 13:02:16 +02:00
|
|
|
|
|
|
|
if (PFOUND) {
|
|
|
|
sl.x = subx;
|
|
|
|
sl.y = suby;
|
|
|
|
return PFOUND;
|
|
|
|
}
|
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
sl.x = pos.x - pWindow->m_vRealPosition.value().x;
|
|
|
|
sl.y = pos.y - pWindow->m_vRealPosition.value().y;
|
2022-04-02 13:02:16 +02:00
|
|
|
|
2022-06-22 15:45:56 +02:00
|
|
|
sl.x += geom.x;
|
|
|
|
sl.y += geom.y;
|
|
|
|
|
2022-04-02 13:02:16 +02:00
|
|
|
return PSURFACE->surface;
|
|
|
|
}
|
|
|
|
|
2023-09-23 02:21:59 +02:00
|
|
|
Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow, wlr_surface* pSurface) {
|
|
|
|
if (!windowValidMapped(pWindow))
|
|
|
|
return {};
|
|
|
|
|
|
|
|
if (pWindow->m_bIsX11)
|
2024-03-02 01:35:17 +01:00
|
|
|
return vec - pWindow->m_vRealPosition.goal();
|
2023-09-23 02:21:59 +02:00
|
|
|
|
|
|
|
const auto PSURFACE = pWindow->m_uSurface.xdg;
|
|
|
|
|
|
|
|
std::tuple<wlr_surface*, int, int> iterData = {pSurface, -1337, -1337};
|
|
|
|
|
|
|
|
wlr_xdg_surface_for_each_surface(
|
|
|
|
PSURFACE,
|
|
|
|
[](wlr_surface* surf, int x, int y, void* data) {
|
|
|
|
const auto PDATA = (std::tuple<wlr_surface*, int, int>*)data;
|
|
|
|
if (surf == std::get<0>(*PDATA)) {
|
|
|
|
std::get<1>(*PDATA) = x;
|
|
|
|
std::get<2>(*PDATA) = y;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
&iterData);
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
CBox geom = {};
|
|
|
|
wlr_xdg_surface_get_geometry(PSURFACE, geom.pWlr());
|
|
|
|
geom.applyFromWlr();
|
2023-10-30 20:36:34 +01:00
|
|
|
|
2023-09-23 02:21:59 +02:00
|
|
|
if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337)
|
2024-03-02 01:35:17 +01:00
|
|
|
return vec - pWindow->m_vRealPosition.goal();
|
2023-09-23 02:21:59 +02:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
return vec - pWindow->m_vRealPosition.goal() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y};
|
2023-09-23 02:21:59 +02:00
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
|
|
|
if (m->output == out) {
|
|
|
|
return m.get();
|
2022-03-19 20:56:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-02-18 03:24:01 +01:00
|
|
|
CMonitor* CCompositor::getRealMonitorFromOutput(wlr_output* out) {
|
|
|
|
for (auto& m : m_vRealMonitors) {
|
|
|
|
if (m->output == out) {
|
|
|
|
return m.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-04-02 18:57:09 +02:00
|
|
|
void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
2022-03-18 22:53:27 +01:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
|
|
|
static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
|
2023-10-26 23:17:49 +02:00
|
|
|
|
2022-04-18 17:16:01 +02:00
|
|
|
if (g_pCompositor->m_sSeat.exclusiveClient) {
|
|
|
|
Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-01-19 16:45:34 +01:00
|
|
|
if (!g_pInputManager->m_dExclusiveLSes.empty()) {
|
|
|
|
Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-09 23:39:23 +01:00
|
|
|
if (pWindow && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(pWindow->m_uSurface.xwayland))
|
|
|
|
return;
|
|
|
|
|
2023-09-12 23:37:08 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow);
|
2023-08-11 17:27:09 +02:00
|
|
|
|
2022-05-14 20:56:21 +02:00
|
|
|
if (!pWindow || !windowValidMapped(pWindow)) {
|
2023-10-06 02:11:47 +02:00
|
|
|
|
|
|
|
if (!m_pLastWindow && !pWindow)
|
|
|
|
return;
|
|
|
|
|
2022-08-08 20:42:14 +02:00
|
|
|
const auto PLASTWINDOW = m_pLastWindow;
|
2022-12-16 18:17:31 +01:00
|
|
|
m_pLastWindow = nullptr;
|
2022-08-08 20:42:14 +02:00
|
|
|
|
|
|
|
if (windowValidMapped(PLASTWINDOW)) {
|
|
|
|
updateWindowAnimatedDecorationValues(PLASTWINDOW);
|
2022-08-08 20:21:11 +02:00
|
|
|
|
2022-10-28 20:18:10 +02:00
|
|
|
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
|
|
|
|
|
2022-08-08 20:42:14 +02:00
|
|
|
if (PLASTWINDOW->m_phForeignToplevel)
|
|
|
|
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
|
2022-08-08 20:21:11 +02:00
|
|
|
}
|
|
|
|
|
2022-05-14 20:56:21 +02:00
|
|
|
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
|
2022-08-08 20:21:11 +02:00
|
|
|
|
2022-08-21 18:34:38 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","});
|
2023-02-06 14:16:54 +01:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ","});
|
2022-08-21 18:34:38 +02:00
|
|
|
|
2023-04-12 14:11:38 +02:00
|
|
|
EMIT_HOOK_EVENT("activeWindow", (CWindow*)nullptr);
|
2023-02-19 21:54:53 +01:00
|
|
|
|
2022-10-24 13:25:36 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr);
|
|
|
|
|
2022-08-08 20:21:11 +02:00
|
|
|
m_pLastFocus = nullptr;
|
2022-10-31 13:26:07 +01:00
|
|
|
|
|
|
|
g_pInputManager->recheckIdleInhibitorStatus();
|
2022-05-14 14:37:57 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-02-13 19:07:19 +01:00
|
|
|
if (pWindow->m_sAdditionalConfigData.noFocus) {
|
2022-05-14 20:56:21 +02:00
|
|
|
Debug::log(LOG, "Ignoring focus to nofocus window!");
|
2022-03-18 22:53:27 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-14 18:16:09 +02:00
|
|
|
if (m_pLastWindow == pWindow && m_sSeat.seat->keyboard_state.focused_surface == pSurface)
|
2022-04-05 18:29:58 +02:00
|
|
|
return;
|
|
|
|
|
2022-09-10 13:11:02 +02:00
|
|
|
if (pWindow->m_bPinned)
|
2024-04-02 21:32:39 +02:00
|
|
|
pWindow->m_pWorkspace = m_pLastMonitor->activeWorkspace;
|
2022-09-10 13:11:02 +02:00
|
|
|
|
2024-01-07 12:06:33 +01:00
|
|
|
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
|
|
|
|
|
2024-04-03 11:09:42 +02:00
|
|
|
if (!isWorkspaceVisible(pWindow->m_pWorkspace)) {
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
2023-01-20 20:57:35 +01:00
|
|
|
// This is to fix incorrect feedback on the focus history.
|
|
|
|
PWORKSPACE->m_pLastFocusedWindow = pWindow;
|
2024-04-02 21:32:39 +02:00
|
|
|
PWORKSPACE->rememberPrevWorkspace(m_pLastMonitor->activeWorkspace);
|
2024-04-13 15:39:20 +02:00
|
|
|
if (PWORKSPACE->m_bIsSpecialWorkspace)
|
|
|
|
m_pLastMonitor->changeWorkspace(PWORKSPACE, false, true); // if special ws, open on current monitor
|
|
|
|
else
|
|
|
|
PMONITOR->changeWorkspace(PWORKSPACE, false, true);
|
2023-01-20 20:57:35 +01:00
|
|
|
// changeworkspace already calls focusWindow
|
|
|
|
return;
|
|
|
|
}
|
2022-08-06 21:05:19 +02:00
|
|
|
|
2022-04-23 14:16:02 +02:00
|
|
|
const auto PLASTWINDOW = m_pLastWindow;
|
2022-12-16 18:17:31 +01:00
|
|
|
m_pLastWindow = pWindow;
|
2022-04-23 14:16:02 +02:00
|
|
|
|
2024-01-09 13:17:55 +01:00
|
|
|
/* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which
|
|
|
|
window focuses are "via keybinds" and which ones aren't. */
|
2024-04-02 21:32:39 +02:00
|
|
|
if (PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace != pWindow->m_pWorkspace && !pWindow->m_bPinned && !*PSPECIALFALLTHROUGH)
|
2024-01-07 12:06:33 +01:00
|
|
|
PMONITOR->setSpecialWorkspace(nullptr);
|
|
|
|
|
2022-04-23 14:16:02 +02:00
|
|
|
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
|
|
|
|
if (windowValidMapped(PLASTWINDOW)) {
|
2023-12-08 17:02:16 +01:00
|
|
|
PLASTWINDOW->updateDynamicRules();
|
|
|
|
|
2022-07-12 13:40:55 +02:00
|
|
|
updateWindowAnimatedDecorationValues(PLASTWINDOW);
|
2022-04-23 14:16:02 +02:00
|
|
|
|
2022-10-28 21:12:17 +02:00
|
|
|
if (!pWindow->m_bIsX11 || pWindow->m_iX11Type == 1)
|
|
|
|
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
|
2022-05-29 11:24:42 +02:00
|
|
|
|
|
|
|
if (PLASTWINDOW->m_phForeignToplevel)
|
|
|
|
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
|
2022-04-05 18:29:58 +02:00
|
|
|
}
|
|
|
|
|
2022-04-23 14:16:02 +02:00
|
|
|
m_pLastWindow = PLASTWINDOW;
|
|
|
|
|
2023-03-20 16:00:58 +01:00
|
|
|
const auto PWINDOWSURFACE = pSurface ? pSurface : pWindow->m_pWLSurface.wlr();
|
2022-03-18 22:53:27 +01:00
|
|
|
|
2022-04-02 18:57:09 +02:00
|
|
|
focusSurface(PWINDOWSURFACE, pWindow);
|
|
|
|
|
2022-04-23 14:16:02 +02:00
|
|
|
g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow
|
2022-04-02 18:57:09 +02:00
|
|
|
|
2023-12-08 17:02:16 +01:00
|
|
|
pWindow->updateDynamicRules();
|
|
|
|
|
2022-07-12 13:40:55 +02:00
|
|
|
updateWindowAnimatedDecorationValues(pWindow);
|
2022-05-24 22:21:31 +02:00
|
|
|
|
2023-09-01 17:10:03 +02:00
|
|
|
if (pWindow->m_bIsUrgent)
|
2023-01-14 20:31:11 +01:00
|
|
|
pWindow->m_bIsUrgent = false;
|
|
|
|
|
2022-05-24 22:21:31 +02:00
|
|
|
// Send an event
|
2022-07-20 18:39:08 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle});
|
2023-09-20 09:26:20 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)pWindow)});
|
2022-05-29 11:24:42 +02:00
|
|
|
|
2023-02-19 21:54:53 +01:00
|
|
|
EMIT_HOOK_EVENT("activeWindow", pWindow);
|
|
|
|
|
2022-10-24 13:25:36 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(pWindow);
|
|
|
|
|
2023-08-10 20:06:39 +02:00
|
|
|
// TODO: implement this better
|
2023-09-19 12:37:30 +02:00
|
|
|
if (!PLASTWINDOW && pWindow->m_sGroupData.pNextWindow) {
|
|
|
|
for (auto curr = pWindow->m_sGroupData.pNextWindow; curr != pWindow; curr = curr->m_sGroupData.pNextWindow) {
|
2023-08-10 20:06:39 +02:00
|
|
|
if (curr->m_phForeignToplevel)
|
|
|
|
wlr_foreign_toplevel_handle_v1_set_activated(curr->m_phForeignToplevel, false);
|
2023-09-19 12:37:30 +02:00
|
|
|
}
|
2023-08-10 20:06:39 +02:00
|
|
|
}
|
|
|
|
|
2022-05-29 11:24:42 +02:00
|
|
|
if (pWindow->m_phForeignToplevel)
|
|
|
|
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
|
2022-10-28 20:20:12 +02:00
|
|
|
|
2022-10-31 13:26:07 +01:00
|
|
|
g_pInputManager->recheckIdleInhibitorStatus();
|
2023-01-20 19:15:15 +01:00
|
|
|
|
|
|
|
// move to front of the window history
|
|
|
|
const auto HISTORYPIVOT = std::find_if(m_vWindowFocusHistory.begin(), m_vWindowFocusHistory.end(), [&](const auto& other) { return other == pWindow; });
|
|
|
|
if (HISTORYPIVOT == m_vWindowFocusHistory.end()) {
|
2023-09-20 17:25:03 +02:00
|
|
|
Debug::log(ERR, "BUG THIS: {} has no pivot in history", pWindow);
|
2023-01-20 19:15:15 +01:00
|
|
|
} else {
|
|
|
|
std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1);
|
|
|
|
}
|
2023-10-26 23:17:49 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PFOLLOWMOUSE == 0)
|
2023-10-26 23:17:49 +02:00
|
|
|
g_pInputManager->sendMotionEventsToFocused();
|
2022-03-20 14:36:55 +01:00
|
|
|
}
|
|
|
|
|
2022-04-02 13:02:16 +02:00
|
|
|
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
2022-04-18 17:16:01 +02:00
|
|
|
|
2023-03-20 16:00:58 +01:00
|
|
|
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == pWindowOwner->m_pWLSurface.wlr()))
|
2022-12-16 18:17:31 +01:00
|
|
|
return; // Don't focus when already focused on this.
|
2022-03-20 14:36:55 +01:00
|
|
|
|
2024-01-07 14:04:25 +01:00
|
|
|
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
|
|
|
|
return;
|
2023-02-12 20:20:13 +01:00
|
|
|
|
2024-03-02 22:04:55 +01:00
|
|
|
const auto PLASTSURF = m_pLastFocus;
|
|
|
|
|
2022-07-07 21:47:59 +02:00
|
|
|
// Unfocus last surface if should
|
2022-10-28 20:18:10 +02:00
|
|
|
if (m_pLastFocus && !pWindowOwner)
|
2022-07-07 21:47:59 +02:00
|
|
|
g_pXWaylandManager->activateSurface(m_pLastFocus, false);
|
|
|
|
|
2022-07-11 12:29:50 +02:00
|
|
|
if (!pSurface) {
|
|
|
|
wlr_seat_keyboard_clear_focus(m_sSeat.seat);
|
2022-07-20 18:39:08 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // unfocused
|
2023-02-06 14:16:54 +01:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ","});
|
2023-03-08 10:46:17 +01:00
|
|
|
EMIT_HOOK_EVENT("keyboardFocus", (wlr_surface*)nullptr);
|
2023-02-12 20:20:13 +01:00
|
|
|
m_pLastFocus = nullptr;
|
2022-03-27 19:16:33 +02:00
|
|
|
return;
|
2022-07-11 12:29:50 +02:00
|
|
|
}
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2023-12-24 13:20:31 +01:00
|
|
|
if (const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat); KEYBOARD) {
|
|
|
|
uint32_t keycodes[WLR_KEYBOARD_KEYS_CAP] = {0}; // TODO: maybe send valid, non-keybind codes?
|
|
|
|
wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, keycodes, 0, &KEYBOARD->modifiers);
|
|
|
|
|
|
|
|
wlr_seat_keyboard_focus_change_event event = {
|
|
|
|
.seat = m_sSeat.seat,
|
|
|
|
.old_surface = m_pLastFocus,
|
|
|
|
.new_surface = pSurface,
|
|
|
|
};
|
|
|
|
wl_signal_emit_mutable(&m_sSeat.seat->keyboard_state.events.focus_change, &event);
|
|
|
|
}
|
2022-04-02 19:09:27 +02:00
|
|
|
|
2022-04-10 11:17:06 +02:00
|
|
|
if (pWindowOwner)
|
2023-09-20 17:25:03 +02:00
|
|
|
Debug::log(LOG, "Set keyboard focus to surface {:x}, with {}", (uintptr_t)pSurface, pWindowOwner);
|
2022-03-31 19:41:55 +02:00
|
|
|
else
|
2023-09-06 12:51:36 +02:00
|
|
|
Debug::log(LOG, "Set keyboard focus to surface {:x}", (uintptr_t)pSurface);
|
2022-07-08 13:19:57 +02:00
|
|
|
|
2022-11-02 19:54:41 +01:00
|
|
|
g_pXWaylandManager->activateSurface(pSurface, true);
|
2022-07-08 13:19:57 +02:00
|
|
|
m_pLastFocus = pSurface;
|
2023-02-19 21:54:53 +01:00
|
|
|
|
|
|
|
EMIT_HOOK_EVENT("keyboardFocus", pSurface);
|
2024-03-02 22:04:55 +01:00
|
|
|
|
|
|
|
const auto SURF = CWLSurface::surfaceFromWlr(pSurface);
|
|
|
|
const auto OLDSURF = CWLSurface::surfaceFromWlr(PLASTSURF);
|
|
|
|
|
|
|
|
if (OLDSURF && OLDSURF->constraint())
|
|
|
|
OLDSURF->constraint()->deactivate();
|
|
|
|
|
|
|
|
if (SURF && SURF->constraint())
|
|
|
|
SURF->constraint()->activate();
|
2022-03-18 23:16:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CCompositor::windowValidMapped(CWindow* pWindow) {
|
2022-10-14 21:46:32 +02:00
|
|
|
if (!pWindow)
|
|
|
|
return false;
|
|
|
|
|
2022-03-18 23:16:15 +01:00
|
|
|
if (!windowExists(pWindow))
|
|
|
|
return false;
|
|
|
|
|
2022-03-22 20:53:11 +01:00
|
|
|
if (!pWindow->m_bIsMapped)
|
|
|
|
return false;
|
|
|
|
|
2022-10-14 21:46:32 +02:00
|
|
|
if (pWindow->isHidden())
|
2022-04-12 16:44:18 +02:00
|
|
|
return false;
|
|
|
|
|
2022-03-18 23:16:15 +01:00
|
|
|
return true;
|
2022-03-20 12:11:57 +01:00
|
|
|
}
|
|
|
|
|
2024-03-25 17:20:30 +01:00
|
|
|
wlr_surface* CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) {
|
|
|
|
for (auto& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) {
|
|
|
|
for (auto& ls : lsl | std::views::reverse) {
|
|
|
|
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
auto SURFACEAT = wlr_layer_surface_v1_popup_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y);
|
|
|
|
|
|
|
|
if (SURFACEAT) {
|
|
|
|
if (!pixman_region32_not_empty(&SURFACEAT->input_region))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
*ppLayerSurfaceFound = ls.get();
|
|
|
|
return SURFACEAT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords,
|
|
|
|
SLayerSurface** ppLayerSurfaceFound) {
|
2023-03-01 15:06:52 +01:00
|
|
|
for (auto& ls : *layerSurfaces | std::views::reverse) {
|
2024-03-02 01:35:17 +01:00
|
|
|
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f)
|
2022-03-20 14:36:55 +01:00
|
|
|
continue;
|
|
|
|
|
2024-03-25 17:20:30 +01:00
|
|
|
auto SURFACEAT = wlr_surface_surface_at(ls->layerSurface->surface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y);
|
2022-11-18 21:35:15 +01:00
|
|
|
|
2022-07-01 20:14:33 +02:00
|
|
|
if (SURFACEAT) {
|
2022-12-22 16:03:32 +01:00
|
|
|
if (!pixman_region32_not_empty(&SURFACEAT->input_region))
|
|
|
|
continue;
|
|
|
|
|
2023-03-01 15:06:52 +01:00
|
|
|
*ppLayerSurfaceFound = ls.get();
|
2022-03-20 14:36:55 +01:00
|
|
|
return SURFACEAT;
|
2022-07-01 20:14:33 +02:00
|
|
|
}
|
2022-03-20 14:36:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2023-12-17 21:00:18 +01:00
|
|
|
if (!w->m_bIsMapped || w->m_bFadingOut)
|
2022-12-08 18:43:15 +01:00
|
|
|
continue;
|
|
|
|
|
2023-03-20 16:00:58 +01:00
|
|
|
if (w->m_pWLSurface.wlr() == pSurface)
|
2022-06-30 15:44:26 +02:00
|
|
|
return w.get();
|
2022-03-20 14:36:55 +01:00
|
|
|
}
|
|
|
|
|
2022-03-20 15:55:47 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-12-05 18:05:15 +01:00
|
|
|
CWindow* CCompositor::getWindowFromHandle(uint32_t handle) {
|
|
|
|
for (auto& w : m_vWindows) {
|
2022-12-05 18:57:59 +01:00
|
|
|
if ((uint32_t)(((uint64_t)w.get()) & 0xFFFFFFFF) == handle) {
|
2022-12-05 18:05:15 +01:00
|
|
|
return w.get();
|
2022-12-05 18:57:59 +01:00
|
|
|
}
|
2022-12-05 18:05:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-12-12 15:56:42 +01:00
|
|
|
CWindow* CCompositor::getWindowFromZWLRHandle(wl_resource* handle) {
|
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (!w->m_bIsMapped || w->isHidden() || !w->m_phForeignToplevel)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
wl_resource* current;
|
|
|
|
|
|
|
|
wl_list_for_each(current, &w->m_phForeignToplevel->resources, link) {
|
|
|
|
if (current == handle) {
|
|
|
|
return w.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-21 19:18:33 +01:00
|
|
|
CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->workspaceID() == ID && w->m_bIsFullscreen)
|
2022-06-30 15:44:26 +02:00
|
|
|
return w.get();
|
2022-03-21 19:18:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-04-03 11:09:42 +02:00
|
|
|
bool CCompositor::isWorkspaceVisible(PHLWORKSPACE w) {
|
2024-04-03 21:42:38 +02:00
|
|
|
return valid(w) && w->m_bVisible;
|
2022-03-20 15:55:47 +01:00
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
PHLWORKSPACE CCompositor::getWorkspaceByID(const int& id) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWorkspaces) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_iID == id && !w->inert())
|
|
|
|
return w;
|
2022-03-20 15:55:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::sanityCheckWorkspaces() {
|
2022-12-29 17:06:30 +01:00
|
|
|
auto it = m_vWorkspaces.begin();
|
|
|
|
while (it != m_vWorkspaces.end()) {
|
2024-04-06 16:53:32 +02:00
|
|
|
const auto& WORKSPACE = *it;
|
|
|
|
|
2024-04-05 20:32:05 +02:00
|
|
|
// If ref == 1, only the compositor holds a ref, which means it's inactive and has no mapped windows.
|
2024-04-06 16:53:32 +02:00
|
|
|
if (!WORKSPACE->m_bPersistent && WORKSPACE.use_count() == 1) {
|
2024-04-05 20:32:05 +02:00
|
|
|
it = m_vWorkspaces.erase(it);
|
2023-04-13 22:09:50 +02:00
|
|
|
continue;
|
2023-10-09 21:28:22 +02:00
|
|
|
}
|
2023-04-13 22:09:50 +02:00
|
|
|
|
2022-12-29 17:06:30 +01:00
|
|
|
++it;
|
2022-03-20 15:55:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 21:56:20 +01:00
|
|
|
int CCompositor::getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled) {
|
2022-03-20 15:55:47 +01:00
|
|
|
int no = 0;
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->workspaceID() == id && w->m_bIsMapped && !(onlyTiled.has_value() && !w->m_bIsFloating != onlyTiled.value()))
|
2022-03-20 15:55:47 +01:00
|
|
|
no++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
2024-04-09 13:08:38 +02:00
|
|
|
int CCompositor::getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled) {
|
|
|
|
int no = 0;
|
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (w->workspaceID() == id && w->m_bIsMapped && !(onlyTiled.has_value() && !w->m_bIsFloating != onlyTiled.value()) && w->m_sGroupData.head)
|
|
|
|
no++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
2023-01-21 11:18:55 +01:00
|
|
|
CWindow* CCompositor::getUrgentWindow() {
|
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (w->m_bIsMapped && w->m_bIsUrgent)
|
|
|
|
return w.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2023-01-14 20:31:11 +01:00
|
|
|
bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) {
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent)
|
2023-01-14 20:31:11 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-20 15:55:47 +01:00
|
|
|
CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden())
|
2022-06-30 15:44:26 +02:00
|
|
|
return w.get();
|
2022-03-20 15:55:47 +01:00
|
|
|
}
|
|
|
|
|
2022-03-20 14:00:46 +01:00
|
|
|
return nullptr;
|
2022-03-20 19:14:17 +01:00
|
|
|
}
|
|
|
|
|
2023-08-21 20:54:02 +02:00
|
|
|
CWindow* CCompositor::getTopLeftWindowOnWorkspace(const int& id) {
|
|
|
|
const auto PWORKSPACE = getWorkspaceByID(id);
|
|
|
|
|
|
|
|
if (!PWORKSPACE)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
|
|
|
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden())
|
2023-08-21 20:54:02 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
const auto WINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
|
|
|
|
|
|
|
if (WINDOWIDEALBB.x <= PMONITOR->vecPosition.x + 1 && WINDOWIDEALBB.y <= PMONITOR->vecPosition.y + 1)
|
|
|
|
return w.get();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-22 18:29:13 +01:00
|
|
|
bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
|
2023-02-03 12:58:55 +01:00
|
|
|
if (g_pSessionLockManager->isSessionLocked()) {
|
|
|
|
if (g_pSessionLockManager->isSurfaceSessionLock(surface))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_sSeat.exclusiveClient) {
|
|
|
|
if (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-04-02 13:02:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CCompositor::isWindowActive(CWindow* pWindow) {
|
2022-05-29 00:07:31 +02:00
|
|
|
if (!m_pLastWindow && !m_pLastFocus)
|
|
|
|
return false;
|
|
|
|
|
2024-04-02 02:15:58 +02:00
|
|
|
if (!pWindow->m_bIsMapped)
|
2022-04-02 18:57:09 +02:00
|
|
|
return false;
|
|
|
|
|
2023-03-20 16:00:58 +01:00
|
|
|
const auto PSURFACE = pWindow->m_pWLSurface.wlr();
|
2022-04-02 13:02:16 +02:00
|
|
|
|
2022-04-02 18:57:09 +02:00
|
|
|
return PSURFACE == m_pLastFocus || pWindow == m_pLastWindow;
|
2022-04-04 16:25:30 +02:00
|
|
|
}
|
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
void CCompositor::changeWindowZOrder(CWindow* pWindow, bool top) {
|
2022-04-04 16:25:30 +02:00
|
|
|
if (!windowValidMapped(pWindow))
|
|
|
|
return;
|
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
auto moveToZ = [&](CWindow* pw, bool top) -> void {
|
|
|
|
if (top) {
|
|
|
|
for (auto it = m_vWindows.begin(); it != m_vWindows.end(); ++it) {
|
|
|
|
if (it->get() == pw) {
|
|
|
|
std::rotate(it, it + 1, m_vWindows.end());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (auto it = m_vWindows.rbegin(); it != m_vWindows.rend(); ++it) {
|
|
|
|
if (it->get() == pw) {
|
|
|
|
std::rotate(it, it + 1, m_vWindows.rend());
|
|
|
|
break;
|
|
|
|
}
|
2022-08-28 19:47:06 +02:00
|
|
|
}
|
|
|
|
}
|
2023-01-11 17:57:54 +01:00
|
|
|
|
|
|
|
if (pw->m_bIsMapped)
|
|
|
|
g_pHyprRenderer->damageMonitor(getMonitorFromID(pw->m_iMonitorID));
|
2022-08-28 19:47:06 +02:00
|
|
|
};
|
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
if (top)
|
|
|
|
pWindow->m_bCreatedOverFullscreen = true;
|
2022-08-28 19:47:06 +02:00
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
if (!pWindow->m_bIsX11) {
|
|
|
|
moveToZ(pWindow, top);
|
2022-08-28 19:47:06 +02:00
|
|
|
return;
|
2023-09-21 23:18:26 +02:00
|
|
|
} else {
|
|
|
|
// move X11 window stack
|
2022-08-28 19:47:06 +02:00
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
std::deque<CWindow*> toMove;
|
2022-08-28 19:47:06 +02:00
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
auto x11Stack = [&](CWindow* pw, bool top, auto&& x11Stack) -> void {
|
|
|
|
if (top)
|
|
|
|
toMove.emplace_back(pw);
|
|
|
|
else
|
|
|
|
toMove.emplace_front(pw);
|
2022-08-28 19:47:06 +02:00
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2023-12-17 21:00:18 +01:00
|
|
|
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pw) {
|
2023-09-21 23:18:26 +02:00
|
|
|
x11Stack(w.get(), top, x11Stack);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2022-08-28 19:47:06 +02:00
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
x11Stack(pWindow, top, x11Stack);
|
2022-08-28 19:47:06 +02:00
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
for (auto it : toMove) {
|
|
|
|
moveToZ(it, top);
|
|
|
|
}
|
2022-08-28 19:47:06 +02:00
|
|
|
}
|
2022-04-05 19:28:10 +02:00
|
|
|
}
|
|
|
|
|
2022-07-12 23:11:34 +02:00
|
|
|
void CCompositor::cleanupFadingOut(const int& monid) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindowsFadingOut) {
|
2022-04-26 17:51:00 +02:00
|
|
|
|
2022-07-12 23:11:34 +02:00
|
|
|
if (w->m_iMonitorID != (long unsigned int)monid)
|
|
|
|
continue;
|
|
|
|
|
2024-04-06 15:59:30 +02:00
|
|
|
if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) {
|
2022-06-30 15:44:26 +02:00
|
|
|
|
2024-04-06 15:59:30 +02:00
|
|
|
w->m_bFadingOut = false;
|
2024-03-14 19:25:28 +01:00
|
|
|
|
2024-04-06 15:59:30 +02:00
|
|
|
if (!w->m_bReadyToDelete)
|
|
|
|
continue;
|
2023-03-01 14:15:51 +01:00
|
|
|
|
2024-04-06 15:59:30 +02:00
|
|
|
removeWindowFromVectorSafe(w);
|
2022-04-10 11:17:06 +02:00
|
|
|
|
|
|
|
Debug::log(LOG, "Cleanup: destroyed a window");
|
2022-04-05 19:28:10 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2022-05-14 17:23:46 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& ls : m_vSurfacesFadingOut) {
|
2022-07-25 22:40:34 +02:00
|
|
|
|
|
|
|
// sometimes somehow fucking happens wtf
|
|
|
|
bool exists = false;
|
|
|
|
for (auto& m : m_vMonitors) {
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
2022-07-25 22:40:34 +02:00
|
|
|
for (auto& lsp : lsl) {
|
|
|
|
if (lsp.get() == ls) {
|
|
|
|
exists = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exists)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exists)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!exists) {
|
2022-12-16 18:17:31 +01:00
|
|
|
std::erase(m_vSurfacesFadingOut, ls);
|
2022-07-25 22:40:34 +02:00
|
|
|
|
|
|
|
Debug::log(LOG, "Fading out a non-existent LS??");
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-12 23:11:34 +02:00
|
|
|
if (ls->monitorID != monid)
|
|
|
|
continue;
|
|
|
|
|
2022-08-01 12:16:33 +02:00
|
|
|
// mark blur for recalc
|
|
|
|
if (ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || ls->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
|
|
|
g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid));
|
|
|
|
|
2024-02-28 16:00:34 +01:00
|
|
|
if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) {
|
2022-07-23 15:48:08 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
2022-07-25 21:08:54 +02:00
|
|
|
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; }) != lsl.end()) {
|
2022-12-16 18:17:31 +01:00
|
|
|
std::erase_if(lsl, [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; });
|
2022-07-25 21:08:54 +02:00
|
|
|
}
|
2022-07-23 15:48:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
std::erase(m_vSurfacesFadingOut, ls);
|
2022-07-25 22:00:46 +02:00
|
|
|
|
2022-05-14 17:28:55 +02:00
|
|
|
Debug::log(LOG, "Cleanup: destroyed a layersurface");
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
glFlush(); // to free mem NOW.
|
2022-05-14 17:23:46 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2022-04-09 13:26:55 +02:00
|
|
|
}
|
|
|
|
|
2022-07-25 21:08:54 +02:00
|
|
|
void CCompositor::addToFadingOutSafe(SLayerSurface* pLS) {
|
|
|
|
const auto FOUND = std::find_if(m_vSurfacesFadingOut.begin(), m_vSurfacesFadingOut.end(), [&](SLayerSurface* other) { return other == pLS; });
|
|
|
|
|
|
|
|
if (FOUND != m_vSurfacesFadingOut.end())
|
2022-12-16 18:17:31 +01:00
|
|
|
return; // if it's already added, don't add it.
|
2022-07-25 21:08:54 +02:00
|
|
|
|
|
|
|
m_vSurfacesFadingOut.emplace_back(pLS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::addToFadingOutSafe(CWindow* pWindow) {
|
|
|
|
const auto FOUND = std::find_if(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), [&](CWindow* other) { return other == pWindow; });
|
|
|
|
|
|
|
|
if (FOUND != m_vWindowsFadingOut.end())
|
2022-12-16 18:17:31 +01:00
|
|
|
return; // if it's already added, don't add it.
|
2022-07-25 21:08:54 +02:00
|
|
|
|
|
|
|
m_vWindowsFadingOut.emplace_back(pWindow);
|
|
|
|
}
|
|
|
|
|
2022-04-09 13:26:55 +02:00
|
|
|
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
2022-06-23 20:39:48 +02:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
if (!isDirection(dir))
|
|
|
|
return nullptr;
|
|
|
|
|
2023-01-26 15:36:22 +01:00
|
|
|
// 0 -> history, 1 -> shared length
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PMETHOD = CConfigValue<Hyprlang::INT>("binds:focus_preferred_method");
|
2022-06-23 20:39:48 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
2022-04-09 13:26:55 +02:00
|
|
|
|
2023-11-04 22:03:08 +01:00
|
|
|
if (!PMONITOR)
|
|
|
|
return nullptr; // ??
|
2023-01-26 15:36:22 +01:00
|
|
|
|
2023-11-04 22:03:08 +01:00
|
|
|
const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? wlr_box{(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y} :
|
|
|
|
pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
|
|
|
|
|
|
|
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
|
|
|
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
2023-11-04 22:03:08 +01:00
|
|
|
auto leaderValue = -1;
|
|
|
|
CWindow* leaderWindow = nullptr;
|
2022-04-09 13:26:55 +02:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
if (!pWindow->m_bIsFloating) {
|
2022-04-09 13:26:55 +02:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
// for tiled windows, we calc edges
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-03 11:09:42 +02:00
|
|
|
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->m_bIsFullscreen && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
2023-11-05 17:18:41 +01:00
|
|
|
continue;
|
2023-10-20 11:53:37 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace)
|
2023-11-05 17:18:41 +01:00
|
|
|
continue;
|
2022-11-24 00:40:05 +01:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
|
|
|
continue;
|
2022-06-23 20:39:48 +02:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
2022-06-23 20:39:48 +02:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
|
|
|
|
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
|
2023-01-26 15:36:22 +01:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
double intersectLength = -1;
|
2023-01-26 15:36:22 +01:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
switch (dir) {
|
|
|
|
case 'l':
|
|
|
|
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
|
|
|
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
|
|
|
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
case 'u':
|
|
|
|
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
|
|
|
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
case 'd':
|
|
|
|
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
|
|
|
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-01-26 15:36:22 +01:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PMETHOD == 0 /* history */) {
|
2023-11-05 17:18:41 +01:00
|
|
|
if (intersectLength > 0) {
|
|
|
|
|
|
|
|
// get idx
|
|
|
|
int windowIDX = -1;
|
|
|
|
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
|
|
|
if (g_pCompositor->m_vWindowFocusHistory[i] == w.get()) {
|
|
|
|
windowIDX = i;
|
|
|
|
break;
|
|
|
|
}
|
2023-01-26 15:36:22 +01:00
|
|
|
}
|
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
windowIDX = g_pCompositor->m_vWindowFocusHistory.size() - windowIDX;
|
2023-01-26 15:36:22 +01:00
|
|
|
|
2023-11-05 17:18:41 +01:00
|
|
|
if (windowIDX > leaderValue) {
|
|
|
|
leaderValue = windowIDX;
|
|
|
|
leaderWindow = w.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else /* length */ {
|
|
|
|
if (intersectLength > leaderValue) {
|
|
|
|
leaderValue = intersectLength;
|
2023-01-26 15:36:22 +01:00
|
|
|
leaderWindow = w.get();
|
|
|
|
}
|
|
|
|
}
|
2023-11-05 17:18:41 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// for floating windows, we calculate best distance and angle.
|
|
|
|
// if there is a window with angle better than THRESHOLD, only distance counts
|
|
|
|
|
|
|
|
if (dir == 'u')
|
|
|
|
dir = 't';
|
|
|
|
if (dir == 'd')
|
|
|
|
dir = 'b';
|
|
|
|
|
|
|
|
static const std::unordered_map<char, Vector2D> VECTORS = {{'r', {1, 0}}, {'t', {0, -1}}, {'b', {0, 1}}, {'l', {-1, 0}}};
|
|
|
|
|
|
|
|
//
|
|
|
|
auto vectorAngles = [](Vector2D a, Vector2D b) -> double {
|
|
|
|
double dot = a.x * b.x + a.y * b.y;
|
|
|
|
double ang = std::acos(dot / (a.size() * b.size()));
|
|
|
|
return ang;
|
|
|
|
};
|
|
|
|
|
|
|
|
float bestAngleAbs = 2.0 * M_PI;
|
|
|
|
constexpr float THRESHOLD = 0.3 * M_PI;
|
|
|
|
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-03 11:09:42 +02:00
|
|
|
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->m_bIsFullscreen && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
|
2023-11-05 17:18:41 +01:00
|
|
|
continue;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_pWorkspace != w->m_pWorkspace)
|
2023-11-05 17:18:41 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const auto DIST = w->middle().distance(pWindow->middle());
|
|
|
|
const auto ANGLE = vectorAngles(Vector2D{w->middle() - pWindow->middle()}, VECTORS.at(dir));
|
|
|
|
|
|
|
|
if (ANGLE > M_PI_2)
|
|
|
|
continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely.
|
|
|
|
|
|
|
|
if ((bestAngleAbs < THRESHOLD && DIST < leaderValue && ANGLE < THRESHOLD) || (ANGLE < bestAngleAbs && bestAngleAbs > THRESHOLD) || leaderValue == -1) {
|
|
|
|
leaderValue = DIST;
|
|
|
|
bestAngleAbs = ANGLE;
|
2023-01-26 15:36:22 +01:00
|
|
|
leaderWindow = w.get();
|
|
|
|
}
|
|
|
|
}
|
2023-11-05 17:18:41 +01:00
|
|
|
|
|
|
|
if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow)
|
|
|
|
leaderWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
2022-04-09 13:26:55 +02:00
|
|
|
}
|
|
|
|
|
2023-01-26 15:36:22 +01:00
|
|
|
if (leaderValue != -1)
|
|
|
|
return leaderWindow;
|
2022-04-09 13:26:55 +02:00
|
|
|
|
|
|
|
return nullptr;
|
2022-04-11 19:51:37 +02:00
|
|
|
}
|
|
|
|
|
2023-12-24 15:08:48 +01:00
|
|
|
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableOnly, std::optional<bool> floating) {
|
2022-04-13 20:45:06 +02:00
|
|
|
bool gotToWindow = false;
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (w.get() != pWindow && !gotToWindow)
|
2022-04-13 20:45:06 +02:00
|
|
|
continue;
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
if (w.get() == pWindow) {
|
2022-04-13 20:45:06 +02:00
|
|
|
gotToWindow = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-12-24 15:08:48 +01:00
|
|
|
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
|
|
|
continue;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
2022-06-30 15:44:26 +02:00
|
|
|
return w.get();
|
2022-04-13 20:45:06 +02:00
|
|
|
}
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2023-12-24 15:08:48 +01:00
|
|
|
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
|
|
|
continue;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w.get() != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
2022-06-30 15:44:26 +02:00
|
|
|
return w.get();
|
2022-04-13 20:45:06 +02:00
|
|
|
}
|
|
|
|
|
2022-04-21 16:38:48 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2023-12-24 15:08:48 +01:00
|
|
|
CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableOnly, std::optional<bool> floating) {
|
2022-07-09 18:39:41 +02:00
|
|
|
bool gotToWindow = false;
|
2023-03-01 15:06:52 +01:00
|
|
|
for (auto& w : m_vWindows | std::views::reverse) {
|
|
|
|
if (w.get() != pWindow && !gotToWindow)
|
2022-07-09 18:39:41 +02:00
|
|
|
continue;
|
|
|
|
|
2023-03-01 15:06:52 +01:00
|
|
|
if (w.get() == pWindow) {
|
2022-07-09 18:39:41 +02:00
|
|
|
gotToWindow = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-12-24 15:08:48 +01:00
|
|
|
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
|
|
|
continue;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
2023-03-01 15:06:52 +01:00
|
|
|
return w.get();
|
2022-07-09 18:39:41 +02:00
|
|
|
}
|
|
|
|
|
2023-03-01 15:06:52 +01:00
|
|
|
for (auto& w : m_vWindows | std::views::reverse) {
|
2023-12-24 15:08:48 +01:00
|
|
|
if (floating.has_value() && w->m_bIsFloating != floating.value())
|
|
|
|
continue;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w.get() != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sAdditionalConfigData.noFocus))
|
2023-03-01 15:06:52 +01:00
|
|
|
return w.get();
|
2022-07-09 18:39:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-04-21 16:38:48 +02:00
|
|
|
int CCompositor::getNextAvailableNamedWorkspace() {
|
2022-04-21 21:35:08 +02:00
|
|
|
int lowest = -1337 + 1;
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWorkspaces) {
|
|
|
|
if (w->m_iID < -1 && w->m_iID < lowest)
|
|
|
|
lowest = w->m_iID;
|
2022-04-21 16:38:48 +02:00
|
|
|
}
|
|
|
|
|
2022-04-21 21:35:08 +02:00
|
|
|
return lowest - 1;
|
2022-04-21 16:38:48 +02:00
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
PHLWORKSPACE CCompositor::getWorkspaceByName(const std::string& name) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWorkspaces) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_szName == name && !w->inert())
|
|
|
|
return w;
|
2022-04-21 16:38:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
PHLWORKSPACE CCompositor::getWorkspaceByString(const std::string& str) {
|
2023-10-15 20:07:23 +02:00
|
|
|
if (str.starts_with("name:")) {
|
2022-04-21 16:38:48 +02:00
|
|
|
return getWorkspaceByName(str.substr(str.find_first_of(':') + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2022-05-30 14:18:46 +02:00
|
|
|
std::string name = "";
|
|
|
|
return getWorkspaceByID(getWorkspaceIDFromString(str, name));
|
2022-12-16 18:17:31 +01:00
|
|
|
} catch (std::exception& e) { Debug::log(ERR, "Error in getWorkspaceByString, invalid id"); }
|
2022-04-21 16:38:48 +02:00
|
|
|
|
2022-04-13 20:45:06 +02:00
|
|
|
return nullptr;
|
2022-04-23 14:16:02 +02:00
|
|
|
}
|
2022-04-24 17:53:50 +02:00
|
|
|
|
|
|
|
bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
|
|
|
if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y))
|
2022-04-24 17:53:50 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2022-04-25 13:40:46 +02:00
|
|
|
}
|
|
|
|
|
2023-12-26 17:24:31 +01:00
|
|
|
bool CCompositor::isPointOnReservedArea(const Vector2D& point, const CMonitor* pMonitor) {
|
|
|
|
const auto PMONITOR = pMonitor ? pMonitor : getMonitorFromVector(point);
|
|
|
|
|
|
|
|
const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
|
|
|
const auto XY2 = PMONITOR->vecPosition + PMONITOR->vecSize - PMONITOR->vecReservedBottomRight;
|
|
|
|
|
|
|
|
return !VECINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y);
|
|
|
|
}
|
|
|
|
|
2022-10-28 20:35:02 +02:00
|
|
|
void checkFocusSurfaceIter(wlr_surface* pSurface, int x, int y, void* data) {
|
2022-12-16 18:17:31 +01:00
|
|
|
auto pair = (std::pair<wlr_surface*, bool>*)data;
|
2022-10-28 20:35:02 +02:00
|
|
|
pair->second = pair->second || pSurface == pair->first;
|
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
|
2024-02-25 15:03:00 +01:00
|
|
|
return this->getMonitorInDirection(m_pLastMonitor, dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const char& dir) {
|
2024-02-26 01:05:20 +01:00
|
|
|
if (!pSourceMonitor)
|
|
|
|
return nullptr;
|
2024-02-25 15:03:00 +01:00
|
|
|
|
|
|
|
const auto POSA = pSourceMonitor->vecPosition;
|
|
|
|
const auto SIZEA = pSourceMonitor->vecSize;
|
2022-05-05 12:50:25 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
auto longestIntersect = -1;
|
|
|
|
CMonitor* longestIntersectMonitor = nullptr;
|
2022-05-05 12:50:25 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
|
|
|
if (m.get() == m_pLastMonitor)
|
2022-05-05 12:50:25 +02:00
|
|
|
continue;
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto POSB = m->vecPosition;
|
2022-06-30 15:44:26 +02:00
|
|
|
const auto SIZEB = m->vecSize;
|
2022-05-05 12:50:25 +02:00
|
|
|
switch (dir) {
|
|
|
|
case 'l':
|
|
|
|
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
2022-09-28 19:43:35 +02:00
|
|
|
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
2022-05-05 12:50:25 +02:00
|
|
|
if (INTERSECTLEN > longestIntersect) {
|
2022-12-16 18:17:31 +01:00
|
|
|
longestIntersect = INTERSECTLEN;
|
2022-06-30 15:44:26 +02:00
|
|
|
longestIntersectMonitor = m.get();
|
2022-05-05 12:50:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
2022-09-28 19:43:35 +02:00
|
|
|
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
2022-05-05 12:50:25 +02:00
|
|
|
if (INTERSECTLEN > longestIntersect) {
|
2022-12-16 18:17:31 +01:00
|
|
|
longestIntersect = INTERSECTLEN;
|
2022-06-30 15:44:26 +02:00
|
|
|
longestIntersectMonitor = m.get();
|
2022-05-05 12:50:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
case 'u':
|
|
|
|
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
2022-09-28 19:43:35 +02:00
|
|
|
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
2022-05-05 12:50:25 +02:00
|
|
|
if (INTERSECTLEN > longestIntersect) {
|
2022-12-16 18:17:31 +01:00
|
|
|
longestIntersect = INTERSECTLEN;
|
2022-06-30 15:44:26 +02:00
|
|
|
longestIntersectMonitor = m.get();
|
2022-05-05 12:50:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
case 'd':
|
|
|
|
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
2022-09-28 19:43:35 +02:00
|
|
|
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
2022-05-05 12:50:25 +02:00
|
|
|
if (INTERSECTLEN > longestIntersect) {
|
2022-12-16 18:17:31 +01:00
|
|
|
longestIntersect = INTERSECTLEN;
|
2022-06-30 15:44:26 +02:00
|
|
|
longestIntersectMonitor = m.get();
|
2022-05-05 12:50:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (longestIntersect != -1)
|
|
|
|
return longestIntersectMonitor;
|
|
|
|
|
2022-04-25 13:40:46 +02:00
|
|
|
return nullptr;
|
2022-05-14 17:23:46 +02:00
|
|
|
}
|
2022-05-26 21:23:13 +02:00
|
|
|
|
2022-07-12 13:40:55 +02:00
|
|
|
void CCompositor::updateAllWindowsAnimatedDecorationValues() {
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (!w->m_bIsMapped)
|
2022-05-26 21:23:13 +02:00
|
|
|
continue;
|
|
|
|
|
2022-07-12 13:40:55 +02:00
|
|
|
updateWindowAnimatedDecorationValues(w.get());
|
2022-05-26 21:23:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-20 23:52:18 +01:00
|
|
|
void CCompositor::updateWorkspaceWindows(const int64_t& id) {
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (!w->m_bIsMapped || w->workspaceID() != id)
|
2023-12-20 23:52:18 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
w->updateDynamicRules();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-12 13:40:55 +02:00
|
|
|
void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
2022-05-26 21:23:13 +02:00
|
|
|
// optimization
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.active_border");
|
|
|
|
static auto PINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.inactive_border");
|
|
|
|
static auto PNOGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border_active");
|
|
|
|
static auto PNOGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border");
|
|
|
|
static auto PGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_active");
|
|
|
|
static auto PGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_inactive");
|
|
|
|
static auto PGROUPACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_active");
|
|
|
|
static auto PGROUPINACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_inactive");
|
|
|
|
static auto PINACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:inactive_opacity");
|
|
|
|
static auto PACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:active_opacity");
|
|
|
|
static auto PFULLSCREENALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:fullscreen_opacity");
|
|
|
|
static auto PSHADOWCOL = CConfigValue<Hyprlang::INT>("decoration:col.shadow");
|
|
|
|
static auto PSHADOWCOLINACTIVE = CConfigValue<Hyprlang::INT>("decoration:col.shadow_inactive");
|
|
|
|
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
|
|
|
static auto PDIMENABLED = CConfigValue<Hyprlang::INT>("decoration:dim_inactive");
|
|
|
|
|
|
|
|
auto* const ACTIVECOL = (CGradientValueData*)(PACTIVECOL.ptr())->getData();
|
|
|
|
auto* const INACTIVECOL = (CGradientValueData*)(PINACTIVECOL.ptr())->getData();
|
|
|
|
auto* const NOGROUPACTIVECOL = (CGradientValueData*)(PNOGROUPACTIVECOL.ptr())->getData();
|
|
|
|
auto* const NOGROUPINACTIVECOL = (CGradientValueData*)(PNOGROUPINACTIVECOL.ptr())->getData();
|
|
|
|
auto* const GROUPACTIVECOL = (CGradientValueData*)(PGROUPACTIVECOL.ptr())->getData();
|
|
|
|
auto* const GROUPINACTIVECOL = (CGradientValueData*)(PGROUPINACTIVECOL.ptr())->getData();
|
|
|
|
auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)(PGROUPACTIVELOCKEDCOL.ptr())->getData();
|
|
|
|
auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)(PGROUPINACTIVELOCKEDCOL.ptr())->getData();
|
|
|
|
|
|
|
|
auto setBorderColor = [&](CGradientValueData grad) -> void {
|
2022-11-26 18:56:43 +01:00
|
|
|
if (grad == pWindow->m_cRealBorderColor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pWindow->m_cRealBorderColorPrevious = pWindow->m_cRealBorderColor;
|
2022-12-16 18:17:31 +01:00
|
|
|
pWindow->m_cRealBorderColor = grad;
|
2023-02-01 22:06:01 +01:00
|
|
|
pWindow->m_fBorderFadeAnimationProgress.setValueAndWarp(0.f);
|
|
|
|
pWindow->m_fBorderFadeAnimationProgress = 1.f;
|
2022-11-26 18:56:43 +01:00
|
|
|
};
|
|
|
|
|
2022-07-12 13:40:55 +02:00
|
|
|
// border
|
2022-05-26 21:23:13 +02:00
|
|
|
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
|
2022-12-31 16:23:56 +01:00
|
|
|
if (RENDERDATA.isBorderGradient)
|
|
|
|
setBorderColor(*RENDERDATA.borderGradient);
|
2023-02-19 22:07:32 +01:00
|
|
|
else {
|
2023-06-13 12:04:54 +02:00
|
|
|
const bool GROUPLOCKED = pWindow->m_sGroupData.pNextWindow ? pWindow->getGroupHead()->m_sGroupData.locked : false;
|
2023-02-19 22:07:32 +01:00
|
|
|
if (pWindow == m_pLastWindow) {
|
2023-09-22 01:42:00 +02:00
|
|
|
const auto* const ACTIVECOLOR =
|
|
|
|
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
2024-01-14 18:27:32 +01:00
|
|
|
setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying().m_vColors.empty() ? *ACTIVECOLOR :
|
|
|
|
pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying());
|
2023-02-19 22:07:32 +01:00
|
|
|
} else {
|
2023-09-22 01:42:00 +02:00
|
|
|
const auto* const INACTIVECOLOR =
|
|
|
|
!pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
2024-01-14 18:27:32 +01:00
|
|
|
setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying().m_vColors.empty() ? *INACTIVECOLOR :
|
|
|
|
pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying());
|
2023-02-19 22:07:32 +01:00
|
|
|
}
|
|
|
|
}
|
2022-07-12 13:40:55 +02:00
|
|
|
|
2023-02-01 22:06:01 +01:00
|
|
|
// tick angle if it's not running (aka dead)
|
|
|
|
if (!pWindow->m_fBorderAngleAnimationProgress.isBeingAnimated())
|
|
|
|
pWindow->m_fBorderAngleAnimationProgress.setValueAndWarp(0.f);
|
|
|
|
|
2022-07-12 13:40:55 +02:00
|
|
|
// opacity
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
2022-12-11 18:15:02 +01:00
|
|
|
if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
2024-04-08 00:19:02 +02:00
|
|
|
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaFullscreen.toUnderlying() != -1 ?
|
|
|
|
(pWindow->m_sSpecialRenderData.alphaFullscreenOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alphaFullscreen.toUnderlying() :
|
|
|
|
pWindow->m_sSpecialRenderData.alphaFullscreen.toUnderlying() * *PFULLSCREENALPHA) :
|
|
|
|
*PFULLSCREENALPHA;
|
2022-07-12 13:40:55 +02:00
|
|
|
} else {
|
|
|
|
if (pWindow == m_pLastWindow)
|
2023-01-26 15:36:22 +01:00
|
|
|
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alpha.toUnderlying() :
|
2024-03-03 19:39:20 +01:00
|
|
|
pWindow->m_sSpecialRenderData.alpha.toUnderlying() * *PACTIVEALPHA;
|
2022-07-12 13:40:55 +02:00
|
|
|
else
|
2023-01-24 20:05:34 +01:00
|
|
|
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() != -1 ?
|
|
|
|
(pWindow->m_sSpecialRenderData.alphaInactiveOverride.toUnderlying() ? pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() :
|
2024-03-03 19:39:20 +01:00
|
|
|
pWindow->m_sSpecialRenderData.alphaInactive.toUnderlying() * *PINACTIVEALPHA) :
|
|
|
|
*PINACTIVEALPHA;
|
2022-07-12 13:40:55 +02:00
|
|
|
}
|
2022-07-16 12:44:45 +02:00
|
|
|
|
2022-08-30 12:46:17 +02:00
|
|
|
// dim
|
2024-03-03 19:39:20 +01:00
|
|
|
if (pWindow == m_pLastWindow || pWindow->m_sAdditionalConfigData.forceNoDim || !*PDIMENABLED) {
|
2022-08-30 12:46:17 +02:00
|
|
|
pWindow->m_fDimPercent = 0;
|
|
|
|
} else {
|
2024-03-03 19:39:20 +01:00
|
|
|
pWindow->m_fDimPercent = *PDIMSTRENGTH;
|
2022-08-30 12:46:17 +02:00
|
|
|
}
|
|
|
|
|
2022-07-16 12:44:45 +02:00
|
|
|
// shadow
|
2022-07-18 12:39:57 +02:00
|
|
|
if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) {
|
|
|
|
if (pWindow == m_pLastWindow) {
|
2024-03-03 19:39:20 +01:00
|
|
|
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL);
|
2022-07-18 12:39:57 +02:00
|
|
|
} else {
|
2024-03-03 19:39:20 +01:00
|
|
|
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
|
2022-07-18 12:39:57 +02:00
|
|
|
}
|
2022-07-16 12:44:45 +02:00
|
|
|
} else {
|
2022-07-18 12:39:57 +02:00
|
|
|
pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow
|
2022-07-16 12:44:45 +02:00
|
|
|
}
|
2023-02-28 00:34:41 +01:00
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
pWindow->updateWindowDecos();
|
2022-05-30 17:11:35 +02:00
|
|
|
}
|
|
|
|
|
2023-07-09 23:08:40 +02:00
|
|
|
int CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
2023-07-18 12:12:05 +02:00
|
|
|
// reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor
|
|
|
|
if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; }))
|
2023-07-09 23:08:40 +02:00
|
|
|
return m_mMonitorIDMap[name];
|
|
|
|
|
|
|
|
// otherwise, find minimum available ID that is not in the map
|
2023-07-18 12:12:05 +02:00
|
|
|
std::unordered_set<uint64_t> usedIDs;
|
2023-07-09 23:08:40 +02:00
|
|
|
for (auto const& monitor : m_vRealMonitors) {
|
|
|
|
usedIDs.insert(monitor->ID);
|
2022-05-30 17:11:35 +02:00
|
|
|
}
|
|
|
|
|
2023-07-18 12:12:05 +02:00
|
|
|
uint64_t nextID = 0;
|
2023-07-09 23:08:40 +02:00
|
|
|
while (usedIDs.count(nextID) > 0) {
|
|
|
|
nextID++;
|
|
|
|
}
|
|
|
|
m_mMonitorIDMap[name] = nextID;
|
|
|
|
return nextID;
|
2022-05-30 17:11:35 +02:00
|
|
|
}
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2022-08-25 21:25:28 +02:00
|
|
|
void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) {
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACEA = pMonitorA->activeWorkspace;
|
|
|
|
const auto PWORKSPACEB = pMonitorB->activeWorkspace;
|
2022-08-25 21:25:28 +02:00
|
|
|
|
|
|
|
PWORKSPACEA->m_iMonitorID = pMonitorB->ID;
|
|
|
|
PWORKSPACEA->moveToMonitor(pMonitorB->ID);
|
|
|
|
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_pWorkspace == PWORKSPACEA) {
|
2023-03-20 02:50:46 +01:00
|
|
|
if (w->m_bPinned) {
|
2024-04-02 21:32:39 +02:00
|
|
|
w->m_pWorkspace = PWORKSPACEB;
|
2023-03-20 02:50:46 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-08-25 21:25:28 +02:00
|
|
|
w->m_iMonitorID = pMonitorB->ID;
|
|
|
|
|
2022-08-27 19:11:21 +02:00
|
|
|
// additionally, move floating and fs windows manually
|
|
|
|
if (w->m_bIsFloating)
|
2024-03-30 17:57:43 +01:00
|
|
|
w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorA->vecPosition + pMonitorB->vecPosition;
|
2022-08-27 19:11:21 +02:00
|
|
|
|
|
|
|
if (w->m_bIsFullscreen) {
|
|
|
|
w->m_vRealPosition = pMonitorB->vecPosition;
|
2022-12-16 18:17:31 +01:00
|
|
|
w->m_vRealSize = pMonitorB->vecSize;
|
2022-08-25 21:25:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
w->updateToplevel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PWORKSPACEB->m_iMonitorID = pMonitorA->ID;
|
|
|
|
PWORKSPACEB->moveToMonitor(pMonitorA->ID);
|
|
|
|
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_pWorkspace == PWORKSPACEB) {
|
2023-03-20 02:50:46 +01:00
|
|
|
if (w->m_bPinned) {
|
2024-04-02 21:32:39 +02:00
|
|
|
w->m_pWorkspace = PWORKSPACEA;
|
2023-03-20 02:50:46 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-08-25 21:25:28 +02:00
|
|
|
w->m_iMonitorID = pMonitorA->ID;
|
|
|
|
|
2022-08-27 19:11:21 +02:00
|
|
|
// additionally, move floating and fs windows manually
|
|
|
|
if (w->m_bIsFloating)
|
2024-03-30 17:57:43 +01:00
|
|
|
w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorB->vecPosition + pMonitorA->vecPosition;
|
2022-08-27 19:11:21 +02:00
|
|
|
|
|
|
|
if (w->m_bIsFullscreen) {
|
|
|
|
w->m_vRealPosition = pMonitorA->vecPosition;
|
2022-12-16 18:17:31 +01:00
|
|
|
w->m_vRealSize = pMonitorA->vecSize;
|
2022-08-25 21:25:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
w->updateToplevel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
pMonitorA->activeWorkspace = PWORKSPACEB;
|
|
|
|
pMonitorB->activeWorkspace = PWORKSPACEA;
|
2022-08-25 21:25:28 +02:00
|
|
|
|
2024-03-04 18:05:20 +01:00
|
|
|
PWORKSPACEA->rememberPrevWorkspace(PWORKSPACEB);
|
|
|
|
PWORKSPACEB->rememberPrevWorkspace(PWORKSPACEA);
|
|
|
|
|
2022-08-25 21:25:28 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorA->ID);
|
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitorB->ID);
|
|
|
|
|
2023-04-25 00:21:51 +02:00
|
|
|
updateFullscreenFadeOnWorkspace(PWORKSPACEB);
|
|
|
|
updateFullscreenFadeOnWorkspace(PWORKSPACEA);
|
|
|
|
|
2024-02-13 18:53:50 +01:00
|
|
|
if (pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID || pMonitorB->ID == g_pCompositor->m_pLastMonitor->ID) {
|
|
|
|
const auto LASTWIN = pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID ? PWORKSPACEB->getLastFocusedWindow() : PWORKSPACEA->getLastFocusedWindow();
|
|
|
|
g_pCompositor->focusWindow(LASTWIN ? LASTWIN :
|
|
|
|
(g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING)));
|
2024-03-25 02:50:41 +01:00
|
|
|
|
|
|
|
const auto PNEWWORKSPACE = pMonitorA->ID == g_pCompositor->m_pLastMonitor->ID ? PWORKSPACEB : PWORKSPACEA;
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PNEWWORKSPACE->m_szName});
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"workspacev2", std::format("{},{}", PNEWWORKSPACE->m_iID, PNEWWORKSPACE->m_szName)});
|
|
|
|
EMIT_HOOK_EVENT("workspace", PNEWWORKSPACE);
|
2024-02-13 18:53:50 +01:00
|
|
|
}
|
2022-08-26 16:05:02 +02:00
|
|
|
|
|
|
|
// event
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName});
|
2024-03-08 18:39:53 +01:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEA->m_iID, PWORKSPACEA->m_szName, pMonitorB->szName)});
|
2024-04-02 21:32:39 +02:00
|
|
|
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{PWORKSPACEA, pMonitorB}));
|
2022-08-26 16:05:02 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEB->m_szName + "," + pMonitorA->szName});
|
2024-03-08 18:39:53 +01:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", PWORKSPACEB->m_iID, PWORKSPACEB->m_szName, pMonitorA->szName)});
|
2024-04-02 21:32:39 +02:00
|
|
|
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{PWORKSPACEB, pMonitorA}));
|
2022-08-25 21:25:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
2024-02-27 23:11:59 +01:00
|
|
|
if (name == "current")
|
|
|
|
return g_pCompositor->m_pLastMonitor;
|
|
|
|
else if (isDirection(name))
|
|
|
|
return getMonitorInDirection(name[0]);
|
|
|
|
else if (name[0] == '+' || name[0] == '-') {
|
2022-11-10 13:22:19 +01:00
|
|
|
// relative
|
2023-01-14 20:45:24 +01:00
|
|
|
|
|
|
|
if (m_vMonitors.size() == 1)
|
|
|
|
return m_vMonitors.begin()->get();
|
|
|
|
|
2022-11-10 13:22:19 +01:00
|
|
|
const auto OFFSET = name[0] == '-' ? name : name.substr(1);
|
|
|
|
|
|
|
|
if (!isNumber(OFFSET)) {
|
|
|
|
Debug::log(ERR, "Error in getMonitorFromString: Not a number in relative.");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-12-08 13:09:48 +01:00
|
|
|
int offsetLeft = std::stoi(OFFSET);
|
2022-12-16 18:17:31 +01:00
|
|
|
offsetLeft = offsetLeft < 0 ? -((-offsetLeft) % m_vMonitors.size()) : offsetLeft % m_vMonitors.size();
|
2022-11-10 13:22:19 +01:00
|
|
|
|
|
|
|
int currentPlace = 0;
|
|
|
|
for (int i = 0; i < (int)m_vMonitors.size(); i++) {
|
|
|
|
if (m_vMonitors[i].get() == m_pLastMonitor) {
|
|
|
|
currentPlace = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
currentPlace += offsetLeft;
|
|
|
|
|
|
|
|
if (currentPlace < 0) {
|
2023-01-23 21:56:05 +01:00
|
|
|
currentPlace = m_vMonitors.size() + currentPlace;
|
2022-11-10 13:22:19 +01:00
|
|
|
} else {
|
|
|
|
currentPlace = currentPlace % m_vMonitors.size();
|
|
|
|
}
|
|
|
|
|
2023-01-23 21:56:43 +01:00
|
|
|
if (currentPlace != std::clamp(currentPlace, 0, (int)m_vMonitors.size() - 1)) {
|
2022-11-10 13:22:19 +01:00
|
|
|
Debug::log(WARN, "Error in getMonitorFromString: Vaxry's code sucks.");
|
2023-01-14 20:45:24 +01:00
|
|
|
currentPlace = std::clamp(currentPlace, 0, (int)m_vMonitors.size() - 1);
|
2022-11-10 13:22:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return m_vMonitors[currentPlace].get();
|
|
|
|
} else if (isNumber(name)) {
|
2022-08-25 21:25:28 +02:00
|
|
|
// change by ID
|
|
|
|
int monID = -1;
|
|
|
|
try {
|
|
|
|
monID = std::stoi(name);
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
// shouldn't happen but jic
|
|
|
|
Debug::log(ERR, "Error in getMonitorFromString: invalid num");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2023-03-02 13:04:41 +01:00
|
|
|
if (monID > -1 && monID < (int)m_vMonitors.size()) {
|
|
|
|
return getMonitorFromID(monID);
|
2022-08-25 21:25:28 +02:00
|
|
|
} else {
|
|
|
|
Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1");
|
|
|
|
return nullptr;
|
|
|
|
}
|
2024-02-27 23:11:59 +01:00
|
|
|
} else {
|
2023-03-02 13:04:41 +01:00
|
|
|
for (auto& m : m_vMonitors) {
|
2023-03-16 15:03:40 +01:00
|
|
|
if (!m->output)
|
|
|
|
continue;
|
|
|
|
|
2024-02-27 23:11:59 +01:00
|
|
|
if (m->matchesStaticSelector(name)) {
|
2023-03-02 13:04:41 +01:00
|
|
|
return m.get();
|
|
|
|
}
|
|
|
|
}
|
2022-08-25 21:25:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMonitor, bool noWarpCursor) {
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
// We trust the monitor to be correct.
|
2022-05-30 20:05:38 +02:00
|
|
|
|
|
|
|
if (pWorkspace->m_iMonitorID == pMonitor->ID)
|
|
|
|
return;
|
|
|
|
|
2023-09-06 12:51:36 +02:00
|
|
|
Debug::log(LOG, "moveWorkspaceToMonitor: Moving {} to monitor {}", pWorkspace->m_iID, pMonitor->ID);
|
2022-05-30 20:05:38 +02:00
|
|
|
|
|
|
|
const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false;
|
2022-05-30 20:05:38 +02:00
|
|
|
|
|
|
|
// fix old mon
|
2022-12-20 03:18:47 +01:00
|
|
|
int nextWorkspaceOnMonitorID = -1;
|
2024-03-04 18:05:20 +01:00
|
|
|
if (!SWITCHINGISACTIVE)
|
2023-04-28 22:40:40 +02:00
|
|
|
nextWorkspaceOnMonitorID = pWorkspace->m_iID;
|
|
|
|
else {
|
|
|
|
for (auto& w : m_vWorkspaces) {
|
|
|
|
if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) {
|
|
|
|
nextWorkspaceOnMonitorID = w->m_iID;
|
|
|
|
break;
|
|
|
|
}
|
2022-05-30 20:05:38 +02:00
|
|
|
}
|
|
|
|
|
2023-04-28 22:40:40 +02:00
|
|
|
if (nextWorkspaceOnMonitorID == -1) {
|
|
|
|
nextWorkspaceOnMonitorID = 1;
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2023-04-28 22:40:40 +02:00
|
|
|
while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool {
|
|
|
|
const auto B = g_pConfigManager->getBoundMonitorForWS(std::to_string(nextWorkspaceOnMonitorID));
|
|
|
|
return B && B != POLDMON;
|
|
|
|
}())
|
|
|
|
nextWorkspaceOnMonitorID++;
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2023-09-06 12:51:36 +02:00
|
|
|
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new {}", nextWorkspaceOnMonitorID);
|
2023-04-14 16:03:53 +02:00
|
|
|
|
2023-04-28 22:40:40 +02:00
|
|
|
g_pCompositor->createNewWorkspace(nextWorkspaceOnMonitorID, POLDMON->ID);
|
|
|
|
}
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2023-09-06 12:51:36 +02:00
|
|
|
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing {}", nextWorkspaceOnMonitorID);
|
2024-02-10 00:47:00 +01:00
|
|
|
POLDMON->changeWorkspace(nextWorkspaceOnMonitorID, false, true, true);
|
2023-04-28 22:40:40 +02:00
|
|
|
}
|
2023-04-13 22:09:50 +02:00
|
|
|
|
2022-05-30 20:05:38 +02:00
|
|
|
// move the workspace
|
|
|
|
pWorkspace->m_iMonitorID = pMonitor->ID;
|
2022-05-30 20:51:45 +02:00
|
|
|
pWorkspace->moveToMonitor(pMonitor->ID);
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_pWorkspace == pWorkspace) {
|
2023-03-20 02:50:46 +01:00
|
|
|
if (w->m_bPinned) {
|
2024-04-02 21:32:39 +02:00
|
|
|
w->m_pWorkspace = g_pCompositor->getWorkspaceByID(nextWorkspaceOnMonitorID);
|
2023-03-20 02:50:46 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
w->m_iMonitorID = pMonitor->ID;
|
2022-07-25 14:22:32 +02:00
|
|
|
|
2022-08-27 19:11:21 +02:00
|
|
|
// additionally, move floating and fs windows manually
|
2022-10-14 21:46:32 +02:00
|
|
|
if (w->m_bIsMapped && !w->isHidden()) {
|
2023-05-06 17:49:46 +02:00
|
|
|
if (POLDMON) {
|
|
|
|
if (w->m_bIsFloating)
|
2024-03-30 17:57:43 +01:00
|
|
|
w->m_vRealPosition = w->m_vRealPosition.goal() - POLDMON->vecPosition + pMonitor->vecPosition;
|
2022-08-27 19:11:21 +02:00
|
|
|
|
2023-05-06 17:49:46 +02:00
|
|
|
if (w->m_bIsFullscreen) {
|
|
|
|
w->m_vRealPosition = pMonitor->vecPosition;
|
|
|
|
w->m_vRealSize = pMonitor->vecSize;
|
|
|
|
}
|
|
|
|
} else {
|
2024-03-02 01:35:17 +01:00
|
|
|
w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goal().y % (int)pMonitor->vecSize.y};
|
2022-08-27 19:11:21 +02:00
|
|
|
}
|
2022-07-25 14:22:32 +02:00
|
|
|
}
|
2022-08-06 20:57:38 +02:00
|
|
|
|
|
|
|
w->updateToplevel();
|
2022-07-25 14:22:32 +02:00
|
|
|
}
|
2022-05-30 20:05:38 +02:00
|
|
|
}
|
|
|
|
|
2023-04-29 14:32:59 +02:00
|
|
|
if (SWITCHINGISACTIVE && POLDMON == g_pCompositor->m_pLastMonitor) { // if it was active, preserve its' status. If it wasn't, don't.
|
2024-04-02 21:32:39 +02:00
|
|
|
Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active {} -> {}", pMonitor->activeWorkspaceID(), pWorkspace->m_iID);
|
2022-05-31 17:17:44 +02:00
|
|
|
|
2024-04-04 19:30:32 +02:00
|
|
|
if (valid(pMonitor->activeWorkspace)) {
|
|
|
|
pMonitor->activeWorkspace->m_bVisible = false;
|
2024-04-02 21:32:39 +02:00
|
|
|
pMonitor->activeWorkspace->startAnim(false, false);
|
2024-04-04 19:30:32 +02:00
|
|
|
}
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2024-02-10 00:47:00 +01:00
|
|
|
setActiveMonitor(pMonitor);
|
2024-04-02 21:32:39 +02:00
|
|
|
pMonitor->activeWorkspace = pWorkspace;
|
2022-05-30 20:05:38 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
|
|
|
|
|
|
|
|
pWorkspace->startAnim(true, true, true);
|
2024-04-04 19:30:32 +02:00
|
|
|
pWorkspace->m_bVisible = true;
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2024-01-15 16:30:46 +01:00
|
|
|
if (!noWarpCursor)
|
|
|
|
wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
|
2023-05-06 17:13:26 +02:00
|
|
|
|
2023-12-12 15:58:43 +01:00
|
|
|
g_pInputManager->sendMotionEventsToFocused();
|
2022-05-30 20:05:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// finalize
|
2023-05-06 17:49:46 +02:00
|
|
|
if (POLDMON) {
|
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
2024-04-02 21:32:39 +02:00
|
|
|
updateFullscreenFadeOnWorkspace(POLDMON->activeWorkspace);
|
2023-05-06 17:49:46 +02:00
|
|
|
}
|
2022-05-30 20:05:38 +02:00
|
|
|
|
2023-04-25 00:23:12 +02:00
|
|
|
updateFullscreenFadeOnWorkspace(pWorkspace);
|
|
|
|
|
2022-08-26 16:05:02 +02:00
|
|
|
// event
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", pWorkspace->m_szName + "," + pMonitor->szName});
|
2024-03-08 18:39:53 +01:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspacev2", std::format("{},{},{}", pWorkspace->m_iID, pWorkspace->m_szName, pMonitor->szName)});
|
2024-04-02 21:32:39 +02:00
|
|
|
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{pWorkspace, pMonitor}));
|
2022-05-31 12:33:08 +02:00
|
|
|
}
|
|
|
|
|
2023-05-09 15:07:58 +02:00
|
|
|
bool CCompositor::workspaceIDOutOfBounds(const int64_t& id) {
|
|
|
|
int64_t lowestID = INT64_MAX;
|
|
|
|
int64_t highestID = INT64_MIN;
|
2022-05-31 12:33:08 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
for (auto& w : m_vWorkspaces) {
|
2022-11-27 23:42:22 +01:00
|
|
|
if (w->m_bIsSpecialWorkspace)
|
2022-09-17 16:05:12 +02:00
|
|
|
continue;
|
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
if (w->m_iID < lowestID)
|
|
|
|
lowestID = w->m_iID;
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
if (w->m_iID > highestID)
|
|
|
|
highestID = w->m_iID;
|
2022-05-31 12:33:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return std::clamp(id, lowestID, highestID) != id;
|
2022-06-26 12:12:29 +02:00
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
|
2023-04-25 00:21:51 +02:00
|
|
|
|
|
|
|
const auto FULLSCREEN = pWorkspace->m_bHasFullscreenWindow;
|
|
|
|
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_pWorkspace == pWorkspace) {
|
2023-04-25 00:21:51 +02:00
|
|
|
|
2023-05-10 19:36:13 +02:00
|
|
|
if (w->m_bFadingOut || w->m_bPinned || w->m_bIsFullscreen)
|
2023-04-25 00:21:51 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!FULLSCREEN)
|
|
|
|
w->m_fAlpha = 1.f;
|
|
|
|
else if (!w->m_bIsFullscreen)
|
|
|
|
w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto PMONITOR = getMonitorFromID(pWorkspace->m_iMonitorID);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) {
|
2023-08-21 20:55:57 +02:00
|
|
|
for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
|
|
|
if (!ls->fadingOut)
|
|
|
|
ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 1.f;
|
|
|
|
}
|
2023-04-25 00:21:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-26 12:12:29 +02:00
|
|
|
void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode mode) {
|
2023-10-23 01:53:33 +02:00
|
|
|
if (!windowValidMapped(pWindow) || g_pCompositor->m_bUnsafeState)
|
2022-06-26 12:12:29 +02:00
|
|
|
return;
|
|
|
|
|
2022-09-21 15:09:26 +02:00
|
|
|
if (pWindow->m_bPinned) {
|
|
|
|
Debug::log(LOG, "Pinned windows cannot be fullscreen'd");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-13 03:09:20 +01:00
|
|
|
if (pWindow->m_bIsFullscreen == on) {
|
|
|
|
Debug::log(LOG, "Window is already in the required fullscreen state");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-29 11:20:12 +02:00
|
|
|
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
2022-09-29 11:20:12 +02:00
|
|
|
|
2023-09-28 18:49:33 +02:00
|
|
|
const auto MODE = mode == FULLSCREEN_INVALID ? PWORKSPACE->m_efFullscreenMode : mode;
|
|
|
|
|
2022-09-29 11:20:12 +02:00
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
|
|
|
Debug::log(LOG, "Rejecting fullscreen ON on a fullscreen workspace");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-28 18:49:33 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, MODE, on);
|
2022-06-26 12:12:29 +02:00
|
|
|
|
2023-12-11 17:51:10 +01:00
|
|
|
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->shouldSendFullscreenState());
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2023-05-10 19:36:13 +02:00
|
|
|
updateWindowAnimatedDecorationValues(pWindow);
|
2022-11-15 11:21:26 +01:00
|
|
|
|
2022-06-26 12:12:29 +02:00
|
|
|
// make all windows on the same workspace under the fullscreen window
|
2023-04-25 00:21:51 +02:00
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->m_pWorkspace == PWORKSPACE && !w->m_bIsFullscreen && !w->m_bFadingOut && !w->m_bPinned)
|
2022-06-30 15:44:26 +02:00
|
|
|
w->m_bCreatedOverFullscreen = false;
|
2022-09-19 11:23:13 +02:00
|
|
|
}
|
2023-04-25 00:21:51 +02:00
|
|
|
updateFullscreenFadeOnWorkspace(PWORKSPACE);
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal(), true);
|
2022-08-22 14:22:21 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
forceReportSizesToWindowsOnWorkspace(pWindow->workspaceID());
|
2022-10-31 13:26:07 +01:00
|
|
|
|
|
|
|
g_pInputManager->recheckIdleInhibitorStatus();
|
2022-11-05 13:50:47 +01:00
|
|
|
|
|
|
|
// DMAbuf stuff for direct scanout
|
|
|
|
g_pHyprRenderer->setWindowScanoutMode(pWindow);
|
2023-02-14 18:08:42 +01:00
|
|
|
|
|
|
|
g_pConfigManager->ensureVRR(PMONITOR);
|
2022-06-30 15:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CWindow* CCompositor::getX11Parent(CWindow* pWindow) {
|
|
|
|
if (!pWindow->m_bIsX11)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (!w->m_bIsX11)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (w->m_uSurface.xwayland == pWindow->m_uSurface.xwayland->parent)
|
|
|
|
return w.get();
|
|
|
|
}
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-06-30 15:44:26 +02:00
|
|
|
return nullptr;
|
2022-07-07 11:52:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::updateWorkspaceWindowDecos(const int& id) {
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->workspaceID() != id)
|
2022-07-07 11:52:12 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
w->updateWindowDecos();
|
|
|
|
}
|
|
|
|
}
|
2022-07-13 18:18:23 +02:00
|
|
|
|
2024-04-10 18:26:11 +02:00
|
|
|
void CCompositor::updateWorkspaceSpecialRenderData(const int& id) {
|
|
|
|
const auto PWORKSPACE = getWorkspaceByID(id);
|
|
|
|
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
|
|
|
|
|
|
|
for (auto& w : m_vWindows) {
|
|
|
|
if (w->workspaceID() != id)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
w->updateSpecialRenderData(WORKSPACERULE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-27 12:32:00 +02:00
|
|
|
void CCompositor::scheduleFrameForMonitor(CMonitor* pMonitor) {
|
2022-07-13 18:31:09 +02:00
|
|
|
if ((m_sWLRSession && !m_sWLRSession->active) || !m_bSessionActive)
|
2022-07-13 18:18:23 +02:00
|
|
|
return;
|
|
|
|
|
2022-11-19 14:01:32 +01:00
|
|
|
if (!pMonitor->m_bEnabled)
|
|
|
|
return;
|
|
|
|
|
2023-02-27 13:32:38 +01:00
|
|
|
if (pMonitor->renderingActive)
|
|
|
|
pMonitor->pendingFrame = true;
|
|
|
|
|
2022-07-13 18:18:23 +02:00
|
|
|
wlr_output_schedule_frame(pMonitor->output);
|
2022-07-26 17:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
|
|
|
|
eFocusWindowMode mode = MODE_CLASS_REGEX;
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
std::regex regexCheck(regexp);
|
|
|
|
std::string matchCheck;
|
2023-10-15 20:07:23 +02:00
|
|
|
if (regexp.starts_with("title:")) {
|
2022-12-16 18:17:31 +01:00
|
|
|
mode = MODE_TITLE_REGEX;
|
2022-07-26 17:30:30 +02:00
|
|
|
regexCheck = std::regex(regexp.substr(6));
|
2023-10-15 20:07:23 +02:00
|
|
|
} else if (regexp.starts_with("address:")) {
|
2022-12-16 18:17:31 +01:00
|
|
|
mode = MODE_ADDRESS;
|
2022-07-26 17:30:30 +02:00
|
|
|
matchCheck = regexp.substr(8);
|
2023-10-15 20:07:23 +02:00
|
|
|
} else if (regexp.starts_with("pid:")) {
|
2022-12-16 18:17:31 +01:00
|
|
|
mode = MODE_PID;
|
2022-07-26 17:30:30 +02:00
|
|
|
matchCheck = regexp.substr(4);
|
2023-11-05 17:22:43 +01:00
|
|
|
} else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) {
|
2023-11-05 17:21:47 +01:00
|
|
|
// first floating on the current ws
|
|
|
|
if (!m_pLastWindow)
|
|
|
|
return nullptr;
|
|
|
|
|
2023-11-05 17:22:43 +01:00
|
|
|
const bool FLOAT = regexp.starts_with("floating");
|
|
|
|
|
2023-11-05 17:21:47 +01:00
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden())
|
2023-11-05 17:21:47 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
return w.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2022-07-26 17:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2023-09-12 23:37:08 +02:00
|
|
|
if (!w->m_bIsMapped || (w->isHidden() && !g_pLayoutManager->getCurrentLayout()->isWindowReachable(w.get())))
|
2022-07-26 17:30:30 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case MODE_CLASS_REGEX: {
|
|
|
|
const auto windowClass = g_pXWaylandManager->getAppIDClass(w.get());
|
|
|
|
if (!std::regex_search(g_pXWaylandManager->getAppIDClass(w.get()), regexCheck))
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MODE_TITLE_REGEX: {
|
|
|
|
const auto windowTitle = g_pXWaylandManager->getTitle(w.get());
|
|
|
|
if (!std::regex_search(windowTitle, regexCheck))
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MODE_ADDRESS: {
|
2023-09-20 09:26:20 +02:00
|
|
|
std::string addr = std::format("0x{:x}", (uintptr_t)w.get());
|
2022-07-26 17:30:30 +02:00
|
|
|
if (matchCheck != addr)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MODE_PID: {
|
2023-09-20 09:26:20 +02:00
|
|
|
std::string pid = std::format("{}", w->getPID());
|
2022-07-26 17:30:30 +02:00
|
|
|
if (matchCheck != pid)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
2022-12-16 18:17:31 +01:00
|
|
|
default: break;
|
2022-07-26 17:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return w.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2022-07-31 00:27:32 +02:00
|
|
|
}
|
|
|
|
|
2023-01-28 13:26:33 +01:00
|
|
|
void CCompositor::warpCursorTo(const Vector2D& pos, bool force) {
|
2022-08-01 18:50:16 +02:00
|
|
|
|
|
|
|
// warpCursorTo should only be used for warps that
|
|
|
|
// should be disabled with no_cursor_warps
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PNOWARPS = CConfigValue<Hyprlang::INT>("general:no_cursor_warps");
|
2022-08-01 18:50:16 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PNOWARPS && !force)
|
2022-08-01 18:50:16 +02:00
|
|
|
return;
|
|
|
|
|
2023-01-28 18:54:14 +01:00
|
|
|
if (!m_sSeat.mouse)
|
|
|
|
return;
|
|
|
|
|
2022-08-01 18:50:16 +02:00
|
|
|
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pos.x, pos.y);
|
2022-09-03 11:55:14 +02:00
|
|
|
|
|
|
|
const auto PMONITORNEW = getMonitorFromVector(pos);
|
|
|
|
if (PMONITORNEW != m_pLastMonitor)
|
2022-11-19 17:41:36 +01:00
|
|
|
setActiveMonitor(PMONITORNEW);
|
2022-08-01 18:50:16 +02:00
|
|
|
}
|
|
|
|
|
2022-08-05 17:07:01 +02:00
|
|
|
SLayerSurface* CCompositor::getLayerSurfaceFromWlr(wlr_layer_surface_v1* pLS) {
|
|
|
|
for (auto& m : m_vMonitors) {
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
2022-08-05 17:07:01 +02:00
|
|
|
for (auto& ls : lsl) {
|
|
|
|
if (ls->layerSurface == pLS)
|
|
|
|
return ls.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
2022-08-06 20:57:38 +02:00
|
|
|
|
|
|
|
void CCompositor::closeWindow(CWindow* pWindow) {
|
|
|
|
if (pWindow && windowValidMapped(pWindow)) {
|
|
|
|
g_pXWaylandManager->sendCloseWindow(pWindow);
|
|
|
|
}
|
2022-08-10 17:46:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SLayerSurface* CCompositor::getLayerSurfaceFromSurface(wlr_surface* pSurface) {
|
2023-04-02 14:30:45 +02:00
|
|
|
std::pair<wlr_surface*, bool> result = {pSurface, false};
|
|
|
|
|
2022-08-10 17:46:01 +02:00
|
|
|
for (auto& m : m_vMonitors) {
|
2023-01-22 17:03:25 +01:00
|
|
|
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
2022-08-10 17:46:01 +02:00
|
|
|
for (auto& ls : lsl) {
|
|
|
|
if (ls->layerSurface && ls->layerSurface->surface == pSurface)
|
|
|
|
return ls.get();
|
2023-04-02 14:30:45 +02:00
|
|
|
|
|
|
|
static auto iter = [](wlr_surface* surf, int x, int y, void* data) -> void {
|
|
|
|
if (surf == ((std::pair<wlr_surface*, bool>*)data)->first) {
|
|
|
|
*(bool*)data = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
2023-04-02 14:42:57 +02:00
|
|
|
|
2023-04-02 14:30:45 +02:00
|
|
|
if (!ls->layerSurface || !ls->mapped)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
wlr_surface_for_each_surface(ls->layerSurface->surface, iter, &result);
|
|
|
|
|
|
|
|
if (result.second)
|
|
|
|
return ls.get();
|
2022-08-10 17:46:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2022-08-15 15:59:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// returns a delta
|
|
|
|
Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, const Vector2D& relativeTo) {
|
2024-03-31 01:48:39 +01:00
|
|
|
if (!args.contains(' ') && !args.contains('\t'))
|
2022-08-15 15:59:07 +02:00
|
|
|
return relativeTo;
|
|
|
|
|
2023-09-11 00:26:14 +02:00
|
|
|
const auto PMONITOR = m_pLastMonitor;
|
|
|
|
|
|
|
|
bool xIsPercent = false;
|
|
|
|
bool yIsPercent = false;
|
|
|
|
bool isExact = false;
|
|
|
|
|
2024-03-31 01:48:39 +01:00
|
|
|
CVarList varList(args, 0, 's', true);
|
|
|
|
std::string x = varList[0];
|
|
|
|
std::string y = varList[1];
|
2022-08-15 15:59:07 +02:00
|
|
|
|
|
|
|
if (x == "exact") {
|
2024-03-31 01:48:39 +01:00
|
|
|
x = varList[1];
|
|
|
|
y = varList[2];
|
2023-09-11 00:26:14 +02:00
|
|
|
isExact = true;
|
|
|
|
}
|
2022-08-15 15:59:07 +02:00
|
|
|
|
2023-09-11 00:26:14 +02:00
|
|
|
if (x.contains('%')) {
|
|
|
|
xIsPercent = true;
|
|
|
|
x = x.substr(0, x.length() - 1);
|
|
|
|
}
|
2022-08-15 15:59:07 +02:00
|
|
|
|
2023-09-11 00:26:14 +02:00
|
|
|
if (y.contains('%')) {
|
|
|
|
yIsPercent = true;
|
|
|
|
y = y.substr(0, y.length() - 1);
|
2022-08-15 15:59:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!isNumber(x) || !isNumber(y)) {
|
|
|
|
Debug::log(ERR, "parseWindowVectorArgsRelative: args not numbers");
|
|
|
|
return relativeTo;
|
|
|
|
}
|
|
|
|
|
2023-09-11 00:26:14 +02:00
|
|
|
int X = 0;
|
|
|
|
int Y = 0;
|
|
|
|
|
|
|
|
if (isExact) {
|
|
|
|
X = xIsPercent ? std::stof(x) * 0.01 * PMONITOR->vecSize.x : std::stoi(x);
|
|
|
|
Y = yIsPercent ? std::stof(y) * 0.01 * PMONITOR->vecSize.y : std::stoi(y);
|
|
|
|
} else {
|
|
|
|
X = xIsPercent ? std::stof(x) * 0.01 * relativeTo.x + relativeTo.x : std::stoi(x) + relativeTo.x;
|
|
|
|
Y = yIsPercent ? std::stof(y) * 0.01 * relativeTo.y + relativeTo.y : std::stoi(y) + relativeTo.y;
|
|
|
|
}
|
2022-08-15 15:59:07 +02:00
|
|
|
|
2023-09-11 00:26:14 +02:00
|
|
|
return Vector2D(X, Y);
|
2022-08-22 14:22:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) {
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) {
|
2024-03-02 01:35:17 +01:00
|
|
|
g_pXWaylandManager->setWindowSize(w.get(), w->m_vRealSize.value(), true);
|
2022-08-22 14:22:21 +02:00
|
|
|
}
|
|
|
|
}
|
2022-09-03 15:35:53 +02:00
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name) {
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto NAME = name == "" ? std::to_string(id) : name;
|
|
|
|
auto monID = monid;
|
2022-10-25 11:30:25 +02:00
|
|
|
|
|
|
|
// check if bound
|
|
|
|
if (const auto PMONITOR = g_pConfigManager->getBoundMonitorForWS(NAME); PMONITOR) {
|
|
|
|
monID = PMONITOR->ID;
|
|
|
|
}
|
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, monID, NAME, SPECIAL));
|
2022-10-24 19:36:31 +02:00
|
|
|
|
2023-11-18 18:00:24 +01:00
|
|
|
PWORKSPACE->m_fAlpha.setValueAndWarp(0);
|
|
|
|
|
2022-10-24 19:36:31 +02:00
|
|
|
return PWORKSPACE;
|
|
|
|
}
|
2022-11-19 17:41:36 +01:00
|
|
|
|
2023-01-08 14:19:18 +01:00
|
|
|
void CCompositor::renameWorkspace(const int& id, const std::string& name) {
|
|
|
|
const auto PWORKSPACE = getWorkspaceByID(id);
|
|
|
|
|
|
|
|
if (!PWORKSPACE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (isWorkspaceSpecial(id))
|
|
|
|
return;
|
|
|
|
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(LOG, "renameWorkspace: Renaming workspace {} to '{}'", id, name);
|
2023-01-08 14:19:18 +01:00
|
|
|
PWORKSPACE->m_szName = name;
|
2023-09-05 15:55:20 +02:00
|
|
|
|
|
|
|
g_pEventManager->postEvent({"renameworkspace", std::to_string(PWORKSPACE->m_iID) + "," + PWORKSPACE->m_szName});
|
2023-01-08 14:19:18 +01:00
|
|
|
}
|
|
|
|
|
2022-11-19 17:41:36 +01:00
|
|
|
void CCompositor::setActiveMonitor(CMonitor* pMonitor) {
|
|
|
|
if (m_pLastMonitor == pMonitor)
|
|
|
|
return;
|
|
|
|
|
2022-11-23 00:17:10 +01:00
|
|
|
if (!pMonitor) {
|
|
|
|
m_pLastMonitor = nullptr;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = pMonitor->activeWorkspace;
|
2022-11-19 17:41:36 +01:00
|
|
|
|
2024-02-22 16:12:51 +01:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + (PWORKSPACE ? PWORKSPACE->m_szName : "?")});
|
2023-02-19 21:54:53 +01:00
|
|
|
EMIT_HOOK_EVENT("focusedMon", pMonitor);
|
2022-11-19 17:41:36 +01:00
|
|
|
m_pLastMonitor = pMonitor;
|
|
|
|
}
|
2022-11-27 23:42:22 +01:00
|
|
|
|
|
|
|
bool CCompositor::isWorkspaceSpecial(const int& id) {
|
|
|
|
return id >= SPECIAL_WORKSPACE_START && id <= -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCompositor::getNewSpecialID() {
|
2023-07-16 21:00:38 +02:00
|
|
|
int highest = SPECIAL_WORKSPACE_START;
|
2022-11-27 23:42:22 +01:00
|
|
|
for (auto& ws : m_vWorkspaces) {
|
|
|
|
if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) {
|
|
|
|
highest = ws->m_iID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return highest + 1;
|
|
|
|
}
|
2023-03-20 16:02:47 +01:00
|
|
|
|
|
|
|
void CCompositor::performUserChecks() {
|
2024-01-27 14:58:13 +01:00
|
|
|
; // intentional
|
2023-03-20 16:02:47 +01:00
|
|
|
}
|
2023-04-14 16:03:53 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, PHLWORKSPACE pWorkspace) {
|
2023-04-14 16:03:53 +02:00
|
|
|
if (!pWindow || !pWorkspace)
|
|
|
|
return;
|
|
|
|
|
2023-05-29 17:46:06 +02:00
|
|
|
if (pWindow->m_bPinned && pWorkspace->m_bIsSpecialWorkspace)
|
|
|
|
return;
|
|
|
|
|
2023-04-30 00:39:09 +02:00
|
|
|
const bool FULLSCREEN = pWindow->m_bIsFullscreen;
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto FULLSCREENMODE = pWindow->m_pWorkspace->m_efFullscreenMode;
|
2023-04-14 16:03:53 +02:00
|
|
|
|
|
|
|
if (FULLSCREEN)
|
|
|
|
setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
pWindow->moveToWorkspace(pWorkspace);
|
2023-04-22 22:13:02 +02:00
|
|
|
|
2023-04-14 16:03:53 +02:00
|
|
|
if (!pWindow->m_bIsFloating) {
|
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow);
|
2024-04-02 21:32:39 +02:00
|
|
|
pWindow->m_pWorkspace = pWorkspace;
|
|
|
|
pWindow->m_iMonitorID = pWorkspace->m_iMonitorID;
|
2023-04-14 16:03:53 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow);
|
|
|
|
} else {
|
|
|
|
const auto PWINDOWMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
2024-03-02 01:35:17 +01:00
|
|
|
const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition;
|
2023-04-14 16:03:53 +02:00
|
|
|
|
|
|
|
const auto PWORKSPACEMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
pWindow->m_pWorkspace = pWorkspace;
|
|
|
|
pWindow->m_iMonitorID = pWorkspace->m_iMonitorID;
|
2023-04-14 16:03:53 +02:00
|
|
|
|
|
|
|
pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition;
|
|
|
|
}
|
|
|
|
|
2024-03-06 22:33:50 +01:00
|
|
|
pWindow->updateToplevel();
|
|
|
|
pWindow->updateDynamicRules();
|
|
|
|
pWindow->uncacheWindowDecos();
|
|
|
|
|
2023-06-21 20:51:18 +02:00
|
|
|
if (pWindow->m_sGroupData.pNextWindow) {
|
|
|
|
CWindow* next = pWindow->m_sGroupData.pNextWindow;
|
|
|
|
while (next != pWindow) {
|
2024-04-02 21:32:39 +02:00
|
|
|
next->moveToWorkspace(pWorkspace);
|
2023-06-21 20:51:18 +02:00
|
|
|
next->updateToplevel();
|
|
|
|
next = next->m_sGroupData.pNextWindow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-14 16:03:53 +02:00
|
|
|
if (FULLSCREEN)
|
2023-04-30 00:39:09 +02:00
|
|
|
setWindowFullscreen(pWindow, true, FULLSCREENMODE);
|
2023-12-20 23:52:18 +01:00
|
|
|
|
|
|
|
g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID);
|
2024-04-02 21:32:39 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID());
|
2023-04-14 16:03:53 +02:00
|
|
|
}
|
2023-07-04 12:05:25 +02:00
|
|
|
|
|
|
|
CWindow* CCompositor::getForceFocus() {
|
|
|
|
for (auto& w : m_vWindows) {
|
2024-04-03 11:09:42 +02:00
|
|
|
if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace))
|
2023-07-04 12:05:25 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!w->m_bStayFocused)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return w.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
2023-07-13 18:05:34 +02:00
|
|
|
|
|
|
|
void CCompositor::notifyIdleActivity() {
|
|
|
|
wlr_idle_notifier_v1_notify_activity(g_pCompositor->m_sWLRIdleNotifier, g_pCompositor->m_sSeat.seat);
|
|
|
|
}
|
|
|
|
|
2023-07-14 19:56:50 +02:00
|
|
|
void CCompositor::setIdleActivityInhibit(bool enabled) {
|
|
|
|
wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled);
|
2023-07-13 18:05:34 +02:00
|
|
|
}
|
2023-08-14 14:22:06 +02:00
|
|
|
void CCompositor::arrangeMonitors() {
|
2024-02-18 16:00:34 +01:00
|
|
|
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
|
2023-08-15 19:15:37 +02:00
|
|
|
|
2023-08-14 14:22:06 +02:00
|
|
|
std::vector<CMonitor*> toArrange;
|
|
|
|
std::vector<CMonitor*> arranged;
|
|
|
|
|
|
|
|
for (auto& m : m_vMonitors)
|
|
|
|
toArrange.push_back(m.get());
|
|
|
|
|
2023-09-06 12:51:36 +02:00
|
|
|
Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size());
|
2023-08-21 19:52:30 +02:00
|
|
|
|
2023-08-14 19:27:33 +02:00
|
|
|
for (auto it = toArrange.begin(); it != toArrange.end();) {
|
2023-08-14 14:22:06 +02:00
|
|
|
auto m = *it;
|
|
|
|
|
2023-08-16 18:16:36 +02:00
|
|
|
if (m->activeMonitorRule.offset != Vector2D{-INT32_MAX, -INT32_MAX}) {
|
2023-08-14 14:22:06 +02:00
|
|
|
// explicit.
|
2023-09-20 17:25:03 +02:00
|
|
|
Debug::log(LOG, "arrangeMonitors: {} explicit {:j2}", m->szName, m->activeMonitorRule.offset);
|
2023-08-21 19:52:30 +02:00
|
|
|
|
2023-08-14 14:22:06 +02:00
|
|
|
m->moveTo(m->activeMonitorRule.offset);
|
|
|
|
arranged.push_back(m);
|
|
|
|
it = toArrange.erase(it);
|
|
|
|
|
|
|
|
if (it == toArrange.end())
|
|
|
|
break;
|
2023-08-14 19:27:33 +02:00
|
|
|
|
|
|
|
continue;
|
2023-08-14 14:22:06 +02:00
|
|
|
}
|
2023-08-14 19:27:33 +02:00
|
|
|
|
|
|
|
++it;
|
2023-08-14 14:22:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// auto left
|
|
|
|
int maxOffset = 0;
|
|
|
|
for (auto& m : arranged) {
|
|
|
|
if (m->vecPosition.x + m->vecSize.x > maxOffset)
|
|
|
|
maxOffset = m->vecPosition.x + m->vecSize.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& m : toArrange) {
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(LOG, "arrangeMonitors: {} auto [{}, {:.2f}]", m->szName, maxOffset, 0.f);
|
2023-08-14 14:22:06 +02:00
|
|
|
m->moveTo({maxOffset, 0});
|
2023-08-25 13:11:32 +02:00
|
|
|
maxOffset += m->vecSize.x;
|
2023-08-14 14:22:06 +02:00
|
|
|
}
|
2023-08-15 19:15:37 +02:00
|
|
|
|
|
|
|
// reset maxOffset (reuse)
|
|
|
|
// and set xwayland positions aka auto for all
|
|
|
|
maxOffset = 0;
|
|
|
|
for (auto& m : m_vMonitors) {
|
2023-09-06 21:45:37 +02:00
|
|
|
Debug::log(LOG, "arrangeMonitors: {} xwayland [{}, {:.2f}]", m->szName, maxOffset, 0.f);
|
2023-08-15 19:15:37 +02:00
|
|
|
m->vecXWaylandPosition = {maxOffset, 0};
|
2024-03-03 19:39:20 +01:00
|
|
|
maxOffset += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x);
|
2023-09-20 17:47:05 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PXWLFORCESCALEZERO)
|
2023-09-20 17:47:05 +02:00
|
|
|
m->xwaylandScale = m->scale;
|
|
|
|
else
|
|
|
|
m->xwaylandScale = 1.f;
|
2023-08-15 19:15:37 +02:00
|
|
|
}
|
2023-08-14 14:22:06 +02:00
|
|
|
}
|
2023-09-24 19:04:38 +02:00
|
|
|
|
|
|
|
void CCompositor::enterUnsafeState() {
|
|
|
|
if (m_bUnsafeState)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Debug::log(LOG, "Entering unsafe state");
|
|
|
|
|
2023-11-01 19:53:36 +01:00
|
|
|
if (!m_pUnsafeOutput->m_bEnabled)
|
|
|
|
m_pUnsafeOutput->onConnect(false);
|
2023-09-24 19:04:38 +02:00
|
|
|
|
2023-11-01 19:53:36 +01:00
|
|
|
m_bUnsafeState = true;
|
2024-03-26 03:26:09 +01:00
|
|
|
|
|
|
|
setActiveMonitor(m_pUnsafeOutput);
|
2023-09-24 19:04:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::leaveUnsafeState() {
|
|
|
|
if (!m_bUnsafeState)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Debug::log(LOG, "Leaving unsafe state");
|
|
|
|
|
|
|
|
m_bUnsafeState = false;
|
|
|
|
|
2023-11-01 19:53:36 +01:00
|
|
|
CMonitor* pNewMonitor = nullptr;
|
|
|
|
for (auto& pMonitor : m_vMonitors) {
|
|
|
|
if (pMonitor->output != m_pUnsafeOutput->output) {
|
|
|
|
pNewMonitor = pMonitor.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RASSERT(pNewMonitor, "Tried to leave unsafe without a monitor");
|
|
|
|
|
|
|
|
if (m_pUnsafeOutput->m_bEnabled)
|
|
|
|
m_pUnsafeOutput->onDisconnect();
|
2023-09-24 19:04:38 +02:00
|
|
|
|
2023-11-01 19:53:36 +01:00
|
|
|
for (auto& m : m_vMonitors) {
|
|
|
|
scheduleFrameForMonitor(m.get());
|
|
|
|
}
|
2023-09-24 19:04:38 +02:00
|
|
|
}
|
2023-10-22 17:58:06 +02:00
|
|
|
|
|
|
|
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
|
|
|
|
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale);
|
2023-11-03 00:29:47 +01:00
|
|
|
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
|
2024-01-11 13:15:20 +01:00
|
|
|
|
|
|
|
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
|
|
|
if (!PSURFACE) {
|
|
|
|
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PSURFACE->m_fLastScale = scale;
|
|
|
|
PSURFACE->m_iLastScale = static_cast<int32_t>(std::ceil(scale));
|
2023-10-22 17:58:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
|
|
|
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
2024-01-11 13:15:20 +01:00
|
|
|
|
|
|
|
const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
|
|
|
if (!PSURFACE) {
|
|
|
|
Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PSURFACE->m_eLastTransform = transform;
|
2023-12-13 18:25:19 +01:00
|
|
|
}
|
2023-12-23 22:30:49 +01:00
|
|
|
|
|
|
|
void CCompositor::updateSuspendedStates() {
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
|
|
|
if (!w->m_bIsMapped)
|
|
|
|
continue;
|
|
|
|
|
2024-04-03 11:09:42 +02:00
|
|
|
w->setSuspended(w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace));
|
2023-12-23 22:30:49 +01:00
|
|
|
}
|
|
|
|
}
|