2021-11-18 18:04:09 +01:00
# include "windowManager.hpp"
# include "./events/events.hpp"
2021-11-21 17:40:02 +01:00
# include <string.h>
2021-11-18 18:04:09 +01:00
2021-11-29 21:51:01 +01:00
xcb_visualtype_t * CWindowManager : : setupColors ( const int & desiredDepth ) {
2021-11-21 11:25:26 +01:00
auto depthIter = xcb_screen_allowed_depths_iterator ( Screen ) ;
2021-11-29 21:51:01 +01:00
if ( depthIter . data ) {
for ( ; depthIter . rem ; xcb_depth_next ( & depthIter ) ) {
if ( desiredDepth = = 0 | | desiredDepth = = depthIter . data - > depth ) {
for ( auto it = xcb_depth_visuals_iterator ( depthIter . data ) ; it . rem ; xcb_visualtype_next ( & it ) ) {
return it . data ;
}
}
}
if ( desiredDepth > 0 ) {
return setupColors ( 0 ) ;
2021-11-21 11:25:26 +01:00
}
}
return nullptr ;
}
2021-11-27 13:28:30 +01:00
void CWindowManager : : setupDepth ( ) {
2021-11-29 21:51:01 +01:00
Depth = 24 ;
VisualType = setupColors ( Depth ) ;
2021-11-27 13:28:30 +01:00
}
void CWindowManager : : createAndOpenAllPipes ( ) {
system ( " mkdir -p /tmp/hypr " ) ;
system ( " cat \" \" > /tmp/hypr/hyprbarin " ) ;
system ( " cat \" \" > /tmp/hypr/hyprbarout " ) ;
system ( " cat \" \" > /tmp/hypr/hyprbarind " ) ;
system ( " cat \" \" > /tmp/hypr/hyprbaroutd " ) ;
}
2021-11-25 17:57:50 +01:00
void CWindowManager : : updateRootCursor ( ) {
if ( xcb_cursor_context_new ( DisplayConnection , Screen , & pointerContext ) < 0 ) {
Debug : : log ( ERR , " Creating a cursor context failed! " ) ;
return ;
}
pointerCursor = xcb_cursor_load_cursor ( pointerContext , " left_ptr " ) ;
2021-11-22 22:37:01 +01:00
2021-11-25 17:57:50 +01:00
Debug : : log ( LOG , " Cursor created with ID " + std : : to_string ( pointerCursor ) ) ;
2021-11-22 22:37:01 +01:00
2021-11-25 17:57:50 +01:00
// Set the cursor
uint32_t values [ 1 ] = { pointerCursor } ;
xcb_change_window_attributes ( DisplayConnection , Screen - > root , XCB_CW_CURSOR , values ) ;
}
2021-11-29 21:51:01 +01:00
void CWindowManager : : setupColormapAndStuff ( ) {
VisualType = xcb_aux_find_visual_by_attrs ( Screen , - 1 , 32 ) ; // Transparency by default
Depth = xcb_aux_get_depth_of_visual ( Screen , VisualType - > visual_id ) ;
Colormap = xcb_generate_id ( DisplayConnection ) ;
const auto COOKIE = xcb_create_colormap ( DisplayConnection , XCB_COLORMAP_ALLOC_NONE , Colormap , Screen - > root , VisualType - > visual_id ) ;
const auto XERR = xcb_request_check ( DisplayConnection , COOKIE ) ;
if ( XERR ! = NULL ) {
Debug : : log ( ERR , " Error in setupColormapAndStuff! Code: " + std : : to_string ( XERR - > error_code ) ) ;
}
free ( XERR ) ;
}
2021-11-25 17:57:50 +01:00
void CWindowManager : : setupRandrMonitors ( ) {
2021-11-22 22:37:01 +01:00
XCBQUERYCHECK ( RANDRVER , xcb_randr_query_version_reply (
2021-11-23 16:24:31 +01:00
DisplayConnection , xcb_randr_query_version ( DisplayConnection , XCB_RANDR_MAJOR_VERSION , XCB_RANDR_MINOR_VERSION ) , & errorRANDRVER ) , " RandR query failed! " ) ;
2021-11-22 22:37:01 +01:00
free ( RANDRVER ) ;
2021-11-23 16:24:31 +01:00
Debug : : log ( LOG , " Setting up RandR! Query: v1.5. " ) ;
XCBQUERYCHECK ( MONITORS , xcb_randr_get_monitors_reply ( DisplayConnection , xcb_randr_get_monitors ( DisplayConnection , Screen - > root , true ) , & errorMONITORS ) , " Couldn't get monitors. " + std : : to_string ( errorMONITORS - > error_code ) ) ;
const auto MONITORNUM = xcb_randr_get_monitors_monitors_length ( MONITORS ) ;
Debug : : log ( LOG , " Found " + std : : to_string ( MONITORNUM ) + " Monitors! " ) ;
if ( MONITORNUM < 1 ) {
// TODO: RandR 1.4 maybe for people with ancient hardware?
Debug : : log ( ERR , " RandR returned an invalid amount of monitors. Falling back to 1 monitor. " ) ;
2021-11-21 17:40:02 +01:00
return ;
}
2021-11-23 16:24:31 +01:00
for ( xcb_randr_monitor_info_iterator_t iterator = xcb_randr_get_monitors_monitors_iterator ( MONITORS ) ; iterator . rem ; xcb_randr_monitor_info_next ( & iterator ) ) {
const auto MONITORINFO = iterator . data ;
// basically an XCBQUERYCHECK but with continue; as its not fatal
xcb_generic_error_t * error ;
const auto ATOMNAME = xcb_get_atom_name_reply ( DisplayConnection , xcb_get_atom_name ( DisplayConnection , MONITORINFO - > name ) , & error ) ;
if ( error ! = NULL ) {
Debug : : log ( ERR , " Failed to get monitor info... " ) ;
free ( error ) ;
free ( ATOMNAME ) ;
continue ;
}
free ( error ) ;
monitors . push_back ( SMonitor ( ) ) ;
const auto NAMELEN = xcb_get_atom_name_name_length ( ATOMNAME ) ;
const auto NAME = xcb_get_atom_name_name ( ATOMNAME ) ;
free ( ATOMNAME ) ;
for ( int j = 0 ; j < NAMELEN ; + + j ) {
monitors [ monitors . size ( ) - 1 ] . szName + = NAME [ j ] ;
}
monitors [ monitors . size ( ) - 1 ] . vecPosition = Vector2D ( MONITORINFO - > x , MONITORINFO - > y ) ;
monitors [ monitors . size ( ) - 1 ] . vecSize = Vector2D ( MONITORINFO - > width , MONITORINFO - > height ) ;
monitors [ monitors . size ( ) - 1 ] . primary = MONITORINFO - > primary ;
monitors [ monitors . size ( ) - 1 ] . ID = monitors . size ( ) - 1 ;
Debug : : log ( NONE , " Monitor " + monitors [ monitors . size ( ) - 1 ] . szName + " : " + std : : to_string ( monitors [ monitors . size ( ) - 1 ] . vecSize . x ) + " x " + std : : to_string ( monitors [ monitors . size ( ) - 1 ] . vecSize . y ) +
" , at " + std : : to_string ( monitors [ monitors . size ( ) - 1 ] . vecPosition . x ) + " , " + std : : to_string ( monitors [ monitors . size ( ) - 1 ] . vecPosition . y ) + " , ID: " + std : : to_string ( monitors [ monitors . size ( ) - 1 ] . ID ) ) ;
}
free ( MONITORS ) ;
2021-11-21 17:40:02 +01:00
const auto EXTENSIONREPLY = xcb_get_extension_data ( DisplayConnection , & xcb_randr_id ) ;
if ( ! EXTENSIONREPLY - > present )
Debug : : log ( ERR , " RandR extension missing " ) ;
else {
//listen for screen change events
xcb_randr_select_input ( DisplayConnection , Screen - > root , XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE ) ;
2021-12-22 14:53:53 +01:00
RandREventBase = EXTENSIONREPLY - > first_event ;
2021-11-21 17:40:02 +01:00
}
2021-11-22 22:37:01 +01:00
xcb_flush ( DisplayConnection ) ;
2021-12-22 14:53:53 +01:00
}
void CWindowManager : : setupManager ( ) {
setupColormapAndStuff ( ) ;
EWMH : : setupInitEWMH ( ) ;
// ---- RANDR ----- //
setupRandrMonitors ( ) ;
2021-11-21 17:40:02 +01:00
2021-12-17 20:59:21 +01:00
if ( monitors . size ( ) = = 0 ) {
2021-11-21 17:40:02 +01:00
// RandR failed!
Debug : : log ( WARN , " RandR failed! " ) ;
2021-11-25 17:44:46 +01:00
monitors . clear ( ) ;
2021-11-21 17:40:02 +01:00
2021-12-22 14:53:53 +01:00
# define TESTING_MON_AMOUNT 3
2021-11-22 18:43:55 +01:00
for ( int i = 0 ; i < TESTING_MON_AMOUNT /* Testing on 3 monitors, RandR shouldnt fail on a real desktop */ ; + + i ) {
monitors . push_back ( SMonitor ( ) ) ;
monitors [ i ] . vecPosition = Vector2D ( i * Screen - > width_in_pixels / TESTING_MON_AMOUNT , 0 ) ;
monitors [ i ] . vecSize = Vector2D ( Screen - > width_in_pixels / TESTING_MON_AMOUNT , Screen - > height_in_pixels ) ;
monitors [ i ] . ID = i ;
monitors [ i ] . szName = " Screen " + std : : to_string ( i ) ;
}
2021-11-21 17:40:02 +01:00
}
2021-11-21 19:59:59 +01:00
Debug : : log ( LOG , " RandR done. " ) ;
2021-11-19 20:20:05 +01:00
2021-12-22 14:53:53 +01:00
//
//
2021-11-20 09:25:21 +01:00
Values [ 0 ] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE ;
xcb_change_window_attributes_checked ( DisplayConnection , Screen - > root ,
XCB_CW_EVENT_MASK , Values ) ;
2021-11-19 20:20:05 +01:00
2021-11-23 16:49:53 +01:00
ConfigManager : : init ( ) ;
2021-11-21 19:59:59 +01:00
Debug : : log ( LOG , " Keys done. " ) ;
2021-11-20 10:04:14 +01:00
2021-11-21 17:40:02 +01:00
// Add workspaces to the monitors
2021-11-22 18:43:55 +01:00
for ( long unsigned int i = 0 ; i < monitors . size ( ) ; + + i ) {
2021-11-21 17:40:02 +01:00
CWorkspace protoWorkspace ;
protoWorkspace . setID ( i + 1 ) ;
protoWorkspace . setMonitor ( i ) ;
2021-11-21 19:59:59 +01:00
protoWorkspace . setHasFullscreenWindow ( false ) ;
2021-11-21 17:40:02 +01:00
workspaces . push_back ( protoWorkspace ) ;
2021-11-21 19:59:59 +01:00
activeWorkspaces . push_back ( workspaces [ i ] . getID ( ) ) ;
2021-11-21 17:40:02 +01:00
}
2021-11-21 19:59:59 +01:00
Debug : : log ( LOG , " Workspace protos done. " ) ;
2021-11-20 10:04:14 +01:00
//
2021-11-21 11:25:26 +01:00
2021-11-27 13:28:30 +01:00
// ---- INIT THE THREAD FOR ANIM & CONFIG ---- //
2021-11-21 11:25:26 +01:00
2021-11-27 13:28:30 +01:00
// start its' update thread
Events : : setThread ( ) ;
2021-11-21 22:24:38 +01:00
2021-11-27 13:28:30 +01:00
Debug : : log ( LOG , " Thread (Parent) done. " ) ;
2021-11-21 19:59:59 +01:00
ConfigManager : : loadConfigLoadVars ( ) ;
2021-11-25 17:57:50 +01:00
updateRootCursor ( ) ;
2021-11-21 19:59:59 +01:00
Debug : : log ( LOG , " Finished setup! " ) ;
2021-11-23 22:15:36 +01:00
// TODO: EWMH
2021-11-18 18:04:09 +01:00
}
2021-11-20 09:25:21 +01:00
bool CWindowManager : : handleEvent ( ) {
if ( xcb_connection_has_error ( DisplayConnection ) )
2021-11-18 18:04:09 +01:00
return false ;
2021-11-21 11:25:26 +01:00
xcb_flush ( DisplayConnection ) ;
2021-12-06 18:56:24 +01:00
// recieve the event. Blocks.
recieveEvent ( ) ;
// refresh and apply the parameters of all dirty windows.
refreshDirtyWindows ( ) ;
// Sanity checks
for ( const auto active : activeWorkspaces ) {
sanityCheckOnWorkspace ( active ) ;
}
// remove unused workspaces
cleanupUnusedWorkspaces ( ) ;
// Update last window name
updateActiveWindowName ( ) ;
// Update the bar with the freshest stuff
updateBarInfo ( ) ;
2021-12-21 09:41:55 +01:00
// Update EWMH workspace info
EWMH : : updateDesktops ( ) ;
2021-12-06 18:56:24 +01:00
xcb_flush ( DisplayConnection ) ;
// Restore thread state
mainThreadBusy = false ;
return true ;
}
void CWindowManager : : recieveEvent ( ) {
2021-11-20 09:25:21 +01:00
const auto ev = xcb_wait_for_event ( DisplayConnection ) ;
2021-11-18 18:04:09 +01:00
if ( ev ! = NULL ) {
2021-11-23 18:48:03 +01:00
while ( animationUtilBusy ) {
2021-12-06 18:56:24 +01:00
; // wait for it to finish
2021-11-23 18:48:03 +01:00
}
// Set thread state, halt animations until done.
mainThreadBusy = true ;
2021-11-27 13:28:30 +01:00
// Read from the bar
2021-12-06 18:56:24 +01:00
if ( ! g_pWindowManager - > statusBar )
IPCRecieveMessageM ( m_sIPCBarPipeOut . szPipeName ) ;
2021-12-22 14:53:53 +01:00
const uint8_t TYPE = XCB_EVENT_RESPONSE_TYPE ( ev ) ;
2021-12-06 18:56:24 +01:00
const auto EVENTCODE = ev - > response_type & ~ 0x80 ;
2021-11-27 13:28:30 +01:00
2021-12-06 18:56:24 +01:00
switch ( EVENTCODE ) {
2021-11-18 18:04:09 +01:00
case XCB_ENTER_NOTIFY :
Events : : eventEnter ( ev ) ;
Debug : : log ( LOG , " Event dispatched ENTER " ) ;
break ;
2021-11-18 22:08:28 +01:00
case XCB_LEAVE_NOTIFY :
Events : : eventLeave ( ev ) ;
Debug : : log ( LOG , " Event dispatched LEAVE " ) ;
break ;
2021-11-18 18:04:09 +01:00
case XCB_DESTROY_NOTIFY :
Events : : eventDestroy ( ev ) ;
Debug : : log ( LOG , " Event dispatched DESTROY " ) ;
break ;
2021-11-30 17:08:52 +01:00
case XCB_UNMAP_NOTIFY :
Events : : eventUnmapWindow ( ev ) ;
Debug : : log ( LOG , " Event dispatched UNMAP " ) ;
break ;
2021-11-18 18:04:09 +01:00
case XCB_MAP_REQUEST :
Events : : eventMapWindow ( ev ) ;
Debug : : log ( LOG , " Event dispatched MAP " ) ;
break ;
2021-11-19 20:20:05 +01:00
case XCB_BUTTON_PRESS :
2021-11-22 21:20:32 +01:00
Events : : eventButtonPress ( ev ) ;
2021-11-21 15:25:57 +01:00
Debug : : log ( LOG , " Event dispatched BUTTON_PRESS " ) ;
2021-11-19 20:20:05 +01:00
break ;
2021-11-22 21:20:32 +01:00
case XCB_BUTTON_RELEASE :
Events : : eventButtonRelease ( ev ) ;
Debug : : log ( LOG , " Event dispatched BUTTON_RELEASE " ) ;
break ;
case XCB_MOTION_NOTIFY :
Events : : eventMotionNotify ( ev ) ;
2021-12-06 18:56:24 +01:00
// Debug::log(LOG, "Event dispatched MOTION_NOTIFY"); // Spam!!
2021-11-22 21:20:32 +01:00
break ;
2021-11-21 11:25:26 +01:00
case XCB_EXPOSE :
Events : : eventExpose ( ev ) ;
Debug : : log ( LOG , " Event dispatched EXPOSE " ) ;
break ;
2021-11-21 15:25:57 +01:00
case XCB_KEY_PRESS :
2021-11-22 21:20:32 +01:00
Events : : eventKeyPress ( ev ) ;
2021-11-21 15:25:57 +01:00
Debug : : log ( LOG , " Event dispatched KEY_PRESS " ) ;
break ;
2021-12-06 18:56:24 +01:00
case XCB_CLIENT_MESSAGE :
Events : : eventClientMessage ( ev ) ;
Debug : : log ( LOG , " Event dispatched CLIENT_MESSAGE " ) ;
break ;
2021-11-18 18:04:09 +01:00
default :
2021-12-06 18:56:24 +01:00
if ( ( EVENTCODE ! = 14 ) & & ( EVENTCODE ! = 13 ) & & ( EVENTCODE ! = 0 ) & & ( EVENTCODE ! = 22 ) )
2021-11-25 16:51:09 +01:00
Debug : : log ( WARN , " Unknown event: " + std : : to_string ( ev - > response_type & ~ 0x80 ) ) ;
2021-11-18 18:04:09 +01:00
break ;
}
2021-12-22 14:53:53 +01:00
if ( TYPE - RandREventBase = = XCB_RANDR_SCREEN_CHANGE_NOTIFY ) {
Events : : eventRandRScreenChange ( ev ) ;
Debug : : log ( LOG , " Event dispatched RANDR_SCREEN_CHANGE " ) ;
}
2021-11-18 18:04:09 +01:00
free ( ev ) ;
}
}
2021-11-20 10:04:14 +01:00
void CWindowManager : : cleanupUnusedWorkspaces ( ) {
2021-12-22 20:40:24 +01:00
std : : deque < CWorkspace > temp = workspaces ;
2021-11-20 10:04:14 +01:00
workspaces . clear ( ) ;
for ( auto & work : temp ) {
2021-11-21 17:40:02 +01:00
if ( ! isWorkspaceVisible ( work . getID ( ) ) ) {
2021-11-20 10:04:14 +01:00
// check if it has any children
bool hasChildren = false ;
for ( auto & window : windows ) {
if ( window . getWorkspaceID ( ) = = work . getID ( ) ) {
hasChildren = true ;
break ;
}
}
if ( hasChildren ) {
// Has windows opened on it.
workspaces . push_back ( work ) ;
}
} else {
// Foreground workspace
workspaces . push_back ( work ) ;
}
}
2021-11-21 22:24:38 +01:00
// Update bar info
updateBarInfo ( ) ;
2021-11-20 10:04:14 +01:00
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : refreshDirtyWindows ( ) {
2021-12-18 15:01:20 +01:00
const auto START = std : : chrono : : high_resolution_clock : : now ( ) ;
2021-11-18 18:04:09 +01:00
for ( auto & window : windows ) {
if ( window . getDirty ( ) ) {
2021-11-22 21:20:32 +01:00
window . setDirty ( false ) ;
2021-11-20 10:04:14 +01:00
2021-11-28 11:52:40 +01:00
// Check if the window isn't a node or has the noInterventions prop
2021-12-19 12:33:36 +01:00
if ( window . getChildNodeAID ( ) ! = 0 | | window . getNoInterventions ( ) | | window . getDock ( ) )
2021-11-22 18:43:55 +01:00
continue ;
2021-11-22 21:20:32 +01:00
2021-11-21 12:40:03 +01:00
setEffectiveSizePosUsingConfig ( & window ) ;
2021-11-21 11:42:44 +01:00
// Fullscreen flag
2021-11-21 17:40:02 +01:00
bool bHasFullscreenWindow = getWorkspaceByID ( window . getWorkspaceID ( ) ) - > getHasFullscreenWindow ( ) ;
2021-11-21 11:42:44 +01:00
2021-11-21 17:40:02 +01:00
// first and foremost, let's check if the window isn't on a hidden workspace
2021-12-11 14:50:29 +01:00
// or that it is not a non-fullscreen window in a fullscreen workspace thats under
2021-11-21 17:40:02 +01:00
if ( ! isWorkspaceVisible ( window . getWorkspaceID ( ) )
2021-12-11 14:50:29 +01:00
| | ( bHasFullscreenWindow & & ! window . getFullscreen ( ) & & ( window . getUnderFullscreen ( ) | | ! window . getIsFloating ( ) ) ) ) {
2021-11-20 10:04:14 +01:00
// Move it to hades
Values [ 0 ] = ( int ) 1500000 ; // hmu when monitors actually have that many pixels
Values [ 1 ] = ( int ) 1500000 ; // and we are still using xorg =)
2021-12-18 15:01:20 +01:00
if ( VECTORDELTANONZERO ( window . getLastUpdatePosition ( ) , Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ) {
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y , Values ) ;
window . setLastUpdatePosition ( Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ;
}
2021-11-20 10:04:14 +01:00
// Set the size JIC.
Values [ 0 ] = ( int ) window . getEffectiveSize ( ) . x ;
Values [ 1 ] = ( int ) window . getEffectiveSize ( ) . y ;
2021-12-18 15:01:20 +01:00
if ( VECTORDELTANONZERO ( window . getLastUpdateSize ( ) , Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ) {
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT , Values ) ;
window . setLastUpdateSize ( Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ;
}
2021-11-20 10:04:14 +01:00
continue ;
}
2021-11-19 22:29:44 +01:00
2021-11-21 11:42:44 +01:00
// Fullscreen window. No border, all screen.
if ( window . getFullscreen ( ) ) {
Values [ 0 ] = 0 ;
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_BORDER_WIDTH , Values ) ;
2021-11-21 22:24:38 +01:00
const auto MONITOR = getMonitorFromWindow ( & window ) ;
Values [ 0 ] = ( int ) MONITOR - > vecSize . x ;
Values [ 1 ] = ( int ) MONITOR - > vecSize . y ;
2021-12-18 15:01:20 +01:00
if ( VECTORDELTANONZERO ( window . getLastUpdateSize ( ) , Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ) {
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT , Values ) ;
window . setLastUpdateSize ( Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ;
}
2021-11-21 11:42:44 +01:00
2021-11-21 22:24:38 +01:00
Values [ 0 ] = ( int ) MONITOR - > vecPosition . x ;
Values [ 1 ] = ( int ) MONITOR - > vecPosition . y ;
2021-12-18 15:01:20 +01:00
if ( VECTORDELTANONZERO ( window . getLastUpdatePosition ( ) , Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ) {
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y , Values ) ;
window . setLastUpdatePosition ( Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ;
}
2021-11-21 11:42:44 +01:00
2021-12-04 15:55:54 +01:00
// Apply rounded corners, does all the checks inside
2021-12-06 19:43:01 +01:00
applyShapeToWindow ( & window ) ;
2021-12-04 15:55:54 +01:00
2021-11-21 11:42:44 +01:00
continue ;
}
2021-11-21 22:24:38 +01:00
// Update the position because the border makes the window jump
// I have added the bordersize vec2d before in the setEffectiveSizePosUsingConfig function.
2021-11-23 18:48:03 +01:00
Values [ 0 ] = ( int ) window . getRealPosition ( ) . x - ConfigManager : : getInt ( " border_size " ) ;
Values [ 1 ] = ( int ) window . getRealPosition ( ) . y - ConfigManager : : getInt ( " border_size " ) ;
2021-12-18 15:01:20 +01:00
if ( VECTORDELTANONZERO ( window . getLastUpdatePosition ( ) , Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ) {
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y , Values ) ;
window . setLastUpdatePosition ( Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ;
}
2021-11-18 18:04:09 +01:00
2021-12-04 15:55:54 +01:00
Values [ 0 ] = ( int ) ConfigManager : : getInt ( " border_size " ) ;
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_BORDER_WIDTH , Values ) ;
2021-12-10 21:55:41 +01:00
// do border
Values [ 0 ] = window . getRealBorderColor ( ) . getAsUint32 ( ) ;
xcb_change_window_attributes ( DisplayConnection , window . getDrawable ( ) , XCB_CW_BORDER_PIXEL , Values ) ;
2021-11-18 22:08:28 +01:00
2021-12-06 19:43:01 +01:00
// If it isn't animated or we have non-cheap animations, update the real size
2021-12-10 19:10:12 +01:00
if ( ! window . getIsAnimated ( ) | | ConfigManager : : getInt ( " anim:cheap " ) = = 0 ) {
2021-12-06 19:43:01 +01:00
Values [ 0 ] = ( int ) window . getRealSize ( ) . x ;
Values [ 1 ] = ( int ) window . getRealSize ( ) . y ;
2021-12-18 15:01:20 +01:00
if ( VECTORDELTANONZERO ( window . getLastUpdateSize ( ) , Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ) {
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT , Values ) ;
window . setLastUpdateSize ( Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ;
}
2021-12-06 19:43:01 +01:00
window . setFirstAnimFrame ( true ) ;
}
2021-12-10 19:10:12 +01:00
if ( ConfigManager : : getInt ( " anim:cheap " ) = = 1 & & window . getFirstAnimFrame ( ) & & window . getIsAnimated ( ) ) {
2021-12-06 19:43:01 +01:00
// first frame, fix the size if smaller
window . setFirstAnimFrame ( false ) ;
if ( window . getRealSize ( ) . x < window . getEffectiveSize ( ) . x | | window . getRealSize ( ) . y < window . getEffectiveSize ( ) . y ) {
Values [ 0 ] = ( int ) window . getEffectiveSize ( ) . x ;
Values [ 1 ] = ( int ) window . getEffectiveSize ( ) . y ;
2021-12-18 15:01:20 +01:00
if ( VECTORDELTANONZERO ( window . getLastUpdateSize ( ) , Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ) {
xcb_configure_window ( DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT , Values ) ;
window . setLastUpdateSize ( Vector2D ( Values [ 0 ] , Values [ 1 ] ) ) ;
}
2021-12-06 19:43:01 +01:00
}
}
applyShapeToWindow ( & window ) ;
2021-12-21 10:46:22 +01:00
// EWMH
EWMH : : updateWindow ( window . getDrawable ( ) ) ;
2021-11-18 18:04:09 +01:00
}
}
2021-12-11 13:04:03 +01:00
2021-12-18 15:01:20 +01:00
Debug : : log ( LOG , " Refreshed dirty windows in " + std : : to_string ( std : : chrono : : duration_cast < std : : chrono : : microseconds > ( std : : chrono : : high_resolution_clock : : now ( ) - START ) . count ( ) ) + " us. " ) ;
2021-11-18 18:04:09 +01:00
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : setFocusedWindow ( xcb_drawable_t window ) {
if ( window & & window ! = Screen - > root ) {
2021-12-10 21:55:41 +01:00
// border color
if ( const auto PLASTWIN = getWindowFromDrawable ( LastWindow ) ; PLASTWIN ) {
PLASTWIN - > setEffectiveBorderColor ( CFloatingColor ( ConfigManager : : getInt ( " col.inactive_border " ) ) ) ;
}
if ( const auto PLASTWIN = getWindowFromDrawable ( window ) ; PLASTWIN ) {
PLASTWIN - > setEffectiveBorderColor ( CFloatingColor ( ConfigManager : : getInt ( " col.active_border " ) ) ) ;
}
2021-11-18 22:08:28 +01:00
2021-11-22 21:20:32 +01:00
float values [ 1 ] ;
2021-12-17 23:27:27 +01:00
if ( const auto PWINDOW = g_pWindowManager - > getWindowFromDrawable ( window ) ; PWINDOW ) {
2021-12-17 22:25:36 +01:00
// Apply rounded corners, does all the checks inside.
// The border changed so let's not make it rectangular maybe
2021-12-17 23:27:27 +01:00
applyShapeToWindow ( PWINDOW ) ;
2021-12-17 22:25:36 +01:00
}
2021-12-04 20:52:55 +01:00
2021-11-20 09:25:21 +01:00
LastWindow = window ;
2021-12-04 20:52:55 +01:00
2021-12-21 12:22:41 +01:00
const auto PNEWFOCUS = g_pWindowManager - > getWindowFromDrawable ( window ) ;
if ( PNEWFOCUS ) {
2021-12-17 22:25:36 +01:00
applyShapeToWindow ( g_pWindowManager - > getWindowFromDrawable ( window ) ) ;
2021-12-05 12:05:44 +01:00
2021-12-21 12:22:41 +01:00
// Transients
PNEWFOCUS - > bringTopRecursiveTransients ( ) ;
}
2021-12-17 22:25:36 +01:00
// set focus in X11
xcb_set_input_focus ( DisplayConnection , XCB_INPUT_FOCUS_POINTER_ROOT , window , XCB_CURRENT_TIME ) ;
2021-12-13 20:21:54 +01:00
2021-12-17 22:25:36 +01:00
// EWMH
EWMH : : updateCurrentWindow ( window ) ;
}
2021-11-18 18:04:09 +01:00
}
2021-11-24 21:50:44 +01:00
// TODO: make this executed less. It's too often imo.
2021-11-24 18:51:34 +01:00
void CWindowManager : : sanityCheckOnWorkspace ( int workspaceID ) {
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = workspaceID ) {
// Check #1: Parent has 2 identical children (happens!)
if ( w . getDrawable ( ) < 0 ) {
const auto CHILDA = w . getChildNodeAID ( ) ;
const auto CHILDB = w . getChildNodeBID ( ) ;
if ( CHILDA = = CHILDB ) {
// Fix. Remove this parent, replace with child.
Debug : : log ( LOG , " Sanity check A triggered for window ID " + std : : to_string ( w . getDrawable ( ) ) ) ;
const auto PCHILD = getWindowFromDrawable ( CHILDA ) ;
2021-11-24 21:50:44 +01:00
if ( ! PCHILD ) {
// Means both children are 0 (dead)
removeWindowFromVectorSafe ( w . getDrawable ( ) ) ;
continue ;
}
2021-11-24 18:51:34 +01:00
PCHILD - > setPosition ( w . getPosition ( ) ) ;
PCHILD - > setSize ( w . getSize ( ) ) ;
// make the sibling replace the parent
PCHILD - > setParentNodeID ( w . getParentNodeID ( ) ) ;
if ( w . getParentNodeID ( ) ! = 0 & & getWindowFromDrawable ( w . getParentNodeID ( ) ) ) {
if ( getWindowFromDrawable ( w . getParentNodeID ( ) ) - > getChildNodeAID ( ) = = w . getDrawable ( ) ) {
getWindowFromDrawable ( w . getParentNodeID ( ) ) - > setChildNodeAID ( w . getDrawable ( ) ) ;
} else {
getWindowFromDrawable ( w . getParentNodeID ( ) ) - > setChildNodeBID ( w . getDrawable ( ) ) ;
}
}
// Make the sibling eat the closed window
PCHILD - > setDirtyRecursive ( true ) ;
PCHILD - > recalcSizePosRecursive ( ) ;
// Remove the parent
removeWindowFromVectorSafe ( w . getDrawable ( ) ) ;
if ( findWindowAtCursor ( ) )
setFocusedWindow ( findWindowAtCursor ( ) - > getDrawable ( ) ) ; // Set focus. :)
Debug : : log ( LOG , " Sanity check A finished successfully. " ) ;
}
}
2021-11-24 19:01:29 +01:00
// Hypothetical check #2: Check if children are present and tiled. (for nodes)
// I have not found this occurring but I have had some issues with... stuff.
if ( w . getDrawable ( ) < 0 ) {
const auto CHILDA = getWindowFromDrawable ( w . getChildNodeAID ( ) ) ;
const auto CHILDB = getWindowFromDrawable ( w . getChildNodeBID ( ) ) ;
if ( CHILDA & & CHILDB ) {
if ( CHILDA - > getIsFloating ( ) ) {
g_pWindowManager - > fixWindowOnClose ( CHILDA ) ;
g_pWindowManager - > calculateNewWindowParams ( CHILDA ) ;
2021-11-24 21:50:44 +01:00
Debug : : log ( LOG , " Found an invalid tiled window, ID: " + std : : to_string ( CHILDA - > getDrawable ( ) ) + " , untiling it. " ) ;
2021-11-24 19:01:29 +01:00
}
if ( CHILDB - > getIsFloating ( ) ) {
g_pWindowManager - > fixWindowOnClose ( CHILDB ) ;
g_pWindowManager - > calculateNewWindowParams ( CHILDB ) ;
2021-11-24 21:50:44 +01:00
Debug : : log ( LOG , " Found an invalid tiled window, ID: " + std : : to_string ( CHILDB - > getDrawable ( ) ) + " , untiling it. " ) ;
2021-11-24 19:01:29 +01:00
}
} else {
Debug : : log ( ERR , " Malformed node ID " + std : : to_string ( w . getDrawable ( ) ) + " with 2 children but one or both are nullptr. " ) ;
}
}
2021-11-24 18:51:34 +01:00
}
}
}
2021-11-22 18:43:55 +01:00
CWindow * CWindowManager : : getWindowFromDrawable ( int64_t window ) {
2021-11-24 21:50:44 +01:00
if ( ! window )
return nullptr ;
2021-12-17 20:58:32 +01:00
for ( auto & w : windows ) {
if ( w . getDrawable ( ) = = window ) {
return & w ;
}
}
for ( auto & w : unmappedWindows ) {
2021-11-18 18:04:09 +01:00
if ( w . getDrawable ( ) = = window ) {
return & w ;
}
}
2021-12-17 20:58:32 +01:00
2021-11-18 18:04:09 +01:00
return nullptr ;
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : addWindowToVectorSafe ( CWindow window ) {
for ( auto & w : windows ) {
2021-11-18 18:04:09 +01:00
if ( w . getDrawable ( ) = = window . getDrawable ( ) )
return ; // Do not add if already present.
}
2021-11-20 09:25:21 +01:00
windows . push_back ( window ) ;
2021-11-18 18:04:09 +01:00
}
2021-11-23 17:41:30 +01:00
void CWindowManager : : removeWindowFromVectorSafe ( int64_t window ) {
2021-11-18 18:04:09 +01:00
if ( ! window )
return ;
2021-12-22 20:40:24 +01:00
std : : deque < CWindow > temp = windows ;
2021-11-18 18:04:09 +01:00
2021-11-20 09:25:21 +01:00
windows . clear ( ) ;
2021-11-18 18:04:09 +01:00
for ( auto p : temp ) {
if ( p . getDrawable ( ) ! = window ) {
2021-11-20 09:25:21 +01:00
windows . push_back ( p ) ;
2021-11-18 18:04:09 +01:00
continue ;
}
}
}
2021-12-06 19:43:01 +01:00
void CWindowManager : : applyShapeToWindow ( CWindow * pWindow ) {
2021-11-28 14:03:34 +01:00
if ( ! pWindow )
return ;
2021-12-04 15:55:54 +01:00
const auto ROUNDING = pWindow - > getFullscreen ( ) ? 0 : ConfigManager : : getInt ( " rounding " ) ;
2021-11-28 14:03:34 +01:00
const auto SHAPEQUERY = xcb_get_extension_data ( DisplayConnection , & xcb_shape_id ) ;
2021-12-04 15:55:54 +01:00
if ( ! SHAPEQUERY | | ! SHAPEQUERY - > present | | pWindow - > getNoInterventions ( ) )
2021-11-28 14:03:34 +01:00
return ;
2021-12-04 15:55:54 +01:00
// Prepare values
const auto MONITOR = getMonitorFromWindow ( pWindow ) ;
const uint16_t W = pWindow - > getFullscreen ( ) ? MONITOR - > vecSize . x : pWindow - > getRealSize ( ) . x ;
const uint16_t H = pWindow - > getFullscreen ( ) ? MONITOR - > vecSize . y : pWindow - > getRealSize ( ) . y ;
const uint16_t BORDER = pWindow - > getFullscreen ( ) ? 0 : ConfigManager : : getInt ( " border_size " ) ;
const uint16_t TOTALW = W + 2 * BORDER ;
const uint16_t TOTALH = H + 2 * BORDER ;
const auto RADIUS = ROUNDING + BORDER ;
const auto DIAMETER = RADIUS = = 0 ? 0 : RADIUS * 2 - 1 ;
const xcb_arc_t BOUNDINGARCS [ ] = {
{ - 1 , - 1 , DIAMETER , DIAMETER , 0 , 360 < < 6 } ,
{ - 1 , TOTALH - DIAMETER , DIAMETER , DIAMETER , 0 , 360 < < 6 } ,
{ TOTALW - DIAMETER , - 1 , DIAMETER , DIAMETER , 0 , 360 < < 6 } ,
{ TOTALW - DIAMETER , TOTALH - DIAMETER , DIAMETER , DIAMETER , 0 , 360 < < 6 } ,
} ;
const xcb_rectangle_t BOUNDINGRECTS [ ] = {
{ RADIUS , 0 , TOTALW - DIAMETER , TOTALH } ,
{ 0 , RADIUS , TOTALW , TOTALH - DIAMETER } ,
} ;
const auto DIAMETERC = ROUNDING = = 0 ? 0 : 2 * ROUNDING - 1 ;
xcb_arc_t CLIPPINGARCS [ ] = {
{ - 1 , - 1 , DIAMETERC , DIAMETERC , 0 , 360 < < 6 } ,
{ - 1 , H - DIAMETERC , DIAMETERC , DIAMETERC , 0 , 360 < < 6 } ,
{ W - DIAMETERC , - 1 , DIAMETERC , DIAMETERC , 0 , 360 < < 6 } ,
{ W - DIAMETERC , H - DIAMETERC , DIAMETERC , DIAMETERC , 0 , 360 < < 6 } ,
} ;
xcb_rectangle_t CLIPPINGRECTS [ ] = {
{ ROUNDING , 0 , W - DIAMETERC , H } ,
{ 0 , ROUNDING , W , H - DIAMETERC } ,
} ;
// Values done
2021-11-28 14:03:34 +01:00
2021-12-04 15:55:54 +01:00
// XCB
2021-11-28 14:03:34 +01:00
2021-12-04 15:55:54 +01:00
const xcb_pixmap_t PIXMAP1 = xcb_generate_id ( DisplayConnection ) ;
const xcb_pixmap_t PIXMAP2 = xcb_generate_id ( DisplayConnection ) ;
const xcb_gcontext_t BLACK = xcb_generate_id ( DisplayConnection ) ;
const xcb_gcontext_t WHITE = xcb_generate_id ( DisplayConnection ) ;
xcb_create_pixmap ( DisplayConnection , 1 , PIXMAP1 , pWindow - > getDrawable ( ) , TOTALW , TOTALH ) ;
xcb_create_pixmap ( DisplayConnection , 1 , PIXMAP2 , pWindow - > getDrawable ( ) , W , H ) ;
2021-11-28 14:03:34 +01:00
Values [ 0 ] = 0 ;
Values [ 1 ] = 0 ;
2021-12-04 15:55:54 +01:00
xcb_create_gc ( DisplayConnection , BLACK , PIXMAP1 , XCB_GC_FOREGROUND , Values ) ;
2021-11-28 14:03:34 +01:00
Values [ 0 ] = 1 ;
2021-12-04 15:55:54 +01:00
xcb_create_gc ( DisplayConnection , WHITE , PIXMAP1 , XCB_GC_FOREGROUND , Values ) ;
2021-11-28 14:03:34 +01:00
2021-12-04 15:55:54 +01:00
// XCB done
// Draw
xcb_rectangle_t BOUNDINGRECT = { 0 , 0 , W + 2 * BORDER , H + 2 * BORDER } ;
xcb_poly_fill_rectangle ( DisplayConnection , PIXMAP1 , BLACK , 1 , & BOUNDINGRECT ) ;
xcb_poly_fill_rectangle ( DisplayConnection , PIXMAP1 , WHITE , 2 , BOUNDINGRECTS ) ;
xcb_poly_fill_arc ( DisplayConnection , PIXMAP1 , WHITE , 4 , BOUNDINGARCS ) ;
xcb_rectangle_t CLIPPINGRECT = { 0 , 0 , W , H } ;
xcb_poly_fill_rectangle ( DisplayConnection , PIXMAP2 , BLACK , 1 , & CLIPPINGRECT ) ;
xcb_poly_fill_rectangle ( DisplayConnection , PIXMAP2 , WHITE , 2 , CLIPPINGRECTS ) ;
xcb_poly_fill_arc ( DisplayConnection , PIXMAP2 , WHITE , 4 , CLIPPINGARCS ) ;
// Draw done
// Shape
2021-11-28 14:03:34 +01:00
2021-12-04 15:55:54 +01:00
xcb_shape_mask ( DisplayConnection , XCB_SHAPE_SO_SET , XCB_SHAPE_SK_BOUNDING , pWindow - > getDrawable ( ) , - BORDER , - BORDER , PIXMAP1 ) ;
xcb_shape_mask ( DisplayConnection , XCB_SHAPE_SO_SET , XCB_SHAPE_SK_CLIP , pWindow - > getDrawable ( ) , 0 , 0 , PIXMAP2 ) ;
2021-11-28 14:03:34 +01:00
2021-12-04 15:55:54 +01:00
// Shape done
2021-11-28 14:03:34 +01:00
2021-12-04 15:55:54 +01:00
// Cleanup
2021-11-28 14:03:34 +01:00
2021-12-04 15:55:54 +01:00
xcb_free_pixmap ( DisplayConnection , PIXMAP1 ) ;
xcb_free_pixmap ( DisplayConnection , PIXMAP2 ) ;
2021-11-28 14:03:34 +01:00
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : setEffectiveSizePosUsingConfig ( CWindow * pWindow ) {
2021-11-25 17:44:46 +01:00
if ( ! pWindow | | pWindow - > getIsFloating ( ) )
2021-11-18 22:08:28 +01:00
return ;
2021-12-18 15:01:20 +01:00
auto START = std : : chrono : : high_resolution_clock : : now ( ) ;
2021-11-21 20:34:31 +01:00
const auto MONITOR = getMonitorFromWindow ( pWindow ) ;
2021-12-17 23:31:12 +01:00
const auto BARHEIGHT = ( MONITOR - > ID = = ConfigManager : : getInt ( " bar:monitor " ) ? ( ConfigManager : : getInt ( " bar:enabled " ) = = 1 ? ConfigManager : : getInt ( " bar:height " ) : ConfigManager : : parseError = = " " ? 0 : ConfigManager : : getInt ( " bar:height " ) ) : 0 ) ;
2021-11-21 20:34:31 +01:00
2021-11-19 19:04:42 +01:00
// set some flags.
2021-11-21 20:34:31 +01:00
const bool DISPLAYLEFT = STICKS ( pWindow - > getPosition ( ) . x , MONITOR - > vecPosition . x ) ;
const bool DISPLAYRIGHT = STICKS ( pWindow - > getPosition ( ) . x + pWindow - > getSize ( ) . x , MONITOR - > vecPosition . x + MONITOR - > vecSize . x ) ;
const bool DISPLAYTOP = STICKS ( pWindow - > getPosition ( ) . y , MONITOR - > vecPosition . y ) ;
const bool DISPLAYBOTTOM = STICKS ( pWindow - > getPosition ( ) . y + pWindow - > getSize ( ) . y , MONITOR - > vecPosition . y + MONITOR - > vecSize . y ) ;
2021-11-19 19:04:42 +01:00
2021-12-18 15:01:20 +01:00
const auto BORDERSIZE = ConfigManager : : getInt ( " border_size " ) ;
const auto GAPSOUT = ConfigManager : : getInt ( " gaps_out " ) ;
const auto GAPSIN = ConfigManager : : getInt ( " gaps_in " ) ;
pWindow - > setEffectivePosition ( pWindow - > getPosition ( ) + Vector2D ( BORDERSIZE , BORDERSIZE ) ) ;
pWindow - > setEffectiveSize ( pWindow - > getSize ( ) - ( Vector2D ( BORDERSIZE , BORDERSIZE ) * 2 ) ) ;
2021-11-19 19:04:42 +01:00
2021-12-18 15:01:20 +01:00
const auto OFFSETTOPLEFT = Vector2D ( DISPLAYLEFT ? GAPSOUT + MONITOR - > vecReservedTopLeft . x : GAPSIN ,
DISPLAYTOP ? GAPSOUT + MONITOR - > vecReservedTopLeft . y + BARHEIGHT : GAPSIN ) ;
2021-12-17 20:58:32 +01:00
2021-12-18 15:01:20 +01:00
const auto OFFSETBOTTOMRIGHT = Vector2D ( DISPLAYRIGHT ? GAPSOUT + MONITOR - > vecReservedBottomRight . x : GAPSIN ,
DISPLAYBOTTOM ? GAPSOUT + MONITOR - > vecReservedBottomRight . y : GAPSIN ) ;
2021-12-17 20:58:32 +01:00
2021-11-19 19:04:42 +01:00
// do gaps, set top left
2021-12-17 20:58:32 +01:00
pWindow - > setEffectivePosition ( pWindow - > getEffectivePosition ( ) + OFFSETTOPLEFT ) ;
2021-11-19 19:04:42 +01:00
// fix to old size bottom right
2021-12-17 20:58:32 +01:00
pWindow - > setEffectiveSize ( pWindow - > getEffectiveSize ( ) - OFFSETTOPLEFT ) ;
2021-11-19 19:04:42 +01:00
// set bottom right
2021-12-17 20:58:32 +01:00
pWindow - > setEffectiveSize ( pWindow - > getEffectiveSize ( ) - OFFSETBOTTOMRIGHT ) ;
2021-11-18 22:08:28 +01:00
}
2021-11-21 15:15:33 +01:00
CWindow * CWindowManager : : findWindowAtCursor ( ) {
const auto POINTERCOOKIE = xcb_query_pointer ( DisplayConnection , Screen - > root ) ;
2021-11-22 21:20:32 +01:00
Vector2D cursorPos = getCursorPos ( ) ;
2021-11-21 15:15:33 +01:00
2021-11-21 17:40:02 +01:00
const auto WORKSPACE = activeWorkspaces [ getMonitorFromCursor ( ) - > ID ] ;
2021-11-21 15:15:33 +01:00
for ( auto & window : windows ) {
2021-11-28 12:43:53 +01:00
if ( window . getWorkspaceID ( ) = = WORKSPACE & & ! window . getIsFloating ( ) & & window . getDrawable ( ) > 0 ) {
2021-11-21 15:15:33 +01:00
if ( cursorPos . x > = window . getPosition ( ) . x
& & cursorPos . x < = window . getPosition ( ) . x + window . getSize ( ) . x
& & cursorPos . y > = window . getPosition ( ) . y
& & cursorPos . y < = window . getPosition ( ) . y + window . getSize ( ) . y ) {
return & window ;
}
}
}
2021-11-21 17:40:02 +01:00
return nullptr ;
2021-11-21 15:15:33 +01:00
}
2021-12-21 18:30:35 +01:00
CWindow * CWindowManager : : findFirstWindowOnWorkspace ( const int & work ) {
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = work & & ! w . getIsFloating ( ) & & ! w . getNoInterventions ( ) & & w . getDrawable ( ) > 0 ) {
return & w ;
}
}
return nullptr ;
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : calculateNewTileSetOldTile ( CWindow * pWindow ) {
2021-11-22 18:43:55 +01:00
// Get the parent and both children, one of which will be pWindow
const auto PPARENT = getWindowFromDrawable ( pWindow - > getParentNodeID ( ) ) ;
2021-12-22 14:53:53 +01:00
auto PMONITOR = getMonitorFromWindow ( pWindow ) ;
2021-12-04 23:16:24 +01:00
if ( ! PMONITOR ) {
2021-12-22 14:53:53 +01:00
Debug : : log ( ERR , " Monitor was nullptr! (calculateNewTileSetOldTile) using 0. " ) ;
PMONITOR = & monitors [ 0 ] ;
if ( monitors . size ( ) = = 0 ) {
Debug : : log ( ERR , " Not continuing. Monitors size 0. " ) ;
return ;
}
2021-12-04 23:16:24 +01:00
}
2021-11-22 18:43:55 +01:00
if ( ! PPARENT ) {
// New window on this workspace.
// Open a fullscreen window.
2021-12-04 23:16:24 +01:00
pWindow - > setSize ( Vector2D ( PMONITOR - > vecSize . x , PMONITOR - > vecSize . y ) ) ;
pWindow - > setPosition ( Vector2D ( PMONITOR - > vecPosition . x , PMONITOR - > vecPosition . y ) ) ;
2021-11-21 15:15:33 +01:00
2021-11-22 18:43:55 +01:00
return ;
2021-11-21 15:15:33 +01:00
}
2021-12-04 23:16:24 +01:00
switch ( ConfigManager : : getInt ( " layout " ) )
{
case LAYOUT_DWINDLE :
{
// Get the sibling
const auto PSIBLING = getWindowFromDrawable ( PPARENT - > getChildNodeAID ( ) = = pWindow - > getDrawable ( ) ? PPARENT - > getChildNodeBID ( ) : PPARENT - > getChildNodeAID ( ) ) ;
// Should NEVER be null
if ( PSIBLING ) {
const auto PLASTSIZE = PPARENT - > getSize ( ) ;
const auto PLASTPOS = PPARENT - > getPosition ( ) ;
if ( PLASTSIZE . x > PLASTSIZE . y ) {
PSIBLING - > setPosition ( Vector2D ( PLASTPOS . x , PLASTPOS . y ) ) ;
PSIBLING - > setSize ( Vector2D ( PLASTSIZE . x / 2.f , PLASTSIZE . y ) ) ;
pWindow - > setSize ( Vector2D ( PLASTSIZE . x / 2.f , PLASTSIZE . y ) ) ;
pWindow - > setPosition ( Vector2D ( PLASTPOS . x + PLASTSIZE . x / 2.f , PLASTPOS . y ) ) ;
} else {
PSIBLING - > setPosition ( Vector2D ( PLASTPOS . x , PLASTPOS . y ) ) ;
PSIBLING - > setSize ( Vector2D ( PLASTSIZE . x , PLASTSIZE . y / 2.f ) ) ;
pWindow - > setSize ( Vector2D ( PLASTSIZE . x , PLASTSIZE . y / 2.f ) ) ;
pWindow - > setPosition ( Vector2D ( PLASTPOS . x , PLASTPOS . y + PLASTSIZE . y / 2.f ) ) ;
}
PSIBLING - > setDirty ( true ) ;
} else {
Debug : : log ( ERR , " Sibling node was null?? pWindow x,y,w,h: " + std : : to_string ( pWindow - > getPosition ( ) . x ) + " " + std : : to_string ( pWindow - > getPosition ( ) . y ) + " " + std : : to_string ( pWindow - > getSize ( ) . x ) + " " + std : : to_string ( pWindow - > getSize ( ) . y ) ) ;
}
2021-11-18 18:04:09 +01:00
}
2021-12-04 23:16:24 +01:00
break ;
case LAYOUT_MASTER :
{
recalcEntireWorkspace ( pWindow - > getWorkspaceID ( ) ) ;
}
break ;
}
}
2021-11-18 18:04:09 +01:00
2021-12-04 23:16:24 +01:00
int CWindowManager : : getWindowsOnWorkspace ( const int & workspace ) {
int number = 0 ;
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = workspace & & w . getDrawable ( ) > 0 ) {
+ + number ;
}
2021-11-18 18:04:09 +01:00
}
2021-11-22 21:20:32 +01:00
2021-12-04 23:16:24 +01:00
return number ;
}
SMonitor * CWindowManager : : getMonitorFromWorkspace ( const int & workspace ) {
int monitorID = - 1 ;
for ( auto & work : workspaces ) {
if ( work . getID ( ) = = workspace ) {
monitorID = work . getMonitor ( ) ;
break ;
}
}
for ( auto & monitor : monitors ) {
if ( monitor . ID = = monitorID ) {
return & monitor ;
}
}
return nullptr ;
}
void CWindowManager : : recalcEntireWorkspace ( const int & workspace ) {
switch ( ConfigManager : : getInt ( " layout " ) )
{
case LAYOUT_MASTER :
{
// Get the monitor
const auto PMONITOR = getMonitorFromWorkspace ( workspace ) ;
// first, calc the size
CWindow * pMaster = nullptr ;
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = workspace & & w . getMaster ( ) & & ! w . getDead ( ) ) {
pMaster = & w ;
break ;
}
}
if ( ! pMaster ) {
Debug : : log ( ERR , " No master found on workspace??? " ) ;
return ;
}
// set the xy for master
pMaster - > setPosition ( Vector2D ( 0 , 0 ) + PMONITOR - > vecPosition ) ;
pMaster - > setSize ( Vector2D ( PMONITOR - > vecSize . x / 2 , PMONITOR - > vecSize . y ) ) ;
// get children sorted
std : : vector < CWindow * > children ;
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = workspace & & ! w . getMaster ( ) & & w . getDrawable ( ) > 0 & & ! w . getDead ( ) )
children . push_back ( & w ) ;
}
std : : sort ( children . begin ( ) , children . end ( ) , [ ] ( CWindow * & a , CWindow * & b ) {
return a - > getMasterChildIndex ( ) < b - > getMasterChildIndex ( ) ;
} ) ;
// if no children, master full
if ( children . size ( ) = = 0 ) {
pMaster - > setPosition ( Vector2D ( 0 , 0 ) + PMONITOR - > vecPosition ) ;
pMaster - > setSize ( Vector2D ( PMONITOR - > vecSize . x , PMONITOR - > vecSize . y ) ) ;
}
// Children sorted, set xy
int yoff = 0 ;
for ( const auto & child : children ) {
child - > setPosition ( Vector2D ( PMONITOR - > vecSize . x / 2 , yoff ) + PMONITOR - > vecPosition ) ;
child - > setSize ( Vector2D ( PMONITOR - > vecSize . x / 2 , PMONITOR - > vecSize . y / children . size ( ) ) ) ;
yoff + = PMONITOR - > vecSize . y / children . size ( ) ;
}
// done
setAllWorkspaceWindowsDirtyByID ( workspace ) ;
}
break ;
case LAYOUT_DWINDLE :
{
// get the master on the workspace
CWindow * pMasterWindow = nullptr ;
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = workspace & & w . getParentNodeID ( ) = = 0 ) {
pMasterWindow = & w ;
break ;
}
}
2021-12-22 14:53:53 +01:00
if ( ! pMasterWindow )
return ;
const auto PMONITOR = getMonitorFromWorkspace ( workspace ) ;
if ( ! PMONITOR )
2021-12-04 23:16:24 +01:00
return ;
2021-12-22 14:53:53 +01:00
Debug : : log ( LOG , " Recalc for workspace " + std : : to_string ( workspace ) ) ;
pMasterWindow - > setSize ( PMONITOR - > vecSize ) ;
pMasterWindow - > setPosition ( PMONITOR - > vecPosition ) ;
2021-12-04 23:16:24 +01:00
pMasterWindow - > recalcSizePosRecursive ( ) ;
setAllWorkspaceWindowsDirtyByID ( workspace ) ;
}
break ;
default :
break ;
}
2021-11-18 18:04:09 +01:00
}
2021-11-21 15:15:33 +01:00
void CWindowManager : : calculateNewFloatingWindow ( CWindow * pWindow ) {
if ( ! pWindow )
return ;
2021-12-19 12:33:36 +01:00
if ( ! pWindow - > getNoInterventions ( ) & & ! pWindow - > getDock ( ) ) {
2021-12-04 17:07:26 +01:00
pWindow - > setPosition ( pWindow - > getEffectivePosition ( ) + Vector2D ( 3 , 3 ) ) ;
pWindow - > setSize ( pWindow - > getEffectiveSize ( ) - Vector2D ( 6 , 6 ) ) ;
2021-11-22 21:20:32 +01:00
2021-12-04 23:38:31 +01:00
// min size
pWindow - > setSize ( Vector2D ( std : : clamp ( pWindow - > getSize ( ) . x , ( double ) 40 , ( double ) 99999 ) ,
std : : clamp ( pWindow - > getSize ( ) . y , ( double ) 40 , ( double ) 99999 ) ) ) ;
2021-11-28 11:52:40 +01:00
pWindow - > setEffectivePosition ( pWindow - > getPosition ( ) + Vector2D ( 10 , 10 ) ) ;
2021-12-04 17:07:26 +01:00
pWindow - > setEffectiveSize ( pWindow - > getSize ( ) ) ;
2021-11-24 19:33:32 +01:00
2021-11-28 11:52:40 +01:00
pWindow - > setRealPosition ( pWindow - > getPosition ( ) ) ;
pWindow - > setRealSize ( pWindow - > getSize ( ) ) ;
}
2021-11-25 16:06:52 +01:00
2021-11-22 21:20:32 +01:00
Values [ 0 ] = XCB_STACK_MODE_ABOVE ;
xcb_configure_window ( DisplayConnection , pWindow - > getDrawable ( ) , XCB_CONFIG_WINDOW_STACK_MODE , Values ) ;
2021-11-21 15:15:33 +01:00
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : calculateNewWindowParams ( CWindow * pWindow ) {
2021-11-18 18:04:09 +01:00
// And set old one's if needed.
if ( ! pWindow )
return ;
if ( ! pWindow - > getIsFloating ( ) ) {
calculateNewTileSetOldTile ( pWindow ) ;
2021-11-21 15:15:33 +01:00
} else {
calculateNewFloatingWindow ( pWindow ) ;
2021-11-18 18:04:09 +01:00
}
2021-11-23 18:48:03 +01:00
setEffectiveSizePosUsingConfig ( pWindow ) ;
2021-11-18 18:04:09 +01:00
pWindow - > setDirty ( true ) ;
}
2021-11-20 09:25:21 +01:00
bool CWindowManager : : isNeighbor ( CWindow * a , CWindow * b ) {
2021-11-20 10:04:14 +01:00
2021-11-21 20:17:49 +01:00
if ( a - > getWorkspaceID ( ) ! = b - > getWorkspaceID ( ) )
2021-11-20 10:04:14 +01:00
return false ; // Different workspaces
2021-11-18 18:04:09 +01:00
const auto POSA = a - > getPosition ( ) ;
const auto POSB = b - > getPosition ( ) ;
const auto SIZEA = a - > getSize ( ) ;
2021-11-18 22:26:29 +01:00
const auto SIZEB = b - > getSize ( ) ;
2021-11-18 18:04:09 +01:00
if ( POSA . x ! = 0 ) {
if ( STICKS ( POSA . x , ( POSB . x + SIZEB . x ) ) ) {
return true ;
}
}
if ( POSA . y ! = 0 ) {
if ( STICKS ( POSA . y , ( POSB . y + SIZEB . y ) ) ) {
return true ;
}
}
if ( POSB . x ! = 0 ) {
if ( STICKS ( POSB . x , ( POSA . x + SIZEA . x ) ) ) {
return true ;
}
}
if ( POSB . y ! = 0 ) {
if ( STICKS ( POSB . y , ( POSA . y + SIZEA . y ) ) ) {
return true ;
}
}
return false ;
}
2021-11-20 09:25:21 +01:00
bool CWindowManager : : canEatWindow ( CWindow * a , CWindow * toEat ) {
2021-11-19 19:04:42 +01:00
// Pos is min of both.
const auto POSAFTEREAT = Vector2D ( std : : min ( a - > getPosition ( ) . x , toEat - > getPosition ( ) . x ) , std : : min ( a - > getPosition ( ) . y , toEat - > getPosition ( ) . y ) ) ;
// Size is pos + size max - pos
const auto OPPCORNERA = Vector2D ( POSAFTEREAT ) + a - > getSize ( ) ;
const auto OPPCORNERB = toEat - > getPosition ( ) + toEat - > getSize ( ) ;
const auto SIZEAFTEREAT = Vector2D ( std : : max ( OPPCORNERA . x , OPPCORNERB . x ) , std : : max ( OPPCORNERA . y , OPPCORNERB . y ) ) - POSAFTEREAT ;
const auto doOverlap = [ & ] ( CWindow * b ) {
const auto RIGHT1 = Vector2D ( POSAFTEREAT . x + SIZEAFTEREAT . x , POSAFTEREAT . y + SIZEAFTEREAT . y ) ;
const auto RIGHT2 = b - > getPosition ( ) + b - > getSize ( ) ;
const auto LEFT1 = POSAFTEREAT ;
const auto LEFT2 = b - > getPosition ( ) ;
return ! ( LEFT1 . x > = RIGHT2 . x | | LEFT2 . x > = RIGHT1 . x | | LEFT1 . y > = RIGHT2 . y | | LEFT2 . y > = RIGHT1 . y ) ;
} ;
2021-11-20 09:25:21 +01:00
for ( auto & w : windows ) {
2021-11-21 17:40:02 +01:00
if ( w . getDrawable ( ) = = a - > getDrawable ( ) | | w . getDrawable ( ) = = toEat - > getDrawable ( ) | | w . getWorkspaceID ( ) ! = toEat - > getWorkspaceID ( )
| | w . getIsFloating ( ) | | getMonitorFromWindow ( & w ) ! = getMonitorFromWindow ( toEat ) )
2021-11-19 19:04:42 +01:00
continue ;
if ( doOverlap ( & w ) )
return false ;
}
return true ;
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : eatWindow ( CWindow * a , CWindow * toEat ) {
2021-11-19 22:29:44 +01:00
2021-11-18 18:04:09 +01:00
// Size is pos + size max - pos
const auto OPPCORNERA = a - > getPosition ( ) + a - > getSize ( ) ;
const auto OPPCORNERB = toEat - > getPosition ( ) + toEat - > getSize ( ) ;
2021-11-19 20:39:43 +01:00
// Pos is min of both.
a - > setPosition ( Vector2D ( std : : min ( a - > getPosition ( ) . x , toEat - > getPosition ( ) . x ) , std : : min ( a - > getPosition ( ) . y , toEat - > getPosition ( ) . y ) ) ) ;
2021-11-18 18:04:09 +01:00
a - > setSize ( Vector2D ( std : : max ( OPPCORNERA . x , OPPCORNERB . x ) , std : : max ( OPPCORNERA . y , OPPCORNERB . y ) ) - a - > getPosition ( ) ) ;
}
2021-11-24 21:50:44 +01:00
void CWindowManager : : closeWindowAllChecks ( int64_t id ) {
// fix last window if tile
const auto CLOSEDWINDOW = g_pWindowManager - > getWindowFromDrawable ( id ) ;
2021-11-28 12:57:10 +01:00
2021-12-11 12:54:45 +01:00
if ( ! CLOSEDWINDOW )
return ; // It's not in the vec, ignore. (weird)
2021-12-17 20:58:32 +01:00
CLOSEDWINDOW - > setDead ( true ) ;
2021-12-11 12:54:45 +01:00
if ( const auto WORKSPACE = getWorkspaceByID ( CLOSEDWINDOW - > getWorkspaceID ( ) ) ; WORKSPACE & & CLOSEDWINDOW - > getFullscreen ( ) )
WORKSPACE - > setHasFullscreenWindow ( false ) ;
2021-11-25 16:51:09 +01:00
2021-12-11 14:53:51 +01:00
if ( ! CLOSEDWINDOW - > getIsFloating ( ) )
g_pWindowManager - > fixWindowOnClose ( CLOSEDWINDOW ) ;
2021-12-17 20:58:32 +01:00
const bool WASDOCK = CLOSEDWINDOW - > getDock ( ) ;
2021-12-11 14:53:51 +01:00
2021-11-25 16:51:09 +01:00
// delete off of the arr
g_pWindowManager - > removeWindowFromVectorSafe ( id ) ;
2021-12-17 20:58:32 +01:00
// Fix docks
if ( WASDOCK )
g_pWindowManager - > recalcAllDocks ( ) ;
2021-11-24 21:50:44 +01:00
}
2021-12-04 23:16:24 +01:00
void CWindowManager : : fixMasterWorkspaceOnClosed ( CWindow * pWindow ) {
// get children and master
CWindow * pMaster = nullptr ;
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = pWindow - > getWorkspaceID ( ) & & w . getMaster ( ) ) {
pMaster = & w ;
break ;
}
}
if ( ! pMaster ) {
Debug : : log ( ERR , " No master found on workspace??? " ) ;
return ;
}
// get children sorted
std : : vector < CWindow * > children ;
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = pWindow - > getWorkspaceID ( ) & & ! w . getMaster ( ) & & w . getDrawable ( ) > 0 & & w . getDrawable ( ) ! = pWindow - > getDrawable ( ) )
children . push_back ( & w ) ;
}
std : : sort ( children . begin ( ) , children . end ( ) , [ ] ( CWindow * & a , CWindow * & b ) {
return a - > getMasterChildIndex ( ) < b - > getMasterChildIndex ( ) ;
} ) ;
// If closed window was master, set a new master.
if ( pWindow - > getMaster ( ) ) {
if ( children . size ( ) > 0 ) {
children [ 0 ] - > setMaster ( true ) ;
}
} else {
// else fix the indices
for ( long unsigned int i = pWindow - > getMasterChildIndex ( ) - 1 ; i < children . size ( ) ; + + i ) {
// masterChildIndex = 1 for the first child
children [ i ] - > setMasterChildIndex ( i ) ;
}
}
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : fixWindowOnClose ( CWindow * pClosedWindow ) {
2021-11-18 18:04:09 +01:00
if ( ! pClosedWindow )
return ;
2021-11-22 18:43:55 +01:00
// Get the parent and both children, one of which will be pWindow
const auto PPARENT = getWindowFromDrawable ( pClosedWindow - > getParentNodeID ( ) ) ;
2021-11-21 17:40:02 +01:00
2021-11-22 18:43:55 +01:00
if ( ! PPARENT )
return ; // if there was no parent, we do not need to update anything. it was a fullscreen window, the only one on a given workspace.
2021-11-21 11:42:44 +01:00
2021-11-22 18:43:55 +01:00
// Get the sibling
const auto PSIBLING = getWindowFromDrawable ( PPARENT - > getChildNodeAID ( ) = = pClosedWindow - > getDrawable ( ) ? PPARENT - > getChildNodeBID ( ) : PPARENT - > getChildNodeAID ( ) ) ;
2021-11-18 18:04:09 +01:00
2021-11-22 21:20:32 +01:00
if ( ! PSIBLING ) {
Debug : : log ( ERR , " No sibling found in fixOnClose! (Corrupted tree...?) " ) ;
return ;
}
2021-12-04 23:16:24 +01:00
// used by master layout
pClosedWindow - > setDead ( true ) ;
2021-11-22 18:43:55 +01:00
2021-12-04 23:16:24 +01:00
// FIX TREE ----
2021-11-22 18:43:55 +01:00
// make the sibling replace the parent
2021-12-04 23:16:24 +01:00
PSIBLING - > setPosition ( PPARENT - > getPosition ( ) ) ;
PSIBLING - > setSize ( PPARENT - > getSize ( ) ) ;
2021-11-22 18:43:55 +01:00
PSIBLING - > setParentNodeID ( PPARENT - > getParentNodeID ( ) ) ;
2021-12-04 23:16:24 +01:00
if ( PPARENT - > getParentNodeID ( ) ! = 0
2021-11-22 18:43:55 +01:00
& & getWindowFromDrawable ( PPARENT - > getParentNodeID ( ) ) ) {
if ( getWindowFromDrawable ( PPARENT - > getParentNodeID ( ) ) - > getChildNodeAID ( ) = = PPARENT - > getDrawable ( ) ) {
getWindowFromDrawable ( PPARENT - > getParentNodeID ( ) ) - > setChildNodeAID ( PSIBLING - > getDrawable ( ) ) ;
} else {
getWindowFromDrawable ( PPARENT - > getParentNodeID ( ) ) - > setChildNodeBID ( PSIBLING - > getDrawable ( ) ) ;
}
2021-11-18 18:04:09 +01:00
}
2021-12-04 23:16:24 +01:00
// TREE FIXED ----
2021-11-18 18:04:09 +01:00
2021-12-04 23:16:24 +01:00
// Fix master stuff
const auto WORKSPACE = pClosedWindow - > getWorkspaceID ( ) ;
fixMasterWorkspaceOnClosed ( pClosedWindow ) ;
2021-11-18 18:04:09 +01:00
2021-12-04 23:16:24 +01:00
// recalc the workspace
if ( ConfigManager : : getInt ( " layout " ) = = LAYOUT_MASTER )
recalcEntireWorkspace ( WORKSPACE ) ;
else {
PSIBLING - > recalcSizePosRecursive ( ) ;
PSIBLING - > setDirtyRecursive ( true ) ;
}
2021-11-22 18:43:55 +01:00
// Remove the parent
removeWindowFromVectorSafe ( PPARENT - > getDrawable ( ) ) ;
2021-11-18 18:04:09 +01:00
2021-11-22 18:43:55 +01:00
if ( findWindowAtCursor ( ) )
setFocusedWindow ( findWindowAtCursor ( ) - > getDrawable ( ) ) ; // Set focus. :)
2021-11-19 22:29:44 +01:00
}
2021-11-20 09:25:21 +01:00
CWindow * CWindowManager : : getNeighborInDir ( char dir ) {
2021-11-19 22:29:44 +01:00
2021-11-20 09:25:21 +01:00
const auto CURRENTWINDOW = getWindowFromDrawable ( LastWindow ) ;
2021-11-19 22:29:44 +01:00
if ( ! CURRENTWINDOW )
return nullptr ;
const auto POSA = CURRENTWINDOW - > getPosition ( ) ;
const auto SIZEA = CURRENTWINDOW - > getSize ( ) ;
2021-11-20 09:25:21 +01:00
for ( auto & w : windows ) {
2021-11-20 10:04:14 +01:00
if ( w . getDrawable ( ) = = CURRENTWINDOW - > getDrawable ( ) | | w . getWorkspaceID ( ) ! = CURRENTWINDOW - > getWorkspaceID ( ) )
2021-11-19 22:29:44 +01:00
continue ;
const auto POSB = w . getPosition ( ) ;
const auto SIZEB = w . getSize ( ) ;
switch ( dir ) {
case ' l ' :
if ( STICKS ( POSA . x , POSB . x + SIZEB . x ) )
return & w ;
break ;
case ' r ' :
if ( STICKS ( POSA . x + SIZEA . x , POSB . x ) )
return & w ;
break ;
case ' t ' :
2021-12-05 12:05:44 +01:00
case ' u ' :
2021-11-19 22:29:44 +01:00
if ( STICKS ( POSA . y , POSB . y + SIZEB . y ) )
return & w ;
break ;
case ' b ' :
2021-12-05 12:05:44 +01:00
case ' d ' :
2021-11-19 22:29:44 +01:00
if ( STICKS ( POSA . y + SIZEA . y , POSB . y ) )
return & w ;
break ;
}
}
return nullptr ;
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : warpCursorTo ( Vector2D to ) {
const auto POINTERCOOKIE = xcb_query_pointer ( DisplayConnection , Screen - > root ) ;
2021-11-19 23:08:59 +01:00
2021-11-20 09:25:21 +01:00
xcb_query_pointer_reply_t * pointerreply = xcb_query_pointer_reply ( DisplayConnection , POINTERCOOKIE , NULL ) ;
2021-11-19 23:08:59 +01:00
if ( ! pointerreply ) {
Debug : : log ( ERR , " Couldn't query pointer. " ) ;
2021-11-22 22:37:01 +01:00
free ( pointerreply ) ;
2021-11-19 23:08:59 +01:00
return ;
}
2021-12-23 10:06:48 +01:00
xcb_warp_pointer ( DisplayConnection , XCB_NONE , Screen - > root , 0 , 0 , Screen - > width_in_pixels , Screen - > height_in_pixels , ( int ) to . x , ( int ) to . y ) ;
2021-11-19 23:08:59 +01:00
free ( pointerreply ) ;
}
2021-11-25 17:44:46 +01:00
void CWindowManager : : moveActiveWindowToWorkspace ( int workspace ) {
const auto PWINDOW = getWindowFromDrawable ( LastWindow ) ;
if ( ! PWINDOW )
return ;
const auto SAVEDDEFAULTSIZE = PWINDOW - > getDefaultSize ( ) ;
const auto SAVEDFLOATSTATUS = PWINDOW - > getIsFloating ( ) ;
const auto SAVEDDRAWABLE = PWINDOW - > getDrawable ( ) ;
closeWindowAllChecks ( SAVEDDRAWABLE ) ;
// PWINDOW is dead!
changeWorkspaceByID ( workspace ) ;
// Find new mon
int NEWMONITOR = 0 ;
for ( long unsigned int i = 0 ; i < activeWorkspaces . size ( ) ; + + i ) {
if ( activeWorkspaces [ i ] = = workspace ) {
NEWMONITOR = i ;
}
}
// Find the first window on the new workspace
xcb_drawable_t newLastWindow = 0 ;
for ( auto & w : windows ) {
if ( w . getDrawable ( ) > 0 & & w . getWorkspaceID ( ) = = workspace & & ! w . getIsFloating ( ) ) {
newLastWindow = w . getDrawable ( ) ;
break ;
}
}
if ( newLastWindow ) {
setFocusedWindow ( newLastWindow ) ;
}
2021-12-21 18:30:35 +01:00
CWindow newWindow ;
newWindow . setDrawable ( SAVEDDRAWABLE ) ;
newWindow . setFirstOpen ( false ) ;
addWindowToVectorSafe ( newWindow ) ;
2021-11-25 17:44:46 +01:00
CWindow * PNEWWINDOW = nullptr ;
if ( SAVEDFLOATSTATUS )
PNEWWINDOW = Events : : remapFloatingWindow ( SAVEDDRAWABLE , NEWMONITOR ) ;
else
PNEWWINDOW = Events : : remapWindow ( SAVEDDRAWABLE , false , NEWMONITOR ) ;
PNEWWINDOW - > setDefaultSize ( SAVEDDEFAULTSIZE ) ;
}
2021-11-20 09:25:21 +01:00
void CWindowManager : : moveActiveWindowTo ( char dir ) {
const auto CURRENTWINDOW = getWindowFromDrawable ( LastWindow ) ;
2021-11-19 22:29:44 +01:00
if ( ! CURRENTWINDOW )
return ;
const auto neighbor = getNeighborInDir ( dir ) ;
if ( ! neighbor )
return ;
// swap their stuff and mark dirty
const auto TEMP_SIZEA = CURRENTWINDOW - > getSize ( ) ;
const auto TEMP_POSA = CURRENTWINDOW - > getPosition ( ) ;
CURRENTWINDOW - > setSize ( neighbor - > getSize ( ) ) ;
CURRENTWINDOW - > setPosition ( neighbor - > getPosition ( ) ) ;
neighbor - > setSize ( TEMP_SIZEA ) ;
neighbor - > setPosition ( TEMP_POSA ) ;
CURRENTWINDOW - > setDirty ( true ) ;
neighbor - > setDirty ( true ) ;
2021-12-23 10:06:48 +01:00
// finish by moving the cursor to the new current window
2021-11-20 09:25:21 +01:00
warpCursorTo ( CURRENTWINDOW - > getPosition ( ) + CURRENTWINDOW - > getSize ( ) / 2.f ) ;
2021-11-20 10:04:14 +01:00
}
2021-12-12 13:40:13 +01:00
CWindow * CWindowManager : : getFullscreenWindowByWorkspace ( const int & id ) {
for ( auto & window : windows ) {
2021-12-23 10:16:53 +01:00
if ( window . getWorkspaceID ( ) = = id & & window . getFullscreen ( ) & & window . getDrawable ( ) > 0 )
2021-12-12 13:40:13 +01:00
return & window ;
}
return nullptr ;
}
2021-12-05 12:05:44 +01:00
void CWindowManager : : moveActiveFocusTo ( char dir ) {
const auto CURRENTWINDOW = getWindowFromDrawable ( LastWindow ) ;
if ( ! CURRENTWINDOW )
return ;
2021-12-12 13:40:13 +01:00
const auto PWORKSPACE = getWorkspaceByID ( CURRENTWINDOW - > getWorkspaceID ( ) ) ;
2021-12-05 12:05:44 +01:00
2021-12-12 13:40:13 +01:00
if ( ! PWORKSPACE )
return ;
const auto NEIGHBOR = PWORKSPACE - > getHasFullscreenWindow ( ) ? getFullscreenWindowByWorkspace ( PWORKSPACE - > getID ( ) ) : getNeighborInDir ( dir ) ;
if ( ! NEIGHBOR )
2021-12-05 12:05:44 +01:00
return ;
// move the focus
2021-12-12 13:40:13 +01:00
setFocusedWindow ( NEIGHBOR - > getDrawable ( ) ) ;
2021-12-05 12:05:44 +01:00
2021-12-23 10:06:48 +01:00
// finish by moving the cursor to the neighbor window
warpCursorTo ( NEIGHBOR - > getPosition ( ) + ( NEIGHBOR - > getSize ( ) / 2.f ) ) ;
2021-12-05 12:05:44 +01:00
}
2021-11-20 10:04:14 +01:00
void CWindowManager : : changeWorkspaceByID ( int ID ) {
2021-11-21 17:40:02 +01:00
2021-12-22 14:53:53 +01:00
auto MONITOR = getMonitorFromCursor ( ) ;
2021-11-21 22:24:38 +01:00
2021-11-22 22:37:01 +01:00
if ( ! MONITOR ) {
2021-12-22 14:53:53 +01:00
Debug : : log ( ERR , " Monitor was nullptr! (changeWorkspaceByID) Using monitor 0. " ) ;
MONITOR = & monitors [ 0 ] ;
2021-11-22 22:37:01 +01:00
}
2021-11-21 22:24:38 +01:00
// mark old workspace dirty
setAllWorkspaceWindowsDirtyByID ( activeWorkspaces [ MONITOR - > ID ] ) ;
2021-11-21 17:40:02 +01:00
2021-11-20 10:04:14 +01:00
for ( auto & workspace : workspaces ) {
if ( workspace . getID ( ) = = ID ) {
2021-11-23 22:23:22 +01:00
// set workspaces dirty
setAllWorkspaceWindowsDirtyByID ( activeWorkspaces [ workspace . getMonitor ( ) ] ) ;
setAllWorkspaceWindowsDirtyByID ( ID ) ;
2021-11-21 19:59:59 +01:00
activeWorkspaces [ workspace . getMonitor ( ) ] = workspace . getID ( ) ;
2021-11-21 21:16:19 +01:00
2021-12-12 13:40:13 +01:00
// if not fullscreen set the focus to any window on that workspace
// if fullscreen, set to the fullscreen window
const auto PWORKSPACE = getWorkspaceByID ( ID ) ;
if ( PWORKSPACE ) {
if ( ! PWORKSPACE - > getHasFullscreenWindow ( ) ) {
for ( auto & window : windows ) {
if ( window . getWorkspaceID ( ) = = ID & & window . getDrawable ( ) > 0 ) {
setFocusedWindow ( window . getDrawable ( ) ) ;
break ;
}
}
} else {
const auto PFULLWINDOW = getFullscreenWindowByWorkspace ( ID ) ;
if ( PFULLWINDOW )
setFocusedWindow ( PFULLWINDOW - > getDrawable ( ) ) ;
2021-11-23 22:23:22 +01:00
}
}
2021-11-21 22:24:38 +01:00
// Update bar info
updateBarInfo ( ) ;
2021-11-23 22:23:22 +01:00
2021-11-21 19:59:59 +01:00
return ;
2021-11-20 10:04:14 +01:00
}
}
// If we are here it means the workspace is new. Let's create it.
CWorkspace newWorkspace ;
newWorkspace . setID ( ID ) ;
2021-11-21 17:40:02 +01:00
newWorkspace . setMonitor ( MONITOR - > ID ) ;
2021-11-20 10:04:14 +01:00
workspaces . push_back ( newWorkspace ) ;
2021-11-21 19:59:59 +01:00
activeWorkspaces [ MONITOR - > ID ] = workspaces [ workspaces . size ( ) - 1 ] . getID ( ) ;
2021-11-20 10:04:14 +01:00
LastWindow = - 1 ;
2021-11-21 21:16:19 +01:00
2021-11-21 22:24:38 +01:00
// Update bar info
updateBarInfo ( ) ;
// no need for the new dirty, it's empty
2021-11-20 10:04:14 +01:00
}
2021-11-21 12:40:03 +01:00
void CWindowManager : : setAllWindowsDirty ( ) {
for ( auto & window : windows ) {
window . setDirty ( true ) ;
}
}
2021-11-20 10:04:14 +01:00
void CWindowManager : : setAllWorkspaceWindowsDirtyByID ( int ID ) {
int workspaceID = - 1 ;
for ( auto & workspace : workspaces ) {
if ( workspace . getID ( ) = = ID ) {
workspaceID = workspace . getID ( ) ;
break ;
}
}
if ( workspaceID = = - 1 )
return ;
for ( auto & window : windows ) {
if ( window . getWorkspaceID ( ) = = workspaceID )
window . setDirty ( true ) ;
}
2021-11-21 11:25:26 +01:00
}
int CWindowManager : : getHighestWorkspaceID ( ) {
int max = - 1 ;
for ( auto & workspace : workspaces ) {
if ( workspace . getID ( ) > max ) {
max = workspace . getID ( ) ;
}
}
return max ;
}
CWorkspace * CWindowManager : : getWorkspaceByID ( int ID ) {
for ( auto & workspace : workspaces ) {
if ( workspace . getID ( ) = = ID ) {
return & workspace ;
}
}
return nullptr ;
2021-11-21 17:40:02 +01:00
}
SMonitor * CWindowManager : : getMonitorFromWindow ( CWindow * pWindow ) {
return & monitors [ pWindow - > getMonitor ( ) ] ;
}
SMonitor * CWindowManager : : getMonitorFromCursor ( ) {
2021-11-22 21:20:32 +01:00
const auto CURSORPOS = getCursorPos ( ) ;
for ( auto & monitor : monitors ) {
if ( VECINRECT ( CURSORPOS , monitor . vecPosition . x , monitor . vecPosition . y , monitor . vecPosition . x + monitor . vecSize . x , monitor . vecPosition . y + monitor . vecSize . y ) )
return & monitor ;
}
// should never happen tho, I'm using >= and the cursor cant get outside the screens, i hope.
return nullptr ;
}
Vector2D CWindowManager : : getCursorPos ( ) {
2021-11-21 17:40:02 +01:00
const auto POINTERCOOKIE = xcb_query_pointer ( DisplayConnection , Screen - > root ) ;
xcb_query_pointer_reply_t * pointerreply = xcb_query_pointer_reply ( DisplayConnection , POINTERCOOKIE , NULL ) ;
if ( ! pointerreply ) {
Debug : : log ( ERR , " Couldn't query pointer. " ) ;
2021-11-22 22:37:01 +01:00
free ( pointerreply ) ;
2021-11-22 21:20:32 +01:00
return Vector2D ( 0 , 0 ) ;
2021-11-21 17:40:02 +01:00
}
const auto CURSORPOS = Vector2D ( pointerreply - > root_x , pointerreply - > root_y ) ;
free ( pointerreply ) ;
2021-11-22 21:20:32 +01:00
return CURSORPOS ;
2021-11-21 17:40:02 +01:00
}
bool CWindowManager : : isWorkspaceVisible ( int workspaceID ) {
for ( auto & workspace : activeWorkspaces ) {
2021-11-21 19:59:59 +01:00
if ( workspace = = workspaceID )
2021-11-21 17:40:02 +01:00
return true ;
}
return false ;
}
2021-11-21 22:24:38 +01:00
void CWindowManager : : updateBarInfo ( ) {
2021-11-27 13:28:30 +01:00
// IPC
// What we need to send:
// - Workspace data
// - Active Workspace
2021-12-10 22:12:42 +01:00
// If bar disabled, ignore
if ( ConfigManager : : getInt ( " bar:enabled " ) = = 0 )
return ;
2021-11-27 13:28:30 +01:00
SIPCMessageMainToBar message ;
2021-11-21 22:24:38 +01:00
2021-12-22 14:53:53 +01:00
auto PMONITOR = getMonitorFromCursor ( ) ;
if ( ! PMONITOR ) {
Debug : : log ( ERR , " Monitor was null! (updateBarInfo) Using 0. " ) ;
PMONITOR = & monitors [ 0 ] ;
if ( monitors . size ( ) = = 0 ) {
Debug : : log ( ERR , " Not continuing. Monitors size 0. " ) ;
return ;
}
2021-11-22 22:37:01 +01:00
}
2021-12-22 14:53:53 +01:00
message . activeWorkspace = activeWorkspaces [ PMONITOR - > ID ] ;
2021-11-27 13:28:30 +01:00
2021-11-27 19:07:33 +01:00
auto winname = getWindowFromDrawable ( LastWindow ) ? getWindowFromDrawable ( LastWindow ) - > getName ( ) : " " ;
2021-12-01 22:23:16 +01:00
auto winclassname = getWindowFromDrawable ( LastWindow ) ? getWindowFromDrawable ( LastWindow ) - > getClassName ( ) : " " ;
2021-11-27 19:07:33 +01:00
for ( auto & c : winname ) {
// Remove illegal chars
2021-12-17 23:27:27 +01:00
if ( c = = ' = ' | | c = = ' \t ' )
2021-11-27 19:07:33 +01:00
c = ' ' ;
}
2021-12-01 22:23:16 +01:00
for ( auto & c : winclassname ) {
// Remove illegal chars
2021-12-17 23:27:27 +01:00
if ( c = = ' = ' | | c = = ' \t ' )
2021-12-01 22:23:16 +01:00
c = ' ' ;
}
2021-11-27 19:07:33 +01:00
message . lastWindowName = winname ;
2021-12-01 22:23:16 +01:00
message . lastWindowClass = winclassname ;
2021-11-27 20:24:50 +01:00
message . fullscreenOnBar = getWorkspaceByID ( activeWorkspaces [ ConfigManager : : getInt ( " bar:monitor " ) > monitors . size ( ) ? 0 : ConfigManager : : getInt ( " bar:monitor " ) ] ) - > getHasFullscreenWindow ( ) ;
2021-11-27 13:28:30 +01:00
for ( auto & workspace : workspaces ) {
message . openWorkspaces . push_back ( workspace . getID ( ) ) ;
}
IPCSendMessage ( m_sIPCBarPipeIn . szPipeName , message ) ;
2021-11-28 13:04:07 +01:00
// Also check if the bar should be made invisibel
// we make it by moving it far far away
// the bar will also stop all updates
if ( message . fullscreenOnBar ) {
if ( lastKnownBarPosition . x = = - 1 & & lastKnownBarPosition . y = = - 1 ) {
lastKnownBarPosition = monitors [ ConfigManager : : getInt ( " bar:monitor " ) > monitors . size ( ) ? 0 : ConfigManager : : getInt ( " bar:monitor " ) ] . vecPosition ;
}
Values [ 0 ] = ( int ) - 99999 ;
Values [ 1 ] = ( int ) - 99999 ;
xcb_configure_window ( DisplayConnection , barWindowID , XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y , Values ) ;
} else {
if ( lastKnownBarPosition . x ! = - 1 & & lastKnownBarPosition . y ! = - 1 ) {
Values [ 0 ] = ( int ) lastKnownBarPosition . x ;
Values [ 1 ] = ( int ) lastKnownBarPosition . y ;
xcb_configure_window ( DisplayConnection , barWindowID , XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y , Values ) ;
}
lastKnownBarPosition = Vector2D ( - 1 , - 1 ) ;
}
2021-11-23 16:53:29 +01:00
}
2021-11-23 17:43:27 +01:00
void CWindowManager : : setAllFloatingWindowsTop ( ) {
for ( auto & window : windows ) {
2021-12-21 12:22:41 +01:00
if ( window . getIsFloating ( ) & & ! window . getTransient ( ) ) {
2021-11-23 17:43:27 +01:00
Values [ 0 ] = XCB_STACK_MODE_ABOVE ;
xcb_configure_window ( g_pWindowManager - > DisplayConnection , window . getDrawable ( ) , XCB_CONFIG_WINDOW_STACK_MODE , Values ) ;
2021-12-21 12:22:41 +01:00
window . bringTopRecursiveTransients ( ) ;
2021-12-23 10:06:48 +01:00
} else {
2021-12-21 12:22:41 +01:00
window . bringTopRecursiveTransients ( ) ;
2021-11-23 17:43:27 +01:00
}
}
2021-11-23 22:15:36 +01:00
}
2021-12-06 19:43:01 +01:00
void CWindowManager : : setAWindowTop ( xcb_window_t window ) {
Values [ 0 ] = XCB_STACK_MODE_ABOVE ;
xcb_configure_window ( g_pWindowManager - > DisplayConnection , window , XCB_CONFIG_WINDOW_STACK_MODE , Values ) ;
}
2021-11-23 22:15:36 +01:00
bool CWindowManager : : shouldBeFloatedOnInit ( int64_t window ) {
// Should be floated also sets some properties
2021-12-21 18:30:35 +01:00
const auto PWINDOW = getWindowFromDrawable ( window ) ;
if ( ! PWINDOW ) {
Debug : : log ( ERR , " shouldBeFloatedOnInit with an invalid window! " ) ;
return true ;
}
2021-11-24 18:37:45 +01:00
const auto WINCLASS = getClassName ( window ) ;
const auto CLASSNAME = WINCLASS . second ;
const auto CLASSINSTANCE = WINCLASS . first ;
2021-11-23 22:15:36 +01:00
Debug : : log ( LOG , " New window got class " + ( std : : string ) CLASSINSTANCE + " -> " + CLASSNAME ) ;
xcb_change_property ( DisplayConnection , XCB_PROP_MODE_REPLACE , window , XCB_ATOM_WM_NAME , XCB_ATOM_STRING , 8 , strlen ( " hypr " ) , " hypr " ) ;
2021-11-24 18:37:45 +01:00
// Role stuff
const auto WINROLE = getRoleName ( window ) ;
Debug : : log ( LOG , " Window opened with a role of " + WINROLE ) ;
2021-12-21 18:30:35 +01:00
// Set it in the pwindow
PWINDOW - > setClassName ( CLASSNAME ) ;
PWINDOW - > setRoleName ( WINROLE ) ;
2021-11-27 19:07:33 +01:00
2021-11-24 18:37:45 +01:00
//
// Type stuff
//
PROP ( wm_type_cookie , HYPRATOMS [ " _NET_WM_WINDOW_TYPE " ] , UINT32_MAX ) ;
xcb_atom_t TYPEATOM = NULL ;
if ( wm_type_cookiereply = = NULL | | xcb_get_property_value_length ( wm_type_cookiereply ) < 1 ) {
2021-12-13 20:21:54 +01:00
Debug : : log ( LOG , " No preferred type found. (shouldBeFloatedOnInit) " ) ;
2021-11-24 18:37:45 +01:00
} else {
const auto ATOMS = ( xcb_atom_t * ) xcb_get_property_value ( wm_type_cookiereply ) ;
if ( ! ATOMS ) {
Debug : : log ( ERR , " Atoms not found in preferred type! " ) ;
} else {
2021-11-28 16:14:12 +01:00
if ( xcbContainsAtom ( wm_type_cookiereply , HYPRATOMS [ " _NET_WM_WINDOW_TYPE_DOCK " ] ) ) {
2021-11-24 18:37:45 +01:00
free ( wm_type_cookiereply ) ;
return true ;
2021-11-28 16:14:12 +01:00
} else if ( xcbContainsAtom ( wm_type_cookiereply , HYPRATOMS [ " _NET_WM_WINDOW_TYPE_DIALOG " ] )
| | xcbContainsAtom ( wm_type_cookiereply , HYPRATOMS [ " _NET_WM_WINDOW_TYPE_TOOLBAR " ] )
| | xcbContainsAtom ( wm_type_cookiereply , HYPRATOMS [ " _NET_WM_WINDOW_TYPE_UTILITY " ] )
| | xcbContainsAtom ( wm_type_cookiereply , HYPRATOMS [ " _NET_WM_STATE_MODAL " ] )
| | xcbContainsAtom ( wm_type_cookiereply , HYPRATOMS [ " _NET_WM_WINDOW_TYPE_SPLASH " ] ) ) {
Events : : nextWindowCentered = true ;
2021-11-28 11:52:40 +01:00
free ( wm_type_cookiereply ) ;
return true ;
2021-11-24 18:37:45 +01:00
}
}
}
free ( wm_type_cookiereply ) ;
//
//
//
2021-12-21 18:30:35 +01:00
// Verify the rules.
for ( auto & rule : ConfigManager : : getMatchingRules ( window ) ) {
if ( rule . szRule = = " tile " )
return false ;
else if ( rule . szRule = = " float " )
return true ;
}
2021-11-23 22:15:36 +01:00
return false ;
2021-11-27 19:07:33 +01:00
}
void CWindowManager : : updateActiveWindowName ( ) {
if ( ! getWindowFromDrawable ( LastWindow ) )
return ;
const auto PLASTWINDOW = getWindowFromDrawable ( LastWindow ) ;
auto WINNAME = getWindowName ( LastWindow ) ;
if ( WINNAME ! = PLASTWINDOW - > getName ( ) ) {
Debug : : log ( LOG , " Update, window got name: " + WINNAME ) ;
PLASTWINDOW - > setName ( WINNAME ) ;
}
2021-11-28 11:52:40 +01:00
}
void CWindowManager : : doPostCreationChecks ( CWindow * pWindow ) {
//
Debug : : log ( LOG , " Post creation checks init " ) ;
const auto window = pWindow - > getDrawable ( ) ;
PROP ( wm_type_cookie , HYPRATOMS [ " _NET_WM_WINDOW_TYPE " ] , UINT32_MAX ) ;
if ( wm_type_cookiereply = = NULL | | xcb_get_property_value_length ( wm_type_cookiereply ) < 1 ) {
2021-12-13 20:21:54 +01:00
Debug : : log ( LOG , " No preferred type found. (doPostCreationChecks) " ) ;
2021-11-28 11:52:40 +01:00
} else {
const auto ATOMS = ( xcb_atom_t * ) xcb_get_property_value ( wm_type_cookiereply ) ;
if ( ! ATOMS ) {
Debug : : log ( ERR , " Atoms not found in preferred type! " ) ;
} else {
if ( xcbContainsAtom ( wm_type_cookiereply , HYPRATOMS [ " _NET_WM_STATE_FULLSCREEN " ] ) ) {
// set it fullscreen
pWindow - > setFullscreen ( true ) ;
setFocusedWindow ( window ) ;
KeybindManager : : toggleActiveWindowFullscreen ( " " ) ;
}
}
}
free ( wm_type_cookiereply ) ;
2021-12-19 00:47:58 +01:00
// Check if it has a name
const auto NAME = getClassName ( window ) ;
if ( NAME . first = = " Error " & & NAME . second = = " Error " ) {
closeWindowAllChecks ( window ) ;
Debug : : log ( WARN , " Window created but has a class of NULL. Removing. " ) ;
}
2021-11-28 11:52:40 +01:00
Debug : : log ( LOG , " Post creation checks ended " ) ;
//
2021-11-30 16:43:28 +01:00
}
void CWindowManager : : getICCCMWMProtocols ( CWindow * pWindow ) {
xcb_icccm_get_wm_protocols_reply_t WMProtocolsReply ;
if ( ! xcb_icccm_get_wm_protocols_reply ( DisplayConnection ,
xcb_icccm_get_wm_protocols ( DisplayConnection , pWindow - > getDrawable ( ) , HYPRATOMS [ " WM_PROTOCOLS " ] ) , & WMProtocolsReply , NULL ) )
return ;
for ( auto i = 0 ; i < ( int ) WMProtocolsReply . atoms_len ; i + + ) {
if ( WMProtocolsReply . atoms [ i ] = = HYPRATOMS [ " WM_DELETE_WINDOW " ] )
pWindow - > setCanKill ( true ) ;
}
xcb_icccm_get_wm_protocols_reply_wipe ( & WMProtocolsReply ) ;
2021-12-02 15:08:19 +01:00
}
void CWindowManager : : refocusWindowOnClosed ( ) {
const auto PWINDOW = findWindowAtCursor ( ) ;
2021-12-05 12:05:44 +01:00
// No window or last window valid
2021-12-13 20:44:14 +01:00
if ( ! PWINDOW | | getWindowFromDrawable ( LastWindow ) ) {
setFocusedWindow ( Screen - > root ) ; //refocus on root
2021-12-02 15:08:19 +01:00
return ;
2021-12-13 20:44:14 +01:00
}
2021-12-02 15:08:19 +01:00
LastWindow = PWINDOW - > getDrawable ( ) ;
setFocusedWindow ( PWINDOW - > getDrawable ( ) ) ;
2021-12-04 23:16:24 +01:00
}
void CWindowManager : : recalcAllWorkspaces ( ) {
for ( auto & workspace : workspaces ) {
recalcEntireWorkspace ( workspace . getID ( ) ) ;
}
2021-12-11 12:54:45 +01:00
}
void CWindowManager : : moveWindowToUnmapped ( int64_t id ) {
for ( auto & w : windows ) {
if ( w . getDrawable ( ) = = id ) {
// Move it
unmappedWindows . push_back ( w ) ;
removeWindowFromVectorSafe ( w . getDrawable ( ) ) ;
return ;
}
}
}
void CWindowManager : : moveWindowToMapped ( int64_t id ) {
for ( auto & w : unmappedWindows ) {
if ( w . getDrawable ( ) = = id ) {
// Move it
windows . push_back ( w ) ;
// manually remove
auto temp = unmappedWindows ;
unmappedWindows . clear ( ) ;
for ( auto & t : temp ) {
if ( t . getDrawable ( ) ! = id )
unmappedWindows . push_back ( t ) ;
}
2021-12-11 14:50:29 +01:00
windows [ windows . size ( ) - 1 ] . setUnderFullscreen ( false ) ;
2021-12-21 19:30:54 +01:00
windows [ windows . size ( ) - 1 ] . setDirty ( true ) ;
windows [ windows . size ( ) - 1 ] . setLastUpdatePosition ( Vector2D ( 0 , 0 ) ) ;
windows [ windows . size ( ) - 1 ] . setLastUpdateSize ( Vector2D ( 0 , 0 ) ) ;
2021-12-11 14:50:29 +01:00
2021-12-11 12:54:45 +01:00
return ;
}
}
}
bool CWindowManager : : isWindowUnmapped ( int64_t id ) {
for ( auto & w : unmappedWindows ) {
if ( w . getDrawable ( ) = = id ) {
return true ;
}
}
return false ;
2021-12-11 14:50:29 +01:00
}
void CWindowManager : : setAllWorkspaceWindowsAboveFullscreen ( const int & workspace ) {
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = workspace & & w . getIsFloating ( ) ) {
w . setUnderFullscreen ( false ) ;
}
}
}
void CWindowManager : : setAllWorkspaceWindowsUnderFullscreen ( const int & workspace ) {
for ( auto & w : windows ) {
if ( w . getWorkspaceID ( ) = = workspace & & w . getIsFloating ( ) ) {
w . setUnderFullscreen ( true ) ;
}
}
2021-12-17 19:57:07 +01:00
}
void CWindowManager : : toggleWindowFullscrenn ( const int & window ) {
const auto PWINDOW = getWindowFromDrawable ( window ) ;
if ( ! PWINDOW )
return ;
const auto MONITOR = getMonitorFromWindow ( PWINDOW ) ;
setAllWorkspaceWindowsDirtyByID ( activeWorkspaces [ MONITOR - > ID ] ) ;
PWINDOW - > setFullscreen ( ! PWINDOW - > getFullscreen ( ) ) ;
getWorkspaceByID ( PWINDOW - > getWorkspaceID ( ) ) - > setHasFullscreenWindow ( PWINDOW - > getFullscreen ( ) ) ;
// Fix windows over and below fullscreen.
if ( PWINDOW - > getFullscreen ( ) )
setAllWorkspaceWindowsUnderFullscreen ( activeWorkspaces [ MONITOR - > ID ] ) ;
else
setAllWorkspaceWindowsAboveFullscreen ( activeWorkspaces [ MONITOR - > ID ] ) ;
// EWMH
Values [ 0 ] = HYPRATOMS [ " _NET_WM_STATE_FULLSCREEN " ] ;
if ( PWINDOW - > getFullscreen ( ) )
xcb_change_property ( DisplayConnection , XCB_PROP_MODE_APPEND , window , HYPRATOMS [ " _NET_WM_STATE " ] , XCB_ATOM_ATOM , 32 , 1 , Values ) ;
else
removeAtom ( window , HYPRATOMS [ " _NET_WM_STATE " ] , HYPRATOMS [ " _NET_WM_STATE_FULLSCREEN " ] ) ;
2021-12-21 10:46:22 +01:00
EWMH : : updateWindow ( window ) ;
2021-12-17 19:57:07 +01:00
Debug : : log ( LOG , " Set fullscreen to " + std : : to_string ( PWINDOW - > getFullscreen ( ) ) + " for " + std : : to_string ( window ) ) ;
}
void CWindowManager : : handleClientMessage ( xcb_client_message_event_t * E ) {
const auto PWINDOW = getWindowFromDrawable ( E - > window ) ;
if ( ! PWINDOW )
return ;
if ( E - > type = = HYPRATOMS [ " _NET_WM_STATE " ] ) {
// The window wants to change its' state.
// For now we only support FULLSCREEN
if ( E - > data . data32 [ 1 ] = = HYPRATOMS [ " _NET_WM_STATE_FULLSCREEN " ] ) {
2021-12-17 21:03:53 +01:00
if ( ( PWINDOW - > getFullscreen ( ) & & ( E - > data . data32 [ 0 ] = = 0 | | E - > data . data32 [ 0 ] = = 2 ) )
| | ( ! PWINDOW - > getFullscreen ( ) & & ( E - > data . data32 [ 0 ] = = 1 | | E - > data . data32 [ 0 ] = = 2 ) ) ) {
// Toggle fullscreen
toggleWindowFullscrenn ( PWINDOW - > getDrawable ( ) ) ;
}
2021-12-17 19:57:07 +01:00
Debug : : log ( LOG , " Message recieved to toggle fullscreen for " + std : : to_string ( PWINDOW - > getDrawable ( ) ) ) ;
}
} else if ( E - > type = = HYPRATOMS [ " _NET_ACTIVE_WINDOW " ] ) {
// Change the focused window
if ( E - > format ! = 32 )
return ;
setFocusedWindow ( PWINDOW - > getDrawable ( ) ) ;
Debug : : log ( LOG , " Message recieved to set active for " + std : : to_string ( PWINDOW - > getDrawable ( ) ) ) ;
}
2021-12-17 20:58:32 +01:00
}
void CWindowManager : : recalcAllDocks ( ) {
for ( auto & mon : monitors ) {
mon . vecReservedTopLeft = { 0 , 0 } ;
mon . vecReservedBottomRight = { 0 , 0 } ;
setAllWorkspaceWindowsDirtyByID ( activeWorkspaces [ mon . ID ] ) ;
}
for ( auto & w : windows ) {
if ( ! w . getDock ( ) | | w . getDead ( ) | | ! w . getIsFloating ( ) )
continue ;
const auto MONITOR = & monitors [ w . getMonitor ( ) ] ;
const auto VERTICAL = w . getSize ( ) . x / w . getSize ( ) . y < 1 ;
if ( VERTICAL ) {
if ( w . getPosition ( ) . x < MONITOR - > vecSize . x / 2.f + MONITOR - > vecPosition . x ) {
// Left
MONITOR - > vecReservedTopLeft = Vector2D ( w . getSize ( ) . x , 0 ) ;
} else {
// Right
MONITOR - > vecReservedBottomRight = Vector2D ( w . getSize ( ) . x , 0 ) ;
}
} else {
if ( w . getPosition ( ) . y < MONITOR - > vecSize . y / 2.f + MONITOR - > vecPosition . y ) {
// Top
MONITOR - > vecReservedTopLeft = Vector2D ( 0 , w . getSize ( ) . y ) ;
} else {
// Bottom
MONITOR - > vecReservedBottomRight = Vector2D ( 0 , w . getSize ( ) . y ) ;
}
}
2021-12-19 12:33:36 +01:00
// Move it
Values [ 0 ] = w . getDefaultPosition ( ) . x ;
Values [ 1 ] = w . getDefaultPosition ( ) . y ;
xcb_configure_window ( DisplayConnection , w . getDrawable ( ) , XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y , Values ) ;
Values [ 0 ] = w . getDefaultSize ( ) . x ;
Values [ 1 ] = w . getDefaultSize ( ) . y ;
xcb_configure_window ( DisplayConnection , w . getDrawable ( ) , XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT , Values ) ;
2021-12-17 20:58:32 +01:00
}
2021-11-23 17:43:27 +01:00
}