Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
justforlxz committed Dec 11, 2023
1 parent 7ac4342 commit 661f826
Show file tree
Hide file tree
Showing 19 changed files with 585 additions and 2 deletions.
48 changes: 48 additions & 0 deletions src/treeland/data/treeland-foreign-toplevel-manager-v1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
the client should free any resources associated with it.
</description>
</event>
<request name="get_dock_preview_context">
<arg name="relative_surface" type="object" interface="wl_surface" />
<arg name="id" type="new_id" interface="treeland_dock_preview_context_v1" />
</request>
</interface>
<interface name="ztreeland_foreign_toplevel_handle_v1" version="1">
<description summary="An opened toplevel">
Expand Down Expand Up @@ -290,4 +294,48 @@
allow-null="true" />
</event>
</interface>
<interface name="treeland_dock_preview_context_v1" version="1">
<description summary="handle dock preview">
This interface allows dock set windows preview.

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>
<event name="enter">
<description summary="enter preview box">
This event is sent after mouse enter preview box.
</description>
</event>
<event name="leave">
<description summary="leave preview box">
This event is sent after mouse leave preview box.
</description>
</event>

<request name="show">
<description summary="set preview surfaces">
X and Y are relative to the relative_surface.
surfaces wl_array is identifiers.
</description>

<arg name="surfaces" type="array" />
<arg name="x" type="int" />
<arg name="y" type="int" />
<arg name="direction" type="uint" />
</request>

<request name="close">
<description summary="close preview box">
close preview box
</description>
</request>

<request name="destroy" type="destructor">
<description summary="destroy the context object">
Destroy the context object.
</description>
</request>
</interface>
</protocol>
1 change: 1 addition & 0 deletions src/treeland/protocols/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ target_sources(treeland-protocols PRIVATE
ext_foreign_toplevel_list_impl.cpp
foreigntoplevelhandlev1.cpp
foreigntoplevelmanagerv1.cpp
dockpreviewcontextv1.cpp
)

target_compile_definitions(treeland-protocols
Expand Down
91 changes: 91 additions & 0 deletions src/treeland/protocols/dockpreviewcontextv1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// 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 "foreigntoplevelhandlev1.h"
#include "foreign_toplevel_manager_impl.h"

#include <QHash>

#include <qwoutput.h>
#include <qwsignalconnector.h>
#include <qwglobal.h>

QW_USE_NAMESPACE

class TreeLandDockPreviewContextV1Private : public QWObjectPrivate
{
public:
TreeLandDockPreviewContextV1Private(treeland_dock_preview_context_v1 *handle, bool isOwner, TreeLandDockPreviewContextV1 *qq)
: QWObjectPrivate(handle, isOwner, qq)
{
Q_ASSERT(!map.contains(handle));
map.insert(handle, qq);
sc.connect(&handle->events.destroy, this, &TreeLandDockPreviewContextV1Private::on_destroy);
sc.connect(&handle->events.request_show, this, &TreeLandDockPreviewContextV1Private::on_request_show);
}
~TreeLandDockPreviewContextV1Private() {
if (!m_handle)
return;
destroy();
if (isHandleOwner)
treeland_dock_preview_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_request_show(void *);

static QHash<void*, TreeLandDockPreviewContextV1*> map;
QW_DECLARE_PUBLIC(TreeLandDockPreviewContextV1)

Check warning on line 47 in src/treeland/protocols/dockpreviewcontextv1.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

There is an unknown macro here somewhere. Configuration is required. If QW_DECLARE_PUBLIC is a macro then please configure it.
QWSignalConnector sc;
};
QHash<void*, TreeLandDockPreviewContextV1*> TreeLandDockPreviewContextV1Private::map;

void TreeLandDockPreviewContextV1Private::on_destroy(void *)
{
destroy();
m_handle = nullptr;
delete q_func();
}

void TreeLandDockPreviewContextV1Private::on_request_show(void *data)
{
Q_EMIT q_func()->requestShow(static_cast<treeland_dock_preview_context_v1_preview_event*>(data));
}

TreeLandDockPreviewContextV1::TreeLandDockPreviewContextV1(treeland_dock_preview_context_v1 *handle, bool isOwner)
: QObject(nullptr)
, QWObject(*new TreeLandDockPreviewContextV1Private(handle, isOwner, this))
{

}

TreeLandDockPreviewContextV1 *TreeLandDockPreviewContextV1::get(treeland_dock_preview_context_v1 *handle)
{
return TreeLandDockPreviewContextV1Private::map.value(handle);
}

TreeLandDockPreviewContextV1 *TreeLandDockPreviewContextV1::from(treeland_dock_preview_context_v1 *handle)
{
if (auto o = get(handle))
return o;
return new TreeLandDockPreviewContextV1(handle, false);
}

void TreeLandDockPreviewContextV1::enter()
{
treeland_dock_preview_context_v1_enter(handle());
}

void TreeLandDockPreviewContextV1::leave()
{
treeland_dock_preview_context_v1_leave(handle());
}
157 changes: 155 additions & 2 deletions src/treeland/protocols/foreign_toplevel_manager_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,27 @@ static void treeland_foreign_toplevel_handle_set_fullscreen(struct wl_client *cl
struct wl_resource *output);
static void treeland_foreign_toplevel_handle_unset_fullscreen(struct wl_client *client,
struct wl_resource *resource);
static void treeland_foreign_toplevel_handle_set_preview(struct wl_client *client,
struct wl_resource *resource);
static void treeland_foreign_toplevel_handle_unset_preview(struct wl_client *client,
struct wl_resource *resource);
static void treeland_foreign_toplevel_handle_destroy(struct wl_client *client,
struct wl_resource *resource);
static void treeland_foreign_toplevel_manager_handle_stop(struct wl_client *client,
struct wl_resource *resource);
static void treeland_foreign_toplevel_manager_handle_get_dock_preview_context(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *relative_surface,
uint32_t id);

static void treeland_dock_preview_context_handle_show(struct wl_client *client,
struct wl_resource *resource,
struct wl_array *surfaces,
int32_t x,
int32_t y,
uint32_t direction);

static void treeland_dock_preview_context_handle_destroy(struct wl_client *client, struct wl_resource *resource);

static const struct ztreeland_foreign_toplevel_handle_v1_interface treeland_toplevel_handle_impl = {
.set_maximized = treeland_foreign_toplevel_handle_set_maximized,
Expand All @@ -61,6 +78,12 @@ static const struct ztreeland_foreign_toplevel_handle_v1_interface treeland_topl
.unset_fullscreen = treeland_foreign_toplevel_handle_unset_fullscreen,
};

static const struct treeland_dock_preview_context_v1_interface
treeland_dock_preview_context_impl = {
.show = treeland_dock_preview_context_handle_show,
.destroy = treeland_dock_preview_context_handle_destroy,
};

static struct treeland_foreign_toplevel_handle_v1 *
toplevel_handle_from_resource(struct wl_resource *resource)
{
Expand All @@ -71,6 +94,16 @@ toplevel_handle_from_resource(struct wl_resource *resource)
wl_resource_get_user_data(resource));
}

static struct treeland_dock_preview_context_v1 *
toplevel_dock_preview_context_from_resource(struct wl_resource *resource)
{
assert(wl_resource_instance_of(resource,
&treeland_dock_preview_context_v1_interface,
&treeland_dock_preview_context_impl));
return static_cast<struct treeland_dock_preview_context_v1 *>(
wl_resource_get_user_data(resource));
}

static void toplevel_handle_send_maximized_event(struct wl_resource *resource, bool state)
{
struct treeland_foreign_toplevel_handle_v1 *toplevel = toplevel_handle_from_resource(resource);
Expand Down Expand Up @@ -143,6 +176,38 @@ static void toplevel_send_fullscreen_event(struct wl_resource *resource,
wl_signal_emit_mutable(&toplevel->events.request_fullscreen, &event);
}

static void dock_send_preview_event(struct wl_resource *resource, struct wl_array *surfaces, int32_t x, int32_t y, int32_t direction)
{
struct treeland_dock_preview_context_v1 *dock_preview = toplevel_dock_preview_context_from_resource(resource);
if (!dock_preview) {
return;
}

std::vector<wlr_surface*> s;

struct treeland_foreign_toplevel_handle_v1 *pos;
struct treeland_foreign_toplevel_handle_v1 *tmp;
wl_list_for_each_safe(pos, tmp, &dock_preview->manager->toplevels, link) {
void *p;
wl_array_for_each(p, surfaces) {
if (strcmp(static_cast<char*>(p), pos->identifier) == 0) {

Check warning on line 193 in src/treeland/protocols/foreign_toplevel_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Uninitialized variable: pos->identifier
s.push_back(wlr_surface_from_resource(pos->surface));
break;
}
}
}

struct treeland_dock_preview_context_v1_preview_event event = {
.toplevel = dock_preview,
.surfaces = s,
.x = x,
.y = y,
.direction = direction,
};

wl_signal_emit_mutable(&dock_preview->events.request_show, &event);
}

static void treeland_foreign_toplevel_handle_set_fullscreen([[maybe_unused]] struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *output)
Expand Down Expand Up @@ -589,6 +654,34 @@ void treeland_foreign_toplevel_handle_v1_set_parent(
toplevel_update_idle_source(toplevel);
}

void treeland_dock_preview_context_v1_enter(

Check warning on line 657 in src/treeland/protocols/foreign_toplevel_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_dock_preview_context_v1_enter' is never used.
struct treeland_dock_preview_context_v1 *toplevel)
{
treeland_dock_preview_context_v1_send_enter(toplevel->resource);
}

void treeland_dock_preview_context_v1_leave(

Check warning on line 663 in src/treeland/protocols/foreign_toplevel_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_dock_preview_context_v1_leave' is never used.
struct treeland_dock_preview_context_v1 *toplevel)
{
treeland_dock_preview_context_v1_send_leave(toplevel->resource);
}

void treeland_dock_preview_context_v1_destroy(

Check warning on line 669 in src/treeland/protocols/foreign_toplevel_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_dock_preview_context_v1_destroy' is never used.
struct treeland_dock_preview_context_v1 *toplevel)
{
if (!toplevel) {
return;
}

wl_signal_emit_mutable(&toplevel->events.destroy, toplevel);

wl_resource_set_user_data(toplevel->resource, NULL);
wl_list_remove(wl_resource_get_link(toplevel->resource));
wl_list_remove(&toplevel->link);

free(toplevel);
}

void treeland_foreign_toplevel_handle_v1_destroy(

Check warning on line 685 in src/treeland/protocols/foreign_toplevel_manager_impl.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'treeland_foreign_toplevel_handle_v1_destroy' is never used.
struct treeland_foreign_toplevel_handle_v1 *toplevel)
{
Expand Down Expand Up @@ -643,6 +736,21 @@ static void treeland_foreign_toplevel_resource_destroy(struct wl_resource *resou
wl_list_remove(wl_resource_get_link(resource));
}

static void treeland_dock_preview_context_handle_show([[maybe_unused]] struct wl_client *client,
struct wl_resource *resource,
struct wl_array *surfaces,
int32_t x,
int32_t y,
uint32_t direction)
{
dock_send_preview_event(resource, surfaces, x, y, direction);
}

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

static struct wl_resource *create_toplevel_resource_for_resource(
struct treeland_foreign_toplevel_handle_v1 *toplevel, struct wl_resource *manager_resource)
{
Expand Down Expand Up @@ -700,8 +808,17 @@ treeland_foreign_toplevel_handle_v1_create(struct treeland_foreign_toplevel_mana
}

static const struct ztreeland_foreign_toplevel_manager_v1_interface
treeland_foreign_toplevel_manager_impl = { .stop =
treeland_foreign_toplevel_manager_handle_stop };
treeland_foreign_toplevel_manager_impl = {
.stop = treeland_foreign_toplevel_manager_handle_stop,
.get_dock_preview_context = treeland_foreign_toplevel_manager_handle_get_dock_preview_context,
};

struct treeland_foreign_toplevel_manager_v1 *foreign_toplevel_manager_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &ztreeland_foreign_toplevel_manager_v1_interface, &treeland_foreign_toplevel_manager_impl));
struct treeland_foreign_toplevel_manager_v1 *manager = static_cast<treeland_foreign_toplevel_manager_v1*>(wl_resource_get_user_data(resource));
assert(manager != NULL);
return manager;
}

static void treeland_foreign_toplevel_manager_handle_stop([[maybe_unused]] struct wl_client *client,
struct wl_resource *resource)
Expand All @@ -714,6 +831,41 @@ static void treeland_foreign_toplevel_manager_handle_stop([[maybe_unused]] struc
wl_resource_destroy(resource);
}

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

static void treeland_foreign_toplevel_manager_handle_get_dock_preview_context(struct wl_client *client,
struct wl_resource *manager_resource,
struct wl_resource *relative_surface,
uint32_t id)
{
auto *manager = foreign_toplevel_manager_from_resource(manager_resource);

struct treeland_dock_preview_context_v1 *context = static_cast<treeland_dock_preview_context_v1*>(calloc(1, sizeof(*context)));
if (context == NULL) {
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, &treeland_dock_preview_context_v1_interface, version, id);
if (resource == NULL) {
free(context);
wl_resource_post_no_memory(manager_resource);
return;
}

wl_resource_set_implementation(resource, &treeland_dock_preview_context_impl, context, treeland_dock_preview_context_resource_destroy);

context->manager = manager;
context->relative_surface = relative_surface;
context->resource = resource;

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

static void treeland_foreign_toplevel_manager_resource_destroy(struct wl_resource *resource)
{
wl_list_remove(wl_resource_get_link(resource));
Expand Down Expand Up @@ -823,6 +975,7 @@ treeland_foreign_toplevel_manager_v1_create(struct wl_display *display)
}

wl_signal_init(&manager->events.destroy);
wl_signal_init(&manager->events.dock_preview_created);
wl_list_init(&manager->resources);
wl_list_init(&manager->toplevels);

Expand Down
Loading

0 comments on commit 661f826

Please sign in to comment.