2022-03-16 21:37:21 +01:00
# include "Compositor.hpp"
2022-07-10 15:41:26 +02:00
# include "helpers/Splashes.hpp"
# 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>
2022-03-16 21:37:21 +01:00
2022-07-13 18:18:23 +02:00
int handleCritSignal ( int signo , void * data ) {
Debug : : log ( LOG , " Hyprland received signal %d " , signo ) ;
if ( signo = = SIGTERM | | signo = = SIGINT | | signo = = SIGKILL ) {
g_pCompositor - > cleanup ( ) ;
}
return 0 ; // everything went fine
}
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-02-27 13:32:38 +01:00
if ( g_pHookSystem - > m_bCurrentEventPlugin ) {
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
}
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 " ) ;
std : : filesystem : : permissions ( " /tmp/hypr " , std : : filesystem : : perms : : all , std : : filesystem : : perm_options : : replace ) ;
}
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 ) ;
2022-06-03 17:41:57 +02:00
Debug : : log ( LOG , " Instance Signature: %s " , m_szInstanceSignature . c_str ( ) ) ;
2022-08-28 11:19:08 +02:00
Debug : : log ( LOG , " Hyprland PID: %i " , m_iHyprlandPID ) ;
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 ( ) ;
Debug : : log ( LOG , " \n Current splash: %s \n \n " , m_szCurrentSplash . c_str ( ) ) ;
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 ) ;
2023-03-01 16:08:44 +01:00
signal ( SIGSEGV , handleUnrecoverableSignal ) ;
signal ( SIGABRT , handleUnrecoverableSignal ) ;
2022-07-13 18:18:23 +02:00
//wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr);
2023-03-05 14:37:21 +01:00
initManagers ( STAGE_PRIORITY ) ;
wlr_log_init ( WLR_INFO , NULL ) ;
const auto LOGWLR = getenv ( " HYPRLAND_LOG_WLR " ) ;
if ( LOGWLR & & std : : string ( LOGWLR ) = = " 1 " )
wlr_log_init ( WLR_DEBUG , Debug : : wlrLog ) ;
2022-11-19 17:28:04 +01:00
m_sWLRBackend = wlr_backend_autocreate ( m_sWLDisplay , & m_sWLRSession ) ;
2022-03-16 21:37:21 +01:00
if ( ! m_sWLRBackend ) {
Debug : : log ( CRIT , " m_sWLRBackend was NULL! " ) ;
2022-07-06 16:17:58 +02:00
throw std : : runtime_error ( " wlr_backend_autocreate() failed! " ) ;
2022-03-16 21:37:21 +01:00
}
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-07-06 16:17:58 +02:00
throw std : : runtime_error ( " wlr_backend_get_drm_fd() failed! " ) ;
2022-03-24 15:57:46 +01:00
}
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! " ) ;
2022-07-06 16:17:58 +02:00
throw std : : runtime_error ( " 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! " ) ;
2022-07-06 16:17:58 +02:00
throw std : : runtime_error ( " 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! " ) ;
2022-07-06 16:17:58 +02:00
throw std : : runtime_error ( " 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 ) ;
2022-03-16 21:37:21 +01:00
m_sWLROutputLayout = wlr_output_layout_create ( ) ;
2022-07-30 22:41:24 +02:00
m_sWLROutputPowerMgr = wlr_output_power_manager_v1_create ( m_sWLDisplay ) ;
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-10-20 19:04:21 +02:00
m_sWLRXDGShell = wlr_xdg_shell_create ( m_sWLDisplay , 5 ) ;
2022-03-16 21:37:21 +01:00
m_sWLRCursor = wlr_cursor_create ( ) ;
wlr_cursor_attach_output_layout ( m_sWLRCursor , m_sWLROutputLayout ) ;
2022-10-17 15:01:04 +02:00
if ( const auto XCURSORENV = getenv ( " XCURSOR_SIZE " ) ; ! XCURSORENV | | std : : string ( XCURSORENV ) . empty ( ) )
setenv ( " XCURSOR_SIZE " , " 24 " , true ) ;
2023-03-01 14:54:48 +01:00
const auto XCURSORENV = getenv ( " XCURSOR_SIZE " ) ;
int cursorSize = 24 ;
try {
cursorSize = std : : stoi ( XCURSORENV ) ;
} catch ( std : : exception & e ) { Debug : : log ( ERR , " XCURSOR_SIZE invalid in check #2? (%s) " , XCURSORENV ) ; }
m_sWLRXCursorMgr = wlr_xcursor_manager_create ( nullptr , cursorSize ) ;
wlr_xcursor_manager_load ( m_sWLRXCursorMgr , 1 ) ;
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
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-06-23 21:14:04 +02:00
m_sWLRXDGOutputMgr = 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
2022-12-16 18:17:31 +01:00
m_sWLRInhibitMgr = wlr_input_inhibit_manager_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
m_sWLREXTWorkspaceMgr = wlr_ext_workspace_manager_v1_create ( m_sWLDisplay ) ;
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
m_sWLRHeadlessBackend = wlr_headless_backend_create ( m_sWLDisplay ) ;
2023-02-03 12:58:55 +01:00
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create ( m_sWLDisplay ) ;
2022-11-05 19:04:44 +01:00
if ( ! m_sWLRHeadlessBackend ) {
Debug : : log ( CRIT , " Couldn't create the headless backend " ) ;
throw std : : runtime_error ( " wlr_headless_backend_create() failed! " ) ;
}
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 " ) ;
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 " ) ;
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 " ) ;
addWLSignal ( & m_sWLRInhibitMgr - > events . activate , & Events : : listen_InhibitActivate , m_sWLRInhibitMgr , " InhibitMgr " ) ;
addWLSignal ( & m_sWLRInhibitMgr - > events . deactivate , & Events : : listen_InhibitDeactivate , m_sWLRInhibitMgr , " InhibitMgr " ) ;
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 " ) ;
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
}
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 ;
2022-10-24 01:14:42 +02:00
m_bIsShuttingDown = true ;
2023-07-06 15:24:49 +02:00
# ifdef USES_SYSTEMD
if ( sd_booted ( ) > 0 )
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 ( ) ) ;
2022-08-25 21:35:47 +02:00
wlr_output_enable ( m - > output , false ) ;
wlr_output_commit ( m - > output ) ;
}
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 ;
}
2023-03-09 15:19:41 +01:00
wl_display_destroy_clients ( g_pCompositor - > m_sWLDisplay ) ;
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 : {
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 ( ) ;
} break ;
case STAGE_LATE : {
Debug : : log ( LOG , " Creating the ThreadManager! " ) ;
g_pThreadManager = std : : make_unique < CThreadManager > ( ) ;
2022-03-17 20:22:29 +01:00
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-03-05 14:37:21 +01:00
} break ;
default : UNREACHABLE ( ) ;
}
}
2022-08-01 23:31:25 +02:00
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 ;
Debug : : log ( LOG , " wl_display_add_socket for %s succeeded with %i " , CANDIDATESTR . c_str ( ) , RETVAL ) ;
2022-12-05 18:21:09 +01:00
break ;
2023-01-19 16:44:23 +01:00
} else {
Debug : : log ( WARN , " wl_display_add_socket for %s returned %i: skipping candidate %i " , CANDIDATESTR . c_str ( ) , 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-01-19 16:44:23 +01:00
throw std : : runtime_error ( " 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 ) ;
2022-11-04 12:30:25 +01:00
if ( m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */ & & fork ( ) = = 0 )
2023-03-04 16:20:23 +01:00
execl (
" /bin/sh " , " /bin/sh " , " -c " ,
2023-04-15 21:03:09 +02:00
# ifdef USES_SYSTEMD
2023-03-04 16:20:23 +01:00
" systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && hash dbus-update-activation-environment 2>/dev/null && "
2023-04-15 21:03:09 +02:00
# endif
2023-03-04 16:20:23 +01:00
" dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE " ,
nullptr ) ;
2022-11-04 11:37:14 +01:00
2022-12-07 23:47:32 +01:00
Debug : : log ( LOG , " Running on WAYLAND_DISPLAY: %s " , m_szWLDisplaySocket . c_str ( ) ) ;
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-07-06 16:17:58 +02:00
throw std : : runtime_error ( " The backend could not start! " ) ;
2022-03-16 21:37:21 +01:00
}
wlr_xcursor_manager_set_cursor_image ( m_sWLRXCursorMgr , " left_ptr " , m_sWLRCursor ) ;
2023-01-05 20:17:55 +01:00
# ifdef USES_SYSTEMD
if ( sd_booted ( ) > 0 )
// tell systemd that we are ready so it can start other bond, following, related units
sd_notify ( 0 , " READY=1 " ) ;
2023-01-08 14:19:18 +01:00
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
2022-03-16 21:37:21 +01:00
// 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
}
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 ) {
if ( desc = = m - > output - > description ) {
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 ) {
2023-04-06 21:59:44 +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 ; } ) ;
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 ;
}
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
2022-11-27 23:42:22 +01:00
if ( PMONITOR - > specialWorkspaceID ) {
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 21:59:44 +02:00
if ( w - > m_bIsFloating & & w - > m_iWorkspaceID = = PMONITOR - > specialWorkspaceID & & w - > m_bIsMapped & & wlr_box_contains_point ( & box , pos . x , pos . y ) & & ! w - > isHidden ( ) & &
! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-07-06 11:07:23 +02:00
}
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 21:59:44 +02:00
if ( w - > m_iWorkspaceID = = PMONITOR - > specialWorkspaceID & & wlr_box_contains_point ( & box , pos . x , pos . y ) & & w - > m_bIsMapped & & ! w - > m_bIsFloating & & ! w - > isHidden ( ) & &
! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-05-31 14:01:00 +02:00
}
}
2022-09-10 13:11:02 +02:00
// pinned
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 14:10:57 +02:00
if ( wlr_box_contains_point ( & box , pos . x , pos . y ) & & w - > m_bIsMapped & & w - > m_bIsFloating & & ! w - > isHidden ( ) & & w - > m_bPinned & & ! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-09-10 13:11:02 +02:00
}
2022-06-30 15:44:26 +02:00
// first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter.
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 21:59:44 +02:00
if ( wlr_box_contains_point ( & box , pos . x , pos . y ) & & w - > m_bIsMapped & & w - > m_bIsFloating & & isWorkspaceVisible ( w - > m_iWorkspaceID ) & & ! w - > isHidden ( ) & & ! w - > m_bPinned & &
! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-03-22 17:14:07 +01:00
}
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 14:10:57 +02:00
if ( wlr_box_contains_point ( & box , pos . x , pos . y ) & & w - > m_bIsMapped & & ! w - > m_bIsFloating & & PMONITOR - > activeWorkspace = = w - > m_iWorkspaceID & & ! w - > isHidden ( ) & & ! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-03-18 22:53:27 +01:00
}
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
2022-11-27 23:42:22 +01:00
if ( PMONITOR - > specialWorkspaceID ) {
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vPosition . x , w - > m_vPosition . y , w - > m_vSize . x , w - > m_vSize . y } ;
2023-04-06 14:10:57 +02:00
if ( w - > m_iWorkspaceID = = PMONITOR - > specialWorkspaceID & & wlr_box_contains_point ( & box , pos . x , pos . y ) & & ! w - > m_bIsFloating & & ! w - > isHidden ( ) & & ! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-05-31 14:01:00 +02:00
}
}
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vPosition . x , w - > m_vPosition . y , w - > m_vSize . x , w - > m_vSize . y } ;
2023-04-06 14:10:57 +02:00
if ( w - > m_bIsMapped & & wlr_box_contains_point ( & box , pos . x , pos . y ) & & w - > m_iWorkspaceID = = PMONITOR - > activeWorkspace & & ! w - > m_bIsFloating & & ! w - > isHidden ( ) & & ! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-03-20 18:31:58 +01:00
}
return nullptr ;
}
2022-03-19 17:48:18 +01:00
CWindow * CCompositor : : vectorToWindowIdeal ( const Vector2D & pos ) {
2023-02-18 23:35:31 +01:00
const auto PMONITOR = getMonitorFromVector ( pos ) ;
static auto * const PRESIZEONBORDER = & g_pConfigManager - > getConfigValuePtr ( " general:resize_on_border " ) - > intValue ;
static auto * const PBORDERSIZE = & g_pConfigManager - > getConfigValuePtr ( " general:border_size " ) - > intValue ;
static auto * const PBORDERGRABEXTEND = & g_pConfigManager - > getConfigValuePtr ( " general:extend_border_grab_area " ) - > intValue ;
const auto BORDER_GRAB_AREA = * PRESIZEONBORDER ? * PBORDERSIZE + * PBORDERGRABEXTEND : 0 ;
2022-05-31 14:01:00 +02:00
// special workspace
2022-11-27 23:42:22 +01:00
if ( PMONITOR - > specialWorkspaceID ) {
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
const auto BB = w - > getWindowInputBox ( ) ;
2023-02-28 23:32:42 +01:00
wlr_box box = { BB . x - BORDER_GRAB_AREA , BB . y - BORDER_GRAB_AREA , BB . width + 2 * BORDER_GRAB_AREA , BB . height + 2 * BORDER_GRAB_AREA } ;
2023-03-01 15:06:52 +01:00
if ( w - > m_bIsFloating & & w - > m_iWorkspaceID = = PMONITOR - > specialWorkspaceID & & w - > m_bIsMapped & & wlr_box_contains_point ( & box , pos . x , pos . y ) & & ! w - > isHidden ( ) & &
2023-04-06 14:10:57 +02:00
! w - > m_bX11ShouldntFocus & & ! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-07-06 11:07:23 +02:00
}
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vPosition . x , w - > m_vPosition . y , w - > m_vSize . x , w - > m_vSize . y } ;
2022-12-16 18:17:31 +01:00
if ( ! w - > m_bIsFloating & & w - > m_iWorkspaceID = = PMONITOR - > specialWorkspaceID & & w - > m_bIsMapped & & wlr_box_contains_point ( & box , pos . x , pos . y ) & & ! w - > isHidden ( ) & &
2023-04-06 14:10:57 +02:00
! w - > m_bX11ShouldntFocus & & ! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-05-31 14:01:00 +02:00
}
}
2022-09-10 13:11:02 +02:00
// pinned windows on top of floating regardless
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
const auto BB = w - > getWindowInputBox ( ) ;
2023-02-28 23:32:42 +01:00
wlr_box box = { BB . x - BORDER_GRAB_AREA , BB . y - BORDER_GRAB_AREA , BB . width + 2 * BORDER_GRAB_AREA , BB . height + 2 * BORDER_GRAB_AREA } ;
2023-04-06 14:10:57 +02:00
if ( w - > m_bIsFloating & & w - > m_bIsMapped & & ! w - > isHidden ( ) & & ! w - > m_bX11ShouldntFocus & & w - > m_bPinned & & ! w - > m_bNoFocus ) {
2022-09-10 13:11:02 +02:00
if ( wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-09-10 13:11:02 +02:00
2023-03-01 15:06:52 +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
}
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.
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
const auto BB = w - > getWindowInputBox ( ) ;
2023-02-28 23:32:42 +01:00
wlr_box box = { BB . x - BORDER_GRAB_AREA , BB . y - BORDER_GRAB_AREA , BB . width + 2 * BORDER_GRAB_AREA , BB . height + 2 * BORDER_GRAB_AREA } ;
2023-04-06 14:10:57 +02:00
if ( w - > m_bIsFloating & & w - > m_bIsMapped & & isWorkspaceVisible ( w - > m_iWorkspaceID ) & & ! w - > isHidden ( ) & & ! w - > m_bPinned & & ! w - > m_bNoFocus ) {
2022-10-01 19:25:02 +02:00
// OR windows should add focus to parent
2023-03-01 15:06:52 +01:00
if ( w - > m_bX11ShouldntFocus & & w - > m_iX11Type ! = 2 )
2022-10-01 19:25:02 +02:00
continue ;
if ( wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) ) {
2023-03-01 15:06:52 +01:00
if ( w - > m_bIsX11 & & w - > m_iX11Type = = 2 & & ! wlr_xwayland_or_surface_wants_focus ( w - > m_uSurface . xwayland ) ) {
2022-10-01 19:25:02 +02:00
// Override Redirect
2022-12-16 18:17:31 +01:00
return g_pCompositor - > m_pLastWindow ; // we kinda trick everything here.
2022-10-01 19:25:02 +02:00
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
}
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-10-01 19:25:02 +02:00
}
2022-07-12 09:49:56 +02:00
2023-03-01 15:06:52 +01:00
if ( ! w - > m_bIsX11 ) {
if ( w - > hasPopupAt ( pos ) )
return w . get ( ) ;
2022-07-12 09:49:56 +02:00
}
2022-09-25 20:07:48 +02:00
}
2022-03-20 11:14:24 +01:00
}
2022-07-12 09:49:56 +02:00
// for windows, we need to check their extensions too, first.
for ( auto & w : m_vWindows ) {
2023-04-06 14:10:57 +02:00
if ( ! w - > m_bIsX11 & & ! w - > m_bIsFloating & & w - > m_bIsMapped & & w - > m_iWorkspaceID = = PMONITOR - > activeWorkspace & & ! w - > isHidden ( ) & & ! w - > m_bX11ShouldntFocus & & ! w - > m_bNoFocus ) {
2023-02-18 23:35:31 +01:00
if ( ( w ) - > hasPopupAt ( pos ) )
2022-07-12 09:49:56 +02:00
return w . get ( ) ;
}
}
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vPosition . x , w - > m_vPosition . y , w - > m_vSize . x , w - > m_vSize . y } ;
2022-12-16 18:17:31 +01:00
if ( ! w - > m_bIsFloating & & w - > m_bIsMapped & & wlr_box_contains_point ( & box , pos . x , pos . y ) & & w - > m_iWorkspaceID = = PMONITOR - > activeWorkspace & & ! w - > isHidden ( ) & &
2023-04-06 14:10:57 +02:00
! w - > m_bX11ShouldntFocus & & ! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-03-19 20:30:21 +01:00
}
return nullptr ;
}
CWindow * CCompositor : : windowFromCursor ( ) {
const auto PMONITOR = getMonitorFromCursor ( ) ;
2022-03-20 11:14:24 +01:00
2022-11-27 23:42:22 +01:00
if ( PMONITOR - > specialWorkspaceID ) {
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
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_iWorkspaceID = = PMONITOR - > specialWorkspaceID & & w - > m_bIsMapped & & wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) & &
2023-04-06 14:10:57 +02:00
! w - > isHidden ( ) & & ! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-07-06 11:07:23 +02:00
}
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vPosition . x , w - > m_vPosition . y , w - > m_vSize . x , w - > m_vSize . y } ;
2023-04-06 14:10:57 +02:00
if ( w - > m_iWorkspaceID = = PMONITOR - > specialWorkspaceID & & wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) & & w - > m_bIsMapped & & ! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-05-31 14:01:00 +02:00
}
}
2022-09-10 13:11:02 +02:00
// pinned
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 14:10:57 +02:00
if ( wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) & & w - > m_bIsMapped & & w - > m_bIsFloating & & w - > m_bPinned & & ! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-09-10 13:11:02 +02:00
}
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.
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 21:59:44 +02:00
if ( wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) & & w - > m_bIsMapped & & w - > m_bIsFloating & & isWorkspaceVisible ( w - > m_iWorkspaceID ) & & ! w - > m_bPinned & &
! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-03-20 11:14:24 +01:00
}
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
wlr_box box = { w - > m_vPosition . x , w - > m_vPosition . y , w - > m_vSize . x , w - > m_vSize . y } ;
2023-04-06 14:10:57 +02:00
if ( wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) & & w - > m_bIsMapped & & w - > m_iWorkspaceID = = PMONITOR - > activeWorkspace & & ! w - > m_bNoFocus )
2022-06-30 15:44:26 +02:00
return w . get ( ) ;
2022-03-19 17:48:18 +01:00
}
return nullptr ;
}
2022-03-20 11:14:24 +01:00
CWindow * CCompositor : : windowFloatingFromCursor ( ) {
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
wlr_box box = { w - > m_vRealPosition . vec ( ) . x , w - > m_vRealPosition . vec ( ) . y , w - > m_vRealSize . vec ( ) . x , w - > m_vRealSize . vec ( ) . y } ;
2023-04-06 14:10:57 +02:00
if ( wlr_box_contains_point ( & box , m_sWLRCursor - > x , m_sWLRCursor - > y ) & & w - > m_bIsMapped & & w - > m_bIsFloating & & ! w - > isHidden ( ) & & w - > m_bPinned & & ! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
2022-09-10 13:11:02 +02:00
}
2023-03-01 15:06:52 +01:00
for ( auto & w : m_vWindows | std : : views : : reverse ) {
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 - > isHidden ( ) & &
2023-04-06 14:10:57 +02:00
! w - > m_bPinned & & ! w - > m_bNoFocus )
2023-03-01 15:06:52 +01:00
return w . get ( ) ;
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-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.
2022-12-20 03:18:47 +01:00
wlr_box geom ;
2022-06-22 15:45:56 +02:00
wlr_xdg_surface_get_geometry ( pWindow - > m_uSurface . xdg , & geom ) ;
const auto PFOUND = wlr_xdg_surface_surface_at ( PSURFACE , pos . x - pWindow - > m_vRealPosition . vec ( ) . x + geom . x , pos . y - pWindow - > m_vRealPosition . vec ( ) . y + geom . 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
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 ;
}
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 ;
}
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 ) ) {
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 ;
}
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 ;
}
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 )
pWindow - > m_iWorkspaceID = m_pLastMonitor - > activeWorkspace ;
2023-01-20 20:57:35 +01:00
if ( ! isWorkspaceVisible ( pWindow - > m_iWorkspaceID ) ) {
// This is to fix incorrect feedback on the focus history.
const auto PWORKSPACE = getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
PWORKSPACE - > m_pLastFocusedWindow = pWindow ;
2023-04-14 16:03:53 +02:00
const auto PMONITOR = getMonitorFromID ( PWORKSPACE - > m_iMonitorID ) ;
PMONITOR - > changeWorkspace ( PWORKSPACE ) ;
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
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
if ( windowValidMapped ( PLASTWINDOW ) ) {
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
2022-07-12 13:40:55 +02:00
updateWindowAnimatedDecorationValues ( pWindow ) ;
2022-05-24 22:21:31 +02:00
2023-01-14 20:31:11 +01:00
// Handle urgency hint on the workspace
if ( pWindow - > m_bIsUrgent ) {
pWindow - > m_bIsUrgent = false ;
if ( ! hasUrgentWindowOnWorkspace ( pWindow - > m_iWorkspaceID ) ) {
const auto PWORKSPACE = getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
if ( PWORKSPACE - > m_pWlrHandle ) {
wlr_ext_workspace_handle_v1_set_urgent ( PWORKSPACE - > m_pWlrHandle , 0 ) ;
}
}
}
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-04-17 18:35:28 +02:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " activewindowv2 " , getFormat ( " %lx " , 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 ) ;
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
if ( ! pWindow - > m_bIsX11 ) {
const auto PCONSTRAINT = wlr_pointer_constraints_v1_constraint_for_surface ( m_sWLRPointerConstraints , pWindow - > m_uSurface . xdg - > surface , m_sSeat . seat ) ;
if ( PCONSTRAINT )
g_pInputManager - > constrainMouse ( m_sSeat . mouse , PCONSTRAINT ) ;
}
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-04-17 18:35:28 +02:00
Debug : : log ( ERR , " BUG THIS: Window %lx has no pivot in history " , pWindow ) ;
2023-01-20 19:15:15 +01:00
} else {
std : : rotate ( m_vWindowFocusHistory . begin ( ) , HISTORYPIVOT , HISTORYPIVOT + 1 ) ;
}
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
2023-02-12 20:20:13 +01:00
if ( g_pSessionLockManager - > isSessionLocked ( ) ) {
wlr_seat_keyboard_clear_focus ( m_sSeat . seat ) ;
m_pLastFocus = nullptr ;
}
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
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 ;
2023-04-10 23:37:55 +02:00
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 ) ;
2022-03-18 22:53:27 +01:00
2022-04-02 19:09:27 +02:00
wlr_seat_keyboard_focus_change_event event = {
2022-12-16 18:17:31 +01:00
. seat = m_sSeat . seat ,
2022-04-02 19:09:27 +02:00
. old_surface = m_pLastFocus ,
. new_surface = pSurface ,
} ;
2022-08-20 20:06:24 +02:00
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-04-17 18:35:28 +02:00
Debug : : log ( LOG , " Set keyboard focus to surface %lx, with window name: %s " , pSurface , pWindowOwner - > m_szTitle . c_str ( ) ) ;
2022-03-31 19:41:55 +02:00
else
2023-04-17 18:35:28 +02:00
Debug : : log ( LOG , " Set keyboard focus to surface %lx " , 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 ) ;
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 ;
if ( pWindow - > m_bIsX11 & & ! pWindow - > m_bMappedX11 )
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
}
2022-03-20 14:00:46 +01:00
CWindow * CCompositor : : getWindowForPopup ( wlr_xdg_popup * popup ) {
2022-06-30 15:44:26 +02:00
for ( auto & p : m_vXDGPopups ) {
if ( p - > popup = = popup )
return p - > parentWindow ;
2022-03-20 14:00:46 +01:00
}
2022-03-20 14:36:55 +01:00
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 ) {
2023-06-03 12:20:23 +02:00
if ( ls - > fadingOut | | ! ls - > layerSurface | | ( ls - > layerSurface & & ! ls - > layerSurface - > surface - > mapped ) | | ls - > alpha . fl ( ) = = 0.f )
2022-03-20 14:36:55 +01:00
continue ;
2023-03-01 15:06:52 +01:00
auto SURFACEAT = wlr_layer_surface_v1_surface_at ( ls - > layerSurface , pos . x - ls - > geometry . x , pos . y - ls - > geometry . y , & sCoords - > x , & sCoords - > y ) ;
2022-11-18 21:35:15 +01:00
2023-03-01 15:06:52 +01:00
if ( ls - > layerSurface - > current . keyboard_interactive & & ls - > layer > = ZWLR_LAYER_SHELL_V1_LAYER_TOP ) {
2022-12-17 23:35:47 +01:00
if ( ! SURFACEAT )
2023-03-01 15:06:52 +01:00
SURFACEAT = ls - > layerSurface - > surface ;
2022-12-17 23:35:47 +01:00
2023-03-01 15:06:52 +01:00
* ppLayerSurfaceFound = ls . get ( ) ;
2022-12-17 23:35:47 +01:00
return SURFACEAT ;
}
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 ) {
2022-12-08 18:43:15 +01:00
if ( ! w - > m_bIsMapped | | w - > m_bFadingOut | | ! w - > m_bMappedX11 )
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 ) {
if ( w - > m_iWorkspaceID = = ID & & w - > m_bIsFullscreen )
return w . get ( ) ;
2022-03-21 19:18:33 +01:00
}
return nullptr ;
}
2022-03-20 15:55:47 +01:00
bool CCompositor : : isWorkspaceVisible ( const int & w ) {
2022-06-30 15:44:26 +02:00
for ( auto & m : m_vMonitors ) {
if ( m - > activeWorkspace = = w )
2022-03-20 15:55:47 +01:00
return true ;
2022-09-25 20:07:48 +02:00
2023-05-06 17:10:51 +02:00
if ( m - > specialWorkspaceID = = w )
2022-05-31 14:01:00 +02:00
return true ;
2022-03-20 15:55:47 +01:00
}
return false ;
}
2022-04-11 19:51:37 +02:00
CWorkspace * CCompositor : : getWorkspaceByID ( const int & id ) {
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWorkspaces ) {
if ( w - > m_iID = = id )
return w . get ( ) ;
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 ( ) ) {
2023-04-13 22:09:50 +02:00
if ( ( * it ) - > m_bIndestructible )
continue ;
2022-06-30 16:11:26 +02:00
const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace ( ( * it ) - > m_iID ) ;
2022-06-30 16:00:44 +02:00
2022-11-27 23:42:22 +01:00
if ( ( * it ) - > m_bIsSpecialWorkspace & & WINDOWSONWORKSPACE = = 0 ) {
2023-04-16 22:33:28 +02:00
getMonitorFromID ( ( * it ) - > m_iMonitorID ) - > setSpecialWorkspace ( nullptr ) ;
2022-05-31 14:01:00 +02:00
2022-06-30 15:44:26 +02:00
it = m_vWorkspaces . erase ( it ) ;
2022-12-29 17:06:30 +01:00
continue ;
}
2022-06-30 16:11:26 +02:00
2022-12-29 17:06:30 +01:00
if ( ( WINDOWSONWORKSPACE = = 0 & & ! isWorkspaceVisible ( ( * it ) - > m_iID ) ) ) {
it = m_vWorkspaces . erase ( it ) ;
2022-07-07 19:00:34 +02:00
continue ;
2022-05-31 14:01:00 +02:00
}
2022-12-29 17:06:30 +01:00
+ + it ;
2022-03-20 15:55:47 +01:00
}
}
int CCompositor : : getWindowsOnWorkspace ( const int & id ) {
int no = 0 ;
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
if ( w - > m_iWorkspaceID = = id & & w - > m_bIsMapped )
2022-03-20 15:55:47 +01:00
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 ) {
if ( w - > m_iWorkspaceID = = id & & w - > m_bIsMapped & & w - > m_bIsUrgent )
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 ) {
2022-10-14 21:46:32 +02:00
if ( w - > m_iWorkspaceID = = 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
}
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 ;
2022-04-02 18:57:09 +02:00
if ( ! windowValidMapped ( pWindow ) )
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
}
void CCompositor : : moveWindowToTop ( CWindow * pWindow ) {
if ( ! windowValidMapped ( pWindow ) )
return ;
2022-08-28 19:47:06 +02:00
auto moveToTop = [ & ] ( CWindow * pw ) - > void {
for ( auto it = m_vWindows . begin ( ) ; it ! = m_vWindows . end ( ) ; + + it ) {
if ( it - > get ( ) = = pw ) {
std : : rotate ( it , it + 1 , m_vWindows . end ( ) ) ;
break ;
}
}
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
} ;
moveToTop ( pWindow ) ;
2022-12-15 18:29:06 +01:00
pWindow - > m_bCreatedOverFullscreen = true ;
2022-08-28 19:47:06 +02:00
if ( ! pWindow - > m_bIsX11 )
return ;
// move all children
std : : deque < CWindow * > toMove ;
for ( auto & w : m_vWindows ) {
2022-10-14 21:46:32 +02:00
if ( w - > m_bIsMapped & & w - > m_bMappedX11 & & ! w - > isHidden ( ) & & w - > m_bIsX11 & & w - > X11TransientFor ( ) = = pWindow ) {
2022-08-28 19:47:06 +02:00
toMove . emplace_back ( w . get ( ) ) ;
2022-04-04 16:25:30 +02:00
}
}
2022-08-28 19:47:06 +02:00
for ( auto & pw : toMove ) {
moveToTop ( pw ) ;
moveWindowToTop ( pw ) ;
}
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 ;
2022-04-28 15:39:49 +02:00
bool valid = windowExists ( w ) ;
2022-06-30 15:44:26 +02:00
2022-04-26 17:51:00 +02:00
if ( ! valid | | ! w - > m_bFadingOut | | w - > m_fAlpha . fl ( ) = = 0.f ) {
if ( valid & & ! w - > m_bReadyToDelete )
2022-04-10 11:17:06 +02:00
continue ;
2023-03-01 14:15:51 +01:00
2023-03-01 11:06:04 +01:00
std : : erase_if ( g_pHyprOpenGL - > m_mWindowFramebuffers , [ & ] ( const auto & other ) { return other . first = = w ; } ) ;
2022-12-07 15:32:24 +01:00
w - > m_bFadingOut = false ;
2022-06-30 15:44:26 +02:00
removeWindowFromVectorSafe ( w ) ;
2022-12-07 15:32:24 +01:00
std : : erase ( m_vWindowsFadingOut , w ) ;
2022-04-10 11:17:06 +02:00
Debug : : log ( LOG , " Cleanup: destroyed a window " ) ;
2022-07-12 23:11:34 +02:00
2022-12-16 18:17:31 +01:00
glFlush ( ) ; // to free mem NOW.
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 ) ) ;
2022-05-14 17:23:46 +02:00
if ( ls - > fadingOut & & ls - > readyToDelete & & ! ls - > alpha . isBeingAnimated ( ) ) {
g_pHyprOpenGL - > m_mLayerFramebuffers [ ls ] . release ( ) ;
g_pHyprOpenGL - > m_mLayerFramebuffers . erase ( ls ) ;
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-01-26 15:36:22 +01:00
// 0 -> history, 1 -> shared length
static auto * const PMETHOD = & g_pConfigManager - > getConfigValuePtr ( " binds:focus_preferred_method " ) - > intValue ;
2022-06-23 20:39:48 +02:00
2023-01-26 15:36:22 +01:00
const auto WINDOWIDEALBB = pWindow - > getWindowIdealBoundingBoxIgnoreReserved ( ) ;
2022-04-09 13:26:55 +02:00
2023-01-26 15:36:22 +01:00
const auto POSA = Vector2D ( WINDOWIDEALBB . x , WINDOWIDEALBB . y ) ;
const auto SIZEA = Vector2D ( WINDOWIDEALBB . width , WINDOWIDEALBB . height ) ;
auto leaderValue = - 1 ;
CWindow * leaderWindow = nullptr ;
2022-04-09 13:26:55 +02:00
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
2022-10-14 21:46:32 +02:00
if ( w . get ( ) = = pWindow | | ! w - > m_bIsMapped | | w - > isHidden ( ) | | w - > m_bIsFloating | | ! isWorkspaceVisible ( w - > m_iWorkspaceID ) )
2022-04-09 13:26:55 +02:00
continue ;
2022-11-24 00:40:05 +01:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( w - > m_iWorkspaceID ) ;
if ( PWORKSPACE - > m_bHasFullscreenWindow & & ! w - > m_bIsFullscreen & & ! w - > m_bCreatedOverFullscreen )
continue ;
2022-06-30 15:44:26 +02:00
const auto BWINDOWIDEALBB = w - > getWindowIdealBoundingBoxIgnoreReserved ( ) ;
2022-06-23 20:39:48 +02:00
2022-12-16 18:17:31 +01:00
const auto POSB = Vector2D ( BWINDOWIDEALBB . x , BWINDOWIDEALBB . y ) ;
2022-06-23 20:39:48 +02:00
const auto SIZEB = Vector2D ( BWINDOWIDEALBB . width , BWINDOWIDEALBB . height ) ;
2023-01-26 15:36:22 +01:00
double intersectLength = - 1 ;
2022-04-09 13:26:55 +02:00
switch ( dir ) {
case ' l ' :
if ( STICKS ( POSA . x , POSB . x + SIZEB . x ) ) {
2023-01-26 15:36:22 +01:00
intersectLength = std : : max ( 0.0 , std : : min ( POSA . y + SIZEA . y , POSB . y + SIZEB . y ) - std : : max ( POSA . y , POSB . y ) ) ;
2022-04-09 13:26:55 +02:00
}
break ;
case ' r ' :
if ( STICKS ( POSA . x + SIZEA . x , POSB . x ) ) {
2023-01-26 15:36:22 +01:00
intersectLength = std : : max ( 0.0 , std : : min ( POSA . y + SIZEA . y , POSB . y + SIZEB . y ) - std : : max ( POSA . y , POSB . y ) ) ;
2022-04-09 13:26:55 +02:00
}
break ;
case ' t ' :
case ' u ' :
if ( STICKS ( POSA . y , POSB . y + SIZEB . y ) ) {
2023-01-26 15:36:22 +01:00
intersectLength = std : : max ( 0.0 , std : : min ( POSA . x + SIZEA . x , POSB . x + SIZEB . x ) - std : : max ( POSA . x , POSB . x ) ) ;
2022-04-09 13:26:55 +02:00
}
break ;
case ' b ' :
case ' d ' :
if ( STICKS ( POSA . y + SIZEA . y , POSB . y ) ) {
2023-01-26 15:36:22 +01:00
intersectLength = std : : max ( 0.0 , std : : min ( POSA . x + SIZEA . x , POSB . x + SIZEB . x ) - std : : max ( POSA . x , POSB . x ) ) ;
2022-04-09 13:26:55 +02:00
}
break ;
}
2023-01-26 15:36:22 +01:00
if ( * PMETHOD = = 0 /* history */ ) {
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 ;
}
}
windowIDX = g_pCompositor - > m_vWindowFocusHistory . size ( ) - windowIDX ;
if ( windowIDX > leaderValue ) {
leaderValue = windowIDX ;
leaderWindow = w . get ( ) ;
}
}
} else /* length */ {
if ( intersectLength > leaderValue ) {
leaderValue = intersectLength ;
leaderWindow = w . get ( ) ;
}
}
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
}
2022-04-28 17:55:25 +02:00
void CCompositor : : deactivateAllWLRWorkspaces ( wlr_ext_workspace_handle_v1 * exclude ) {
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWorkspaces ) {
if ( w - > m_pWlrHandle & & w - > m_pWlrHandle ! = exclude )
w - > setActive ( false ) ;
2022-04-11 19:51:37 +02:00
}
2022-04-13 20:45:06 +02:00
}
2022-09-29 17:53:31 +02:00
CWindow * CCompositor : : getNextWindowOnWorkspace ( CWindow * pWindow , bool focusableOnly ) {
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 ;
}
2022-10-14 21:46:32 +02:00
if ( w - > m_iWorkspaceID = = pWindow - > m_iWorkspaceID & & w - > m_bIsMapped & & ! w - > isHidden ( ) & & ( ! focusableOnly | | ! w - > m_bNoFocus ) )
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 ) {
2022-10-14 21:46:32 +02:00
if ( w . get ( ) ! = pWindow & & w - > m_iWorkspaceID = = pWindow - > m_iWorkspaceID & & w - > m_bIsMapped & & ! w - > isHidden ( ) & & ( ! focusableOnly | | ! w - > m_bNoFocus ) )
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 ;
}
2022-09-29 17:53:31 +02:00
CWindow * CCompositor : : getPrevWindowOnWorkspace ( CWindow * pWindow , bool focusableOnly ) {
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-03-01 15:06:52 +01:00
if ( w - > m_iWorkspaceID = = pWindow - > m_iWorkspaceID & & w - > m_bIsMapped & & ! w - > isHidden ( ) & & ( ! focusableOnly | | ! w - > m_bNoFocus ) )
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 ) {
if ( w . get ( ) ! = pWindow & & w - > m_iWorkspaceID = = pWindow - > m_iWorkspaceID & & w - > m_bIsMapped & & ! w - > isHidden ( ) & & ( ! focusableOnly | | ! w - > m_bNoFocus ) )
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
}
CWorkspace * CCompositor : : getWorkspaceByName ( const std : : string & name ) {
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWorkspaces ) {
if ( w - > m_szName = = name )
return w . get ( ) ;
2022-04-21 16:38:48 +02:00
}
return nullptr ;
}
CWorkspace * CCompositor : : getWorkspaceByString ( const std : : string & str ) {
if ( str . find ( " name: " ) = = 0 ) {
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
2023-05-22 19:36:47 +02:00
CWorkspace * CCompositor : : getWorkspaceByWorkspaceHandle ( const wlr_ext_workspace_handle_v1 * handle ) {
for ( auto & ws : m_vWorkspaces ) {
if ( ws - > m_pWlrHandle = = handle )
return ws . get ( ) ;
}
return nullptr ;
}
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
}
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-04-25 13:40:46 +02:00
CWindow * CCompositor : : getConstraintWindow ( SMouse * pMouse ) {
if ( ! pMouse - > currentConstraint )
return nullptr ;
const auto PSURFACE = pMouse - > currentConstraint - > surface ;
2022-06-30 15:44:26 +02:00
for ( auto & w : m_vWindows ) {
2023-03-20 16:00:58 +01:00
if ( w - > isHidden ( ) | | ! w - > m_bMappedX11 | | ! w - > m_bIsMapped | | ! w - > m_pWLSurface . exists ( ) )
2022-10-28 20:35:02 +02:00
continue ;
2022-04-25 13:40:46 +02:00
2022-10-28 20:35:02 +02:00
if ( w - > m_bIsX11 ) {
2023-03-20 16:00:58 +01:00
if ( PSURFACE = = w - > m_pWLSurface . wlr ( ) )
2022-10-28 20:35:02 +02:00
return w . get ( ) ;
} else {
std : : pair < wlr_surface * , bool > check = { PSURFACE , false } ;
wlr_surface_for_each_surface ( w - > m_uSurface . xdg - > surface , checkFocusSurfaceIter , & check ) ;
if ( check . second )
return w . get ( ) ;
2022-04-25 13:40:46 +02:00
}
}
2022-05-05 12:50:25 +02:00
return nullptr ;
}
2022-07-27 12:32:00 +02:00
CMonitor * CCompositor : : getMonitorInDirection ( const char & dir ) {
2022-12-16 18:17:31 +01:00
const auto POSA = m_pLastMonitor - > vecPosition ;
2022-05-05 12:50:25 +02:00
const auto SIZEA = m_pLastMonitor - > vecSize ;
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
}
}
2022-07-12 13:40:55 +02:00
void CCompositor : : updateWindowAnimatedDecorationValues ( CWindow * pWindow ) {
2022-05-26 21:23:13 +02:00
// optimization
2023-06-13 12:04:54 +02:00
static auto * const ACTIVECOL = ( CGradientValueData * ) g_pConfigManager - > getConfigValuePtr ( " general:col.active_border " ) - > data . get ( ) ;
static auto * const INACTIVECOL = ( CGradientValueData * ) g_pConfigManager - > getConfigValuePtr ( " general:col.inactive_border " ) - > data . get ( ) ;
static auto * const GROUPACTIVECOL = ( CGradientValueData * ) g_pConfigManager - > getConfigValuePtr ( " general:col.group_border_active " ) - > data . get ( ) ;
static auto * const GROUPINACTIVECOL = ( CGradientValueData * ) g_pConfigManager - > getConfigValuePtr ( " general:col.group_border " ) - > data . get ( ) ;
static auto * const GROUPACTIVELOCKEDCOL = ( CGradientValueData * ) g_pConfigManager - > getConfigValuePtr ( " general:col.group_border_locked_active " ) - > data . get ( ) ;
static auto * const GROUPINACTIVELOCKEDCOL = ( CGradientValueData * ) g_pConfigManager - > getConfigValuePtr ( " general:col.group_border_locked " ) - > data . get ( ) ;
static auto * const PINACTIVEALPHA = & g_pConfigManager - > getConfigValuePtr ( " decoration:inactive_opacity " ) - > floatValue ;
static auto * const PACTIVEALPHA = & g_pConfigManager - > getConfigValuePtr ( " decoration:active_opacity " ) - > floatValue ;
static auto * const PFULLSCREENALPHA = & g_pConfigManager - > getConfigValuePtr ( " decoration:fullscreen_opacity " ) - > floatValue ;
static auto * const PSHADOWCOL = & g_pConfigManager - > getConfigValuePtr ( " decoration:col.shadow " ) - > intValue ;
static auto * const PSHADOWCOLINACTIVE = & g_pConfigManager - > getConfigValuePtr ( " decoration:col.shadow_inactive " ) - > intValue ;
static auto * const PDIMSTRENGTH = & g_pConfigManager - > getConfigValuePtr ( " decoration:dim_strength " ) - > floatValue ;
2023-06-13 18:50:40 +02:00
static auto * const PDIMENABLED = & g_pConfigManager - > getConfigValuePtr ( " decoration:dim_inactive " ) - > intValue ;
2022-12-16 18:17:31 +01:00
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-06-13 12:04:54 +02:00
const auto * const ACTIVECOLOR = ! pWindow - > m_sGroupData . pNextWindow ? ACTIVECOL : ( GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL ) ;
2023-02-19 22:07:32 +01:00
setBorderColor ( pWindow - > m_sSpecialRenderData . activeBorderColor . toUnderlying ( ) > = 0 ?
CGradientValueData ( CColor ( pWindow - > m_sSpecialRenderData . activeBorderColor . toUnderlying ( ) ) ) :
* ACTIVECOLOR ) ;
} else {
2023-06-13 12:04:54 +02:00
const auto * const INACTIVECOLOR = ! pWindow - > m_sGroupData . pNextWindow ? INACTIVECOL : ( GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL ) ;
2023-02-19 22:07:32 +01:00
setBorderColor ( pWindow - > m_sSpecialRenderData . inactiveBorderColor . toUnderlying ( ) > = 0 ?
CGradientValueData ( CColor ( pWindow - > m_sSpecialRenderData . inactiveBorderColor . toUnderlying ( ) ) ) :
* INACTIVECOLOR ) ;
}
}
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
2022-12-11 18:15:02 +01:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
if ( pWindow - > m_bIsFullscreen & & PWORKSPACE - > m_efFullscreenMode = = FULLSCREEN_FULL ) {
pWindow - > m_fActiveInactiveAlpha = * 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 ( ) :
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 ( ) :
pWindow - > m_sSpecialRenderData . alphaInactive . toUnderlying ( ) * * PINACTIVEALPHA ) :
2022-12-16 18:17:31 +01:00
* 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
2023-06-13 18:50:40 +02:00
if ( pWindow = = m_pLastWindow | | pWindow - > m_sAdditionalConfigData . forceNoDim | | ! * PDIMENABLED ) {
2022-08-30 12:46:17 +02:00
pWindow - > m_fDimPercent = 0 ;
} else {
pWindow - > m_fDimPercent = * PDIMSTRENGTH ;
}
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 ) {
pWindow - > m_cRealShadowColor = CColor ( * PSHADOWCOL ) ;
} else {
pWindow - > m_cRealShadowColor = CColor ( * PSHADOWCOLINACTIVE ! = INT_MAX ? * PSHADOWCOLINACTIVE : * PSHADOWCOL ) ;
}
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
for ( auto & d : pWindow - > m_dWindowDecorations )
d - > updateWindow ( pWindow ) ;
2022-05-30 17:11:35 +02:00
}
2023-07-09 23:08:40 +02:00
int CCompositor : : getNextAvailableMonitorID ( std : : string const & name ) {
// reuse ID if it's already in the map
if ( m_mMonitorIDMap . contains ( name ) )
return m_mMonitorIDMap [ name ] ;
// otherwise, find minimum available ID that is not in the map
std : : unordered_set < int > usedIDs ;
for ( auto const & monitor : m_vRealMonitors ) {
usedIDs . insert ( monitor - > ID ) ;
2022-05-30 17:11:35 +02:00
}
2023-07-09 23:08:40 +02:00
int nextID = 0 ;
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 ) {
const auto PWORKSPACEA = g_pCompositor - > getWorkspaceByID ( pMonitorA - > activeWorkspace ) ;
const auto PWORKSPACEB = g_pCompositor - > getWorkspaceByID ( pMonitorB - > activeWorkspace ) ;
PWORKSPACEA - > m_iMonitorID = pMonitorB - > ID ;
PWORKSPACEA - > moveToMonitor ( pMonitorB - > ID ) ;
for ( auto & w : m_vWindows ) {
if ( w - > m_iWorkspaceID = = PWORKSPACEA - > m_iID ) {
2023-03-20 02:50:46 +01:00
if ( w - > m_bPinned ) {
w - > m_iWorkspaceID = PWORKSPACEB - > m_iID ;
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 )
2022-08-25 21:25:28 +02:00
w - > m_vRealPosition = w - > m_vRealPosition . vec ( ) - 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 ) {
if ( w - > m_iWorkspaceID = = PWORKSPACEB - > m_iID ) {
2023-03-20 02:50:46 +01:00
if ( w - > m_bPinned ) {
w - > m_iWorkspaceID = PWORKSPACEA - > m_iID ;
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 )
2022-08-25 21:25:28 +02:00
w - > m_vRealPosition = w - > m_vRealPosition . vec ( ) - 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 ( ) ;
}
}
pMonitorA - > activeWorkspace = PWORKSPACEB - > m_iID ;
pMonitorB - > activeWorkspace = PWORKSPACEA - > m_iID ;
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( pMonitorA - > ID ) ;
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( pMonitorB - > ID ) ;
2023-04-25 00:21:51 +02:00
updateFullscreenFadeOnWorkspace ( PWORKSPACEB ) ;
updateFullscreenFadeOnWorkspace ( PWORKSPACEA ) ;
2023-05-17 14:32:59 +02:00
g_pInputManager - > simulateMouseMovement ( ) ;
2022-08-26 16:05:02 +02:00
// event
g_pEventManager - > postEvent ( SHyprIPCEvent { " moveworkspace " , PWORKSPACEA - > m_szName + " , " + pMonitorB - > szName } ) ;
2023-02-19 21:54:53 +01:00
EMIT_HOOK_EVENT ( " moveWorkspace " , ( std : : vector < void * > { PWORKSPACEA , pMonitorB } ) ) ;
2022-08-26 16:05:02 +02:00
g_pEventManager - > postEvent ( SHyprIPCEvent { " moveworkspace " , PWORKSPACEB - > m_szName + " , " + pMonitorA - > szName } ) ;
2023-02-19 21:54:53 +01:00
EMIT_HOOK_EVENT ( " moveWorkspace " , ( std : : vector < void * > { PWORKSPACEB , pMonitorA } ) ) ;
2022-08-25 21:25:28 +02:00
}
CMonitor * CCompositor : : getMonitorFromString ( const std : : string & name ) {
2022-11-10 13:22:19 +01:00
if ( name [ 0 ] = = ' + ' | | name [ 0 ] = = ' - ' ) {
// 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 ;
}
2023-03-02 13:04:41 +01:00
} else if ( name . find ( " desc: " ) = = 0 ) {
const auto DESCRIPTION = name . substr ( 5 ) ;
for ( auto & m : m_vMonitors ) {
2023-03-16 15:03:40 +01:00
if ( ! m - > output )
continue ;
2023-03-02 13:04:41 +01:00
if ( m - > output - > description & & std : : string ( m - > output - > description ) . find ( DESCRIPTION ) = = 0 ) {
return m . get ( ) ;
}
}
return nullptr ;
2022-08-25 21:25:28 +02:00
} else {
2022-09-10 19:57:57 +02:00
if ( name = = " current " )
return g_pCompositor - > m_pLastMonitor ;
2022-08-25 21:25:28 +02:00
if ( isDirection ( name ) ) {
2023-03-02 13:04:41 +01:00
const auto PMONITOR = getMonitorInDirection ( name [ 0 ] ) ;
2022-08-25 21:25:28 +02:00
return PMONITOR ;
} else {
2023-03-02 13:04:41 +01:00
for ( auto & m : m_vMonitors ) {
2022-08-25 21:25:28 +02:00
if ( m - > szName = = name ) {
return m . get ( ) ;
}
}
}
}
return nullptr ;
}
2022-07-27 12:32:00 +02:00
void CCompositor : : moveWorkspaceToMonitor ( CWorkspace * pWorkspace , CMonitor * pMonitor ) {
2022-05-30 20:05:38 +02:00
// 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 ) ;
2023-05-06 17:49:46 +02:00
const bool SWITCHINGISACTIVE = POLDMON ? POLDMON - > activeWorkspace = = pWorkspace - > m_iID : false ;
2022-05-30 20:05:38 +02:00
// fix old mon
2022-12-20 03:18:47 +01:00
int nextWorkspaceOnMonitorID = - 1 ;
2023-04-28 22:40:40 +02:00
if ( ! SWITCHINGISACTIVE )
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-04-28 22:40:40 +02:00
Debug : : log ( LOG , " moveWorkspaceToMonitor: Plugging gap with new %d " , 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-04-28 22:40:40 +02:00
Debug : : log ( LOG , " moveWorkspaceToMonitor: Plugging gap with existing %d " , nextWorkspaceOnMonitorID ) ;
POLDMON - > changeWorkspace ( nextWorkspaceOnMonitorID ) ;
}
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 ) {
2022-07-25 14:22:32 +02:00
if ( w - > m_iWorkspaceID = = pWorkspace - > m_iID ) {
2023-03-20 02:50:46 +01:00
if ( w - > m_bPinned ) {
w - > m_iWorkspaceID = nextWorkspaceOnMonitorID ;
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 )
w - > m_vRealPosition = w - > m_vRealPosition . vec ( ) - 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 {
w - > m_vRealPosition = Vector2D { ( int ) w - > m_vRealPosition . goalv ( ) . x % ( int ) pMonitor - > vecSize . x , ( int ) w - > m_vRealPosition . goalv ( ) . 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.
2022-05-30 20:05:38 +02:00
Debug : : log ( LOG , " moveWorkspaceToMonitor: SWITCHINGISACTIVE, active %d -> %d " , pMonitor - > activeWorkspace , pWorkspace - > m_iID ) ;
2022-05-31 17:17:44 +02:00
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 ) ;
2023-04-15 22:27:07 +02:00
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-05-17 14:32:59 +02:00
g_pInputManager - > simulateMouseMovement ( ) ;
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 ) ;
updateFullscreenFadeOnWorkspace ( getWorkspaceByID ( POLDMON - > activeWorkspace ) ) ;
}
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 } ) ;
2023-02-19 21:54:53 +01:00
EMIT_HOOK_EVENT ( " moveWorkspace " , ( std : : vector < void * > { 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
}
2023-04-25 00:21:51 +02:00
void CCompositor : : updateFullscreenFadeOnWorkspace ( CWorkspace * pWorkspace ) {
const auto FULLSCREEN = pWorkspace - > m_bHasFullscreenWindow ;
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_iWorkspaceID = = pWorkspace - > m_iID ) {
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 ) ;
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 ;
}
}
2022-06-26 12:12:29 +02:00
void CCompositor : : setWindowFullscreen ( CWindow * pWindow , bool on , eFullscreenMode mode ) {
if ( ! windowValidMapped ( pWindow ) )
return ;
2022-09-21 15:09:26 +02:00
if ( pWindow - > m_bPinned ) {
Debug : : log ( LOG , " Pinned windows cannot be fullscreen'd " ) ;
return ;
}
2022-09-29 11:20:12 +02:00
const auto PMONITOR = getMonitorFromID ( pWindow - > m_iMonitorID ) ;
const auto PWORKSPACE = getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
if ( PWORKSPACE - > m_bHasFullscreenWindow & & on ) {
Debug : : log ( LOG , " Rejecting fullscreen ON on a fullscreen workspace " ) ;
return ;
}
2022-06-26 12:12:29 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > fullscreenRequestForWindow ( pWindow , mode , on ) ;
g_pXWaylandManager - > setWindowFullscreen ( pWindow , pWindow - > m_bIsFullscreen & & mode = = FULLSCREEN_FULL ) ;
2022-09-25 20:07:48 +02:00
2022-11-15 11:21:26 +01:00
pWindow - > updateDynamicRules ( ) ;
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 ) {
if ( w - > m_iWorkspaceID = = PWORKSPACE - > m_iID & & ! 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
2022-08-16 16:30:10 +02:00
g_pXWaylandManager - > setWindowSize ( pWindow , pWindow - > m_vRealSize . goalv ( ) , true ) ;
2022-08-22 14:22:21 +02:00
forceReportSizesToWindowsOnWorkspace ( pWindow - > m_iWorkspaceID ) ;
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 ) {
if ( w - > m_iWorkspaceID ! = id )
continue ;
w - > updateWindowDecos ( ) ;
}
}
2022-07-13 18:18:23 +02:00
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 ;
2022-07-26 17:30:30 +02:00
if ( regexp . find ( " title: " ) = = 0 ) {
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 ) ) ;
} else if ( regexp . find ( " address: " ) = = 0 ) {
2022-12-16 18:17:31 +01:00
mode = MODE_ADDRESS ;
2022-07-26 17:30:30 +02:00
matchCheck = regexp . substr ( 8 ) ;
} else if ( regexp . find ( " pid: " ) = = 0 ) {
2022-12-16 18:17:31 +01:00
mode = MODE_PID ;
2022-07-26 17:30:30 +02:00
matchCheck = regexp . substr ( 4 ) ;
}
for ( auto & w : g_pCompositor - > m_vWindows ) {
2023-02-28 13:34:59 +01:00
if ( ! w - > m_bIsMapped | | ( w - > isHidden ( ) & & ! w - > m_sGroupData . pNextWindow ) )
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-04-17 18:35:28 +02:00
std : : string addr = getFormat ( " 0x%lx " , w . get ( ) ) ;
2022-07-26 17:30:30 +02:00
if ( matchCheck ! = addr )
continue ;
break ;
}
case MODE_PID : {
std : : string pid = getFormat ( " %d " , w - > getPID ( ) ) ;
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
2022-12-16 18:17:31 +01:00
static auto * const PNOWARPS = & g_pConfigManager - > getConfigValuePtr ( " general:no_cursor_warps " ) - > intValue ;
2022-08-01 18:50:16 +02:00
2023-01-28 13:26:33 +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 ) {
if ( ! args . contains ( ' ' ) )
return relativeTo ;
std : : string x = args . substr ( 0 , args . find_first_of ( ' ' ) ) ;
std : : string y = args . substr ( args . find_first_of ( ' ' ) + 1 ) ;
if ( x = = " exact " ) {
std : : string newX = y . substr ( 0 , y . find_first_of ( ' ' ) ) ;
std : : string newY = y . substr ( y . find_first_of ( ' ' ) + 1 ) ;
if ( ! isNumber ( newX ) | | ! isNumber ( newY ) ) {
Debug : : log ( ERR , " parseWindowVectorArgsRelative: exact args not numbers " ) ;
return relativeTo ;
}
const int X = std : : stoi ( newX ) ;
const int Y = std : : stoi ( newY ) ;
return Vector2D ( X , Y ) ;
}
if ( ! isNumber ( x ) | | ! isNumber ( y ) ) {
Debug : : log ( ERR , " parseWindowVectorArgsRelative: args not numbers " ) ;
return relativeTo ;
}
const int X = std : : stoi ( x ) ;
const int Y = std : : stoi ( y ) ;
return Vector2D ( X + relativeTo . x , Y + relativeTo . y ) ;
2022-08-22 14:22:21 +02:00
}
void CCompositor : : forceReportSizesToWindowsOnWorkspace ( const int & wid ) {
for ( auto & w : m_vWindows ) {
2022-10-14 21:46:32 +02:00
if ( w - > m_iWorkspaceID = = wid & & w - > m_bIsMapped & & ! w - > isHidden ( ) ) {
2022-08-22 14:22:21 +02:00
g_pXWaylandManager - > setWindowSize ( w . get ( ) , w - > m_vRealSize . vec ( ) , true ) ;
}
}
2022-09-03 15:35:53 +02:00
}
bool CCompositor : : cursorOnReservedArea ( ) {
const auto PMONITOR = getMonitorFromCursor ( ) ;
const auto XY1 = PMONITOR - > vecPosition + PMONITOR - > vecReservedTopLeft ;
const auto XY2 = PMONITOR - > vecPosition + PMONITOR - > vecSize - PMONITOR - > vecReservedBottomRight ;
const auto CURSORPOS = g_pInputManager - > getMouseCoordsInternal ( ) ;
return ! VECINRECT ( CURSORPOS , XY1 . x , XY1 . y , XY2 . x , XY2 . y ) ;
}
2022-10-24 19:36:31 +02:00
CWorkspace * 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 ;
const auto PWORKSPACE = m_vWorkspaces . emplace_back ( std : : make_unique < CWorkspace > ( monID , NAME , SPECIAL ) ) . get ( ) ;
2022-10-24 19:36:31 +02:00
// We are required to set the name here immediately
2022-11-27 23:42:22 +01:00
if ( ! SPECIAL )
2022-10-24 19:36:31 +02:00
wlr_ext_workspace_handle_v1_set_name ( PWORKSPACE - > m_pWlrHandle , NAME . c_str ( ) ) ;
2022-12-16 18:17:31 +01:00
PWORKSPACE - > m_iID = id ;
2022-10-25 11:30:25 +02:00
PWORKSPACE - > m_iMonitorID = monID ;
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-01-28 18:52:32 +01:00
Debug : : log ( LOG , " renameWorkspace: Renaming workspace %d to '%s' " , id , name . c_str ( ) ) ;
2023-01-08 14:19:18 +01:00
wlr_ext_workspace_handle_v1_set_name ( PWORKSPACE - > m_pWlrHandle , name . c_str ( ) ) ;
PWORKSPACE - > m_szName = name ;
}
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 ;
}
2022-11-19 17:41:36 +01:00
const auto PWORKSPACE = getWorkspaceByID ( pMonitor - > activeWorkspace ) ;
g_pEventManager - > postEvent ( SHyprIPCEvent { " focusedmon " , pMonitor - > szName + " , " + 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 ( ) {
int highest = - 100 ;
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 ( ) {
2023-03-20 23:26:49 +01:00
static constexpr auto BAD_PORTALS = { " kde " , " gnome " } ;
2023-03-20 16:02:47 +01:00
2023-03-22 13:17:08 +01:00
static auto * const PSUPPRESSPORTAL = & g_pConfigManager - > getConfigValuePtr ( " misc:suppress_portal_warnings " ) - > intValue ;
if ( ! * PSUPPRESSPORTAL ) {
if ( std : : ranges : : any_of ( BAD_PORTALS , [ & ] ( const std : : string & portal ) { return std : : filesystem : : exists ( " /usr/share/xdg-desktop-portal/portals/ " + portal + " .portal " ) ; } ) ) {
// bad portal detected
g_pHyprNotificationOverlay - > addNotification ( " You have one or more incompatible xdg-desktop-portal impls installed. Please remove incompatible ones to avoid issues. " ,
CColor ( 0 ) , 15000 , ICON_ERROR ) ;
}
2023-03-20 23:26:49 +01:00
2023-03-22 13:17:08 +01:00
if ( std : : filesystem : : exists ( " /usr/share/xdg-desktop-portal/portals/hyprland.portal " ) & & std : : filesystem : : exists ( " /usr/share/xdg-desktop-portal/portals/wlr.portal " ) ) {
g_pHyprNotificationOverlay - > addNotification ( " You have xdg-desktop-portal-hyprland and -wlr installed simultaneously. Please uninstall one to avoid issues. " , CColor ( 0 ) ,
15000 , ICON_ERROR ) ;
}
2023-03-20 23:26:49 +01:00
}
2023-03-20 16:02:47 +01:00
}
2023-04-14 16:03:53 +02:00
void CCompositor : : moveWindowToWorkspaceSafe ( CWindow * pWindow , CWorkspace * pWorkspace ) {
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 ;
const auto FULLSCREENMODE = getWorkspaceByID ( pWindow - > m_iWorkspaceID ) - > m_efFullscreenMode ;
2023-04-14 16:03:53 +02:00
if ( FULLSCREEN )
setWindowFullscreen ( pWindow , false , FULLSCREEN_FULL ) ;
2023-04-22 22:13:02 +02:00
pWindow - > moveToWorkspace ( pWorkspace - > m_iID ) ;
pWindow - > updateToplevel ( ) ;
2023-04-14 16:03:53 +02:00
if ( ! pWindow - > m_bIsFloating ) {
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowRemovedTiling ( pWindow ) ;
pWindow - > m_iWorkspaceID = pWorkspace - > m_iID ;
pWindow - > m_iMonitorID = pWorkspace - > m_iMonitorID ;
g_pLayoutManager - > getCurrentLayout ( ) - > onWindowCreatedTiling ( pWindow ) ;
} else {
const auto PWINDOWMONITOR = g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ;
const auto POSTOMON = pWindow - > m_vRealPosition . goalv ( ) - PWINDOWMONITOR - > vecPosition ;
const auto PWORKSPACEMONITOR = g_pCompositor - > getMonitorFromID ( pWorkspace - > m_iMonitorID ) ;
pWindow - > m_iWorkspaceID = pWorkspace - > m_iID ;
pWindow - > m_iMonitorID = pWorkspace - > m_iMonitorID ;
pWindow - > m_vRealPosition = POSTOMON + PWORKSPACEMONITOR - > vecPosition ;
}
2023-06-21 20:51:18 +02:00
if ( pWindow - > m_sGroupData . pNextWindow ) {
CWindow * next = pWindow - > m_sGroupData . pNextWindow ;
while ( next ! = pWindow ) {
next - > moveToWorkspace ( pWorkspace - > m_iID ) ;
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-04-14 16:03:53 +02:00
}
2023-07-04 12:05:25 +02:00
CWindow * CCompositor : : getForceFocus ( ) {
for ( auto & w : m_vWindows ) {
if ( ! w - > m_bIsMapped | | w - > isHidden ( ) | | ! isWorkspaceVisible ( w - > m_iWorkspaceID ) )
continue ;
if ( ! w - > m_bStayFocused )
continue ;
return w . get ( ) ;
}
return nullptr ;
}