Barebones horizontal placement algorithm with a single zone

This commit is contained in:
mattkae 2023-02-19 16:41:25 -05:00
parent 7640b2b9be
commit d50b2783ab
7 changed files with 129 additions and 17 deletions

View File

@ -15,7 +15,7 @@ find_package(PkgConfig)
pkg_check_modules(MIRAL miral REQUIRED)
find_package(OpenGL REQUIRED)
add_executable(compositor src/main.cpp src/FloatingWindowManager.cpp)
add_executable(compositor src/main.cpp src/FloatingWindowManager.cpp src/WindowGroup.cpp)
target_include_directories(compositor PUBLIC SYSTEM ${MIRAL_INCLUDE_DIRS})
target_link_libraries( compositor ${MIRAL_LDFLAGS})

View File

@ -13,6 +13,8 @@ I will begin my searching for documentation on how I made write a Mir-based comp
### Programming
1. To get started at a reasonabel pace, I copy and pasted the example `FloatingWindowManager` class. I plan to rework it for a `TilingWindowManager` with controls that mimic those if `i3.`
2. Zones seem like a good candidate for the purposes of grouping windows together here.
3. I have successfully created the `WindowGroup` which allows me to continually create new windows horizontally. Now I will hook up keybinds to support vertical.
My task is to build a compositor, so I will first define what is that I need in my compositor. As an MVP, I would like to support:
- Window transparency

View File

@ -15,7 +15,10 @@
*/
#include "FloatingWindowManager.hpp"
#include "WindowGroup.hpp"
#include "mir/geometry/forward.h"
#include <memory>
#include <miral/application_info.h>
#include <miral/internal_client.h>
#include <miral/toolkit_event.h>
@ -50,7 +53,8 @@ FloatingWindowManagerPolicy::FloatingWindowManagerPolicy(
WindowManagerTools const& tools,
miral::InternalClientLauncher const& launcher,
std::function<void()>& shutdown_hook) :
MinimalWindowManager(tools)
MinimalWindowManager(tools),
mRootWindowGroup()
{
mActivePlacementStrategy = PlacementStrategy::Horizontal;
shutdown_hook = [this] { };
@ -234,6 +238,8 @@ void FloatingWindowManagerPolicy::advise_new_window(WindowInfo const& window_inf
if (policy_data_for(tools.info_for(parent)).in_hidden_workspace)
apply_workspace_hidden_to(window_info.window());
}
mActiveWindowGroup->addWindow(std::make_shared<Window>(window_info.window()));
}
void FloatingWindowManagerPolicy::handle_window_ready(WindowInfo& window_info)
@ -453,15 +459,39 @@ WindowSpecification FloatingWindowManagerPolicy::place_new_window(
auto parameters = MinimalWindowManager::place_new_window(app_info, request_parameters);
bool const needs_titlebar = WindowInfo::needs_titlebar(parameters.type().value());
auto activeWindow = tools.active_window();
auto activeZone = tools.active_application_zone();
if (!activeWindow) {
parameters.top_left() = Point{0, 0};
parameters.size() = Size{ activeZone.extents().size };
// If it is our first time adding an item to the view, we initialize the root window group.
if (!mActiveWindowGroup.get()) {
mRootWindowGroup = WindowGroup(tools.active_application_zone().extents());
mActiveWindowGroup = std::make_shared<WindowGroup>(mRootWindowGroup);
}
parameters.top_left() = Point{0, 0};
auto targetNumberOfWindows = mActiveWindowGroup->getNumWindowsInGroup() + 1;
auto activeZone = mActiveWindowGroup->getZone();
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 (mActivePlacementStrategy == PlacementStrategy::Horizontal) {
// Adjust current windows
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 : mActiveWindowGroup->getWindowsInZone()) {
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() * mActiveWindowGroup->getNumWindowsInGroup() + activeZone.extents().top_left.x.as_value();
parameters.top_left() = Point{ x, y };
parameters.size() = zoneFractionSize;
}
else {
}
parameters.userdata() = std::make_shared<PolicyData>();
return parameters;

View File

@ -1,6 +1,8 @@
#ifndef TILING_WINDOW_MANAGER_HPP
#define TILING_WINDOW_MANAGER_HPP
#include "WindowGroup.hpp"
#include <memory>
#include <miral/minimal_window_manager.h>
#include <mir_toolkit/events/enums.h>
#include <chrono>
@ -40,6 +42,8 @@ public:
bool handle_pointer_event(MirPointerEvent const* event) override;
bool handle_touch_event(MirTouchEvent const* event) override;
bool handle_keyboard_event(MirKeyboardEvent const* event) override;
/** Add the window to the active zone. */
void advise_new_window(miral::WindowInfo const& window_info) override;
void handle_window_ready(miral::WindowInfo& window_info) override;
void advise_focus_gained(miral::WindowInfo const& info) override;
@ -56,7 +60,9 @@ protected:
private:
PlacementStrategy mActivePlacementStrategy;
std::vector<std::shared_ptr<miral::Window>> mActiveWindows;
std::map<int, miral::Window> mZoneIdToWindowMap;
WindowGroup mRootWindowGroup;
std::shared_ptr<WindowGroup> mActiveWindowGroup;
void toggle(MirWindowState state);

48
src/WindowGroup.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "WindowGroup.hpp"
#include "mir/geometry/forward.h"
#include "miral/window.h"
#include "miral/zone.h"
#include <bits/ranges_util.h>
#include <cstddef>
WindowGroup::WindowGroup():
mZone(mir::geometry::Rectangle())
{
}
WindowGroup::WindowGroup(mir::geometry::Rectangle rectangle):
mZone(rectangle)
{
}
WindowGroup::~WindowGroup() {
}
miral::Zone WindowGroup::getZone() {
return mZone;
}
int WindowGroup::getZoneId() {
return mZone.id();
}
size_t WindowGroup::getNumWindowsInGroup() {
return mWindowsInZone.size();
}
void WindowGroup::addWindow(std::shared_ptr<miral::Window> window) {
mWindowsInZone.push_back(window);
}
void WindowGroup::removeWindow(std::shared_ptr<miral::Window> window) {
auto toErase = std::ranges::find(mWindowsInZone, window);
if (toErase != mWindowsInZone.end()) {
mWindowsInZone.erase(toErase);
}
}
std::vector<std::shared_ptr<miral::Window>> WindowGroup::getWindowsInZone() {
return mWindowsInZone;
}

31
src/WindowGroup.hpp Normal file
View File

@ -0,0 +1,31 @@
#ifndef WINDOW_GROUP_HPP
#define WINDOW_GROUP_HPP
#include "mir/geometry/forward.h"
#include "miral/window_info.h"
#include "miral/zone.h"
#include <cstddef>
#include <memory>
#include <vector>
/** Represents a group of windows in the tiler. */
class WindowGroup {
public:
WindowGroup();
WindowGroup(mir::geometry::Rectangle);
~WindowGroup();
miral::Zone getZone();
int getZoneId();
void addWindow(std::shared_ptr<miral::Window>);
void removeWindow(std::shared_ptr<miral::Window>);
std::vector<std::shared_ptr<miral::Window>> getWindowsInZone();
size_t getNumWindowsInGroup();
private:
miral::Zone mZone;
std::vector<std::shared_ptr<WindowGroup>> mSubGroups;
std::vector<std::shared_ptr<miral::Window>> mWindowsInZone;
};
#endif

View File

@ -35,7 +35,7 @@ int main(int argc, char const* argv[]) {
add_window_manager_policy<FloatingWindowManagerPolicy>("floating", launcher, shutdown_hook)
};
std::string terminal_cmd{"gedit"};
std::string terminal_cmd{"xfce4-terminal"};
auto const onEvent = [&](MirEvent const* event)
{
@ -60,14 +60,9 @@ int main(int argc, char const* argv[]) {
runner.stop();
return true;
case XKB_KEY_t:
case XKB_KEY_T:
external_client_launcher.launch({terminal_cmd});
return false;
case XKB_KEY_x:
case XKB_KEY_X:
external_client_launcher.launch_using_x11({"xterm"});
external_client_launcher.launch({terminal_cmd});
return false;
default: