Skip to content
Open
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
1 change: 1 addition & 0 deletions debian/libmuffin0.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -2637,6 +2637,7 @@ libmuffin.so.0 libmuffin0 #MINVER#
meta_window_get_sandboxed_app_id@Base 5.3.0
meta_window_get_stable_sequence@Base 5.3.0
meta_window_get_startup_id@Base 5.3.0
meta_window_get_tag@Base 6.4.1
meta_window_get_tile_match@Base 5.3.0
meta_window_get_title@Base 5.3.0
meta_window_get_transient_for@Base 5.3.0
Expand Down
5 changes: 5 additions & 0 deletions src/core/window-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ struct _MetaWindow
char *sm_client_id;
char *wm_client_machine;

char *tag;

char *startup_id;
char *muffin_hints;
char *sandboxed_app_id;
Expand Down Expand Up @@ -912,4 +914,7 @@ gboolean meta_window_is_focus_async (MetaWindow *window);
gboolean meta_window_calculate_bounds (MetaWindow *window,
int *bounds_width,
int *bounds_height);

void meta_window_set_tag (MetaWindow *window,
const char *tag);
#endif
37 changes: 37 additions & 0 deletions src/core/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ enum
PROP_PROGRESS_PULSE,
PROP_TILE_MODE,
PROP_OPACITY,
PROP_TAG,
PROP_LAST,
};

Expand Down Expand Up @@ -352,6 +353,7 @@ meta_window_finalize (GObject *object)
g_free (window->gtk_app_menu_object_path);
g_free (window->gtk_menubar_object_path);
g_free (window->placement.rule);
g_free (window->tag);

G_OBJECT_CLASS (meta_window_parent_class)->finalize (object);
}
Expand Down Expand Up @@ -453,6 +455,9 @@ meta_window_get_property(GObject *object,
case PROP_OPACITY:
g_value_set_uint (value, win->opacity);
break;
case PROP_TAG:
g_value_set_string (value, win->tag);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
Expand Down Expand Up @@ -674,6 +679,12 @@ meta_window_class_init (MetaWindowClass *klass)
0xFF,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);

obj_props[PROP_TAG] =
g_param_spec_string ("tag", NULL, NULL,
NULL,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS);

g_object_class_install_properties (object_class, PROP_LAST, obj_props);

window_signals[WORKSPACE_CHANGED] =
Expand Down Expand Up @@ -9526,3 +9537,29 @@ meta_window_calculate_bounds (MetaWindow *window,
return FALSE;
}
}

void
meta_window_set_tag (MetaWindow *window,
const char *tag)
{
if (g_set_str (&window->tag, tag))
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_TAG]);
}

/**
* meta_window_get_tag:
* @window: A #MetaWindow
*
* Get a tag associated to the window.
* Under wayland the tag can be set using the toplevel tag protocol,
* and under x11 it falls back to using `NET_WM_WINDOW_TAG` atom.
*
* Returns: (nullable): An associated toplevel tag
*/
const char *
meta_window_get_tag (MetaWindow *window)
{
g_return_val_if_fail (META_IS_WINDOW (window), NULL);

return window->tag;
}
3 changes: 3 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,8 @@ if have_wayland
'wayland/meta-wayland-xdg-shell.h',
'wayland/meta-wayland-xdg-dialog.c',
'wayland/meta-wayland-xdg-dialog.h',
'wayland/meta-wayland-xdg-toplevel-tag.c',
'wayland/meta-wayland-xdg-toplevel-tag.h',
'wayland/meta-window-wayland.c',
'wayland/meta-window-wayland.h',
'wayland/meta-window-xwayland.c',
Expand Down Expand Up @@ -811,6 +813,7 @@ if have_wayland
['xdg-foreign', 'unstable', 'v2', ],
['xdg-output', 'unstable', 'v1', ],
['xdg-shell', 'stable', ],
['xdg-toplevel-tag-v1', 'private', ],
['xwayland-keyboard-grab', 'unstable', 'v1', ],
]
if have_wayland_eglstream
Expand Down
3 changes: 3 additions & 0 deletions src/meta/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,4 +469,7 @@ void meta_window_set_opacity (MetaWindow *window,
META_EXPORT
guint8 meta_window_get_opacity (MetaWindow *window);

META_EXPORT
const char * meta_window_get_tag (MetaWindow *window);

#endif
1 change: 1 addition & 0 deletions src/wayland/meta-wayland-versions.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@
#define META_WP_VIEWPORTER_VERSION 1
#define META_XDG_DIALOG_VERSION 1
#define META_ZWP_PRIMARY_SELECTION_V1_VERSION 1
#define META_XDG_TOPLEVEL_TAG_V1_VERSION 1

#endif
105 changes: 105 additions & 0 deletions src/wayland/meta-wayland-xdg-toplevel-tag.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (C) 2024 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Written by:
* Bilal Elmoussaoui <[email protected]>
*/

#include "config.h"

#include "wayland/meta-wayland-xdg-toplevel-tag.h"

#include <wayland-server.h>

#include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-versions.h"
#include "wayland/meta-wayland-xdg-shell.h"

#include "xdg-toplevel-tag-v1-server-protocol.h"

static void
xdg_toplevel_tag_manager_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}

static void
xdg_toplevel_tag_manager_set_toplevel_tag (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *toplevel_resource,
const char *tag)
{
MetaWaylandXdgToplevel *xdg_toplevel;
MetaWaylandSurfaceRole *surface_role;
MetaWaylandSurface *surface;
MetaWindow *window;

if (!toplevel_resource)
return;

xdg_toplevel = wl_resource_get_user_data (toplevel_resource);
surface_role = META_WAYLAND_SURFACE_ROLE (xdg_toplevel);
surface = meta_wayland_surface_role_get_surface (surface_role);
window = meta_wayland_surface_get_window (surface);

meta_window_set_tag (window, tag);
}

static void
xdg_toplevel_tag_manager_set_toplevel_tag_description (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *toplevel,
const char *tag_description)
{
/* We don't make use of the toplevel tag description */
}

static const struct xdg_toplevel_tag_manager_v1_interface meta_xdg_toplevel_tag_interface = {
xdg_toplevel_tag_manager_destroy,
xdg_toplevel_tag_manager_set_toplevel_tag,
xdg_toplevel_tag_manager_set_toplevel_tag_description,
};


static void
bind_xdg_toplevel_tag (struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
struct wl_resource *resource;

resource = wl_resource_create (client,
&xdg_toplevel_tag_manager_v1_interface,
META_XDG_TOPLEVEL_TAG_V1_VERSION,
id);

wl_resource_set_implementation (resource,
&meta_xdg_toplevel_tag_interface,
NULL, NULL);
}

void
meta_wayland_xdg_toplevel_tag_init (MetaWaylandCompositor *compositor)
{
if (wl_global_create (compositor->wayland_display,
&xdg_toplevel_tag_manager_v1_interface,
META_XDG_TOPLEVEL_TAG_V1_VERSION,
NULL,
bind_xdg_toplevel_tag) == NULL)
g_error ("Failed to register a global xdg-toplevel-tag object");
}
27 changes: 27 additions & 0 deletions src/wayland/meta-wayland-xdg-toplevel-tag.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2024 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Written by:
* Bilal Elmoussaoui <[email protected]>
*/

#pragma once

#include <glib.h>

#include "wayland/meta-wayland-types.h"

void meta_wayland_xdg_toplevel_tag_init (MetaWaylandCompositor *compositor);
2 changes: 2 additions & 0 deletions src/wayland/meta-wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "wayland/meta-wayland-tablet-manager.h"
#include "wayland/meta-wayland-xdg-dialog.h"
#include "wayland/meta-wayland-xdg-foreign.h"
#include "wayland/meta-wayland-xdg-toplevel-tag.h"
#include "wayland/meta-xwayland-grab-keyboard.h"
#include "wayland/meta-xwayland-private.h"
#include "wayland/meta-xwayland.h"
Expand Down Expand Up @@ -440,6 +441,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
meta_wayland_surface_inhibit_shortcuts_dialog_init ();
meta_wayland_text_input_init (compositor);
meta_wayland_init_xdg_wm_dialog (compositor);
meta_wayland_xdg_toplevel_tag_init (compositor);

/* Xwayland specific protocol, needs to be filtered out for all other clients */
if (meta_xwayland_grab_keyboard_init (compositor))
Expand Down
85 changes: 85 additions & 0 deletions src/wayland/protocol/xdg-toplevel-tag-v1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="xdg_toplevel_tag_v1">
<copyright>
Copyright © 2024 Xaver Hugl

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.
</copyright>

<interface name="xdg_toplevel_tag_manager_v1" version="1">
<description summary="protocol for setting toplevel tags">
In order to make some window properties like position, size,
"always on top" or user defined rules for window behavior persistent, the
compositor needs some way to identify windows even after the application
has been restarted.
This protocol allows clients to make this possible by setting a tag for
toplevels.

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="destroy" type="destructor">
<description summary="destroy toplevel tag object">
Destroy this toplevel tag manager object. This request has no other
effects.
</description>
</request>

<request name="set_toplevel_tag">
<description summary="set tag">
Set a tag for a toplevel. The tag may be shown to the user in UI, so
it's preferable for it to be human readable, but it must be suitable
for configuration files and should not be translated.
Suitable tags would for example be "main window", "settings",
"e-mail composer" or similar.

The tag does not need to be unique across applications, and the client
may set the same tag for multiple windows, for example if the user has
opened the same UI twice. How the potentially resulting conflicts are
handled is compositor policy.

The client should set the tag as part of the initial commit on the
associated toplevel, but it may set it at any time afterwards as well,
for example if the purpose of the toplevel changes.
</description>
<arg name="toplevel" type="object" interface="xdg_toplevel"/>
<arg name="tag" type="string" summary="untranslated tag"/>
</request>

<request name="set_toplevel_description">
<description summary="set description">
Set a description for a toplevel. This description may be shown to the
user in UI or read by a screen reader for accessibility purposes, and
should be translated.
It is recommended to make the description the translation of the tag.

The client should set the description as part of the initial commit on
the associated toplevel, but it may set it at any time afterwards as
well, for example if the purpose of the toplevel changes.
</description>
<arg name="toplevel" type="object" interface="xdg_toplevel"/>
<arg name="description" type="string" summary="translated description"/>
</request>
</interface>

</protocol>
1 change: 1 addition & 0 deletions src/x11/atomnames.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ item(_NET_WM_OPAQUE_REGION)
item(_NET_WM_FRAME_DRAWN)
item(_NET_WM_FRAME_TIMINGS)
item(_NET_WM_WINDOW_OPACITY)
item(_NET_WM_WINDOW_TAG)
item(_NET_RESTACK_WINDOW)
item(_NET_WM_XAPP_ICON_NAME)
item(_NET_WM_XAPP_PROGRESS)
Expand Down
9 changes: 9 additions & 0 deletions src/x11/window-props.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,14 @@ reload_struts (MetaWindow *window,
meta_window_update_struts (window);
}

static void
reload_toplevel_tag (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
meta_window_set_tag (window, value->v.str);
}

static void
reload_wm_window_role (MetaWindow *window,
MetaPropValue *value,
Expand Down Expand Up @@ -2055,6 +2063,7 @@ meta_x11_display_init_window_prop_hooks (MetaX11Display *x11_display)
{ x11_display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, NONE },
{ x11_display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, LOAD_INIT | INCLUDE_OR },
{ x11_display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, LOAD_INIT | INCLUDE_OR },
{ x11_display->atom__NET_WM_WINDOW_TAG, META_PROP_VALUE_STRING, reload_toplevel_tag, LOAD_INIT },
{ x11_display->atom__NET_WM_XAPP_ICON_NAME, META_PROP_VALUE_UTF8, reload_theme_icon_name, LOAD_INIT | INCLUDE_OR },
{ x11_display->atom__NET_WM_XAPP_PROGRESS, META_PROP_VALUE_CARDINAL, reload_progress, LOAD_INIT | INCLUDE_OR },
{ x11_display->atom__NET_WM_XAPP_PROGRESS_PULSE, META_PROP_VALUE_CARDINAL, reload_progress_pulse, LOAD_INIT | INCLUDE_OR },
Expand Down
Loading