mirror of
https://github.com/miracle-wm-org/miracle-wm.git
synced 2024-11-26 12:34:40 +03:00
bugfix: handling initially fullscreen windows + allowing workspaces to be floating by default + allowing windows to be floating initially + fixes for #168 (#171)
* bugfix: handling initially fullscreen windows + allowing workspaces to be floating by default * (#168) bugfix: enabling zwp_pointer_constraints_v1 and zwp_relative_pointer_manager_v1 so that we can game
This commit is contained in:
parent
caab71d750
commit
dbd50f3b74
@ -132,7 +132,7 @@ void LeafNode::toggle_fullscreen()
|
||||
if (node_interface.is_fullscreen(window))
|
||||
next_state = mir_window_state_restored;
|
||||
else
|
||||
next_state = mir_window_state_maximized;
|
||||
next_state = mir_window_state_fullscreen;
|
||||
}
|
||||
|
||||
bool LeafNode::is_fullscreen() const
|
||||
|
24
src/main.cpp
24
src/main.cpp
@ -101,17 +101,23 @@ int main(int argc, char const* argv[])
|
||||
};
|
||||
|
||||
notify_init("miracle-wm");
|
||||
|
||||
WaylandExtensions wayland_extensions = WaylandExtensions{}
|
||||
.enable(miral::WaylandExtensions::zwlr_layer_shell_v1)
|
||||
.enable(miral::WaylandExtensions::zwlr_foreign_toplevel_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zxdg_output_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zwp_virtual_keyboard_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zwlr_virtual_pointer_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zwp_input_method_manager_v2)
|
||||
.enable(miral::WaylandExtensions::zwlr_screencopy_manager_v1)
|
||||
.enable(miral::WaylandExtensions::ext_session_lock_manager_v1);
|
||||
|
||||
for (auto const& extension : {"zwp_pointer_constraints_v1", "zwp_relative_pointer_manager_v1"})
|
||||
wayland_extensions.enable(extension);
|
||||
|
||||
return runner.run_with(
|
||||
{ window_managers,
|
||||
WaylandExtensions {}
|
||||
.enable(miral::WaylandExtensions::zwlr_layer_shell_v1)
|
||||
.enable(miral::WaylandExtensions::zwlr_foreign_toplevel_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zxdg_output_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zwp_virtual_keyboard_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zwlr_virtual_pointer_manager_v1)
|
||||
.enable(miral::WaylandExtensions::zwp_input_method_manager_v2)
|
||||
.enable(miral::WaylandExtensions::zwlr_screencopy_manager_v1)
|
||||
.enable(miral::WaylandExtensions::ext_session_lock_manager_v1),
|
||||
wayland_extensions,
|
||||
X11Support {}.default_to_enabled(),
|
||||
config_keymap,
|
||||
external_client_launcher,
|
||||
|
@ -796,6 +796,39 @@ void MiracleConfig::_load()
|
||||
}
|
||||
}
|
||||
|
||||
if (config["workspaces"])
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const& workspaces = config["workspaces"];
|
||||
if (!workspaces.IsSequence())
|
||||
{
|
||||
mir::log_error("workspaces: expected sequence: L%d:%d", workspaces.Mark().line, workspaces.Mark().column);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto const& workspace : workspaces)
|
||||
{
|
||||
auto num = workspace["number"].as<int>();
|
||||
auto type = window_type_from_string(workspace["layout"].as<std::string>());
|
||||
if (type != WindowType::tiled && type != WindowType::floating)
|
||||
{
|
||||
mir::log_error("layout should be 'tiled' or 'floating': L%d:%d", workspace["layout"].Mark().line, workspace["layout"].Mark().column);
|
||||
continue;
|
||||
}
|
||||
|
||||
workspace_configs.push_back({
|
||||
num, type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (YAML::BadConversion const& e)
|
||||
{
|
||||
mir::log_error("workspaces: unable to parse: %s, L%d:%d", e.msg.c_str(), e.mark.line, e.mark.column);
|
||||
}
|
||||
}
|
||||
|
||||
read_animation_definitions(config);
|
||||
}
|
||||
|
||||
@ -1110,3 +1143,14 @@ bool MiracleConfig::are_animations_enabled() const
|
||||
{
|
||||
return animations_enabled;
|
||||
}
|
||||
|
||||
WorkspaceConfig MiracleConfig::get_workspace_config(int key) const
|
||||
{
|
||||
for (auto const& config : workspace_configs)
|
||||
{
|
||||
if (config.num == key)
|
||||
return config;
|
||||
}
|
||||
|
||||
return { key, WindowType::tiled };
|
||||
}
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MIRACLEWM_MIRACLE_CONFIG_H
|
||||
|
||||
#include "animation_defintion.h"
|
||||
#include "window_metadata.h"
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <glm/glm.hpp>
|
||||
@ -124,6 +125,12 @@ struct BorderConfig
|
||||
glm::vec4 color;
|
||||
};
|
||||
|
||||
struct WorkspaceConfig
|
||||
{
|
||||
int num = -1;
|
||||
WindowType layout = WindowType::tiled;
|
||||
};
|
||||
|
||||
class MiracleConfig
|
||||
{
|
||||
public:
|
||||
@ -145,6 +152,7 @@ public:
|
||||
[[nodiscard]] BorderConfig const& get_border_config() const;
|
||||
[[nodiscard]] std::array<AnimationDefinition, (int)AnimateableEvent::max> const& get_animation_definitions() const;
|
||||
[[nodiscard]] bool are_animations_enabled() const;
|
||||
[[nodiscard]] WorkspaceConfig get_workspace_config(int key) const;
|
||||
|
||||
/// Register a listener on configuration change. A lower "priority" number signifies that the
|
||||
/// listener should be triggered earlier. A higher priority means later
|
||||
@ -191,6 +199,7 @@ private:
|
||||
std::atomic<bool> has_changes = false;
|
||||
bool animations_enabled = true;
|
||||
std::array<AnimationDefinition, (int)AnimateableEvent::max> animation_defintions;
|
||||
std::vector<WorkspaceConfig> workspace_configs;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,7 @@ bool OutputContent::handle_pointer_event(const MirPointerEvent* event)
|
||||
if (get_active_workspace_num() < 0)
|
||||
return false;
|
||||
|
||||
if (select_window_from_point(static_cast<int>(x), static_cast<int>(y)))
|
||||
return true;
|
||||
select_window_from_point(static_cast<int>(x), static_cast<int>(y));
|
||||
|
||||
auto const action = mir_pointer_event_action(event);
|
||||
if (has_clicked_floating_window || get_active_workspace()->has_floating_window(active_window))
|
||||
@ -93,13 +92,18 @@ bool OutputContent::handle_pointer_event(const MirPointerEvent* event)
|
||||
return false;
|
||||
}
|
||||
|
||||
WindowType OutputContent::allocate_position(miral::WindowSpecification& requested_specification)
|
||||
WindowType OutputContent::allocate_position(miral::ApplicationInfo const& app_info, miral::WindowSpecification& requested_specification)
|
||||
{
|
||||
if (!window_helpers::is_tileable(requested_specification))
|
||||
return WindowType::other;
|
||||
|
||||
requested_specification = get_active_tree()->allocate_position(requested_specification);
|
||||
return WindowType::tiled;
|
||||
auto type = get_active_workspace()->allocate_position(requested_specification);
|
||||
if (type == WindowType::floating)
|
||||
{
|
||||
requested_specification = floating_window_manager.place_new_window(app_info, requested_specification);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
std::shared_ptr<WindowMetadata> OutputContent::advise_new_window(miral::WindowInfo const& window_info, WindowType type)
|
||||
@ -109,7 +113,8 @@ std::shared_ptr<WindowMetadata> OutputContent::advise_new_window(miral::WindowIn
|
||||
{
|
||||
case WindowType::tiled:
|
||||
{
|
||||
auto node = get_active_tree()->advise_new_window(window_info);
|
||||
auto const& tree = get_active_tree();
|
||||
auto node = tree->advise_new_window(window_info);
|
||||
metadata = std::make_shared<WindowMetadata>(WindowType::tiled, window_info.window(), get_active_workspace());
|
||||
metadata->associate_to_node(node);
|
||||
break;
|
||||
@ -117,6 +122,8 @@ std::shared_ptr<WindowMetadata> OutputContent::advise_new_window(miral::WindowIn
|
||||
case WindowType::floating:
|
||||
{
|
||||
floating_window_manager.advise_new_window(window_info);
|
||||
metadata = std::make_shared<WindowMetadata>(WindowType::floating, window_info.window(), get_active_workspace());
|
||||
get_active_workspace()->add_floating_window(window_info.window());
|
||||
break;
|
||||
}
|
||||
case WindowType::other:
|
||||
@ -138,6 +145,12 @@ std::shared_ptr<WindowMetadata> OutputContent::advise_new_window(miral::WindowIn
|
||||
spec.min_width() = mir::geometry::Width(0);
|
||||
spec.min_height() = mir::geometry::Height(0);
|
||||
tools.modify_window(window_info.window(), spec);
|
||||
|
||||
// Warning: We need to advise fullscreen only after we've associated the userdata() appropriately
|
||||
if (type == WindowType::tiled && window_helpers::is_window_fullscreen(window_info.state()))
|
||||
{
|
||||
get_active_tree()->advise_fullscreen_window(window_info.window());
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
else
|
||||
@ -382,7 +395,7 @@ OutputContent::confirm_placement_on_display(
|
||||
mir::log_error("Unsupported window type: %d", (int)metadata->get_type());
|
||||
break;
|
||||
}
|
||||
return new_placement;
|
||||
return modified_placement;
|
||||
}
|
||||
|
||||
bool OutputContent::select_window_from_point(int x, int y)
|
||||
@ -829,7 +842,7 @@ void OutputContent::add_immediately(miral::Window& window)
|
||||
{
|
||||
auto& prev_info = tools.info_for(window);
|
||||
WindowSpecification spec = window_helpers::copy_from(prev_info);
|
||||
WindowType type = allocate_position(spec);
|
||||
WindowType type = allocate_position(tools.info_for(window.application()), spec);
|
||||
tools.modify_window(window, spec);
|
||||
advise_new_window(tools.info_for(window), type);
|
||||
auto metadata = window_helpers::get_metadata(window, tools);
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
[[nodiscard]] int get_active_workspace_num() const { return active_workspace; }
|
||||
[[nodiscard]] std::shared_ptr<WorkspaceContent> const& get_active_workspace() const;
|
||||
bool handle_pointer_event(MirPointerEvent const* event);
|
||||
WindowType allocate_position(miral::WindowSpecification& requested_specification);
|
||||
WindowType allocate_position(miral::ApplicationInfo const& app_info, miral::WindowSpecification& requested_specification);
|
||||
std::shared_ptr<WindowMetadata> advise_new_window(miral::WindowInfo const& window_info, WindowType type);
|
||||
void handle_window_ready(miral::WindowInfo& window_info, std::shared_ptr<miracle::WindowMetadata> const& metadata);
|
||||
void advise_focus_gained(std::shared_ptr<miracle::WindowMetadata> const& metadata);
|
||||
|
@ -235,7 +235,7 @@ auto Policy::place_new_window(
|
||||
|
||||
auto new_spec = requested_specification;
|
||||
pending_output = active_output;
|
||||
pending_type = active_output->allocate_position(new_spec);
|
||||
pending_type = active_output->allocate_position(app_info, new_spec);
|
||||
return new_spec;
|
||||
}
|
||||
|
||||
|
@ -68,27 +68,20 @@ miral::WindowSpecification TilingWindowTree::allocate_position(const miral::Wind
|
||||
new_spec.max_height() = geom::Height { std::numeric_limits<int>::max() };
|
||||
auto node = get_active_lane()->create_space_for_window();
|
||||
auto rect = node->get_visible_area();
|
||||
new_spec.size() = rect.size;
|
||||
new_spec.top_left() = rect.top_left;
|
||||
|
||||
if (new_spec.state().is_set() && window_helpers::is_window_fullscreen(new_spec.state().value()))
|
||||
if (!new_spec.state().is_set() || !window_helpers::is_window_fullscreen(new_spec.state().value()))
|
||||
{
|
||||
// Don't start anyone in fullscreen mode
|
||||
new_spec.state() = mir::optional_value<MirWindowState>();
|
||||
// We only set the size immediately if we have no strong opinions about the size
|
||||
new_spec.size() = rect.size;
|
||||
new_spec.top_left() = rect.top_left;
|
||||
}
|
||||
|
||||
return new_spec;
|
||||
}
|
||||
|
||||
std::shared_ptr<LeafNode> TilingWindowTree::advise_new_window(miral::WindowInfo const& window_info)
|
||||
{
|
||||
auto node = get_active_lane()->confirm_window(window_info.window());
|
||||
if (window_helpers::is_window_fullscreen(window_info.state()))
|
||||
{
|
||||
tiling_interface.select_active_window(window_info.window());
|
||||
advise_fullscreen_window(window_info.window());
|
||||
}
|
||||
|
||||
return node;
|
||||
return get_active_lane()->confirm_window(window_info.window());
|
||||
}
|
||||
|
||||
bool TilingWindowTree::try_resize_active_window(miracle::Direction direction)
|
||||
|
@ -225,5 +225,9 @@ void WindowManagerToolsTilingInterface::on_animation(
|
||||
mir::geometry::Rectangle new_rectangle(
|
||||
{ spec.top_left().value().x.as_int(), spec.top_left().value().y.as_int() },
|
||||
{ scale.x, scale.y });
|
||||
clip(window, new_rectangle);
|
||||
|
||||
if (metadata->get_type() == WindowType::tiled)
|
||||
clip(window, new_rectangle);
|
||||
else
|
||||
noclip(window);
|
||||
}
|
@ -21,6 +21,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using namespace miracle;
|
||||
|
||||
WindowType miracle::window_type_from_string(std::string const& str)
|
||||
{
|
||||
if (str == "tiled")
|
||||
return WindowType::tiled;
|
||||
else if (str == "floating")
|
||||
return WindowType::floating;
|
||||
else if (str == "other")
|
||||
return WindowType::other;
|
||||
else
|
||||
return WindowType::none;
|
||||
}
|
||||
|
||||
WindowMetadata::WindowMetadata(WindowType type, miral::Window const& window) :
|
||||
WindowMetadata(type, window, nullptr)
|
||||
{
|
||||
|
@ -38,6 +38,8 @@ enum class WindowType
|
||||
other
|
||||
};
|
||||
|
||||
WindowType window_type_from_string(std::string const&);
|
||||
|
||||
/// Applied to WindowInfo to enable
|
||||
class WindowMetadata
|
||||
{
|
||||
|
@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "tiling_window_tree.h"
|
||||
#include "window_helpers.h"
|
||||
#include "window_metadata.h"
|
||||
#include "miracle_config.h"
|
||||
#include <mir/log.h>
|
||||
#include <mir/scene/surface.h>
|
||||
|
||||
@ -37,7 +38,8 @@ WorkspaceContent::WorkspaceContent(
|
||||
tools { tools },
|
||||
tree(std::make_shared<TilingWindowTree>(screen, node_interface, config)),
|
||||
workspace { workspace },
|
||||
node_interface{ node_interface}
|
||||
node_interface{ node_interface},
|
||||
config { config }
|
||||
{
|
||||
}
|
||||
|
||||
@ -51,6 +53,21 @@ std::shared_ptr<TilingWindowTree> const& WorkspaceContent::get_tree() const
|
||||
return tree;
|
||||
}
|
||||
|
||||
WindowType WorkspaceContent::allocate_position(miral::WindowSpecification& requested_specification)
|
||||
{
|
||||
auto layout = config->get_workspace_config(workspace).layout;
|
||||
switch (layout)
|
||||
{
|
||||
case WindowType::tiled:
|
||||
{
|
||||
requested_specification = tree->allocate_position(requested_specification);
|
||||
return WindowType::tiled;
|
||||
}
|
||||
default:
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
|
||||
void WorkspaceContent::show()
|
||||
{
|
||||
auto fullscreen_node = tree->show();
|
||||
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MIRACLEWM_WORKSPACE_CONTENT_H
|
||||
|
||||
#include "animator.h"
|
||||
#include "window_metadata.h"
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <miral/minimal_window_manager.h>
|
||||
@ -29,7 +30,6 @@ namespace miracle
|
||||
class OutputContent;
|
||||
class MiracleConfig;
|
||||
class TilingWindowTree;
|
||||
class WindowMetadata;
|
||||
class TilingInterface;
|
||||
|
||||
class WorkspaceContent
|
||||
@ -44,6 +44,7 @@ public:
|
||||
|
||||
[[nodiscard]] int get_workspace() const;
|
||||
[[nodiscard]] std::shared_ptr<TilingWindowTree> const& get_tree() const;
|
||||
WindowType allocate_position(miral::WindowSpecification& requested_specification);
|
||||
void show();
|
||||
void hide();
|
||||
void transfer_pinned_windows_to(std::shared_ptr<WorkspaceContent> const& other);
|
||||
@ -65,6 +66,7 @@ private:
|
||||
int workspace;
|
||||
std::vector<miral::Window> floating_windows;
|
||||
TilingInterface& node_interface;
|
||||
std::shared_ptr<MiracleConfig> config;
|
||||
};
|
||||
|
||||
} // miracle
|
||||
|
Loading…
Reference in New Issue
Block a user