mirror of
https://github.com/miracle-wm-org/miracle-wm.git
synced 2024-11-23 12:15:59 +03:00
An initial WIP
This commit is contained in:
parent
da7c5a3ca5
commit
5ccdee560c
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -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
|
1
.idea/.name
Normal file
1
.idea/.name
Normal file
@ -0,0 +1 @@
|
|||||||
|
MirCompositor
|
2
.idea/mir-i3.iml
Normal file
2
.idea/mir-i3.iml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
4
.idea/misc.xml
Normal file
4
.idea/misc.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/mir-i3.iml" filepath="$PROJECT_DIR$/.idea/mir-i3.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -15,7 +15,13 @@ find_package(PkgConfig)
|
|||||||
pkg_check_modules(MIRAL miral REQUIRED)
|
pkg_check_modules(MIRAL miral REQUIRED)
|
||||||
find_package(OpenGL 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_include_directories(compositor PUBLIC SYSTEM ${MIRAL_INCLUDE_DIRS})
|
||||||
target_link_libraries( compositor ${MIRAL_LDFLAGS})
|
target_link_libraries( compositor ${MIRAL_LDFLAGS})
|
173
src/TileNode.cpp
173
src/TileNode.cpp
@ -1,173 +0,0 @@
|
|||||||
#include "TileNode.hpp"
|
|
||||||
#include "mir/geometry/forward.h"
|
|
||||||
#include "miral/window.h"
|
|
||||||
#include "miral/zone.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <bits/ranges_algobase.h>
|
|
||||||
#include <bits/ranges_util.h>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <exception>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
TileNode::TileNode(mir::geometry::Rectangle rectangle, PlacementStrategy strategy):
|
|
||||||
std::enable_shared_from_this<TileNode>(),
|
|
||||||
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<std::shared_ptr<TileNode>> TileNode::getChildNodeList() {
|
|
||||||
return mChildNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TileNode> TileNode::addWindow(std::shared_ptr<miral::Window> 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<miral::Window> 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<std::shared_ptr<TileNode>>::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> TileNode::makeTileNode(std::shared_ptr<miral::Window> 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<TileNode>(zoneSize, placementStrategy);
|
|
||||||
tileNode->mWindow = window;
|
|
||||||
return tileNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlacementStrategy TileNode::getPlacementStrategy() {
|
|
||||||
return mPlacementStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileNode::setPlacementStrategy(PlacementStrategy strategy) {
|
|
||||||
mPlacementStrategy = strategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TileNode> 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<std::shared_ptr<miral::Window>> TileNode::getWindowsInTile() {
|
|
||||||
std::vector<std::shared_ptr<miral::Window>> 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> TileNode::getParent() {
|
|
||||||
if (mParent.get()) return mParent;
|
|
||||||
else return shared_from_this();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TileNode> TileNode::getTileNodeForWindow(std::shared_ptr<miral::Window> 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;
|
|
||||||
}
|
|
||||||
}
|
|
136
src/TileNode.hpp
136
src/TileNode.hpp
@ -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 <cstddef>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/** 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<TileNode> {
|
|
||||||
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<std::shared_ptr<TileNode>> getChildNodeList();
|
|
||||||
|
|
||||||
/**
|
|
||||||
Adds a window to the TileNode.
|
|
||||||
|
|
||||||
@returns a pointer to the TileNode that the window now exists in.
|
|
||||||
*/
|
|
||||||
std::shared_ptr<TileNode> addWindow(std::shared_ptr<miral::Window>);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Removes a window from the ToleNode.
|
|
||||||
|
|
||||||
@returns True if the window was removed, otherwise false.
|
|
||||||
*/
|
|
||||||
bool removeWindow(std::shared_ptr<miral::Window>);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Collects all of the windows in the TileNode, including those in child nodes.
|
|
||||||
|
|
||||||
@returns A list of windows underneath this tile node.
|
|
||||||
*/
|
|
||||||
std::vector<std::shared_ptr<miral::Window>> 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<TileNode> 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<TileNode> 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<TileNode> getTileNodeForWindow(std::shared_ptr<miral::Window>);
|
|
||||||
|
|
||||||
private:
|
|
||||||
miral::Zone mZone;
|
|
||||||
|
|
||||||
std::shared_ptr<miral::Window> mWindow;
|
|
||||||
std::shared_ptr<TileNode> mParent;
|
|
||||||
std::vector<std::shared_ptr<TileNode>> mChildNodes;
|
|
||||||
PlacementStrategy mPlacementStrategy;
|
|
||||||
|
|
||||||
std::shared_ptr<TileNode> makeTileNode(std::shared_ptr<miral::Window>, PlacementStrategy strategy);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 <linux/input-event-codes.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <miral/application_info.h>
|
|
||||||
#include <miral/internal_client.h>
|
|
||||||
#include <miral/toolkit_event.h>
|
|
||||||
#include <miral/window_info.h>
|
|
||||||
#include <miral/window_manager_tools.h>
|
|
||||||
#include <miral/zone.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
|
||||||
#include <csignal>
|
|
||||||
#include <ostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
using namespace miral;
|
|
||||||
using namespace miral::toolkit;
|
|
||||||
|
|
||||||
TilingWindowManagerPolicy::TilingWindowManagerPolicy(
|
|
||||||
WindowManagerTools const& inTools,
|
|
||||||
miral::InternalClientLauncher const& launcher,
|
|
||||||
std::function<void()>& 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<TileNode>(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>(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;
|
|
||||||
}
|
|
@ -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 <memory>
|
|
||||||
#include <miral/minimal_window_manager.h>
|
|
||||||
#include <mir_toolkit/events/enums.h>
|
|
||||||
#include <chrono>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
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<void()>&);
|
|
||||||
~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<TileNode> mRootTileNode;
|
|
||||||
std::shared_ptr<TileNode> mActiveTileNode;
|
|
||||||
PlacementStrategy mDefaultStrategy;
|
|
||||||
std::vector<std::shared_ptr<miral::Window>> mWindowsOnDesktop;
|
|
||||||
std::shared_ptr<miral::Window> mActiveWindow;
|
|
||||||
|
|
||||||
void requestPlacementStrategyChange(PlacementStrategy);
|
|
||||||
void requestQuitSelectedApplication();
|
|
||||||
bool requestChangeActiveWindow(int);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //TILING_WINDOW_MANAGER_HPP
|
|
12
src/display_listener.cpp
Normal file
12
src/display_listener.cpp
Normal file
@ -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
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
25
src/display_listener.h
Normal file
25
src/display_listener.h
Normal file
@ -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
|
54
src/main.cpp
54
src/main.cpp
@ -1,80 +1,38 @@
|
|||||||
#include <cstdlib>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include "TilingWindowManager.hpp"
|
|
||||||
#include <linux/input-event-codes.h>
|
|
||||||
#include <miral/set_window_management_policy.h>
|
#include <miral/set_window_management_policy.h>
|
||||||
#include <miral/external_client.h>
|
#include <miral/external_client.h>
|
||||||
#include <miral/runner.h>
|
#include <miral/runner.h>
|
||||||
#include <miral/window_management_options.h>
|
#include <miral/window_management_options.h>
|
||||||
#include <miral/append_event_filter.h>
|
|
||||||
#include <miral/internal_client.h>
|
#include <miral/internal_client.h>
|
||||||
#include <miral/keymap.h>
|
#include <miral/keymap.h>
|
||||||
#include <miral/toolkit_event.h>
|
#include <miral/toolkit_event.h>
|
||||||
#include <miral/x11_support.h>
|
#include <miral/x11_support.h>
|
||||||
#include <miral/wayland_extensions.h>
|
#include <miral/wayland_extensions.h>
|
||||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
#include "mirie_window_management_policy.h"
|
||||||
#include <miral/minimal_window_manager.h>
|
|
||||||
|
|
||||||
using namespace miral;
|
using namespace miral;
|
||||||
using namespace miral::toolkit;
|
using namespace miral::toolkit;
|
||||||
|
|
||||||
int main(int argc, char const* argv[]) {
|
int main(int argc, char const* argv[])
|
||||||
|
{
|
||||||
MirRunner runner{argc, argv};
|
MirRunner runner{argc, argv};
|
||||||
|
|
||||||
std::function<void()> shutdown_hook{[]{}};
|
std::function<void()> shutdown_hook{[]{}};
|
||||||
runner.add_stop_callback([&] { shutdown_hook(); });
|
runner.add_stop_callback([&] { shutdown_hook(); });
|
||||||
|
|
||||||
InternalClientLauncher launcher;
|
InternalClientLauncher launcher;
|
||||||
|
|
||||||
ExternalClientLauncher external_client_launcher;
|
ExternalClientLauncher external_client_launcher;
|
||||||
WindowManagerOptions window_managers
|
WindowManagerOptions window_managers
|
||||||
{
|
{
|
||||||
add_window_manager_policy<TilingWindowManagerPolicy>("tiling", launcher, shutdown_hook)
|
add_window_manager_policy<mirie::MirieWindowManagementPolicy>("tiling", external_client_launcher)
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Keymap config_keymap;
|
Keymap config_keymap;
|
||||||
|
|
||||||
|
|
||||||
return runner.run_with(
|
return runner.run_with(
|
||||||
{
|
{
|
||||||
window_managers,
|
window_managers,
|
||||||
WaylandExtensions{},
|
WaylandExtensions{},
|
||||||
X11Support{},
|
X11Support{},
|
||||||
AppendEventFilter{onEvent},
|
|
||||||
config_keymap,
|
config_keymap,
|
||||||
external_client_launcher
|
external_client_launcher
|
||||||
});
|
});
|
||||||
|
54
src/mirie_window_management_policy.cpp
Normal file
54
src/mirie_window_management_policy.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// Created by mattkae on 9/8/23.
|
||||||
|
//
|
||||||
|
#define MIR_LOG_COMPONENT "mirie"
|
||||||
|
|
||||||
|
#include "mirie_window_management_policy.h"
|
||||||
|
#include <mir_toolkit/events/enums.h>
|
||||||
|
#include <miral/toolkit_event.h>
|
||||||
|
#include <mir/log.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
37
src/mirie_window_management_policy.h
Normal file
37
src/mirie_window_management_policy.h
Normal file
@ -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 <miral/window_manager_tools.h>
|
||||||
|
#include <miral/minimal_window_manager.h>
|
||||||
|
#include <miral/external_client.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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<TilingRegion> root;
|
||||||
|
mirie::DisplayListener const display_listener;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MIRCOMPOSITOR_MIRIE_WINDOW_MANAGEMENT_POLICY_H
|
27
src/tiled_node.cpp
Normal file
27
src/tiled_node.cpp
Normal file
@ -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<TilingRegion> 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<TilingRegion>& in_region)
|
||||||
|
{
|
||||||
|
region = in_region;
|
||||||
|
}
|
28
src/tiled_node.h
Normal file
28
src/tiled_node.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by mattkae on 9/8/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MIRCOMPOSITOR_TILED_NODE_H
|
||||||
|
#define MIRCOMPOSITOR_TILED_NODE_H
|
||||||
|
|
||||||
|
#include <miral/window.h>
|
||||||
|
#include <mir/geometry/rectangle.h>
|
||||||
|
|
||||||
|
namespace mirie
|
||||||
|
{
|
||||||
|
class TilingRegion;
|
||||||
|
|
||||||
|
class TiledNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TiledNode(miral::Window const&, std::shared_ptr<TilingRegion> const&);
|
||||||
|
auto get_rectangle() -> mir::geometry::Rectangle;
|
||||||
|
void update_region(std::shared_ptr<TilingRegion> const&);
|
||||||
|
private:
|
||||||
|
miral::Window window;
|
||||||
|
std::shared_ptr<TilingRegion> region;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MIRCOMPOSITOR_TILED_NODE_H
|
5
src/tiling_region.cpp
Normal file
5
src/tiling_region.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by mattkae on 9/8/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "tiling_region.h"
|
40
src/tiling_region.h
Normal file
40
src/tiling_region.h
Normal file
@ -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 <mir/geometry/rectangle.h>
|
||||||
|
#include <miral/window.h>
|
||||||
|
#include <miral/application.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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<TiledNode> windows;
|
||||||
|
std::vector<std::shared_ptr<TilingRegion>> sub_regions;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MIRCOMPOSITOR_TILING_REGION_H
|
Loading…
Reference in New Issue
Block a user