feat: add personalization cursor

Signed-off-by: pengwenhao <pengwenhao@uniontech.com>
This commit is contained in:
pengwenhao 2024-05-30 16:12:49 +08:00 committed by groveer
parent 58edf5c716
commit db4bbf1cd5
13 changed files with 838 additions and 43 deletions

View File

@ -3,5 +3,10 @@ install(FILES
DESTINATION "${CMAKE_INSTALL_DATADIR}/dbus-1/system.d"
)
install(FILES
"dconfig/org.deepin.Treeland.json"
DESTINATION "${CMAKE_INSTALL_DATADIR}/dsg/configs/org.deepin.Treeland"
)
add_subdirectory(systemd)
add_subdirectory(wayland-sessions)

View File

@ -0,0 +1,160 @@
{
"magic": "dsg.config.meta",
"version": "1.0",
"contents": {
"ShowOnLock": {
"value": false,
"serial": 0,
"flags": ["user-public"],
"name": "ShowOnLock",
"name[zh_CN]": "显示在锁屏之上",
"description": "Allow show context on lock screen",
"description[zh_CN]": "允许在锁屏界面上显示内容",
"permissions": "readwrite",
"visibility": "private"
},
"LostScreen": {
"value": "MoveToPrimary",
"serial": 0,
"flags": ["user-public"],
"name": "Behaivor when lost screen",
"name[zh_CN]": "丢失屏幕的行为",
"description": "Behaivor when lost screen, allow value: MoveToPrimary、Minimize",
"description[zh_CN]": "丢失屏幕的行为可选值为MoveToPrimary、Minimize",
"permissions": "readwrite",
"visibility": "private"
},
"Font": {
"value": "",
"serial": 0,
"flags": ["user-public"],
"name": "Font",
"name[zh_CN]": "字体",
"description": "Font Family",
"description[zh_CN]": "字体",
"permissions": "readwrite",
"visibility": "private"
},
"FontSize": {
"value": 14,
"serial": 0,
"flags": ["user-public"],
"name": "Font Size",
"name[zh_CN]": "字体大小",
"description": "Font Size",
"description[zh_CN]": "字体大小",
"permissions": "readwrite",
"visibility": "private"
},
"PreferDark": {
"value": false,
"serial": 0,
"flags": ["user-public"],
"name": "Prefer Dark",
"name[zh_CN]": "倾向暗色",
"description": "Color scheme is prefer dark",
"description[zh_CN]": "颜色方案是否倾向暗色",
"permissions": "readwrite",
"visibility": "private"
},
"ThemeName": {
"value": "",
"serial": 0,
"flags": ["user-public"],
"name": "Theme Name",
"name[zh_CN]": "主题名称",
"description": "Theme Name",
"description[zh_CN]": "主题名称",
"permissions": "readwrite",
"visibility": "private"
},
"IconThemeName": {
"value": "",
"serial": 0,
"flags": ["user-public"],
"name": "Icon Theme Name",
"name[zh_CN]": "图标主题名称",
"description": "Icon Theme Name",
"description[zh_CN]": "图标主题名称",
"permissions": "readwrite",
"visibility": "private"
},
"CursorThemeName": {
"value": "",
"serial": 0,
"flags": ["user-public"],
"name": "Cursor Theme Name",
"name[zh_CN]": "光标主题名称",
"description": "Cursor Theme Name",
"description[zh_CN]": "光标主题名称",
"permissions": "readwrite",
"visibility": "private"
},
"CursorSize": {
"value": "",
"serial": 0,
"flags": ["user-public"],
"name": "Cursor Size",
"name[zh_CN]": "光标大小",
"description": "Cursor Size",
"description[zh_CN]": "光标大小",
"permissions": "readwrite",
"visibility": "private"
},
"CursorBlink": {
"value": true,
"serial": 0,
"flags": ["user-public"],
"name": "Cursor Blink",
"name[zh_CN]": "光标闪烁",
"description": "Whether the cursor should blink",
"description[zh_CN]": "光标是否应闪烁",
"permissions": "readwrite",
"visibility": "private"
},
"CursorBlinkTime": {
"value": 1200,
"serial": 0,
"flags": ["user-public"],
"name": "Cursor Blink Time",
"name[zh_CN]": "光标闪烁时间",
"description": "Length of the cursor blink cycle, in milleseconds",
"description[zh_CN]": "光标闪烁周期的长度,以千秒为单位",
"permissions": "readwrite",
"visibility": "private"
},
"DoubleClickTime": {
"value": 250,
"serial": 0,
"flags": ["user-public"],
"name": "Double Click Time",
"name[zh_CN]": "双击时间",
"description": "Maximum time allowed between two clicks for them to be considered a double click (in milliseconds)",
"description[zh_CN]": "两次单击之间允许被视为双击的最长时间(以毫秒为单位)",
"permissions": "readwrite",
"visibility": "private"
},
"DoubleClickDistance": {
"value": 5,
"serial": 0,
"flags": ["user-public"],
"name": "Double Click Distance",
"name[zh_CN]": "双击距离",
"description": "Maximum distance allowed between two clicks for them to be considered a double click (in pixels)",
"description[zh_CN]": "两次单击之间允许被视为双击的最大距离(以像素为单位)",
"permissions": "readwrite",
"visibility": "private"
},
"DndDragThreshold": {
"value": 8,
"serial": 0,
"flags": ["user-public"],
"name": "Dnd Drag Threshold",
"name[zh_CN]": "拖动阈值",
"description": "Number of pixels the cursor can move before dragging",
"description[zh_CN]": "拖动之前光标可以移动的像素数",
"permissions": "readwrite",
"visibility": "private"
}
}
}

View File

@ -4,6 +4,7 @@ ws_generate_local(server ${CMAKE_CURRENT_SOURCE_DIR}/protocols/treeland-personal
ws_generate(server wayland-protocols stable/xdg-shell/xdg-shell.xml xdg-shell-protocol)
pkg_search_module(WLROOTS REQUIRED IMPORTED_TARGET wlroots)
find_package(Dtk6Core REQUIRED)
set(MODULE_URI "PersonalizationManager")
@ -30,6 +31,7 @@ target_sources(${MODULE_NAME} PRIVATE
impl/personalization_manager_impl.cpp
impl/personalizationwindowcontext.cpp
impl/personalizationwallpapercontext.cpp
impl/personalizationcursorcontext.cpp
impl/personalizationmanager.cpp
server-protocol.c
xdg-shell-protocol.c
@ -53,4 +55,5 @@ target_link_libraries(${MODULE_NAME}
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::Gui
Qt${QT_MAJOR_VERSION}::Quick
)
Dtk6::Core
)

View File

@ -18,8 +18,8 @@ extern "C" {
#define TREELAND_PERSONALIZATION_MANAGEMENT_V1_VERSION 1
struct personalization_window_context_v1 *personalization_window_from_resource(
struct wl_resource *resource);
static void personalization_window_context_set_background_type(
[[maybe_unused]] struct wl_client *client, struct wl_resource *resource, uint32_t type);
static void personalization_window_context_destroy([[maybe_unused]] struct wl_client *client,
struct wl_resource *resource)
@ -27,24 +27,11 @@ static void personalization_window_context_destroy([[maybe_unused]] struct wl_cl
wl_resource_destroy(resource);
}
static void personalization_window_context_set_background_type(
[[maybe_unused]] struct wl_client *client, struct wl_resource *resource, uint32_t type)
{
struct personalization_window_context_v1 *window =
personalization_window_from_resource(resource);
if (!window) {
return;
}
window->background_type = type;
wl_signal_emit_mutable(&window->events.set_background_type, window);
}
static const struct personalization_window_context_v1_interface
personalization_window_context_impl = {
.set_background_type = personalization_window_context_set_background_type,
.destroy = personalization_window_context_destroy,
};
personalization_window_context_impl = {
.set_background_type = personalization_window_context_set_background_type,
.destroy = personalization_window_context_destroy,
};
struct personalization_window_context_v1 *personalization_window_from_resource(
struct wl_resource *resource)
@ -56,11 +43,6 @@ struct personalization_window_context_v1 *personalization_window_from_resource(
wl_resource_get_user_data(resource));
}
static void personalization_wallpaper_context_destroy([[maybe_unused]] struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
void personalization_window_context_v1_destroy(struct personalization_window_context_v1 *window)
{
@ -80,6 +62,19 @@ static void personalization_window_context_resource_destroy(struct wl_resource *
wl_list_remove(wl_resource_get_link(resource));
}
static void personalization_window_context_set_background_type(
[[maybe_unused]] struct wl_client *client, struct wl_resource *resource, uint32_t type)
{
struct personalization_window_context_v1 *window =
personalization_window_from_resource(resource);
if (!window) {
return;
}
window->background_type = type;
wl_signal_emit_mutable(&window->events.set_background_type, window);
}
void get_metadata(struct wl_client *client, struct wl_resource *manager_resource);
void set_fd(struct wl_client *client,
@ -93,7 +88,13 @@ void set_output(struct wl_client *client, struct wl_resource *resource, const ch
void set_on(struct wl_client *client, struct wl_resource *resource, uint32_t options);
void commit(struct wl_client *client, struct wl_resource *resource);
void wallpaper_commit(struct wl_client *client, struct wl_resource *resource);
static void personalization_wallpaper_context_destroy([[maybe_unused]] struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static const struct personalization_wallpaper_context_v1_interface
personalization_wallpaper_context_impl = {
@ -101,7 +102,7 @@ static const struct personalization_wallpaper_context_v1_interface
.set_identifier = set_identifier,
.set_output = set_output,
.set_on = set_on,
.commit = commit,
.commit = wallpaper_commit,
.get_metadata = get_metadata,
.destroy = personalization_wallpaper_context_destroy,
};
@ -135,6 +136,59 @@ static void personalization_wallpaper_context_resource_destroy(struct wl_resourc
wl_list_remove(wl_resource_get_link(resource));
}
void set_cursor_theme(struct wl_client *client, struct wl_resource *resource, const char *name);
void get_cursor_theme(struct wl_client *client, struct wl_resource *resource);
void set_cursor_size(struct wl_client *client, struct wl_resource *resource, uint32_t size);
void get_cursor_size(struct wl_client *client, struct wl_resource *resource);
void cursor_commit(struct wl_client *client, struct wl_resource *resource);
static void personalization_cursor_context_destroy([[maybe_unused]] struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static const struct personalization_cursor_context_v1_interface personalization_cursor_context_impl = {
.set_theme = set_cursor_theme,
.get_theme = get_cursor_theme,
.set_size = set_cursor_size,
.get_size = get_cursor_size,
.commit = cursor_commit,
.destroy = personalization_cursor_context_destroy,
};
struct personalization_cursor_context_v1 *personalization_cursor_from_resource(
struct wl_resource *resource)
{
assert(wl_resource_instance_of(resource,
&personalization_cursor_context_v1_interface,
&personalization_cursor_context_impl));
return static_cast<struct personalization_cursor_context_v1 *>(
wl_resource_get_user_data(resource));
}
void personalization_cursor_context_v1_destroy(personalization_cursor_context_v1 *cursor)
{
if (!cursor) {
return;
}
wl_signal_emit_mutable(&cursor->events.destroy, cursor);
wl_list_remove(&cursor->link);
free(cursor);
}
static void personalization_cursor_context_resource_destroy(struct wl_resource *resource)
{
wl_list_remove(wl_resource_get_link(resource));
}
void create_personalization_window_context_listener(struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id,
@ -144,10 +198,15 @@ void create_personalization_wallpaper_context_listener(struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id);
void create_personalization_cursor_context_listener(struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id);
static const struct treeland_personalization_manager_v1_interface
treeland_personalization_manager_impl = {
.get_window_context = create_personalization_window_context_listener,
.get_wallpaper_context = create_personalization_wallpaper_context_listener,
.get_cursor_context = create_personalization_cursor_context_listener,
};
struct treeland_personalization_manager_v1 *treeland_personalization_manager_from_resource(
@ -258,6 +317,51 @@ void create_personalization_wallpaper_context_listener(struct wl_client *client,
wl_signal_emit_mutable(&manager->events.wallpaper_context_created, context);
}
void create_personalization_cursor_context_listener(struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id)
{
struct treeland_personalization_manager_v1 *manager =
treeland_personalization_manager_from_resource(manager_resource);
if (manager == NULL)
return;
struct personalization_cursor_context_v1 *context =
static_cast<personalization_cursor_context_v1 *>(calloc(1, sizeof(*context)));
if (context == NULL) {
wl_resource_post_no_memory(manager_resource);
return;
}
context->manager = manager;
wl_list_init(&context->link);
wl_signal_init(&context->events.commit);
wl_signal_init(&context->events.get_size);
wl_signal_init(&context->events.get_theme);
wl_signal_init(&context->events.destroy);
uint32_t version = wl_resource_get_version(manager_resource);
struct wl_resource *resource =
wl_resource_create(client, &personalization_cursor_context_v1_interface, version, id);
if (resource == NULL) {
free(context);
wl_resource_post_no_memory(manager_resource);
return;
}
context->resource = resource;
wl_resource_set_implementation(resource,
&personalization_cursor_context_impl,
context,
personalization_cursor_context_resource_destroy);
wl_list_insert(&manager->resources, wl_resource_get_link(resource));
wl_signal_emit_mutable(&manager->events.cursor_context_created, context);
}
void set_fd(struct wl_client *client [[maybe_unused]],
struct wl_resource *resource,
int32_t fd,
@ -306,7 +410,8 @@ void set_on(struct wl_client *client [[maybe_unused]],
wallpaper->options = options;
}
void commit(struct wl_client *client [[maybe_unused]], struct wl_resource *resource)
void wallpaper_commit(struct wl_client *client [[maybe_unused]],
struct wl_resource *resource)
{
struct personalization_wallpaper_context_v1 *wallpaper =
personalization_wallpaper_from_resource(resource);
@ -326,6 +431,53 @@ void get_metadata(struct wl_client *client [[maybe_unused]], struct wl_resource
wl_signal_emit_mutable(&wallpaper->events.get_wallpapers, wallpaper);
}
void set_cursor_theme(struct wl_client *client, struct wl_resource *resource, const char *name)
{
struct personalization_cursor_context_v1 *cursor =
personalization_cursor_from_resource(resource);
if (cursor == NULL)
return;
cursor->theme = strdup(name);
}
void get_cursor_theme(struct wl_client *client, struct wl_resource *resource)
{
struct personalization_cursor_context_v1 *cursor = personalization_cursor_from_resource(resource);
if(cursor == NULL)
return;
wl_signal_emit_mutable(&cursor->events.get_theme, cursor);
}
void set_cursor_size(struct wl_client *client, struct wl_resource *resource, uint32_t size)
{
struct personalization_cursor_context_v1 *cursor =
personalization_cursor_from_resource(resource);
if (cursor == NULL)
return;
cursor->size = size;
}
void get_cursor_size(struct wl_client *client, struct wl_resource *resource)
{
struct personalization_cursor_context_v1 *cursor = personalization_cursor_from_resource(resource);
if(cursor == NULL)
return;
wl_signal_emit_mutable(&cursor->events.get_size, cursor);
}
void cursor_commit(struct wl_client *client, struct wl_resource *resource)
{
struct personalization_cursor_context_v1 *cursor = personalization_cursor_from_resource(resource);
if(cursor == NULL)
return;
wl_signal_emit_mutable(&cursor->events.commit, cursor);
}
static void treeland_personalization_manager_bind(struct wl_client *client,
void *data,
uint32_t version,
@ -380,6 +532,7 @@ struct treeland_personalization_manager_v1 *treeland_personalization_manager_v1_
wl_signal_init(&manager->events.destroy);
wl_signal_init(&manager->events.window_context_created);
wl_signal_init(&manager->events.wallpaper_context_created);
wl_signal_init(&manager->events.cursor_context_created);
wl_list_init(&manager->resources);
manager->display_destroy.notify = handle_display_destroy;

View File

@ -19,6 +19,7 @@ struct treeland_personalization_manager_v1
{
struct wl_signal window_context_created;
struct wl_signal wallpaper_context_created;
struct wl_signal cursor_context_created;
struct wl_signal destroy;
} events;
@ -64,9 +65,29 @@ struct personalization_wallpaper_context_v1
void *data;
};
struct personalization_cursor_context_v1
{
struct treeland_personalization_manager_v1 *manager;
struct wl_list link;
struct wl_resource *resource;
bool verfity;
uint32_t size;
const char* theme;
struct {
struct wl_signal commit;
struct wl_signal get_theme;
struct wl_signal get_size;
struct wl_signal destroy;
} events;
void *data;
};
struct treeland_personalization_manager_v1 *treeland_personalization_manager_v1_create(
struct wl_display *display);
void personalization_window_context_v1_destroy(struct personalization_window_context_v1 *window);
void personalization_wallpaper_context_v1_destroy(
struct personalization_wallpaper_context_v1 *wallpaper);
void personalization_wallpaper_context_v1_destroy(personalization_wallpaper_context_v1 *wallpaper);
void personalization_window_context_v1_destroy(personalization_window_context_v1 *window);
void personalization_cursor_context_v1_destroy(personalization_cursor_context_v1 *cursor);

View File

@ -0,0 +1,113 @@
// Copyright (C) 2024 WenHao Peng <pengwenhao@uniontech.com>.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "personalization_manager_impl.h"
#include "personalizationmanager.h"
#include <qwglobal.h>
#include <qwoutput.h>
#include <qwsignalconnector.h>
#include <QHash>
QW_USE_NAMESPACE
class PersonalizationCursorContextPrivate : public QWObjectPrivate
{
public:
PersonalizationCursorContextPrivate(personalization_cursor_context_v1 *handle,
bool isOwner,
PersonalizationCursorContext *qq)
: QWObjectPrivate(handle, isOwner, qq)
{
Q_ASSERT(!map.contains(handle));
map.insert(handle, qq);
sc.connect(&handle->events.destroy, this, &PersonalizationCursorContextPrivate::on_destroy);
sc.connect(&handle->events.commit, this,
&PersonalizationCursorContextPrivate::on_commit);
sc.connect(&handle->events.get_size, this,
&PersonalizationCursorContextPrivate::on_get_size);
sc.connect(&handle->events.get_theme, this,
&PersonalizationCursorContextPrivate::on_get_theme);
}
~PersonalizationCursorContextPrivate()
{
if (!m_handle)
return;
destroy();
if (isHandleOwner)
personalization_cursor_context_v1_destroy(q_func()->handle());
}
inline void destroy()
{
Q_ASSERT(m_handle);
Q_ASSERT(map.contains(m_handle));
Q_EMIT q_func()->beforeDestroy(q_func());
map.remove(m_handle);
sc.invalidate();
}
void on_destroy(void *);
void on_commit(void *);
void on_get_size(void *);
void on_get_theme(void *);
static QHash<void *, PersonalizationCursorContext *> map;
QW_DECLARE_PUBLIC(PersonalizationCursorContext)
QWSignalConnector sc;
};
QHash<void *, PersonalizationCursorContext *> PersonalizationCursorContextPrivate::map;
void PersonalizationCursorContextPrivate::on_destroy(void *)
{
destroy();
m_handle = nullptr;
delete q_func();
}
void PersonalizationCursorContextPrivate::on_commit(void *data)
{
Q_EMIT q_func()->commit(reinterpret_cast<personalization_cursor_context_v1*>(data));
}
void PersonalizationCursorContextPrivate::on_get_size(void *data)
{
Q_EMIT q_func()->get_size(reinterpret_cast<personalization_cursor_context_v1*>(data));
}
void PersonalizationCursorContextPrivate::on_get_theme(void *data)
{
Q_EMIT q_func()->get_theme(reinterpret_cast<personalization_cursor_context_v1*>(data));
}
PersonalizationCursorContext::PersonalizationCursorContext(
personalization_cursor_context_v1 *handle, bool isOwner)
: QObject(nullptr)
, QWObject(*new PersonalizationCursorContextPrivate(handle, isOwner, this))
{
}
PersonalizationCursorContext *PersonalizationCursorContext::get(
personalization_cursor_context_v1 *handle)
{
return PersonalizationCursorContextPrivate::map.value(handle);
}
PersonalizationCursorContext *PersonalizationCursorContext::from(
personalization_cursor_context_v1 *handle)
{
if (auto o = get(handle))
return o;
return new PersonalizationCursorContext(handle, false);
}
PersonalizationCursorContext *PersonalizationCursorContext::create(
personalization_cursor_context_v1 *handle)
{
if (!handle)
return nullptr;
return new PersonalizationCursorContext(handle, true);
}

View File

@ -32,6 +32,9 @@ public:
sc.connect(&handle->events.wallpaper_context_created,
this,
&TreeLandPersonalizationManagerPrivate::on_wallpaper_context_created);
sc.connect(&handle->events.cursor_context_created,
this,
&TreeLandPersonalizationManagerPrivate::on_cursor_context_created);
}
~TreeLandPersonalizationManagerPrivate()
@ -53,6 +56,7 @@ public:
void on_destroy(void *);
void on_window_context_created(void *);
void on_wallpaper_context_created(void *);
void on_cursor_context_created(void *);
static QHash<void *, TreeLandPersonalizationManager *> map;
QW_DECLARE_PUBLIC(TreeLandPersonalizationManager)
@ -82,6 +86,13 @@ void TreeLandPersonalizationManagerPrivate::on_wallpaper_context_created(void *d
}
}
void TreeLandPersonalizationManagerPrivate::on_cursor_context_created(void *data)
{
if (auto *p = reinterpret_cast<personalization_cursor_context_v1 *>(data)) {
Q_EMIT q_func()->cursorContextCreated(PersonalizationCursorContext::from(p));
}
}
TreeLandPersonalizationManager::TreeLandPersonalizationManager(
treeland_personalization_manager_v1 *handle, bool isOwner)
: QObject(nullptr)

View File

@ -7,9 +7,10 @@
#include <QObject>
struct personalization_window_context_v1;
struct treeland_personalization_manager_v1;
struct personalization_wallpaper_context_v1;
struct personalization_window_context_v1;
struct personalization_cursor_context_v1;
QW_USE_NAMESPACE
@ -20,6 +21,7 @@ QW_END_NAMESPACE
class TreeLandPersonalizationManager;
class PersonalizationWindowContext;
class PersonalizationWallpaperContext;
class PersonalizationCursorContext;
class TreeLandPersonalizationManagerPrivate;
class QW_EXPORT TreeLandPersonalizationManager : public QObject, public QWObject
@ -40,6 +42,7 @@ Q_SIGNALS:
void beforeDestroy(TreeLandPersonalizationManager *self);
void windowContextCreated(PersonalizationWindowContext *context);
void wallpaperContextCreated(PersonalizationWallpaperContext *context);
void cursorContextCreated(PersonalizationCursorContext *context);
private:
TreeLandPersonalizationManager(treeland_personalization_manager_v1 *handle, bool isOwner);
@ -98,3 +101,32 @@ Q_SIGNALS:
private:
PersonalizationWallpaperContext(personalization_wallpaper_context_v1 *handle, bool isOwner);
};
class PersonalizationCursorContextPrivate;
class PersonalizationCursorContext : public QObject, public QWObject
{
Q_OBJECT
QW_DECLARE_PRIVATE(PersonalizationCursorContext)
public:
~PersonalizationCursorContext() = default;
inline personalization_cursor_context_v1 *handle() const
{
return QWObject::handle<personalization_cursor_context_v1>();
}
static PersonalizationCursorContext *get(personalization_cursor_context_v1 *handle);
static PersonalizationCursorContext *from(personalization_cursor_context_v1 *handle);
static PersonalizationCursorContext *create(personalization_cursor_context_v1 *handle);
Q_SIGNALS:
void beforeDestroy(PersonalizationCursorContext *self);
void commit(personalization_cursor_context_v1 *handle);
void get_size(personalization_cursor_context_v1 *handle);
void get_theme(personalization_cursor_context_v1 *handle);
void verfity(personalization_cursor_context_v1 *handle);
private:
PersonalizationCursorContext(personalization_cursor_context_v1 *handle, bool isOwner);
};

View File

@ -44,6 +44,12 @@
</description>
<arg name="id" type="new_id" interface="personalization_wallpaper_context_v1"/>
</request>
<request name="get_cursor_context">
<description summary="custom wallpaper context">
custom user cursor
</description>
<arg name="id" type="new_id" interface="personalization_cursor_context_v1"/>
</request>
</interface>
<interface name="personalization_wallpaper_context_v1" version="1">
<description summary="client custom wallpaper context">
@ -97,6 +103,58 @@
<arg name="metadata" type="string" summary="user meta data"/>
</event>
</interface>
<interface name="personalization_cursor_context_v1" version="1">
<description summary="client custom cursor context">
This interface allows a client personalization cursor.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
</description>
<request name="set_theme">
<description summary="set system cursor theme"/>
<arg name="name" type="string" summary="cursor theme name"/>
</request>
<request name="get_theme">
<description summary="get system cursor theme"/>
</request>
<request name="set_size">
<description summary="set system cursor size"/>
<arg name="size" type="uint" summary="cursor size"/>
</request>
<request name="get_size">
<description summary="get system cursor size"/>
</request>
<request name="commit">
<description summary="commit configure">
if only one commit fails validation, the commit will fail
</description>
</request>
<request name="destroy" type="destructor">
<description summary="destroy the context object">
Destroy the context object.
</description>
</request>
<event name="verfity">
<description summary="verfity event">
Send this signal after commit cursor configure.
</description>
<arg name="success" type="int" summary="check whether the configuration is successful"/>
</event>
<event name="theme">
<description summary="cursor theme changed event">
Send this signal after system cursor theme changed.
</description>
<arg name="name" type="string" summary="cursor theme name"/>
</event>
<event name="size">
<description summary="cursor size changed event">
Send this signal after system cursor size changed.
</description>
<arg name="size" type="uint" summary="cursor size"/>
</event>
</interface>
<interface name="personalization_window_context_v1" version="1">
<description summary="client custom window context">
This interface allows a client personalization window.

View File

@ -23,6 +23,7 @@
#include <QJsonObject>
#include <QSettings>
#include <QStandardPaths>
#include <DConfig>
#include <sys/socket.h>
#include <unistd.h>
@ -33,6 +34,8 @@ extern "C" {
#undef static
}
DCORE_USE_NAMESPACE
static QuickPersonalizationManager *PERSONALIZATION_MANAGER = nullptr;
static QQuickItem *PERSONALIZATION_IMAGE = nullptr;
@ -44,6 +47,7 @@ public:
QuickPersonalizationManagerPrivate(QuickPersonalizationManager *qq);
~QuickPersonalizationManagerPrivate();
void initCursorConfig();
void updateCacheWallpaperPath(uid_t uid);
QString readWallpaperSettings(const QString &group, WOutput *w_output);
void saveWallpaperSettings(const QString &current,
@ -56,6 +60,7 @@ public:
QString m_cacheDirectory;
QString m_settingFile;
QString m_iniMetaData;
DConfig *m_cursorConfig = nullptr;
TreeLandPersonalizationManager *manager = nullptr;
};
@ -63,10 +68,17 @@ public:
QuickPersonalizationManagerPrivate::QuickPersonalizationManagerPrivate(
QuickPersonalizationManager *qq)
: WObjectPrivate(qq)
, m_cursorConfig(DConfig::create("org.deepin.Treeland", "org.deepin.Treeland", QString()))
{
}
QuickPersonalizationManagerPrivate::~QuickPersonalizationManagerPrivate() { }
QuickPersonalizationManagerPrivate::~QuickPersonalizationManagerPrivate()
{
if (m_cursorConfig != nullptr) {
delete m_cursorConfig;
m_cursorConfig = nullptr;
}
}
void QuickPersonalizationManagerPrivate::updateCacheWallpaperPath(uid_t uid)
{
@ -94,7 +106,7 @@ QString QuickPersonalizationManagerPrivate::readWallpaperSettings(const QString
WOutput *w_output)
{
if (m_settingFile.isEmpty())
return QString();
return DEFAULT_WALLPAPER;
QSettings settings(m_settingFile, QSettings::IniFormat);
@ -158,6 +170,10 @@ void QuickPersonalizationManager::create()
&TreeLandPersonalizationManager::wallpaperContextCreated,
this,
&QuickPersonalizationManager::onWallpaperContextCreated);
connect(d->manager,
&TreeLandPersonalizationManager::cursorContextCreated,
this,
&QuickPersonalizationManager::onCursorContextCreated);
}
void QuickPersonalizationManager::onWindowContextCreated(PersonalizationWindowContext *context)
@ -168,21 +184,35 @@ void QuickPersonalizationManager::onWindowContextCreated(PersonalizationWindowCo
&QuickPersonalizationManager::onBackgroundTypeChanged);
}
void QuickPersonalizationManager::onWallpaperContextCreated(
PersonalizationWallpaperContext *context)
void QuickPersonalizationManager::onWallpaperContextCreated(PersonalizationWallpaperContext *context)
{
connect(context,
&PersonalizationWallpaperContext::commit,
this,
&QuickPersonalizationManager::onCommit);
&QuickPersonalizationManager::onWallpaperCommit);
connect(context,
&PersonalizationWallpaperContext::getWallpapers,
this,
&QuickPersonalizationManager::onGetWallpapers);
}
QString QuickPersonalizationManager::saveImage(personalization_wallpaper_context_v1 *context,
const QString prefix)
void QuickPersonalizationManager::onCursorContextCreated(PersonalizationCursorContext *context)
{
connect(context,
&PersonalizationCursorContext::commit,
this,
&QuickPersonalizationManager::onCursorCommit);
connect(context,
&PersonalizationCursorContext::get_theme,
this,
&QuickPersonalizationManager::onGetCursorTheme);
connect(context,
&PersonalizationCursorContext::get_size,
this,
&QuickPersonalizationManager::onGetCursorSize);
}
QString QuickPersonalizationManager::saveImage(personalization_wallpaper_context_v1 *context, const QString prefix)
{
if (!context || context->fd == -1 || !strlen(context->output_name))
return QString();
@ -215,7 +245,7 @@ QString QuickPersonalizationManager::saveImage(personalization_wallpaper_context
return QString();
}
void QuickPersonalizationManager::onCommit(personalization_wallpaper_context_v1 *context)
void QuickPersonalizationManager::onWallpaperCommit(personalization_wallpaper_context_v1 *context)
{
if (context->options & PERSONALIZATION_WALLPAPER_CONTEXT_V1_OPTIONS_BACKGROUND) {
QString background = saveImage(context, "background");
@ -232,6 +262,53 @@ void QuickPersonalizationManager::onCommit(personalization_wallpaper_context_v1
}
}
void QuickPersonalizationManager::onCursorCommit(personalization_cursor_context_v1 *context)
{
if (!context)
return;
W_D(QuickPersonalizationManager);
if (d->m_cursorConfig == nullptr || !d->m_cursorConfig->isValid()) {
personalization_cursor_context_v1_send_verfity(context->resource, false);
return;
}
if (context->size > 0)
setCursorSize(QSize(context->size, context->size));
if (strlen(context->theme) > 0)
setCursorTheme(context->theme);
personalization_cursor_context_v1_send_verfity(context->resource, true);
}
void QuickPersonalizationManager::onGetCursorTheme(personalization_cursor_context_v1 *context)
{
if (!context)
return;
W_D(QuickPersonalizationManager);
if (d->m_cursorConfig == nullptr || !d->m_cursorConfig->isValid())
return;
context->theme = cursorTheme().toStdString().c_str();
personalization_cursor_context_v1_send_theme(context->resource, context->theme);
}
void QuickPersonalizationManager::onGetCursorSize(personalization_cursor_context_v1 *context)
{
if (!context)
return;
W_D(QuickPersonalizationManager);
if (d->m_cursorConfig == nullptr)
return;
context->size = cursorSize().width();
personalization_cursor_context_v1_send_size(context->resource, context->size);
}
void QuickPersonalizationManager::onGetWallpapers(personalization_wallpaper_context_v1 *context)
{
if (!context)
@ -271,7 +348,37 @@ void QuickPersonalizationManager::setUserId(uid_t uid)
Q_EMIT userIdChanged(uid);
}
QString QuickPersonalizationManager::background(WOutput *w_output)
QString QuickPersonalizationManager::cursorTheme()
{
W_D(QuickPersonalizationManager);
QString value = d->m_cursorConfig->value("CursorThemeName").toString();
return value;
}
void QuickPersonalizationManager::setCursorTheme(const QString &name)
{
W_D(QuickPersonalizationManager);
d->m_cursorConfig->setValue("CursorThemeName", name);
Q_EMIT cursorThemeChanged(name);
}
QSize QuickPersonalizationManager::cursorSize()
{
W_D(QuickPersonalizationManager);
int size = d->m_cursorConfig->value("CursorSize").toInt();
return QSize(size, size);
}
void QuickPersonalizationManager::setCursorSize(const QSize &size)
{
W_D(QuickPersonalizationManager);
d->m_cursorConfig->setValue("CursorSize", size.width());
Q_EMIT cursorSizeChanged(size);
}
QString QuickPersonalizationManager::background(WOutput* w_output)
{
W_D(QuickPersonalizationManager);
return d->readWallpaperSettings("background", w_output);

View File

@ -55,6 +55,7 @@ private:
class QuickPersonalizationManagerPrivate;
class PersonalizationWindowContext;
class PersonalizationWallpaperContext;
class PersonalizationCursorContext;
class QuickPersonalizationManager : public WQuickWaylandServerInterface, public WObject
{
@ -64,25 +65,42 @@ class QuickPersonalizationManager : public WQuickWaylandServerInterface, public
QML_ATTACHED(QuickPersonalizationManagerAttached)
Q_PROPERTY(uid_t userId READ userId WRITE setUserId NOTIFY userIdChanged FINAL)
Q_PROPERTY(QString cursorTheme READ cursorTheme WRITE setCursorTheme NOTIFY cursorThemeChanged FINAL)
Q_PROPERTY(QSize cursorSize READ cursorSize WRITE setCursorSize NOTIFY cursorSizeChanged FINAL)
public:
explicit QuickPersonalizationManager(QObject *parent = nullptr);
void onWindowContextCreated(PersonalizationWindowContext *context);
void onWallpaperContextCreated(PersonalizationWallpaperContext *context);
void onCursorContextCreated(PersonalizationCursorContext *context);
void onBackgroundTypeChanged(PersonalizationWindowContext *context);
void onCommit(personalization_wallpaper_context_v1 *context);
void onWallpaperCommit(personalization_wallpaper_context_v1 *context);
void onGetWallpapers(personalization_wallpaper_context_v1 *context);
void onCursorCommit(personalization_cursor_context_v1 *context);
void onGetCursorTheme(personalization_cursor_context_v1 *context);
void onGetCursorSize(personalization_cursor_context_v1 *context);
static QuickPersonalizationManagerAttached *qmlAttachedProperties(QObject *target);
uid_t userId();
void setUserId(uid_t uid);
QString cursorTheme();
void setCursorTheme(const QString &name);
QSize cursorSize();
void setCursorSize(const QSize &size);
Q_SIGNALS:
void backgroundTypeChanged(WSurface *surface, uint32_t type);
void userIdChanged(uid_t uid);
void backgroundChanged();
void lockscreenChanged();
void cursorThemeChanged(const QString &name);
void cursorSizeChanged(const QSize &size);
public slots:
QString background(WOutput *w_output);

View File

@ -75,7 +75,8 @@ Item {
name: "seat0"
cursor: Cursor {
id: cursor1
themeName: personalizationManager.cursorTheme
size: personalizationManager.cursorSize
layout: QmlHelper.layout
}

View File

@ -0,0 +1,113 @@
// Copyright (C) 2024 WenHao Peng <pengwenhao@uniontech.com>.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "personalization_manager_impl.h"
#include "personalizationmanager.h"
#include <qwglobal.h>
#include <qwoutput.h>
#include <qwsignalconnector.h>
#include <QHash>
QW_USE_NAMESPACE
class PersonalizationCursorContextPrivate : public QWObjectPrivate
{
public:
PersonalizationCursorContextPrivate(personalization_cursor_context_v1 *handle,
bool isOwner,
PersonalizationCursorContext *qq)
: QWObjectPrivate(handle, isOwner, qq)
{
Q_ASSERT(!map.contains(handle));
map.insert(handle, qq);
sc.connect(&handle->events.destroy, this, &PersonalizationCursorContextPrivate::on_destroy);
sc.connect(&handle->events.commit, this,
&PersonalizationCursorContextPrivate::on_commit);
sc.connect(&handle->events.get_size, this,
&PersonalizationCursorContextPrivate::on_get_size);
sc.connect(&handle->events.get_theme, this,
&PersonalizationCursorContextPrivate::on_get_theme);
}
~PersonalizationCursorContextPrivate()
{
if (!m_handle)
return;
destroy();
if (isHandleOwner)
personalization_cursor_context_v1_destroy(q_func()->handle());
}
inline void destroy()
{
Q_ASSERT(m_handle);
Q_ASSERT(map.contains(m_handle));
Q_EMIT q_func()->beforeDestroy(q_func());
map.remove(m_handle);
sc.invalidate();
}
void on_destroy(void *);
void on_commit(void *);
void on_get_size(void *);
void on_get_theme(void *);
static QHash<void *, PersonalizationCursorContext *> map;
QW_DECLARE_PUBLIC(PersonalizationCursorContext)
QWSignalConnector sc;
};
QHash<void *, PersonalizationCursorContext *> PersonalizationCursorContextPrivate::map;
void PersonalizationCursorContextPrivate::on_destroy(void *)
{
destroy();
m_handle = nullptr;
delete q_func();
}
void PersonalizationCursorContextPrivate::on_commit(void *data)
{
Q_EMIT q_func()->commit(reinterpret_cast<personalization_cursor_context_v1*>(data));
}
void PersonalizationCursorContextPrivate::on_get_size(void *data)
{
Q_EMIT q_func()->get_size(reinterpret_cast<personalization_cursor_context_v1*>(data));
}
void PersonalizationCursorContextPrivate::on_get_theme(void *data)
{
Q_EMIT q_func()->get_theme(reinterpret_cast<personalization_cursor_context_v1*>(data));
}
PersonalizationCursorContext::PersonalizationCursorContext(
personalization_cursor_context_v1 *handle, bool isOwner)
: QObject(nullptr)
, QWObject(*new PersonalizationCursorContextPrivate(handle, isOwner, this))
{
}
PersonalizationCursorContext *PersonalizationCursorContext::get(
personalization_cursor_context_v1 *handle)
{
return PersonalizationCursorContextPrivate::map.value(handle);
}
PersonalizationCursorContext *PersonalizationCursorContext::from(
personalization_cursor_context_v1 *handle)
{
if (auto o = get(handle))
return o;
return new PersonalizationCursorContext(handle, false);
}
PersonalizationCursorContext *PersonalizationCursorContext::create(
personalization_cursor_context_v1 *handle)
{
if (!handle)
return nullptr;
return new PersonalizationCursorContext(handle, true);
}