I have something functionng, time to dissect!

This commit is contained in:
mattkae 2023-02-19 12:57:46 -05:00
parent 3043463965
commit cb50196482
6 changed files with 718 additions and 71 deletions

View File

@ -16,7 +16,7 @@ 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) add_executable(compositor src/main.cpp src/FloatingWindowManager.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})

View File

@ -2,22 +2,18 @@
The following file will serve the purpose of documenting my thought processes and progress as I complete the assignment. I am starting this project on February 18, 2023. The following file will serve the purpose of documenting my thought processes and progress as I complete the assignment. I am starting this project on February 18, 2023.
## Step 1: Setting up the miral app ## Step 1: Setting up the miral app
At first, I went the virtual box route, but then I saw how easy it would be to do this locally, so I opted for that instead. On Arch, I did: .. TODO
```sh
git clone https://aur.archlinux.org/mir.git
cd mir
makepkg -si
```
and voila. It lives!
## Step 2: Hacking ## Step 2: Hacking
### Research ### Research
I will begin my searching for documentation on how I made write a Mir-based compositor: I will begin my searching for documentation on how I made write a Mir-based compositor:
1. https://mir-server.io/docs/developing-a-wayland-compositor-using-mir This seems like a good match! 1. https://mir-server.io/docs/developing-a-wayland-compositor-using-mir This seems like a good match.
2. I will also look extensively at the `miral-app` demo to see how it is starting the miral server. The `miral-shell` looks like the easiest barebone candidate for me to follow.
### ### Programming
1. I started off by implementing the simple miral-terminal example, however I am runnning into an issue where the `ExternalClientLauncher` is claiming that the server has not yet been set.
2.
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: 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 - Window transparency
- Drop shadows - Drop shadows

3
run.sh
View File

@ -8,5 +8,6 @@ if [ -O "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" ]
then then
unset WAYLAND_DISPLAY unset WAYLAND_DISPLAY
fi fi
# miral-shell can launch it's own terminal with Ctrl-Alt-T
echo $bindir
MIR_SERVER_ENABLE_X11=1 MIR_SERVER_SHELL_TERMINAL_EMULATOR=${terminal} exec ${bindir}${miral_server} $* MIR_SERVER_ENABLE_X11=1 MIR_SERVER_SHELL_TERMINAL_EMULATOR=${terminal} exec ${bindir}${miral_server} $*

View File

@ -1,29 +1,601 @@
/*
* 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 "FloatingWindowManager.hpp" #include "FloatingWindowManager.hpp"
#include <miral/minimal_window_manager.h>
const int title_bar_height = 16; #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>
FloatingWindowManager::FloatingWindowManager(const miral::WindowManagerTools& tools) { #include <linux/input.h>
#include <csignal>
using namespace miral;
using namespace miral::toolkit;
namespace
{
DeltaY const title_bar_height{12};
struct PolicyData
{
bool in_hidden_workspace{false};
MirWindowState old_state;
};
inline PolicyData& policy_data_for(WindowInfo const& info)
{
return *std::static_pointer_cast<PolicyData>(info.userdata());
}
} }
miral::WindowSpecification FloatingWindowManager::place_new_window( FloatingWindowManagerPolicy::FloatingWindowManagerPolicy(
miral::ApplicationInfo const& app_info, WindowManagerTools const& tools,
miral::WindowSpecification const& requested_specification) miral::InternalClientLauncher const& launcher,
std::function<void()>& shutdown_hook) :
MinimalWindowManager(tools)
{ {
auto parameters = miral::MinimalWindowManager::place_new_window(app_info, requested_specification); shutdown_hook = [this] { };
// if (app_info.application() == miral::decoration_provider->session()) for (auto key : {KEY_F1, KEY_F2, KEY_F3, KEY_F4})
// { key_to_workspace[key] = this->tools.create_workspace();
// parameters.type() = mir_window_type_decoration;
// parameters.depth_layer() = mir_depth_layer_background;
// }
bool const needs_titlebar = miral::WindowInfo::needs_titlebar(parameters.type().value()); active_workspace = key_to_workspace[KEY_F1];
}
FloatingWindowManagerPolicy::~FloatingWindowManagerPolicy() = default;
bool FloatingWindowManagerPolicy::handle_pointer_event(MirPointerEvent const* event)
{
if (MinimalWindowManager::handle_pointer_event(event))
return true;
auto const action = mir_pointer_event_action(event);
auto const modifiers = mir_pointer_event_modifiers(event) & modifier_mask;
Point const cursor{
mir_pointer_event_axis_value(event, mir_pointer_axis_x),
mir_pointer_event_axis_value(event, mir_pointer_axis_y)};
bool consumes_event = false;
if (action == mir_pointer_action_button_down)
{
if (auto const window = tools.window_at(cursor))
tools.select_active_window(window);
if (auto const window = tools.active_window())
{
if (mir_pointer_event_button_state(event, mir_pointer_button_tertiary))
{
if (modifiers == mir_input_event_modifier_alt)
{
Rectangle const old_pos{window.top_left(), window.size()};
auto anchor = old_pos.bottom_right();
auto edge = mir_resize_edge_northwest;
struct Corner { Point point; MirResizeEdge edge; };
for (auto const& corner : {
Corner{old_pos.top_right(), mir_resize_edge_southwest},
Corner{old_pos.bottom_left(), mir_resize_edge_northeast},
Corner{old_pos.top_left, mir_resize_edge_southeast}})
{
if ((cursor - anchor).length_squared() <
(cursor - corner.point).length_squared())
{
anchor = corner.point;
edge = corner.edge;
}
}
begin_pointer_resize(tools.info_for(window), mir_pointer_event_input_event(event), edge);
consumes_event = true;
}
}
}
}
return consumes_event;
}
bool FloatingWindowManagerPolicy::handle_touch_event(MirTouchEvent const* event)
{
auto const count = mir_touch_event_point_count(event);
if (MinimalWindowManager::handle_touch_event(event) || count != 3)
{
pinching = false;
return false;
}
for (auto i = 0U; i != count; ++i)
{
switch (mir_touch_event_action(event, i))
{
case mir_touch_action_up:
case mir_touch_action_down:
pinching = false;
return false;
default:
continue;
}
}
int touch_pinch_top = std::numeric_limits<int>::max();
int touch_pinch_left = std::numeric_limits<int>::max();
int touch_pinch_width = 0;
int touch_pinch_height = 0;
for (auto i = 0U; i != count; ++i)
{
for (auto j = 0U; j != i; ++j)
{
int dx = mir_touch_event_axis_value(event, i, mir_touch_axis_x) -
mir_touch_event_axis_value(event, j, mir_touch_axis_x);
int dy = mir_touch_event_axis_value(event, i, mir_touch_axis_y) -
mir_touch_event_axis_value(event, j, mir_touch_axis_y);
if (touch_pinch_width < dx)
touch_pinch_width = dx;
if (touch_pinch_height < dy)
touch_pinch_height = dy;
}
int const x = mir_touch_event_axis_value(event, i, mir_touch_axis_x);
int const y = mir_touch_event_axis_value(event, i, mir_touch_axis_y);
if (touch_pinch_top > y)
touch_pinch_top = y;
if (touch_pinch_left > x)
touch_pinch_left = x;
}
if (auto window = tools.active_window())
{
auto const old_size = window.size();
auto const delta_width = DeltaX{touch_pinch_width - old_touch_pinch_width};
auto const delta_height = DeltaY{touch_pinch_height - old_touch_pinch_height};
auto new_width = std::max(old_size.width + delta_width, Width{5});
auto new_height = std::max(old_size.height + delta_height, Height{5});
Displacement movement{
DeltaX{touch_pinch_left - old_touch_pinch_left},
DeltaY{touch_pinch_top - old_touch_pinch_top}};
auto& window_info = tools.info_for(window);
keep_window_within_constraints(window_info, movement, new_width, new_height);
auto new_pos = window.top_left() + movement;
Size new_size{new_width, new_height};
{ // Workaround for lp:1627697
auto now = std::chrono::steady_clock::now();
if (pinching && now < last_resize+std::chrono::milliseconds(20))
return true;
last_resize = now;
}
if (pinching)
{
WindowSpecification modifications;
modifications.top_left() = new_pos;
modifications.size() = new_size;
tools.modify_window(window_info, modifications);
}
else
{
pinching = true;
}
old_touch_pinch_top = touch_pinch_top;
old_touch_pinch_left = touch_pinch_left;
old_touch_pinch_width = touch_pinch_width;
old_touch_pinch_height = touch_pinch_height;
}
return true;
}
void FloatingWindowManagerPolicy::advise_new_window(WindowInfo const& window_info)
{
MinimalWindowManager::advise_new_window(window_info);
auto const parent = window_info.parent();
if (!parent)
tools.add_tree_to_workspace(window_info.window(), active_workspace);
else
{
if (policy_data_for(tools.info_for(parent)).in_hidden_workspace)
apply_workspace_hidden_to(window_info.window());
}
}
void FloatingWindowManagerPolicy::handle_window_ready(WindowInfo& window_info)
{
MinimalWindowManager::handle_window_ready(window_info);
}
void FloatingWindowManagerPolicy::advise_focus_gained(WindowInfo const& info)
{
MinimalWindowManager::advise_focus_gained(info);
}
bool FloatingWindowManagerPolicy::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) & modifier_mask;
// Switch workspaces
if (action == mir_keyboard_action_down &&
modifiers == (mir_input_event_modifier_alt | mir_input_event_modifier_meta))
{
auto const found = key_to_workspace.find(scan_code);
if (found != key_to_workspace.end())
{
switch_workspace_to(found->second);
return true;
}
}
// Switch workspace taking the active window
if (action == mir_keyboard_action_down &&
modifiers == (mir_input_event_modifier_ctrl | mir_input_event_modifier_meta))
{
auto const found = key_to_workspace.find(scan_code);
if (found != key_to_workspace.end())
{
switch_workspace_to(found->second, tools.active_window());
return true;
}
}
if (action == mir_keyboard_action_down && scan_code == KEY_F11)
{
switch (modifiers)
{
case mir_input_event_modifier_alt:
toggle(mir_window_state_maximized);
return true;
case mir_input_event_modifier_shift:
toggle(mir_window_state_vertmaximized);
return true;
case mir_input_event_modifier_ctrl:
toggle(mir_window_state_horizmaximized);
return true;
case mir_input_event_modifier_meta:
toggle(mir_window_state_fullscreen);
return true;
default:
break;
}
}
else if (action == mir_keyboard_action_down && scan_code == KEY_F4 &&
modifiers == (mir_input_event_modifier_alt|mir_input_event_modifier_shift))
{
if (auto const& window = tools.active_window())
kill(window.application(), SIGTERM);
return true;
}
else if (action == mir_keyboard_action_down &&
modifiers == (mir_input_event_modifier_ctrl|mir_input_event_modifier_meta))
{
if (auto active_window = tools.active_window())
{
auto active_zone = tools.active_application_zone().extents();
auto& window_info = tools.info_for(active_window);
WindowSpecification modifications;
switch (scan_code)
{
case KEY_LEFT:
modifications.state() = mir_window_state_vertmaximized;
tools.place_and_size_for_state(modifications, window_info);
modifications.top_left() = window_info.needs_titlebar(window_info.type()) ?
active_zone.top_left + title_bar_height :
active_zone.top_left;
break;
case KEY_RIGHT:
{
modifications.state() = mir_window_state_vertmaximized;
tools.place_and_size_for_state(modifications, window_info);
auto const new_width =
(modifications.size().is_set() ? modifications.size().value() : active_window.size()).width;
modifications.top_left() = window_info.needs_titlebar(window_info.type()) ?
active_zone.top_right() - Displacement{as_delta(new_width), 0} + title_bar_height :
active_zone.top_right() - Displacement{as_delta(new_width), 0};
break;
}
case KEY_UP:
modifications.state() = mir_window_state_horizmaximized;
tools.place_and_size_for_state(modifications, window_info);
modifications.top_left() = window_info.needs_titlebar(window_info.type()) ?
active_zone.top_left + title_bar_height :
active_zone.top_left;
break;
case KEY_DOWN:
modifications.state() = mir_window_state_horizmaximized;
tools.place_and_size_for_state(modifications, window_info);
modifications.top_left() =
active_zone.bottom_right() - as_displacement(
modifications.size().is_set() ? modifications.size().value() : active_window.size());
break;
default:
return false;
}
tools.modify_window(window_info, modifications);
return true;
}
}
return false;
}
void FloatingWindowManagerPolicy::toggle(MirWindowState state)
{
if (auto const window = tools.active_window())
{
auto& info = tools.info_for(window);
WindowSpecification modifications;
modifications.state() = (info.state() == state) ? mir_window_state_restored : state;
tools.place_and_size_for_state(modifications, info);
tools.modify_window(info, modifications);
}
}
void FloatingWindowManagerPolicy::keep_window_within_constraints(
WindowInfo const& window_info, Displacement& movement, Width& new_width, Height& new_height) const
{
switch (window_info.state())
{
case mir_window_state_maximized:
case mir_window_state_fullscreen:
new_width = window_info.window().size().width;
new_height = window_info.window().size().height;
movement = {0, 0};
break;
case mir_window_state_vertmaximized:
new_height = window_info.window().size().height;
movement.dy = DeltaY{0};
break;
case mir_window_state_horizmaximized:
new_width = window_info.window().size().width;
movement.dx - DeltaX{0};
break;
default:;
}
auto const min_width = std::max(window_info.min_width(), Width{5});
auto const min_height = std::max(window_info.min_height(), Height{5});
if (new_width < min_width)
{
new_width = min_width;
if (movement.dx > DeltaX{0})
movement.dx = DeltaX{0};
}
if (new_height < min_height)
{
new_height = min_height;
if (movement.dy > DeltaY{0})
movement.dy = DeltaY{0};
}
auto const max_width = window_info.max_width();
auto const max_height = window_info.max_height();
if (new_width > max_width)
{
new_width = max_width;
if (movement.dx < DeltaX{0})
movement.dx = DeltaX{0};
}
if (new_height > max_height)
{
new_height = max_height;
if (movement.dy < DeltaY{0})
movement.dy = DeltaY{0};
}
}
WindowSpecification FloatingWindowManagerPolicy::place_new_window(
ApplicationInfo const& app_info, WindowSpecification const& request_parameters)
{
auto parameters = MinimalWindowManager::place_new_window(app_info, request_parameters);
bool const needs_titlebar = WindowInfo::needs_titlebar(parameters.type().value());
if (parameters.state().value() != mir_window_state_fullscreen && needs_titlebar) if (parameters.state().value() != mir_window_state_fullscreen && needs_titlebar)
parameters.top_left() = miral::Point{parameters.top_left().value().x, parameters.top_left().value().y + title_bar_height}; parameters.top_left() = Point{parameters.top_left().value().x, parameters.top_left().value().y + title_bar_height};
parameters.userdata() = std::make_shared<miral::PolicyData>(); parameters.userdata() = std::make_shared<PolicyData>();
return parameters; return parameters;
} }
void FloatingWindowManagerPolicy::advise_adding_to_workspace(
std::shared_ptr<Workspace> const& workspace, std::vector<Window> const& windows)
{
if (windows.empty())
return;
for (auto const& window : windows)
{
if (workspace == active_workspace)
{
apply_workspace_visible_to(window);
}
else
{
apply_workspace_hidden_to(window);
}
}
}
auto FloatingWindowManagerPolicy::confirm_placement_on_display(
miral::WindowInfo const& window_info, MirWindowState new_state, Rectangle const& new_placement) -> Rectangle
{
switch (new_state)
{
case mir_window_state_maximized:
case mir_window_state_vertmaximized:
if (window_info.needs_titlebar(window_info.type()))
{
auto result = new_placement;
result.top_left.y = result.top_left.y + title_bar_height;
result.size.height = result.size.height - title_bar_height;
return result;
}
// else
// Falls through.
default:
return new_placement;
}
}
void FloatingWindowManagerPolicy::switch_workspace_to(
std::shared_ptr<Workspace> const& workspace,
Window const& window)
{
if (workspace == active_workspace)
return;
auto const old_active = active_workspace;
active_workspace = workspace;
auto const old_active_window = tools.active_window();
if (!old_active_window)
{
// If there's no active window, the first shown grabs focus: get the right one
if (auto const ww = workspace_to_active[workspace])
{
tools.for_each_workspace_containing(ww, [&](std::shared_ptr<miral::Workspace> const& ws)
{
if (ws == workspace)
{
apply_workspace_visible_to(ww);
}
});
}
}
tools.remove_tree_from_workspace(window, old_active);
tools.add_tree_to_workspace(window, active_workspace);
tools.for_each_window_in_workspace(active_workspace, [&](Window const& window)
{
apply_workspace_visible_to(window);
});
bool hide_old_active = false;
tools.for_each_window_in_workspace(old_active, [&](Window const& window)
{
if (window == old_active_window)
{
// If we hide the active window focus will shift: do that last
hide_old_active = true;
return;
}
apply_workspace_hidden_to(window);
});
if (hide_old_active)
{
apply_workspace_hidden_to(old_active_window);
// Remember the old active_window when we switch away
workspace_to_active[old_active] = old_active_window;
}
}
void FloatingWindowManagerPolicy::apply_workspace_hidden_to(Window const& window)
{
auto const& window_info = tools.info_for(window);
auto& pdata = policy_data_for(window_info);
if (!pdata.in_hidden_workspace)
{
pdata.in_hidden_workspace = true;
pdata.old_state = window_info.state();
WindowSpecification modifications;
modifications.state() = mir_window_state_hidden;
tools.place_and_size_for_state(modifications, window_info);
tools.modify_window(window_info.window(), modifications);
}
}
void FloatingWindowManagerPolicy::apply_workspace_visible_to(Window const& window)
{
auto const& window_info = tools.info_for(window);
auto& pdata = policy_data_for(window_info);
if (pdata.in_hidden_workspace)
{
pdata.in_hidden_workspace = false;
WindowSpecification modifications;
modifications.state() = pdata.old_state;
tools.place_and_size_for_state(modifications, window_info);
tools.modify_window(window_info.window(), modifications);
}
}
void FloatingWindowManagerPolicy::handle_modify_window(WindowInfo& window_info, WindowSpecification const& modifications)
{
auto mods = modifications;
auto& pdata = policy_data_for(window_info);
if (pdata.in_hidden_workspace && mods.state().is_set())
pdata.old_state = mods.state().consume();
MinimalWindowManager::handle_modify_window(window_info, mods);
}

View File

@ -1,38 +1,117 @@
#ifndef FLOATING_WINDOW_MANAGER_HPP /*
#define FLOATING_WINDOW_MANAGER_HPP * 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/>.
*/
#ifndef MIRAL_SHELL_FLOATING_WINDOW_MANAGER_H
#define MIRAL_SHELL_FLOATING_WINDOW_MANAGER_H
#include "mir/geometry/rectangles.h"
#include <miral/window_management_policy.h>
#include <miral/window_manager_tools.h>
#include <mir_toolkit/events/enums.h>
#include <miral/minimal_window_manager.h> #include <miral/minimal_window_manager.h>
#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>
class FloatingWindowManager : public miral::WindowManagementPolicy { #include <mir_toolkit/events/enums.h>
#include <chrono>
#include <map>
namespace miral { class InternalClientLauncher; }
using namespace mir::geometry;
class FloatingWindowManagerPolicy : public miral::MinimalWindowManager
{
public: public:
FloatingWindowManager(const miral::WindowManagerTools&); FloatingWindowManagerPolicy(
~FloatingWindowManager(); miral::WindowManagerTools const& tools,
miral::WindowSpecification place_new_window( miral::InternalClientLauncher const& launcher,
miral::ApplicationInfo const& app_info, std::function<void()>& shutdown_hook);
miral::WindowSpecification const& requested_specification) override; ~FloatingWindowManagerPolicy();
virtual miral::WindowSpecification place_new_window(
miral::ApplicationInfo const& app_info, miral::WindowSpecification const& request_parameters) override;
/** @name example event handling:
* o Switch apps: Alt+Tab, tap or click on the corresponding window
* o Switch window: Alt+`, tap or click on the corresponding window
* o Move window: Alt-leftmousebutton drag (three finger drag)
* o Resize window: Alt-middle_button drag (three finger pinch)
* o Maximize/restore current window (to display size): Alt-F11
* o Maximize/restore current window (to display height): Shift-F11
* o Maximize/restore current window (to display width): Ctrl-F11
* o Switch workspace . . . . . . . . . . : Meta-Alt-[F1|F2|F3|F4]
* o Switch workspace taking active window: Meta-Ctrl-[F1|F2|F3|F4]
* @{ */
bool handle_pointer_event(MirPointerEvent const* event) override; bool handle_pointer_event(MirPointerEvent const* event) override;
bool handle_touch_event(MirTouchEvent const* event) override; bool handle_touch_event(MirTouchEvent const* event) override;
bool handle_keyboard_event(MirKeyboardEvent const* event) override; bool handle_keyboard_event(MirKeyboardEvent const* event) override;
/** @} */
/** @name track events that affect titlebar
* @{ */
void advise_new_window(miral::WindowInfo const& window_info) override; void advise_new_window(miral::WindowInfo const& window_info) override;
void handle_window_ready(miral::WindowInfo& window_info) override; void handle_window_ready(miral::WindowInfo& window_info) override;
void handle_raise_window (miral::WindowInfo &window_info) override;
void advise_focus_gained(miral::WindowInfo const& info) override; void advise_focus_gained(miral::WindowInfo const& info) override;
void handle_modify_window(miral::WindowInfo& window_info, miral::WindowSpecification const& modifications) override; void handle_modify_window(miral::WindowInfo& window_info, miral::WindowSpecification const& modifications) override;
mir::geometry::Rectangle confirm_placement_on_display (miral::WindowInfo const &window_info, MirWindowState new_state, mir::geometry::Rectangle const &new_placement) override; /** @} */
void handle_request_drag_and_drop (miral::WindowInfo &window_info) override;
void handle_request_move (miral::WindowInfo &window_info, MirInputEvent const *input_event) override; protected:
void handle_request_resize (miral::WindowInfo &window_info, MirInputEvent const *input_event, MirResizeEdge edge) override; static const int modifier_mask =
mir::geometry::Rectangle confirm_inherited_move (miral::WindowInfo const &window_info, mir::geometry::Displacement movement) override; 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:
void toggle(MirWindowState state);
int old_touch_pinch_top = 0;
int old_touch_pinch_left = 0;
int old_touch_pinch_width = 0;
int old_touch_pinch_height = 0;
bool pinching = false;
void keep_window_within_constraints(
miral::WindowInfo const& window_info,
Displacement& movement,
Width& new_width,
Height& new_height) const;
// Workaround for lp:1627697
std::chrono::steady_clock::time_point last_resize;
void advise_adding_to_workspace(
std::shared_ptr<miral::Workspace> const& workspace,
std::vector<miral::Window> const& windows) override;
auto confirm_placement_on_display(
miral::WindowInfo const& window_info,
MirWindowState new_state,
Rectangle const& new_placement) -> Rectangle override;
// Switch workspace, taking window (if not null)
void switch_workspace_to(
std::shared_ptr<miral::Workspace> const& workspace,
miral::Window const& window = miral::Window{});
std::shared_ptr<miral::Workspace> active_workspace;
std::map<int, std::shared_ptr<miral::Workspace>> key_to_workspace;
std::map<std::shared_ptr<miral::Workspace>, miral::Window> workspace_to_active;
void apply_workspace_visible_to(miral::Window const& window);
void apply_workspace_hidden_to(miral::Window const& window);
}; };
#endif #endif //MIRAL_SHELL_FLOATING_WINDOW_MANAGER_H

View File

@ -1,6 +1,7 @@
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include "FloatingWindowManager.hpp"
#include <miral/set_window_management_policy.h> #include <miral/set_window_management_policy.h>
#include <miral/display_configuration_option.h> #include <miral/display_configuration_option.h>
#include <miral/external_client.h> #include <miral/external_client.h>
@ -26,14 +27,15 @@ int main(int argc, char const* argv[]) {
std::function<void()> shutdown_hook{[]{}}; std::function<void()> shutdown_hook{[]{}};
runner.add_stop_callback([&] { shutdown_hook(); }); runner.add_stop_callback([&] { shutdown_hook(); });
WindowManagerOptions windowManagers InternalClientLauncher launcher;
{
add_window_manager_policy<MinimalWindowManager>("floating"),
};
ExternalClientLauncher external_client_launcher; ExternalClientLauncher external_client_launcher;
WindowManagerOptions window_managers
{
add_window_manager_policy<FloatingWindowManagerPolicy>("floating", launcher, shutdown_hook)
};
std::string terminal_cmd{"miral-terminal"}; std::string terminal_cmd{"gedit"};
auto const onEvent = [&](MirEvent const* event) auto const onEvent = [&](MirEvent const* event)
{ {
@ -74,24 +76,21 @@ int main(int argc, char const* argv[]) {
}; };
Keymap config_keymap; Keymap config_keymap;
auto run_startup_apps = [&](std::string const& apps)
{
for (auto i = begin(apps); i != end(apps); )
{
auto const j = find(i, end(apps), ':');
external_client_launcher.launch(std::vector<std::string>{std::string{i, j}});
if ((i = j) != end(apps)) ++i;
}
};
return runner.run_with( auto runResult = runner.run_with(
{ {
windowManagers, window_managers,
WaylandExtensions{}, WaylandExtensions{},
X11Support{}, X11Support{},
AppendEventFilter{onEvent}, AppendEventFilter{onEvent},
config_keymap config_keymap,
external_client_launcher
}); });
if (runResult == EXIT_FAILURE) {
return runResult;
}
return EXIT_SUCCESS;
} }