-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: impl treeland output management
Log: primary output setting
- Loading branch information
Showing
14 changed files
with
300 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<protocol name="treeland_output_manager_v1"> | ||
<copyright><![CDATA[ | ||
SPDX-FileCopyrightText: 2023 rewine <[email protected]>. | ||
SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | ||
]]></copyright> | ||
|
||
<interface name="treeland_output_manager_v1" version="1"> | ||
<description summary="expose which is the primary display"> | ||
Protocol for telling which is the primary display among the selection of enabled outputs. | ||
</description> | ||
|
||
<request name="set_primary_output" since="1"> | ||
<description summary="Select which primary output to use" /> | ||
<arg name="output" type="string" allow-null="false"/> | ||
</request> | ||
|
||
<event name="primary_output"> | ||
<description summary="Provide the current primary output's name"> | ||
Specifies which output is the primary one identified by their name. | ||
</description> | ||
<arg name="output_name" type="string" summary="the name of the output"/> | ||
</event> | ||
|
||
<request name="destroy" type="destructor" since="1"> | ||
<description summary="Destroy the primary output notifier."/> | ||
</request> | ||
</interface> | ||
|
||
</protocol> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copyright (C) 2023 rewine <[email protected]>. | ||
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | ||
|
||
#include "output_manager_impl.h" | ||
#include "utils.h" | ||
|
||
#include <wayland-server-core.h> | ||
#include <cassert> | ||
|
||
void output_manager_handle_set_primary_output([[maybe_unused]]struct wl_client *client, | ||
struct wl_resource *resource, | ||
const char *output) { | ||
auto *manager = output_manager_from_resource(resource); | ||
wl_signal_emit(&manager->events.set_primary_output, &output); | ||
} | ||
|
||
static const struct treeland_output_manager_v1_interface output_manager_impl { | ||
.set_primary_output = output_manager_handle_set_primary_output, | ||
.destroy = resource_handle_destroy, | ||
}; | ||
|
||
struct treeland_output_manager_v1 *treeland_output_manager_v1_create(struct wl_display *display) | ||
{ | ||
auto *manager = static_cast<treeland_output_manager_v1*>(calloc(1, sizeof(treeland_output_manager_v1))); | ||
if (manager == nullptr) { | ||
return nullptr; | ||
} | ||
manager->global = wl_global_create( | ||
display, &treeland_output_manager_v1_interface, | ||
TREELAND_OUTPUT_MANAGER_V1_VERSION, manager, output_manager_bind); | ||
|
||
wl_list_init(&manager->resources); | ||
wl_signal_init(&manager->events.set_primary_output); | ||
|
||
manager->display_destroy.notify = output_manager_handle_display_destroy; | ||
wl_display_add_destroy_listener(display, | ||
&manager->display_destroy); | ||
return manager; | ||
} | ||
|
||
void treeland_output_manager_v1_set_primary_output(treeland_output_manager_v1 *manager, const char *name) | ||
{ | ||
manager->primary_output_name = name; | ||
wl_resource *resource; | ||
wl_list_for_each(resource, &manager->resources, link) { | ||
treeland_output_manager_v1_send_primary_output(resource, name); | ||
} | ||
} | ||
|
||
struct treeland_output_manager_v1 *output_manager_from_resource( | ||
struct wl_resource *resource) { | ||
assert(wl_resource_instance_of(resource, &treeland_output_manager_v1_interface, &output_manager_impl)); | ||
struct treeland_output_manager_v1 *manager = static_cast<treeland_output_manager_v1*>(wl_resource_get_user_data(resource)); | ||
assert(manager != NULL); | ||
return manager; | ||
} | ||
|
||
void output_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { | ||
struct treeland_output_manager_v1 *manager = static_cast<treeland_output_manager_v1*>(data); | ||
|
||
struct wl_resource *resource = wl_resource_create(client, &treeland_output_manager_v1_interface, version, id); | ||
if (!resource) { | ||
wl_client_post_no_memory(client); | ||
return; | ||
} | ||
wl_resource_set_implementation(resource, &output_manager_impl, manager, NULL); | ||
wl_list_insert(&manager->resources, wl_resource_get_link(resource)); | ||
|
||
treeland_output_manager_v1_send_primary_output(resource, manager->primary_output_name); | ||
} | ||
|
||
void output_manager_handle_display_destroy(struct wl_listener *listener, [[maybe_unused]] void *data) | ||
{ | ||
struct treeland_output_manager_v1 *manager = | ||
wl_container_of(listener, manager, display_destroy); | ||
|
||
wl_global_destroy(manager->global); | ||
wl_list_remove(&manager->display_destroy.link); | ||
free(manager); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright (C) 2023 rewine <[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 "output-management-protocol.h" | ||
|
||
#define TREELAND_OUTPUT_MANAGER_V1_VERSION 1 | ||
|
||
struct treeland_output_manager_v1 { | ||
struct wl_global *global; | ||
struct wl_list resources; | ||
|
||
struct { | ||
struct wl_signal set_primary_output; | ||
} events; | ||
|
||
const char *primary_output_name { nullptr }; | ||
|
||
struct wl_listener display_destroy; | ||
}; | ||
|
||
struct treeland_output_manager_v1 *treeland_output_manager_v1_create( | ||
struct wl_display *display); | ||
|
||
void treeland_output_manager_v1_set_primary_output( | ||
struct treeland_output_manager_v1 *manager, | ||
const char *name); | ||
|
||
struct treeland_output_manager_v1 *output_manager_from_resource( | ||
struct wl_resource *resource); | ||
|
||
void output_manager_bind(struct wl_client *client, | ||
void *data, | ||
uint32_t version, | ||
uint32_t id); | ||
|
||
void output_manager_handle_display_destroy(struct wl_listener *listener, | ||
void *data); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright (C) 2023 rewine <[email protected]>. | ||
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | ||
|
||
#include "outputmanagement.h" | ||
#include "output_manager_impl.h" | ||
|
||
#include <qwdisplay.h> | ||
#include <wserver.h> | ||
#include <woutput.h> | ||
|
||
#include <QQmlInfo> | ||
#include <QDebug> | ||
|
||
extern "C" { | ||
#include <wayland-server-core.h> | ||
} | ||
|
||
TreelandOutputManager::TreelandOutputManager(QObject *parent) | ||
: Waylib::Server::WQuickWaylandServerInterface(parent) | ||
{ | ||
|
||
} | ||
|
||
void TreelandOutputManager::on_set_primary_output(void *data) | ||
{ | ||
const char *name = *(static_cast<const char **>(data)); | ||
Q_EMIT requestSetPrimaryOutput(name); | ||
} | ||
|
||
const char *TreelandOutputManager::primaryOutput() | ||
{ | ||
return m_handle->primary_output_name; | ||
} | ||
|
||
bool TreelandOutputManager::setPrimaryOutput(const char *name) | ||
{ | ||
if (name == nullptr) { | ||
if (m_outputs.empty()) { // allow null when output list is empty | ||
treeland_output_manager_v1_set_primary_output(m_handle, nullptr); | ||
Q_EMIT primaryOutputChanged(); | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
if (m_handle->primary_output_name != nullptr && strcmp(m_handle->primary_output_name, name) == 0) | ||
return true; | ||
for (auto *output : m_outputs) | ||
if (strcmp(output->nativeHandle()->name, name) == 0) { | ||
treeland_output_manager_v1_set_primary_output(m_handle, output->nativeHandle()->name); | ||
Q_EMIT primaryOutputChanged(); | ||
return true; | ||
} | ||
qmlWarning(this) << QString("Try to set unknown output(%1) as primary output!").arg(name); | ||
return false; | ||
} | ||
|
||
void TreelandOutputManager::newOutput(WAYLIB_SERVER_NAMESPACE::WOutput *output) | ||
{ | ||
m_outputs.append(output); | ||
if (m_handle->primary_output_name == nullptr) | ||
setPrimaryOutput(output->nativeHandle()->name); | ||
} | ||
|
||
void TreelandOutputManager::removeOutput(WAYLIB_SERVER_NAMESPACE::WOutput *output) | ||
{ | ||
m_outputs.removeOne(output); | ||
|
||
if (m_handle->primary_output_name == output->nativeHandle()->name) { | ||
if (m_outputs.isEmpty()) { | ||
setPrimaryOutput(nullptr); | ||
} else { | ||
setPrimaryOutput(m_outputs.first()->nativeHandle()->name); | ||
} | ||
} | ||
} | ||
|
||
void TreelandOutputManager::create() | ||
{ | ||
m_handle = treeland_output_manager_v1_create(server()->handle()->handle()); | ||
|
||
m_sc.connect(&m_handle->events.set_primary_output, this, &TreelandOutputManager::on_set_primary_output); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright (C) 2023 rewine <[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 <qwsignalconnector.h> | ||
#include <wquickwaylandserver.h> | ||
|
||
#include <QList> | ||
#include <QQmlEngine> | ||
|
||
struct treeland_output_manager_v1; | ||
|
||
WAYLIB_SERVER_BEGIN_NAMESPACE | ||
class WOutput; | ||
WAYLIB_SERVER_END_NAMESPACE | ||
|
||
class TreelandOutputManager : public Waylib::Server::WQuickWaylandServerInterface { | ||
Q_OBJECT | ||
QML_ELEMENT | ||
Q_PROPERTY(const char *primaryOutput READ primaryOutput WRITE setPrimaryOutput NOTIFY primaryOutputChanged) | ||
|
||
public: | ||
explicit TreelandOutputManager(QObject *parent = nullptr); | ||
|
||
const char *primaryOutput(); | ||
bool setPrimaryOutput(const char *name); | ||
Q_INVOKABLE void newOutput(WAYLIB_SERVER_NAMESPACE::WOutput *output); | ||
Q_INVOKABLE void removeOutput(WAYLIB_SERVER_NAMESPACE::WOutput *output); | ||
|
||
public Q_SLOTS: | ||
void on_set_primary_output(void *data); | ||
|
||
protected: | ||
void create() override; | ||
|
||
Q_SIGNALS: | ||
void requestSetPrimaryOutput(const char *); | ||
void primaryOutputChanged(); | ||
|
||
private: | ||
treeland_output_manager_v1 *m_handle { nullptr }; | ||
QList<WAYLIB_SERVER_NAMESPACE::WOutput*> m_outputs; | ||
QW_NAMESPACE::QWSignalConnector m_sc; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.