Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support dock preview #40

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 65 additions & 21 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 @@ -93,28 +97,13 @@
</event>
<event name="identifier">
<description summary="a stable identifier for a toplevel">
This identifier is used to check if two or more toplevel handles belong
to the same toplevel.

The identifier is useful for command line tools or privileged clients
which may need to reference an exact toplevel across processes or
instances of the ext_foreign_toplevel_list_v1 global.

The compositor must only send this event when the handle is created.

The identifier must be unique per toplevel and it's handles. Two different
toplevels must not have the same identifier. The identifier is only valid
as long as the toplevel is mapped. If the toplevel is unmapped the identifier
must not be reused. An identifier must not be reused by the compositor to
ensure there are no races when sharing identifiers between processes.

An identifier is a string that contains up to 32 printable ASCII bytes.
An identifier must not be an empty string. It is recommended that a
compositor includes an opaque generation value in identifiers. How the
generation value is used when generating the identifier is implementation
dependent.
The identifier of each top level and its handle must be unique.
Two different top layers cannot have the same identifier.
This identifier is only valid as long as the top level is mapped.
Identifiers must not be reused if the top level is not mapped.
The compositor must not reuse identifiers to ensure there are no races when identifiers are shared between processes.
</description>
<arg name="identifier" type="string" />
<arg name="identifier" type="uint" />
</event>

<event name="output_enter">
Expand Down Expand Up @@ -290,4 +279,59 @@
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>

<enum name="direction">
<description summary="types of direction on the dock preview">
</description>

<entry name="top" value="0" summary="top" />
<entry name="right" value="1" summary="right" />
<entry name="bottom" value="2" summary="bottom" />
<entry name="left" value="3" summary="left" />
</enum>

<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 @@ -30,6 +30,7 @@ target_sources(treeland-protocols PRIVATE
personalizationwallpapercontext.cpp
personalizationmanager.cpp
qshortcutmanager.cpp
dockpreviewcontextv1.cpp
)

target_compile_definitions(treeland-protocols
Expand Down
99 changes: 99 additions & 0 deletions src/treeland/protocols/dockpreviewcontextv1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (C) 2024 Dingyuan Zhang <[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);
sc.connect(&handle->events.request_close, this, &TreeLandDockPreviewContextV1Private::on_request_close);
}
~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 *);
void on_request_close(void *);

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

Check warning on line 49 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)
{
struct treeland_dock_preview_context_v1_preview_event *event = static_cast<treeland_dock_preview_context_v1_preview_event*>(data);
Q_EMIT q_func()->requestShow(event);
}

void TreeLandDockPreviewContextV1Private::on_request_close([[maybe_unused]] void *data)
{
Q_EMIT q_func()->requestClose();
}

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());
}
Loading
Loading