Source

Mirror / src / setup.cpp

Full commit
#include "setup.h"
#include "monitor.h"
#include "statusBar.h"
#include "window.h"

Setup::Setup()
{
    conn = xcb_connect(nullptr, nullptr);
    screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
    root = screen->root;

    ewmh = ewmhInit(conn);
    
    uint32_t event_mask[] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
                                XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
                                XCB_EVENT_MASK_PROPERTY_CHANGE};
    xcb_void_cookie_t checkCookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, event_mask);
    if (xcb_request_check(conn, checkCookie))
	{
        throw OtherWindowManager();                                                                                       
    }
	std::cout << "numberOfTags is: " << numberOfTags << std::endl;
    getMonitors();

    for (auto& monitor : monitors)
    {
        statusBars.push_back(StatusBar(this, monitor));
    }

}

Setup::~Setup()
{
    xcb_disconnect(conn);
}

void Setup::getMonitors()
{
    if (!getXrandrMonitors())
    {
		int uid = 1;
        xcb_rectangle_t screenArea;
        screenArea.x = 0;
        screenArea.y = statusBarHeight;
        screenArea.width = screen->width_in_pixels;
        screenArea.height = screen->height_in_pixels - statusBarHeight+1;
        Monitor newMonitor(screenArea);				
		while (uid <= numberOfTags)
		{
			newMonitor.tagList.push_back(Tag("default"+std::to_string(uid)));
			uid++;
		}
        monitors.push_back(newMonitor);

    }
}

bool Setup::getXrandrMonitors()
{
    if (xcb_get_extension_data(conn, &xcb_randr_id)->present)
    {
        int uid = 1;
        auto *versionReply = xcb_randr_query_version_reply(conn, xcb_randr_query_version(conn, 1, 1), 0);

        if (versionReply)
        {
            free(versionReply);

            auto screenResCookie = xcb_randr_get_screen_resources(conn, root);
            auto *screenResReply = xcb_randr_get_screen_resources_reply(conn, screenResCookie, nullptr);
            if (screenResReply->num_crtcs <= 1)                
            {
                    free(screenResReply);                            
                    return false;                                                
            }
                
            xcb_randr_crtc_t *randrCRTCs = xcb_randr_get_screen_resources_crtcs(screenResReply);
            for (int i = 0; i < screenResReply->num_crtcs; i++)
            {
                auto crtcInfoCookie = xcb_randr_get_crtc_info(conn, randrCRTCs[i], XCB_CURRENT_TIME);
                auto *crtcInfoReply = xcb_randr_get_crtc_info_reply(conn, crtcInfoCookie, nullptr);
                if(!xcb_randr_get_crtc_info_outputs_length(crtcInfoReply))
                    continue;

                xcb_rectangle_t screenArea;
                screenArea.x = crtcInfoReply->x;
                screenArea.y = crtcInfoReply->y+statusBarHeight;
                screenArea.width = crtcInfoReply->width;
                screenArea.height = crtcInfoReply->height-statusBarHeight;
                Monitor newMonitor(screenArea);
				while (uid <= numberOfTags)
				{
					std::cout << "uid is: " << uid << std::endl;
					newMonitor.tagList.push_back(Tag("default"+std::to_string(uid)));
					uid++;
				}
				uid = 1;
				std::cout << "newMonitor's tagList size is: " << newMonitor.tagList.size() << std::endl;
                monitors.push_back(newMonitor);
                free(crtcInfoReply);
            }

            free(screenResReply);
            return true;
        }
    }
    return false;
}

Window& Setup::findWindow(xcb_window_t window)
{
    for(auto& monitor : monitors)
        for (auto& tag : monitor.tagList)
        {
            auto& win = tag.windowContainer.findWindow(window);
            if (win)
                return win;
        }
    return monitors.at(0).tagList.at(0).windowContainer.invalidWin;
}

void Setup::addWindow(xcb_window_t window)
{
    if(findWindow(window))
        return;
	
    auto& monitor = getCurrentMonitor();
	std::cout << "monitor's tagList has this size: " << monitor.tagList.size() << std::endl;
    Window win(this, window, monitor.tagList.at(monitor.currentTag).name);

    for (auto& tag : monitor.tagList)
        if (tag.name == win.tagName)
        {
            tag.windowContainer.addWindow(win);
            return;
        }
    monitor.tagList.at(monitor.currentTag).windowContainer.addWindow(win);
}

void Setup::addWindow(Window window)
{
    if (findWindow(window.id))
        return;
    auto monitor = getCurrentMonitor();
    for (auto& tag : monitor.tagList)
    {
        if (tag.name == window.tagName)
        {
            tag.windowContainer.addWindow(window);
            return;
        }
    }
}

void Setup::removeWindow(Window window)
{
    for (auto& monitor: monitors)
    {
        for (auto& tag : monitor.tagList)
        {
            if (tag.windowContainer.removeWindow(window))
                return;
        }
    }
}

void Setup::removeWindow(xcb_window_t window)
{
    for (auto& monitor: monitors)
        for (auto& tag : monitor.tagList)
        {
            auto &win = tag.windowContainer.findWindow(window);
            if (win)
            {
                tag.windowContainer.removeWindow(win);
                return;
            }
           
        }
}

void Setup::focusWindow(xcb_window_t window)
{
    int i=0;
    Monitor &monitor = getCurrentMonitor();
	for (auto& tag : monitor.tagList)
    {
        auto &win = tag.windowContainer.findWindow(window);
        if (win)
        {
            tag.windowContainer.focusWindow(win);
            monitor.currentTag = i;
            std::cerr << "focusWindow setting currentTag to: " << monitor.currentTag << std::endl;
            return;
        }
		i++;
    }
	std::cerr << "didn't find or focus a window" << std::endl;     
}


void Setup::layoutWindows()
{
    Monitor &monitor = getCurrentMonitor();
    monitor.tagList.at(monitor.currentTag).windowContainer.layoutWindows(monitor.area);
}

Monitor& Setup::getCurrentMonitor()
{
    int x = 0;
    int y = 0;
    auto* pointerReply = xcb_query_pointer_reply(conn, xcb_query_pointer_unchecked(conn, root), nullptr);
    if(pointerReply)
    {
        x = pointerReply->root_x;
        y = pointerReply->root_y; 
    }
    free(pointerReply);

    for (auto& monitor : monitors)
    {
        if (x >= monitor.area.x
            and x <= monitor.area.x + monitor.area.width)
        { 
            if (y >= monitor.area.y 
                and y <= monitor.area.y + monitor.area.height)
            {
                return monitor;
            }

        }
    }
    return monitors.at(0);
}

void Setup::nextTag()
{
    std::cerr << "nextTag"<< std::endl;
	Monitor &monitor = getCurrentMonitor();
    xcb_rectangle_t rect = monitor.area;
    rect.x = 0 - rect.width;
    rect.y = 0 - rect.height;
    monitor.tagList.at(monitor.currentTag).windowContainer.layoutWindows(rect);
	monitor.currentTag++;

	if (monitor.currentTag > monitor.tagList.size()-1)
		monitor.currentTag = 0;

	std::cerr << "currentTag is: " << monitor.currentTag << std::endl;
	//monitor.tagList.at(monitor.currentTag).windowContainer.raiseAll();
    monitor.tagList.at(monitor.currentTag).windowContainer.layoutWindows(monitor.area);
}

void Setup::prevTag()
{
    std::cerr << "prevTag" << std::endl;
	Monitor &monitor = getCurrentMonitor();
    xcb_rectangle_t rect = monitor.area;
    rect.x = 0 - rect.width;
    rect.y = 0 - rect.height;
    monitor.tagList.at(monitor.currentTag).windowContainer.layoutWindows(rect);
	monitor.currentTag--;
	if (monitor.currentTag < 0)
	{
		monitor.currentTag = monitor.tagList.size()-1;
	}

	std::cerr << "currentTag is: " << monitor.currentTag << std::endl;
	//monitor.tagList.at(monitor.currentTag).windowContainer.raiseAll();
    monitor.tagList.at(monitor.currentTag).windowContainer.layoutWindows(monitor.area);

}

void Setup::launchApp(std::string command)
{
	pid_t pid1;
	pid_t pid2;
	int status;

	if (pid1 = fork()) 
	{
		/* parent process A */
		waitpid(pid1, &status, 0);
												      
	} 
	else if (!pid1) 
	{
		setsid();
		/* child process B */
		if (pid2 = fork()) 
		{
			exit(0);
		} 
		else if (!pid2) 
		{
			/* child process C */
			int stdinFd = open("/dev/null", O_RDONLY);
			dup2(stdinFd, STDIN_FILENO);
			close(stdinFd);
			int stdoutFd = open("/dev/null", O_WRONLY);
			dup2(stdoutFd, STDOUT_FILENO);
			close(stdoutFd);
			int stderrFd = open("/dev/null", O_WRONLY | O_CREAT | O_APPEND);
			dup2(stderrFd, STDERR_FILENO);
            close(stderrFd);
			char *const argv [] = {nullptr};
			execvp(command.c_str(), argv);
																	              
		} 
		else 
		{
			/* error */
			std::cerr << "The second fork failed when trying to launch " << command << std::endl;
												             
		}
	        
	} 
	else 
	{
		/* error */								     
		std::cerr << "The first fork failed when trying to launch " << command << std::endl;
	}
}