Skip to content

Commit

Permalink
feat: Implement treeland_virtual_manager_v1 function
Browse files Browse the repository at this point in the history
Implementing Virtual Output
  • Loading branch information
Dami-star committed Jun 27, 2024
1 parent 21d47d0 commit e460e66
Show file tree
Hide file tree
Showing 13 changed files with 673 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ target_link_libraries(treeland
shortcut
wallpaper-color
window-management
virtual-output
)

target_compile_definitions(treeland
Expand Down
1 change: 1 addition & 0 deletions src/modules/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ add_subdirectory("personalization")
add_subdirectory("shortcut")
add_subdirectory("wallpaper-color")
add_subdirectory("window-management")
add_subdirectory("virtual-output")
40 changes: 40 additions & 0 deletions src/modules/virtual-output/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
set(MODULE_NAME virtual-output)

ws_generate_local(server ${CMAKE_CURRENT_SOURCE_DIR}/protocols/treeland-virtual-output-manager-v1.xml server-protocol)

pkg_search_module(WLROOTS REQUIRED IMPORTED_TARGET wlroots)

qt_add_library(${MODULE_NAME} STATIC)

target_sources(${MODULE_NAME} PUBLIC
FILE_SET HEADERS
FILES
virtualoutputmanager.h
impl/virtual_output_manager_impl.h
)

target_sources(${MODULE_NAME} PRIVATE
virtualoutputmanager.cpp
impl/virtual_output_manager_impl.cpp
server-protocol.c
)

target_include_directories(${MODULE_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)

target_compile_definitions(${MODULE_NAME}
PRIVATE
WLR_USE_UNSTABLE
)

target_link_libraries(${MODULE_NAME}
PUBLIC
utils
PkgConfig::WLROOTS
Waylib::WaylibServer
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::Gui
Qt${QT_MAJOR_VERSION}::Quick
)
217 changes: 217 additions & 0 deletions src/modules/virtual-output/impl/virtual_output_manager_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
// Copyright (C) 2024 Lu YaNing <[email protected]>.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "virtual_output_manager_impl.h"

#include <wayland-server-core.h>
#include <cassert>

#define TREELAND_VIRTUAL_OUTPUT_MANAGER_V1_VERSION 1

using QW_NAMESPACE::QWDisplay;

static treeland_virtual_output_manager_v1 *virtual_output_manager_from_resource(wl_resource *resource);
static void virtual_output_manager_bind(wl_client *client, void *data, uint32_t version, uint32_t id);

static void virtual_output_manager_handle_create_virtual_output([[maybe_unused]]struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id,
const char *name,
struct wl_array *outputs);

static void virtual_output_manager_handle_get_virtual_output_list([[maybe_unused]]struct wl_client *client, struct wl_resource *resource);

static void virtual_output_manager_handle_get_virtual_output([[maybe_unused]]struct wl_client *client,
struct wl_resource *resource,
const char *name,
uint32_t id);

static void virtual_output_handle_destroy([[maybe_unused]]struct wl_client *client,
struct wl_resource *resource);


static void virtual_output_handle_destroy([[maybe_unused]]struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy(resource);
}


static const struct virtual_output_v1_interface virtual_output_impl {
.destroy = virtual_output_handle_destroy,
};


static const struct virtual_output_manager_v1_interface virtual_output_manager_impl {
.create_virtual_output = virtual_output_manager_handle_create_virtual_output,
.get_virtual_output_list = virtual_output_manager_handle_get_virtual_output_list,
.get_virtual_output = virtual_output_manager_handle_get_virtual_output,
};

static void virtual_output_resource_destroy(struct wl_resource *resource)
{
wl_list_remove(wl_resource_get_link(resource));
}

static void virtual_output_manager_resource_destroy(struct wl_resource *resource)
{
wl_list_remove(wl_resource_get_link(resource));
}

static struct treeland_virtual_output_v1 *treeland_virtual_output_from_resource(wl_resource *resource)

Check warning on line 61 in src/modules/virtual-output/impl/virtual_output_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_virtual_output_from_resource' is never used.
{
assert(wl_resource_instance_of(resource,
&virtual_output_v1_interface,
&virtual_output_impl));
auto *manager = static_cast<treeland_virtual_output_v1 *>(wl_resource_get_user_data(resource));
assert(manager != nullptr);
return manager;
}

static treeland_virtual_output_manager_v1 *virtual_output_manager_from_resource(wl_resource *resource)
{
assert(wl_resource_instance_of(resource,
&virtual_output_manager_v1_interface,
&virtual_output_manager_impl));
auto *manager = static_cast<treeland_virtual_output_manager_v1 *>(wl_resource_get_user_data(resource));
assert(manager != nullptr);
return manager;
}

static void virtual_output_manager_handle_create_virtual_output([[maybe_unused]]struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id,
const char *name,
struct wl_array *outputs)
{
auto *manager = virtual_output_manager_from_resource(manager_resource);

auto *virtual_output = new treeland_virtual_output_v1;
if (virtual_output == nullptr) {
wl_resource_post_no_memory(manager_resource);
return;
}

uint32_t version = wl_resource_get_version(manager_resource);
struct wl_resource *resource =
wl_resource_create(client, &virtual_output_v1_interface, version, id);
if (resource == nullptr) {
delete virtual_output;
wl_resource_post_no_memory(manager_resource);
return;
}

wl_resource_set_implementation(resource,
&virtual_output_impl,
virtual_output,
virtual_output_resource_destroy);
wl_resource_set_user_data(resource, virtual_output);

virtual_output->manager = manager;
virtual_output->resource = resource;
virtual_output->name = name;
virtual_output->screen_outputs = outputs;

manager->virtual_output.append(virtual_output);
QObject::connect(virtual_output, &treeland_virtual_output_v1::beforeDestroy, manager, [manager, virtual_output]() {
manager->virtual_output.removeOne(virtual_output);
});

virtual_output->send_outputs(virtual_output->name, outputs);
Q_EMIT virtual_output->manager->virtualOutputCreated(virtual_output);
}

static void virtual_output_manager_handle_get_virtual_output_list([[maybe_unused]]struct wl_client *client, struct wl_resource *resource)
{
auto *manager = virtual_output_manager_from_resource(resource);

wl_array arr;
wl_array_init(&arr);
for(int i = 0; i < manager->virtual_output.size(); ++i) {
treeland_virtual_output_v1 *virtual_output = manager->virtual_output.at(i);
char *dest = static_cast<char *>(wl_array_add(&arr, virtual_output->name.length() + 1));
strncpy(dest, virtual_output->name.toLatin1().data(), static_cast<uint>(virtual_output->name.length()));
}

virtual_output_manager_v1_send_virtual_output_list(resource,&arr);
}

static void virtual_output_manager_handle_get_virtual_output([[maybe_unused]]struct wl_client *client,
struct wl_resource *resource,
const char *name,
uint32_t id)
{
auto *manager = virtual_output_manager_from_resource(resource);
for(int i = 0; i < manager->virtual_output.size(); ++i) {
treeland_virtual_output_v1 *virtual_output = manager->virtual_output.at(i);
if (virtual_output->name == name) {
virtual_output->send_outputs(name, virtual_output->screen_outputs);
}
}
}

void treeland_virtual_output_v1::send_outputs(QString name, struct wl_array *outputs)

Check warning on line 153 in src/modules/virtual-output/impl/virtual_output_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Parameter 'name' is passed by value. It could be passed as a const reference which is usually faster and recommended in C++.
{
virtual_output_v1_send_outputs(resource, name.toUtf8().data(), outputs);
}

void treeland_virtual_output_v1::send_error(uint32_t code, const char *message)

Check warning on line 158 in src/modules/virtual-output/impl/virtual_output_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'send_error' is never used.
{
virtual_output_v1_send_error(resource, code, message);
}

treeland_virtual_output_v1::~treeland_virtual_output_v1()
{
Q_EMIT beforeDestroy();
if (resource)
wl_resource_set_user_data(resource,nullptr);
}

treeland_virtual_output_manager_v1::~treeland_virtual_output_manager_v1()
{
Q_EMIT beforeDestroy();
if (global)
wl_global_destroy(global);
}

static void virtual_output_manager_bind(wl_client *client, void *data, uint32_t version, uint32_t id)
{
auto *manager = static_cast<treeland_virtual_output_manager_v1 *>(data);

struct wl_resource *resource =
wl_resource_create(client, &virtual_output_manager_v1_interface, version, id);
if (!resource) {
wl_client_post_no_memory(client);
return;
}

wl_resource_set_implementation(resource,
&virtual_output_manager_impl,
manager,
virtual_output_manager_resource_destroy);
wl_list_insert(&manager->resources, wl_resource_get_link(resource));
}

treeland_virtual_output_manager_v1 *treeland_virtual_output_manager_v1::create(QWDisplay *display)
{
auto *manager = new treeland_virtual_output_manager_v1;
if (!manager)
return nullptr;

manager->event_loop = wl_display_get_event_loop(display->handle());
manager->global = wl_global_create(display->handle(),
&virtual_output_manager_v1_interface,
TREELAND_VIRTUAL_OUTPUT_MANAGER_V1_VERSION,
manager,
virtual_output_manager_bind);
if (!manager->global) {
delete manager;
return nullptr;
}

wl_list_init(&manager->resources);

connect(display, &QWDisplay::beforeDestroy, manager, [manager] { delete manager; });

return manager;
}
50 changes: 50 additions & 0 deletions src/modules/virtual-output/impl/virtual_output_manager_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (C) 2024 Lu YaNing <[email protected]>.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#pragma once

#include "server-protocol.h"
#include <wayland-server-core.h>
#include <qwsignalconnector.h>
#include <qwdisplay.h>
#include <QObject>

#include <QList>
#include <QString>

struct treeland_virtual_output_v1;

struct treeland_virtual_output_manager_v1 : public QObject
{
Q_OBJECT
public:
~treeland_virtual_output_manager_v1();

wl_global *global{ nullptr };
wl_list resources;
wl_event_loop *event_loop{ nullptr };
QList<treeland_virtual_output_v1 *> virtual_output;

static treeland_virtual_output_manager_v1 *create(QW_NAMESPACE::QWDisplay *display);

Q_SIGNALS:
void virtualOutputCreated(treeland_virtual_output_v1 *virtual_output);
void beforeDestroy();
};

struct treeland_virtual_output_v1 : public QObject
{
Q_OBJECT
public:
~treeland_virtual_output_v1();
treeland_virtual_output_manager_v1 *manager{ nullptr };
wl_resource *resource{ nullptr };
QString name;
struct wl_array *screen_outputs;

void send_outputs(QString name, struct wl_array *outputs);
void send_error(uint32_t code, const char *message); // tode: send err code and message

Q_SIGNALS:
void beforeDestroy();
};
Loading

0 comments on commit e460e66

Please sign in to comment.