Skip to content

Commit 10ce4d7

Browse files
committed
KDE Appmenu: new protocol implementation
This allows apps to link their implementation of the com.canonical.dbusmenu DBus interface to their open views, implementing global menus.
1 parent f1dda31 commit 10ce4d7

File tree

7 files changed

+173
-2
lines changed

7 files changed

+173
-2
lines changed

metadata/kde-appmenu.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0"?>
2+
<wayfire>
3+
<plugin name="kde-appmenu">
4+
<_short>KDE Appmenu support</_short>
5+
<_long>An implementation of the KDE Appmenu protocol for global menus.</_long>
6+
<category>Utility</category>
7+
</plugin>
8+
</wayfire>

metadata/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ install_data('input-method-v1.xml', install_dir: conf_data.get('PLUGIN_XML_DIR')
2020
install_data('invert.xml', install_dir: conf_data.get('PLUGIN_XML_DIR'))
2121
install_data('ipc.xml', install_dir: conf_data.get('PLUGIN_XML_DIR'))
2222
install_data('ipc-rules.xml', install_dir: conf_data.get('PLUGIN_XML_DIR'))
23+
install_data('kde-appmenu.xml', install_dir: conf_data.get('PLUGIN_XML_DIR'))
2324
install_data('move.xml', install_dir: conf_data.get('PLUGIN_XML_DIR'))
2425
install_data('oswitch.xml', install_dir: conf_data.get('PLUGIN_XML_DIR'))
2526
install_data('output.xml', install_dir: conf_data.get('PLUGIN_XML_DIR'))

plugins/protocols/kde-appmenu.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include "kde-appmenu-protocol.h"
2+
#include "wayfire/core.hpp"
3+
#include "wayfire/object.hpp"
4+
#include <wayfire/plugin.hpp>
5+
#include <wayfire/view.hpp>
6+
#include <wayfire/toplevel-view.hpp>
7+
#include "kde-appmenu.hpp"
8+
9+
#define KDE_APPMENU_VERSION 2
10+
11+
struct wf_kde_appmenu_surface
12+
{
13+
wl_resource *resource;
14+
wl_resource *wl_surface;
15+
};
16+
17+
static void handle_kde_appmenu_set_address(wl_client *client,
18+
wl_resource *resource, const char *service_name,
19+
const char *object_path)
20+
{
21+
auto surface = static_cast<wf_kde_appmenu_surface*>(wl_resource_get_user_data(resource));
22+
wayfire_view view = wf::wl_surface_to_wayfire_view(surface->wl_surface);
23+
if (!view)
24+
{
25+
LOGE("Could not get view");
26+
return;
27+
} else
28+
{
29+
kde_appmenu_dbus_address_signal ev;
30+
ev.view = view;
31+
ev.service_name = service_name;
32+
ev.object_path = object_path;
33+
34+
wf::get_core().emit(&ev);
35+
}
36+
}
37+
38+
static void handle_kde_appmenu_release(wl_client*, wl_resource*)
39+
{
40+
/* no-op */
41+
}
42+
43+
static void handle_kde_appmenu_destroy(wl_resource *resource)
44+
{
45+
auto surface = static_cast<wf_kde_appmenu_surface*>(wl_resource_get_user_data(resource));
46+
delete surface;
47+
}
48+
49+
const struct org_kde_kwin_appmenu_interface kde_appmenu_impl = {
50+
.set_address = handle_kde_appmenu_set_address,
51+
.release = handle_kde_appmenu_release
52+
};
53+
54+
55+
static void handle_kde_appmenu_manager_create(wl_client *client,
56+
wl_resource *resource, uint32_t id, wl_resource *surface)
57+
{
58+
wf_kde_appmenu_surface *kde_appmenu_surface = new wf_kde_appmenu_surface;
59+
kde_appmenu_surface->resource = wl_resource_create(client,
60+
&org_kde_kwin_appmenu_interface, wl_resource_get_version(resource), id);
61+
kde_appmenu_surface->wl_surface = surface;
62+
wl_resource_set_implementation(kde_appmenu_surface->resource, &kde_appmenu_impl,
63+
kde_appmenu_surface, handle_kde_appmenu_destroy);
64+
}
65+
66+
static void handle_kde_appmenu_manager_release(wl_client*, wl_resource*)
67+
{
68+
/* no-op */
69+
}
70+
71+
static void handle_kde_appmenu_manager_destroy(wl_resource*)
72+
{
73+
/* no-op */
74+
}
75+
76+
static const struct org_kde_kwin_appmenu_manager_interface kde_appmenu_manager_impl = {
77+
.create = handle_kde_appmenu_manager_create,
78+
.release = handle_kde_appmenu_manager_release
79+
};
80+
81+
82+
static void bind_kde_appmenu(wl_client *client, void *data, uint32_t version, uint32_t id)
83+
{
84+
auto resource = wl_resource_create(client, &org_kde_kwin_appmenu_manager_interface,
85+
KDE_APPMENU_VERSION, id);
86+
wl_resource_set_implementation(resource, &kde_appmenu_manager_impl,
87+
data, handle_kde_appmenu_manager_destroy);
88+
}
89+
90+
class wayfire_kde_appmenu_impl : public wf::plugin_interface_t
91+
{
92+
public:
93+
void init() override
94+
{
95+
auto display = wf::get_core().display;
96+
wl_global_create(display, &org_kde_kwin_appmenu_manager_interface,
97+
KDE_APPMENU_VERSION, NULL, bind_kde_appmenu);
98+
}
99+
100+
bool is_unloadable() override
101+
{
102+
return false;
103+
}
104+
};
105+
106+
DECLARE_WAYFIRE_PLUGIN(wayfire_kde_appmenu_impl);

plugins/protocols/kde-appmenu.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include <wayfire/view.hpp>
4+
5+
/**
6+
* A signal that is emitted when the DBus address specified for a view
7+
* via the kde-appmenu protocol changes.
8+
*/
9+
struct kde_appmenu_dbus_address_signal
10+
{
11+
wayfire_view view;
12+
13+
const char *service_name;
14+
const char *object_path;
15+
};

plugins/protocols/meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
protocol_plugins = [
22
'foreign-toplevel', 'gtk-shell', 'wayfire-shell', 'xdg-activation', 'shortcuts-inhibit',
3-
'input-method-v1', 'session-lock'
3+
'input-method-v1', 'session-lock', 'kde-appmenu'
44
]
55

66
all_include_dirs = [wayfire_api_inc, wayfire_conf_inc, plugins_common_inc]

proto/kde-appmenu.xml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<protocol name="appmenu">
3+
<copyright><![CDATA[
4+
SPDX-FileCopyrightText: 2017 David Edmundson
5+
6+
SPDX-License-Identifier: LGPL-2.1-or-later
7+
]]></copyright>
8+
<interface name="org_kde_kwin_appmenu_manager" version="2">
9+
<description summary="appmenu dbus address interface">
10+
This interface allows a client to link a window (or wl_surface) to an com.canonical.dbusmenu
11+
interface registered on DBus.
12+
</description>
13+
<request name="create">
14+
<arg name="id" type="new_id" interface="org_kde_kwin_appmenu"/>
15+
<arg name="surface" type="object" interface="wl_surface"/>
16+
</request>
17+
<!-- version 2 additions-->
18+
<request name="release" type="destructor" since="2">
19+
<description summary="destroy the org_kde_kwin_appmenu_manager object" />
20+
</request>
21+
</interface>
22+
<interface name="org_kde_kwin_appmenu" version="2">
23+
<description summary="appmenu dbus address interface">
24+
The DBus service name and object path where the appmenu interface is present
25+
The object should be registered on the session bus before sending this request.
26+
If not applicable, clients should remove this object.
27+
</description>
28+
<request name="set_address">
29+
<description summary="initialise or update the location of the AppMenu interface">
30+
Set or update the service name and object path.
31+
Strings should be formatted in Latin-1 matching the relevant DBus specifications.
32+
</description>
33+
<arg name="service_name" type="string" />
34+
<arg name="object_path" type="string" />
35+
</request>
36+
<request name="release" type="destructor">
37+
<description summary="release the appmenu object"/>
38+
</request>
39+
</interface>
40+
</protocol>

proto/meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ server_protocols = [
3535
'wayfire-shell-unstable-v2.xml',
3636
'gtk-shell.xml',
3737
'wlr-layer-shell-unstable-v1.xml',
38-
'wlr-output-power-management-unstable-v1.xml'
38+
'wlr-output-power-management-unstable-v1.xml',
39+
'kde-appmenu.xml'
3940
]
4041

4142
wl_protos_src = []

0 commit comments

Comments
 (0)