diff --git a/docs/meson.build b/docs/meson.build
index dab89bf6..e1e6022c 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -51,6 +51,9 @@ all_doc_target = custom_target(
'--pkg', 'granite',
'--pkg', 'gnome-desktop-3.0',
'--pkg', 'gmodule-2.0',
+ '--pkg', 'wayland-server',
+ '--pkg', 'pantheon-desktop-shell',
+ '--vapidir=' + join_paths(meson.global_source_root(), 'protocol'),
'-o', '@OUTPUT@',
'@INPUT@'
],
diff --git a/meson.build b/meson.build
index cdeb9043..a583d3e6 100644
--- a/meson.build
+++ b/meson.build
@@ -182,6 +182,7 @@ if get_option('systemd')
endif
subdir('data')
+subdir('protocol')
subdir('lib')
subdir('src')
subdir('daemon')
diff --git a/po/POTFILES b/po/POTFILES
index 9db9a2e0..b579e950 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -1,4 +1,5 @@
src/Dialogs.vala
+src/PantheonShell.vala
src/ScreenshotManager.vala
src/WindowManager.vala
daemon/BackgroundMenu.vala
diff --git a/protocol/meson.build b/protocol/meson.build
new file mode 100644
index 00000000..771af1a0
--- /dev/null
+++ b/protocol/meson.build
@@ -0,0 +1,32 @@
+dep_scanner = dependency('wayland-scanner', native: true)
+prog_scanner = find_program(dep_scanner.get_variable(pkgconfig: 'wayland_scanner'))
+
+protocol_file = files('pantheon-desktop-shell-v1.xml')
+
+pantheon_desktop_shell_sources = []
+pantheon_desktop_shell_sources += custom_target(
+ 'pantheon-desktop-shell-server-protocol.h',
+ command: [ prog_scanner, 'server-header', '@INPUT@', '@OUTPUT@' ],
+ input: protocol_file,
+ output: 'pantheon-desktop-shell-server-protocol.h',
+)
+
+output_type = 'private-code'
+if dep_scanner.version().version_compare('< 1.14.91')
+ output_type = 'code'
+endif
+pantheon_desktop_shell_sources += custom_target(
+ 'pantheon-desktop-shell-protocol.c',
+ command: [ prog_scanner, output_type, '@INPUT@', '@OUTPUT@' ],
+ input: protocol_file,
+ output: 'pantheon-desktop-shell-protocol.c',
+)
+
+pantheon_desktop_shell_dep = declare_dependency(
+ dependencies: [
+ vala.find_library('pantheon-desktop-shell', dirs: meson.current_source_dir()),
+ dependency('wayland-server'),
+ ],
+ include_directories: include_directories('.'),
+ sources: pantheon_desktop_shell_sources
+)
diff --git a/protocol/pantheon-desktop-shell-v1.xml b/protocol/pantheon-desktop-shell-v1.xml
new file mode 100644
index 00000000..18a7da64
--- /dev/null
+++ b/protocol/pantheon-desktop-shell-v1.xml
@@ -0,0 +1,115 @@
+
+
+
+
+ SPDX-License-Identifier: LGPL-2.1-or-later
+ ]]>
+
+
+
+ This interface is used by the Pantheon Wayland shell to communicate with
+ the compositor.
+
+
+
+
+ Create a panel surface from an existing surface.
+
+
+
+
+
+
+
+ Create a desktop widget surface from an existing surface.
+
+
+
+
+
+
+
+ Create a desktop-specific surface from an existing surface.
+
+
+
+
+
+
+
+
+
+
+
+ The anchor is a placement hint to the compositor.
+
+
+
+
+
+
+
+
+
+ How the shell should handle the window.
+
+
+
+
+
+
+
+
+
+
+ Tell the shell which side of the screen the panel is
+ located. This is so that new windows do not overlap the panel
+ and maximized windows maximize properly.
+
+
+
+
+
+
+
+ Request keyboard focus, taking it away from any other window.
+ Keyboard focus must always be manually be requested and is
+ - in contrast to normal windows - never automatically granted
+ by the compositor.
+
+
+
+
+
+ The given size is only used for exclusive zones and
+ collision tracking for auto hide. By default and if set
+ to -1 the size of the surface is used.
+
+
+
+
+
+
+
+
+ Tell the shell when to hide the panel.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tell the shell to keep the surface above on all workspaces
+
+
+
+
diff --git a/protocol/pantheon-desktop-shell.deps b/protocol/pantheon-desktop-shell.deps
new file mode 100644
index 00000000..62acb1e0
--- /dev/null
+++ b/protocol/pantheon-desktop-shell.deps
@@ -0,0 +1 @@
+wayland-server
diff --git a/protocol/pantheon-desktop-shell.vapi b/protocol/pantheon-desktop-shell.vapi
new file mode 100644
index 00000000..b699c45c
--- /dev/null
+++ b/protocol/pantheon-desktop-shell.vapi
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 elementary, Inc.
+ * Copyright 2023 Corentin Noël
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+namespace Pantheon.Desktop {
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "struct io_elementary_pantheon_shell_v1_interface")]
+ public struct ShellInterface {
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "io_elementary_pantheon_shell_v1_interface")]
+ public static Wl.Interface iface;
+ public Pantheon.Desktop.GetPanel get_panel;
+ public Pantheon.Desktop.GetWidget get_widget;
+ public Pantheon.Desktop.GetExtendedBehavior get_extended_behavior;
+
+ }
+
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "enum io_elementary_pantheon_panel_v1_anchor", cprefix="IO_ELEMENTARY_PANTHEON_PANEL_V1_ANCHOR_", has_type_id = false)]
+ public enum Anchor {
+ TOP,
+ BOTTOM,
+ LEFT,
+ RIGHT,
+ }
+
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "enum io_elementary_pantheon_panel_v1_hide_mode", cprefix="IO_ELEMENTARY_PANTHEON_PANEL_V1_HIDE_MODE_", has_type_id = false)]
+ public enum HideMode {
+ NEVER,
+ MAXIMIZED_FOCUS_WINDOW,
+ OVERLAPPING_FOCUS_WINDOW,
+ OVERLAPPING_WINDOW,
+ ALWAYS
+ }
+
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "struct io_elementary_pantheon_panel_v1_interface")]
+ public struct PanelInterface {
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "io_elementary_pantheon_panel_v1_interface")]
+ public static Wl.Interface iface;
+ public Destroy destroy;
+ public SetAnchor set_anchor;
+ public Focus focus;
+ public SetSize set_size;
+ public SetHideMode set_hide_mode;
+ }
+
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "struct io_elementary_pantheon_widget_v1_interface")]
+ public struct WidgetInterface {
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "io_elementary_pantheon_widget_v1_interface")]
+ public static Wl.Interface iface;
+ public Destroy destroy;
+ }
+
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "struct io_elementary_pantheon_extended_behavior_v1_interface")]
+ public struct ExtendedBehaviorInterface {
+ [CCode (cheader_filename = "pantheon-desktop-shell-server-protocol.h", cname = "io_elementary_pantheon_extended_behavior_v1_interface")]
+ public static Wl.Interface iface;
+ public Destroy destroy;
+ public SetKeepAbove set_keep_above;
+ }
+
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void GetPanel (Wl.Client client, Wl.Resource resource, uint32 output, Wl.Resource surface);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void GetWidget (Wl.Client client, Wl.Resource resource, uint32 output, Wl.Resource surface);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void GetExtendedBehavior (Wl.Client client, Wl.Resource resource, uint32 output, Wl.Resource surface);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void SetAnchor (Wl.Client client, Wl.Resource resource, [CCode (type = "uint32_t")] Anchor anchor);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void Focus (Wl.Client client, Wl.Resource resource);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void SetSize (Wl.Client client, Wl.Resource resource, int width, int height);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void SetHideMode (Wl.Client client, Wl.Resource resource, [CCode (type = "uint32_t")] HideMode hide_mode);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void SetKeepAbove (Wl.Client client, Wl.Resource resource);
+ [CCode (has_target = false, has_typedef = false)]
+ public delegate void Destroy (Wl.Client client, Wl.Resource resource);
+}
diff --git a/src/Main.vala b/src/Main.vala
index 2bb7070b..30f4ef0b 100644
--- a/src/Main.vala
+++ b/src/Main.vala
@@ -76,6 +76,9 @@ namespace Gala {
try {
ctx.start ();
+ if (ctx.get_compositor_type () == Meta.CompositorType.WAYLAND) {
+ Gala.init_pantheon_shell (ctx);
+ }
} catch (Error e) {
stderr.printf ("Failed to start: %s\n", e.message);
return Posix.EXIT_FAILURE;
diff --git a/src/PantheonShell.vala b/src/PantheonShell.vala
new file mode 100644
index 00000000..55d802e8
--- /dev/null
+++ b/src/PantheonShell.vala
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2023 elementary, Inc.
+ * Copyright 2023 Corentin Noël
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+namespace Gala {
+#if !HAS_MUTTER45
+ [Compact]
+ public class FakeMetaWaylandCompositor : GLib.Object {
+ // It is the third field and Vala adds a FakeMetaWaylandCompositorPrivate *priv
+ public Wl.Display wayland_display;
+
+ [CCode (cname = "meta_context_get_wayland_compositor")]
+ public extern static unowned Gala.FakeMetaWaylandCompositor from_context (Meta.Context context);
+ }
+#endif
+ public static inline unowned Wl.Display? get_display_from_context (Meta.Context context) {
+#if HAS_MUTTER45
+ unowned Meta.WaylandCompositor? compositor = context.get_wayland_compositor ();
+ if (compositor == null) {
+ return null;
+ }
+
+ return (Wl.Display) compositor.get_wayland_display ();
+#else
+ unowned FakeMetaWaylandCompositor compositor = Gala.FakeMetaWaylandCompositor.from_context (context);
+ if (compositor == null) {
+ return null;
+ }
+
+ return compositor.wayland_display;
+#endif
+ }
+
+ private static Pantheon.Desktop.ShellInterface wayland_pantheon_shell_interface;
+ private static Pantheon.Desktop.PanelInterface wayland_pantheon_panel_interface;
+ private static Pantheon.Desktop.WidgetInterface wayland_pantheon_widget_interface;
+ private static Pantheon.Desktop.ExtendedBehaviorInterface wayland_pantheon_extended_behavior_interface;
+ private static Wl.Global shell_global;
+
+ public void init_pantheon_shell (Meta.Context context) {
+ unowned Wl.Display? wl_disp = get_display_from_context (context);
+ if (wl_disp == null) {
+ debug ("Not running under Wayland, no Pantheon Shell protocol");
+ return;
+ }
+
+ wayland_pantheon_shell_interface = {
+ get_panel,
+ get_widget,
+ get_extended_behavior,
+ };
+
+ wayland_pantheon_panel_interface = {
+ destroy_panel_surface,
+ set_anchor,
+ focus,
+ set_size,
+ set_hide_mode,
+ };
+
+ wayland_pantheon_widget_interface = {
+ destroy_widget_surface,
+ };
+
+ wayland_pantheon_extended_behavior_interface = {
+ destroy_extended_behavior_surface,
+ set_keep_above,
+ };
+
+ PanelSurface.quark = GLib.Quark.from_string ("-gala-wayland-panel-surface-data");
+
+ shell_global = Wl.Global.create (wl_disp, ref Pantheon.Desktop.ShellInterface.iface, 1, (client, version, id) => {
+ unowned var resource = client.create_resource (ref Pantheon.Desktop.ShellInterface.iface, (int) version, id);
+ resource.set_implementation (&wayland_pantheon_shell_interface, null, (res) => {});
+ });
+ }
+
+ public class PanelSurface : GLib.Object {
+ public static GLib.Quark quark = 0;
+ public unowned GLib.Object? wayland_surface;
+
+ public PanelSurface (GLib.Object wayland_surface) {
+ this.wayland_surface = wayland_surface;
+ }
+
+ ~PanelSurface () {
+ if (wayland_surface != null) {
+ wayland_surface.steal_qdata (quark);
+ }
+ }
+
+ public void on_wayland_surface_disposed () {
+ wayland_surface = null;
+ }
+ }
+
+ public class WidgetSurface : GLib.Object {
+ public static GLib.Quark quark = 0;
+ public unowned GLib.Object? wayland_surface;
+
+ public WidgetSurface (GLib.Object wayland_surface) {
+ this.wayland_surface = wayland_surface;
+ }
+
+ ~WidgetSurface () {
+ if (wayland_surface != null) {
+ wayland_surface.steal_qdata (quark);
+ }
+ }
+
+ public void on_wayland_surface_disposed () {
+ wayland_surface = null;
+ }
+ }
+
+ public class ExtendedBehaviorSurface : GLib.Object {
+ public static GLib.Quark quark = 0;
+ public unowned GLib.Object? wayland_surface;
+
+ public ExtendedBehaviorSurface (GLib.Object wayland_surface) {
+ this.wayland_surface = wayland_surface;
+ }
+
+ ~ExtendedBehaviorSurface () {
+ if (wayland_surface != null) {
+ wayland_surface.steal_qdata (quark);
+ }
+ }
+
+ public void on_wayland_surface_disposed () {
+ wayland_surface = null;
+ }
+ }
+
+ static void unref_obj_on_destroy (Wl.Resource resource) {
+ resource.get_user_data ().unref ();
+ }
+
+ internal static void get_panel (Wl.Client client, Wl.Resource resource, uint32 output, Wl.Resource surface_resource) {
+ unowned GLib.Object? wayland_surface = surface_resource.get_user_data ();
+ PanelSurface? panel_surface = wayland_surface.get_qdata (PanelSurface.quark);
+ if (panel_surface != null) {
+ surface_resource.post_error (
+ Wl.DisplayError.INVALID_OBJECT,
+ "io_elementary_pantheon_shell_v1_interface::get_panel already requested"
+ );
+ return;
+ }
+
+ panel_surface = new PanelSurface (wayland_surface);
+ unowned var panel_resource = client.create_resource (
+ ref Pantheon.Desktop.PanelInterface.iface,
+ resource.get_version (),
+ output
+ );
+ panel_resource.set_implementation (
+ &wayland_pantheon_panel_interface,
+ panel_surface.ref (),
+ unref_obj_on_destroy
+ );
+ wayland_surface.set_qdata_full (
+ PanelSurface.quark,
+ panel_surface,
+ (GLib.DestroyNotify) PanelSurface.on_wayland_surface_disposed
+ );
+ }
+
+ internal static void get_widget (Wl.Client client, Wl.Resource resource, uint32 output, Wl.Resource surface_resource) {
+ unowned GLib.Object? wayland_surface = surface_resource.get_user_data ();
+ WidgetSurface? widget_surface = wayland_surface.get_qdata (WidgetSurface.quark);
+ if (widget_surface != null) {
+ surface_resource.post_error (
+ Wl.DisplayError.INVALID_OBJECT,
+ "io_elementary_pantheon_shell_v1_interface::get_widget already requested"
+ );
+ return;
+ }
+
+ widget_surface = new WidgetSurface (wayland_surface);
+ unowned var widget_resource = client.create_resource (
+ ref Pantheon.Desktop.WidgetInterface.iface,
+ resource.get_version (),
+ output
+ );
+ widget_resource.set_implementation (
+ &wayland_pantheon_widget_interface,
+ widget_surface.ref (),
+ unref_obj_on_destroy
+ );
+ wayland_surface.set_qdata_full (
+ WidgetSurface.quark,
+ widget_surface,
+ (GLib.DestroyNotify) WidgetSurface.on_wayland_surface_disposed
+ );
+ }
+
+ internal static void get_extended_behavior (Wl.Client client, Wl.Resource resource, uint32 output, Wl.Resource surface_resource) {
+ unowned GLib.Object? wayland_surface = surface_resource.get_user_data ();
+ ExtendedBehaviorSurface? eb_surface = wayland_surface.get_qdata (ExtendedBehaviorSurface.quark);
+ if (eb_surface != null) {
+ surface_resource.post_error (
+ Wl.DisplayError.INVALID_OBJECT,
+ "io_elementary_pantheon_shell_v1_interface::get_extended_behavior already requested"
+ );
+ return;
+ }
+
+ eb_surface = new ExtendedBehaviorSurface (wayland_surface);
+ unowned var eb_resource = client.create_resource (
+ ref Pantheon.Desktop.ExtendedBehaviorInterface.iface,
+ resource.get_version (),
+ output
+ );
+ eb_resource.set_implementation (
+ &wayland_pantheon_extended_behavior_interface,
+ eb_surface.ref (),
+ unref_obj_on_destroy
+ );
+ wayland_surface.set_qdata_full (
+ ExtendedBehaviorSurface.quark,
+ eb_surface,
+ (GLib.DestroyNotify) ExtendedBehaviorSurface.on_wayland_surface_disposed
+ );
+ }
+
+ internal static void set_anchor (Wl.Client client, Wl.Resource resource, [CCode (type = "uint32_t")] Pantheon.Desktop.Anchor anchor) {
+ unowned PanelSurface? panel_surface = resource.get_user_data ();
+ if (panel_surface.wayland_surface == null) {
+ return;
+ }
+
+ Meta.Window? window;
+ panel_surface.wayland_surface.get ("window", out window, null);
+ if (window == null) {
+ return;
+ }
+
+ // TODO
+ }
+
+ internal static void focus (Wl.Client client, Wl.Resource resource) {
+ unowned PanelSurface? panel_surface = resource.get_user_data ();
+ if (panel_surface.wayland_surface == null) {
+ return;
+ }
+
+ Meta.Window? window;
+ panel_surface.wayland_surface.get ("window", out window, null);
+ if (window == null) {
+ return;
+ }
+
+ window.focus (window.get_display ().get_current_time ());
+ }
+
+ internal static void set_size (Wl.Client client, Wl.Resource resource, int width, int height) {
+ unowned PanelSurface? panel_surface = resource.get_user_data ();
+ if (panel_surface.wayland_surface == null) {
+ return;
+ }
+
+ Meta.Window? window;
+ panel_surface.wayland_surface.get ("window", out window, null);
+ if (window == null) {
+ return;
+ }
+
+ // TODO
+ }
+
+ internal static void set_hide_mode (Wl.Client client, Wl.Resource resource, [CCode (type = "uint32_t")] Pantheon.Desktop.HideMode hide_mode) {
+ unowned PanelSurface? panel_surface = resource.get_user_data ();
+ if (panel_surface.wayland_surface == null) {
+ return;
+ }
+
+ Meta.Window? window;
+ panel_surface.wayland_surface.get ("window", out window, null);
+ if (window == null) {
+ return;
+ }
+
+ // TODO
+ }
+
+ internal static void set_keep_above (Wl.Client client, Wl.Resource resource) {
+ unowned ExtendedBehaviorSurface? eb_surface = resource.get_user_data ();
+ if (eb_surface.wayland_surface == null) {
+ return;
+ }
+
+ Meta.Window? window;
+ eb_surface.wayland_surface.get ("window", out window, null);
+ if (window == null) {
+ return;
+ }
+
+ window.make_above ();
+ }
+
+ internal static void destroy_panel_surface (Wl.Client client, Wl.Resource resource) {
+ resource.destroy ();
+ }
+
+ internal static void destroy_widget_surface (Wl.Client client, Wl.Resource resource) {
+ resource.destroy ();
+ }
+
+ internal static void destroy_extended_behavior_surface (Wl.Client client, Wl.Resource resource) {
+ resource.destroy ();
+ }
+}
diff --git a/src/meson.build b/src/meson.build
index 452a2457..afe387c9 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -9,6 +9,7 @@ gala_bin_sources = files(
'Main.vala',
'MediaFeedback.vala',
'NotificationStack.vala',
+ 'PantheonShell.vala',
'PluginManager.vala',
'ScreenSaverManager.vala',
'ScreenshotManager.vala',
@@ -69,7 +70,7 @@ gala_bin_sources = files(
gala_bin = executable(
'gala',
gala_bin_sources,
- dependencies: [gala_dep, gala_base_dep],
+ dependencies: [gala_dep, gala_base_dep, pantheon_desktop_shell_dep],
include_directories: config_inc_dir,
install_rpath: mutter_typelib_dir,
install: true,
diff --git a/vapi/wayland-server.deps b/vapi/wayland-server.deps
new file mode 100644
index 00000000..b3188f74
--- /dev/null
+++ b/vapi/wayland-server.deps
@@ -0,0 +1 @@
+posix
diff --git a/vapi/wayland-server.vapi b/vapi/wayland-server.vapi
new file mode 100644
index 00000000..6fa1885b
--- /dev/null
+++ b/vapi/wayland-server.vapi
@@ -0,0 +1,125 @@
+/* wayland-server.vapi
+ *
+ * Copyright 2022 Corentin Noël
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Corentin Noël
+ */
+
+[CCode (cprefix = "wl_", lower_case_cprefix = "wl_", cheader_filename = "wayland-server.h")]
+namespace Wl {
+ [Compact]
+ [CCode (cname = "struct wl_display", free_function = "wl_display_destroy")]
+ public class Display {
+ [CCode (cname = "wl_display_create")]
+ public Display ();
+ public int add_socket (string name);
+ public unowned string add_socket_auto ();
+ public int add_socket_fd (int sock_fd);
+ public void terminate ();
+ public void run ();
+ public void flush_clients ();
+ public void destroy_clients ();
+ public uint32 get_serial ();
+ public uint32 next_serial ();
+ }
+
+ [Compact]
+ [CCode (cname = "struct wl_client", free_function = "wl_client_destroy")]
+ public class Client {
+ [CCode (cname = "wl_client_create")]
+ public Client (Wl.Display display, int fd);
+ public void flush ();
+ public void get_credentials (out Posix.pid_t pid, out Posix.uid_t uid, out Posix.gid_t gid);
+ public int get_fd ();
+ public unowned Wl.Display get_display ();
+ [CCode (cname = "wl_resource_create")]
+ public unowned Wl.Resource? create_resource (ref Wl.Interface interface, int version, uint32 id);
+ }
+
+ [Compact]
+ [CCode (cname = "struct wl_resource", free_function = "wl_resource_destroy")]
+ public class Resource {
+ public uint32 get_id ();
+ public unowned Wl.Client get_client ();
+ [CCode (simple_generics = true)]
+ public void set_user_data (T? data);
+ [CCode (simple_generics = true)]
+ public unowned T? get_user_data ();
+ public int get_version ();
+ public unowned string get_class ();
+ public void destroy ();
+ public void set_implementation (void* implementation, void* data, [CCode (delegate_target = false)] ResourceDestroyFunc destroy);
+ [PrintfFormat]
+ public void post_error(uint32 code, string format, ...);
+ }
+ [Compact]
+ [CCode (cname = "struct wl_interface")]
+ public class Interface {
+ public string name;
+ public int version;
+ [CCode (array_length = "method_count")]
+ public Wl.Message[] methods;
+ [CCode (array_length = "event_count")]
+ public Wl.Message[] events;
+ }
+
+ [Compact]
+ [CCode (cname = "struct wl_message")]
+ public class Message {
+ public string name;
+ public string signature;
+ [CCode (array_length = false)]
+ public Wl.Interface?[] types;
+ }
+
+ [Compact]
+ [CCode (cname = "struct wl_global", free_function = "wl_global_destroy")]
+ public class Global {
+ [CCode (cname = "wl_global_create")]
+ public static Wl.Global? create (Wl.Display display, ref Wl.Interface interface, int version, [CCode (delegate_target_pos = 3.9) ] Wl.GlobalBindFunc bind);
+ }
+
+ [CCode (cheader_filename = "wayland-server-protocol.h", cname = "enum wl_display_error", cprefix="WL_DISPLAY_ERROR_", has_type_id = false)]
+ public enum DisplayError {
+ INVALID_OBJECT,
+ INVALID_METHOD,
+ NO_MEMORY,
+ IMPLEMENTATION,
+ }
+
+ [CCode (cname = "wl_global_bind_func_t", instance_pos = 1.9)]
+ public delegate void GlobalBindFunc (Wl.Client client, uint32 version, uint32 id);
+ [CCode (cname = "wl_resource_destroy_func_t", has_target = false)]
+ public delegate void ResourceDestroyFunc (Wl.Resource resource);
+ [CCode (cname = "WAYLAND_VERSION_MAJOR")]
+ public const int VERSION_MAJOR;
+ [CCode (cname = "WAYLAND_VERSION_MINOR")]
+ public const int VERSION_MINOR;
+ [CCode (cname = "WAYLAND_VERSION_MICRO")]
+ public const int VERSION_MICRO;
+ [CCode (cname = "WAYLAND_VERSION")]
+ public const string VERSION;
+}
+