Skip to content

Commit

Permalink
Add support for wlr-output-management-v1
Browse files Browse the repository at this point in the history
  • Loading branch information
serebit committed Nov 3, 2023
1 parent 7fae4d4 commit e18d367
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 21 deletions.
4 changes: 2 additions & 2 deletions src/foreign_toplevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ void ForeignToplevelHandle::set_fullscreen(const bool fullscreen) {
}

void ForeignToplevelHandle::output_enter(const Output& output) {
wlr_foreign_toplevel_handle_v1_output_enter(&handle, output.output);
wlr_foreign_toplevel_handle_v1_output_enter(&handle, output.wlr);
}

void ForeignToplevelHandle::output_leave(const Output& output) {
wlr_foreign_toplevel_handle_v1_output_leave(&handle, output.output);
wlr_foreign_toplevel_handle_v1_output_leave(&handle, output.wlr);
}
14 changes: 7 additions & 7 deletions src/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ static void output_enable_notify(wl_listener* listener, void* data) {
Output& output = magpie_container_of(listener, output, enable);
(void) data;

output.scene_output = wlr_scene_get_scene_output(output.server.scene, output.output);
output.scene_output = wlr_scene_get_scene_output(output.server.scene, output.wlr);
}

/* This function is called every time an output is ready to display a frame,
Expand All @@ -32,12 +32,12 @@ static void output_frame_notify(wl_listener* listener, void* data) {
Output& output = magpie_container_of(listener, output, frame);
(void) data;

if (output.scene_output == nullptr || output.is_leased || !output.output->enabled) {
if (output.scene_output == nullptr || output.is_leased || !output.wlr->enabled) {
return;
}

wlr_scene* scene = output.server.scene;
wlr_scene_output* scene_output = wlr_scene_get_scene_output(scene, output.output);
wlr_scene_output* scene_output = wlr_scene_get_scene_output(scene, output.wlr);

/* Render the scene if needed and commit the output */
wlr_scene_output_commit(scene_output);
Expand All @@ -60,7 +60,7 @@ static void output_destroy_notify(wl_listener* listener, void* data) {
}

Output::Output(Server& server, wlr_output* output) noexcept : listeners(*this), server(server) {
this->output = output;
this->wlr = output;
output->data = this;

is_leased = false;
Expand All @@ -82,11 +82,11 @@ Output::~Output() noexcept {
}

void Output::update_layout() {
wlr_scene_output* scene_output = wlr_scene_get_scene_output(server.scene, output);
wlr_scene_output* scene_output = wlr_scene_get_scene_output(server.scene, wlr);

full_area.x = scene_output->x;
full_area.y = scene_output->y;
wlr_output_effective_resolution(output, &full_area.width, &full_area.height);
wlr_output_effective_resolution(wlr, &full_area.width, &full_area.height);

usable_area = full_area;

Expand All @@ -97,7 +97,7 @@ void Output::update_layout() {

wlr_box Output::usable_area_in_layout_coords() const {
double layout_x = 0, layout_y = 0;
wlr_output_layout_output_coords(server.output_layout, output, &layout_x, &layout_y);
wlr_output_layout_output_coords(server.output_layout, wlr, &layout_x, &layout_y);

wlr_box box = usable_area;
box.x += layout_x;
Expand Down
2 changes: 1 addition & 1 deletion src/output.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Output {

public:
Server& server;
wlr_output* output;
wlr_output* wlr;
wlr_scene_output* scene_output;
wlr_box full_area;
wlr_box usable_area;
Expand Down
97 changes: 91 additions & 6 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <wlr/types/wlr_xdg_foreign_registry.h>
#include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h>
#include <wlr/util/box.h>
#include <wlr/util/log.h>
#include "wlr-wrap-end.hpp"

void Server::focus_view(View& view, wlr_surface* surface) {
Expand Down Expand Up @@ -185,7 +187,7 @@ static void new_layer_surface_notify(wl_listener* listener, void* data) {
Output* output;
if (layer_surface.output == nullptr) {
output = static_cast<Output*>(wlr_output_layout_get_center_output(server.output_layout)->data);
layer_surface.output = output->output;
layer_surface.output = output->wlr;
} else {
output = static_cast<Output*>(layer_surface.output->data);
}
Expand Down Expand Up @@ -223,14 +225,92 @@ static void drm_lease_notify(wl_listener* listener, void* data) {
if (output == nullptr)
continue;

wlr_output_enable(output->output, false);
wlr_output_commit(output->output);
wlr_output_layout_remove(server.output_layout, output->output);
wlr_output_enable(output->wlr, false);
wlr_output_commit(output->wlr);
wlr_output_layout_remove(server.output_layout, output->wlr);
output->is_leased = true;
output->scene_output = nullptr;
}
}

void output_layout_change_notify(wl_listener* listener, void* data) {
Server& server = magpie_container_of(listener, server, output_layout_change);
(void) data;

if (server.num_pending_output_layout_changes > 0) {
return;
}

wlr_output_configuration_v1* config = wlr_output_configuration_v1_create();

for (auto* output : server.outputs) {
wlr_output_configuration_head_v1* head = wlr_output_configuration_head_v1_create(config, output->wlr);

wlr_box box;
wlr_output_layout_get_box(server.output_layout, output->wlr, &box);
if (!wlr_box_empty(&box)) {
head->state.x = box.x;
head->state.y = box.y;
}
}

wlr_output_manager_v1_set_configuration(server.output_manager, config);
}

void output_manager_apply_notify(wl_listener* listener, void* data) {
Server& server = magpie_container_of(listener, server, output_manager_apply);
auto& config = *static_cast<wlr_output_configuration_v1*>(data);

server.num_pending_output_layout_changes++;

wlr_output_configuration_head_v1* head;
wl_list_for_each(head, &config.heads, link) {
Output& output = *static_cast<Output*>(head->state.output->data);
bool enabled = head->state.enabled && !output.is_leased;
bool adding = enabled && !output.wlr->enabled;
bool removing = !enabled && output.wlr->enabled;

wlr_output_enable(output.wlr, enabled);
if (enabled) {
if (head->state.mode) {
wlr_output_set_mode(output.wlr, head->state.mode);
} else {
int32_t width = head->state.custom_mode.width;
int32_t height = head->state.custom_mode.height;
int32_t refresh = head->state.custom_mode.refresh;
wlr_output_set_custom_mode(output.wlr, width, height, refresh);
}

wlr_output_set_scale(output.wlr, head->state.scale);
wlr_output_set_transform(output.wlr, head->state.transform);
}

if (!wlr_output_commit(output.wlr)) {
wlr_log(WLR_ERROR, "Output config commit failed");
continue;
}

if (adding) {
wlr_output_layout_add_auto(server.output_layout, output.wlr);
output.scene_output = wlr_scene_get_scene_output(server.scene, output.wlr);
}

if (enabled) {
wlr_box box;
wlr_output_layout_get_box(server.output_layout, output.wlr, &box);
if (box.x != head->state.x || box.y != head->state.y) {
/* This overrides the automatic layout */
wlr_output_layout_move(server.output_layout, output.wlr, head->state.x, head->state.y);
}
}

if (removing) {
wlr_output_layout_remove(server.output_layout, output.wlr);
output.scene_output = nullptr;
}
}
}

Server::Server() : listeners(*this) {
/* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */
Expand Down Expand Up @@ -276,9 +356,14 @@ Server::Server() : listeners(*this) {
/* Creates an output layout, which a wlroots utility for working with an
* arrangement of screens in a physical layout. */
output_layout = wlr_output_layout_create();
assert(output_layout);
listeners.output_layout_change.notify = output_layout_change_notify;
wl_signal_add(&output_layout->events.change, &listeners.output_layout_change);

wlr_xdg_output_manager_v1_create(display, output_layout);

output_manager = wlr_xdg_output_manager_v1_create(display, output_layout);
output_manager = wlr_output_manager_v1_create(display);
listeners.output_manager_apply.notify = output_manager_apply_notify;
wl_signal_add(&output_manager->events.apply, &listeners.output_manager_apply);

output_power_manager = wlr_output_power_manager_v1_create(display);
listeners.output_power_manager_set_mode.notify = output_power_manager_set_mode_notify;
Expand Down
6 changes: 5 additions & 1 deletion src/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output_management_v1.h>
#include <wlr/types/wlr_output_power_management_v1.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_activation_v1.h>
Expand All @@ -39,6 +40,8 @@ class Server {
wl_listener activation_request_activation;
wl_listener backend_new_output;
wl_listener drm_lease_request;
wl_listener output_layout_change;
wl_listener output_manager_apply;
wl_listener output_power_manager_set_mode;
Listeners(Server& parent) noexcept : parent(parent) {}
};
Expand Down Expand Up @@ -75,10 +78,11 @@ class Server {
wlr_box grab_geobox;
uint32_t resize_edges;

wlr_xdg_output_manager_v1* output_manager;
wlr_output_manager_v1* output_manager;
wlr_output_power_manager_v1* output_power_manager;
wlr_output_layout* output_layout;
std::set<Output*> outputs;
uint8_t num_pending_output_layout_changes = 0;

wlr_idle_notifier_v1* idle_notifier;
wlr_idle_inhibit_manager_v1* idle_inhibit_manager;
Expand Down
8 changes: 4 additions & 4 deletions src/surface/view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ const std::optional<const Output*> View::find_output_for_maximize() {
long best_area = 0;

for (auto* output : server.outputs) {
if (!wlr_output_layout_intersects(server.output_layout, output->output, &previous)) {
if (!wlr_output_layout_intersects(server.output_layout, output->wlr, &previous)) {
continue;
}

wlr_box output_box;
wlr_output_layout_get_box(server.output_layout, output->output, &output_box);
wlr_output_layout_get_box(server.output_layout, output->wlr, &output_box);
wlr_box intersection;
wlr_box_intersection(&intersection, &previous, &output_box);
long intersection_area = intersection.width * intersection.height;
Expand All @@ -43,9 +43,9 @@ const std::optional<const Output*> View::find_output_for_maximize() {
}

// if it's outside of all outputs, just use the pointer position
if (best_output == NULL) {
if (best_output == nullptr) {
for (auto* output : server.outputs) {
if (wlr_output_layout_contains_point(server.output_layout, output->output, cursor.cursor->x, cursor.cursor->y)) {
if (wlr_output_layout_contains_point(server.output_layout, output->wlr, cursor.cursor->x, cursor.cursor->y)) {
best_output = output;
break;
}
Expand Down

0 comments on commit e18d367

Please sign in to comment.