diff options
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' +) @@ -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', +) |
