From 5ccdee560c5e1209d57ab0fb770a34a293c30a46 Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Fri, 8 Sep 2023 16:50:02 -0400 Subject: [PATCH] An initial WIP --- .idea/.gitignore | 8 + .idea/.name | 1 + .idea/mir-i3.iml | 2 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + CMakeLists.txt | 8 +- src/TileNode.cpp | 173 ---------------- src/TileNode.hpp | 136 ------------- src/TilingWindowManager.cpp | 263 ------------------------- src/TilingWindowManager.hpp | 67 ------- src/display_listener.cpp | 12 ++ src/display_listener.h | 25 +++ src/main.cpp | 54 +---- src/mirie_window_management_policy.cpp | 54 +++++ src/mirie_window_management_policy.h | 37 ++++ src/tiled_node.cpp | 27 +++ src/tiled_node.h | 28 +++ src/tiling_region.cpp | 5 + src/tiling_region.h | 40 ++++ 20 files changed, 270 insertions(+), 688 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/mir-i3.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml delete mode 100644 src/TileNode.cpp delete mode 100644 src/TileNode.hpp delete mode 100644 src/TilingWindowManager.cpp delete mode 100644 src/TilingWindowManager.hpp create mode 100644 src/display_listener.cpp create mode 100644 src/display_listener.h create mode 100644 src/mirie_window_management_policy.cpp create mode 100644 src/mirie_window_management_policy.h create mode 100644 src/tiled_node.cpp create mode 100644 src/tiled_node.h create mode 100644 src/tiling_region.cpp create mode 100644 src/tiling_region.h diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..c4f1134 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +MirCompositor \ No newline at end of file diff --git a/.idea/mir-i3.iml b/.idea/mir-i3.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/mir-i3.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..79b3c94 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..f847681 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 78fd37b..3f39ede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,13 @@ find_package(PkgConfig) pkg_check_modules(MIRAL miral REQUIRED) find_package(OpenGL REQUIRED) -add_executable(compositor src/main.cpp src/TilingWindowManager.cpp src/TileNode.cpp) +add_executable(compositor + src/display_listener.cpp + src/main.cpp + src/mirie_window_management_policy.cpp + src/tiling_region.cpp + src/tiled_node.cpp + ) target_include_directories(compositor PUBLIC SYSTEM ${MIRAL_INCLUDE_DIRS}) target_link_libraries( compositor ${MIRAL_LDFLAGS}) \ No newline at end of file diff --git a/src/TileNode.cpp b/src/TileNode.cpp deleted file mode 100644 index 3ba96aa..0000000 --- a/src/TileNode.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "TileNode.hpp" -#include "mir/geometry/forward.h" -#include "miral/window.h" -#include "miral/zone.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -TileNode::TileNode(mir::geometry::Rectangle rectangle, PlacementStrategy strategy): - std::enable_shared_from_this(), - mZone(rectangle) -{ - mPlacementStrategy = strategy; -} - -TileNode::~TileNode() { - std::cout << "Decounstructing " << getZoneId() << std::endl; -} - -miral::Zone TileNode::getZone() { - return mZone; -} - -int TileNode::getZoneId() { - return mZone.id(); -} - -std::vector> TileNode::getChildNodeList() { - return mChildNodes; -} - -std::shared_ptr TileNode::addWindow(std::shared_ptr window) { - // We don't have a root window - if (!mWindow.get() && mChildNodes.size() == 0) { - std::cout << "Adding window as root window in the group" << std::endl; - mWindow = window; - return shared_from_this(); - } - - if (mChildNodes.size() > 0 && mWindow.get()) { - throw new std::exception(); - } - - auto controllingTileNode = getControllingTileNode(); - - // If we are controlling ourselves AND we are just a single window, we need to go "amoeba-mode" and create - // a new tile from the parent tile. - if (controllingTileNode == shared_from_this() && mWindow) { - std::cout << "Creating a new window group from the previous window." << std::endl; - auto firstNewTileNode = controllingTileNode->makeTileNode(mWindow, PlacementStrategy::Parent); - firstNewTileNode->mParent = shared_from_this(); - controllingTileNode->mChildNodes.push_back(firstNewTileNode); - mWindow.reset(); - } - - // Add the new window. - std::cout << "Creating a new window group from the new window." << std::endl; - auto secondNewTileNode = controllingTileNode->makeTileNode(window, PlacementStrategy::Parent); - secondNewTileNode->mParent = controllingTileNode; - controllingTileNode->mChildNodes.push_back(secondNewTileNode); - return secondNewTileNode; -} - -size_t TileNode::getNumberOfTiles() { - if (mWindow.get()) { - return 1; - } - - return mChildNodes.size(); -} - -bool TileNode::removeWindow(std::shared_ptr window) { - if (mWindow == window) { - // If this group represents the window, remove it. - mWindow.reset(); - - // Remove the child from the parent and take its children. - if (mParent.get()) { - std::vector>::iterator it = std::find( - mParent->mChildNodes.begin(), mParent->mChildNodes.end(), shared_from_this()); - if (it != mParent->mChildNodes.end()) { - for (auto adoptedTileNodes : mChildNodes) { - mParent->mChildNodes.push_back(adoptedTileNodes); - } - std::cout << "Erasing window group from the parent. Size = " << mParent->mChildNodes.size() << std::endl; - mParent->mChildNodes.erase(it); - } - } - return true; - } - else { - // Otherwise, search the other groups to remove it. - for (auto group: mChildNodes) { - if (group->removeWindow(window)) { - return true; - } - } - return false; - } -} - -std::shared_ptr TileNode::makeTileNode(std::shared_ptr window, PlacementStrategy placementStrategy) { - // Capture the size of the window to make it the size of the new group. - auto nextGroupPosition = window->top_left(); - auto nextGroupSize = window->size(); - auto zoneSize = mir::geometry::Rectangle(nextGroupPosition, nextGroupSize); - auto tileNode = std::make_shared(zoneSize, placementStrategy); - tileNode->mWindow = window; - return tileNode; -} - -PlacementStrategy TileNode::getPlacementStrategy() { - return mPlacementStrategy; -} - -void TileNode::setPlacementStrategy(PlacementStrategy strategy) { - mPlacementStrategy = strategy; -} - -std::shared_ptr TileNode::getControllingTileNode() { - if (mPlacementStrategy == PlacementStrategy::Parent) { - return mParent->getControllingTileNode(); - } - - return shared_from_this(); -} - -bool TileNode::isEmpty() { - return mParent.get() == nullptr && mWindow.get() == nullptr && mChildNodes.size() == 0; -} - -std::vector> TileNode::getWindowsInTile() { - std::vector> retval; - if (mWindow.get()) { - retval.push_back(mWindow); - } - - for (auto tileNode : mChildNodes) { - auto otherRetval = tileNode->getWindowsInTile(); - for (auto otherWindow : otherRetval) { - retval.push_back(otherWindow); - } - } - - return retval; -} - -std::shared_ptr TileNode::getParent() { - if (mParent.get()) return mParent; - else return shared_from_this(); -} - -std::shared_ptr TileNode::getTileNodeForWindow(std::shared_ptr window) { - if (mWindow == window) { - return shared_from_this(); - } - else { - // Otherwise, search the other groups to remove it. - for (auto group: mChildNodes) { - auto tileNode = group->getTileNodeForWindow(window); - if (tileNode) { - return tileNode; - } - } - return nullptr; - } -} \ No newline at end of file diff --git a/src/TileNode.hpp b/src/TileNode.hpp deleted file mode 100644 index 0b3600e..0000000 --- a/src/TileNode.hpp +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef WINDOW_GROUP_HPP -#define WINDOW_GROUP_HPP - -#include "mir/geometry/forward.h" -#include "miral/window.h" -#include "miral/window_info.h" -#include "miral/window_specification.h" -#include "miral/zone.h" -#include -#include -#include - -/** Defines how new windows will be placed in the TileNode. */ -enum class PlacementStrategy { - /** If horizontal, we will place the new window to the right of the selectd window. */ - Horizontal, - /** If vertical, we will place the new window below the selected window. */ - Vertical, - /** If parent, we will defer the placement strategy of this window to the parent's placement strategy. */ - Parent -}; - -/** - Each TileNode represents a Tilelable object on the desktop. - The TileNodes create a Tree data structure that represents the - control of placement on the desktop grid. - - The smallest node is comprised of a single window. - A large TileNode is made up of many TileNodes. -*/ -class TileNode : public std::enable_shared_from_this { -public: - TileNode(mir::geometry::Rectangle, PlacementStrategy strategy); - ~TileNode(); - - /** - Retrieve the zone defined by this TileNode. - */ - miral::Zone getZone(); - - /** - Retrieve the unique identifier for this zone. - - @returns Zone if - */ - int getZoneId(); - - /** - Retrieve the child nodes of this group. - - @returns A list of child nodes contained within this TileNode. - */ - std::vector> getChildNodeList(); - - /** - Adds a window to the TileNode. - - @returns a pointer to the TileNode that the window now exists in. - */ - std::shared_ptr addWindow(std::shared_ptr); - - /** - Removes a window from the ToleNode. - - @returns True if the window was removed, otherwise false. - */ - bool removeWindow(std::shared_ptr); - - /** - Collects all of the windows in the TileNode, including those in child nodes. - - @returns A list of windows underneath this tile node. - */ - std::vector> getWindowsInTile(); - - /** - Gets the number of tiles under the control of this node EXCLUDING child nodes. - - @returns The immediate number of tiles under the control of this TileNode. - */ - size_t getNumberOfTiles(); - - /** - Retrieves the placement strategy of this node. - - @returns The placement strategy - */ - PlacementStrategy getPlacementStrategy(); - - /** - Sets the placement strategy of this node. - */ - void setPlacementStrategy(PlacementStrategy); - - /** - Returns the TileNode who is in charge of organizing this TileNode. - This COULD be itself. - - @returns The TileNode that controls this TileNode. - */ - std::shared_ptr getControllingTileNode(); - - /** - Returns true if the TileNode is the parent AND nothing has been added to it. - - @returns True if it is empty, otherwise false. - */ - bool isEmpty(); - - /** - Retrieves the parent of this child node. Expected to be nullptr for the root. - - @returns The parent node - */ - std::shared_ptr getParent(); - - /** - Given a window, searches recursively for the TileNode that holds it. Returns nullptr - if none is found. - - @returns The TileNode to which the window belongs. - */ - std::shared_ptr getTileNodeForWindow(std::shared_ptr); - -private: - miral::Zone mZone; - - std::shared_ptr mWindow; - std::shared_ptr mParent; - std::vector> mChildNodes; - PlacementStrategy mPlacementStrategy; - - std::shared_ptr makeTileNode(std::shared_ptr, PlacementStrategy strategy); -}; - -#endif \ No newline at end of file diff --git a/src/TilingWindowManager.cpp b/src/TilingWindowManager.cpp deleted file mode 100644 index dfa8349..0000000 --- a/src/TilingWindowManager.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright © Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 or 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "TilingWindowManager.hpp" -#include "mir/geometry/forward.h" -#include "mir/logging/logger.h" -#include "mir_toolkit/events/enums.h" -#include "miral/application.h" -#include "miral/minimal_window_manager.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace miral; -using namespace miral::toolkit; - -TilingWindowManagerPolicy::TilingWindowManagerPolicy( - WindowManagerTools const& inTools, - miral::InternalClientLauncher const& launcher, - std::function& shutdown_hook) : - miral::MinimalWindowManager(inTools), - mRootTileNode() -{ - mDefaultStrategy = PlacementStrategy::Horizontal; - shutdown_hook = [this] { }; - mActiveTileNode = nullptr; -} - -TilingWindowManagerPolicy::~TilingWindowManagerPolicy() = default; - -bool TilingWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event) { - if (MinimalWindowManager::handle_keyboard_event(event)) { - return true; - } - - auto const action = mir_keyboard_event_action(event); - auto const scan_code = mir_keyboard_event_scan_code(event); - auto const modifiers = mir_keyboard_event_modifiers(event) & pModifierMask; - - if (action == MirKeyboardAction::mir_keyboard_action_down && (modifiers && mir_input_event_modifier_meta)) { - if (scan_code == KEY_V) { - requestPlacementStrategyChange(PlacementStrategy::Vertical); - return true; - } - else if (scan_code == KEY_H) { - requestPlacementStrategyChange(PlacementStrategy::Horizontal); - return true; - } - else if (scan_code == KEY_LEFT) { - requestChangeActiveWindow(-1); - return true; - } - else if (scan_code == KEY_RIGHT) { - requestChangeActiveWindow(1); - return true; - } - else if ((modifiers && mir_input_event_modifier_shift) && scan_code == KEY_Q) { - requestQuitSelectedApplication(); - return true; - } - } - - return false; -} - -void TilingWindowManagerPolicy::requestPlacementStrategyChange(PlacementStrategy strategy) { - auto activeWindow = tools.active_window(); - - if (!activeWindow) { - // Nothing is selected which means nothing is added to the screen. - mDefaultStrategy = strategy; - return; - } - - mActiveTileNode->setPlacementStrategy(strategy); -} - -void TilingWindowManagerPolicy::requestQuitSelectedApplication() { - if (!mActiveWindow.get()) { - std::cout << "There is no current application to quit." << std::endl; - return; - } - - // Kill the application and remove it from the grid. - auto application = mActiveWindow->application(); - mRootTileNode->removeWindow(mActiveWindow); - miral::kill(application, SIGTERM); - - // Remove the window from our list of applications. - auto it = std::find(mWindowsOnDesktop.begin(), mWindowsOnDesktop.end(), mActiveWindow); - int index = it - mWindowsOnDesktop.begin(); - if (it != mWindowsOnDesktop.end()) { - mWindowsOnDesktop.erase(it); - } - - // TODO: If I had more time, I would resize the grid when a quit occurs. - if (index >= mWindowsOnDesktop.size()) { - index = mWindowsOnDesktop.size() - 1; - } - - // Select the next available window. - if (index >= 0) { - mActiveWindow = mWindowsOnDesktop[index]; - mActiveTileNode = mRootTileNode->getTileNodeForWindow(mActiveWindow); - } - else { - mActiveTileNode = mRootTileNode; - mActiveWindow.reset(); - } - - std::cout << "Quit the current application." << std::endl; -} - -bool TilingWindowManagerPolicy::requestChangeActiveWindow(int moveAmount) { - auto it = std::find(mWindowsOnDesktop.begin(), mWindowsOnDesktop.end(), mActiveWindow); - if (it == mWindowsOnDesktop.end()) { - std::cerr << "Unable to find current window on the desktop." << std::endl; - return false; - } - - int index = it - mWindowsOnDesktop.begin(); - int newIndex = index + moveAmount; - while (newIndex < 0) { - newIndex += mWindowsOnDesktop.size(); - } - while (newIndex >= mWindowsOnDesktop.size()) { - newIndex -= mWindowsOnDesktop.size(); - } - - mActiveWindow = mWindowsOnDesktop[newIndex]; - mActiveTileNode = mRootTileNode->getTileNodeForWindow(mActiveWindow); - tools.select_active_window(*mActiveWindow.get()); - return true; -} - -WindowSpecification TilingWindowManagerPolicy::place_new_window( - ApplicationInfo const& app_info, WindowSpecification const& request_parameters) -{ - auto parameters = MinimalWindowManager::place_new_window(app_info, request_parameters); - - // If it is our first time adding an item to the view, we initialize the root window group. - if (!mRootTileNode.get()) { - mRootTileNode = std::make_shared(tools.active_application_zone().extents(), mDefaultStrategy); - mActiveTileNode = mRootTileNode; - } - - auto groupInCharge = mActiveTileNode->getControllingTileNode(); - auto targetNumberOfWindows = groupInCharge->getNumberOfTiles() + 1; - auto activeZone = groupInCharge->getZone(); - auto placementStrategy = groupInCharge->getPlacementStrategy(); - - std::cout << "Placing new window into group. Group ID: " << activeZone.id() << ". Target Number of Windows: " << targetNumberOfWindows << std::endl; - if (targetNumberOfWindows == 1) { - - // There are no windows in the current zone so we can place it to take up the whole zone. - parameters.top_left() = activeZone.extents().top_left; - parameters.size() = Size{ activeZone.extents().size }; - } - else if (placementStrategy == PlacementStrategy::Horizontal) { - auto zoneFractionSize = Size{ activeZone.extents().size.width / targetNumberOfWindows, activeZone.extents().size.height }; - const int y = activeZone.extents().top_left.y.as_value(); - - for (unsigned short i = 0; auto window : groupInCharge->getWindowsInTile()) { - window->resize(zoneFractionSize); - - const int x = zoneFractionSize.width.as_int() * i + activeZone.extents().top_left.x.as_value(); - window->move_to(Point{ x, y }); - i++; - } - - const int x = zoneFractionSize.width.as_int() * groupInCharge->getNumberOfTiles() + activeZone.extents().top_left.x.as_value(); - parameters.top_left() = Point{ x, y }; - parameters.size() = zoneFractionSize; - } - else if (placementStrategy == PlacementStrategy::Vertical) { - auto zoneFractionSize = Size{ activeZone.extents().size.width, activeZone.extents().size.height / targetNumberOfWindows }; - const int x = activeZone.extents().top_left.x.as_value(); - for (unsigned short i = 0; auto window : groupInCharge->getWindowsInTile()) { - window->resize(zoneFractionSize); - - const int y = zoneFractionSize.height.as_int() * i + activeZone.extents().top_left.y.as_value(); - window->move_to(Point{ x, y }); - i++; - } - - const int y = zoneFractionSize.height.as_int() * groupInCharge->getNumberOfTiles() + activeZone.extents().top_left.y.as_value(); - parameters.top_left() = Point{ x, y }; - parameters.size() = zoneFractionSize; - } - - std::cout << "Placement of window complete." << std::endl; - - return parameters; -} - -bool TilingWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event) { - return true; -} - -bool TilingWindowManagerPolicy::handle_touch_event(MirTouchEvent const* event) { - return true; -} - -void TilingWindowManagerPolicy::advise_new_window(WindowInfo const& window_info) { - std::cout << "Adding window into the TileNode" << std::endl; - - // Add the window into the current tile. - auto window = std::make_shared(window_info.window()); - mActiveTileNode = mActiveTileNode->addWindow(window); - mActiveWindow = window; - - // Do the regular placing and sizing. - WindowSpecification modifications; - tools.place_and_size_for_state(modifications, window_info); - tools.modify_window(window_info.window(), modifications); - std::cout << "New window group has ID: " << mActiveTileNode->getZoneId() << ". New zone is now active." << std::endl; - if (mActiveTileNode->getParent().get()) { - std::cout << "Parent window group has ID: " << mActiveTileNode->getParent()->getZoneId() << std::endl; - } - - mWindowsOnDesktop.push_back(window); -} - -void TilingWindowManagerPolicy::handle_window_ready(WindowInfo& window_info) { - MinimalWindowManager::handle_window_ready(window_info); - return; -} - -void TilingWindowManagerPolicy::advise_focus_gained(WindowInfo const& info) { - MinimalWindowManager::advise_focus_gained(info); - return; -} - -void TilingWindowManagerPolicy::handle_modify_window(WindowInfo& window_info, WindowSpecification const& modifications) { - MinimalWindowManager::handle_modify_window(window_info, modifications); - return; -} diff --git a/src/TilingWindowManager.hpp b/src/TilingWindowManager.hpp deleted file mode 100644 index 4030886..0000000 --- a/src/TilingWindowManager.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef TILING_WINDOW_MANAGER_HPP -#define TILING_WINDOW_MANAGER_HPP - -#include "TileNode.hpp" -#include "miral/window_management_policy.h" -#include "miral/window_specification.h" -#include -#include -#include -#include -#include -#include - -namespace miral { - class InternalClientLauncher; -} - -/** -* An implementation of a tiling window manager, much like i3. -*/ -class TilingWindowManagerPolicy : public miral::MinimalWindowManager { -public: - TilingWindowManagerPolicy( - miral::WindowManagerTools const&, - miral::InternalClientLauncher const&, - std::function&); - ~TilingWindowManagerPolicy(); - - /** - * Positions the new window in reference to the currently selected window and the current mode. - */ - virtual miral::WindowSpecification place_new_window( - miral::ApplicationInfo const&, miral::WindowSpecification const&) override; - - - bool handle_pointer_event(MirPointerEvent const*) override; - bool handle_touch_event(MirTouchEvent const*) override; - bool handle_keyboard_event(MirKeyboardEvent const*) override; - - /** Add the window to the active zone. */ - void advise_new_window(miral::WindowInfo const&) override; - void handle_window_ready(miral::WindowInfo&) override; - void advise_focus_gained(miral::WindowInfo const&) override; - - void handle_modify_window(miral::WindowInfo&, miral::WindowSpecification const&) override; - -protected: - static const int pModifierMask = - mir_input_event_modifier_alt | - mir_input_event_modifier_shift | - mir_input_event_modifier_sym | - mir_input_event_modifier_ctrl | - mir_input_event_modifier_meta; - -private: - std::shared_ptr mRootTileNode; - std::shared_ptr mActiveTileNode; - PlacementStrategy mDefaultStrategy; - std::vector> mWindowsOnDesktop; - std::shared_ptr mActiveWindow; - - void requestPlacementStrategyChange(PlacementStrategy); - void requestQuitSelectedApplication(); - bool requestChangeActiveWindow(int); -}; - -#endif //TILING_WINDOW_MANAGER_HPP diff --git a/src/display_listener.cpp b/src/display_listener.cpp new file mode 100644 index 0000000..ecb05d4 --- /dev/null +++ b/src/display_listener.cpp @@ -0,0 +1,12 @@ +// +// Created by mattkae on 9/8/23. +// + +#include "display_listener.h" + +using namespace mirie; + +void DisplayListener::operator()(mir::Server &server) const +{ + +} \ No newline at end of file diff --git a/src/display_listener.h b/src/display_listener.h new file mode 100644 index 0000000..9cfcd2e --- /dev/null +++ b/src/display_listener.h @@ -0,0 +1,25 @@ +// +// Created by mattkae on 9/8/23. +// + +#ifndef MIRCOMPOSITOR_DISPLAY_LISTENER_H +#define MIRCOMPOSITOR_DISPLAY_LISTENER_H + + +namespace mir +{ +class Server; +} + +namespace mirie +{ +class DisplayListener +{ +public: + DisplayListener() = default; + void operator()(mir::Server& server) const; +}; +} + + +#endif //MIRCOMPOSITOR_DISPLAY_LISTENER_H diff --git a/src/main.cpp b/src/main.cpp index 011c1c3..e882bce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,80 +1,38 @@ -#include -#include - -#include "TilingWindowManager.hpp" -#include #include #include #include #include -#include #include #include #include #include #include -#include -#include +#include "mirie_window_management_policy.h" using namespace miral; using namespace miral::toolkit; -int main(int argc, char const* argv[]) { +int main(int argc, char const* argv[]) +{ MirRunner runner{argc, argv}; std::function shutdown_hook{[]{}}; runner.add_stop_callback([&] { shutdown_hook(); }); InternalClientLauncher launcher; - ExternalClientLauncher external_client_launcher; WindowManagerOptions window_managers - { - add_window_manager_policy("tiling", launcher, shutdown_hook) - }; - - std::string terminal_cmd{"xfce4-terminal"}; - - auto const onEvent = [&](MirEvent const* event){ - if (mir_event_get_type(event) != mir_event_type_input) - return false; - - MirInputEvent const* input_event = mir_event_get_input_event(event); - if (mir_input_event_get_type(input_event) != mir_input_event_type_key) - return false; - - MirKeyboardEvent const* kev = mir_input_event_get_keyboard_event(input_event); - if (mir_keyboard_event_action(kev) != mir_keyboard_action_down) - return false; - - MirInputEventModifiers modifiers = mir_keyboard_event_modifiers(kev); - auto const keyEvent = mir_keyboard_event_keysym(kev); - if ((modifiers & mir_input_event_modifier_meta) && keyEvent == XKB_KEY_Return) { - external_client_launcher.launch({terminal_cmd}); - return true; - } - - if (!(modifiers & mir_input_event_modifier_alt) || !(modifiers & mir_input_event_modifier_ctrl)) - return false; - - switch (keyEvent) { - case XKB_KEY_BackSpace: - runner.stop(); - return true; - default: - return false; - }; + { + add_window_manager_policy("tiling", external_client_launcher) }; - + Keymap config_keymap; - return runner.run_with( { window_managers, WaylandExtensions{}, X11Support{}, - AppendEventFilter{onEvent}, config_keymap, external_client_launcher }); diff --git a/src/mirie_window_management_policy.cpp b/src/mirie_window_management_policy.cpp new file mode 100644 index 0000000..f7110c3 --- /dev/null +++ b/src/mirie_window_management_policy.cpp @@ -0,0 +1,54 @@ +// +// Created by mattkae on 9/8/23. +// +#define MIR_LOG_COMPONENT "mirie" + +#include "mirie_window_management_policy.h" +#include +#include +#include +#include + + +using namespace mirie; + +namespace +{ +const int MODIFIER_MASK = + mir_input_event_modifier_alt | + mir_input_event_modifier_shift | + mir_input_event_modifier_sym | + mir_input_event_modifier_ctrl | + mir_input_event_modifier_meta; + +const std::string TERMINAL = "xfce4-terminal"; +} + +MirieWindowManagementPolicy::MirieWindowManagementPolicy( + const miral::WindowManagerTools & tools, + miral::ExternalClientLauncher const& launcher) + : miral::MinimalWindowManager(tools), + window_manager_tools{tools}, + launcher{launcher} +{ +} + +bool MirieWindowManagementPolicy::handle_keyboard_event(MirKeyboardEvent const* event) +{ + if (MinimalWindowManager::handle_keyboard_event(event)) { + return true; + } + + auto const action = miral::toolkit::mir_keyboard_event_action(event); + auto const scan_code = miral::toolkit::mir_keyboard_event_scan_code(event); + auto const modifiers = miral::toolkit::mir_keyboard_event_modifiers(event) & MODIFIER_MASK; + + if (action == MirKeyboardAction::mir_keyboard_action_down && (modifiers && mir_input_event_modifier_alt)) { + if (scan_code == KEY_ENTER) { + launcher.launch({TERMINAL}); + return true; + } + } + + return false; +} \ No newline at end of file diff --git a/src/mirie_window_management_policy.h b/src/mirie_window_management_policy.h new file mode 100644 index 0000000..a2a065c --- /dev/null +++ b/src/mirie_window_management_policy.h @@ -0,0 +1,37 @@ +// +// Created by mattkae on 9/8/23. +// + +#ifndef MIRCOMPOSITOR_MIRIE_WINDOW_MANAGEMENT_POLICY_H +#define MIRCOMPOSITOR_MIRIE_WINDOW_MANAGEMENT_POLICY_H + +#include +#include +#include +#include + +namespace mirie +{ +class TilingRegion; +class DisplayListener; + +class MirieWindowManagementPolicy : public miral::MinimalWindowManager +{ +public: + MirieWindowManagementPolicy( + miral::WindowManagerTools const&, + miral::ExternalClientLauncher const&, + mirie::DisplayListener& display_listener); + ~MirieWindowManagementPolicy() = default; + + bool handle_keyboard_event(MirKeyboardEvent const* event) override; + +private: + miral::WindowManagerTools const window_manager_tools; + miral::ExternalClientLauncher const launcher; + std::shared_ptr root; + mirie::DisplayListener const display_listener; +}; +} + +#endif //MIRCOMPOSITOR_MIRIE_WINDOW_MANAGEMENT_POLICY_H diff --git a/src/tiled_node.cpp b/src/tiled_node.cpp new file mode 100644 index 0000000..115efb7 --- /dev/null +++ b/src/tiled_node.cpp @@ -0,0 +1,27 @@ +// +// Created by mattkae on 9/8/23. +// + +#include "tiled_node.h" + +using namespace mirie; + +TiledNode::TiledNode( + miral::Window const& window, + std::shared_ptr const& region): + window{window}, + region{region} +{ +} + +auto TiledNode::get_rectangle() -> mir::geometry::Rectangle +{ + return mir::geometry::Rectangle( + window.top_left(), + window.size()); +} + +void TiledNode::update_region(const std::shared_ptr& in_region) +{ + region = in_region; +} \ No newline at end of file diff --git a/src/tiled_node.h b/src/tiled_node.h new file mode 100644 index 0000000..c2c014c --- /dev/null +++ b/src/tiled_node.h @@ -0,0 +1,28 @@ +// +// Created by mattkae on 9/8/23. +// + +#ifndef MIRCOMPOSITOR_TILED_NODE_H +#define MIRCOMPOSITOR_TILED_NODE_H + +#include +#include + +namespace mirie +{ +class TilingRegion; + +class TiledNode +{ +public: + TiledNode(miral::Window const&, std::shared_ptr const&); + auto get_rectangle() -> mir::geometry::Rectangle; + void update_region(std::shared_ptr const&); +private: + miral::Window window; + std::shared_ptr region; +}; +} + + +#endif //MIRCOMPOSITOR_TILED_NODE_H diff --git a/src/tiling_region.cpp b/src/tiling_region.cpp new file mode 100644 index 0000000..ae318c5 --- /dev/null +++ b/src/tiling_region.cpp @@ -0,0 +1,5 @@ +// +// Created by mattkae on 9/8/23. +// + +#include "tiling_region.h" diff --git a/src/tiling_region.h b/src/tiling_region.h new file mode 100644 index 0000000..62a54b2 --- /dev/null +++ b/src/tiling_region.h @@ -0,0 +1,40 @@ +// +// Created by mattkae on 9/8/23. +// + +#ifndef MIRCOMPOSITOR_TILING_REGION_H +#define MIRCOMPOSITOR_TILING_REGION_H + +#include "tiled_node.h" + +#include +#include +#include +#include +#include + +namespace mirie +{ + +enum class TilingRegionDirection +{ + horizontal, + vertical, + length +}; + +class TilingRegion +{ +public: + explicit TilingRegion(mir::geometry::Rectangle const&); + void split(TilingRegionDirection direction); + +private: + mir::geometry::Rectangle rectangle; + std::vector windows; + std::vector> sub_regions; +}; +} + + +#endif //MIRCOMPOSITOR_TILING_REGION_H