summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml2
-rw-r--r--.gitignore86
-rw-r--r--applets/clock/calendar-window.c4
-rw-r--r--applets/clock/clock.c10
-rw-r--r--applets/clock/meson.build241
-rw-r--r--applets/fish/meson.build138
-rw-r--r--applets/meson.build4
-rw-r--r--applets/notification_area/libstatus-notifier-watcher/meson.build12
-rw-r--r--applets/notification_area/meson.build162
-rw-r--r--applets/notification_area/status-notifier/meson.build40
-rw-r--r--applets/notification_area/system-tray/meson.build23
-rw-r--r--applets/wncklet/Makefile.am28
-rw-r--r--applets/wncklet/meson.build164
-rw-r--r--applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in2
-rw-r--r--applets/wncklet/wayland-workspace.c526
-rw-r--r--applets/wncklet/wayland-workspace.h52
-rw-r--r--applets/wncklet/window-list.c100
-rw-r--r--applets/wncklet/wncklet.c2
-rw-r--r--applets/wncklet/workspace-switcher.c155
-rw-r--r--configure.ac11
-rw-r--r--data/default.layout18
-rw-r--r--data/fedora.layout28
-rw-r--r--data/linuxmint.layout14
-rw-r--r--data/mageia.layout25
-rw-r--r--data/meson.build64
-rw-r--r--data/opensuse.layout22
-rw-r--r--data/org.mate.panel.object.gschema.xml.in18
-rw-r--r--data/ubuntu.layout28
-rw-r--r--doc/meson.build1
-rw-r--r--doc/reference/mate-panel-applet/meson.build22
-rw-r--r--doc/reference/meson.build1
-rw-r--r--help/mate-clock/meson.build21
-rw-r--r--help/mate-fish/meson.build21
-rw-r--r--help/meson.build2
-rw-r--r--icons/meson.build53
-rw-r--r--libmate-panel-applet/meson.build145
-rw-r--r--man/meson.build5
-rw-r--r--mate-panel/applet.c132
-rw-r--r--mate-panel/applet.h35
-rw-r--r--mate-panel/drawer-private.h2
-rw-r--r--mate-panel/drawer.c27
-rw-r--r--mate-panel/drawer.h2
-rw-r--r--mate-panel/launcher.c18
-rw-r--r--mate-panel/launcher.h2
-rw-r--r--mate-panel/libmate-panel-applet-private/meson.build47
-rw-r--r--mate-panel/libmate-panel-applet-private/panel-applet-frame-dbus.c10
-rw-r--r--mate-panel/libpanel-util/meson.build33
-rw-r--r--mate-panel/meson.build355
-rw-r--r--mate-panel/panel-action-button.c16
-rw-r--r--mate-panel/panel-action-button.h2
-rw-r--r--mate-panel/panel-applet-frame.c49
-rw-r--r--mate-panel/panel-applet-frame.h2
-rw-r--r--mate-panel/panel-enums-gsettings.h6
-rw-r--r--mate-panel/panel-layout.c2
-rw-r--r--mate-panel/panel-menu-bar.c16
-rw-r--r--mate-panel/panel-menu-bar.h2
-rw-r--r--mate-panel/panel-menu-button.c16
-rw-r--r--mate-panel/panel-menu-button.h2
-rw-r--r--mate-panel/panel-profile.c51
-rw-r--r--mate-panel/panel-profile.h19
-rw-r--r--mate-panel/panel-schemas.h2
-rw-r--r--mate-panel/panel-separator.c12
-rw-r--r--mate-panel/panel-separator.h2
-rw-r--r--mate-panel/panel-widget.c1166
-rw-r--r--mate-panel/panel-widget.h27
-rw-r--r--mate-panel/panel.c20
-rw-r--r--mate-panel/panel.h2
-rw-r--r--meson.build325
-rw-r--r--meson_options.txt60
-rw-r--r--po/LINGUAS1
-rw-r--r--po/meson.build6
71 files changed, 3905 insertions, 814 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d1febfd6..40c9afb4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -39,6 +39,7 @@ env:
libsoup-3.0-dev
libwnck-3-dev
libx11-dev
+ libxfce4windowing-0-dev
libxrandr-dev
# mate-desktop dependencies
DEB_LIBRARY_DEPS_MATE_DESKTOP: |
@@ -79,6 +80,7 @@ env:
libmateweather
libsm
libwnck3
+ libxfce4windowing
make
mate-common
mate-desktop
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..615554d2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,86 @@
+# Build artifacts
+*.o
+*.lo
+*.la
+.deps/
+.libs/
+*.gcda
+*.gcno
+*.orig
+*.rej
+*.tab.c
+*~
+.*.sw[nop]
+.dirstamp
+/build/
+/build-inproc/
+/builddir/
+/meson-private/
+/Makefile
+/Makefile.in
+
+# Autotools generated
+/ABOUT-NLS
+/GPATH
+/GRTAGS
+/GSYMS
+/GTAGS
+/ID
+/INSTALL
+/TAGS
+/aclocal.m4
+/autom4te.cache/
+/compile
+/config.cache
+/config.guess
+/config.h
+/config.h.in
+/config.log
+/config.lt
+/config.rpath
+/config.status
+/config.status.lineno
+/config.sub
+/configure
+/configure.lineno
+/depcomp
+/gtk-doc.make
+/install-sh
+/intltool-extract.in
+/intltool-merge.in
+/intltool-update.in
+/libtool
+/ltmain.sh
+/m4/
+/missing
+/mkinstalldirs
+/omf.make
+/so_locations
+/stamp-h1
+/tags
+/xmldocs.make
+
+# Generated data
+/data/Makefile
+/data/Makefile.in
+/data/org.mate.panel.enums.xml
+/data/*.gschema.xml
+/data/*.valid
+
+# gettext/po generated
+/po/*.gmo
+/po/*.header
+/po/*.mo
+/po/*.sed
+/po/*.sin
+/po/.intltool-merge-cache
+/po/Makefile
+/po/Makefile.in
+/po/Makefile.in.in
+/po/Makefile.in.in~
+/po/Makevars.template
+/po/POTFILES
+/po/Rules-quot
+/po/mate-panel.pot
+/po/stamp-it
+/po/stamp-po
diff --git a/applets/clock/calendar-window.c b/applets/clock/calendar-window.c
index bd117a3f..79780d34 100644
--- a/applets/clock/calendar-window.c
+++ b/applets/clock/calendar-window.c
@@ -1423,6 +1423,8 @@ handle_appointments_changed (CalendarWindow *calwin)
update_frame_visibility (calwin->priv->appointment_list,
GTK_TREE_MODEL (calwin->priv->appointments_filter));
+ g_slist_free_full (events, (GDestroyNotify) calendar_event_free);
+
/* Auto-scroll to next upcoming event */
if (calwin->priv->appointment_tree_view) {
GtkTreeView *tree_view = GTK_TREE_VIEW(calwin->priv->appointment_tree_view);
@@ -1544,6 +1546,8 @@ handle_tasks_changed (CalendarWindow *calwin)
g_free (percent_complete_text);
}
+ g_slist_free_full (events, (GDestroyNotify) calendar_event_free);
+
/* Refresh filter before checking visibility */
if (calwin->priv->tasks_filter)
gtk_tree_model_filter_refilter (calwin->priv->tasks_filter);
diff --git a/applets/clock/clock.c b/applets/clock/clock.c
index 2aff3878..0c104f31 100644
--- a/applets/clock/clock.c
+++ b/applets/clock/clock.c
@@ -1546,6 +1546,16 @@ create_main_clock_label (ClockData *cd)
GtkWidget *label;
label = gtk_label_new (NULL);
+
+ // Fix proportional font by font feature tabular numbers (tnum) (if supported by the font)
+ PangoAttribute *attr;
+ PangoAttrList *alist;
+ attr = pango_attr_font_features_new ("tnum=1");
+ alist = pango_attr_list_new ();
+ pango_attr_list_insert (alist, attr);
+ gtk_label_set_attributes (GTK_LABEL (label), alist);
+ pango_attr_list_unref (alist);
+
/*Fixme-this is invalid for labels with any recent GTK3 version, maybe all of them*/
/*
g_signal_connect (label, "size-request",
diff --git a/applets/clock/meson.build b/applets/clock/meson.build
new file mode 100644
index 00000000..c0db5a17
--- /dev/null
+++ b/applets/clock/meson.build
@@ -0,0 +1,241 @@
+clock_enum_headers = ['clock-utils.h']
+
+clock_typebuiltins_h = custom_target('clock-typebuiltins.h',
+ input: clock_enum_headers,
+ output: 'clock-typebuiltins.h',
+ command: [
+ glib_mkenums,
+ '--fhead', '#ifndef __CLOCK_TYPEBUILTINS_H__\n',
+ '--fhead', '#define __CLOCK_TYPEBUILTINS_H__ 1\n\n',
+ '--fhead', '#ifdef __cplusplus\nextern "C" {\n#endif\n\n',
+ '--ftail', '#ifdef __cplusplus\n}\n#endif\n\n',
+ '--ftail', '#endif /* __CLOCK_TYPEBUILTINS_H__ */\n',
+ '--fprod', '\n/* --- @filename@ --- */',
+ '--eprod', '#define CLOCK_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n',
+ '--eprod', 'GType @enum_name@_get_type (void);\n',
+ '--output', '@OUTPUT@',
+ '@INPUT@',
+ ],
+)
+
+clock_typebuiltins_c = custom_target('clock-typebuiltins.c',
+ input: clock_enum_headers,
+ output: 'clock-typebuiltins.c',
+ command: [
+ glib_mkenums,
+ '--fhead', '#include <glib-object.h>\n',
+ '--fhead', '#include "clock-typebuiltins.h"\n\n',
+ '--fprod', '\n/* enumerations from "@filename@" */',
+ '--fprod', '\n#include "@filename@"\n',
+ '--vhead', 'static const GEnumValue _@enum_name@_values[] = {',
+ '--vprod', ' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },',
+ '--vtail', ' { 0, NULL, NULL }\n};\n\n',
+ '--vtail', 'GType\n@enum_name@_get_type (void)\n{\n',
+ '--vtail', ' static GType type = 0;\n\n',
+ '--vtail', ' if (!type)\n',
+ '--vtail', ' type = g_enum_register_static ("@EnumName@", _@enum_name@_values);\n\n',
+ '--vtail', ' return type;\n}\n\n',
+ '--output', '@OUTPUT@',
+ '@INPUT@',
+ ],
+)
+
+clock_marshal = gnome.genmarshal('clock-marshallers',
+ sources: 'clock-marshallers.list',
+ prefix: '_clock_marshal',
+ internal: true,
+)
+
+clock_resource_deps = files(
+ 'clock.ui',
+ 'clock-menu.xml',
+ 'pixmaps/clock-face-large.svg',
+ 'pixmaps/clock-face-small.svg',
+ 'pixmaps/clock-face-small-morning.svg',
+ 'pixmaps/clock-face-small-day.svg',
+ 'pixmaps/clock-face-small-evening.svg',
+ 'pixmaps/clock-face-small-night.svg',
+ 'pixmaps/clock-map.png',
+ 'pixmaps/clock-map-location-marker.png',
+ 'pixmaps/clock-map-location-current.png',
+ 'pixmaps/clock-map-location-hilight.png',
+)
+
+clock_resources_c = custom_target('clock-resources.c',
+ input: 'clock.gresource.xml',
+ output: 'clock-resources.c',
+ depend_files: clock_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-source',
+ '--c-name', 'clock',
+ '@INPUT@',
+ ],
+)
+
+clock_resources_h = custom_target('clock-resources.h',
+ input: 'clock.gresource.xml',
+ output: 'clock-resources.h',
+ depend_files: clock_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-header',
+ '--c-name', 'clock',
+ '@INPUT@',
+ ],
+)
+
+clock_built_sources = [
+ clock_marshal,
+ clock_resources_c,
+ clock_resources_h,
+ clock_typebuiltins_c,
+ clock_typebuiltins_h,
+]
+
+# system timezone helper
+libsystem_timezone = static_library('system-timezone',
+ 'system-timezone.c',
+ 'system-timezone.h',
+ dependencies: [gio_dep],
+ c_args: disable_deprecated_flags,
+)
+
+executable('test-system-timezone',
+ 'test-system-timezone.c',
+ dependencies: [gio_dep],
+ link_with: libsystem_timezone,
+ c_args: disable_deprecated_flags,
+)
+
+clock_sources = [
+ 'calendar-window.c',
+ 'calendar-window.h',
+ 'clock.c',
+ 'clock.h',
+ 'clock-face.c',
+ 'clock-face.h',
+ 'clock-location.c',
+ 'clock-location.h',
+ 'clock-location-tile.c',
+ 'clock-location-tile.h',
+ 'clock-map.c',
+ 'clock-map.h',
+ 'clock-sunpos.c',
+ 'clock-sunpos.h',
+ 'clock-utils.c',
+ 'clock-utils.h',
+ 'set-timezone.c',
+ 'set-timezone.h',
+ clock_built_sources,
+]
+
+if have_eds
+ clock_sources += [
+ 'calendar-client.c',
+ 'calendar-client.h',
+ 'calendar-sources.c',
+ 'calendar-sources.h',
+ 'calendar-debug.h',
+ ]
+endif
+
+clock_deps = [
+ pango_dep,
+ gtk_dep,
+ glib_dep,
+ gio_dep,
+ mateweather_dep,
+ mate_desktop_dep,
+ m_dep,
+] + libmate_panel_applet_deps
+
+if have_eds
+ clock_deps += eds_deps
+endif
+
+if have_wayland
+ clock_deps += wayland_deps
+endif
+
+clock_inc_dirs = [
+ include_directories('.'),
+ libmate_panel_applet_inc,
+]
+
+clock_c_args = [
+ '-DMATELOCALEDIR="@0@"'.format(mate_panel_localedir),
+ '-DMATEWEATHER_I_KNOW_THIS_IS_UNSTABLE',
+] + disable_deprecated_flags
+
+if clock_inprocess
+ clock_applet = shared_library('clock-applet',
+ clock_sources,
+ include_directories: clock_inc_dirs,
+ dependencies: clock_deps,
+ c_args: clock_c_args,
+ link_with: [libmate_panel_applet_lib, libsystem_timezone],
+ install: true,
+ install_dir: mate_panel_pkglibdir,
+ )
+ clock_applet_in_process = 'true'
+ clock_applet_location = join_paths(mate_panel_pkglibdir, 'libclock-applet.so')
+else
+ clock_applet = executable('clock-applet',
+ clock_sources,
+ include_directories: clock_inc_dirs,
+ dependencies: clock_deps,
+ c_args: clock_c_args,
+ link_with: [libmate_panel_applet_lib, libsystem_timezone],
+ install: true,
+ install_dir: mate_panel_libexecdir,
+ )
+ clock_applet_in_process = 'false'
+ clock_applet_location = join_paths(mate_panel_libexecdir, 'clock-applet')
+endif
+
+# applet registration file
+clock_applet_desktop_in = configure_file(
+ input: 'org.mate.panel.ClockApplet.mate-panel-applet.desktop.in.in',
+ output: 'org.mate.panel.ClockApplet.mate-panel-applet.desktop.in',
+ configuration: {
+ 'IN_PROCESS': clock_applet_in_process,
+ 'LOCATION': clock_applet_location,
+ 'VERSION': mate_panel_version,
+ },
+)
+
+clock_applet_desktop = i18n.merge_file(
+ input: clock_applet_desktop_in,
+ output: 'org.mate.panel.ClockApplet.mate-panel-applet',
+ type: 'desktop',
+ po_dir: '../../po',
+ install: true,
+ install_dir: mate_panel_appletsdir,
+)
+
+if not clock_inprocess
+ clock_service = configure_file(
+ input: 'org.mate.panel.applet.ClockAppletFactory.service.in',
+ output: 'org.mate.panel.applet.ClockAppletFactory.service',
+ configuration: {
+ 'LOCATION': clock_applet_location,
+ },
+ )
+ install_data(clock_service,
+ install_dir: join_paths(mate_panel_datadir, 'dbus-1', 'services'),
+ )
+endif
+
+# gsettings schema
+clock_gschema = configure_file(
+ input: 'org.mate.panel.applet.clock.gschema.xml.in',
+ output: 'org.mate.panel.applet.clock.gschema.xml',
+ configuration: {'GETTEXT_PACKAGE': mate_panel_gettext_package},
+)
+
+install_data(clock_gschema, install_dir: mate_panel_schemadir)
diff --git a/applets/fish/meson.build b/applets/fish/meson.build
new file mode 100644
index 00000000..59d538e7
--- /dev/null
+++ b/applets/fish/meson.build
@@ -0,0 +1,138 @@
+mate_panel_fishdir = join_paths(mate_panel_pkgdatadir, 'fish')
+
+fish_resource_deps = files(
+ 'fish.ui',
+ 'fish-menu.xml',
+)
+
+fish_resources_c = custom_target('fish-resources.c',
+ input: 'fish.gresource.xml',
+ output: 'fish-resources.c',
+ depend_files: fish_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-source',
+ '--c-name', 'fish',
+ '@INPUT@',
+ ],
+)
+
+fish_resources_h = custom_target('fish-resources.h',
+ input: 'fish.gresource.xml',
+ output: 'fish-resources.h',
+ depend_files: fish_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-header',
+ '--c-name', 'fish',
+ '@INPUT@',
+ ],
+)
+
+fish_built_sources = [
+ fish_resources_c,
+ fish_resources_h,
+]
+
+fish_sources = [
+ 'fish.c',
+ fish_built_sources,
+]
+
+fish_deps = [
+ gtk_dep,
+ cairo_dep,
+ mate_desktop_dep,
+] + libmate_panel_applet_deps
+
+fish_inc_dirs = [
+ include_directories('.'),
+ libmate_panel_applet_inc,
+]
+
+fish_c_args = [
+ '-DMATELOCALEDIR="@0@"'.format(mate_panel_localedir),
+ '-DFISH_ICONDIR="@0@"'.format(mate_panel_fishdir),
+] + disable_deprecated_flags
+
+if fish_inprocess
+ fish_applet = shared_library('fish-applet',
+ fish_sources,
+ include_directories: fish_inc_dirs,
+ dependencies: fish_deps,
+ c_args: fish_c_args,
+ link_with: libmate_panel_applet_lib,
+ install: true,
+ install_dir: mate_panel_pkglibdir,
+ )
+ fish_applet_in_process = 'true'
+ fish_applet_location = join_paths(mate_panel_pkglibdir, 'libfish-applet.so')
+else
+ fish_applet = executable('fish-applet',
+ fish_sources,
+ include_directories: fish_inc_dirs,
+ dependencies: fish_deps,
+ c_args: fish_c_args,
+ link_with: libmate_panel_applet_lib,
+ install: true,
+ install_dir: mate_panel_libexecdir,
+ )
+ fish_applet_in_process = 'false'
+ fish_applet_location = join_paths(mate_panel_libexecdir, 'fish-applet')
+endif
+
+# applet registration file
+fish_applet_desktop_in = configure_file(
+ input: 'org.mate.panel.FishApplet.mate-panel-applet.desktop.in.in',
+ output: 'org.mate.panel.FishApplet.mate-panel-applet.desktop.in',
+ configuration: {
+ 'IN_PROCESS': fish_applet_in_process,
+ 'LOCATION': fish_applet_location,
+ 'VERSION': mate_panel_version,
+ },
+)
+
+fish_applet_desktop = i18n.merge_file(
+ input: fish_applet_desktop_in,
+ output: 'org.mate.panel.FishApplet.mate-panel-applet',
+ type: 'desktop',
+ po_dir: '../../po',
+ install: true,
+ install_dir: mate_panel_appletsdir,
+)
+
+if not fish_inprocess
+ fish_service = configure_file(
+ input: 'org.mate.panel.applet.FishAppletFactory.service.in',
+ output: 'org.mate.panel.applet.FishAppletFactory.service',
+ configuration: {
+ 'LOCATION': fish_applet_location,
+ },
+ )
+ install_data(fish_service,
+ install_dir: join_paths(mate_panel_datadir, 'dbus-1', 'services'),
+ )
+endif
+
+# fish bitmaps
+install_data(
+ 'wanda.png',
+ 'fishanim.png',
+ 'oldwanda.png',
+ 'footguy.png',
+ 'monkey.png',
+ install_dir: mate_panel_fishdir,
+)
+
+# gsettings schema
+fish_gschema = configure_file(
+ input: 'org.mate.panel.applet.fish.gschema.xml.in',
+ output: 'org.mate.panel.applet.fish.gschema.xml',
+ configuration: {'GETTEXT_PACKAGE': mate_panel_gettext_package},
+)
+
+install_data(fish_gschema, install_dir: mate_panel_schemadir)
diff --git a/applets/meson.build b/applets/meson.build
new file mode 100644
index 00000000..21511944
--- /dev/null
+++ b/applets/meson.build
@@ -0,0 +1,4 @@
+subdir('clock')
+subdir('fish')
+subdir('wncklet')
+subdir('notification_area')
diff --git a/applets/notification_area/libstatus-notifier-watcher/meson.build b/applets/notification_area/libstatus-notifier-watcher/meson.build
new file mode 100644
index 00000000..a180a16e
--- /dev/null
+++ b/applets/notification_area/libstatus-notifier-watcher/meson.build
@@ -0,0 +1,12 @@
+libstatus_notifier_watcher = static_library('status-notifier-watcher',
+ 'gf-sn-watcher-v0.c',
+ 'gf-sn-watcher-v0.h',
+ 'gf-status-notifier-watcher.c',
+ 'gf-status-notifier-watcher.h',
+ gnome.gdbus_codegen('gf-sn-watcher-v0-gen',
+ 'org.kde.StatusNotifierWatcher.xml',
+ namespace: 'Gf',
+ ),
+ dependencies: notification_area_deps,
+ c_args: ['-DG_LOG_DOMAIN="status-notifier-watcher"'] + disable_deprecated_flags,
+)
diff --git a/applets/notification_area/meson.build b/applets/notification_area/meson.build
new file mode 100644
index 00000000..74400b21
--- /dev/null
+++ b/applets/notification_area/meson.build
@@ -0,0 +1,162 @@
+notification_area_deps = [
+ gtk_dep,
+ mate_desktop_dep,
+]
+
+notification_area_c_args = [
+ '-DMATELOCALEDIR="@0@"'.format(mate_panel_localedir),
+ '-DG_LOG_DOMAIN="notification-area-applet"',
+ '-DPROVIDE_WATCHER_SERVICE=1',
+] + disable_deprecated_flags
+
+subdir('libstatus-notifier-watcher')
+subdir('status-notifier')
+
+if have_x11
+ subdir('system-tray')
+endif
+
+libtray_sources = [
+ 'na-grid.c',
+ 'na-grid.h',
+ 'na-host.c',
+ 'na-host.h',
+ 'na-item.c',
+ 'na-item.h',
+]
+
+libtray = static_library('tray',
+ libtray_sources + status_notifier_codegen,
+ include_directories: [include_directories('.'), include_directories('status-notifier')],
+ dependencies: notification_area_deps,
+ link_with: [libstatus_notifier, libstatus_notifier_watcher],
+ c_args: notification_area_c_args,
+)
+
+if have_x11
+ libtray_extra_link = libsystem_tray
+ executable('testtray',
+ 'testtray.c',
+ include_directories: include_directories('.'),
+ dependencies: notification_area_deps,
+ link_with: [libtray, libstatus_notifier, libstatus_notifier_watcher, libsystem_tray],
+ c_args: notification_area_c_args,
+ )
+else
+ libtray_extra_link = []
+endif
+
+na_resource_deps = files(
+ 'notification-area-preferences-dialog.ui',
+ 'notification-area-menu.xml',
+)
+
+na_resources_c = custom_target('na-resources.c',
+ input: 'na.gresource.xml',
+ output: 'na-resources.c',
+ depend_files: na_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-source',
+ '--c-name', 'na',
+ '@INPUT@',
+ ],
+)
+
+na_resources_h = custom_target('na-resources.h',
+ input: 'na.gresource.xml',
+ output: 'na-resources.h',
+ depend_files: na_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-header',
+ '--c-name', 'na',
+ '@INPUT@',
+ ],
+)
+
+notification_area_sources = [
+ 'main.c',
+ 'main.h',
+ na_resources_c,
+ na_resources_h,
+]
+
+notification_area_full_deps = notification_area_deps + libmate_panel_applet_deps
+
+notification_area_inc_dirs = [
+ include_directories('.'),
+ libmate_panel_applet_inc,
+]
+
+if notification_area_inprocess
+ notification_area_applet = shared_library('notification-area-applet',
+ notification_area_sources,
+ include_directories: notification_area_inc_dirs,
+ dependencies: notification_area_full_deps,
+ c_args: notification_area_c_args,
+ link_with: [libmate_panel_applet_lib, libtray, libstatus_notifier, libstatus_notifier_watcher] + libtray_extra_link,
+ install: true,
+ install_dir: mate_panel_pkglibdir,
+ )
+ notification_area_applet_in_process = 'true'
+ notification_area_applet_location = join_paths(mate_panel_pkglibdir, 'libnotification-area-applet.so')
+else
+ notification_area_applet = executable('notification-area-applet',
+ notification_area_sources,
+ include_directories: notification_area_inc_dirs,
+ dependencies: notification_area_full_deps,
+ c_args: notification_area_c_args,
+ link_with: [libmate_panel_applet_lib, libtray, libstatus_notifier, libstatus_notifier_watcher] + libtray_extra_link,
+ install: true,
+ install_dir: mate_panel_libexecdir,
+ )
+ notification_area_applet_in_process = 'false'
+ notification_area_applet_location = join_paths(mate_panel_libexecdir, 'notification-area-applet')
+endif
+
+# applet registration file
+notification_area_applet_desktop_in = configure_file(
+ input: 'org.mate.panel.NotificationAreaApplet.mate-panel-applet.desktop.in.in',
+ output: 'org.mate.panel.NotificationAreaApplet.mate-panel-applet.desktop.in',
+ configuration: {
+ 'IN_PROCESS': notification_area_applet_in_process,
+ 'LOCATION': notification_area_applet_location,
+ 'VERSION': mate_panel_version,
+ },
+)
+
+notification_area_applet_desktop = i18n.merge_file(
+ input: notification_area_applet_desktop_in,
+ output: 'org.mate.panel.NotificationAreaApplet.mate-panel-applet',
+ type: 'desktop',
+ po_dir: '../../po',
+ install: true,
+ install_dir: mate_panel_appletsdir,
+)
+
+if not notification_area_inprocess
+ notification_area_service = configure_file(
+ input: 'org.mate.panel.applet.NotificationAreaAppletFactory.service.in',
+ output: 'org.mate.panel.applet.NotificationAreaAppletFactory.service',
+ configuration: {
+ 'LOCATION': notification_area_applet_location,
+ },
+ )
+ install_data(notification_area_service,
+ install_dir: join_paths(mate_panel_datadir, 'dbus-1', 'services'),
+ )
+endif
+
+# gsettings schema
+notification_area_gschema = configure_file(
+ input: 'org.mate.panel.applet.notification-area.gschema.xml.in',
+ output: 'org.mate.panel.applet.notification-area.gschema.xml',
+ configuration: {'GETTEXT_PACKAGE': mate_panel_gettext_package},
+)
+
+install_data(notification_area_gschema, install_dir: mate_panel_schemadir)
diff --git a/applets/notification_area/status-notifier/meson.build b/applets/notification_area/status-notifier/meson.build
new file mode 100644
index 00000000..6f6305a5
--- /dev/null
+++ b/applets/notification_area/status-notifier/meson.build
@@ -0,0 +1,40 @@
+status_notifier_codegen = [
+ gnome.gdbus_codegen('sn-dbus-menu-gen',
+ 'com.canonical.dbusmenu.xml',
+ namespace: 'Sn',
+ ),
+ gnome.gdbus_codegen('sn-host-v0-gen',
+ 'org.kde.StatusNotifierHost.xml',
+ namespace: 'Sn',
+ ),
+ gnome.gdbus_codegen('sn-item-v0-gen',
+ 'org.kde.StatusNotifierItem.xml',
+ namespace: 'Sn',
+ ),
+ gnome.gdbus_codegen('sn-watcher-v0-gen',
+ 'org.kde.StatusNotifierWatcher.xml',
+ namespace: 'Sn',
+ ),
+]
+
+libstatus_notifier = static_library('status-notifier',
+ 'sn-dbus-menu.c',
+ 'sn-dbus-menu.h',
+ 'sn-dbus-menu-item.c',
+ 'sn-dbus-menu-item.h',
+ 'sn-flat-button.c',
+ 'sn-flat-button.h',
+ 'sn-host-v0.c',
+ 'sn-host-v0.h',
+ 'sn-item.c',
+ 'sn-item.h',
+ 'sn-item-v0.c',
+ 'sn-item-v0.h',
+ status_notifier_codegen,
+ include_directories: [include_directories('.'), include_directories('..')],
+ dependencies: notification_area_deps + [m_dep],
+ c_args: [
+ '-DMATELOCALEDIR="@0@"'.format(mate_panel_localedir),
+ '-DG_LOG_DOMAIN="notification-area-applet"',
+ ] + disable_deprecated_flags,
+)
diff --git a/applets/notification_area/system-tray/meson.build b/applets/notification_area/system-tray/meson.build
new file mode 100644
index 00000000..a3add66a
--- /dev/null
+++ b/applets/notification_area/system-tray/meson.build
@@ -0,0 +1,23 @@
+na_marshal = gnome.genmarshal('na-marshal',
+ sources: 'na-marshal.list',
+ prefix: '_na_marshal',
+ internal: true,
+)
+
+libsystem_tray = static_library('system-tray',
+ 'fixedtip.c',
+ 'fixedtip.h',
+ na_marshal,
+ 'na-tray.c',
+ 'na-tray.h',
+ 'na-tray-child.c',
+ 'na-tray-child.h',
+ 'na-tray-manager.c',
+ 'na-tray-manager.h',
+ include_directories: [include_directories('.'), include_directories('..')],
+ dependencies: notification_area_deps + [x11_dep],
+ c_args: [
+ '-DMATELOCALEDIR="@0@"'.format(mate_panel_localedir),
+ '-DG_LOG_DOMAIN="notification-area-applet"',
+ ] + disable_deprecated_flags,
+)
diff --git a/applets/wncklet/Makefile.am b/applets/wncklet/Makefile.am
index a59b1192..abfb5113 100644
--- a/applets/wncklet/Makefile.am
+++ b/applets/wncklet/Makefile.am
@@ -21,13 +21,9 @@ WNCKLET_SOURCES = \
window-list.h \
showdesktop.c \
showdesktop.h \
- $(BUILT_SOURCES)
-
-if ENABLE_X11
-WNCKLET_SOURCES += \
workspace-switcher.c \
- workspace-switcher.h
-endif
+ workspace-switcher.h \
+ $(BUILT_SOURCES)
@@ -36,18 +32,27 @@ WNCKLET_LDADD = \
$(WNCKLET_LIBS) \
$(LIBMATE_PANEL_APPLET_LIBS)
+if ENABLE_X11
+WNCKLET_LDADD += \
+ $(X_LIBS)
+endif
+
if ENABLE_WAYLAND
WNCKLET_SOURCES += \
wayland-backend.c \
wayland-backend.h \
+ wayland-workspace.c \
+ wayland-workspace.h \
wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-code.c \
wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-client.h
WNCKLET_LDADD += \
- $(WAYLAND_LIBS)
+ $(WAYLAND_LIBS) \
+ $(XFW_LIBS)
AM_CPPFLAGS += \
- $(WAYLAND_CFLAGS)
+ $(WAYLAND_CFLAGS) \
+ $(XFW_CFLAGS)
endif
if WNCKLET_INPROCESS
@@ -99,15 +104,10 @@ ui_FILES = \
showdesktop-menu.xml \
window-list-menu.xml \
window-list.ui \
- window-menu-menu.xml
-
-if ENABLE_X11
-ui_FILES += \
+ window-menu-menu.xml \
workspace-switcher-menu.xml \
workspace-switcher.ui
-endif
-
diff --git a/applets/wncklet/meson.build b/applets/wncklet/meson.build
new file mode 100644
index 00000000..2a07cb21
--- /dev/null
+++ b/applets/wncklet/meson.build
@@ -0,0 +1,164 @@
+wncklet_resource_deps = files(
+ 'showdesktop-menu.xml',
+ 'window-list.ui',
+ 'window-list-menu.xml',
+ 'window-menu-menu.xml',
+ 'workspace-switcher.ui',
+ 'workspace-switcher-menu.xml',
+)
+
+wncklet_resources_c = custom_target('wncklet-resources.c',
+ input: 'wncklet.gresource.xml',
+ output: 'wncklet-resources.c',
+ depend_files: wncklet_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-source',
+ '--c-name', 'wncklet',
+ '@INPUT@',
+ ],
+)
+
+wncklet_resources_h = custom_target('wncklet-resources.h',
+ input: 'wncklet.gresource.xml',
+ output: 'wncklet-resources.h',
+ depend_files: wncklet_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-header',
+ '--c-name', 'wncklet',
+ '@INPUT@',
+ ],
+)
+
+wncklet_built_sources = [
+ wncklet_resources_c,
+ wncklet_resources_h,
+]
+
+wncklet_sources = [
+ 'wncklet.c',
+ 'wncklet.h',
+ 'window-menu.c',
+ 'window-menu.h',
+ 'window-list.c',
+ 'window-list.h',
+ 'showdesktop.c',
+ 'showdesktop.h',
+ 'workspace-switcher.c',
+ 'workspace-switcher.h',
+ wncklet_built_sources,
+]
+
+if have_wayland
+ wncklet_sources += [
+ 'wayland-backend.c',
+ 'wayland-backend.h',
+ 'wayland-workspace.c',
+ 'wayland-workspace.h',
+ 'wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-code.c',
+ 'wayland-protocol/wlr-foreign-toplevel-management-unstable-v1-client.h',
+ ]
+endif
+
+wncklet_deps = [
+ gtk_dep,
+ wnck_dep,
+ mate_desktop_dep,
+] + libmate_panel_applet_deps
+
+if have_x11
+ wncklet_deps += x11_dep
+endif
+
+if have_wayland
+ wncklet_deps += wayland_deps + [xfw_dep]
+endif
+
+wncklet_inc_dirs = [
+ include_directories('.'),
+ libmate_panel_applet_inc,
+]
+
+wncklet_c_args = [
+ '-DMATELOCALEDIR="@0@"'.format(mate_panel_localedir),
+] + disable_deprecated_flags
+
+if wncklet_inprocess
+ wncklet_applet = shared_library('wnck-applet',
+ wncklet_sources,
+ include_directories: wncklet_inc_dirs,
+ dependencies: wncklet_deps,
+ c_args: wncklet_c_args,
+ link_with: libmate_panel_applet_lib,
+ install: true,
+ install_dir: mate_panel_pkglibdir,
+ )
+ wncklet_applet_in_process = 'true'
+ wncklet_applet_location = join_paths(mate_panel_pkglibdir, 'libwnck-applet.so')
+else
+ wncklet_applet = executable('wnck-applet',
+ wncklet_sources,
+ include_directories: wncklet_inc_dirs,
+ dependencies: wncklet_deps,
+ c_args: wncklet_c_args,
+ link_with: libmate_panel_applet_lib,
+ install: true,
+ install_dir: mate_panel_libexecdir,
+ )
+ wncklet_applet_in_process = 'false'
+ wncklet_applet_location = join_paths(mate_panel_libexecdir, 'wnck-applet')
+endif
+
+# applet registration file
+wncklet_applet_desktop_in = configure_file(
+ input: 'org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in',
+ output: 'org.mate.panel.Wncklet.mate-panel-applet.desktop.in',
+ configuration: {
+ 'IN_PROCESS': wncklet_applet_in_process,
+ 'LOCATION': wncklet_applet_location,
+ 'VERSION': mate_panel_version,
+ },
+)
+
+wncklet_applet_desktop = i18n.merge_file(
+ input: wncklet_applet_desktop_in,
+ output: 'org.mate.panel.Wncklet.mate-panel-applet',
+ type: 'desktop',
+ po_dir: '../../po',
+ install: true,
+ install_dir: mate_panel_appletsdir,
+)
+
+if not wncklet_inprocess
+ wncklet_service = configure_file(
+ input: 'org.mate.panel.applet.WnckletFactory.service.in',
+ output: 'org.mate.panel.applet.WnckletFactory.service',
+ configuration: {
+ 'LOCATION': wncklet_applet_location,
+ },
+ )
+ install_data(wncklet_service,
+ install_dir: join_paths(mate_panel_datadir, 'dbus-1', 'services'),
+ )
+endif
+
+# gsettings schemas
+foreach schema : [
+ 'org.mate.panel.applet.window-list',
+ 'org.mate.panel.applet.window-list-previews',
+ 'org.mate.panel.applet.workspace-switcher',
+ ]
+ install_data(
+ configure_file(
+ input: schema + '.gschema.xml.in',
+ output: schema + '.gschema.xml',
+ configuration: {'GETTEXT_PACKAGE': mate_panel_gettext_package},
+ ),
+ install_dir: mate_panel_schemadir,
+ )
+endforeach
diff --git a/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in b/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in
index ec53ade3..6a2285af 100644
--- a/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in
+++ b/applets/wncklet/org.mate.panel.Wncklet.mate-panel-applet.desktop.in.in
@@ -24,7 +24,7 @@ Description=Switch between workspaces
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=mate-panel-workspace-switcher
MateComponentId=OAFIID:MATE_WorkspaceSwitcherApplet;OAFIID:MATE_PagerApplet;
-Platforms=X11;
+Platforms=X11;Wayland;
X-MATE-Bugzilla-Bugzilla=MATE
X-MATE-Bugzilla-Product=mate-panel
X-MATE-Bugzilla-Component=workspace switcher
diff --git a/applets/wncklet/wayland-workspace.c b/applets/wncklet/wayland-workspace.c
new file mode 100644
index 00000000..646ab802
--- /dev/null
+++ b/applets/wncklet/wayland-workspace.c
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2026 MATE Desktop Team
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <libxfce4windowing/libxfce4windowing.h>
+
+#include "wayland-workspace.h"
+
+typedef struct _GroupSignal GroupSignal;
+
+struct _GroupSignal {
+ XfwWorkspaceGroup *group;
+ gulong handlers[3]; /* active-changed, added, removed */
+};
+
+typedef struct _WaylandWorkspaceData WaylandWorkspaceData;
+
+struct _WaylandWorkspaceData {
+ GtkWidget *grid;
+
+ XfwScreen *screen;
+ XfwWorkspaceManager *workspace_manager;
+ GList *group_signals; /* list of GroupSignal* */
+
+ GtkOrientation orientation;
+ int n_rows;
+ gboolean display_all;
+ gboolean display_names;
+ gboolean ignore_toggle;
+};
+
+static void rebuild_ui (WaylandWorkspaceData *data);
+
+/* ---- Helpers ---- */
+
+static int
+count_visible_workspaces (WaylandWorkspaceData *data)
+{
+ GList *workspaces, *l;
+ int n = 0;
+
+ workspaces = xfw_workspace_manager_list_workspaces (data->workspace_manager);
+
+ for (l = workspaces; l != NULL; l = l->next)
+ {
+ XfwWorkspace *ws = l->data;
+ XfwWorkspaceState state = xfw_workspace_get_state (ws);
+
+ if (data->display_all || !(state & XFW_WORKSPACE_STATE_HIDDEN))
+ n++;
+ }
+
+ return MAX (n, 1);
+}
+
+static XfwWorkspace *
+get_nth_workspace (WaylandWorkspaceData *data, int index)
+{
+ GList *workspaces, *l;
+ int i = 0;
+
+ workspaces = xfw_workspace_manager_list_workspaces (data->workspace_manager);
+
+ for (l = workspaces; l != NULL; l = l->next)
+ {
+ XfwWorkspace *ws = l->data;
+ XfwWorkspaceState state = xfw_workspace_get_state (ws);
+
+ if (data->display_all || !(state & XFW_WORKSPACE_STATE_HIDDEN))
+ {
+ if (i == index)
+ return ws;
+ i++;
+ }
+ }
+
+ return NULL;
+}
+
+/* ---- Build / rebuild the button grid ---- */
+
+static void
+on_button_toggled (GtkToggleButton *button, WaylandWorkspaceData *data)
+{
+ int index;
+
+ if (data->ignore_toggle)
+ return;
+
+ if (gtk_toggle_button_get_active (button))
+ {
+ index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "ws-index"));
+ XfwWorkspace *ws = get_nth_workspace (data, index);
+ if (ws)
+ {
+ GError *error = NULL;
+ if (!xfw_workspace_activate (ws, &error))
+ {
+ g_warning ("Failed to activate workspace: %s",
+ error ? error->message : "unknown error");
+ g_clear_error (&error);
+ }
+ }
+ }
+ else
+ {
+ /* User clicked the already-active button — keep it toggled on */
+ data->ignore_toggle = TRUE;
+ gtk_toggle_button_set_active (button, TRUE);
+ data->ignore_toggle = FALSE;
+ }
+}
+
+static void
+rebuild_ui (WaylandWorkspaceData *data)
+{
+ GList *children, *l;
+ int n_spaces, i, col, row;
+ int rows, cols;
+
+ /* Destroy old buttons */
+ children = gtk_container_get_children (GTK_CONTAINER (data->grid));
+ for (l = children; l != NULL; l = l->next)
+ gtk_widget_destroy (GTK_WIDGET (l->data));
+ g_list_free (children);
+
+ n_spaces = count_visible_workspaces (data);
+
+ /* Determine grid dimensions */
+ if (data->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ rows = data->n_rows;
+ cols = (n_spaces + rows - 1) / rows;
+ }
+ else
+ {
+ cols = data->n_rows;
+ rows = (n_spaces + cols - 1) / cols;
+ }
+
+ gtk_grid_set_column_homogeneous (GTK_GRID (data->grid), TRUE);
+ gtk_grid_set_row_homogeneous (GTK_GRID (data->grid), TRUE);
+
+ /* Create buttons */
+ for (i = 0; i < n_spaces; i++)
+ {
+ XfwWorkspace *ws;
+ const char *name;
+ char *free_name = NULL;
+ GtkWidget *button;
+ XfwWorkspaceState ws_state;
+
+ ws = get_nth_workspace (data, i);
+
+ if (data->display_names && ws)
+ {
+ name = xfw_workspace_get_name (ws);
+ if (!name || name[0] == '\0')
+ name = xfw_workspace_get_id (ws);
+ if (!name)
+ name = "";
+ }
+ else
+ {
+ free_name = g_strdup_printf ("%d", i + 1);
+ name = free_name;
+ }
+
+ button = gtk_toggle_button_new_with_label (name);
+ g_free (free_name);
+
+ gtk_widget_set_name (button, "wnck-pager-button");
+ g_object_set_data (G_OBJECT (button), "ws-index", GINT_TO_POINTER (i));
+
+ /* Set active state */
+ ws_state = ws ? xfw_workspace_get_state (ws) : XFW_WORKSPACE_STATE_NONE;
+ data->ignore_toggle = TRUE;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ (ws_state & XFW_WORKSPACE_STATE_ACTIVE) != 0);
+ data->ignore_toggle = FALSE;
+
+ g_signal_connect (button, "toggled",
+ G_CALLBACK (on_button_toggled), data);
+
+ /* Calculate grid position */
+ if (data->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ col = i / rows;
+ row = i % rows;
+ }
+ else
+ {
+ col = i % cols;
+ row = i / cols;
+ }
+
+ gtk_grid_attach (GTK_GRID (data->grid), button, col, row, 1, 1);
+ }
+
+ gtk_widget_show_all (data->grid);
+}
+
+/* ---- Signal handlers on workspace groups ---- */
+
+static void
+on_active_workspace_changed (XfwWorkspaceGroup *group,
+ XfwWorkspace *previous,
+ WaylandWorkspaceData *data)
+{
+ rebuild_ui (data);
+}
+
+static void
+on_workspace_added (XfwWorkspaceGroup *group,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
+{
+ rebuild_ui (data);
+}
+
+static void
+on_workspace_removed (XfwWorkspaceGroup *group,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
+{
+ rebuild_ui (data);
+}
+
+/* ---- Group signal management ---- */
+
+static void
+disconnect_group_signals (WaylandWorkspaceData *data)
+{
+ for (GList *l = data->group_signals; l != NULL; l = l->next)
+ {
+ GroupSignal *gs = l->data;
+ g_signal_handler_disconnect (gs->group, gs->handlers[0]);
+ g_signal_handler_disconnect (gs->group, gs->handlers[1]);
+ g_signal_handler_disconnect (gs->group, gs->handlers[2]);
+ g_free (gs);
+ }
+
+ g_list_free (data->group_signals);
+ data->group_signals = NULL;
+}
+
+static void
+connect_group_signals (WaylandWorkspaceData *data)
+{
+ GList *groups, *l;
+
+ disconnect_group_signals (data);
+
+ groups = xfw_workspace_manager_list_workspace_groups (data->workspace_manager);
+ if (!groups)
+ return;
+
+ for (l = groups; l != NULL; l = l->next)
+ {
+ XfwWorkspaceGroup *group = l->data;
+ GroupSignal *gs = g_new0 (GroupSignal, 1);
+
+ gs->group = group;
+ gs->handlers[0] = g_signal_connect (group, "active-workspace-changed",
+ G_CALLBACK (on_active_workspace_changed), data);
+ gs->handlers[1] = g_signal_connect (group, "workspace-added",
+ G_CALLBACK (on_workspace_added), data);
+ gs->handlers[2] = g_signal_connect (group, "workspace-removed",
+ G_CALLBACK (on_workspace_removed), data);
+
+ data->group_signals = g_list_append (data->group_signals, gs);
+ }
+}
+
+static void
+on_workspace_group_created (XfwWorkspaceManager *manager,
+ XfwWorkspaceGroup *group,
+ WaylandWorkspaceData *data)
+{
+ connect_group_signals (data);
+ rebuild_ui (data);
+}
+
+static void
+on_workspace_group_destroyed (XfwWorkspaceManager *manager,
+ XfwWorkspaceGroup *group,
+ WaylandWorkspaceData *data)
+{
+ connect_group_signals (data);
+ rebuild_ui (data);
+}
+
+static void
+on_workspace_created (XfwWorkspaceManager *manager,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
+{
+ rebuild_ui (data);
+}
+
+static void
+on_workspace_destroyed (XfwWorkspaceManager *manager,
+ XfwWorkspace *workspace,
+ WaylandWorkspaceData *data)
+{
+ rebuild_ui (data);
+}
+
+/* ---- Cleanup ---- */
+
+static void
+wayland_pager_data_free (WaylandWorkspaceData *data)
+{
+ disconnect_group_signals (data);
+ g_free (data);
+}
+
+/* ---- Public API ---- */
+
+GtkWidget *
+wayland_workspace_new (void)
+{
+ WaylandWorkspaceData *data;
+
+ xfw_set_client_type (XFW_CLIENT_TYPE_PAGER);
+
+ data = g_new0 (WaylandWorkspaceData, 1);
+ data->orientation = GTK_ORIENTATION_HORIZONTAL;
+ data->n_rows = 1;
+ data->display_all = TRUE;
+ data->display_names = FALSE;
+ data->ignore_toggle = FALSE;
+
+ data->grid = gtk_grid_new ();
+ gtk_widget_set_size_request (data->grid, 48, -1);
+
+ GtkStyleContext *context = gtk_widget_get_style_context (data->grid);
+ gtk_style_context_add_class (context, "wnck-pager");
+
+ g_object_set_data_full (G_OBJECT (data->grid),
+ "wayland_pager_data",
+ data,
+ (GDestroyNotify) wayland_pager_data_free);
+
+ data->screen = xfw_screen_get_default ();
+ if (!data->screen)
+ {
+ g_warning ("xfw_screen_get_default() failed");
+ return data->grid;
+ }
+
+ data->workspace_manager = xfw_screen_get_workspace_manager (data->screen);
+ if (!data->workspace_manager)
+ {
+ g_warning ("xfw_screen_get_workspace_manager() failed");
+ return data->grid;
+ }
+
+ g_signal_connect (data->workspace_manager, "workspace-group-created",
+ G_CALLBACK (on_workspace_group_created), data);
+ g_signal_connect (data->workspace_manager, "workspace-group-destroyed",
+ G_CALLBACK (on_workspace_group_destroyed), data);
+
+ g_signal_connect (data->workspace_manager, "workspace-created",
+ G_CALLBACK (on_workspace_created), data);
+ g_signal_connect (data->workspace_manager, "workspace-destroyed",
+ G_CALLBACK (on_workspace_destroyed), data);
+
+ connect_group_signals (data);
+ rebuild_ui (data);
+
+ return data->grid;
+}
+
+static WaylandWorkspaceData *
+pager_widget_get_data (GtkWidget *pager_widget)
+{
+ return g_object_get_data (G_OBJECT (pager_widget), "wayland_pager_data");
+}
+
+void
+wayland_workspace_set_orientation (GtkWidget *pager_widget, GtkOrientation orientation)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ g_return_if_fail (data);
+
+ if (data->orientation == orientation)
+ return;
+
+ data->orientation = orientation;
+ rebuild_ui (data);
+}
+
+void
+wayland_workspace_set_rows (GtkWidget *pager_widget, int n_rows)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ g_return_if_fail (data);
+
+ n_rows = CLAMP (n_rows, 1, 16);
+
+ if (data->n_rows == n_rows)
+ return;
+
+ data->n_rows = n_rows;
+ rebuild_ui (data);
+}
+
+void
+wayland_workspace_set_show_all (GtkWidget *pager_widget, gboolean show_all)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ g_return_if_fail (data);
+
+ if (data->display_all == show_all)
+ return;
+
+ data->display_all = show_all;
+ rebuild_ui (data);
+}
+
+void
+wayland_workspace_set_show_names (GtkWidget *pager_widget, gboolean show_names)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ g_return_if_fail (data);
+
+ if (data->display_names == show_names)
+ return;
+
+ data->display_names = show_names;
+ rebuild_ui (data);
+}
+
+int
+wayland_workspace_get_count (GtkWidget *pager_widget)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+
+ g_return_val_if_fail (data, 0);
+
+ return g_list_length (xfw_workspace_manager_list_workspaces (data->workspace_manager));
+}
+
+const char *
+wayland_workspace_get_name (GtkWidget *pager_widget, int index)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ XfwWorkspace *ws;
+
+ g_return_val_if_fail (data, "workspace");
+
+ ws = get_nth_workspace (data, index);
+ if (ws)
+ {
+ const char *name = xfw_workspace_get_name (ws);
+ if (name && name[0] != '\0')
+ return name;
+ return xfw_workspace_get_id (ws);
+ }
+
+ return "workspace";
+}
+
+int
+wayland_workspace_get_active_index (GtkWidget *pager_widget)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ GList *workspaces, *l;
+ int i = 0;
+
+ g_return_val_if_fail (data, 0);
+
+ workspaces = xfw_workspace_manager_list_workspaces (data->workspace_manager);
+
+ for (l = workspaces; l != NULL; l = l->next)
+ {
+ XfwWorkspace *ws = l->data;
+ XfwWorkspaceState state = xfw_workspace_get_state (ws);
+
+ if (state & XFW_WORKSPACE_STATE_ACTIVE)
+ return i;
+ i++;
+ }
+
+ return 0;
+}
+
+void
+wayland_workspace_activate_nth (GtkWidget *pager_widget, int index)
+{
+ WaylandWorkspaceData *data = pager_widget_get_data (pager_widget);
+ XfwWorkspace *ws;
+
+ g_return_if_fail (data);
+
+ ws = get_nth_workspace (data, index);
+ if (ws)
+ {
+ GError *error = NULL;
+ if (!xfw_workspace_activate (ws, &error))
+ {
+ g_warning ("Failed to activate workspace: %s",
+ error ? error->message : "unknown error");
+ g_clear_error (&error);
+ }
+ }
+}
diff --git a/applets/wncklet/wayland-workspace.h b/applets/wncklet/wayland-workspace.h
new file mode 100644
index 00000000..36d84c47
--- /dev/null
+++ b/applets/wncklet/wayland-workspace.h
@@ -0,0 +1,52 @@
+/* Wncklet applet Wayland workspace backend */
+
+/*
+ * Copyright (C) 2026 MATE Desktop Team
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _WNCKLET_APPLET_WAYLAND_WORKSPACE_H_
+#define _WNCKLET_APPLET_WAYLAND_WORKSPACE_H_
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GtkWidget* wayland_workspace_new (void);
+void wayland_workspace_set_orientation(GtkWidget *pager_widget,
+ GtkOrientation orientation);
+void wayland_workspace_set_rows (GtkWidget *pager_widget,
+ int n_rows);
+void wayland_workspace_set_show_all (GtkWidget *pager_widget,
+ gboolean show_all);
+void wayland_workspace_set_show_names (GtkWidget *pager_widget,
+ gboolean show_names);
+int wayland_workspace_get_count (GtkWidget *pager_widget);
+const char* wayland_workspace_get_name (GtkWidget *pager_widget,
+ int index);
+int wayland_workspace_get_active_index (GtkWidget *pager_widget);
+void wayland_workspace_activate_nth (GtkWidget *pager_widget,
+ int index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WNCKLET_APPLET_WAYLAND_WORKSPACE_H_ */
diff --git a/applets/wncklet/window-list.c b/applets/wncklet/window-list.c
index 17821cdd..d7e9f438 100644
--- a/applets/wncklet/window-list.c
+++ b/applets/wncklet/window-list.c
@@ -21,6 +21,7 @@
#ifdef HAVE_X11
#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
#include <libwnck/libwnck.h>
#endif /* HAVE_X11 */
@@ -251,56 +252,119 @@ preview_window_thumbnail (WnckWindow *wnck_window,
int *thumbnail_scale)
{
GdkWindow *window;
- Window win;
+ GdkDisplay *display;
+ Display *xdpy;
+ Window win, frame, parent, root;
+ Window *children;
+ unsigned int nchildren;
cairo_surface_t *thumbnail;
cairo_t *cr;
double ratio;
int width, height, scale;
+ int src_x = 0, src_y = 0;
win = wnck_window_get_xid (wnck_window);
+ display = gdk_display_get_default ();
+ xdpy = GDK_DISPLAY_XDISPLAY (display);
- if ((window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), win)) == NULL)
+ /* Find the frame window (WM parent) which includes decorations */
+ frame = win;
+ if (XQueryTree (xdpy, win, &root, &parent, &children, &nchildren))
+ {
+ if (children)
+ XFree (children);
+ if (parent != root)
+ frame = parent;
+ }
+
+ if ((window = gdk_x11_window_foreign_new_for_display (display, frame)) == NULL)
{
return NULL;
}
*thumbnail_scale = scale = gdk_window_get_scale_factor (window);
- width = gdk_window_get_width (window) * scale;
- height = gdk_window_get_height (window) * scale;
+ width = gdk_window_get_width (window);
+ height = gdk_window_get_height (window);
+
+ /* Strip invisible resize borders using _NET_FRAME_EXTENTS */
+ if (frame != win)
+ {
+ Atom frame_extents = XInternAtom (xdpy, "_NET_FRAME_EXTENTS", False);
+ Atom type;
+ int fmt;
+ unsigned long nitems, bytes;
+ unsigned char *data = NULL;
+
+ if (XGetWindowProperty (xdpy, win, frame_extents, 0, 4, False,
+ XA_CARDINAL, &type, &fmt, &nitems, &bytes,
+ &data) == Success && data && nitems >= 4)
+ {
+ unsigned long *ext = (unsigned long *) data;
+ XWindowAttributes wa;
+
+ if (XGetWindowAttributes (xdpy, win, &wa))
+ {
+ int vis_w = (wa.width + ext[0] + ext[1]) / scale;
+ int vis_h = (wa.height + ext[2] + ext[3]) / scale;
+ int border_x = (wa.x - (int) ext[0]) / scale;
+ int border_y = (wa.y - (int) ext[2]) / scale;
+
+ if (border_x > 0 && vis_w < width)
+ {
+ src_x = border_x;
+ width = vis_w;
+ }
+ if (border_y > 0 && vis_h < height)
+ {
+ src_y = border_y;
+ height = vis_h;
+ }
+ }
+ }
+ if (data)
+ XFree (data);
+ }
/* Scale to configured size while maintaining aspect ratio */
if (width > height)
{
- int max_size = MIN (width, tasklist->thumbnail_size * scale);
+ int max_size = MIN (width, tasklist->thumbnail_size);
ratio = (double) max_size / (double) width;
- *thumbnail_width = max_size;
- *thumbnail_height = (int) ((double) height * ratio);
+ *thumbnail_width = max_size * scale;
+ *thumbnail_height = (int) ((double) height * ratio) * scale;
}
else
{
- int max_size = MIN (height, tasklist->thumbnail_size * scale);
+ int max_size = MIN (height, tasklist->thumbnail_size);
ratio = (double) max_size / (double) height;
- *thumbnail_height = max_size;
- *thumbnail_width = (int) ((double) width * ratio);
+ *thumbnail_height = max_size * scale;
+ *thumbnail_width = (int) ((double) width * ratio) * scale;
}
gdk_x11_display_error_trap_push (gdk_window_get_display (window));
+ GdkPixbuf *pixbuf = gdk_pixbuf_get_from_window (window,
+ src_x, src_y,
+ width, height);
+
+ if (gdk_x11_display_error_trap_pop (gdk_window_get_display (window)) || pixbuf == NULL)
+ {
+ g_object_unref (window);
+ return NULL;
+ }
+
thumbnail = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
*thumbnail_width,
*thumbnail_height);
cairo_surface_set_device_scale (thumbnail, scale, scale);
cr = cairo_create (thumbnail);
- cairo_scale (cr, ratio, ratio);
- gdk_cairo_set_source_window (cr, window, 0, 0);
+ cairo_scale (cr,
+ (double) *thumbnail_width / scale / gdk_pixbuf_get_width (pixbuf),
+ (double) *thumbnail_height / scale / gdk_pixbuf_get_height (pixbuf));
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
-
- if (gdk_x11_display_error_trap_pop (gdk_window_get_display (window)))
- {
- cairo_surface_destroy (thumbnail);
- thumbnail = NULL;
- }
+ g_object_unref (pixbuf);
g_object_unref (window);
diff --git a/applets/wncklet/wncklet.c b/applets/wncklet/wncklet.c
index 1ced4507..5662aead 100644
--- a/applets/wncklet/wncklet.c
+++ b/applets/wncklet/wncklet.c
@@ -131,10 +131,8 @@ static gboolean wncklet_factory(MatePanelApplet* applet, const char* iid, gpoint
if (!strcmp(iid, "WindowMenuApplet"))
retval = window_menu_applet_fill(applet);
-#ifdef HAVE_X11
else if (!strcmp(iid, "WorkspaceSwitcherApplet") || !strcmp(iid, "PagerApplet"))
retval = workspace_switcher_applet_fill(applet);
-#endif
else if (!strcmp(iid, "WindowListApplet") || !strcmp(iid, "TasklistApplet"))
retval = window_list_applet_fill(applet);
else if (!strcmp(iid, "ShowDesktopApplet"))
diff --git a/applets/wncklet/workspace-switcher.c b/applets/wncklet/workspace-switcher.c
index cba0ecbd..93318314 100644
--- a/applets/wncklet/workspace-switcher.c
+++ b/applets/wncklet/workspace-switcher.c
@@ -31,6 +31,7 @@
#ifdef HAVE_WAYLAND
#include <gdk/gdkwayland.h>
+#include "wayland-workspace.h"
#endif /* HAVE_WAYLAND */
#include <libmate-desktop/mate-gsettings.h>
@@ -217,8 +218,11 @@ typedef struct {
#ifdef HAVE_X11
WnckHandle* wnck_handle;
-#endif
WnckScreen* screen;
+#endif
+#ifdef HAVE_WAYLAND
+ gboolean is_wayland;
+#endif
PagerWM wm;
/* Properties: */
@@ -280,6 +284,16 @@ static void pager_update(PagerData* pager)
pager_update_wnck(pager, WNCK_PAGER(pager->pager));
}
#endif /* HAVE_X11 */
+
+#ifdef HAVE_WAYLAND
+ if (pager->is_wayland)
+ {
+ wayland_workspace_set_orientation(pager->pager, pager->orientation);
+ wayland_workspace_set_rows(pager->pager, pager->n_rows);
+ wayland_workspace_set_show_all(pager->pager, pager->display_all);
+ wayland_workspace_set_show_names(pager->pager, pager->display_names);
+ }
+#endif /* HAVE_WAYLAND */
}
static void update_properties_for_wm(PagerData* pager)
@@ -365,9 +379,9 @@ static void update_properties_for_wm(PagerData* pager)
}
}
+#ifdef HAVE_X11
static void window_manager_changed(WnckScreen* screen, PagerData* pager)
{
-#ifdef HAVE_X11
const char *wm_name = NULL;
if (pager->screen)
@@ -389,13 +403,11 @@ static void window_manager_changed(WnckScreen* screen, PagerData* pager)
pager->wm = PAGER_WM_COMPIZ;
else
pager->wm = PAGER_WM_UNKNOWN;
-#else
- pager->wm = PAGER_WM_UNKNOWN;
-#endif /* HAVE_X11 */
update_properties_for_wm(pager);
pager_update(pager);
}
+#endif /* HAVE_X11 */
static void applet_realized(MatePanelApplet* applet, PagerData* pager)
{
@@ -404,10 +416,17 @@ static void applet_realized(MatePanelApplet* applet, PagerData* pager)
{
pager->screen = wncklet_get_screen(pager->wnck_handle, GTK_WIDGET(applet));
wncklet_connect_while_alive(pager->screen, "window_manager_changed", G_CALLBACK(window_manager_changed), pager, pager->applet);
+ window_manager_changed(pager->screen, pager);
+ return;
}
#endif /* HAVE_X11 */
- window_manager_changed(pager->screen, pager);
+#ifdef HAVE_WAYLAND
+ if (pager->is_wayland)
+ {
+ pager_update(pager);
+ }
+#endif /* HAVE_WAYLAND */
}
static void applet_unrealized(MatePanelApplet* applet, PagerData* pager)
@@ -473,7 +492,6 @@ static void applet_style_updated (MatePanelApplet *applet, GtkStyleContext *cont
provider = gtk_css_provider_new ();
- /* Provide a fallback color for the highlighted workspace based on the current theme */
gtk_style_context_lookup_color (context, "theme_selected_bg_color", &color);
color_str = gdk_rgba_to_string (&color);
bg_css = g_strconcat (".wnck-pager:selected {\n"
@@ -485,7 +503,7 @@ static void applet_style_updated (MatePanelApplet *applet, GtkStyleContext *cont
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER (provider),
- GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
}
@@ -508,6 +526,91 @@ static gboolean applet_scroll(MatePanelApplet* applet, GdkEventScroll* event, Pa
if (event->direction == GDK_SCROLL_SMOOTH)
return FALSE;
+#ifdef HAVE_WAYLAND
+ if (pager->is_wayland)
+ {
+ GdkScrollDirection absolute_direction;
+ int index;
+ int n_workspaces;
+ int n_columns;
+ int in_last_row;
+
+ index = wayland_workspace_get_active_index (pager->pager);
+ n_workspaces = wayland_workspace_get_count (pager->pager);
+
+ if (n_workspaces <= 0)
+ return TRUE;
+
+ n_columns = n_workspaces / pager->n_rows;
+ if (n_workspaces % pager->n_rows != 0)
+ n_columns++;
+
+ in_last_row = n_workspaces % n_columns;
+
+ absolute_direction = event->direction;
+
+ if (gtk_widget_get_direction (GTK_WIDGET (applet)) == GTK_TEXT_DIR_RTL)
+ {
+ switch (event->direction)
+ {
+ case GDK_SCROLL_RIGHT:
+ absolute_direction = GDK_SCROLL_LEFT;
+ break;
+ case GDK_SCROLL_LEFT:
+ absolute_direction = GDK_SCROLL_RIGHT;
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (absolute_direction)
+ {
+ case GDK_SCROLL_DOWN:
+ if (index + n_columns < n_workspaces)
+ index += n_columns;
+ else if (pager->wrap_workspaces && index == n_workspaces - 1)
+ index = 0;
+ else if ((index < n_workspaces - 1 && index + in_last_row != n_workspaces - 1) ||
+ (index == n_workspaces - 1 && in_last_row != 0))
+ index = (index % n_columns) + 1;
+ break;
+
+ case GDK_SCROLL_RIGHT:
+ if (index < n_workspaces - 1)
+ index++;
+ else if (pager->wrap_workspaces)
+ index = 0;
+ break;
+
+ case GDK_SCROLL_UP:
+ if (index - n_columns >= 0)
+ index -= n_columns;
+ else if (index > 0)
+ index = ((pager->n_rows - 1) * n_columns) + (index % n_columns) - 1;
+ else if (pager->wrap_workspaces)
+ index = n_workspaces - 1;
+
+ if (index >= n_workspaces)
+ index -= n_columns;
+ break;
+
+ case GDK_SCROLL_LEFT:
+ if (index > 0)
+ index--;
+ else if (pager->wrap_workspaces)
+ index = n_workspaces - 1;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ wayland_workspace_activate_nth (pager->pager, index);
+ return TRUE;
+ }
+#endif /* HAVE_WAYLAND */
+
#ifdef HAVE_X11
if (pager->screen)
{
@@ -644,10 +747,21 @@ static const GtkActionEntry pager_menu_actions[] = {
static void num_rows_changed(GSettings* settings, gchar* key, PagerData* pager)
{
int n_rows;
+ int ws_count = MAX_REASONABLE_ROWS;
+
+#ifdef HAVE_X11
+ if (pager->screen)
+ ws_count = wnck_screen_get_workspace_count (pager->screen);
+#endif /* HAVE_X11 */
+
+#ifdef HAVE_WAYLAND
+ if (pager->is_wayland)
+ ws_count = wayland_workspace_get_count (pager->pager);
+#endif /* HAVE_WAYLAND */
n_rows = CLAMP (g_settings_get_int (settings, key),
1,
- MIN (wnck_screen_get_workspace_count (pager->screen),
+ MIN (ws_count,
MAX_REASONABLE_ROWS));
pager->n_rows = n_rows;
@@ -785,7 +899,8 @@ gboolean workspace_switcher_applet_fill(MatePanelApplet* applet)
#ifdef HAVE_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
{
- pager->pager = gtk_label_new ("[Pager not supported on Wayland]");
+ pager->is_wayland = TRUE;
+ pager->pager = wayland_workspace_new();
}
else
#endif /* HAVE_WAYLAND */
@@ -922,6 +1037,13 @@ static const char *get_workspace_name(PagerData* pager, int workspace_index)
}
#endif /* HAVE_X11 */
+#ifdef HAVE_WAYLAND
+ if (pager->is_wayland)
+ {
+ return wayland_workspace_get_name(pager->pager, workspace_index);
+ }
+#endif /* HAVE_WAYLAND */
+
/* Fallback */
return "workspace";
}
@@ -935,6 +1057,14 @@ static void update_workspaces_model(PagerData* pager)
nr_ws = wnck_screen_get_workspace_count (pager->screen);
#endif /* HAVE_X11 */
+#ifdef HAVE_WAYLAND
+ if (pager->is_wayland)
+ nr_ws = wayland_workspace_get_count (pager->pager);
+#endif /* HAVE_WAYLAND */
+
+ if (nr_ws == 0)
+ nr_ws = 1;
+
if (pager->properties_dialog)
{
int i;
@@ -1297,5 +1427,10 @@ static void destroy_pager(GtkWidget* widget, PagerData* pager)
g_clear_object(&pager->wnck_handle);
#endif
+#ifdef HAVE_WAYLAND
+ /* The Wayland pager widget cleanup is handled by the
+ * destroy notify on the outer_box's g_object_set_data */
+#endif
+
g_free(pager);
}
diff --git a/configure.ac b/configure.ac
index 92dd8aae..cde280a0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -214,6 +214,17 @@ if test "x$enable_wayland" != "xno"; then
])
fi
+have_xfw=no
+if test "x$have_wayland" = "xyes"; then
+ PKG_CHECK_MODULES(XFW, libxfce4windowing-0 >= 4.19.4, have_xfw=yes, [
+ if test "x$enable_wayland" = "xyes"; then
+ AC_MSG_ERROR([Wayland support requires libxfce4windowing-0 >= 4.19.4])
+ else
+ have_wayland=no
+ fi
+ ])
+fi
+
AM_CONDITIONAL(ENABLE_WAYLAND, [test "x$have_wayland" = "xyes"])
if test "x$have_wayland" = "xyes"; then
diff --git a/data/default.layout b/data/default.layout
index 77923b42..db73094d 100644
--- a/data/default.layout
+++ b/data/default.layout
@@ -11,43 +11,43 @@ size=24
[Object menu-bar]
object-type=menu-bar
toplevel-id=top
-position=0
+pack-index=0
locked=true
[Object notification-area]
object-type=applet
applet-iid=NotificationAreaAppletFactory::NotificationArea
toplevel-id=top
-position=10
-panel-right-stick=true
+pack-type=end
+pack-index=1
locked=true
[Object clock]
object-type=applet
applet-iid=ClockAppletFactory::ClockApplet
toplevel-id=top
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
[Object show-desktop]
object-type=applet
applet-iid=WnckletFactory::ShowDesktopApplet
toplevel-id=bottom
-position=0
+pack-index=0
locked=true
[Object window-list]
object-type=applet
applet-iid=WnckletFactory::WindowListApplet
toplevel-id=bottom
-position=20
+pack-index=1
locked=true
[Object workspace-switcher]
object-type=applet
applet-iid=WnckletFactory::WorkspaceSwitcherApplet
toplevel-id=bottom
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
diff --git a/data/fedora.layout b/data/fedora.layout
index ed55eca0..336567d8 100644
--- a/data/fedora.layout
+++ b/data/fedora.layout
@@ -11,72 +11,72 @@ size=24
[Object menu-bar]
object-type=menu-bar
toplevel-id=top
-position=0
+pack-index=0
locked=true
[Object file-browser]
object-type=launcher
launcher-location=/usr/share/applications/caja-browser.desktop
toplevel-id=top
-position=10
+pack-index=1
locked=true
[Object terminal]
object-type=launcher
launcher-location=/usr/share/applications/mate-terminal.desktop
toplevel-id=top
-position=20
+pack-index=2
locked=true
[Object web-browser]
object-type=launcher
launcher-location=/usr/share/applications/firefox.desktop
toplevel-id=top
-position=30
+pack-index=3
locked=true
[Object volume-control]
object-type=applet
applet-iid=GvcAppletFactory::GvcApplet
toplevel-id=top
-position=20
-panel-right-stick=true
+pack-type=end
+pack-index=2
locked=true
[Object notification-area]
object-type=applet
applet-iid=NotificationAreaAppletFactory::NotificationArea
toplevel-id=top
-position=10
-panel-right-stick=true
+pack-type=end
+pack-index=1
locked=true
[Object clock]
object-type=applet
applet-iid=ClockAppletFactory::ClockApplet
toplevel-id=top
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
[Object show-desktop]
object-type=applet
applet-iid=WnckletFactory::ShowDesktopApplet
toplevel-id=bottom
-position=0
+pack-index=0
locked=true
[Object window-list]
object-type=applet
applet-iid=WnckletFactory::WindowListApplet
toplevel-id=bottom
-position=20
+pack-index=1
locked=true
[Object workspace-switcher]
object-type=applet
applet-iid=WnckletFactory::WorkspaceSwitcherApplet
toplevel-id=bottom
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
diff --git a/data/linuxmint.layout b/data/linuxmint.layout
index 43d1b908..50783204 100644
--- a/data/linuxmint.layout
+++ b/data/linuxmint.layout
@@ -7,35 +7,35 @@ size=24
object-type=applet
applet-iid=MintMenuAppletFactory::MintMenuApplet
toplevel-id=bottom
-position=0
+pack-index=0
locked=true
[Object show-desktop]
object-type=applet
applet-iid=WnckletFactory::ShowDesktopApplet
toplevel-id=bottom
-position=1
+pack-index=1
locked=true
[Object window-list]
object-type=applet
applet-iid=WnckletFactory::WindowListApplet
toplevel-id=bottom
-position=20
+pack-index=2
locked=true
[Object notification-area]
object-type=applet
applet-iid=NotificationAreaAppletFactory::NotificationArea
toplevel-id=bottom
-position=10
-panel-right-stick=true
+pack-type=end
+pack-index=1
locked=true
[Object clock]
object-type=applet
applet-iid=ClockAppletFactory::ClockApplet
toplevel-id=bottom
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
diff --git a/data/mageia.layout b/data/mageia.layout
index 504a3377..6b66b31a 100644
--- a/data/mageia.layout
+++ b/data/mageia.layout
@@ -11,65 +11,64 @@ size=24
[Object menu-bar]
object-type=menu-bar
toplevel-id=top
-position=0
+pack-index=0
locked=true
[Object mcc]
object-type=launcher
launcher-location=/usr/share/applications/mageia-drakconf.desktop
toplevel-id=top
-position=10
+pack-index=1
locked=true
[Object terminal]
object-type=launcher
launcher-location=/usr/share/applications/mate-terminal.desktop
toplevel-id=top
-position=20
+pack-index=2
locked=true
[Object web-browser]
object-type=launcher
launcher-location=/usr/share/applications/firefox.desktop
toplevel-id=top
-position=30
+pack-index=3
locked=true
[Object notification-area]
object-type=applet
applet-iid=NotificationAreaAppletFactory::NotificationArea
toplevel-id=top
-position=10
-panel-right-stick=true
+pack-type=end
+pack-index=1
locked=true
[Object clock]
object-type=applet
applet-iid=ClockAppletFactory::ClockApplet
toplevel-id=top
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
[Object show-desktop]
object-type=applet
applet-iid=WnckletFactory::ShowDesktopApplet
toplevel-id=bottom
-position=0
+pack-index=0
locked=true
[Object window-list]
object-type=applet
applet-iid=WnckletFactory::WindowListApplet
toplevel-id=bottom
-position=20
+pack-index=1
locked=true
[Object workspace-switcher]
object-type=applet
applet-iid=WnckletFactory::WorkspaceSwitcherApplet
toplevel-id=bottom
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
-
diff --git a/data/meson.build b/data/meson.build
new file mode 100644
index 00000000..e87e5e1c
--- /dev/null
+++ b/data/meson.build
@@ -0,0 +1,64 @@
+# panel layouts
+install_data(
+ 'default.layout',
+ 'fedora.layout',
+ 'linuxmint.layout',
+ 'mageia.layout',
+ 'opensuse.layout',
+ 'ubuntu.layout',
+ install_dir: mate_panel_layoutsdir,
+)
+
+# gsettings enums
+glib_mkenums = find_program('glib-mkenums')
+
+panel_enums = custom_target('org.mate.panel.enums.xml',
+ input: '../mate-panel/panel-enums-gsettings.h',
+ output: 'org.mate.panel.enums.xml',
+ build_by_default: true,
+ install: true,
+ install_dir: mate_panel_schemadir,
+ command: [
+ glib_mkenums,
+ '--comments', '<!-- @comment@ -->',
+ '--fhead', '<schemalist>',
+ '--vhead', ' <@type@ id=\'org.mate.panel.@EnumName@\'>',
+ '--vprod', ' <value nick=\'@valuenick@\' value=\'@valuenum@\'/>',
+ '--vtail', ' </@type@>',
+ '--ftail', '</schemalist>',
+ '--output', '@OUTPUT@',
+ '@INPUT@',
+ ],
+)
+
+# gsettings schemas
+schemas = []
+foreach schema : [
+ 'org.mate.panel',
+ 'org.mate.panel.object',
+ 'org.mate.panel.toplevel',
+ 'org.mate.panel.menubar',
+ ]
+ schemas += configure_file(
+ input: schema + '.gschema.xml.in',
+ output: schema + '.gschema.xml',
+ configuration: {'GETTEXT_PACKAGE': mate_panel_gettext_package},
+ )
+endforeach
+
+install_data(schemas, install_dir: mate_panel_schemadir)
+
+glib_compile_schemas = find_program('glib-compile-schemas')
+
+gschemas_compiled = custom_target('gschemas.compiled',
+ output: 'gschemas.compiled',
+ input: schemas,
+ build_by_default: true,
+ command: [
+ glib_compile_schemas,
+ meson.current_build_dir(),
+ ],
+)
+
+gnome = import('gnome')
+gnome.post_install(glib_compile_schemas: true)
diff --git a/data/opensuse.layout b/data/opensuse.layout
index d0f96927..67e730e2 100644
--- a/data/opensuse.layout
+++ b/data/opensuse.layout
@@ -7,51 +7,51 @@ size=24
object-type=applet
applet-iid=MateMenuAppletFactory::MateMenuApplet
toplevel-id=bottom
-position=0
+pack-index=0
locked=true
[Object stickynotes]
object-type=applet
applet-iid=StickyNotesAppletFactory::StickyNotesApplet
toplevel-id=bottom
-position=10
+pack-index=1
locked=true
[Object window-list]
object-type=applet
applet-iid=WnckletFactory::WindowListApplet
toplevel-id=bottom
-position=20
+pack-index=2
locked=true
[Object notification-area]
object-type=applet
applet-iid=NotificationAreaAppletFactory::NotificationArea
toplevel-id=bottom
-position=30
-panel-right-stick=true
+pack-type=end
+pack-index=3
locked=true
[Object workspace-switcher]
object-type=applet
applet-iid=WnckletFactory::WorkspaceSwitcherApplet
toplevel-id=bottom
-position=20
-panel-right-stick=true
+pack-type=end
+pack-index=2
locked=true
[Object clock]
object-type=applet
applet-iid=ClockAppletFactory::ClockApplet
toplevel-id=bottom
-position=10
-panel-right-stick=true
+pack-type=end
+pack-index=1
locked=true
[Object show-desktop]
object-type=applet
applet-iid=WnckletFactory::ShowDesktopApplet
toplevel-id=bottom
-position=0
-panel-right-stick=true
+pack-type=end
+pack-index=0
locked=true
diff --git a/data/org.mate.panel.object.gschema.xml.in b/data/org.mate.panel.object.gschema.xml.in
index 73656bc5..53e23117 100644
--- a/data/org.mate.panel.object.gschema.xml.in
+++ b/data/org.mate.panel.object.gschema.xml.in
@@ -10,15 +10,25 @@
<summary>Toplevel panel containing object</summary>
<description>The identifier of the toplevel panel which contains this object.</description>
</key>
- <key name="position" type="i">
+ <key name="pack-type" enum="org.mate.panel.PanelObjectPackType">
+ <default>'start'</default>
+ <summary>Interpret position relative to bottom/right edge</summary>
+ <description>If set to 'end', the position of the object is interpreted relative to the right (or bottom if vertical) edge of the panel.</description>
+ </key>
+ <key name="pack-index" type="i">
<default>0</default>
<summary>Object's position on the panel</summary>
- <description>The position of this panel object. The position is specified by the number of pixels from the left (or top if vertical) panel edge.</description>
+ <description>The index of this panel object within the other objects with the same pack-type, from the left (or top if vertical) panel edge.</description>
+ </key>
+ <key name="position" type="i">
+ <default>0</default>
+ <summary>Object's position on the panel (deprecated)</summary>
+ <description>The position of this panel object. The position is specified by the number of pixels from the left (or top if vertical) panel edge. Deprecated in favor of pack-type and pack-index.</description>
</key>
<key name="panel-right-stick" type="b">
<default>false</default>
- <summary>Interpret position relative to bottom/right edge</summary>
- <description>If true, the position of the object is interpreted relative to the right (or bottom if vertical) edge of the panel.</description>
+ <summary>Interpret position relative to bottom/right edge (deprecated)</summary>
+ <description>If true, the position of the object is interpreted relative to the right (or bottom if vertical) edge of the panel. Deprecated in favor of pack-type.</description>
</key>
<key name="locked" type="b">
<default>false</default>
diff --git a/data/ubuntu.layout b/data/ubuntu.layout
index bab5164f..3c794051 100644
--- a/data/ubuntu.layout
+++ b/data/ubuntu.layout
@@ -11,67 +11,67 @@ size=24
[Object menu-bar]
object-type=menu-bar
toplevel-id=top
-position=0
+pack-index=0
locked=true
[Object firefox]
locked=True
-position=10
launcher-location=/usr/share/applications/firefox.desktop
toplevel-id=top
object-type=launcher
menu-path=applications:/
+pack-index=1
[Object notification-area]
object-type=applet
applet-iid=NotificationAreaAppletFactory::NotificationArea
toplevel-id=top
-position=30
-panel-right-stick=true
+pack-type=end
+pack-index=2
locked=true
[Object clock]
object-type=applet
applet-iid=ClockAppletFactory::ClockApplet
toplevel-id=top
-position=20
-panel-right-stick=true
+pack-type=end
+pack-index=1
locked=true
[Object shutdown]
action-type=shutdown
object-type=action
-position=10
-panel-right-stick=true
toplevel-id=top
+pack-type=end
+pack-index=0
locked=true
[Object show-desktop]
object-type=applet
applet-iid=WnckletFactory::ShowDesktopApplet
toplevel-id=bottom
-position=0
+pack-index=0
locked=true
[Object window-list]
object-type=applet
applet-iid=WnckletFactory::WindowListApplet
toplevel-id=bottom
-position=20
+pack-index=1
locked=true
[Object workspace-switcher]
object-type=applet
applet-iid=WnckletFactory::WorkspaceSwitcherApplet
toplevel-id=bottom
-position=10
-panel-right-stick=true
+pack-type=end
+pack-index=1
locked=true
[Object trashapplet]
locked=True
-position=0
toplevel-id=bottom
applet-iid=TrashAppletFactory::TrashApplet
object-type=applet
-panel-right-stick=true
+pack-type=end
+pack-index=0
diff --git a/doc/meson.build b/doc/meson.build
new file mode 100644
index 00000000..ead14c40
--- /dev/null
+++ b/doc/meson.build
@@ -0,0 +1 @@
+subdir('reference')
diff --git a/doc/reference/mate-panel-applet/meson.build b/doc/reference/mate-panel-applet/meson.build
new file mode 100644
index 00000000..61878e88
--- /dev/null
+++ b/doc/reference/mate-panel-applet/meson.build
@@ -0,0 +1,22 @@
+doc_module = 'mate-panel-applet'
+
+gtkdoc_link_dep = declare_dependency(
+ link_with: libmate_panel_applet_lib,
+ include_directories: libmate_panel_applet_inc,
+)
+
+gnome.gtkdoc(doc_module,
+ main_sgml: '@[email protected]'.format(doc_module),
+ src_dir: 'libmate-panel-applet',
+ gobject_typesfile: '@[email protected]'.format(doc_module),
+ ignore_headers: [
+ 'MATE_Panel.h',
+ 'mate-panel-applet-enums.h',
+ 'mate-panel-applet-marshal.h',
+ 'mate-panel-applet-private.h',
+ 'mate-panel-applet-shell.h',
+ ],
+ mkdb_args: '--output-format=xml',
+ dependencies: libmate_panel_applet_deps + [gtkdoc_link_dep],
+ install: true,
+)
diff --git a/doc/reference/meson.build b/doc/reference/meson.build
new file mode 100644
index 00000000..196fd7ce
--- /dev/null
+++ b/doc/reference/meson.build
@@ -0,0 +1 @@
+subdir('mate-panel-applet')
diff --git a/help/mate-clock/meson.build b/help/mate-clock/meson.build
new file mode 100644
index 00000000..d82268e4
--- /dev/null
+++ b/help/mate-clock/meson.build
@@ -0,0 +1,21 @@
+fs = import('fs')
+
+help_id = 'mate-clock'
+help_sources = ['index.docbook', 'legal.xml']
+help_media = ['figures/clock_applet.png']
+
+# discover the locale directories holding a <locale>.po translation file
+langs = []
+foreach entry : run_command('ls', '-1', meson.current_source_dir(), check: true).stdout().strip().split('\n')
+ entry_path = join_paths(meson.current_source_dir(), entry)
+ if entry != 'C' and fs.is_dir(entry_path) and fs.exists(join_paths(entry_path, entry + '.po'))
+ langs += entry
+ endif
+endforeach
+
+gnome.yelp(help_id,
+ sources: help_sources,
+ media: help_media,
+ languages: langs,
+ symlink_media: true,
+)
diff --git a/help/mate-fish/meson.build b/help/mate-fish/meson.build
new file mode 100644
index 00000000..2cf0f3c0
--- /dev/null
+++ b/help/mate-fish/meson.build
@@ -0,0 +1,21 @@
+fs = import('fs')
+
+help_id = 'mate-fish'
+help_sources = ['index.docbook', 'legal.xml']
+help_media = ['figures/fish_applet.png']
+
+# discover the locale directories holding a <locale>.po translation file
+langs = []
+foreach entry : run_command('ls', '-1', meson.current_source_dir(), check: true).stdout().strip().split('\n')
+ entry_path = join_paths(meson.current_source_dir(), entry)
+ if entry != 'C' and fs.is_dir(entry_path) and fs.exists(join_paths(entry_path, entry + '.po'))
+ langs += entry
+ endif
+endforeach
+
+gnome.yelp(help_id,
+ sources: help_sources,
+ media: help_media,
+ languages: langs,
+ symlink_media: true,
+)
diff --git a/help/meson.build b/help/meson.build
new file mode 100644
index 00000000..a999b5f6
--- /dev/null
+++ b/help/meson.build
@@ -0,0 +1,2 @@
+subdir('mate-clock')
+subdir('mate-fish')
diff --git a/icons/meson.build b/icons/meson.build
new file mode 100644
index 00000000..eb3023d0
--- /dev/null
+++ b/icons/meson.build
@@ -0,0 +1,53 @@
+icon_names = [
+ 'mate-panel-clock',
+ 'mate-panel-drawer',
+ 'mate-panel-fish',
+ 'mate-panel-force-quit',
+ 'mate-panel-launcher',
+ 'mate-panel-notification-area',
+ 'mate-panel-separator',
+ 'mate-panel',
+ 'mate-panel-window-list',
+ 'mate-panel-window-menu',
+ 'mate-panel-workspace-switcher',
+]
+
+foreach size : ['16x16', '22x22', '24x24', '32x32', '48x48', '64x64', '96x96', '256x256']
+ icons_dir = join_paths(mate_panel_datadir, 'icons', 'hicolor', size, 'apps')
+ install_data(
+ sources: [size + '/mate-panel-clock.png',
+ size + '/mate-panel-drawer.png',
+ size + '/mate-panel-fish.png',
+ size + '/mate-panel-force-quit.png',
+ size + '/mate-panel-launcher.png',
+ size + '/mate-panel-notification-area.png',
+ size + '/mate-panel-separator.png',
+ size + '/mate-panel.png',
+ size + '/mate-panel-window-list.png',
+ size + '/mate-panel-window-menu.png',
+ size + '/mate-panel-workspace-switcher.png'],
+ install_dir: icons_dir,
+ )
+endforeach
+
+install_data(
+ 'scalable/mate-panel-clock.svg',
+ 'scalable/mate-panel-drawer.svg',
+ 'scalable/mate-panel-fish.svg',
+ 'scalable/mate-panel-force-quit.svg',
+ 'scalable/mate-panel-launcher.svg',
+ 'scalable/mate-panel-notification-area.svg',
+ 'scalable/mate-panel-separator.svg',
+ 'scalable/mate-panel.svg',
+ 'scalable/mate-panel-window-list.svg',
+ 'scalable/mate-panel-window-menu.svg',
+ 'scalable/mate-panel-workspace-switcher.svg',
+ install_dir: join_paths(mate_panel_datadir, 'icons', 'hicolor', 'scalable', 'apps'),
+)
+
+gnome = import('gnome')
+
+gnome.post_install(
+ glib_compile_schemas: false,
+ gtk_update_icon_cache: true,
+)
diff --git a/libmate-panel-applet/meson.build b/libmate-panel-applet/meson.build
new file mode 100644
index 00000000..4eb4fe27
--- /dev/null
+++ b/libmate-panel-applet/meson.build
@@ -0,0 +1,145 @@
+libmate_panel_applet_inc = include_directories('.')
+
+glib_mkenums = find_program('glib-mkenums')
+
+# generated marshallers
+libmate_panel_applet_marshal = gnome.genmarshal('mate-panel-applet-marshal',
+ sources: 'mate-panel-applet-marshal.list',
+ prefix: 'mate_panel_applet_marshal',
+)
+
+# generated enumerations
+mate_panel_applet_enum_headers = files('mate-panel-applet.h')
+
+libmate_panel_applet_enums_h = custom_target('mate-panel-applet-enums.h',
+ input: mate_panel_applet_enum_headers,
+ output: 'mate-panel-applet-enums.h',
+ install: true,
+ install_dir: join_paths(get_option('includedir'),
+ 'mate-panel-@0@/libmate-panel-applet'.format(mate_panel_api_version)),
+ command: [
+ glib_mkenums,
+ '--fhead', '#ifndef __MATE_PANEL_APPLET_ENUMS_H__\n#define __MATE_PANEL_APPLET_ENUMS_H__\n\n#ifdef __cplusplus\nextern "C" {\n#endif\n\n',
+ '--ftail', '#ifdef __cplusplus\n}\n#endif\n\n#endif /* __MATE_PANEL_APPLET_ENUMS_H__ */\n',
+ '--fprod', '\n/* --- @filename@ --- */',
+ '--eprod', '#define PANEL_TYPE_@ENUMNAME@ @enum_name@_get_type()\nGType @enum_name@_get_type (void);\n',
+ '--output', '@OUTPUT@',
+ '@INPUT@',
+ ],
+)
+
+libmate_panel_applet_enums_c = custom_target('mate-panel-applet-enums.c',
+ input: mate_panel_applet_enum_headers,
+ output: 'mate-panel-applet-enums.c',
+ command: [
+ glib_mkenums,
+ '--fhead', '#include <glib-object.h>\n#include "mate-panel-applet-enums.h"\n',
+ '--fprod', '\n/* enumerations from "@filename@" */\n#include "@filename@"\n',
+ '--vhead', 'static const G@Type@Value _@enum_name@_values[] = {',
+ '--vprod', ' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },',
+ '--vtail', ' { 0, NULL, NULL }\n};\n\n',
+ '--vtail', 'GType\n@enum_name@_get_type (void)\n{\n',
+ '--vtail', ' static GType type = 0;\n\n',
+ '--vtail', ' if (!type)\n',
+ '--vtail', ' type = g_@type@_register_static ("@EnumName@", _@enum_name@_values);\n\n',
+ '--vtail', ' return type;\n}\n\n',
+ '--output', '@OUTPUT@',
+ '@INPUT@',
+ ],
+)
+
+libmate_panel_applet_sources = [
+ 'mate-panel-applet.h',
+ 'mate-panel-applet.c',
+ 'mate-panel-applet-factory.h',
+ 'mate-panel-applet-factory.c',
+ 'mate-panel-applet-gsettings.c',
+ 'mate-panel-applet-gsettings.h',
+ 'panel-applet-private.h',
+ libmate_panel_applet_marshal,
+ libmate_panel_applet_enums_c,
+ libmate_panel_applet_enums_h,
+]
+
+if have_x11
+ libmate_panel_applet_sources += ['panel-plug.c', 'panel-plug-private.h']
+endif
+
+libmate_panel_applet_deps_local = libmate_panel_applet_deps
+if have_x11
+ libmate_panel_applet_deps_local += x11_dep
+endif
+
+libmate_panel_applet_lib = library('mate-panel-applet-4',
+ libmate_panel_applet_sources,
+ version: '@0@.@1@.@2@'.format(libmate_panel_applet_current, libmate_panel_applet_age, libmate_panel_applet_revision),
+ include_directories: libmate_panel_applet_inc,
+ dependencies: libmate_panel_applet_deps_local,
+ c_args: disable_deprecated_flags,
+ install: true,
+)
+
+install_headers(
+ 'mate-panel-applet.h',
+ 'mate-panel-applet-gsettings.h',
+ subdir: 'mate-panel-@0@/libmate-panel-applet'.format(mate_panel_api_version),
+)
+
+pkg = import('pkgconfig')
+
+pkg.generate(libmate_panel_applet_lib,
+ filebase: 'libmatepanelapplet-@0@'.format(mate_panel_api_version),
+ name: 'libmate-panel-applet-4',
+ description: 'libmate-panel-applet-4',
+ version: mate_panel_version,
+ requires: ['glib-2.0', 'gio-2.0', 'gtk+-3.0'],
+ subdirs: 'mate-panel-@0@/libmate-panel-applet'.format(mate_panel_api_version),
+ install_dir: join_paths(mate_panel_libdir, 'pkgconfig'),
+)
+
+# test program
+executable('test-dbus-applet',
+ 'test-dbus-applet.c',
+ include_directories: libmate_panel_applet_inc,
+ dependencies: libmate_panel_applet_deps_local,
+ link_with: libmate_panel_applet_lib,
+)
+
+# test applet desktop file (not installed)
+test_applet_desktop = i18n.merge_file(
+ input: 'org.mate.panel.TestApplet.mate-panel-applet.desktop.in',
+ output: 'org.mate.panel.TestApplet.mate-panel-applet',
+ type: 'desktop',
+ po_dir: '../po',
+ install: false,
+)
+
+# introspection
+if enable_introspection.allowed()
+ introspection_sources = [
+ 'mate-panel-applet.c',
+ 'mate-panel-applet.h',
+ 'mate-panel-applet-gsettings.c',
+ 'mate-panel-applet-gsettings.h',
+ ]
+ built_introspection_sources = [
+ libmate_panel_applet_enums_c,
+ libmate_panel_applet_enums_h,
+ ]
+
+ mate_panel_applet_gir = gnome.generate_gir(libmate_panel_applet_lib,
+ sources: introspection_sources + built_introspection_sources,
+ nsversion: mate_panel_gir_version,
+ namespace: mate_panel_gir_ns,
+ symbol_prefix: 'mate_panel_applet',
+ identifier_prefix: 'MatePanelApplet',
+ export_packages: 'libmatepanelapplet-@0@'.format(mate_panel_api_version),
+ includes: ['GObject-2.0', 'Gtk-3.0', 'Gio-2.0'],
+ install: true,
+ extra_args: [
+ '--warn-all',
+ '--strip-prefix=MatePanel',
+ '--add-include-path=@0@'.format(meson.current_source_dir()),
+ ],
+ )
+endif
diff --git a/man/meson.build b/man/meson.build
new file mode 100644
index 00000000..d93ce456
--- /dev/null
+++ b/man/meson.build
@@ -0,0 +1,5 @@
+install_man(
+ 'mate-panel.1',
+ 'mate-desktop-item-edit.1',
+ 'mate-panel-test-applets.1',
+)
diff --git a/mate-panel/applet.c b/mate-panel/applet.c
index c41f9d85..9f666392 100644
--- a/mate-panel/applet.c
+++ b/mate-panel/applet.c
@@ -764,12 +764,13 @@ mate_panel_applet_destroy (GtkWidget *widget,
}
typedef struct {
- char *id;
- PanelObjectType type;
- char *toplevel_id;
- int position;
- guint right_stick : 1;
- guint locked : 1;
+ char *id;
+ PanelObjectType type;
+ char *toplevel_id;
+ int position;
+ PanelObjectPackType pack_type;
+ int pack_index;
+ guint locked : 1;
} MatePanelAppletToLoad;
/* Each time those lists get both empty,
@@ -892,13 +893,6 @@ mate_panel_applet_load_idle_handler (gpointer dummy)
panel_widget = panel_toplevel_get_panel_widget (toplevel);
- if (applet->right_stick) {
- if (!panel_widget->packed)
- applet->position = panel_widget->size - applet->position;
- else
- applet->position = -1;
- }
-
/* We load applets asynchronously, so we specifically don't call
* mate_panel_applet_stop_loading() for this type. However, in case of
* failure during the load, we might call mate_panel_applet_stop_loading()
@@ -913,18 +907,24 @@ mate_panel_applet_load_idle_handler (gpointer dummy)
panel_widget,
applet->locked,
applet->position,
+ applet->pack_type,
+ applet->pack_index,
applet->id);
break;
case PANEL_OBJECT_DRAWER:
drawer_load_from_gsettings (panel_widget,
applet->locked,
applet->position,
+ applet->pack_type,
+ applet->pack_index,
applet->id);
break;
case PANEL_OBJECT_MENU:
panel_menu_button_load_from_gsettings (panel_widget,
applet->locked,
applet->position,
+ applet->pack_type,
+ applet->pack_index,
TRUE,
applet->id);
break;
@@ -932,6 +932,8 @@ mate_panel_applet_load_idle_handler (gpointer dummy)
launcher_load_from_gsettings (panel_widget,
applet->locked,
applet->position,
+ applet->pack_type,
+ applet->pack_index,
applet->id);
break;
case PANEL_OBJECT_ACTION:
@@ -939,6 +941,8 @@ mate_panel_applet_load_idle_handler (gpointer dummy)
panel_widget,
applet->locked,
applet->position,
+ applet->pack_type,
+ applet->pack_index,
TRUE,
applet->id);
break;
@@ -947,6 +951,8 @@ mate_panel_applet_load_idle_handler (gpointer dummy)
panel_widget,
applet->locked,
applet->position,
+ applet->pack_type,
+ applet->pack_index,
TRUE,
applet->id);
break;
@@ -954,6 +960,8 @@ mate_panel_applet_load_idle_handler (gpointer dummy)
panel_separator_load_from_gsettings (panel_widget,
applet->locked,
applet->position,
+ applet->pack_type,
+ applet->pack_index,
applet->id);
break;
default:
@@ -969,12 +977,13 @@ mate_panel_applet_load_idle_handler (gpointer dummy)
}
void
-mate_panel_applet_queue_applet_to_load (const char *id,
- PanelObjectType type,
- const char *toplevel_id,
- int position,
- gboolean right_stick,
- gboolean locked)
+mate_panel_applet_queue_applet_to_load (const char *id,
+ PanelObjectType type,
+ const char *toplevel_id,
+ int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
+ gboolean locked)
{
MatePanelAppletToLoad *applet;
@@ -989,7 +998,8 @@ mate_panel_applet_queue_applet_to_load (const char *id,
applet->type = type;
applet->toplevel_id = g_strdup (toplevel_id);
applet->position = position;
- applet->right_stick = right_stick != FALSE;
+ applet->pack_type = pack_type;
+ applet->pack_index = pack_index;
applet->locked = locked != FALSE;
mate_panel_applets_to_load = g_slist_prepend (mate_panel_applets_to_load, applet);
@@ -1003,9 +1013,16 @@ mate_panel_applet_compare (const MatePanelAppletToLoad *a,
if ((c = strcmp (a->toplevel_id, b->toplevel_id)))
return c;
- else if (a->right_stick != b->right_stick)
- return b->right_stick ? -1 : 1;
+ else if (a->pack_type != b->pack_type)
+ return a->pack_type - b->pack_type; /* start < center < end */
+ else if (a->pack_index != b->pack_index)
+ /* note: for packed-end, we explicitly want to start loading
+ * from the right/bottom instead of left/top to avoid moving
+ * applets that are on the inside; so the maths are good even
+ * in this case */
+ return a->pack_index - b->pack_index;
else
+ /* Fallback to pixel position in case all pack_index are 0. */
return a->position - b->position;
}
@@ -1086,11 +1103,10 @@ mate_panel_applet_save_position (AppletInfo *applet_info,
gboolean immediate)
{
PanelWidget *panel_widget;
+ AppletData *applet_data;
const char *toplevel_id;
char *old_toplevel_id;
- gboolean right_stick;
gboolean locked;
- int position;
g_return_if_fail (applet_info != NULL);
@@ -1112,9 +1128,8 @@ mate_panel_applet_save_position (AppletInfo *applet_info,
return;
panel_widget = mate_panel_applet_get_panel_widget (applet_info);
-
- /* FIXME: Instead of getting keys, comparing and setting, there
- should be a dirty flag */
+ applet_data = g_object_get_data (G_OBJECT (applet_info->widget),
+ MATE_PANEL_APPLET_DATA);
old_toplevel_id = g_settings_get_string (applet_info->settings, PANEL_OBJECT_TOPLEVEL_ID_KEY);
if (old_toplevel_id == NULL || strcmp (old_toplevel_id, toplevel_id) != 0)
@@ -1122,33 +1137,22 @@ mate_panel_applet_save_position (AppletInfo *applet_info,
g_free (old_toplevel_id);
/* Note: changing some properties of the panel that may not be locked down
- (e.g. background) can change the state of the "panel_right_stick" and
- "position" properties of an applet that may in fact be locked down.
+ (e.g. background) can change the state of the "pack-type" and
+ "pack-index" properties of an applet that may in fact be locked down.
So check if these are writable before attempting to write them */
locked = panel_widget_get_applet_locked (panel_widget, applet_info->widget) ? 1 : 0;
if (g_settings_get_boolean (applet_info->settings, PANEL_OBJECT_LOCKED_KEY) ? 1 : 0 != locked)
g_settings_set_boolean (applet_info->settings, PANEL_OBJECT_LOCKED_KEY, locked);
- if (locked) {
- /* Until position calculations are refactored to fix the issue of the panel applets
- getting reordered on resolution changes...
- .. don't save position/right-stick on locked applets */
- return;
- }
-
- right_stick = panel_is_applet_right_stick (applet_info->widget) ? 1 : 0;
- if (g_settings_is_writable (applet_info->settings, PANEL_OBJECT_PANEL_RIGHT_STICK_KEY) &&
- (g_settings_get_boolean (applet_info->settings, PANEL_OBJECT_PANEL_RIGHT_STICK_KEY) ? 1 : 0) != right_stick)
- g_settings_set_boolean (applet_info->settings, PANEL_OBJECT_PANEL_RIGHT_STICK_KEY, right_stick);
-
- position = mate_panel_applet_get_position (applet_info);
- if (right_stick && !panel_widget->packed)
- position = panel_widget->size - position;
-
- if (g_settings_is_writable (applet_info->settings, PANEL_OBJECT_POSITION_KEY) &&
- g_settings_get_int (applet_info->settings, PANEL_OBJECT_POSITION_KEY) != position)
- g_settings_set_int (applet_info->settings, PANEL_OBJECT_POSITION_KEY, position);
+ if (g_settings_is_writable (applet_info->settings, PANEL_OBJECT_PACK_TYPE_KEY))
+ g_settings_set_enum (applet_info->settings,
+ PANEL_OBJECT_PACK_TYPE_KEY,
+ applet_data->pack_type);
+ if (g_settings_is_writable (applet_info->settings, PANEL_OBJECT_PACK_INDEX_KEY))
+ g_settings_set_int (applet_info->settings,
+ PANEL_OBJECT_PACK_INDEX_KEY,
+ applet_data->pack_index);
}
const char *
@@ -1220,15 +1224,17 @@ mate_panel_applet_get_by_type (PanelObjectType object_type, GdkScreen *screen)
}
AppletInfo *
-mate_panel_applet_register (GtkWidget *applet,
- gpointer data,
- GDestroyNotify data_destroy,
- PanelWidget *panel,
- gboolean locked,
- gint pos,
- gboolean exactpos,
- PanelObjectType type,
- const char *id)
+mate_panel_applet_register (GtkWidget *applet,
+ gpointer data,
+ GDestroyNotify data_destroy,
+ PanelWidget *panel,
+ gboolean locked,
+ gint pos,
+ PanelObjectPackType pack_type,
+ int pack_index,
+ gboolean exactpos,
+ PanelObjectType type,
+ const char *id)
{
AppletInfo *info;
gchar *path;
@@ -1287,14 +1293,14 @@ mate_panel_applet_register (GtkWidget *applet,
registered_applets = g_slist_append (registered_applets, info);
- if (panel_widget_add (panel, applet, locked, pos, exactpos) == -1 &&
- panel_widget_add (panel, applet, locked, 0, TRUE) == -1) {
+ if (panel_widget_add (panel, applet, locked, pos, pack_type, pack_index, exactpos) == -1 &&
+ panel_widget_add (panel, applet, locked, 0, PANEL_OBJECT_PACK_START, 0, FALSE) == -1) {
GSList *l;
for (l = panels; l; l = l->next) {
panel = PANEL_WIDGET (l->data);
- if (panel_widget_add (panel, applet, locked, 0, TRUE) != -1)
+ if (panel_widget_add (panel, applet, locked, 0, PANEL_OBJECT_PACK_START, 0, FALSE) != -1)
break;
}
@@ -1355,13 +1361,13 @@ mate_panel_applet_can_freely_move (AppletInfo *applet)
if (panel_lockdown_get_locked_down ())
return FALSE;
- if (!g_settings_is_writable (applet->settings, PANEL_OBJECT_POSITION_KEY))
+ if (!g_settings_is_writable (applet->settings, PANEL_OBJECT_PACK_TYPE_KEY))
return FALSE;
- if (!g_settings_is_writable (applet->settings, PANEL_OBJECT_TOPLEVEL_ID_KEY))
+ if (!g_settings_is_writable (applet->settings, PANEL_OBJECT_PACK_INDEX_KEY))
return FALSE;
- if (!g_settings_is_writable (applet->settings, PANEL_OBJECT_PANEL_RIGHT_STICK_KEY))
+ if (!g_settings_is_writable (applet->settings, PANEL_OBJECT_TOPLEVEL_ID_KEY))
return FALSE;
return TRUE;
diff --git a/mate-panel/applet.h b/mate-panel/applet.h
index b7b3603b..804d9fba 100644
--- a/mate-panel/applet.h
+++ b/mate-panel/applet.h
@@ -47,15 +47,17 @@ typedef struct {
GtkWidget *submenu;
} AppletUserMenu;
-AppletInfo *mate_panel_applet_register (GtkWidget *applet,
- gpointer data,
- GDestroyNotify data_destroy,
- PanelWidget *panel,
- gboolean locked,
- gint pos,
- gboolean exactpos,
- PanelObjectType type,
- const char *id);
+AppletInfo *mate_panel_applet_register (GtkWidget *applet,
+ gpointer data,
+ GDestroyNotify data_destroy,
+ PanelWidget *panel,
+ gboolean locked,
+ gint pos,
+ PanelObjectPackType pack_type,
+ int pack_index,
+ gboolean exactpos,
+ PanelObjectType type,
+ const char *id);
void mate_panel_applet_stop_loading (const char *id);
const char *mate_panel_applet_get_id (AppletInfo *info);
@@ -67,12 +69,13 @@ GSList *mate_panel_applet_list_applets (void);
void mate_panel_applet_clean (AppletInfo *info);
-void mate_panel_applet_queue_applet_to_load (const char *id,
- PanelObjectType type,
- const char *toplevel_id,
- int position,
- gboolean right_stick,
- gboolean locked);
+void mate_panel_applet_queue_applet_to_load (const char *id,
+ PanelObjectType type,
+ const char *toplevel_id,
+ int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
+ gboolean locked);
void mate_panel_applet_load_queued_applets (gboolean initial_load);
gboolean mate_panel_applet_on_load_queue (const char *id);
@@ -94,7 +97,7 @@ void mate_panel_applet_save_position (AppletInfo *applet_info,
int mate_panel_applet_get_position (AppletInfo *applet);
/* True if all the keys relevant to moving are writable
- (position, toplevel_id, panel_right_stick) */
+ (pack_type, pack_index, toplevel_id) */
gboolean mate_panel_applet_can_freely_move (AppletInfo *applet);
/* True if the locked flag is writable */
diff --git a/mate-panel/drawer-private.h b/mate-panel/drawer-private.h
index b8db81f8..bc067229 100644
--- a/mate-panel/drawer-private.h
+++ b/mate-panel/drawer-private.h
@@ -128,6 +128,8 @@ static void load_drawer_applet (char *toplevel_id,
PanelToplevel *parent_toplevel,
gboolean locked,
int pos,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id);
diff --git a/mate-panel/drawer.c b/mate-panel/drawer.c
index 03d6bd5f..edca5096 100644
--- a/mate-panel/drawer.c
+++ b/mate-panel/drawer.c
@@ -492,6 +492,8 @@ load_drawer_applet (char *toplevel_id,
PanelToplevel *parent_toplevel,
gboolean locked,
int pos,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id)
{
@@ -526,7 +528,7 @@ load_drawer_applet (char *toplevel_id,
drawer->info = mate_panel_applet_register (drawer->button, drawer,
(GDestroyNotify) g_free,
panel_widget,
- locked, pos, exactpos,
+ locked, pos, pack_type, pack_index, exactpos,
PANEL_OBJECT_DRAWER, id);
if (!drawer->info) {
@@ -621,8 +623,14 @@ panel_drawer_create (PanelToplevel *toplevel,
const char *tooltip)
{
char *id;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
- id = panel_profile_prepare_object (PANEL_OBJECT_DRAWER, toplevel, position, FALSE);
+ panel_widget_get_insert_at_pos (panel_toplevel_get_panel_widget (toplevel),
+ &pack_type, &pack_index, position);
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_DRAWER, toplevel, position,
+ pack_type, pack_index);
panel_drawer_prepare (id, custom_icon, use_custom_icon, tooltip, NULL);
@@ -640,8 +648,17 @@ panel_drawer_create_with_id (const char *toplevel_id,
{
char *id;
char *attached_toplevel_id = NULL;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
+ PanelToplevel *toplevel;
+
+ toplevel = panel_profile_get_toplevel_by_id (toplevel_id);
+ if (toplevel)
+ panel_widget_get_insert_at_pos (panel_toplevel_get_panel_widget (toplevel),
+ &pack_type, &pack_index, position);
- id = panel_profile_prepare_object_with_id (PANEL_OBJECT_DRAWER, toplevel_id, position, FALSE);
+ id = panel_profile_prepare_object_with_id (PANEL_OBJECT_DRAWER, toplevel_id, position,
+ pack_type, pack_index);
panel_drawer_prepare (id, custom_icon, use_custom_icon, tooltip, &attached_toplevel_id);
@@ -656,6 +673,8 @@ void
drawer_load_from_gsettings (PanelWidget *panel_widget,
gboolean locked,
gint position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id)
{
gboolean use_custom_icon;
@@ -689,6 +708,8 @@ drawer_load_from_gsettings (PanelWidget *panel_widget,
panel_widget->toplevel,
locked,
position,
+ pack_type,
+ pack_index,
TRUE,
id);
diff --git a/mate-panel/drawer.h b/mate-panel/drawer.h
index 04fcd0a1..c48ac7b3 100644
--- a/mate-panel/drawer.h
+++ b/mate-panel/drawer.h
@@ -36,6 +36,8 @@ char *panel_drawer_create_with_id (const char *toplevel_id,
void drawer_load_from_gsettings (PanelWidget *panel_widget,
gboolean locked,
gint position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id);
void panel_drawer_set_dnd_enabled (Drawer *drawer,
diff --git a/mate-panel/launcher.c b/mate-panel/launcher.c
index 0385ccea..2732aa85 100644
--- a/mate-panel/launcher.c
+++ b/mate-panel/launcher.c
@@ -880,6 +880,8 @@ load_launcher_applet (const char *location,
PanelWidget *panel,
gboolean locked,
int pos,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id)
{
@@ -892,7 +894,7 @@ load_launcher_applet (const char *location,
launcher->info = mate_panel_applet_register (launcher->button, launcher,
free_launcher,
- panel, locked, pos, exactpos,
+ panel, locked, pos, pack_type, pack_index, exactpos,
PANEL_OBJECT_LAUNCHER, id);
if (!launcher->info) {
free_launcher (launcher);
@@ -917,6 +919,8 @@ void
launcher_load_from_gsettings (PanelWidget *panel_widget,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id)
{
GSettings *settings;
@@ -944,6 +948,8 @@ launcher_load_from_gsettings (PanelWidget *panel_widget,
panel_widget,
locked,
position,
+ pack_type,
+ pack_index,
TRUE,
id);
@@ -1088,13 +1094,21 @@ panel_launcher_create_with_id (const char *toplevel_id,
char *id;
char *no_uri;
char *new_location;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
+ PanelToplevel *toplevel;
g_return_if_fail (location != NULL);
+ toplevel = panel_profile_get_toplevel_by_id (toplevel_id);
+ if (toplevel)
+ panel_widget_get_insert_at_pos (panel_toplevel_get_panel_widget (toplevel),
+ &pack_type, &pack_index, position);
+
id = panel_profile_prepare_object_with_id (PANEL_OBJECT_LAUNCHER,
toplevel_id,
position,
- FALSE);
+ pack_type, pack_index);
path = g_strdup_printf ("%s%s/", PANEL_OBJECT_PATH, id);
settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA, path);
diff --git a/mate-panel/launcher.h b/mate-panel/launcher.h
index 8cfd50b9..a46b0a55 100644
--- a/mate-panel/launcher.h
+++ b/mate-panel/launcher.h
@@ -58,6 +58,8 @@ void launcher_properties (Launcher *launcher);
void launcher_load_from_gsettings (PanelWidget *panel_widget,
gboolean locked,
gint position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id);
void panel_launcher_delete (Launcher *launcher);
diff --git a/mate-panel/libmate-panel-applet-private/meson.build b/mate-panel/libmate-panel-applet-private/meson.build
new file mode 100644
index 00000000..14187815
--- /dev/null
+++ b/mate-panel/libmate-panel-applet-private/meson.build
@@ -0,0 +1,47 @@
+panel_applet_private_inc = include_directories('.')
+
+libmate_panel_applet_private_sources = [
+ 'panel-applets-manager-dbus.c',
+ 'panel-applets-manager-dbus.h',
+ 'panel-applet-container.c',
+ 'panel-applet-container.h',
+ 'panel-applet-frame-dbus.c',
+ 'panel-applet-frame-dbus.h',
+]
+
+libmate_panel_applet_private_mini_sources = [
+ 'panel-applet-mini.c',
+ 'panel-applets-manager-dbus.c',
+ 'panel-applets-manager-dbus.h',
+ 'panel-applet-container.c',
+ 'panel-applet-container.h',
+]
+
+libmate_panel_applet_private_common_args = [
+ '-DDATADIR="@0@"'.format(mate_panel_datadir),
+ '-DMATE_PANEL_APPLETS_DIR="@0@"'.format(mate_panel_appletsdir),
+] + disable_deprecated_flags
+
+libmate_panel_applet_private_inc_dirs = [
+ panel_applet_private_inc,
+ mate_panel_inc,
+ libpanel_util_inc,
+]
+
+libmate_panel_applet_private_deps = panel_deps + [dconf_dep]
+
+libmate_panel_applet_private = static_library('mate-panel-applet-private',
+ libmate_panel_applet_private_sources,
+ panel_marshal,
+ include_directories: libmate_panel_applet_private_inc_dirs,
+ dependencies: libmate_panel_applet_private_deps,
+ c_args: libmate_panel_applet_private_common_args,
+)
+
+libmate_panel_applet_private_mini = static_library('mate-panel-applet-private-mini',
+ libmate_panel_applet_private_mini_sources,
+ panel_marshal,
+ include_directories: libmate_panel_applet_private_inc_dirs,
+ dependencies: libmate_panel_applet_private_deps,
+ c_args: libmate_panel_applet_private_common_args,
+)
diff --git a/mate-panel/libmate-panel-applet-private/panel-applet-frame-dbus.c b/mate-panel/libmate-panel-applet-private/panel-applet-frame-dbus.c
index a11d43f4..3ef72b1d 100644
--- a/mate-panel/libmate-panel-applet-private/panel-applet-frame-dbus.c
+++ b/mate-panel/libmate-panel-applet-private/panel-applet-frame-dbus.c
@@ -231,8 +231,14 @@ container_child_background_set (GObject *source_object,
{
MatePanelAppletContainer *container = MATE_PANEL_APPLET_CONTAINER (source_object);
MatePanelAppletFrameDBus *frame = MATE_PANEL_APPLET_FRAME_DBUS (user_data);
+ GError *error = NULL;
+
+ mate_panel_applet_container_child_set_finish (container, res, &error);
- mate_panel_applet_container_child_set_finish (container, res, NULL);
+ if (error) {
+ g_error_free (error);
+ return;
+ }
frame->priv->bg_operation = NULL;
}
@@ -327,6 +333,8 @@ mate_panel_applet_frame_dbus_finalize (GObject *object)
{
MatePanelAppletFrameDBus *frame = MATE_PANEL_APPLET_FRAME_DBUS (object);
+ if (frame->priv->bg_operation)
+ mate_panel_applet_container_cancel_operation (frame->priv->container, frame->priv->bg_operation);
frame->priv->bg_operation = NULL;
G_OBJECT_CLASS (mate_panel_applet_frame_dbus_parent_class)->finalize (object);
diff --git a/mate-panel/libpanel-util/meson.build b/mate-panel/libpanel-util/meson.build
new file mode 100644
index 00000000..6383084c
--- /dev/null
+++ b/mate-panel/libpanel-util/meson.build
@@ -0,0 +1,33 @@
+libpanel_util_sources = [
+ 'panel-cleanup.c',
+ 'panel-cleanup.h',
+ 'panel-color.c',
+ 'panel-color.h',
+ 'panel-error.c',
+ 'panel-error.h',
+ 'panel-glib.c',
+ 'panel-glib.h',
+ 'panel-gtk.c',
+ 'panel-gtk.h',
+ 'panel-icon-chooser.c',
+ 'panel-icon-chooser.h',
+ 'panel-keyfile.c',
+ 'panel-keyfile.h',
+ 'panel-launch.c',
+ 'panel-launch.h',
+ 'panel-list.c',
+ 'panel-list.h',
+ 'panel-session-manager.c',
+ 'panel-session-manager.h',
+ 'panel-show.c',
+ 'panel-show.h',
+ 'panel-xdg.c',
+ 'panel-xdg.h',
+]
+
+libpanel_util = static_library('panel-util',
+ libpanel_util_sources,
+ include_directories: libpanel_util_inc,
+ dependencies: panel_deps + [dconf_dep],
+ c_args: ['-DDATADIR="@0@"'.format(mate_panel_datadir)] + disable_deprecated_flags,
+)
diff --git a/mate-panel/meson.build b/mate-panel/meson.build
new file mode 100644
index 00000000..95af7190
--- /dev/null
+++ b/mate-panel/meson.build
@@ -0,0 +1,355 @@
+mate_panel_inc = include_directories('.')
+mate_submodules_inc = include_directories('mate-submodules')
+libpanel_util_inc = include_directories('libpanel-util')
+
+glib_mkenums = find_program('glib-mkenums')
+glib_compile_resources = find_program('glib-compile-resources')
+
+# --- generated sources ---
+
+# marshallers
+panel_marshal = gnome.genmarshal('panel-marshal',
+ sources: 'panel-marshal.list',
+ prefix: 'panel_marshal',
+)
+
+# enumerations
+panel_enum_headers = [
+ 'panel-enums.h',
+ 'panel-enums-gsettings.h',
+ 'panel-types.h',
+]
+
+panel_typebuiltins_c = custom_target('panel-typebuiltins.c',
+ input: panel_enum_headers,
+ output: 'panel-typebuiltins.c',
+ command: [
+ glib_mkenums,
+ '--fhead', '#include <glib-object.h>\n',
+ '--fhead', '#include "panel-typebuiltins.h"\n\n',
+ '--fprod', '\n/* enumerations from "@filename@" */',
+ '--fprod', '\n#include "@filename@"\n',
+ '--vhead', 'static const GEnumValue _@enum_name@_values[] = {',
+ '--vprod', ' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },',
+ '--vtail', ' { 0, NULL, NULL }\n};\n\n',
+ '--vtail', 'GType\n@enum_name@_get_type (void)\n{\n',
+ '--vtail', ' static GType type = 0;\n\n',
+ '--vtail', ' if (!type)\n',
+ '--vtail', ' type = g_enum_register_static ("@EnumName@", _@enum_name@_values);\n\n',
+ '--vtail', ' return type;\n}\n\n',
+ '--output', '@OUTPUT@',
+ '@INPUT@',
+ ],
+)
+
+panel_typebuiltins_h = custom_target('panel-typebuiltins.h',
+ input: panel_enum_headers,
+ output: 'panel-typebuiltins.h',
+ command: [
+ glib_mkenums,
+ '--fhead', '#ifndef __PANEL_TYPEBUILTINS_H__\n',
+ '--fhead', '#define __PANEL_TYPEBUILTINS_H__ 1\n\n',
+ '--fhead', '#ifdef __cplusplus\nextern "C" {\n#endif\n\n',
+ '--ftail', '#ifdef __cplusplus\n}\n#endif\n\n',
+ '--ftail', '#endif /* __PANEL_TYPEBUILTINS_H__ */\n',
+ '--fprod', '\n/* --- @filename@ --- */',
+ '--eprod', '#define PANEL_TYPE_@ENUMSHORT@ @enum_name@_get_type()\n',
+ '--eprod', 'GType @enum_name@_get_type (void);\n',
+ '--output', '@OUTPUT@',
+ '@INPUT@',
+ ],
+)
+
+# resources
+panel_resource_deps = [
+ 'panel-ditem-editor-dialog.ui',
+ 'panel-properties-dialog.ui',
+ 'panel-run-dialog.ui',
+ '../data/theme/mate-panel.css',
+ '../data/theme/panel-grid-symbolic.svg',
+]
+
+panel_resources_c = custom_target('panel-resources.c',
+ input: 'panel.gresource.xml',
+ output: 'panel-resources.c',
+ depend_files: panel_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-source',
+ '--c-name', 'panel',
+ '@INPUT@',
+ ],
+)
+
+panel_resources_h = custom_target('panel-resources.h',
+ input: 'panel.gresource.xml',
+ output: 'panel-resources.h',
+ depend_files: panel_resource_deps,
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-header',
+ '--c-name', 'panel',
+ '@INPUT@',
+ ],
+)
+
+panel_test_applets_resources_c = custom_target('panel-test-applets-resources.c',
+ input: 'panel-test-applets.gresource.xml',
+ output: 'panel-test-applets-resources.c',
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-source',
+ '--c-name', 'panel',
+ '@INPUT@',
+ ],
+)
+
+panel_test_applets_resources_h = custom_target('panel-test-applets-resources.h',
+ input: 'panel-test-applets.gresource.xml',
+ output: 'panel-test-applets-resources.h',
+ command: [
+ glib_compile_resources,
+ '--target', '@OUTPUT@',
+ '--sourcedir', meson.current_source_dir(),
+ '--generate-header',
+ '--c-name', 'panel',
+ '@INPUT@',
+ ],
+)
+
+# --- sub-libraries ---
+
+# libegg is built from the mate-submodules git submodule, whose working tree
+# is not tracked by this repository. Build it directly from here so that a
+# fresh checkout (with the submodule populated) needs no extra meson files.
+libegg_sources = files(
+ 'mate-submodules/libegg/eggtreemultidnd.c',
+ 'mate-submodules/libegg/eggtreemultidnd.h',
+ 'mate-submodules/libegg/eggdesktopfile.c',
+ 'mate-submodules/libegg/eggdesktopfile.h',
+ 'mate-submodules/libegg/eggsmclient.c',
+ 'mate-submodules/libegg/eggsmclient.h',
+ 'mate-submodules/libegg/eggsmclient-private.h',
+ 'mate-submodules/libegg/eggsmclient-xsmp.c',
+)
+
+libegg = static_library('egg',
+ libegg_sources,
+ dependencies: [ice_dep, sm_dep, gtk_dep, glib_dep],
+ c_args: [
+ '-DEGG_SM_CLIENT_BACKEND_XSMP',
+ '-DG_LOG_DOMAIN="EggSMClient"',
+ ] + disable_deprecated_flags,
+)
+
+subdir('libmate-panel-applet-private')
+subdir('libpanel-util')
+
+# --- programs ---
+
+panel_common_cpp_args = [
+ '-DMATELOCALEDIR="@0@"'.format(mate_panel_localedir),
+ '-DPANELDATADIR="@0@"'.format(mate_panel_pkgdatadir),
+ '-DPANEL_MODULES_DIR="@0@"'.format(mate_panel_modulesdir),
+] + disable_deprecated_flags
+
+panel_common_inc_dirs = [
+ mate_panel_inc,
+ libpanel_util_inc,
+ mate_submodules_inc,
+]
+
+panel_common_deps = panel_deps + [dconf_dep]
+
+panel_sources = [
+ panel_marshal,
+ panel_typebuiltins_c,
+ panel_typebuiltins_h,
+ panel_resources_c,
+ panel_resources_h,
+ 'main.c',
+ 'panel-widget.c',
+ 'button-widget.c',
+ 'panel-session.c',
+ 'panel.c',
+ 'applet.c',
+ 'drawer.c',
+ 'panel-config-global.c',
+ 'panel-util.c',
+ 'panel-properties-dialog.c',
+ 'panel-run-dialog.c',
+ 'menu.c',
+ 'panel-context-menu.c',
+ 'launcher.c',
+ 'panel-applet-frame.c',
+ 'panel-applets-manager.c',
+ 'panel-shell.c',
+ 'panel-background.c',
+ 'panel-stock-icons.c',
+ 'panel-action-button.c',
+ 'panel-menu-bar.c',
+ 'panel-menu-button.c',
+ 'panel-menu-items.c',
+ 'panel-separator.c',
+ 'panel-recent.c',
+ 'panel-toplevel.c',
+ 'panel-frame.c',
+ 'panel-multimonitor.c',
+ 'panel-a11y.c',
+ 'panel-bindings.c',
+ 'panel-layout.c',
+ 'panel-profile.c',
+ 'panel-lockdown.c',
+ 'panel-addto.c',
+ 'panel-ditem-editor.c',
+ 'panel-modules.c',
+ 'panel-applet-info.c',
+ 'panel-reset.c',
+ 'panel-types.h',
+ 'panel-widget.h',
+ 'panel-globals.h',
+ 'button-widget.h',
+ 'panel-session.h',
+ 'panel.h',
+ 'applet.h',
+ 'drawer.h',
+ 'drawer-private.h',
+ 'panel-util.h',
+ 'panel-properties-dialog.h',
+ 'panel-config-global.h',
+ 'panel-run-dialog.h',
+ 'menu.h',
+ 'panel-context-menu.h',
+ 'launcher.h',
+ 'panel-applet-frame.h',
+ 'panel-applets-manager.h',
+ 'panel-shell.h',
+ 'panel-background.h',
+ 'panel-stock-icons.h',
+ 'panel-action-button.h',
+ 'panel-menu-bar.h',
+ 'panel-menu-button.h',
+ 'panel-menu-items.h',
+ 'panel-separator.h',
+ 'panel-recent.h',
+ 'panel-toplevel.h',
+ 'panel-frame.h',
+ 'panel-multimonitor.h',
+ 'panel-a11y.h',
+ 'panel-bindings.h',
+ 'panel-layout.h',
+ 'panel-profile.h',
+ 'panel-enums-gsettings.h',
+ 'panel-enums.h',
+ 'panel-lockdown.h',
+ 'panel-addto.h',
+ 'panel-ditem-editor.h',
+ 'panel-icon-names.h',
+ 'panel-modules.h',
+ 'panel-applet-info.h',
+ 'panel-reset.h',
+ 'panel-schemas.h',
+]
+
+if have_wayland
+ panel_sources += ['wayland-backend.c', 'wayland-backend.h']
+endif
+
+if have_x11
+ panel_sources += [
+ 'xstuff.c',
+ 'panel-xutils.c',
+ 'panel-force-quit.c',
+ 'panel-action-protocol.c',
+ 'panel-struts.c',
+ 'xstuff.h',
+ 'panel-xutils.h',
+ 'panel-force-quit.h',
+ 'panel-action-protocol.h',
+ 'panel-struts.h',
+ ]
+endif
+
+mate_panel_deps = panel_common_deps + [randr_dep]
+if have_x11
+ mate_panel_deps += x11_dep
+endif
+if have_wayland
+ mate_panel_deps += wayland_deps
+endif
+
+executable('mate-panel',
+ panel_sources,
+ include_directories: panel_common_inc_dirs,
+ dependencies: mate_panel_deps,
+ c_args: panel_common_cpp_args + ['-DMATEMENU_I_KNOW_THIS_IS_UNSTABLE'],
+ link_with: [libegg, libmate_panel_applet_private, libpanel_util],
+ export_dynamic: true,
+ install: true,
+)
+
+mate_desktop_item_edit_sources = [
+ 'mate-desktop-item-edit.c',
+ 'panel-ditem-editor.c',
+ panel_resources_c,
+ panel_resources_h,
+ panel_marshal,
+ 'panel-util.c',
+]
+
+if have_x11
+ mate_desktop_item_edit_sources += ['xstuff.c']
+endif
+
+mate_desktop_item_edit_deps = panel_common_deps
+if have_x11
+ mate_desktop_item_edit_deps += x11_dep
+endif
+
+executable('mate-desktop-item-edit',
+ mate_desktop_item_edit_sources,
+ include_directories: panel_common_inc_dirs,
+ dependencies: mate_desktop_item_edit_deps,
+ c_args: panel_common_cpp_args,
+ link_with: libpanel_util,
+ export_dynamic: true,
+ install: true,
+)
+
+mate_panel_test_applets_sources = [
+ panel_marshal,
+ panel_test_applets_resources_c,
+ panel_test_applets_resources_h,
+ 'panel-modules.c',
+ 'panel-applet-info.c',
+ 'panel-applets-manager.c',
+ 'panel-test-applets.c',
+]
+
+executable('mate-panel-test-applets',
+ mate_panel_test_applets_sources,
+ include_directories: panel_common_inc_dirs,
+ dependencies: panel_common_deps,
+ c_args: panel_common_cpp_args + [
+ '-DMATE_PANEL_APPLETS_DIR="@0@"'.format(mate_panel_appletsdir),
+ ],
+ link_with: [libmate_panel_applet_private_mini, libpanel_util],
+ export_dynamic: true,
+ install: true,
+)
+
+# desktop file
+mate_panel_desktop = i18n.merge_file(
+ input: 'mate-panel.desktop.in',
+ output: 'mate-panel.desktop',
+ type: 'desktop',
+ po_dir: '../po',
+ install: true,
+ install_dir: join_paths(mate_panel_datadir, 'applications'),
+)
diff --git a/mate-panel/panel-action-button.c b/mate-panel/panel-action-button.c
index 137399f5..ba598ea7 100644
--- a/mate-panel/panel-action-button.c
+++ b/mate-panel/panel-action-button.c
@@ -898,6 +898,8 @@ panel_action_button_load (PanelActionButtonType type,
PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id)
{
@@ -910,7 +912,7 @@ panel_action_button_load (PanelActionButtonType type,
button->priv->info = mate_panel_applet_register (GTK_WIDGET (button),
NULL, NULL,
panel, locked, position,
- exactpos, PANEL_OBJECT_ACTION, id);
+ pack_type, pack_index, exactpos, PANEL_OBJECT_ACTION, id);
if (!button->priv->info) {
gtk_widget_destroy (GTK_WIDGET (button));
return;
@@ -942,8 +944,14 @@ panel_action_button_create (PanelToplevel *toplevel,
GSettings *settings;
char *id;
char *path;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
- id = panel_profile_prepare_object (PANEL_OBJECT_ACTION, toplevel, position, FALSE);
+ panel_widget_get_insert_at_pos (panel_toplevel_get_panel_widget (toplevel),
+ &pack_type, &pack_index, position);
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_ACTION, toplevel, position,
+ pack_type, pack_index);
path = g_strdup_printf (PANEL_OBJECT_PATH "%s/", id);
settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA, path);
@@ -963,6 +971,8 @@ void
panel_action_button_load_from_gsettings (PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id)
{
@@ -979,7 +989,7 @@ panel_action_button_load_from_gsettings (PanelWidget *panel,
g_object_unref (settings);
panel_action_button_load (type, panel, locked,
- position, exactpos, id);
+ position, pack_type, pack_index, exactpos, id);
}
void
diff --git a/mate-panel/panel-action-button.h b/mate-panel/panel-action-button.h
index 0df9d1ab..59805cc2 100644
--- a/mate-panel/panel-action-button.h
+++ b/mate-panel/panel-action-button.h
@@ -69,6 +69,8 @@ void panel_action_button_set_type (PanelActionButton *button,
void panel_action_button_load_from_gsettings (PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id);
diff --git a/mate-panel/panel-applet-frame.c b/mate-panel/panel-applet-frame.c
index f0b5bfa9..b175f787 100644
--- a/mate-panel/panel-applet-frame.c
+++ b/mate-panel/panel-applet-frame.c
@@ -64,6 +64,8 @@ static void mate_panel_applet_frame_load (const gchar *iid,
PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id);
@@ -71,6 +73,8 @@ struct _MatePanelAppletFrameActivating {
gboolean locked;
PanelWidget *panel;
int position;
+ PanelObjectPackType pack_type;
+ int pack_index;
gboolean exactpos;
char *id;
};
@@ -584,8 +588,9 @@ _mate_panel_applet_frame_activated (MatePanelAppletFrame *frame,
info = mate_panel_applet_register (GTK_WIDGET (frame), GTK_WIDGET (frame),
NULL, frame->priv->panel,
frame_act->locked, frame_act->position,
- frame_act->exactpos, PANEL_OBJECT_APPLET,
- frame_act->id);
+ frame_act->pack_type, frame_act->pack_index,
+ frame_act->exactpos,
+ PANEL_OBJECT_APPLET, frame_act->id);
frame->priv->applet_info = info;
panel_widget_set_applet_size_constrained (frame->priv->panel,
@@ -717,8 +722,20 @@ mate_panel_applet_frame_reload_response (GtkWidget *dialog,
mate_panel_applet_clean (info);
}
+ AppletData *applet_data;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_idx = 0;
+
+ if (info) {
+ applet_data = g_object_get_data (G_OBJECT (info->widget), MATE_PANEL_APPLET_DATA);
+ if (applet_data) {
+ pack_type = applet_data->pack_type;
+ pack_idx = applet_data->pack_index;
+ }
+ }
+
mate_panel_applet_frame_load (iid, panel, locked,
- position, TRUE, id);
+ position, pack_type, pack_idx, TRUE, id);
g_free (iid);
g_free (id);
@@ -999,6 +1016,8 @@ mate_panel_applet_frame_load (const gchar *iid,
PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id)
{
@@ -1020,11 +1039,13 @@ mate_panel_applet_frame_load (const gchar *iid,
}
frame_act = g_slice_new0 (MatePanelAppletFrameActivating);
- frame_act->locked = locked;
- frame_act->panel = panel;
- frame_act->position = position;
- frame_act->exactpos = exactpos;
- frame_act->id = g_strdup (id);
+ frame_act->locked = locked;
+ frame_act->panel = panel;
+ frame_act->position = position;
+ frame_act->pack_type = pack_type;
+ frame_act->pack_index = pack_index;
+ frame_act->exactpos = exactpos;
+ frame_act->id = g_strdup (id);
if (!mate_panel_applets_manager_load_applet (iid, frame_act)) {
mate_panel_applet_frame_loading_failed (iid, panel, id);
@@ -1036,6 +1057,8 @@ void
mate_panel_applet_frame_load_from_gsettings (PanelWidget *panel_widget,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id)
{
GSettings *settings;
@@ -1057,7 +1080,7 @@ mate_panel_applet_frame_load_from_gsettings (PanelWidget *panel_widget,
}
mate_panel_applet_frame_load (applet_iid, panel_widget,
- locked, position, TRUE, id);
+ locked, position, pack_type, pack_index, TRUE, id);
g_free (applet_iid);
}
@@ -1070,10 +1093,16 @@ mate_panel_applet_frame_create (PanelToplevel *toplevel,
GSettings *settings;
gchar *path;
char *id;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
g_return_if_fail (iid != NULL);
- id = panel_profile_prepare_object (PANEL_OBJECT_APPLET, toplevel, position, FALSE);
+ panel_widget_get_insert_at_pos (panel_toplevel_get_panel_widget (toplevel),
+ &pack_type, &pack_index, position);
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_APPLET, toplevel, position,
+ pack_type, pack_index);
path = g_strdup_printf (PANEL_OBJECT_PATH "%s/", id);
settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA, path);
diff --git a/mate-panel/panel-applet-frame.h b/mate-panel/panel-applet-frame.h
index 0c0fbd09..18d6943f 100644
--- a/mate-panel/panel-applet-frame.h
+++ b/mate-panel/panel-applet-frame.h
@@ -86,6 +86,8 @@ void mate_panel_applet_frame_create (PanelToplevel *toplevel,
void mate_panel_applet_frame_load_from_gsettings (PanelWidget *panel_widget,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id);
void mate_panel_applet_frame_sync_menu_state (MatePanelAppletFrame *frame);
diff --git a/mate-panel/panel-enums-gsettings.h b/mate-panel/panel-enums-gsettings.h
index bc8a9c42..88b66f2a 100644
--- a/mate-panel/panel-enums-gsettings.h
+++ b/mate-panel/panel-enums-gsettings.h
@@ -31,6 +31,12 @@
G_BEGIN_DECLS
+typedef enum {
+ PANEL_OBJECT_PACK_START = 0,
+ PANEL_OBJECT_PACK_CENTER = 1,
+ PANEL_OBJECT_PACK_END = 2
+} PanelObjectPackType;
+
typedef enum { /*< flags=0 >*/
PANEL_ORIENTATION_TOP = 1 << 0,
PANEL_ORIENTATION_RIGHT = 1 << 1,
diff --git a/mate-panel/panel-layout.c b/mate-panel/panel-layout.c
index d3bda7de..c0ab9ba6 100644
--- a/mate-panel/panel-layout.c
+++ b/mate-panel/panel-layout.c
@@ -80,6 +80,8 @@ static PanelLayoutKeyDefinition panel_layout_toplevel_keys[] = {
static PanelLayoutKeyDefinition panel_layout_object_keys[] = {
{ PANEL_OBJECT_TYPE_KEY, G_TYPE_STRING },
{ PANEL_OBJECT_TOPLEVEL_ID_KEY, G_TYPE_STRING },
+ { PANEL_OBJECT_PACK_TYPE_KEY, G_TYPE_STRING },
+ { PANEL_OBJECT_PACK_INDEX_KEY, G_TYPE_INT },
{ PANEL_OBJECT_POSITION_KEY, G_TYPE_INT },
{ PANEL_OBJECT_PANEL_RIGHT_STICK_KEY, G_TYPE_BOOLEAN },
{ PANEL_OBJECT_LOCKED_KEY, G_TYPE_BOOLEAN },
diff --git a/mate-panel/panel-menu-bar.c b/mate-panel/panel-menu-bar.c
index f8bbcc2e..28ef9084 100644
--- a/mate-panel/panel-menu-bar.c
+++ b/mate-panel/panel-menu-bar.c
@@ -339,7 +339,7 @@ static gboolean panel_menu_bar_on_draw (GtkWidget* widget, cairo_t* cr, gpointer
return FALSE;
}
-static void panel_menu_bar_load(PanelWidget* panel, gboolean locked, int position, gboolean exactpos, const char* id)
+static void panel_menu_bar_load(PanelWidget* panel, gboolean locked, int position, PanelObjectPackType pack_type, int pack_index, gboolean exactpos, const char* id)
{
PanelMenuBar* menubar;
GtkSettings* settings;
@@ -348,7 +348,7 @@ static void panel_menu_bar_load(PanelWidget* panel, gboolean locked, int positio
menubar = g_object_new(PANEL_TYPE_MENU_BAR, NULL);
- menubar->priv->info = mate_panel_applet_register(GTK_WIDGET(menubar), NULL, NULL, panel, locked, position, exactpos, PANEL_OBJECT_MENU_BAR, id);
+ menubar->priv->info = mate_panel_applet_register(GTK_WIDGET(menubar), NULL, NULL, panel, locked, position, pack_type, pack_index, exactpos, PANEL_OBJECT_MENU_BAR, id);
if (!menubar->priv->info)
{
@@ -377,16 +377,22 @@ static void panel_menu_bar_load(PanelWidget* panel, gboolean locked, int positio
panel_menu_bar_update_visibility(menubar->priv->settings, NULL, menubar);
}
-void panel_menu_bar_load_from_gsettings (PanelWidget* panel, gboolean locked, int position, gboolean exactpos, const char* id)
+void panel_menu_bar_load_from_gsettings (PanelWidget* panel, gboolean locked, int position, PanelObjectPackType pack_type, int pack_index, gboolean exactpos, const char* id)
{
- panel_menu_bar_load(panel, locked, position, exactpos, id);
+ panel_menu_bar_load(panel, locked, position, pack_type, pack_index, exactpos, id);
}
void panel_menu_bar_create(PanelToplevel* toplevel, int position)
{
char* id;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
- id = panel_profile_prepare_object(PANEL_OBJECT_MENU_BAR, toplevel, position, FALSE);
+ panel_widget_get_insert_at_pos(panel_toplevel_get_panel_widget(toplevel),
+ &pack_type, &pack_index, position);
+
+ id = panel_profile_prepare_object(PANEL_OBJECT_MENU_BAR, toplevel, position,
+ pack_type, pack_index);
panel_profile_add_to_list(PANEL_GSETTINGS_OBJECTS, id);
g_free(id);
}
diff --git a/mate-panel/panel-menu-bar.h b/mate-panel/panel-menu-bar.h
index f83bf1f1..4ac34199 100644
--- a/mate-panel/panel-menu-bar.h
+++ b/mate-panel/panel-menu-bar.h
@@ -62,6 +62,8 @@ void panel_menu_bar_create (PanelToplevel *toplevel,
void panel_menu_bar_load_from_gsettings (PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id);
diff --git a/mate-panel/panel-menu-button.c b/mate-panel/panel-menu-button.c
index e65a99d6..52dad972 100644
--- a/mate-panel/panel-menu-button.c
+++ b/mate-panel/panel-menu-button.c
@@ -668,6 +668,8 @@ panel_menu_button_load (const char *menu_path,
PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
gboolean has_arrow,
const char *id)
@@ -687,7 +689,7 @@ panel_menu_button_load (const char *menu_path,
NULL);
info = mate_panel_applet_register (GTK_WIDGET (button), NULL, NULL,
- panel, locked, position, exactpos,
+ panel, locked, position, pack_type, pack_index, exactpos,
PANEL_OBJECT_MENU, id);
if (!info) {
gtk_widget_destroy (GTK_WIDGET (button));
@@ -915,6 +917,8 @@ void
panel_menu_button_load_from_gsettings (PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id)
{
@@ -945,6 +949,8 @@ panel_menu_button_load_from_gsettings (PanelWidget *panel,
panel,
locked,
position,
+ pack_type,
+ pack_index,
exactpos,
has_arrow,
id);
@@ -968,8 +974,14 @@ panel_menu_button_create (PanelToplevel *toplevel,
gchar *path;
const char *scheme;
char *id;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
- id = panel_profile_prepare_object (PANEL_OBJECT_MENU, toplevel, position, FALSE);
+ panel_widget_get_insert_at_pos (panel_toplevel_get_panel_widget (toplevel),
+ &pack_type, &pack_index, position);
+
+ id = panel_profile_prepare_object (PANEL_OBJECT_MENU, toplevel, position,
+ pack_type, pack_index);
path = g_strdup_printf (PANEL_OBJECT_PATH "%s/", id);
settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA, path);
diff --git a/mate-panel/panel-menu-button.h b/mate-panel/panel-menu-button.h
index 2a9d2d32..f38a81e0 100644
--- a/mate-panel/panel-menu-button.h
+++ b/mate-panel/panel-menu-button.h
@@ -80,6 +80,8 @@ void panel_menu_button_set_has_arrow (PanelMenuButton *button,
void panel_menu_button_load_from_gsettings (PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
gboolean exactpos,
const char *id);
diff --git a/mate-panel/panel-profile.c b/mate-panel/panel-profile.c
index 08174fe3..512a18b3 100644
--- a/mate-panel/panel-profile.c
+++ b/mate-panel/panel-profile.c
@@ -1248,10 +1248,11 @@ panel_profile_destroy_toplevel (const char *id)
}
char *
-panel_profile_prepare_object_with_id (PanelObjectType object_type,
- const char *toplevel_id,
- int position,
- gboolean right_stick)
+panel_profile_prepare_object_with_id (PanelObjectType object_type,
+ const char *toplevel_id,
+ int position,
+ PanelObjectPackType pack_type,
+ int pack_index)
{
PanelGSettingsKeyType key_type;
char *id;
@@ -1268,7 +1269,8 @@ panel_profile_prepare_object_with_id (PanelObjectType object_type,
g_settings_set_enum (settings, PANEL_OBJECT_TYPE_KEY, object_type);
g_settings_set_string (settings, PANEL_OBJECT_TOPLEVEL_ID_KEY, toplevel_id);
g_settings_set_int (settings, PANEL_OBJECT_POSITION_KEY, position);
- g_settings_set_boolean (settings, PANEL_OBJECT_PANEL_RIGHT_STICK_KEY, right_stick);
+ g_settings_set_enum (settings, PANEL_OBJECT_PACK_TYPE_KEY, pack_type);
+ g_settings_set_int (settings, PANEL_OBJECT_PACK_INDEX_KEY, pack_index);
/* Force writing the settings in order to reserve the object ID *now*,
* so that a later call to panel_profile_find_new_id() won't find the same
@@ -1282,15 +1284,17 @@ panel_profile_prepare_object_with_id (PanelObjectType object_type,
}
char *
-panel_profile_prepare_object (PanelObjectType object_type,
- PanelToplevel *toplevel,
- int position,
- gboolean right_stick)
+panel_profile_prepare_object (PanelObjectType object_type,
+ PanelToplevel *toplevel,
+ int position,
+ PanelObjectPackType pack_type,
+ int pack_index)
{
return panel_profile_prepare_object_with_id (object_type,
panel_profile_get_toplevel_id (toplevel),
position,
- right_stick);
+ pack_type,
+ pack_index);
}
void
@@ -1308,13 +1312,15 @@ panel_profile_delete_object (AppletInfo *applet_info)
static void
panel_profile_load_object (char *id)
{
- PanelObjectType object_type;
- char *object_path;
- char *toplevel_id;
- int position;
- gboolean right_stick;
- gboolean locked;
- GSettings *settings;
+ PanelObjectType object_type;
+ char *object_path;
+ char *toplevel_id;
+ int position;
+ PanelObjectPackType pack_type;
+ int pack_index;
+ gboolean right_stick;
+ gboolean locked;
+ GSettings *settings;
object_path = g_strdup_printf (PANEL_OBJECT_PATH "%s/", id);
settings = g_settings_new_with_path (PANEL_OBJECT_SCHEMA, object_path);
@@ -1322,14 +1328,23 @@ panel_profile_load_object (char *id)
object_type = g_settings_get_enum (settings, PANEL_OBJECT_TYPE_KEY);
position = g_settings_get_int (settings, PANEL_OBJECT_POSITION_KEY);
toplevel_id = g_settings_get_string (settings, PANEL_OBJECT_TOPLEVEL_ID_KEY);
+ pack_type = g_settings_get_enum (settings, PANEL_OBJECT_PACK_TYPE_KEY);
+ pack_index = g_settings_get_int (settings, PANEL_OBJECT_PACK_INDEX_KEY);
right_stick = g_settings_get_boolean (settings, PANEL_OBJECT_PANEL_RIGHT_STICK_KEY);
locked = g_settings_get_boolean (settings, PANEL_OBJECT_LOCKED_KEY);
+ /* If pack-type is still at the default value ('start') but right-stick
+ * is set, then map right-stick to PACK_END so the comparator sorts
+ * correctly. */
+ if (pack_type == PANEL_OBJECT_PACK_START && right_stick)
+ pack_type = PANEL_OBJECT_PACK_END;
+
mate_panel_applet_queue_applet_to_load (id,
object_type,
toplevel_id,
position,
- right_stick,
+ pack_type,
+ pack_index,
locked);
g_free (toplevel_id);
diff --git a/mate-panel/panel-profile.h b/mate-panel/panel-profile.h
index 36d4f217..152603e2 100644
--- a/mate-panel/panel-profile.h
+++ b/mate-panel/panel-profile.h
@@ -32,6 +32,7 @@
#include "panel-toplevel.h"
#include "panel-enums.h"
+#include "panel-enums-gsettings.h"
#include "panel-types.h"
#include "applet.h"
@@ -58,14 +59,16 @@ gboolean panel_profile_id_lists_are_writable (void);
void panel_profile_create_toplevel (GdkScreen *screen);
PanelToplevel *panel_profile_load_toplevel (const char *toplevel_id);
void panel_profile_delete_toplevel (PanelToplevel *toplevel);
-char *panel_profile_prepare_object (PanelObjectType object_type,
- PanelToplevel *toplevel,
- int position,
- gboolean right_stick);
-char *panel_profile_prepare_object_with_id (PanelObjectType object_type,
- const char *toplevel_id,
- int position,
- gboolean right_stick);
+char *panel_profile_prepare_object (PanelObjectType object_type,
+ PanelToplevel *toplevel,
+ int position,
+ PanelObjectPackType pack_type,
+ int pack_index);
+char *panel_profile_prepare_object_with_id (PanelObjectType object_type,
+ const char *toplevel_id,
+ int position,
+ PanelObjectPackType pack_type,
+ int pack_index);
void panel_profile_delete_object (AppletInfo *applet_info);
gboolean panel_profile_key_is_writable (PanelToplevel *toplevel,
diff --git a/mate-panel/panel-schemas.h b/mate-panel/panel-schemas.h
index 1b787288..6b22e2a7 100644
--- a/mate-panel/panel-schemas.h
+++ b/mate-panel/panel-schemas.h
@@ -45,6 +45,8 @@
#define PANEL_OBJECT_SCHEMA "org.mate.panel.object"
#define PANEL_OBJECT_TYPE_KEY "object-type"
#define PANEL_OBJECT_TOPLEVEL_ID_KEY "toplevel-id"
+#define PANEL_OBJECT_PACK_TYPE_KEY "pack-type"
+#define PANEL_OBJECT_PACK_INDEX_KEY "pack-index"
#define PANEL_OBJECT_POSITION_KEY "position"
#define PANEL_OBJECT_PANEL_RIGHT_STICK_KEY "panel-right-stick"
#define PANEL_OBJECT_LOCKED_KEY "locked"
diff --git a/mate-panel/panel-separator.c b/mate-panel/panel-separator.c
index 864d3107..5893ac32 100644
--- a/mate-panel/panel-separator.c
+++ b/mate-panel/panel-separator.c
@@ -232,6 +232,8 @@ void
panel_separator_load_from_gsettings (PanelWidget *panel,
gboolean locked,
int position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id)
{
PanelSeparator *separator;
@@ -241,7 +243,7 @@ panel_separator_load_from_gsettings (PanelWidget *panel,
separator->priv->info = mate_panel_applet_register (GTK_WIDGET (separator),
NULL, NULL,
panel, locked, position,
- TRUE,
+ pack_type, pack_index, TRUE,
PANEL_OBJECT_SEPARATOR,
id);
@@ -261,9 +263,15 @@ panel_separator_create (PanelToplevel *toplevel,
int position)
{
char *id;
+ PanelObjectPackType pack_type = PANEL_OBJECT_PACK_START;
+ int pack_index = 0;
+
+ panel_widget_get_insert_at_pos (panel_toplevel_get_panel_widget (toplevel),
+ &pack_type, &pack_index, position);
id = panel_profile_prepare_object (PANEL_OBJECT_SEPARATOR,
- toplevel, position, FALSE);
+ toplevel,
+ position, pack_type, pack_index);
panel_profile_add_to_list (PANEL_GSETTINGS_OBJECTS, id);
g_free (id);
}
diff --git a/mate-panel/panel-separator.h b/mate-panel/panel-separator.h
index d91cb1a9..fe6827e9 100644
--- a/mate-panel/panel-separator.h
+++ b/mate-panel/panel-separator.h
@@ -60,6 +60,8 @@ void panel_separator_create (PanelToplevel *toplevel,
void panel_separator_load_from_gsettings (PanelWidget *panel_widget,
gboolean locked,
gint position,
+ PanelObjectPackType pack_type,
+ int pack_index,
const char *id);
void panel_separator_set_orientation (PanelSeparator *separator,
PanelOrientation orientation);
diff --git a/mate-panel/panel-widget.c b/mate-panel/panel-widget.c
index 1ba1d586..6b52b99a 100644
--- a/mate-panel/panel-widget.c
+++ b/mate-panel/panel-widget.c
@@ -31,11 +31,8 @@
#include "panel-profile.h"
#include "panel-lockdown.h"
-#define MOVE_INCREMENT 1
-
typedef enum {
PANEL_SWITCH_MOVE = 0,
- PANEL_FREE_MOVE,
PANEL_PUSH_MOVE
} PanelMovementType;
@@ -49,7 +46,6 @@ enum {
APPLET_REMOVED_SIGNAL,
PUSH_MOVE_SIGNAL,
SWITCH_MOVE_SIGNAL,
- FREE_MOVE_SIGNAL,
TAB_MOVE_SIGNAL,
END_MOVE_SIGNAL,
POPUP_PANEL_MENU_SIGNAL,
@@ -86,27 +82,32 @@ static void panel_widget_push_move_applet (PanelWidget *panel,
GtkDirectionType dir);
static void panel_widget_switch_move_applet (PanelWidget *panel,
GtkDirectionType dir);
-static void panel_widget_free_move_applet (PanelWidget *panel,
- GtkDirectionType dir);
+static void panel_widget_update_positions (PanelWidget *panel);
static void panel_widget_tab_move (PanelWidget *panel,
gboolean next);
static void panel_widget_end_move (PanelWidget *panel);
static gboolean panel_widget_real_focus (GtkWidget *widget,
GtkDirectionType direction);
-static gboolean panel_widget_push_applet_right (PanelWidget *panel,
- GList *list,
- int push);
-static gboolean panel_widget_push_applet_left (PanelWidget *panel,
- GList *list,
- int push);
-
/************************
convenience functions
************************/
static int
applet_data_compare (AppletData *ad1, AppletData *ad2)
{
+ if (ad1->pack_type != ad2->pack_type)
+ return ad1->pack_type - ad2->pack_type; /* start < center < end */
+
+ /* Within the same pack zone, sort by pack_index. For END zone,
+ * higher index = leftmost (closer to center), so reverse. */
+ if (ad1->pack_index != ad2->pack_index) {
+ if (ad1->pack_type != PANEL_OBJECT_PACK_END)
+ return ad1->pack_index - ad2->pack_index;
+ else
+ return ad2->pack_index - ad1->pack_index;
+ }
+
+ /* Fallback to pixel position in case all pack_index are 0. */
return ad1->pos - ad2->pos;
}
@@ -170,8 +171,6 @@ add_all_move_bindings (PanelWidget *panel)
add_move_bindings (binding_set, GDK_SHIFT_MASK, "push_move");
add_move_bindings (binding_set, GDK_CONTROL_MASK, "switch_move");
- add_move_bindings (binding_set, GDK_MOD1_MASK, "free_move");
- add_move_bindings (binding_set, 0, "free_move");
add_tab_bindings (binding_set, 0, TRUE);
add_tab_bindings (binding_set, GDK_SHIFT_MASK, FALSE);
@@ -370,18 +369,6 @@ panel_widget_class_init (PanelWidgetClass *class)
1,
GTK_TYPE_DIRECTION_TYPE);
- panel_widget_signals[FREE_MOVE_SIGNAL] =
- g_signal_new ("free_move",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (PanelWidgetClass, free_move),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__ENUM,
- G_TYPE_NONE,
- 1,
- GTK_TYPE_DIRECTION_TYPE);
-
panel_widget_signals[TAB_MOVE_SIGNAL] =
g_signal_new ("tab_move",
G_TYPE_FROM_CLASS (class),
@@ -412,7 +399,6 @@ panel_widget_class_init (PanelWidgetClass *class)
class->applet_removed = NULL;
class->push_move = panel_widget_push_move_applet;
class->switch_move = panel_widget_switch_move_applet;
- class->free_move = panel_widget_free_move_applet;
class->tab_move = panel_widget_tab_move;
class->end_move = panel_widget_end_move;
@@ -550,7 +536,8 @@ panel_widget_cadd (GtkContainer *container,
g_return_if_fail (PANEL_IS_WIDGET (container));
g_return_if_fail (GTK_IS_WIDGET (widget));
- panel_widget_add (PANEL_WIDGET (container), widget, FALSE, 0, FALSE);
+ panel_widget_add (PANEL_WIDGET (container), widget, FALSE, 0,
+ PANEL_OBJECT_PACK_START, 0, FALSE);
p = g_object_get_data (G_OBJECT(widget),
MATE_PANEL_APPLET_ASSOC_PANEL_KEY);
@@ -595,6 +582,8 @@ panel_widget_cremove (GtkContainer *container, GtkWidget *widget)
if (ad)
panel->applet_list = g_list_remove (panel->applet_list, ad);
+ panel_widget_update_positions (panel);
+
g_signal_emit (G_OBJECT (container),
panel_widget_signals[APPLET_REMOVED_SIGNAL],
0, widget);
@@ -623,38 +612,6 @@ get_applet_list_pos (PanelWidget *panel,
return NULL;
}
-/*tells us if an applet is "stuck" on the right side*/
-int
-panel_widget_is_applet_stuck (PanelWidget *panel_widget,
- GtkWidget *widget)
-{
- AppletData *applet;
-
- g_return_val_if_fail (PANEL_IS_WIDGET (panel_widget), FALSE);
- g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
-
- applet = g_object_get_data (G_OBJECT (widget), MATE_PANEL_APPLET_DATA);
- if (applet) {
- GList *applet_list, *l;
- int end_pos = -1;
-
- applet_list = g_list_find (panel_widget->applet_list, applet);
-
- for (l = applet_list; l; l = l->next) {
- applet = l->data;
-
- if (end_pos != -1 && applet->pos != end_pos)
- break;
-
- end_pos = applet->pos + applet->cells;
- if (end_pos >= panel_widget->size)
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
static int
get_size_from_hints (AppletData *ad, int cells)
{
@@ -676,520 +633,697 @@ get_size_from_hints (AppletData *ad, int cells)
return MAX (cells, ad->min_cells);
}
-static void
-panel_widget_jump_applet_right (PanelWidget *panel,
- GList *list,
- GList *next,
- int pos)
+static inline int
+panel_widget_get_moveby (PanelWidget *panel,
+ AppletData *ad)
{
- AppletData *ad;
- const AppletData *nad = NULL;
-
- ad = list->data;
- if (next)
- nad = next->data;
-
- if (pos >= panel->size)
- return;
-
- if (!nad || nad->constrained >= pos + ad->min_cells)
- goto jump_right;
+ /* move relative to the center of the object */
+ return panel_widget_get_cursorloc (panel) - ad->constrained - ad->cells / 2;
+}
- if (!panel_widget_push_applet_right (panel, next, pos + ad->min_cells - nad->constrained)) {
- panel_widget_jump_applet_right (panel,
- list,
- next->next,
- nad->constrained + nad->min_cells);
- return;
+static int
+panel_widget_move_get_pos_pack (PanelWidget *panel,
+ PanelObjectPackType pack_type)
+{
+ switch (pack_type) {
+ case PANEL_OBJECT_PACK_START:
+ return 0;
+ break;
+ case PANEL_OBJECT_PACK_CENTER:
+ return panel->size / 2;
+ break;
+ case PANEL_OBJECT_PACK_END:
+ return panel->size;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
}
- jump_right:
- ad->pos = ad->constrained = pos;
- panel->applet_list = g_list_remove_link (panel->applet_list, list);
- panel->applet_list = panel_g_list_insert_before (panel->applet_list, next, list);
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
+ return 0;
}
-static void
-panel_widget_switch_applet_right (PanelWidget *panel,
- GList *list)
+static int
+panel_widget_move_get_pos_next_pack (PanelWidget *panel,
+ AppletData *ad,
+ AppletData *nad)
{
- AppletData *ad;
- AppletData *nad = NULL;
+ if (!nad || nad->pack_type > ad->pack_type + 1)
+ return panel_widget_move_get_pos_pack (panel, ad->pack_type + 1);
- g_assert (list != NULL);
+ return nad->constrained;
+}
- ad = list->data;
- if (ad->constrained + ad->min_cells >= panel->size)
- return;
+static int
+panel_widget_move_get_pos_prev_pack (PanelWidget *panel,
+ AppletData *ad,
+ AppletData *pad)
+{
+ if (!pad || pad->pack_type < ad->pack_type - 1)
+ return panel_widget_move_get_pos_pack (panel, ad->pack_type - 1);
- if (list->next)
- nad = list->next->data;
+ return pad->constrained + pad->cells;
+}
- if (!nad || nad->constrained >= ad->constrained + ad->min_cells + MOVE_INCREMENT) {
- ad->pos = ad->constrained += MOVE_INCREMENT;
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
- return;
- }
+static void
+panel_widget_move_to_pack (PanelWidget *panel,
+ AppletData *ad,
+ PanelObjectPackType new_pack_type,
+ int pack_index)
+{
+ GList *l;
- if (nad->locked) {
- panel_widget_jump_applet_right (panel,
- list,
- list->next->next,
- nad->constrained + nad->min_cells);
- return;
- }
+ if (pack_index >= 0) {
+ for (l = panel->applet_list; l; l = l->next) {
+ AppletData *ad_to_move = l->data;
+ if (ad_to_move->pack_type == new_pack_type &&
+ ad_to_move->pack_index >= pack_index) {
+ ad_to_move->pack_index++;
+ emit_applet_moved (panel, ad_to_move);
+ }
+ }
+ } else
+ pack_index = panel_widget_get_new_pack_index (panel, new_pack_type);
- nad->constrained = nad->pos = ad->constrained;
- ad->constrained = ad->pos = ad->constrained + nad->min_cells;
- panel->applet_list = panel_g_list_swap_next (panel->applet_list, list);
+ ad->pack_type = new_pack_type;
+ ad->pack_index = pack_index;
- gtk_widget_queue_resize (GTK_WIDGET (panel));
+ /* Reset pixel position so the backward-compat fallback in
+ * update_positions doesn't override the zone-computed position */
+ ad->pos = 0;
- emit_applet_moved (panel, ad);
- emit_applet_moved (panel, nad);
+ /* Re-sort the applet list since pack_type changed */
+ panel->applet_list =
+ panel_g_list_resort_item (panel->applet_list, ad,
+ (GCompareFunc)applet_data_compare);
}
-static void
-panel_widget_jump_applet_left (PanelWidget *panel,
- GList *list,
- GList *prev,
- int pos)
+/*
+ * Switch move
+ */
+
+/* if force_switch is set, moveby will be ignored */
+static gboolean
+panel_widget_switch_applet_right (PanelWidget *panel,
+ GList *list,
+ int moveby,
+ gboolean force_switch)
{
AppletData *ad;
- const AppletData *pad = NULL;
+ AppletData *nad;
+ int swap_index;
+ int next_pos;
ad = list->data;
- if (prev)
- pad = prev->data;
- if (pos < 0)
- return;
+ if (panel->packed && !list->next)
+ return FALSE;
- if (!pad || pad->constrained + pad->min_cells <= pos)
- goto jump_left;
+ if (ad->pack_type == PANEL_OBJECT_PACK_END && !list->next)
+ return FALSE;
- if (!panel_widget_push_applet_left (panel, prev, pad->constrained + pad->min_cells - pos)) {
- panel_widget_jump_applet_left (panel,
- list,
- prev->prev,
- pad->constrained - ad->min_cells);
- return;
- }
+ /* count moveby from end of object => remove distance to go there */
+ moveby -= ad->cells / 2;
- jump_left:
- ad->pos = ad->constrained = pos;
- panel->applet_list = g_list_remove_link (panel->applet_list, list);
- panel->applet_list = panel_g_list_insert_after (panel->applet_list, prev, list);
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
-}
+ nad = list->next ? list->next->data : NULL;
-static void
-panel_widget_switch_applet_left (PanelWidget *panel,
- GList *list)
-{
- AppletData *ad;
- AppletData *pad = NULL;
+ /* Move inside same pack */
+ if (nad && nad->pack_type == ad->pack_type) {
+ if (force_switch ||
+ (moveby >= nad->cells / 2)) {
+ swap_index = ad->pack_index;
+ ad->pack_index = nad->pack_index;
+ nad->pack_index = swap_index;
- ad = list->data;
- if (ad->constrained <= 0)
- return;
+ panel->applet_list = panel_g_list_swap_next (panel->applet_list, list);
- if (list->prev)
- pad = list->prev->data;
+ emit_applet_moved (panel, nad);
+ emit_applet_moved (panel, ad);
- if (!pad || pad->constrained + pad->min_cells <= ad->constrained - MOVE_INCREMENT) {
- ad->pos = ad->constrained -= MOVE_INCREMENT;
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
- return;
- }
+ panel_widget_update_positions (panel);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
- if (pad->locked) {
- panel_widget_jump_applet_left (panel,
- list,
- list->prev->prev,
- pad->constrained - ad->min_cells);
- return;
+ return TRUE;
+ } else
+ return FALSE;
}
- ad->constrained = ad->pos = pad->constrained;
- pad->constrained = pad->pos = ad->constrained + ad->min_cells;
- panel->applet_list = panel_g_list_swap_prev (panel->applet_list, list);
+ /* Move to next pack */
+ next_pos = panel_widget_move_get_pos_next_pack (panel, ad, nad);
+ if (force_switch ||
+ (moveby >= (next_pos - (ad->constrained + ad->cells)) / 2)) {
+ if (ad->pack_type + 1 == PANEL_OBJECT_PACK_END)
+ panel_widget_move_to_pack (panel, ad, ad->pack_type + 1, -1);
+ else
+ panel_widget_move_to_pack (panel, ad, ad->pack_type + 1, 0);
- gtk_widget_queue_resize (GTK_WIDGET (panel));
+ emit_applet_moved (panel, ad);
- emit_applet_moved (panel, ad);
- emit_applet_moved (panel, pad);
+ panel_widget_update_positions (panel);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
+ return TRUE;
+ }
+
+ return FALSE;
}
+/* if force_switch is set, moveby will be ignored */
static gboolean
-panel_widget_try_push_right (PanelWidget *panel,
- GList *list,
- int push)
+panel_widget_switch_applet_left (PanelWidget *panel,
+ GList *list,
+ int moveby,
+ gboolean force_switch)
{
AppletData *ad;
- const AppletData *nad = NULL;
-
- g_assert (list != NULL);
+ AppletData *pad;
+ int swap_index;
+ int prev_pos;
ad = list->data;
- if (list->next)
- nad = list->next->data;
- if (ad->locked)
+ if (panel->packed && !list->prev)
return FALSE;
- if (ad->constrained + ad->min_cells + push >= panel->size)
+ if (ad->pack_type == PANEL_OBJECT_PACK_START && !list->prev)
return FALSE;
- if (!nad || nad->constrained >= ad->constrained + ad->min_cells + push)
+ /* count moveby from start of object => add distance to go there */
+ moveby += ad->cells / 2;
+
+ pad = list->prev ? list->prev->data : NULL;
+
+ /* Move inside same pack */
+ if (pad && pad->pack_type == ad->pack_type) {
+ if (force_switch ||
+ (moveby <= - pad->cells / 2)) {
+ swap_index = ad->pack_index;
+ ad->pack_index = pad->pack_index;
+ pad->pack_index = swap_index;
+
+ panel->applet_list = panel_g_list_swap_prev (panel->applet_list, list);
+
+ emit_applet_moved (panel, ad);
+ emit_applet_moved (panel, pad);
+
+ panel_widget_update_positions (panel);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
+ return TRUE;
+ } else
+ return FALSE;
+ }
+
+ /* Move to prev pack */
+ prev_pos = panel_widget_move_get_pos_prev_pack (panel, ad, pad);
+ if (force_switch ||
+ (moveby <= - ((ad->constrained - prev_pos) / 2))) {
+ panel_widget_move_to_pack (panel, ad, ad->pack_type - 1, -1);
+ emit_applet_moved (panel, ad);
+
+ panel_widget_update_positions (panel);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
return TRUE;
+ }
- return panel_widget_try_push_right (panel, list->next, push);
+ return FALSE;
}
-static int
-panel_widget_get_right_jump_pos (PanelWidget *panel,
- AppletData *ad,
- GList *next,
- int pos)
+static void
+panel_widget_switch_move (PanelWidget *panel,
+ AppletData *ad)
{
- const AppletData *nad = NULL;
+ GList *list;
+ gboolean moved;
+ int moveby;
- if (next)
- nad = next->data;
+ g_return_if_fail (ad != NULL);
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
- if (!nad || nad->constrained >= pos + ad->min_cells)
- return pos;
+ list = g_list_find (panel->applet_list, ad);
+ g_return_if_fail (list != NULL);
- if (panel_widget_try_push_right (panel, next, pos + ad->min_cells - nad->constrained))
- return pos;
+ moveby = panel_widget_get_moveby (panel, ad);
- return panel_widget_get_right_jump_pos (panel,
- ad,
- next->next,
- nad->constrained + nad->min_cells);
+ if (moveby > ad->cells / 2) {
+ moved = TRUE;
+ while (moved && moveby > ad->cells / 2) {
+ moved = panel_widget_switch_applet_right (panel, list,
+ moveby, FALSE);
+ moveby = panel_widget_get_moveby (panel, ad);
+ }
+ } else {
+ moved = TRUE;
+ while (moved && moveby < - ad->cells / 2) {
+ moved = panel_widget_switch_applet_left (panel, list,
+ moveby, FALSE);
+ moveby = panel_widget_get_moveby (panel, ad);
+ }
+ }
}
static int
-panel_widget_get_right_switch_pos (PanelWidget *panel,
- GList *list)
+panel_widget_push_applet_right (PanelWidget *panel,
+ GList *list,
+ int moveby,
+ gboolean force_switch)
{
AppletData *ad;
- const AppletData *nad = NULL;
-
- g_assert (list != NULL);
+ AppletData *nad;
+ PanelObjectPackType new_pack_type;
+ GList *l;
+ GList *last_in_pack;
+ int next_pos;
ad = list->data;
- if (list->next)
- nad = list->next->data;
- if (!nad || nad->constrained >= ad->constrained + ad->min_cells + MOVE_INCREMENT)
- return ad->constrained + MOVE_INCREMENT;
+ if (ad->pack_type == PANEL_OBJECT_PACK_END)
+ return FALSE;
- if (nad->locked)
- return panel_widget_get_right_jump_pos (panel,
- ad,
- list->next->next,
- nad->constrained + nad->min_cells);
+ /* count moveby from end of object => remove distance to go there */
+ moveby -= ad->cells / 2;
- return nad->constrained + nad->min_cells - ad->cells;
-}
+ new_pack_type = ad->pack_type + 1;
-static gboolean
-panel_widget_try_push_left (PanelWidget *panel,
- GList *list,
- int push)
-{
- AppletData *ad;
- const AppletData *pad = NULL;
+ for (l = list; l && l->next; l = l->next) {
+ nad = l->next->data;
+ if (nad->pack_type != ad->pack_type)
+ break;
+ }
- g_assert (list != NULL);
+ last_in_pack = l;
- ad = list->data;
- if (list->prev)
- pad = list->prev->data;
+ nad = last_in_pack->next ? last_in_pack->next->data : NULL;
+ next_pos = panel_widget_move_get_pos_next_pack (panel, ad, nad);
- if (ad->locked)
+ if (!force_switch &&
+ (moveby < (next_pos - (ad->constrained + ad->cells)) / 2))
return FALSE;
- if (ad->constrained - push < 0)
- return FALSE;
+ for (l = last_in_pack; l; l = l->prev) {
+ ad = l->data;
- if (!pad || pad->constrained + pad->min_cells <= ad->constrained - push)
- return TRUE;
+ if (new_pack_type == PANEL_OBJECT_PACK_END)
+ panel_widget_move_to_pack (panel, ad, new_pack_type, -1);
+ else
+ panel_widget_move_to_pack (panel, ad, new_pack_type, 0);
+
+ emit_applet_moved (panel, ad);
+
+ if (l == list)
+ break;
+ }
- return panel_widget_try_push_left (panel, list->prev, push);
+ panel_widget_update_positions (panel);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
+ return TRUE;
}
static int
-panel_widget_get_left_jump_pos (PanelWidget *panel,
- AppletData *ad,
- GList *prev,
- int pos)
+panel_widget_push_applet_left (PanelWidget *panel,
+ GList *list,
+ int moveby,
+ gboolean force_switch)
{
- const AppletData *pad = NULL;
+ AppletData *ad;
+ AppletData *pad;
+ PanelObjectPackType new_pack_type;
+ GList *l;
+ GList *first_in_pack;
+ int prev_pos;
- if (prev)
- pad = prev->data;
+ ad = list->data;
- if (!pad || pad->constrained + pad->min_cells <= pos)
- return pos;
+ if (ad->pack_type == PANEL_OBJECT_PACK_START)
+ return FALSE;
- if (panel_widget_try_push_left (panel, prev, pad->constrained + pad->min_cells - pos))
- return pos;
+ /* count moveby from start of object => add distance to go there */
+ moveby += ad->cells / 2;
- return panel_widget_get_left_jump_pos (panel,
- ad,
- prev->prev,
- pad->constrained - ad->min_cells);
-}
+ new_pack_type = ad->pack_type - 1;
-static int
-panel_widget_get_left_switch_pos (PanelWidget *panel,
- GList *list)
-{
- AppletData *ad;
- const AppletData *pad = NULL;
+ for (l = list; l && l->prev; l = l->prev) {
+ pad = l->prev->data;
+ if (pad->pack_type != ad->pack_type)
+ break;
+ }
- g_assert (list != NULL);
+ first_in_pack = l;
- ad = list->data;
- if (list->prev)
- pad = list->prev->data;
+ pad = first_in_pack->prev ? first_in_pack->prev->data : NULL;
+ prev_pos = panel_widget_move_get_pos_prev_pack (panel, ad, pad);
- if (!pad || pad->constrained + pad->min_cells <= ad->constrained - MOVE_INCREMENT)
- return ad->constrained - MOVE_INCREMENT;
+ if (!force_switch &&
+ (moveby > - ((ad->constrained - prev_pos) / 2)))
+ return FALSE;
- if (pad->locked)
- return panel_widget_get_left_jump_pos (panel,
- ad,
- list->prev->prev,
- pad->constrained - ad->min_cells);
+ for (l = first_in_pack; l; l = l->next) {
+ ad = l->data;
- return pad->constrained;
+ panel_widget_move_to_pack (panel, ad, new_pack_type, -1);
+ emit_applet_moved (panel, ad);
+
+ if (l == list)
+ break;
+ }
+
+ panel_widget_update_positions (panel);
+ gtk_widget_queue_resize (GTK_WIDGET (panel));
+
+ return TRUE;
}
static void
-panel_widget_switch_move (PanelWidget *panel,
- AppletData *ad,
- int moveby)
+panel_widget_push_move (PanelWidget *panel,
+ AppletData *ad,
+ int direction)
{
GList *list;
- int finalpos;
- int pos;
+ gboolean moved;
+ int moveby;
+
+ /* direction is only used when we move with keybindings */
g_return_if_fail (ad != NULL);
g_return_if_fail (PANEL_IS_WIDGET (panel));
- if (moveby == 0)
- return;
-
list = g_list_find (panel->applet_list, ad);
g_return_if_fail (list != NULL);
- finalpos = ad->constrained + moveby;
+ moveby = panel_widget_get_moveby (panel, ad);
- if (ad->constrained < finalpos) {
- const AppletData *pad;
+ if (direction > 0 || moveby > ad->cells / 2) {
+ moved = TRUE;
+ while (direction > 0 ||
+ (moved && moveby > ad->cells / 2)) {
+ moved = panel_widget_push_applet_right (panel, list,
+ moveby,
+ direction != 0);
+ moveby = panel_widget_get_moveby (panel, ad);
- if (list->prev) {
- pad = list->prev->data;
- if (pad->expand_major)
- gtk_widget_queue_resize (GTK_WIDGET (panel));
+ /* a keybinding pushes only once */
+ if (direction != 0)
+ break;
}
-
- while (ad->constrained < finalpos) {
- pos = panel_widget_get_right_switch_pos (panel, list);
-
- if (abs (pos - finalpos) >= abs (ad->constrained - finalpos) ||
- pos + ad->min_cells > panel->size)
+ } else {
+ moved = TRUE;
+ while (direction < 0 ||
+ (moved && moveby < ad->cells / 2)) {
+ moved = panel_widget_push_applet_left (panel, list,
+ moveby,
+ direction != 0);
+ moveby = panel_widget_get_moveby (panel, ad);
+
+ /* a keybinding pushes only once */
+ if (direction != 0)
break;
-
- panel_widget_switch_applet_right (panel, list);
}
+ }
+}
- if (list->prev) {
- pad = list->prev->data;
- if (pad->expand_major)
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- }
- } else {
+/* data should be freed with g_list_free() */
+static GList *
+get_applet_list_pack (PanelWidget *panel,
+ PanelObjectPackType pack_type)
+{
+ GList *ret;
+ GList *l;
+ GList *prev;
- if (list->next) {
- const AppletData *nad = list->next->data;
- if (nad->expand_major)
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- }
+ g_return_val_if_fail (PANEL_IS_WIDGET (panel), NULL);
- while (ad->constrained > finalpos) {
- pos = panel_widget_get_left_switch_pos (panel, list);
+ for (l = panel->applet_list; l; l = l->next) {
+ AppletData *ad = l->data;
- if (abs (pos - finalpos) >= abs (ad->constrained - finalpos) || pos < 0)
- break;
+ if (ad->pack_type == pack_type)
+ break;
+ }
- panel_widget_switch_applet_left (panel, list);
- }
+ if (!l)
+ return NULL;
+ ret = g_list_copy (l);
+ for (l = ret; l; l = l->next) {
+ AppletData *ad = l->data;
+ if (ad->pack_type != pack_type)
+ break;
}
+
+ if (!l)
+ return ret;
+
+ prev = l->prev;
+ if (prev)
+ prev->next = NULL;
+ g_list_free (l);
+
+ return ret;
}
-static int
-panel_widget_push_applet_right (PanelWidget *panel,
- GList *list,
- int push)
+/* get pack type & index for insertion at a given position in panel */
+void
+panel_widget_get_insert_at_pos (PanelWidget *panel,
+ PanelObjectPackType *pack_type,
+ int *pack_index,
+ int pos)
{
+ GList *l;
AppletData *ad;
- const AppletData *nad = NULL;
- g_assert (list != NULL);
-
- ad = list->data;
- if (ad->constrained + ad->min_cells + push >= panel->size)
- return FALSE;
-
- if (ad->locked)
- return FALSE;
+ g_return_if_fail (PANEL_IS_WIDGET (panel));
- if (list->next)
- nad = list->next->data;
+ /* check if pos is in an object; in this case, return the pack type
+ * of the object */
+ for (l = panel->applet_list; l; l = l->next) {
+ ad = l->data;
- if (!nad || nad->constrained >= ad->constrained + ad->min_cells + push) {
- ad->pos = ad->constrained += push;
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
- return TRUE;
+ if (ad->constrained <= pos) {
+ if (ad->constrained + ad->cells > pos) {
+ *pack_type = ad->pack_type;
+ *pack_index = ad->pack_index;
+ return;
+ }
+ } else
+ break;
}
- g_assert (list->next != NULL);
+ if (pos <= panel->size / 2)
+ *pack_type = PANEL_OBJECT_PACK_START;
+ else
+ *pack_type = PANEL_OBJECT_PACK_END;
- if (!panel_widget_push_applet_right (panel, list->next, push))
- return FALSE;
+ *pack_index = panel_widget_get_new_pack_index (panel, *pack_type);
+}
- ad->pos = ad->constrained += push;;
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
+/* get index for insertion with pack type */
+int
+panel_widget_get_new_pack_index (PanelWidget *panel,
+ PanelObjectPackType pack_type)
+{
+ GList *l;
+ AppletData *ad;
+ int max_pack_index = -1;
- return TRUE;
+ for (l = panel->applet_list; l; l = l->next) {
+ ad = l->data;
+ if (ad->pack_type == pack_type)
+ max_pack_index = MAX (max_pack_index, ad->pack_index);
+ }
+
+ return max_pack_index + 1;
}
-static int
-panel_widget_push_applet_left (PanelWidget *panel,
- GList *list,
- int push)
+/* Note: this can only be called at the beginning of size_allocate, which means
+ * that ad->constrained doesn't matter yet (it will be set to the correct
+ * value in size_allocate). */
+static void
+panel_widget_update_positions_packed_start (PanelWidget *panel)
{
+ GList *list,*l;
AppletData *ad;
- const AppletData *pad = NULL;
+ int size_all = 0;
+ int pos_next;
- g_assert (list != NULL);
+ if (panel->packed)
+ return;
- ad = list->data;
- if (ad->constrained - push < 0)
- return FALSE;
+ list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_START);
- if (ad->locked)
- return FALSE;
+ /* get size used by the objects */
+ for (l = list; l; l = l->next) {
+ ad = l->data;
+ size_all += ad->cells;
+ }
- if (list->prev)
- pad = list->prev->data;
+ /* update absolute position of all applets based on this information,
+ * starting with the first object */
+ pos_next = 0;
+ l = list;
- if (!pad || pad->constrained + pad->min_cells <= ad->constrained - push) {
- ad->pos = ad->constrained -= push;
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
- return TRUE;
+ while (l) {
+ ad = l->data;
+ ad->constrained = pos_next;
+ pos_next += ad->cells;
+ l = l->next;
}
- g_assert (list->prev != NULL);
+ g_list_free (list);
+}
- if (!panel_widget_push_applet_left (panel, list->prev, push))
- return FALSE;
+/* Note: only use this function when you can; see comment above
+ * panel_widget_update_positions_packed_start()
+ * For center specifically, we require ad->cells to be set. Note that we don't
+ * care much about min_cells: if we need it, this means objects will have to be
+ * pushed to accomodate other objects, which will kill centering anyway.
+ * (FIXME: hrm, not that sure about it ;-)) */
+static void
+panel_widget_update_positions_packed_center (PanelWidget *panel)
+{
+ GList *list,*l;
+ AppletData *ad;
+ int size_all = 0;
+ int pos_next;
- ad->pos = ad->constrained -= push;
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- emit_applet_moved (panel, ad);
+ if (panel->packed)
+ return;
- return TRUE;
+ list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_CENTER);
+
+ /* get size used by the objects */
+ for (l = list; l; l = l->next) {
+ ad = l->data;
+ size_all += ad->cells;
+ }
+
+ /* update absolute position of all applets based on this information,
+ * starting with the first centered object */
+ pos_next = (panel->size - size_all) / 2;
+ l = list;
+
+ while (l) {
+ ad = l->data;
+ ad->constrained = pos_next;
+ pos_next += ad->cells;
+ l = l->next;
+ }
+
+ g_list_free (list);
}
+/* Note: only use this function when you can; see comment above
+ * panel_widget_update_positions_packed_start() */
static void
-panel_widget_push_move (PanelWidget *panel,
- AppletData *ad,
- int moveby)
+panel_widget_update_positions_packed_end (PanelWidget *panel)
{
- int finalpos;
- GList *list;
-
- g_return_if_fail (ad != NULL);
- g_return_if_fail (PANEL_IS_WIDGET (panel));
+ GList *list,*l;
+ AppletData *ad;
+ int size_all = 0;
+ int pos_next;
- if (moveby == 0)
+ if (panel->packed)
return;
- list = g_list_find (panel->applet_list, ad);
- g_return_if_fail (list != NULL);
+ list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_END);
- finalpos = ad->constrained + moveby;
+ /* get size used by the objects */
+ for (l = list; l; l = l->next) {
+ ad = l->data;
+ size_all += ad->cells;
+ }
- if (ad->constrained < finalpos) {
- while (ad->constrained < finalpos)
- if (!panel_widget_push_applet_right (panel, list, 1))
- break;
+ /* update absolute position of all applets based on this information,
+ * starting with the first object */
+ pos_next = panel->size - size_all;
+ l = list;
- if (list->prev) {
- const AppletData *pad = list->prev->data;
- if (pad->expand_major)
- gtk_widget_queue_resize (GTK_WIDGET (panel));
- }
- } else {
- while (ad->constrained > finalpos)
- if (!panel_widget_push_applet_left (panel, list, 1))
- break;
+ while (l) {
+ ad = l->data;
+ ad->constrained = pos_next;
+ pos_next += ad->cells;
+ l = l->next;
}
+
+ g_list_free (list);
}
-/*this is a special function and may fail if called improperly, it works
-only under special circumstance when we know there is nothing from
-old_size to panel->size*/
static void
-panel_widget_right_stick(PanelWidget *panel,int old_size)
+panel_widget_update_positions (PanelWidget *panel)
{
- int i,pos;
- GList *list,*prev;
+ int i = 0;
+ GList *list;
AppletData *ad;
- g_return_if_fail(PANEL_IS_WIDGET(panel));
- g_return_if_fail(old_size>=0);
+ i = 0;
- if(old_size>=panel->size ||
- panel->packed)
- return;
+ if (panel->packed) {
+ /* keep in sync with code in size_allocate */
+ for (list = panel->applet_list;
+ list != NULL;
+ list = g_list_next (list)) {
+ ad = list->data;
+ ad->constrained = i;
+ i += ad->cells;
+ }
+ } else {
+ /* Re-compute the ideal position of objects, based on their size */
+ panel_widget_update_positions_packed_start (panel);
+ panel_widget_update_positions_packed_center (panel);
+ panel_widget_update_positions_packed_end (panel);
+
+ /* Second pass: try to position from the start, to make sure
+ * there's enough room. Also respect ad->pos for backward
+ * compat with configs not yet migrated to pack-type/pack-index
+ * (except for CENTER applets, which should stay centered). */
+ for (list = panel->applet_list;
+ list != NULL;
+ list = g_list_next (list)) {
+ ad = list->data;
- list = get_applet_list_pos(panel,old_size-1);
+ /* Use the larger of zone position and old pixel
+ * position, so pre-migration gaps are preserved. */
+ if (ad->pack_type != PANEL_OBJECT_PACK_CENTER && ad->pos > ad->constrained)
+ ad->constrained = ad->pos;
+ if (ad->constrained < i)
+ ad->constrained = i;
- if(!list)
- return;
+ i = ad->constrained + ad->cells;
+ }
- pos = panel->size-1;
+ /* Third pass: try to push applets to the left to see if
+ * there is enough room. */
+ if (i > panel->size) {
+ i = panel->size;
+ for (list = g_list_last (panel->applet_list);
+ list != NULL;
+ list = g_list_previous (list)) {
+ ad = list->data;
- ad = list->data;
- do {
- i = ad->pos;
- ad->pos = ad->constrained = pos--;
- ad->cells = 1;
- prev = list;
- list = g_list_previous(list);
- if(!list)
- break;
- ad = list->data;
- } while(ad->pos + ad->cells == i);
+ if (ad->constrained + ad->cells > i)
+ ad->constrained = MAX (i - ad->cells, 0);
+
+ i = ad->constrained;
+ }
+ }
+
+ /* EEEEK, there's not enough room, so shift applets even
+ * at the expense of perhaps running out of room on the
+ * right if there is no free space in the middle */
+ if (i < 0) {
+ i = 0;
+ for (list = panel->applet_list;
+ list != NULL;
+ list = g_list_next (list)) {
+ ad = list->data;
- for (list = prev; list; list = list->next)
- emit_applet_moved (panel, list->data);
+ if (ad->constrained < i)
+ ad->constrained = i;
+
+ i = ad->constrained + ad->cells;
+ }
+ }
+ }
}
static void
@@ -1361,7 +1495,6 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
PanelWidget *panel;
GList *list;
int i;
- int old_size;
gboolean ltr;
g_return_if_fail(PANEL_IS_WIDGET(widget));
@@ -1369,7 +1502,6 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
panel = PANEL_WIDGET(widget);
- old_size = panel->size;
ltr = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR;
gtk_widget_set_allocation (widget, allocation);
@@ -1384,8 +1516,6 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
panel->size = allocation->width;
else
panel->size = allocation->height;
- if(old_size<panel->size)
- panel_widget_right_stick(panel,old_size);
if (panel->packed) {
/* we're assuming the order is the same as the one that was
@@ -1442,8 +1572,7 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
} else { /*not packed*/
- /* First make sure there's enough room on the left */
- i = 0;
+ /* First pass: set ad->cells from applet sizes */
for (list = panel->applet_list;
list != NULL;
list = g_list_next (list)) {
@@ -1462,23 +1591,24 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
ad->cells = ad->size_hints [ad->size_hints_len - 1];
ad->min_cells = ad->size_hints [ad->size_hints_len - 1];
}
-
- ad->constrained = ad->pos;
- if (ad->constrained < i)
- ad->constrained = i;
-
- i = ad->constrained + ad->cells;
}
- /* Now expand from the right */
+ /* Compute zone-based positions and resolve collisions */
+ panel_widget_update_positions (panel);
+
+ /* Now expand from the right, using size hints.
+ * But don't push CENTER applets since they should stay centered
+ * as computed by update_positions. */
i = panel->size;
for(list = g_list_last(panel->applet_list);
list!=NULL;
list = g_list_previous(list)) {
AppletData *ad = list->data;
- if (ad->constrained + ad->min_cells > i)
- ad->constrained = MAX (i - ad->min_cells, 0);
+ if (ad->pack_type != PANEL_OBJECT_PACK_CENTER) {
+ if (ad->constrained + ad->min_cells > i)
+ ad->constrained = MAX (i - ad->min_cells, 0);
+ }
if (ad->expand_major) {
int cells = (i - ad->constrained) - 1;
@@ -1494,23 +1624,6 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
i = ad->constrained;
}
- /* EEEEK, there's not enough room, so shift applets even
- * at the expense of perhaps running out of room on the
- * right if there is no free space in the middle */
- if(i < 0) {
- i = 0;
- for(list = panel->applet_list;
- list!=NULL;
- list = g_list_next(list)) {
- AppletData *ad = list->data;
-
- if (ad->constrained < i)
- ad->constrained = i;
-
- i = ad->constrained + ad->cells;
- }
- }
-
for(list = panel->applet_list;
list!=NULL;
list = g_list_next(list)) {
@@ -1750,6 +1863,43 @@ panel_widget_applet_drag_start_no_grab (PanelWidget *panel,
}
static void
+panel_widget_compress_pack_indexes_list (PanelWidget *panel,
+ GList *list)
+{
+ GList *l;
+ AppletData *ad;
+ int index;
+
+ for (l = list, index = 0; l; l = l->next, index++) {
+ ad = l->data;
+ if (ad->pack_index != index) {
+ ad->pack_index = index;
+ emit_applet_moved (panel, ad);
+ }
+ }
+}
+
+/* make sure our lists always start at 0 */
+static void
+panel_widget_compress_pack_indexes (PanelWidget *panel)
+{
+ GList *list;
+
+ list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_START);
+ panel_widget_compress_pack_indexes_list (panel, list);
+ g_list_free (list);
+
+ list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_CENTER);
+ panel_widget_compress_pack_indexes_list (panel, list);
+ g_list_free (list);
+
+ list = get_applet_list_pack (panel, PANEL_OBJECT_PACK_END);
+ list = g_list_reverse (list);
+ panel_widget_compress_pack_indexes_list (panel, list);
+ g_list_free (list);
+}
+
+static void
panel_widget_applet_drag_end_no_grab (PanelWidget *panel)
{
g_return_if_fail (panel != NULL);
@@ -1767,6 +1917,15 @@ panel_widget_applet_drag_end_no_grab (PanelWidget *panel)
moving_timeout = 0;
been_moved = FALSE;
}
+
+ /* Make sure we keep our indexes in a 0:n range, instead of a x:x+n
+ * range, with a growing x. Note that this is useful not only because
+ * of moves, but also because of removal of objects (object 0 could be
+ * removed, but if there is still object 1, we start growing the
+ * range). But doing this compress only once in a while, after moving
+ * objects is good enough, since this is nothing urgent and the user
+ * will move objects before this becomes a real annoying issue. */
+ panel_widget_compress_pack_indexes (panel);
}
void
@@ -1861,15 +2020,6 @@ panel_widget_get_cursorloc (PanelWidget *panel)
return y;
}
-/*calculates the value to move the applet by*/
-static int
-panel_widget_get_moveby (PanelWidget *panel, int pos, int offset)
-{
- g_return_val_if_fail (PANEL_IS_WIDGET (panel), -1);
-
- return panel_widget_get_cursorloc (panel) - offset - pos;
-}
-
static GList *
walk_up_to (int pos, GList *list)
{
@@ -1985,29 +2135,6 @@ panel_widget_get_free_spot (PanelWidget *panel,
}
}
-static void
-panel_widget_nice_move (PanelWidget *panel,
- AppletData *ad,
- int pos)
-{
- g_return_if_fail (PANEL_IS_WIDGET (panel));
- g_return_if_fail (ad != NULL);
-
- pos = panel_widget_get_free_spot (panel, ad, pos);
- if (pos < 0 || pos == ad->pos)
- return;
-
- ad->pos = ad->constrained = pos;
-
- panel->applet_list =
- panel_g_list_resort_item (panel->applet_list, ad,
- (GCompareFunc)applet_data_compare);
-
- gtk_widget_queue_resize (GTK_WIDGET (panel));
-
- emit_applet_moved (panel, ad);
-}
-
/* schedule to run the below function */
static void schedule_try_move (PanelWidget *panel, gboolean repeater);
@@ -2015,8 +2142,6 @@ static void schedule_try_move (PanelWidget *panel, gboolean repeater);
static void
panel_widget_applet_move_to_cursor (PanelWidget *panel)
{
- int moveby;
- int pos;
int movement;
GtkWidget *applet;
GdkDevice *device;
@@ -2031,8 +2156,6 @@ panel_widget_applet_move_to_cursor (PanelWidget *panel)
ad = panel->currently_dragged_applet;
- pos = ad->constrained;
-
applet = ad->applet;
g_assert(GTK_IS_WIDGET(applet));
forb = g_object_get_data (G_OBJECT(applet),
@@ -2053,8 +2176,9 @@ panel_widget_applet_move_to_cursor (PanelWidget *panel)
panel_screen_from_panel_widget (new_panel) &&
!g_slist_find (forb, new_panel) &&
!panel_lockdown_get_locked_down ()) {
- pos = panel_widget_get_moveby (new_panel, 0, ad->drag_off);
+ int pos;
+ pos = panel_widget_get_cursorloc (new_panel);
if (pos < 0) pos = 0;
panel_widget_applet_drag_end (panel);
@@ -2062,12 +2186,12 @@ panel_widget_applet_move_to_cursor (PanelWidget *panel)
/*disable reentrancy into this function*/
if (!panel_widget_reparent (panel, new_panel, applet, pos)) {
panel_widget_applet_drag_start (
- panel, applet, ad->drag_off, GDK_CURRENT_TIME);
+ panel, applet, PW_DRAG_OFF_CENTER, GDK_CURRENT_TIME);
continue;
}
panel_widget_applet_drag_start (
- new_panel, applet, ad->drag_off, GDK_CURRENT_TIME);
+ new_panel, applet, PW_DRAG_OFF_CENTER, GDK_CURRENT_TIME);
schedule_try_move (new_panel, TRUE);
return;
@@ -2087,21 +2211,14 @@ panel_widget_applet_move_to_cursor (PanelWidget *panel)
movement = PANEL_SWITCH_MOVE;
else if (mods & GDK_SHIFT_MASK)
movement = PANEL_PUSH_MOVE;
- else if (mods & GDK_MOD1_MASK)
- movement = PANEL_FREE_MOVE;
}
switch (movement) {
case PANEL_SWITCH_MOVE:
- moveby = panel_widget_get_moveby (panel, pos, ad->drag_off);
- panel_widget_switch_move (panel, ad, moveby);
- break;
- case PANEL_FREE_MOVE:
- panel_widget_nice_move (panel, ad, panel_widget_get_cursorloc (panel));
+ panel_widget_switch_move (panel, ad);
break;
case PANEL_PUSH_MOVE:
- moveby = panel_widget_get_moveby (panel, pos, ad->drag_off);
- panel_widget_push_move (panel, ad, moveby);
+ panel_widget_push_move (panel, ad, 0);
break;
}
}
@@ -2443,17 +2560,26 @@ panel_widget_add_forbidden (PanelWidget *panel)
}
int
-panel_widget_add (PanelWidget *panel,
- GtkWidget *applet,
- gboolean locked,
- int pos,
- gboolean insert_at_pos)
+panel_widget_add (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean locked,
+ int pos,
+ PanelObjectPackType pack_type,
+ int pack_index,
+ gboolean insert_at_pos)
{
AppletData *ad = NULL;
g_return_val_if_fail (PANEL_IS_WIDGET (panel), -1);
g_return_val_if_fail (GTK_IS_WIDGET (applet), -1);
+ if (pack_type == PANEL_OBJECT_PACK_END) {
+ if (!panel->packed)
+ pos = panel->size - pos;
+ else
+ pos = -1;
+ }
+
ad = g_object_get_data (G_OBJECT (applet), MATE_PANEL_APPLET_DATA);
if (ad != NULL)
@@ -2483,6 +2609,8 @@ panel_widget_add (PanelWidget *panel,
if (ad == NULL) {
ad = g_new (AppletData, 1);
ad->applet = applet;
+ ad->pack_type = pack_type;
+ ad->pack_index = pack_index;
ad->cells = 1;
ad->min_cells = 1;
ad->pos = pos;
@@ -2640,7 +2768,7 @@ panel_widget_push_move_applet (PanelWidget *panel,
GtkDirectionType dir)
{
AppletData *applet;
- int increment = 0;
+ int direction = 0;
applet = panel->currently_dragged_applet;
g_return_if_fail (applet);
@@ -2648,17 +2776,17 @@ panel_widget_push_move_applet (PanelWidget *panel,
switch (dir) {
case GTK_DIR_LEFT:
case GTK_DIR_UP:
- increment = -MOVE_INCREMENT;
+ direction = -1;
break;
case GTK_DIR_RIGHT:
case GTK_DIR_DOWN:
- increment = MOVE_INCREMENT;
+ direction = 1;
break;
default:
return;
}
- panel_widget_push_move (panel, applet, increment);
+ panel_widget_push_move (panel, applet, direction);
}
static void
@@ -2677,41 +2805,15 @@ panel_widget_switch_move_applet (PanelWidget *panel,
switch (dir) {
case GTK_DIR_LEFT:
case GTK_DIR_UP:
- panel_widget_switch_applet_left (panel, list);
- break;
- case GTK_DIR_RIGHT:
- case GTK_DIR_DOWN:
- panel_widget_switch_applet_right (panel, list);
- break;
- default:
- return;
- }
-}
-
-static void
-panel_widget_free_move_applet (PanelWidget *panel,
- GtkDirectionType dir)
-{
- AppletData *ad;
- gint increment = MOVE_INCREMENT;
-
- ad = panel->currently_dragged_applet;
-
- g_return_if_fail (ad);
-
- switch (dir) {
- case GTK_DIR_LEFT:
- case GTK_DIR_UP:
- increment = -increment;
+ panel_widget_switch_applet_left (panel, list, -1, TRUE);
break;
case GTK_DIR_RIGHT:
case GTK_DIR_DOWN:
+ panel_widget_switch_applet_right (panel, list, -1, TRUE);
break;
default:
return;
}
-
- panel_widget_nice_move (panel, ad, increment + ad->constrained + ad->drag_off);
}
static void
diff --git a/mate-panel/panel-widget.h b/mate-panel/panel-widget.h
index e5dc3da8..1e27daee 100644
--- a/mate-panel/panel-widget.h
+++ b/mate-panel/panel-widget.h
@@ -14,6 +14,7 @@
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "button-widget.h"
+#include "panel-enums-gsettings.h"
#include "panel-types.h"
#include "panel-background.h"
#include "panel-toplevel.h"
@@ -64,6 +65,8 @@ struct _AppletSizeHintsAlloc {
struct _AppletData
{
GtkWidget * applet;
+ PanelObjectPackType pack_type;
+ int pack_index;
int pos;
int constrained;
int cells;
@@ -135,8 +138,6 @@ struct _PanelWidgetClass
GtkDirectionType dir);
void (* switch_move) (PanelWidget *panel,
GtkDirectionType dir);
- void (* free_move) (PanelWidget *panel,
- GtkDirectionType dir);
void (* tab_move) (PanelWidget *panel,
gboolean next);
void (* end_move) (PanelWidget *panel);
@@ -150,11 +151,13 @@ GtkWidget * panel_widget_new (PanelToplevel *toplevel,
int sz);
/*add an applet to the panel, preferably at position pos, if insert_at_pos
is on, we REALLY want to insert at the pos given by pos*/
-int panel_widget_add (PanelWidget *panel,
- GtkWidget *applet,
- gboolean locked,
- int pos,
- gboolean insert_at_pos);
+int panel_widget_add (PanelWidget *panel,
+ GtkWidget *applet,
+ gboolean locked,
+ int pos,
+ PanelObjectPackType pack_type,
+ int pack_index,
+ gboolean insert_at_pos);
/*needs to be called for drawers after add*/
void panel_widget_add_forbidden (PanelWidget *panel);
@@ -191,9 +194,6 @@ void panel_widget_draw_all (PanelWidget *panel,
void panel_widget_draw_icon (PanelWidget *panel,
ButtonWidget *applet);
-/*tells us if an applet is "stuck" on the right side*/
-int panel_widget_is_applet_stuck (PanelWidget *panel,
- GtkWidget *applet);
/*get pos of the cursor location in panel coordinates*/
int panel_widget_get_cursorloc (PanelWidget *panel);
@@ -205,6 +205,13 @@ void panel_widget_focus (PanelWidget *panel);
PanelOrientation panel_widget_get_applet_orientation (PanelWidget *panel);
+void panel_widget_get_insert_at_pos (PanelWidget *panel,
+ PanelObjectPackType *pack_type,
+ int *pack_index,
+ int pos);
+int panel_widget_get_new_pack_index (PanelWidget *panel,
+ PanelObjectPackType pack_type);
+
void panel_widget_emit_background_changed (PanelWidget *panel);
void panel_widget_set_applet_size_constrained (PanelWidget *panel,
diff --git a/mate-panel/panel.c b/mate-panel/panel.c
index 065d2090..b720aeb6 100644
--- a/mate-panel/panel.c
+++ b/mate-panel/panel.c
@@ -1401,26 +1401,6 @@ panel_screen_from_panel_widget (PanelWidget *panel)
return gtk_window_get_screen (GTK_WINDOW (panel->toplevel));
}
-gboolean
-panel_is_applet_right_stick (GtkWidget *applet)
-{
- GtkWidget *parent;
- PanelWidget *panel_widget;
-
- g_return_val_if_fail (GTK_IS_WIDGET (applet), FALSE);
-
- parent = gtk_widget_get_parent (applet);
-
- g_return_val_if_fail (PANEL_IS_WIDGET (parent), FALSE);
-
- panel_widget = PANEL_WIDGET (parent);
-
- if (!panel_toplevel_get_expand (panel_widget->toplevel))
- return FALSE;
-
- return panel_widget_is_applet_stuck (panel_widget, applet);
-}
-
static void
panel_delete_without_query (PanelToplevel *toplevel)
{
diff --git a/mate-panel/panel.h b/mate-panel/panel.h
index bf1517ec..aafddb4a 100644
--- a/mate-panel/panel.h
+++ b/mate-panel/panel.h
@@ -26,7 +26,7 @@ PanelData *panel_setup (PanelToplevel *toplevel);
GdkScreen *panel_screen_from_panel_widget (PanelWidget *panel);
-gboolean panel_is_applet_right_stick (GtkWidget *applet);
+
gboolean panel_check_dnd_target_data (GtkWidget *widget,
GdkDragContext *context,
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000..64c09ab7
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,325 @@
+project(
+ 'mate-panel',
+ 'c',
+ version: '1.29.0',
+ meson_version: '>= 0.56.0',
+ license: ['GPL-2', 'LGPL-2', 'FDL-1.1'],
+)
+
+# Before making a release, the LT_VERSION string should be modified.
+# The string is of the form C:R:A.
+# - If interfaces have been changed or added, but binary compatibility has
+# been preserved, change to C+1:0:A+1
+# - If binary compatibility has been broken (eg removed or changed interfaces)
+# change to C+1:0:0
+# - If the interface is the same as the previous version, change to C:R+1:A
+libmate_panel_applet_current = 2
+libmate_panel_applet_revision = 0
+libmate_panel_applet_age = 0
+
+mate_panel_version = meson.project_version()
+version_array = mate_panel_version.split('.')
+mate_panel_major_version = version_array[0].to_int()
+mate_panel_minor_version = version_array[1].to_int()
+mate_panel_micro_version = version_array[2].to_int()
+
+mate_panel_api_version = '4.0'
+mate_panel_api_name = 'libmate-panel-applet-@0@'.format(mate_panel_api_version)
+
+mate_panel_gir_ns = 'MatePanelApplet'
+mate_panel_gir_version = mate_panel_api_version
+
+mate_panel_gettext_package = meson.project_name()
+
+mate_panel_prefix = get_option('prefix')
+mate_panel_bindir = join_paths(mate_panel_prefix, get_option('bindir'))
+mate_panel_datadir = join_paths(mate_panel_prefix, get_option('datadir'))
+mate_panel_includedir = join_paths(mate_panel_prefix, get_option('includedir'))
+mate_panel_libdir = join_paths(mate_panel_prefix, get_option('libdir'))
+mate_panel_libexecdir = join_paths(mate_panel_prefix, get_option('libexecdir'))
+mate_panel_localedir = join_paths(mate_panel_prefix, get_option('localedir'))
+mate_panel_pkgdatadir = join_paths(mate_panel_datadir, 'mate-panel')
+mate_panel_pkglibdir = join_paths(mate_panel_libdir, 'mate-panel')
+mate_panel_modulesdir = join_paths(mate_panel_libdir, 'mate-panel', 'modules')
+mate_panel_appletsdir = join_paths(mate_panel_datadir, 'mate-panel', 'applets')
+mate_panel_layoutsdir = join_paths(mate_panel_pkgdatadir, 'layouts')
+mate_panel_schemadir = join_paths(mate_panel_datadir, 'glib-2.0', 'schemas')
+
+cc = meson.get_compiler('c')
+
+# options
+enable_deprecation_flags = get_option('enable-deprecation-flags')
+enable_introspection = get_option('introspection')
+enable_gtk_doc = get_option('gtk-doc')
+enable_help = get_option('help')
+enable_compile_warnings = get_option('compile-warnings')
+
+config_h = configuration_data()
+config_h.set_quoted('GETTEXT_PACKAGE', mate_panel_gettext_package)
+config_h.set_quoted('PACKAGE', meson.project_name())
+config_h.set_quoted('PACKAGE_NAME', meson.project_name())
+config_h.set_quoted('PACKAGE_STRING', '@0@ @1@'.format(meson.project_name(), mate_panel_version))
+config_h.set_quoted('PACKAGE_TARNAME', meson.project_name())
+config_h.set_quoted('PACKAGE_URL', 'https://mate-desktop.org')
+config_h.set_quoted('PACKAGE_BUGREPORT', 'https://github.com/mate-desktop/mate-panel/issues')
+config_h.set_quoted('PACKAGE_VERSION', mate_panel_version)
+config_h.set_quoted('VERSION', mate_panel_version)
+config_h.set_quoted('MATELOCALEDIR', mate_panel_localedir)
+config_h.set_quoted('DATADIR', mate_panel_datadir)
+config_h.set_quoted('PANELDATADIR', mate_panel_pkgdatadir)
+config_h.set_quoted('PANEL_MODULES_DIR', mate_panel_modulesdir)
+config_h.set_quoted('MATE_PANEL_APPLETS_DIR', mate_panel_appletsdir)
+config_h.set('ENABLE_NLS', 1)
+
+# standard headers
+foreach header : [
+ 'dirent.h',
+ 'dlfcn.h',
+ 'inttypes.h',
+ 'langinfo.h',
+ 'stdint.h',
+ 'stdio.h',
+ 'stdlib.h',
+ 'strings.h',
+ 'string.h',
+ 'sys/stat.h',
+ 'sys/types.h',
+ 'unistd.h',
+ ]
+ if cc.has_header(header)
+ config_h.set('HAVE_' + header.underscorify().to_upper(), 1)
+ endif
+endforeach
+config_h.set('HAVE_NL_LANGINFO', cc.has_function('nl_langinfo'))
+config_h.set('STDC_HEADERS', 1)
+config_h.set('HAVE_STRUCT_DIRENT_D_TYPE',
+ cc.has_member('struct dirent', 'd_type', prefix: '#include <dirent.h>'))
+
+if get_option('enable-debug').enabled()
+ config_h.set('MATE_ENABLE_DEBUG', 1)
+else
+ config_h.set('NDEBUG', 1)
+endif
+
+# compile warnings
+warning_flags = []
+if enable_compile_warnings == 'no'
+ warning_flags = []
+elif enable_compile_warnings == 'minimum'
+ warning_flags = ['-Wall']
+elif enable_compile_warnings == 'yes'
+ warning_flags = ['-Wall', '-Wmissing-prototypes']
+elif enable_compile_warnings == 'maximum' or enable_compile_warnings == 'error'
+ warning_flags = [
+ '-Wall',
+ '-Wmissing-prototypes',
+ '-Wbad-function-cast',
+ '-Wcast-align',
+ '-Wextra',
+ '-Wno-unused-parameter',
+ '-Wformat-nonliteral',
+ '-Wmissing-declarations',
+ '-Wmissing-field-initializers',
+ '-Wnested-externs',
+ '-Wpointer-arith',
+ '-Wredundant-decls',
+ '-Wshadow',
+ '-Wstrict-prototypes',
+ '-Werror=format-security',
+ ]
+ if enable_compile_warnings == 'error'
+ warning_flags += ['-Werror']
+ endif
+endif
+
+foreach flag : warning_flags
+ if cc.has_argument(flag)
+ add_project_arguments(flag, language: 'c')
+ endif
+endforeach
+
+# *_DISABLE_DEPRECATED flags
+disable_deprecated_flags = []
+if enable_deprecation_flags
+ disable_deprecated_flags = [
+ '-DG_DISABLE_DEPRECATED',
+ '-DG_DISABLE_SINGLE_INCLUDES',
+ '-DATK_DISABLE_DEPRECATED',
+ '-DATK_DISABLE_SINGLE_INCLUDES',
+ '-DPANGO_DISABLE_DEPRECATED',
+ '-DPANGO_DISABLE_SINGLE_INCLUDES',
+ '-DGDK_DISABLE_DEPRECATED',
+ '-DGDK_DISABLE_SINGLE_INCLUDES',
+ '-DGDK_PIXBUF_DISABLE_DEPRECATED',
+ '-DGDK_PIXBUF_DISABLE_SINGLE_INCLUDES',
+ '-DGTK_DISABLE_DEPRECATED',
+ '-DGTK_DISABLE_SINGLE_INCLUDES',
+ '-DMATE_DISABLE_DEPRECATED',
+ '-DMATE_DISABLE_SINGLE_INCLUDES',
+ '-DLIBGLADE_DISABLE_DEPRECATED',
+ '-DLIBGLADE_DISABLE_SINGLE_INCLUDES',
+ '-DVTE_DISABLE_DEPRECATED',
+ '-DVTE_DISABLE_SINGLE_INCLUDES',
+ '-DWNCK_DISABLE_DEPRECATED',
+ '-DWNCK_DISABLE_SINGLE_INCLUDES',
+ '-DLIBSOUP_DISABLE_DEPRECATED',
+ '-DLIBSOUP_DISABLE_SINGLE_INCLUDES',
+ ]
+endif
+
+add_project_arguments(
+ '-DHAVE_CONFIG_H',
+ '-I' + meson.current_build_dir(),
+ language: 'c',
+)
+
+# dependencies
+glib_dep = dependency('glib-2.0', version: '>= 2.50.0')
+gio_dep = dependency('gio-2.0', version: '>= 2.50.0')
+gio_unix_dep = dependency('gio-unix-2.0', version: '>= 2.50.0')
+gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0', version: '>= 2.26.0')
+pango_dep = dependency('pango', version: '>= 1.15.4')
+gtk_dep = dependency('gtk+-3.0', version: '>= 3.24.0')
+cairo_dep = dependency('cairo', version: '>= 1.0.0')
+mate_desktop_dep = dependency('mate-desktop-2.0', version: '>= 1.28.2')
+mate_menu_dep = dependency('libmate-menu', version: '>= 1.21.0')
+dconf_dep = dependency('dconf', version: '>= 0.13.4')
+wnck_dep = dependency('libwnck-3.0', version: '>= 43.0')
+mateweather_dep = dependency('mateweather', version: '>= 1.17.0')
+gmodule_dep = dependency('gmodule-2.0', required: false)
+ice_dep = dependency('ice')
+sm_dep = dependency('sm')
+m_dep = cc.find_library('m', required: false)
+
+# X11 support
+x11_opt = get_option('enable-x11')
+x11_dep = dependency('x11', required: x11_opt)
+have_x11 = x11_dep.found()
+config_h.set('HAVE_X11', have_x11)
+
+# Wayland support
+wayland_opt = get_option('enable-wayland')
+wayland_deps = [
+ dependency('gtk-layer-shell-0', required: wayland_opt),
+ dependency('wayland-client', required: wayland_opt),
+]
+have_wayland = wayland_deps[0].found() and wayland_deps[1].found()
+if have_wayland
+ xfw_dep = dependency('libxfce4windowing-0', version: '>= 4.19.4', required: false)
+ if not xfw_dep.found()
+ if wayland_opt.enabled()
+ error('Wayland support requires libxfce4windowing-0 >= 4.19.4')
+ else
+ have_wayland = false
+ endif
+ endif
+endif
+config_h.set('HAVE_WAYLAND', have_wayland)
+
+if not have_x11 and not have_wayland
+ if wayland_opt.disabled() and x11_opt.disabled()
+ error('At least one backend must be enabled')
+ else
+ error('No usable backend found, install X11 or Wayland development libraries')
+ endif
+endif
+
+# XRandR extension
+randr_dep = dependency('xrandr', version: '>= 1.3.0', required: false)
+have_randr = randr_dep.found()
+config_h.set('HAVE_RANDR', have_randr)
+
+# Evolution Data Server support for calendar integration
+eds_opt = get_option('enable-eds')
+eds_deps = [
+ dependency('libecal-2.0', version: '>= 3.33.2', required: eds_opt),
+ dependency('libedataserver-1.2', version: '>= 3.5.3', required: eds_opt),
+]
+have_eds = eds_deps[0].found() and eds_deps[1].found()
+config_h.set('HAVE_EDS', have_eds)
+
+# applets to compile in-process
+in_process_applets = get_option('in-process-applets')
+clock_inprocess = false
+fish_inprocess = false
+notification_area_inprocess = false
+wncklet_inprocess = false
+if 'none' in in_process_applets
+ in_process_applets = []
+endif
+if 'all' in in_process_applets
+ in_process_applets = ['clock', 'fish', 'notification-area', 'wncklet']
+endif
+foreach applet : in_process_applets
+ if applet == 'clock'
+ clock_inprocess = true
+ config_h.set('CLOCK_INPROCESS', 1)
+ elif applet == 'fish'
+ fish_inprocess = true
+ config_h.set('FISH_INPROCESS', 1)
+ elif applet == 'notification-area'
+ notification_area_inprocess = true
+ config_h.set('NOTIFICATION_AREA_INPROCESS', 1)
+ elif applet == 'wncklet'
+ wncklet_inprocess = true
+ config_h.set('WNCKLET_INPROCESS', 1)
+ else
+ error('applet @0@ not recognized'.format(applet))
+ endif
+endforeach
+
+panel_deps = [
+ gmodule_dep,
+ gdk_pixbuf_dep,
+ pango_dep,
+ gtk_dep,
+ glib_dep,
+ gio_unix_dep,
+ mate_desktop_dep,
+ gio_dep,
+ mate_menu_dep,
+]
+
+libmate_panel_applet_deps = [
+ gtk_dep,
+ gio_dep,
+ gio_unix_dep,
+]
+
+# top-level include dirs
+panel_inc = include_directories('.')
+
+subdir('po')
+subdir('data')
+subdir('icons')
+subdir('man')
+subdir('libmate-panel-applet')
+subdir('mate-panel')
+subdir('applets')
+
+gtk_doc_dep = dependency('gtk-doc', required: enable_gtk_doc)
+if gtk_doc_dep.found()
+ subdir('doc')
+endif
+
+itstool = find_program('itstool', required: enable_help)
+if enable_help.allowed() and itstool.found()
+ subdir('help')
+endif
+
+configure_file(
+ output: 'config.h',
+ configuration: config_h,
+)
+
+summary({
+ 'Maintainer mode': false,
+ 'Use *_DISABLE_DEPRECATED': enable_deprecation_flags,
+ 'Applets to build in-process': in_process_applets.length() > 0 ? in_process_applets : ['(none)'],
+ 'Wayland support': have_wayland,
+ 'X11 support': have_x11,
+ 'XRandr support': have_randr,
+ 'Evolution Data Server support': have_eds,
+ 'Build introspection support': enable_introspection,
+ 'Build gtk-doc documentation': enable_gtk_doc,
+}, section: 'mate-panel')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000..af77de81
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,60 @@
+option('enable-deprecation-flags',
+ type: 'boolean',
+ value: false,
+ description: 'use *_DISABLE_DEPRECATED flags'
+)
+
+option('enable-eds',
+ type: 'feature',
+ value: 'auto',
+ description: 'Enable Evolution Data Server calendar integration'
+)
+
+option('enable-x11',
+ type: 'feature',
+ value: 'auto',
+ description: 'Explicitly enable or disable X11 support'
+)
+
+option('enable-wayland',
+ type: 'feature',
+ value: 'auto',
+ description: 'Explicitly enable or disable Wayland support'
+)
+
+option('in-process-applets',
+ type: 'array',
+ value: ['none'],
+ description: 'list of applets to compile in-process (none, clock, fish, notification-area, wncklet, all)'
+)
+
+option('introspection',
+ type: 'feature',
+ value: 'auto',
+ description: 'Enable introspection for this build'
+)
+
+option('gtk-doc',
+ type: 'feature',
+ value: 'auto',
+ description: 'use gtk-doc to build documentation'
+)
+
+option('help',
+ type: 'feature',
+ value: 'auto',
+ description: 'build the user help documentation'
+)
+
+option('enable-debug',
+ type: 'feature',
+ value: 'disabled',
+ description: 'turn on debugging'
+)
+
+option('compile-warnings',
+ type: 'combo',
+ value: 'yes',
+ choices: ['no', 'minimum', 'yes', 'maximum', 'error'],
+ description: 'Turn on compiler warnings'
+)
diff --git a/po/LINGUAS b/po/LINGUAS
index 2b6da758..85aee4ab 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -1,4 +1,3 @@
-# please keep this list sorted alphabetically
af
am
ar
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 00000000..57ed553d
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1,6 @@
+i18n = import('i18n')
+
+i18n.gettext(
+ mate_panel_gettext_package,
+ preset: 'glib',
+)