
This implements wellbeing screen time limits in gnome-shell. It depends on a few changes in other modules: - New settings schemas in gsettings-desktop-schemas - A settings UI in gnome-control-center - User documentation in gnome-user-docs It implements the design from https://gitlab.gnome.org/Teams/Design/settings-mockups/-/blob/master/wellbeing/wellbeing.png. The core of the implementation is `TimeLimitsManager`, which is a state machine which uses the user’s session state from logind to track how long the user has been in an active session, in aggregate, during the day. If this total exceeds their limit for the day, the state machine changes state. The user’s session activity history (basically, when they logged in and out for the past 14 weeks) is kept in a state file in their home directory. This is used by gnome-shell to count usage across reboots in a single day, and in the future it will also be used to provide usage history in gnome-control-center, so the user can visualise their historic computer usage at a high level, for the past several weeks. The `TimeLimitsDispatcher` is based on top of this, and controls showing notifications and screen fades to make the user aware of whether they’ve used the computer for too long today, as per their preferences. Unit tests are included to check that `TimeLimitsManager` works, in particular with its loading and storing of the history file. The unit tests provide mock implementations of basic GLib clock functions, the logind D-Bus proxy and `Gio.Settings` in order to test the state machine in faster-than-real-time. Signed-off-by: Philip Withnall <pwithnall@gnome.org> See: https://gitlab.gnome.org/Teams/Design/initiatives/-/issues/130 Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3397>
369 lines
10 KiB
Meson
369 lines
10 KiB
Meson
project('gnome-shell', 'c',
|
|
version: '47.0',
|
|
meson_version: '>= 1.1.0',
|
|
license: 'GPL-2.0-or-later',
|
|
)
|
|
|
|
split_version = meson.project_version().split('.')
|
|
|
|
# We depend on a specific version of the libmutter API. The mutter variants of
|
|
# the Cogl and Clutter libraries also use this API version.
|
|
# The API version is increased each development cycle,
|
|
# starting with 0 in 3.23.x
|
|
mutter_api_version = '16'
|
|
|
|
clutter_pc = 'mutter-clutter-' + mutter_api_version
|
|
cogl_pc = 'mutter-cogl-' + mutter_api_version
|
|
mtk_pc = 'mutter-mtk-' + mutter_api_version
|
|
libmutter_pc = 'libmutter-' + mutter_api_version
|
|
libmutter_test_pc = 'libmutter-test-' + mutter_api_version
|
|
|
|
ecal_req = '>= 3.33.1'
|
|
eds_req = '>= 3.33.1'
|
|
gcr_req = '>= 3.90.0'
|
|
gio_req = '>= 2.79.2'
|
|
gi_req = '>= 1.49.1'
|
|
gjs_req = '>= 1.73.1'
|
|
gtk_req = '>= 4.0'
|
|
mutter_req = '>= 47.0'
|
|
polkit_req = '>= 0.100'
|
|
schemas_req = '>= 48.alpha'
|
|
systemd_req = '>= 246'
|
|
gnome_desktop_req = '>= 40'
|
|
pipewire_req = '>= 0.3.49'
|
|
pango_req = '>= 1.46.0'
|
|
|
|
nm_req = '>= 1.10.4'
|
|
secret_req = '>= 0.18'
|
|
|
|
fs = import('fs')
|
|
gnome = import('gnome')
|
|
i18n = import('i18n')
|
|
|
|
prefix = get_option('prefix')
|
|
|
|
bindir = join_paths(prefix, get_option('bindir'))
|
|
datadir = join_paths(prefix, get_option('datadir'))
|
|
libdir = join_paths(prefix, get_option('libdir'))
|
|
libexecdir = join_paths(prefix, get_option('libexecdir'))
|
|
mandir = join_paths(prefix, get_option('mandir'))
|
|
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
|
|
|
|
pkgdatadir = join_paths(datadir, meson.project_name())
|
|
pkglibdir = join_paths(libdir, meson.project_name())
|
|
|
|
autostartdir = join_paths(sysconfdir, 'xdg', 'autostart')
|
|
desktopdir = join_paths(datadir, 'applications')
|
|
icondir = join_paths(datadir, 'icons')
|
|
ifacedir = join_paths(datadir, 'dbus-1', 'interfaces')
|
|
localedir = join_paths(datadir, 'locale')
|
|
metainfodir = join_paths(datadir, 'metainfo')
|
|
schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
|
|
servicedir = join_paths(datadir, 'dbus-1', 'services')
|
|
|
|
keybindings_dep = dependency('gnome-keybindings', required: false)
|
|
if keybindings_dep.found()
|
|
keysdir = keybindings_dep.get_variable('keysdir', pkgconfig_define: ['datadir', datadir])
|
|
else
|
|
keysdir = join_paths(datadir, 'gnome-control-center', 'keybindings')
|
|
endif
|
|
|
|
atk_bridge_dep = dependency('atk-bridge-2.0')
|
|
ecal_dep = dependency('libecal-2.0', version: ecal_req)
|
|
eds_dep = dependency('libedataserver-1.2', version: eds_req)
|
|
gcr_dep = dependency('gcr-4', version: gcr_req)
|
|
gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0')
|
|
gi_dep = dependency('gobject-introspection-1.0', version: gi_req)
|
|
gio_dep = dependency('gio-2.0', version: gio_req)
|
|
gio_unix_dep = dependency('gio-unix-2.0', version: gio_req)
|
|
gjs_dep = dependency('gjs-1.0', version: gjs_req)
|
|
gtk_dep = dependency('gtk4', version: gtk_req)
|
|
libxml_dep = dependency('libxml-2.0')
|
|
clutter_dep = dependency(clutter_pc, version: mutter_req)
|
|
mtk_dep = dependency(mtk_pc, version: mutter_req)
|
|
cogl_dep = dependency(cogl_pc, version: mutter_req)
|
|
mutter_dep = dependency(libmutter_pc, version: mutter_req)
|
|
polkit_dep = dependency('polkit-agent-1', version: polkit_req)
|
|
schemas_dep = dependency('gsettings-desktop-schemas', version: schemas_req)
|
|
gnome_desktop_dep = dependency('gnome-desktop-4', version: gnome_desktop_req)
|
|
pango_dep = dependency('pango', version: pango_req)
|
|
|
|
have_fonts = mutter_dep.get_variable('have_fonts') == 'true'
|
|
have_x11 = mutter_dep.get_variable('have_x11') == 'true'
|
|
have_x11_client = mutter_dep.get_variable('have_x11_client') == 'true'
|
|
if have_x11_client or have_x11
|
|
x11_dep = dependency('x11')
|
|
endif
|
|
|
|
if not have_fonts
|
|
error('Shell requires mutter to be built with fonts rendering support')
|
|
endif
|
|
|
|
|
|
nm_deps = []
|
|
if get_option('networkmanager')
|
|
nm_deps += dependency('libnm', version: nm_req)
|
|
nm_deps += dependency('libsecret-1', version: secret_req)
|
|
|
|
have_networkmanager = true
|
|
else
|
|
have_networkmanager = false
|
|
endif
|
|
|
|
have_portal_helper = get_option('portal_helper')
|
|
if have_portal_helper and not have_networkmanager
|
|
error('Portal helper requires networkmanager support')
|
|
endif
|
|
|
|
if get_option('camera_monitor')
|
|
libpipewire_dep = dependency('libpipewire-0.3', version: pipewire_req)
|
|
have_pipewire = true
|
|
else
|
|
libpipewire_dep = []
|
|
have_pipewire = false
|
|
endif
|
|
|
|
if get_option('systemd')
|
|
libsystemd_dep = dependency('libsystemd', version: systemd_req)
|
|
systemd_dep = dependency('systemd', version: systemd_req)
|
|
systemduserunitdir = systemd_dep.get_variable('systemduserunitdir',
|
|
pkgconfig_define: ['prefix', prefix])
|
|
have_systemd = true
|
|
else
|
|
libsystemd_dep = []
|
|
have_systemd = false
|
|
endif
|
|
|
|
if get_option('man')
|
|
rst2man = find_program('rst2man')
|
|
subdir('man')
|
|
endif
|
|
|
|
mutter_typelibdir = mutter_dep.get_variable('typelibdir')
|
|
python = find_program('python3')
|
|
gjs = find_program('gjs')
|
|
|
|
cc = meson.get_compiler('c')
|
|
|
|
m_dep = cc.find_library('m', required: false)
|
|
|
|
cdata = configuration_data()
|
|
cdata.set_quoted('GETTEXT_PACKAGE', meson.project_name())
|
|
cdata.set_quoted('VERSION', meson.project_version())
|
|
cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
|
|
|
cdata.set('HAVE_NETWORKMANAGER', have_networkmanager)
|
|
cdata.set('HAVE_PIPEWIRE', have_pipewire)
|
|
cdata.set('HAVE_SYSTEMD', have_systemd)
|
|
cdata.set('HAVE_X11', have_x11)
|
|
cdata.set('HAVE_X11_CLIENT', have_x11_client)
|
|
|
|
cdata.set('HAVE_FDWALK', cc.has_function('fdwalk'))
|
|
cdata.set('HAVE_MALLINFO', cc.has_function('mallinfo'))
|
|
cdata.set('HAVE_MALLINFO2', cc.has_function('mallinfo2'))
|
|
cdata.set('HAVE_SYS_RESOURCE_H', cc.has_header('sys/resource.h'))
|
|
cdata.set('HAVE_EXE_INTROSPECTION',
|
|
cc.has_header('elf.h') and cc.has_header('link.h'))
|
|
cdata.set('HAVE__NL_TIME_FIRST_WEEKDAY',
|
|
cc.has_header_symbol('langinfo.h', '_NL_TIME_FIRST_WEEKDAY')
|
|
)
|
|
|
|
cdata.set('HAVE_FDWALK',
|
|
cc.has_function('fdwalk')
|
|
)
|
|
|
|
polkit_has_autocleanup = cc.compiles(
|
|
'''
|
|
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
|
|
#include <polkitagent/polkitagent.h>
|
|
void main(void) { g_autoptr(PolkitAgentListener) agent = NULL; }
|
|
''',
|
|
dependencies: polkit_dep)
|
|
cdata.set('HAVE_POLKIT_AUTOCLEANUP', polkit_has_autocleanup)
|
|
|
|
buildtype = get_option('buildtype')
|
|
if buildtype != 'plain'
|
|
gs_c_args = [
|
|
'-fno-omit-frame-pointer',
|
|
'-mno-omit-leaf-frame-pointer',
|
|
'-fno-strict-aliasing',
|
|
'-Wpointer-arith',
|
|
'-Wmissing-declarations',
|
|
'-Wimplicit-function-declaration',
|
|
'-Wformat=2',
|
|
'-Wformat-nonliteral',
|
|
'-Wformat-security',
|
|
'-Wstrict-prototypes',
|
|
'-Wmissing-prototypes',
|
|
'-Wnested-externs',
|
|
'-Wold-style-definition',
|
|
'-Wundef',
|
|
'-Wunused',
|
|
'-Wcast-align',
|
|
'-Wmissing-noreturn',
|
|
'-Wmissing-format-attribute',
|
|
'-Wmissing-include-dirs',
|
|
'-Wlogical-op',
|
|
'-Wignored-qualifiers',
|
|
'-Werror=redundant-decls',
|
|
'-Werror=implicit',
|
|
'-Werror=nonnull',
|
|
'-Werror=init-self',
|
|
'-Werror=main',
|
|
'-Werror=missing-braces',
|
|
'-Werror=sequence-point',
|
|
'-Werror=return-type',
|
|
'-Werror=trigraphs',
|
|
'-Werror=array-bounds',
|
|
'-Werror=write-strings',
|
|
'-Werror=address',
|
|
'-Werror=int-to-pointer-cast',
|
|
'-Werror=pointer-to-int-cast',
|
|
'-Werror=empty-body',
|
|
'-Werror=write-strings',
|
|
]
|
|
|
|
|
|
if get_option('debug')
|
|
gs_c_args += [
|
|
'-DG_ENABLE_DEBUG',
|
|
]
|
|
else
|
|
gs_c_args += [
|
|
'-DG_DISABLE_ASSERT',
|
|
'-DG_DISABLE_CAST_CHECKS',
|
|
]
|
|
endif
|
|
|
|
supported_gs_c_args = cc.get_supported_arguments(gs_c_args)
|
|
add_project_arguments(supported_gs_c_args, language: 'c')
|
|
endif
|
|
|
|
config_h = configure_file(
|
|
input: 'config.h.meson',
|
|
output: 'config.h',
|
|
configuration: cdata
|
|
)
|
|
|
|
conf_inc = include_directories('.')
|
|
|
|
libgvc = subproject('gvc',
|
|
default_options: [
|
|
'package_name=' + meson.project_name(),
|
|
'package_version=' + meson.project_version(),
|
|
'pkgdatadir=' + pkgdatadir,
|
|
'pkglibdir=' + pkglibdir,
|
|
'static=false',
|
|
'introspection=true',
|
|
'alsa=false'
|
|
]
|
|
)
|
|
libgvc_gir = libgvc.get_variable('libgvc_gir')
|
|
|
|
libshew = subproject('shew',
|
|
default_options: [
|
|
'package_name=@0@'.format(meson.project_name()),
|
|
]
|
|
)
|
|
|
|
libshew_version = libshew.get_variable('package_version')
|
|
assert(libshew_version == meson.project_version(),
|
|
'shew version does not match project version')
|
|
|
|
if get_option('extensions_tool')
|
|
extension_tool = subproject('extensions-tool',
|
|
default_options: [
|
|
'package_name=@0@'.format(meson.project_name()),
|
|
]
|
|
)
|
|
|
|
extension_tool_version = extension_tool.get_variable('package_version')
|
|
assert(extension_tool_version == meson.project_version(),
|
|
'extension-tool version does not match project version'
|
|
)
|
|
endif
|
|
|
|
if get_option('extensions_app')
|
|
extensions_app = subproject('extensions-app',
|
|
default_options: [
|
|
'package_name=@0@'.format(meson.project_name()),
|
|
]
|
|
)
|
|
|
|
extensions_app_version = extensions_app.get_variable('package_version')
|
|
assert(extensions_app_version == meson.project_version(),
|
|
'Extensions app version does not match project version'
|
|
)
|
|
endif
|
|
|
|
if get_option('tests')
|
|
common_test_env = environment()
|
|
common_test_env.set('GSETTINGS_SCHEMA_DIR', meson.project_build_root() / 'data')
|
|
common_test_env.set('GSETTINGS_BACKEND', 'memory')
|
|
common_test_env.set('XDG_CURRENT_DESKTOP', '')
|
|
|
|
jasmine = find_program('jasmine')
|
|
|
|
add_test_setup('default',
|
|
is_default: true,
|
|
env: common_test_env,
|
|
)
|
|
endif
|
|
|
|
po_dir = join_paths(meson.current_source_dir(), 'po')
|
|
|
|
subdir('js')
|
|
subdir('src')
|
|
subdir('po')
|
|
subdir('data')
|
|
|
|
if get_option('tests') and have_x11_client
|
|
subdir('tests')
|
|
endif
|
|
|
|
if get_option('gtk_doc')
|
|
subdir('docs/reference')
|
|
endif
|
|
|
|
gnome.post_install(
|
|
glib_compile_schemas: true,
|
|
gtk_update_icon_cache: true
|
|
)
|
|
|
|
meson.add_dist_script('meson/generate-stylesheets.py')
|
|
meson.add_dist_script('meson/check-version.py', meson.project_version(), 'NEWS')
|
|
|
|
summary_options = {
|
|
'x11': have_x11,
|
|
'x11_client': have_x11_client,
|
|
'camera_monitor': get_option('camera_monitor'),
|
|
'networkmanager': get_option('networkmanager'),
|
|
'systemd': get_option('systemd'),
|
|
'extensions_app': get_option('extensions_app'),
|
|
'extensions_tool': get_option('extensions_tool'),
|
|
'man': get_option('man'),
|
|
'gtk_doc': get_option('gtk_doc'),
|
|
}
|
|
|
|
summary_build = {
|
|
'buildtype': get_option('buildtype'),
|
|
'debug': get_option('debug'),
|
|
}
|
|
|
|
summary_dirs = {
|
|
'prefix': get_option('prefix'),
|
|
'bindir': get_option('bindir'),
|
|
'libdir': get_option('libdir'),
|
|
'libexecdir': get_option('libexecdir'),
|
|
'datadir': get_option('datadir'),
|
|
'sysconfdir': get_option('sysconfdir'),
|
|
}
|
|
|
|
if get_option('man')
|
|
summary_dirs += { 'mandir': get_option('mandir') }
|
|
endif
|
|
|
|
summary(summary_dirs, section: 'Directories')
|
|
summary(summary_build, section: 'Build Configuration')
|
|
summary(summary_options, section: 'Build Options')
|