Hyprland/src/Compositor.cpp

1093 lines
37 KiB
C++
Raw Normal View History

2022-03-16 21:37:21 +01:00
#include "Compositor.hpp"
CCompositor::CCompositor() {
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL));
2022-03-18 23:52:36 +01:00
2022-06-03 17:48:07 +02:00
Debug::init(m_szInstanceSignature);
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str());
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
mkdir(INSTANCEPATH.c_str(), S_IRWXU | S_IRWXG);
2022-03-16 21:37:21 +01:00
m_sWLDisplay = wl_display_create();
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay);
if (!m_sWLRBackend) {
Debug::log(CRIT, "m_sWLRBackend was NULL!");
RIP("m_sWLRBackend NULL!");
return;
}
2022-04-04 19:44:25 +02:00
m_iDRMFD = wlr_backend_get_drm_fd(m_sWLRBackend);
if (m_iDRMFD < 0) {
2022-03-24 15:57:46 +01:00
Debug::log(CRIT, "Couldn't query the DRM FD!");
2022-03-24 17:17:08 +01:00
RIP("DRMFD NULL!");
2022-03-24 15:57:46 +01:00
return;
}
2022-04-04 19:44:25 +02:00
m_sWLRRenderer = wlr_gles2_renderer_create_with_drm_fd(m_iDRMFD);
2022-03-16 21:37:21 +01:00
if (!m_sWLRRenderer) {
Debug::log(CRIT, "m_sWLRRenderer was NULL!");
RIP("m_sWLRRenderer NULL!");
return;
}
2022-03-17 19:03:15 +01:00
wlr_renderer_init_wl_display(m_sWLRRenderer, m_sWLDisplay);
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!");
RIP("m_sWLRAllocator NULL!");
return;
}
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!");
RIP("m_sWLREGL NULL!");
return;
}
2022-03-16 21:37:21 +01:00
m_sWLRCompositor = wlr_compositor_create(m_sWLDisplay, m_sWLRRenderer);
2022-03-17 19:03:15 +01:00
m_sWLRSubCompositor = wlr_subcompositor_create(m_sWLDisplay);
m_sWLRDataDevMgr = wlr_data_device_manager_create(m_sWLDisplay);
2022-04-14 21:48:12 +02:00
m_sWLRDmabuf = wlr_linux_dmabuf_v1_create(m_sWLDisplay, m_sWLRRenderer);
2022-03-19 14:09:11 +01:00
wlr_export_dmabuf_manager_v1_create(m_sWLDisplay);
wlr_screencopy_manager_v1_create(m_sWLDisplay);
wlr_data_control_manager_v1_create(m_sWLDisplay);
wlr_gamma_control_manager_v1_create(m_sWLDisplay);
wlr_primary_selection_v1_device_manager_create(m_sWLDisplay);
wlr_viewporter_create(m_sWLDisplay);
2022-03-16 21:37:21 +01:00
m_sWLROutputLayout = wlr_output_layout_create();
2022-03-17 19:03:15 +01:00
m_sWLRScene = wlr_scene_create();
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
2022-03-16 21:37:21 +01:00
2022-05-27 16:05:25 +02:00
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 3);
2022-03-16 21:37:21 +01:00
m_sWLRCursor = wlr_cursor_create();
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
2022-03-17 19:03:15 +01:00
m_sWLRXCursorMgr = wlr_xcursor_manager_create(nullptr, 24);
wlr_xcursor_manager_load(m_sWLRXCursorMgr, 1);
2022-03-16 21:37:21 +01:00
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);
2022-03-18 20:42:49 +01:00
m_sWLRIdle = wlr_idle_create(m_sWLDisplay);
2022-03-19 13:54:24 +01:00
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay);
m_sWLRServerDecoMgr = wlr_server_decoration_manager_create(m_sWLDisplay);
m_sWLRXDGDecoMgr = wlr_xdg_decoration_manager_v1_create(m_sWLDisplay);
wlr_server_decoration_manager_set_default_mode(m_sWLRServerDecoMgr, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
2022-03-19 13:54:24 +01:00
wlr_xdg_output_manager_v1_create(m_sWLDisplay, m_sWLROutputLayout);
m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay);
2022-03-22 18:29:13 +01:00
m_sWLRInhibitMgr = wlr_input_inhibit_manager_create(m_sWLDisplay);
m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay);
m_sWLREXTWorkspaceMgr = wlr_ext_workspace_manager_v1_create(m_sWLDisplay);
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-03-16 21:37:21 +01:00
}
2022-03-17 15:53:45 +01:00
CCompositor::~CCompositor() {
cleanupExit();
}
2022-03-17 15:53:45 +01:00
void handleCritSignal(int signo) {
g_pCompositor->cleanupExit();
exit(signo);
2022-03-17 15:53:45 +01: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");
addWLSignal(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGSurface, m_sWLRXDGShell, "XDG Shell");
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");
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-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");
addWLSignal(&m_sWLRInhibitMgr->events.activate, &Events::listen_InhibitActivate, m_sWLRInhibitMgr, "InhibitMgr");
addWLSignal(&m_sWLRInhibitMgr->events.deactivate, &Events::listen_InhibitDeactivate, m_sWLRInhibitMgr, "InhibitMgr");
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
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");
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
signal(SIGINT, handleCritSignal);
signal(SIGTERM, handleCritSignal);
}
void CCompositor::cleanupExit() {
if (!m_sWLDisplay)
return;
2022-05-29 00:07:31 +02:00
m_pLastFocus = nullptr;
m_pLastWindow = nullptr;
m_lWorkspaces.clear();
m_lWindows.clear();
if (g_pXWaylandManager->m_sWLRXWayland) {
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
g_pXWaylandManager->m_sWLRXWayland = nullptr;
}
wl_display_destroy_clients(m_sWLDisplay);
wl_display_destroy(m_sWLDisplay);
m_sWLDisplay = nullptr;
2022-03-18 23:52:36 +01:00
}
2022-03-17 17:08:54 +01:00
2022-03-18 23:52:36 +01:00
void CCompositor::startCompositor() {
2022-03-17 17:08:54 +01:00
// Init all the managers BEFORE we start with the wayland server so that ALL of the stuff is initialized
// properly and we dont get any bad mem reads.
//
Debug::log(LOG, "Creating the CHyprError!");
g_pHyprError = std::make_unique<CHyprError>();
2022-03-19 17:48:18 +01:00
Debug::log(LOG, "Creating the KeybindManager!");
g_pKeybindManager = std::make_unique<CKeybindManager>();
2022-04-23 21:47:16 +02:00
Debug::log(LOG, "Creating the AnimationManager!");
g_pAnimationManager = std::make_unique<CAnimationManager>();
2022-03-18 20:03:39 +01:00
Debug::log(LOG, "Creating the ConfigManager!");
2022-03-17 17:08:54 +01:00
g_pConfigManager = std::make_unique<CConfigManager>();
2022-03-18 20:03:39 +01:00
Debug::log(LOG, "Creating the ThreadManager!");
g_pThreadManager = std::make_unique<CThreadManager>();
2022-03-17 17:08:54 +01:00
Debug::log(LOG, "Creating the InputManager!");
g_pInputManager = std::make_unique<CInputManager>();
2022-03-17 20:22:29 +01:00
2022-04-04 19:44:25 +02:00
Debug::log(LOG, "Creating the CHyprOpenGLImpl!");
g_pHyprOpenGL = std::make_unique<CHyprOpenGLImpl>();
2022-03-17 20:22:29 +01:00
Debug::log(LOG, "Creating the HyprRenderer!");
g_pHyprRenderer = std::make_unique<CHyprRenderer>();
2022-03-18 20:03:39 +01:00
Debug::log(LOG, "Creating the XWaylandManager!");
g_pXWaylandManager = std::make_unique<CHyprXWaylandManager>();
Debug::log(LOG, "Creating the LayoutManager!");
g_pLayoutManager = std::make_unique<CLayoutManager>();
Debug::log(LOG, "Creating the EventManager!");
g_pEventManager = std::make_unique<CEventManager>();
g_pEventManager->startThread();
2022-05-28 17:32:19 +02:00
Debug::log(LOG, "Creating the HyprDebugOverlay!");
g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
2022-03-17 17:08:54 +01:00
//
//
2022-03-18 23:52:36 +01:00
initAllSignals();
// Set some env vars so that Firefox is automatically in Wayland mode
// and QT apps too
// electron needs -- flags so we can't really set them here
setenv("QT_QPA_PLATFORM", "wayland", true);
setenv("MOZ_ENABLE_WAYLAND", "1", true);
2022-03-31 19:16:00 +02:00
// Set XDG_CURRENT_DESKTOP to our compositor's name
setenv("XDG_CURRENT_DESKTOP", "hyprland", true);
2022-03-16 21:37:21 +01:00
m_szWLDisplaySocket = wl_display_add_socket_auto(m_sWLDisplay);
if (!m_szWLDisplaySocket) {
Debug::log(CRIT, "m_szWLDisplaySocket NULL!");
2022-03-17 19:03:15 +01:00
wlr_backend_destroy(m_sWLRBackend);
2022-03-16 21:37:21 +01:00
RIP("m_szWLDisplaySocket NULL!");
}
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket, 1);
signal(SIGPIPE, SIG_IGN);
2022-03-17 15:53:45 +01:00
Debug::log(LOG, "Running on WAYLAND_DISPLAY: %s", 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);
2022-03-16 21:37:21 +01:00
RIP("Backend did not start!");
}
wlr_xcursor_manager_set_cursor_image(m_sWLRXCursorMgr, "left_ptr", m_sWLRCursor);
// This blocks until we are done.
Debug::log(LOG, "Hyprland is ready, running the event loop!");
wl_display_run(m_sWLDisplay);
2022-03-17 20:22:29 +01:00
}
SMonitor* CCompositor::getMonitorFromID(const int& id) {
2022-03-18 22:35:51 +01:00
for (auto& m : m_lMonitors) {
2022-03-20 11:23:36 +01:00
if (m.ID == (uint64_t)id) {
2022-03-17 20:22:29 +01:00
return &m;
}
}
return nullptr;
}
SMonitor* CCompositor::getMonitorFromName(const std::string& name) {
for (auto& m : m_lMonitors) {
if (m.szName == name) {
return &m;
}
}
return nullptr;
}
2022-03-17 20:22:29 +01:00
SMonitor* 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
return getMonitorFromVector(COORDS);
2022-03-18 22:35:51 +01:00
}
SMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
const auto OUTPUT = wlr_output_layout_output_at(m_sWLROutputLayout, point.x, point.y);
if (!OUTPUT) {
float bestDistance = 0.f;
SMonitor* pBestMon = nullptr;
for (auto& m : m_lMonitors) {
float dist = vecToRectDistanceSquared(point, m.vecPosition, m.vecPosition + m.vecSize);
if (dist < bestDistance || !pBestMon) {
bestDistance = dist;
pBestMon = &m;
}
}
if (!pBestMon) { // ?????
Debug::log(WARN, "getMonitorFromVector no close mon???");
return &m_lMonitors.front();
}
return pBestMon;
}
return getMonitorFromOutput(OUTPUT);
}
2022-03-18 22:35:51 +01:00
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
2022-04-05 19:28:10 +02:00
if (windowExists(pWindow) && !pWindow->m_bFadingOut)
2022-03-18 23:16:15 +01:00
m_lWindows.remove(*pWindow);
2022-03-18 22:53:27 +01:00
}
bool CCompositor::windowExists(CWindow* pWindow) {
for (auto& w : m_lWindows) {
if (&w == pWindow)
return true;
}
return false;
}
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
2022-03-20 15:55:47 +01:00
const auto PMONITOR = getMonitorFromVector(pos);
2022-05-31 14:01:00 +02:00
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && !w.m_bHidden)
return &w;
}
}
2022-04-04 16:25:30 +02:00
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
2022-04-23 14:16:02 +02:00
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden)
return &(*w);
}
for (auto& w : m_lWindows) {
2022-04-23 14:16:02 +02:00
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && PMONITOR->activeWorkspace == w.m_iWorkspaceID && !w.m_bHidden)
2022-03-18 22:53:27 +01:00
return &w;
}
return nullptr;
}
2022-03-20 18:31:58 +01:00
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos);
2022-05-31 14:01:00 +02:00
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && !w.m_bHidden)
return &w;
}
}
2022-03-20 18:31:58 +01:00
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden)
2022-03-20 18:31:58 +01:00
return &w;
}
return nullptr;
}
2022-03-19 17:48:18 +01:00
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
2022-03-20 15:55:47 +01:00
const auto PMONITOR = getMonitorFromVector(pos);
2022-05-31 14:01:00 +02:00
// special workspace
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bHidden)
return &w;
}
}
2022-04-04 16:25:30 +02:00
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
2022-04-23 14:16:02 +02:00
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden)
return &(*w);
2022-03-20 11:14:24 +01:00
}
2022-03-19 20:30:21 +01:00
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (!w.m_bIsFloating && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bHidden)
2022-03-19 20:30:21 +01:00
return &w;
}
return nullptr;
}
CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor();
2022-03-20 11:14:24 +01:00
2022-05-31 14:01:00 +02:00
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped)
return &w;
}
}
2022-04-04 16:25:30 +02:00
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
2022-04-23 14:16:02 +02:00
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID))
return &(*w);
2022-03-20 11:14:24 +01:00
}
2022-03-19 17:48:18 +01:00
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
2022-03-30 21:18:42 +02:00
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped && w.m_iWorkspaceID == PMONITOR->activeWorkspace)
2022-03-19 17:48:18 +01:00
return &w;
}
return nullptr;
}
2022-03-20 11:14:24 +01:00
CWindow* CCompositor::windowFloatingFromCursor() {
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
2022-04-23 14:16:02 +02:00
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden)
return &(*w);
2022-03-20 11:14:24 +01:00
}
return nullptr;
}
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-04-02 13:02:16 +02:00
double subx, suby;
2022-04-23 14:16:02 +02:00
const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x, pos.y - pWindow->m_vRealPosition.vec().y, &subx, &suby);
2022-04-02 13:02:16 +02:00
if (PFOUND) {
sl.x = subx;
sl.y = suby;
return PFOUND;
}
2022-04-23 14:16:02 +02:00
sl.x = pos.x - pWindow->m_vRealPosition.vec().x;
sl.y = pos.y - pWindow->m_vRealPosition.vec().y;
2022-04-02 13:02:16 +02:00
return PSURFACE->surface;
}
2022-03-19 20:56:19 +01:00
SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
for (auto& m : m_lMonitors) {
if (m.output == out) {
return &m;
}
}
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
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;
}
2022-05-14 20:56:21 +02:00
if (!pWindow || !windowValidMapped(pWindow)) {
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
2022-05-14 14:37:57 +02:00
return;
}
2022-05-14 20:56:21 +02:00
if (pWindow->m_bNoFocus) {
Debug::log(LOG, "Ignoring focus to nofocus window!");
2022-03-18 22:53:27 +01:00
return;
}
if (m_pLastWindow == pWindow && m_sSeat.seat->keyboard_state.focused_surface == pSurface)
2022-04-05 18:29:58 +02:00
return;
2022-04-23 14:16:02 +02:00
const auto PLASTWINDOW = m_pLastWindow;
m_pLastWindow = pWindow;
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
if (windowValidMapped(PLASTWINDOW)) {
2022-05-26 21:23:13 +02:00
updateWindowBorderColor(PLASTWINDOW);
2022-04-23 14:16:02 +02:00
if (PLASTWINDOW->m_bIsX11) {
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
wlr_seat_pointer_clear_focus(m_sSeat.seat);
}
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;
2022-04-02 18:57:09 +02:00
const auto PWINDOWSURFACE = pSurface ? pSurface : g_pXWaylandManager->getWindowSurface(pWindow);
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
// do pointer focus too
const auto POINTERLOCAL = g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.goalv();
wlr_seat_pointer_notify_enter(m_sSeat.seat, PWINDOWSURFACE, POINTERLOCAL.x, POINTERLOCAL.y);
2022-04-13 20:19:40 +02:00
2022-05-26 21:23:13 +02:00
updateWindowBorderColor(pWindow);
// Send an event
2022-05-26 21:24:52 +02:00
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle));
2022-05-29 11:24:42 +02:00
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
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
2022-04-02 13:02:16 +02:00
if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == g_pXWaylandManager->getWindowSurface(pWindowOwner)))
2022-03-20 14:36:55 +01:00
return; // Don't focus when already focused on this.
2022-03-27 19:16:33 +02:00
if (!pSurface)
return;
2022-03-31 21:47:03 +02:00
// Unfocus last surface if should
2022-04-02 18:57:09 +02:00
if (m_pLastFocus && m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus))
wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(m_pLastFocus)->toplevel, false);
2022-03-19 10:53:39 +01:00
2022-03-22 18:29:13 +01:00
const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat);
2022-03-27 19:16:33 +02:00
if (!KEYBOARD)
return;
2022-03-22 18:29:13 +01:00
wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
2022-03-18 22:53:27 +01:00
2022-04-02 19:09:27 +02:00
wlr_seat_keyboard_focus_change_event event = {
.seat = m_sSeat.seat,
.old_surface = m_pLastFocus,
.new_surface = pSurface,
};
wlr_signal_emit_safe(&m_sSeat.seat->keyboard_state.events.focus_change, &event);
if (pWindowOwner)
Debug::log(LOG, "Set keyboard focus to surface %x, with window name: %s", pSurface, pWindowOwner->m_szTitle.c_str());
2022-03-31 19:41:55 +02:00
else
Debug::log(LOG, "Set keyboard focus to surface %x", pSurface);
2022-03-18 23:16:15 +01:00
}
bool CCompositor::windowValidMapped(CWindow* pWindow) {
if (!windowExists(pWindow))
return false;
if (pWindow->m_bIsX11 && !pWindow->m_bMappedX11)
return false;
2022-03-22 20:53:11 +01:00
if (!pWindow->m_bIsMapped)
return false;
if (pWindow->m_bHidden)
return false;
2022-03-18 23:16:15 +01:00
if (!g_pXWaylandManager->getWindowSurface(pWindow))
return false;
return true;
2022-03-20 12:11:57 +01:00
}
2022-03-20 14:00:46 +01:00
CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
for (auto& p : m_lXDGPopups) {
if (p.popup == popup)
return p.parentWindow;
}
2022-03-20 14:36:55 +01:00
return nullptr;
}
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::list<SLayerSurface*>* layerSurfaces, Vector2D* sCoords) {
for (auto& l : *layerSurfaces) {
if (l->fadingOut || (l->layerSurface && !l->layerSurface->mapped))
2022-03-20 14:36:55 +01:00
continue;
const auto SURFACEAT = wlr_layer_surface_v1_surface_at(l->layerSurface, pos.x - l->geometry.x, pos.y - l->geometry.y, &sCoords->x, &sCoords->y);
if (SURFACEAT)
return SURFACEAT;
}
return nullptr;
}
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
for (auto& w : m_lWindows) {
if (g_pXWaylandManager->getWindowSurface(&w) == pSurface)
return &w;
}
2022-03-20 15:55:47 +01:00
return nullptr;
}
2022-03-21 19:18:33 +01:00
CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == ID && w.m_bIsFullscreen)
return &w;
}
return nullptr;
}
2022-03-20 15:55:47 +01:00
bool CCompositor::isWorkspaceVisible(const int& w) {
for (auto& m : m_lMonitors) {
if (m.activeWorkspace == w)
return true;
2022-05-31 14:01:00 +02:00
if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
return true;
2022-03-20 15:55:47 +01:00
}
return false;
}
CWorkspace* CCompositor::getWorkspaceByID(const int& id) {
2022-03-20 15:55:47 +01:00
for (auto& w : m_lWorkspaces) {
if (w.m_iID == id)
2022-03-20 15:55:47 +01:00
return &w;
}
return nullptr;
}
void CCompositor::sanityCheckWorkspaces() {
for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) {
if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) {
2022-03-20 15:55:47 +01:00
it = m_lWorkspaces.erase(it);
}
2022-05-31 14:01:00 +02:00
if (it->m_iID == SPECIAL_WORKSPACE_ID && getWindowsOnWorkspace(it->m_iID) == 0) {
for (auto& m : m_lMonitors) {
m.specialWorkspaceOpen = false;
}
it = m_lWorkspaces.erase(it);
}
2022-03-20 15:55:47 +01:00
}
}
int CCompositor::getWindowsOnWorkspace(const int& id) {
int no = 0;
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id && w.m_bIsMapped)
2022-03-20 15:55:47 +01:00
no++;
}
return no;
}
CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id)
return &w;
}
2022-03-20 14:00:46 +01:00
return nullptr;
}
void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
const auto ISVISIBLE = isWorkspaceVisible(id);
2022-03-21 19:18:33 +01:00
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
2022-05-30 20:05:38 +02:00
if (!PWORKSPACE)
return;
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == id) {
// moveXWaylandWindow only moves XWayland windows
// so there is no need to check here
// if the window is XWayland or not.
if (ISVISIBLE && (!PWORKSPACE->m_bHasFullscreenWindow || w.m_bIsFullscreen))
2022-04-23 14:16:02 +02:00
g_pXWaylandManager->moveXWaylandWindow(&w, w.m_vRealPosition.vec());
else
g_pXWaylandManager->moveXWaylandWindow(&w, Vector2D(42069,42069));
}
}
2022-03-22 18:29:13 +01:00
}
bool CCompositor::doesSeatAcceptInput(wlr_surface* surface) {
2022-03-22 21:59:14 +01:00
return !m_sSeat.exclusiveClient || (surface && m_sSeat.exclusiveClient == wl_resource_get_client(surface->resource));
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;
2022-04-02 18:57:09 +02:00
if (!windowValidMapped(pWindow))
return false;
2022-04-02 13:02:16 +02:00
const auto PSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
2022-04-02 18:57:09 +02:00
return PSURFACE == m_pLastFocus || pWindow == m_pLastWindow;
2022-04-04 16:25:30 +02:00
}
void CCompositor::moveWindowToTop(CWindow* pWindow) {
if (!windowValidMapped(pWindow))
return;
for (auto it = m_lWindows.begin(); it != m_lWindows.end(); ++it) {
if (&(*it) == pWindow) {
m_lWindows.splice(m_lWindows.end(), m_lWindows, it);
break;
}
}
2022-04-05 19:28:10 +02:00
}
void CCompositor::cleanupFadingOut() {
2022-04-05 19:28:10 +02:00
for (auto& w : m_lWindowsFadingOut) {
2022-04-26 17:51:00 +02:00
2022-04-28 15:39:49 +02:00
bool valid = windowExists(w);
2022-04-26 17:51:00 +02:00
if (!valid || !w->m_bFadingOut || w->m_fAlpha.fl() == 0.f) {
if (valid && !w->m_bReadyToDelete)
continue;
2022-04-05 20:49:15 +02:00
g_pHyprOpenGL->m_mWindowFramebuffers[w].release();
g_pHyprOpenGL->m_mWindowFramebuffers.erase(w);
m_lWindows.remove(*w);
m_lWindowsFadingOut.remove(w);
Debug::log(LOG, "Cleanup: destroyed a window");
2022-04-05 19:28:10 +02:00
return;
}
}
for (auto& ls : m_lSurfacesFadingOut) {
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
for (auto& m : m_lMonitors) {
for (auto& lsl : m.m_aLayerSurfaceLists) {
lsl.remove(ls);
}
}
g_pHyprOpenGL->m_mLayerFramebuffers[ls].release();
g_pHyprOpenGL->m_mLayerFramebuffers.erase(ls);
delete ls;
2022-05-17 18:37:14 +02:00
m_lSurfacesFadingOut.remove(ls);
2022-05-14 17:28:55 +02:00
Debug::log(LOG, "Cleanup: destroyed a layersurface");
return;
}
}
2022-04-09 13:26:55 +02:00
}
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
const auto POSA = pWindow->m_vPosition;
const auto SIZEA = pWindow->m_vSize;
auto longestIntersect = -1;
CWindow* longestIntersectWindow = nullptr;
for (auto& w : m_lWindows) {
if (&w == pWindow || !windowValidMapped(&w) || w.m_bIsFloating || w.m_iWorkspaceID != pWindow->m_iWorkspaceID)
continue;
const auto POSB = w.m_vPosition;
const auto SIZEB = w.m_vSize;
switch (dir) {
case 'l':
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
}
}
break;
case 'r':
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
}
}
break;
case 't':
case 'u':
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
}
}
break;
case 'b':
case 'd':
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w;
}
}
break;
}
}
if (longestIntersect != -1)
return longestIntersectWindow;
return nullptr;
}
2022-04-28 17:55:25 +02:00
void CCompositor::deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude) {
for (auto& w : m_lWorkspaces) {
2022-04-28 17:55:25 +02:00
if (w.m_pWlrHandle && w.m_pWlrHandle != exclude)
2022-05-25 10:25:36 +02:00
w.setActive(false);
}
2022-04-13 20:45:06 +02:00
}
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
bool gotToWindow = false;
for (auto& w : m_lWindows) {
if (&w != pWindow && !gotToWindow)
continue;
if (&w == pWindow) {
gotToWindow = true;
continue;
}
if (w.m_iWorkspaceID == pWindow->m_iWorkspaceID && windowValidMapped(&w))
return &w;
}
for (auto& w : m_lWindows) {
if (&w != pWindow && w.m_iWorkspaceID == pWindow->m_iWorkspaceID && windowValidMapped(&w))
return &w;
}
2022-04-21 16:38:48 +02:00
return nullptr;
}
int CCompositor::getNextAvailableNamedWorkspace() {
2022-04-21 21:35:08 +02:00
int lowest = -1337 + 1;
2022-04-21 16:38:48 +02:00
for (auto& w : m_lWorkspaces) {
2022-04-21 21:48:37 +02:00
if (w.m_iID < -1 && w.m_iID < lowest)
2022-04-21 21:35:08 +02:00
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
}
CWorkspace* CCompositor::getWorkspaceByName(const std::string& name) {
for (auto& w : m_lWorkspaces) {
if (w.m_szName == name)
return &w;
}
return nullptr;
}
CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
if (str.find("name:") == 0) {
return getWorkspaceByName(str.substr(str.find_first_of(':') + 1));
}
try {
std::string name = "";
return getWorkspaceByID(getWorkspaceIDFromString(str, name));
2022-04-21 16:38:48 +02:00
} catch (std::exception& e) {
Debug::log(ERR, "Error in getWorkspaceByString, invalid id");
}
2022-04-13 20:45:06 +02:00
return nullptr;
2022-04-23 14:16:02 +02:00
}
bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
for (auto& m : m_lMonitors) {
if (VECINRECT(point, m.vecPosition.x, m.vecPosition.y, m.vecSize.x + m.vecPosition.x, m.vecSize.y + m.vecPosition.y))
return true;
}
return false;
2022-04-25 13:40:46 +02:00
}
CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
if (!pMouse->currentConstraint)
return nullptr;
const auto PSURFACE = pMouse->currentConstraint->surface;
for (auto& w : m_lWindows) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(&w)) {
if (!w.m_bIsX11 && !windowValidMapped(&w))
continue;
return &w;
}
}
2022-05-05 12:50:25 +02:00
return nullptr;
}
SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
const auto POSA = m_pLastMonitor->vecPosition;
const auto SIZEA = m_pLastMonitor->vecSize;
auto longestIntersect = -1;
SMonitor* longestIntersectMonitor = nullptr;
for (auto& m : m_lMonitors) {
if (&m == m_pLastMonitor)
continue;
const auto POSB = m.vecPosition;
const auto SIZEB = m.vecSize;
switch (dir) {
case 'l':
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
}
}
break;
case 'r':
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
}
}
break;
case 't':
case 'u':
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
}
}
break;
case 'b':
case 'd':
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m;
}
}
break;
}
}
if (longestIntersect != -1)
return longestIntersectMonitor;
2022-04-25 13:40:46 +02:00
return nullptr;
}
2022-05-26 21:23:13 +02:00
void CCompositor::updateAllWindowsBorders() {
for (auto& w : m_lWindows) {
if (!w.m_bIsMapped)
continue;
updateWindowBorderColor(&w);
}
}
void CCompositor::updateWindowBorderColor(CWindow* pWindow) {
// optimization
static int64_t* ACTIVECOL = &g_pConfigManager->getConfigValuePtr("general:col.active_border")->intValue;
static int64_t* INACTIVECOL = &g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->intValue;
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
if (RENDERDATA.isBorderColor)
pWindow->m_cRealBorderColor = RENDERDATA.borderColor;
else
pWindow->m_cRealBorderColor = CColor(pWindow == m_pLastWindow ? *ACTIVECOL : *INACTIVECOL);
2022-05-30 17:11:35 +02:00
}
void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& work) {
m_pLastWindow = pWindow;
g_pKeybindManager->moveActiveToWorkspace(work);
g_pInputManager->refocus();
}
int CCompositor::getNextAvailableMonitorID() {
int64_t topID = -1;
for (auto& m : m_lMonitors) {
if ((int64_t)m.ID > topID)
topID = m.ID;
}
return topID + 1;
}
2022-05-30 20:05:38 +02:00
void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMonitor) {
// We trust the workspace and monitor to be correct.
if (pWorkspace->m_iMonitorID == pMonitor->ID)
return;
Debug::log(LOG, "moveWorkspaceToMonitor: Moving %d to monitor %d", pWorkspace->m_iID, pMonitor->ID);
const auto POLDMON = getMonitorFromID(pWorkspace->m_iMonitorID);
const bool SWITCHINGISACTIVE = POLDMON->activeWorkspace == pWorkspace->m_iID;
// fix old mon
int nextWorkspaceOnMonitorID = -1;
for (auto& w : m_lWorkspaces) {
if (w.m_iMonitorID == POLDMON->ID && w.m_iID != pWorkspace->m_iID) {
nextWorkspaceOnMonitorID = w.m_iID;
break;
}
}
if (nextWorkspaceOnMonitorID == -1) {
nextWorkspaceOnMonitorID = 1;
while (getWorkspaceByID(nextWorkspaceOnMonitorID))
nextWorkspaceOnMonitorID++;
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new %d", nextWorkspaceOnMonitorID);
}
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing %d", nextWorkspaceOnMonitorID);
g_pKeybindManager->focusMonitor(std::to_string(POLDMON->ID));
g_pKeybindManager->changeworkspace(std::to_string(nextWorkspaceOnMonitorID));
// move the workspace
pWorkspace->m_iMonitorID = pMonitor->ID;
pWorkspace->moveToMonitor(pMonitor->ID);
2022-05-30 20:05:38 +02:00
for (auto& w : m_lWindows) {
if (w.m_iWorkspaceID == pWorkspace->m_iID)
w.m_iMonitorID = pMonitor->ID;
}
if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't.
Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active %d -> %d", pMonitor->activeWorkspace, pWorkspace->m_iID);
if (const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace); PWORKSPACE)
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
2022-05-30 20:05:38 +02:00
pMonitor->activeWorkspace = pWorkspace->m_iID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
pWorkspace->startAnim(true, true, true);
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2);
}
// finalize
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
g_pInputManager->refocus();
}
bool CCompositor::workspaceIDOutOfBounds(const int& id) {
int lowestID = 99999;
int highestID = -99999;
for (auto& w : m_lWorkspaces) {
if (w.m_iID < lowestID)
lowestID = w.m_iID;
if (w.m_iID > highestID)
highestID = w.m_iID;
}
return std::clamp(id, lowestID, highestID) != id;
2022-05-30 20:05:38 +02:00
}