Source

Mirror / src / main.cpp

#include <iostream>

#include <functional>
#include <string>
#include <future>

#include <xcb/xcb.h>
#include <xcb/xcb_keysyms.h>
#include <X11/keysym.h>

#include "event.h"
#include "setup.h"
#include "monitor.h"
#include "eventHandlers.h"
#include "keyHandlers.h"
#include "statusBar.h"
#include "config.h"


int main()
{
    try
    {
        Config config;
        Setup setup(config.tags, config.rules);
        EventDispatcher eventDispatch(setup.conn);
        EventHandler handler(&setup);
        KeyHandler keyHandler(&setup);
        KeyCallback commandCallback;
        KeyCallback interactCallback;
        eventDispatch.setHandler("ConfigureRequest", 
            std::bind(&EventHandler::handleConfigureRequest, &handler, std::placeholders::_1));

        eventDispatch.setHandler("MapRequest", 
            std::bind(&EventHandler::handleMapRequest, &handler, std::placeholders::_1));

        eventDispatch.setHandler("DestroyNotify", 
            std::bind(&EventHandler::handleDestroyNotify, &handler, std::placeholders::_1));

        eventDispatch.setHandler("UnmapNotify", 
            std::bind(&EventHandler::handleUnmapNotify, &handler, std::placeholders::_1));

        eventDispatch.setHandler("EnterNotify", 
            std::bind(&EventHandler::handleEnterNotify, &handler, std::placeholders::_1));

        eventDispatch.setHandler("error", 
            std::bind(&EventHandler::handleError, &handler, std::placeholders::_1));

        eventDispatch.setHandler("MappingNotify", 
            std::bind(&KeyHandler::handleMappingNotify, &keyHandler, std::placeholders::_1));

        eventDispatch.setHandler("KeyPress", 
            std::bind(&KeyHandler::handleKeyPress, &keyHandler, std::placeholders::_1));

        eventDispatch.setHandler("KeyRelease", 
            std::bind(&KeyHandler::handleKeyRelease, &keyHandler, std::placeholders::_1));

        eventDispatch.setHandler("Expose", [&](EventPtr event){ 
            for (auto& monitor : setup.monitors)
            {
                monitor.statusBar->draw();
            }
             });
        
        eventDispatch.addLoopCallback([&]{
            for (auto& monitor : setup.monitors)
            {
                monitor.statusBar->update();
            }
                });

        
        
        //These functions setup the command and interact modes, respectively.

        commandCallback = [&]{
            //set the status bar text
            for (auto& monitor: setup.monitors)
                monitor.statusBar->setMode(""); 
            //ungrab the command transition keybind
            keyHandler.ungrabKey(config.commandMods, config.commandKey, Press);

            //interact keybind
            keyHandler.grabKey(config.interactMods, config.interactKey, Press, interactCallback);

            //Close focused window keybind
            keyHandler.grabKey(config.closeFocusedMods, config.closeFocusedKey, Press, [&]{
                Monitor& monitor = setup.getCurrentMonitor();
                monitor.tagList.at(monitor.currentTag).windowContainer.killFocused();
            });

            //Make focused window fullscreen
            keyHandler.grabKey(config.fullscreenFocusedMods, config.fullscreenFocusedKey, Press, [&]{
                Monitor &monitor = setup.getCurrentMonitor();
                monitor.tagList.at(monitor.currentTag).windowContainer.toggleFullscreenFocused();
                monitor.tagList.at(monitor.currentTag).windowContainer.layoutWindows(monitor.area);
                    });
            //Tag keybinds
            keyHandler.grabKey(config.tagSwitchMods, config.nextTagKey, Press, [&] {setup.getCurrentMonitor().nextTag();});
            keyHandler.grabKey(config.tagSwitchMods, config.prevTagKey, Press, [&]{setup.getCurrentMonitor().prevTag();});

            //quit keybind
            keyHandler.grabKey(config.quitMods, config.quitKey, Press, [&]{eventDispatch.stop();});
            
            //App keybinds
            for (auto &keybind : config.appKeyBinds)
            {
                keyHandler.grabKey(std::get<0>(keybind), std::get<1>(keybind), Press, [&]{
                    interactCallback();
                    setup.launchApp(std::get<2>(keybind));});
            }
            
            //block the applications from receiving keyboard input
            xcb_grab_keyboard(setup.conn, true, setup.root, XCB_CURRENT_TIME,
                                XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
            //xcb_grab_pointer()
        };

        interactCallback = [&]{
            for (auto& monitor: setup.monitors)
                monitor.statusBar->setMode("Interact"); 
            //Ungrab all command keybinds
            keyHandler.ungrabKey(config.interactMods, config.interactKey, Press);
            keyHandler.ungrabKey(config.quitMods, config.quitKey, Press);
            keyHandler.ungrabKey(config.closeFocusedMods, config.closeFocusedKey, Press);
            keyHandler.ungrabKey(config.fullscreenFocusedMods, config.fullscreenFocusedKey, Press);
            keyHandler.ungrabKey(config.tagSwitchMods, config.nextTagKey, Press);
            keyHandler.ungrabKey(config.tagSwitchMods, config.prevTagKey, Press);

            for (auto &keybind : config.appKeyBinds)
            {
                keyHandler.ungrabKey(std::get<0>(keybind), std::get<1>(keybind), Press);
            }
            
            //grab the command transition keybind
            keyHandler.grabKey(config.commandMods, config.commandKey, Press, commandCallback);

            //Allow keyboard input to the applications
            xcb_ungrab_keyboard(setup.conn, XCB_CURRENT_TIME);
        };

        for (auto &keybind : config.globalKeyBinds)
        {
           keyHandler.grabKey(std::get<0>(keybind), std::get<1>(keybind), Press,
           [&]{ setup.launchApp(std::get<2>(keybind)); }); 
        }

        commandCallback();
        eventDispatch.eventLoop();
        xcb_ungrab_keyboard(setup.conn, XCB_CURRENT_TIME);
    }
    catch (SetupError &ex)
    {
        std::cerr << "Mirror has encountered an error:" << ex.what()  << std::endl;
        return 0;
    }
   return 0;

}