diff --git a/danctnix-phosh-settings/11_mobile.gschema.override b/danctnix-phosh-settings/11_mobile.gschema.override new file mode 100644 index 0000000..ac763b0 --- /dev/null +++ b/danctnix-phosh-settings/11_mobile.gschema.override @@ -0,0 +1,23 @@ +[org.gnome.desktop.session] +idle-delay=60 + +[org.gnome.Epiphany.web] +user-agent='Mozilla/5.0 (PinePhone, like iPhone; Linux aarch64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Chrome/64 Mobile/15E148 Safari/605.1.15' + +[org.gnome.desktop.background] +picture-uri='file:///usr/share/danctnix/adwaita-phone.jpg' + +[org.gnome.desktop.sound] +theme-name='librem5' + +[org.gnome.settings-daemon.peripherals.touchscreen] +orientation-lock=true + +[org.gnome.settings-daemon.plugins.wwan] +unlock-sim=true + +[org.gnome.software] +download-updates=false + +[sm.puri.phosh] +enable-suspend=true diff --git a/danctnix-phosh-settings/PKGBUILD b/danctnix-phosh-settings/PKGBUILD new file mode 100644 index 0000000..bc7c218 --- /dev/null +++ b/danctnix-phosh-settings/PKGBUILD @@ -0,0 +1,31 @@ +# Maintainer: Danct12 +pkgname=danctnix-phosh-settings +pkgver=0.5 +pkgrel=3 +pkgdesc="Settings for Phosh UI" +arch=(any) +url="https://github.com/dreemurrs-embedded/Pine64-Arch" +license=('MIT') +install="$pkgname.install" +source=(adwaita-phone.jpg + pa-phosh.pa + phosh-wayland.sh + 11_mobile.gschema.override) + +package() { + # Add custom PA config + install -Dm755 -t "$pkgdir/etc/pulse/default.pa.d" "$srcdir/pa-phosh.pa" + + # Envscripts + install -Dm755 -t "$pkgdir/etc/profile.d" "$srcdir/phosh-wayland.sh" + + install -Dm644 -t "$pkgdir/usr/share/glib-2.0/schemas" "$srcdir/11_mobile.gschema.override" + + install -Dm644 -t "$pkgdir/usr/share/danctnix" "$srcdir/adwaita-phone.jpg" +} + + +md5sums=('cdc223b00b4e98f77286df98b1cddb4b' + 'fe7dc2d103ce11388af9ed555578fbf7' + '7580818750c3dad45819f0e3345169a7' + '9caef3d24adc4d10528eac294353b167') diff --git a/danctnix-phosh-settings/adwaita-phone.jpg b/danctnix-phosh-settings/adwaita-phone.jpg new file mode 100644 index 0000000..2238cb4 Binary files /dev/null and b/danctnix-phosh-settings/adwaita-phone.jpg differ diff --git a/danctnix-phosh-settings/danctnix-phosh-settings.install b/danctnix-phosh-settings/danctnix-phosh-settings.install new file mode 100644 index 0000000..6f60e9c --- /dev/null +++ b/danctnix-phosh-settings/danctnix-phosh-settings.install @@ -0,0 +1,9 @@ +post_install() { + dconf update + glib-compile-schemas /usr/share/glib-2.0/schemas +} + +post_upgrade() { + dconf update + glib-compile-schemas /usr/share/glib-2.0/schemas +} diff --git a/danctnix-phosh-settings/pa-phosh.pa b/danctnix-phosh-settings/pa-phosh.pa new file mode 100644 index 0000000..f4f0bf4 --- /dev/null +++ b/danctnix-phosh-settings/pa-phosh.pa @@ -0,0 +1,5 @@ +# duck volume of audio streams when notification or accessibility sounds are played +load-module module-role-ducking trigger_roles=event,a11y ducking_roles=no_role,music,video,game global=true + +# automatically switch default source/sink to a new device (Bluetooth, USB) +load-module module-switch-on-connect diff --git a/danctnix-phosh-settings/phosh-wayland.sh b/danctnix-phosh-settings/phosh-wayland.sh new file mode 100755 index 0000000..d337dba --- /dev/null +++ b/danctnix-phosh-settings/phosh-wayland.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# Sometimes users may have multiple UI installed and they may choose to run a non-Wayland environment, +# so let's only set these when the session type is Wayland. + +if [ "$XDG_SESSION_TYPE" = "wayland" ]; then + export MOZ_ENABLE_WAYLAND=1 + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 +fi diff --git a/danctnix-phosh-ui-meta/PKGBUILD b/danctnix-phosh-ui-meta/PKGBUILD new file mode 100644 index 0000000..e4d24ee --- /dev/null +++ b/danctnix-phosh-ui-meta/PKGBUILD @@ -0,0 +1,24 @@ +# Maintainer: Danct12 +pkgname=danctnix-phosh-ui-meta +pkgver=0.2 +pkgrel=4 +pkgdesc="Meta package for Phosh" +arch=(any) +url="https://github.com/dreemurrs-embedded/Pine64-Arch" +depends=( + danctnix-phosh-settings + dconf + gtk3 + gnome-keyring + phoc + phosh + feedbackd + squeekboard + dnsmasq + gnome-control-center + sound-theme-librem5 + iio-sensor-proxy + wys + xdg-desktop-portal-gtk + ) + diff --git a/evince-mobile/0001-toolbar-Allow-to-toggle-the-sidebar-button.patch b/evince-mobile/0001-toolbar-Allow-to-toggle-the-sidebar-button.patch new file mode 100644 index 0000000..c7dbcb1 --- /dev/null +++ b/evince-mobile/0001-toolbar-Allow-to-toggle-the-sidebar-button.patch @@ -0,0 +1,45 @@ +From: Adrien Plazas +Date: Wed, 11 Dec 2019 16:24:31 +0100 +Subject: toolbar: Allow to toggle the sidebar button + +This will allow updating the button's state when gestures will allow +closing the sidebar in the next commit. +--- + shell/ev-toolbar.c | 14 ++++++++++++++ + shell/ev-toolbar.h | 3 +++ + 2 files changed, 17 insertions(+) + +diff --git a/shell/ev-toolbar.c b/shell/ev-toolbar.c +index bb20887..6c5521f 100644 +--- a/shell/ev-toolbar.c ++++ b/shell/ev-toolbar.c +@@ -264,3 +264,17 @@ ev_toolbar_get_mode (EvToolbar *ev_toolbar) + + return priv->toolbar_mode; + } ++ ++void ++ev_toolbar_set_sidebar_visible (EvToolbar *ev_toolbar, ++ gboolean visible) ++{ ++ EvToolbarPrivate *priv; ++ ++ g_return_if_fail (EV_IS_TOOLBAR (ev_toolbar)); ++ ++ priv = GET_PRIVATE (ev_toolbar); ++ visible = !!visible; ++ ++ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->sidebar_button), visible); ++} +diff --git a/shell/ev-toolbar.h b/shell/ev-toolbar.h +index 6cb8ae4..1b15e80 100644 +--- a/shell/ev-toolbar.h ++++ b/shell/ev-toolbar.h +@@ -58,4 +58,7 @@ void ev_toolbar_set_mode (EvToolbar *ev_toolbar, + EvToolbarMode mode); + EvToolbarMode ev_toolbar_get_mode (EvToolbar *ev_toolbar); + ++void ev_toolbar_set_sidebar_visible (EvToolbar *ev_toolbar, ++ gboolean visible); ++ + G_END_DECLS diff --git a/evince-mobile/0002-toolbar-Allow-hiding-zoom-annotation-and-page-widgets.patch b/evince-mobile/0002-toolbar-Allow-hiding-zoom-annotation-and-page-widgets.patch new file mode 100644 index 0000000..adad44e --- /dev/null +++ b/evince-mobile/0002-toolbar-Allow-hiding-zoom-annotation-and-page-widgets.patch @@ -0,0 +1,197 @@ +From: Alexander Mikhaylenko +Date: Thu, 15 Apr 2021 12:28:10 +0500 +Subject: toolbar: Allow hiding zoom, annotation and page widgets + +This will be useful to make it adaptive. +--- + shell/ev-toolbar.c | 32 +++++++++++++++---- + shell/ev-toolbar.h | 2 ++ + shell/evince-toolbar.ui | 84 ++++++++++++++++++++++++++++++------------------- + 3 files changed, 79 insertions(+), 39 deletions(-) + +diff --git a/shell/ev-toolbar.c b/shell/ev-toolbar.c +index 6c5521f..83ba22a 100644 +--- a/shell/ev-toolbar.c ++++ b/shell/ev-toolbar.c +@@ -51,6 +51,8 @@ typedef struct { + GtkWidget *zoom_action; + GtkWidget *find_button; + GtkWidget *action_menu_button; ++ GtkWidget *zoom_revealer; ++ GtkWidget *page_annots_revealer; + + EvToolbarMode toolbar_mode; + } EvToolbarPrivate; +@@ -141,6 +143,8 @@ ev_toolbar_class_init (EvToolbarClass *klass) + gtk_widget_class_bind_template_child_private (widget_class, EvToolbar, action_menu_button); + gtk_widget_class_bind_template_child_private (widget_class, EvToolbar, find_button); + gtk_widget_class_bind_template_child_private (widget_class, EvToolbar, zoom_action); ++ gtk_widget_class_bind_template_child_private (widget_class, EvToolbar, page_annots_revealer); ++ gtk_widget_class_bind_template_child_private (widget_class, EvToolbar, zoom_revealer); + gtk_widget_class_bind_template_callback (widget_class, ev_toolbar_find_button_sensitive_changed); + gtk_widget_class_bind_template_callback (widget_class, ev_toolbar_zoom_selector_activated); + +@@ -235,19 +239,17 @@ ev_toolbar_set_mode (EvToolbar *ev_toolbar, + case EV_TOOLBAR_MODE_FULLSCREEN: + gtk_widget_show (priv->sidebar_button); + gtk_widget_show (priv->action_menu_button); +- gtk_widget_show (priv->zoom_action); +- gtk_widget_show (priv->page_selector); ++ gtk_widget_show (priv->zoom_revealer); ++ gtk_widget_show (priv->page_annots_revealer); + gtk_widget_show (priv->find_button); +- gtk_widget_show (priv->annots_button); + gtk_widget_hide (priv->open_button); + break; + case EV_TOOLBAR_MODE_RECENT_VIEW: + gtk_widget_hide (priv->sidebar_button); + gtk_widget_hide (priv->action_menu_button); +- gtk_widget_hide (priv->zoom_action); +- gtk_widget_hide (priv->page_selector); ++ gtk_widget_hide (priv->zoom_revealer); ++ gtk_widget_hide (priv->page_annots_revealer); + gtk_widget_hide (priv->find_button); +- gtk_widget_hide (priv->annots_button); + gtk_widget_show (priv->open_button); + break; + } +@@ -278,3 +280,21 @@ ev_toolbar_set_sidebar_visible (EvToolbar *ev_toolbar, + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->sidebar_button), visible); + } ++ ++void ++ev_toolbar_set_mobile (EvToolbar *ev_toolbar, ++ gboolean mobile) ++{ ++ EvToolbarPrivate *priv; ++ ++ g_return_if_fail (EV_IS_TOOLBAR (ev_toolbar)); ++ ++ priv = GET_PRIVATE (ev_toolbar); ++ mobile = !!mobile; ++ ++ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->zoom_revealer), !mobile); ++ gtk_revealer_set_reveal_child (GTK_REVEALER (priv->page_annots_revealer), !mobile); ++ ++ if (mobile) ++ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->annots_button), FALSE); ++} +diff --git a/shell/ev-toolbar.h b/shell/ev-toolbar.h +index 1b15e80..1c1f0a2 100644 +--- a/shell/ev-toolbar.h ++++ b/shell/ev-toolbar.h +@@ -60,5 +60,7 @@ EvToolbarMode ev_toolbar_get_mode (EvToolbar *ev_toolbar); + + void ev_toolbar_set_sidebar_visible (EvToolbar *ev_toolbar, + gboolean visible); ++void ev_toolbar_set_mobile (EvToolbar *ev_toolbar, ++ gboolean mobile); + + G_END_DECLS +diff --git a/shell/evince-toolbar.ui b/shell/evince-toolbar.ui +index 4add3ec..f35b961 100644 +--- a/shell/evince-toolbar.ui ++++ b/shell/evince-toolbar.ui +@@ -31,38 +31,50 @@ + + + +- +- Select page or search in the outline +- +- +- Select page +- +- +- +- +- start +- +- +- +- +- win.toggle-edit-annots +- Annotate the document ++ ++ True ++ slide-right + +- +- document-edit-symbolic +- 1 +- true +- +- +- +- +- Annotate document ++ ++ horizontal ++ 6 ++ ++ ++ Select page or search in the outline ++ ++ ++ Select page ++ ++ ++ ++ ++ start ++ ++ ++ ++ ++ win.toggle-edit-annots ++ Annotate the document ++ ++ ++ document-edit-symbolic ++ 1 ++ true ++ ++ ++ ++ ++ Annotate document ++ ++ ++ ++ ++ start ++ ++ + + + +- +- start +- + + + +@@ -103,11 +115,17 @@ + + + +- +- +- +- +- Set zoom level ++ ++ True ++ slide-left ++ ++ ++ ++ ++ ++ Set zoom level ++ ++ + + + diff --git a/evince-mobile/0003-properties-view-Reduce-the-label-width-chars.patch b/evince-mobile/0003-properties-view-Reduce-the-label-width-chars.patch new file mode 100644 index 0000000..428b3bd --- /dev/null +++ b/evince-mobile/0003-properties-view-Reduce-the-label-width-chars.patch @@ -0,0 +1,22 @@ +From: Adrien Plazas +Date: Wed, 11 Dec 2019 14:48:15 +0100 +Subject: properties-view: Reduce the label width chars + +This allows the window to fit phones. +--- + properties/ev-properties-view.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/properties/ev-properties-view.c b/properties/ev-properties-view.c +index 04aa656..972027a 100644 +--- a/properties/ev-properties-view.c ++++ b/properties/ev-properties-view.c +@@ -208,7 +208,7 @@ set_property (EvPropertiesView *properties, + + g_object_set (G_OBJECT (value_label), + "xalign", 0.0, +- "width_chars", 25, ++ "width_chars", 20, + "selectable", TRUE, + "ellipsize", PANGO_ELLIPSIZE_END, + "hexpand", TRUE, diff --git a/evince-mobile/0004-window-Port-it-to-phones.patch b/evince-mobile/0004-window-Port-it-to-phones.patch new file mode 100644 index 0000000..19bacd2 --- /dev/null +++ b/evince-mobile/0004-window-Port-it-to-phones.patch @@ -0,0 +1,467 @@ +From: Adrien Plazas +Date: Tue, 10 Dec 2019 10:04:30 +0100 +Subject: window: Port it to phones + +Fixes https://source.puri.sm/Librem5/Apps_Issues/issues/150. +--- + shell/ev-window.c | 193 ++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 113 insertions(+), 80 deletions(-) + +diff --git a/shell/ev-window.c b/shell/ev-window.c +index d8970e3..93ce02c 100644 +--- a/shell/ev-window.c ++++ b/shell/ev-window.c +@@ -135,8 +135,9 @@ typedef struct { + + GtkWidget *main_box; + GtkWidget *toolbar; +- GtkWidget *hpaned; ++ GtkWidget *flap; + GtkWidget *view_box; ++ GtkWidget *sidebar_stack; + GtkWidget *sidebar; + GtkWidget *search_box; + GtkWidget *search_bar; +@@ -264,7 +265,7 @@ typedef struct { + #define GS_LAST_PICTURES_DIRECTORY "pictures-directory" + #define GS_ALLOW_LINKS_CHANGE_ZOOM "allow-links-change-zoom" + +-#define SIDEBAR_DEFAULT_SIZE 132 ++#define SIDEBAR_DEFAULT_SIZE 246 + #define LINKS_SIDEBAR_ID "links" + #define THUMBNAILS_SIDEBAR_ID "thumbnails" + #define ATTACHMENTS_SIDEBAR_ID "attachments" +@@ -294,9 +295,6 @@ static const gchar *document_print_settings[] = { + }; + + static void ev_window_update_actions_sensitivity (EvWindow *ev_window); +-static void ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_sidebar, +- GParamSpec *pspec, +- EvWindow *ev_window); + static void ev_window_set_page_mode (EvWindow *window, + EvWindowPageMode page_mode); + static void ev_window_load_job_cb (EvJob *job, +@@ -667,7 +665,8 @@ update_chrome_visibility (EvWindow *window) + sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && priv->document && !presentation; + + set_widget_visibility (priv->toolbar, toolbar); +- set_widget_visibility (priv->sidebar, sidebar); ++ set_widget_visibility (priv->sidebar, TRUE); ++ hdy_flap_set_reveal_flap (HDY_FLAP (priv->flap), sidebar); + } + + static void +@@ -1280,15 +1279,11 @@ static void + setup_sidebar_from_metadata (EvWindow *window) + { + gchar *page_id; +- gint sidebar_size; + EvWindowPrivate *priv = GET_PRIVATE (window); + + if (!priv->metadata) + return; + +- if (ev_metadata_get_int (priv->metadata, "sidebar_size", &sidebar_size)) +- gtk_paned_set_position (GTK_PANED (priv->hpaned), sidebar_size); +- + if (ev_metadata_get_string (priv->metadata, "sidebar_page", &page_id)) + ev_window_sidebar_set_current_page (window, page_id); + } +@@ -1583,10 +1578,6 @@ ev_window_setup_default (EvWindow *ev_window) + g_settings_get_boolean (settings, "show-sidebar")); + update_chrome_visibility (ev_window); + +- /* Sidebar */ +- gtk_paned_set_position (GTK_PANED (priv->hpaned), +- g_settings_get_int (settings, "sidebar-size")); +- + /* Document model */ + ev_document_model_set_continuous (model, g_settings_get_boolean (settings, "continuous")); + ev_document_model_set_dual_page (model, g_settings_get_boolean (settings, "dual-page")); +@@ -1705,7 +1696,7 @@ ev_window_setup_document (EvWindow *ev_window) + + if (EV_WINDOW_IS_PRESENTATION (priv)) + gtk_widget_grab_focus (priv->presentation_view); +- else if (!gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (priv->search_bar))) ++ else if (!hdy_search_bar_get_search_mode (HDY_SEARCH_BAR (priv->search_bar))) + gtk_widget_grab_focus (priv->view); + + return G_SOURCE_REMOVE; +@@ -2023,7 +2014,7 @@ ev_window_reload_job_cb (EvJob *job, + } + + /* Restart the search after reloading */ +- if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (priv->search_bar))) ++ if (hdy_search_bar_get_search_mode (HDY_SEARCH_BAR (priv->search_bar))) + ev_search_box_restart (EV_SEARCH_BOX (priv->search_box)); + + ev_window_clear_reload_job (ev_window); +@@ -2536,7 +2527,7 @@ ev_window_open_recent_view (EvWindow *ev_window) + if (priv->recent_view) + return; + +- gtk_widget_hide (priv->hpaned); ++ gtk_widget_hide (priv->flap); + + priv->recent_view = EV_RECENT_VIEW (ev_recent_view_new ()); + g_signal_connect_object (priv->recent_view, +@@ -2565,7 +2556,7 @@ ev_window_destroy_recent_view (EvWindow *ev_window) + + gtk_widget_destroy (GTK_WIDGET (priv->recent_view)); + priv->recent_view = NULL; +- gtk_widget_show (priv->hpaned); ++ gtk_widget_show (priv->flap); + } + + static void +@@ -4099,9 +4090,7 @@ ev_window_save_settings (EvWindow *ev_window) + g_settings_set_double (settings, "zoom", zoom); + } + g_settings_set_boolean (settings, "show-sidebar", +- gtk_widget_get_visible (priv->sidebar)); +- g_settings_set_int (settings, "sidebar-size", +- gtk_paned_get_position (GTK_PANED (priv->hpaned))); ++ hdy_flap_get_reveal_flap (HDY_FLAP (priv->flap))); + g_settings_set_string (settings, "sidebar-page", + ev_window_sidebar_get_current_page_id (ev_window)); + g_settings_set_boolean (settings, "enable-spellchecking", +@@ -4536,7 +4525,7 @@ ev_window_cmd_edit_find_next (GSimpleAction *action, + if (EV_WINDOW_IS_PRESENTATION (priv)) + return; + +- search_mode_enabled = gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (priv->search_bar)); ++ search_mode_enabled = hdy_search_bar_get_search_mode (HDY_SEARCH_BAR (priv->search_bar)); + ev_window_show_find_bar (ev_window, FALSE); + + /* Use idle to make sure view allocation happens before find */ +@@ -4565,7 +4554,7 @@ ev_window_cmd_edit_find_previous (GSimpleAction *action, + if (EV_WINDOW_IS_PRESENTATION (priv)) + return; + +- search_mode_enabled = gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (priv->search_bar)); ++ search_mode_enabled = hdy_search_bar_get_search_mode (HDY_SEARCH_BAR (priv->search_bar)); + ev_window_show_find_bar (ev_window, FALSE); + + /* Use idle to make sure view allocation happens before find */ +@@ -4586,18 +4575,6 @@ ev_window_cmd_edit_copy (GSimpleAction *action, + ev_view_copy (EV_VIEW (priv->view)); + } + +-static void +-ev_window_sidebar_position_change_cb (GObject *object, +- GParamSpec *pspec, +- EvWindow *ev_window) +-{ +- EvWindowPrivate *priv = GET_PRIVATE (ev_window); +- +- if (priv->metadata && !ev_window_is_empty (ev_window)) +- ev_metadata_set_int (priv->metadata, "sidebar_size", +- gtk_paned_get_position (GTK_PANED (object))); +-} +- + static void + ev_window_update_links_model (EvWindow *window) + { +@@ -4805,7 +4782,7 @@ ev_window_run_presentation (EvWindow *window) + priv->presentation_view, + TRUE, TRUE, 0); + +- gtk_widget_hide (priv->hpaned); ++ gtk_widget_hide (priv->flap); + update_chrome_visibility (window); + + gtk_widget_grab_focus (priv->presentation_view); +@@ -4840,7 +4817,7 @@ ev_window_stop_presentation (EvWindow *window, + priv->presentation_view); + priv->presentation_view = NULL; + +- gtk_widget_show (priv->hpaned); ++ gtk_widget_show (priv->flap); + update_chrome_visibility (window); + if (unfullscreen_window) + gtk_window_unfullscreen (GTK_WINDOW (window)); +@@ -5208,7 +5185,7 @@ ev_window_cmd_escape (GSimpleAction *action, + + ev_view_autoscroll_stop (EV_VIEW (priv->view)); + +- if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (priv->search_bar))) ++ if (hdy_search_bar_get_search_mode (HDY_SEARCH_BAR (priv->search_bar))) + ev_window_close_find_bar (window); + else if (ev_document_model_get_fullscreen (priv->model)) + ev_window_stop_fullscreen (window, TRUE); +@@ -5463,14 +5440,12 @@ ev_window_sidebar_current_page_changed_cb (EvSidebar *ev_sidebar, + } + + static void +-ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_sidebar, +- GParamSpec *pspec, +- EvWindow *ev_window) ++flap_reveal_changed_cb (EvWindow *ev_window) + { + EvWindowPrivate *priv = GET_PRIVATE (ev_window); + + if (!EV_WINDOW_IS_PRESENTATION (priv)) { +- gboolean visible = gtk_widget_get_visible (GTK_WIDGET (ev_sidebar)); ++ gboolean visible = hdy_flap_get_reveal_flap (HDY_FLAP (priv->flap)); + + g_action_group_change_action_state (G_ACTION_GROUP (ev_window), "show-side-pane", + g_variant_new_boolean (visible)); +@@ -5480,6 +5455,10 @@ ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_sidebar, + visible); + if (!visible) + gtk_widget_grab_focus (priv->view); ++ ++ update_chrome_flag (ev_window, EV_CHROME_SIDEBAR, visible); ++ update_chrome_visibility (ev_window); ++ ev_toolbar_set_sidebar_visible (EV_TOOLBAR (priv->toolbar), visible); + } + } + +@@ -5829,12 +5808,12 @@ search_next_cb (EvSearchBox *search_box, + } + + static void +-search_bar_search_mode_enabled_changed (GtkSearchBar *search_bar, ++search_bar_search_mode_enabled_changed (HdySearchBar *search_bar, + GParamSpec *param, + EvWindow *ev_window) + { + EvWindowPrivate *priv = GET_PRIVATE (ev_window); +- gboolean enabled = gtk_search_bar_get_search_mode (search_bar); ++ gboolean enabled = hdy_search_bar_get_search_mode (search_bar); + + ev_view_find_set_highlight_search (EV_VIEW (priv->view), enabled); + ev_window_update_actions_sensitivity (ev_window); +@@ -5858,7 +5837,8 @@ ev_window_show_find_bar (EvWindow *ev_window, + { + EvWindowPrivate *priv = GET_PRIVATE (ev_window); + +- if (gtk_widget_get_visible (priv->find_sidebar)) { ++ if (gtk_stack_get_visible_child (GTK_STACK (priv->sidebar_stack)) == priv->find_sidebar) { ++ hdy_flap_set_reveal_flap (HDY_FLAP (priv->flap), TRUE); + gtk_widget_grab_focus (priv->search_box); + return; + } +@@ -5874,13 +5854,10 @@ ev_window_show_find_bar (EvWindow *ev_window, + ev_history_freeze (priv->history); + + g_object_ref (priv->sidebar); +- gtk_container_remove (GTK_CONTAINER (priv->hpaned), priv->sidebar); +- gtk_paned_pack1 (GTK_PANED (priv->hpaned), +- priv->find_sidebar, FALSE, FALSE); +- gtk_widget_show (priv->find_sidebar); ++ gtk_stack_set_visible_child (GTK_STACK (priv->sidebar_stack), priv->find_sidebar); + + +- gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->search_bar), TRUE); ++ hdy_search_bar_set_search_mode (HDY_SEARCH_BAR (priv->search_bar), TRUE); + gtk_widget_grab_focus (priv->search_box); + g_action_group_change_action_state (G_ACTION_GROUP (ev_window), "toggle-find", g_variant_new_boolean (TRUE)); + +@@ -5898,17 +5875,13 @@ ev_window_close_find_bar (EvWindow *ev_window) + { + EvWindowPrivate *priv = GET_PRIVATE (ev_window); + +- if (!gtk_widget_get_visible (priv->find_sidebar)) ++ if (gtk_stack_get_visible_child (GTK_STACK (priv->sidebar_stack)) != priv->find_sidebar) + return; + + g_object_ref (priv->find_sidebar); +- gtk_container_remove (GTK_CONTAINER (priv->hpaned), +- priv->find_sidebar); +- gtk_paned_pack1 (GTK_PANED (priv->hpaned), +- priv->sidebar, FALSE, FALSE); +- gtk_widget_hide (priv->find_sidebar); ++ gtk_stack_set_visible_child (GTK_STACK (priv->sidebar_stack), priv->sidebar); + +- gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->search_bar), FALSE); ++ hdy_search_bar_set_search_mode (HDY_SEARCH_BAR (priv->search_bar), FALSE); + gtk_widget_grab_focus (priv->view); + g_action_group_change_action_state (G_ACTION_GROUP (ev_window), "toggle-find", g_variant_new_boolean (FALSE)); + +@@ -6514,6 +6487,48 @@ window_state_event_cb (EvWindow *window, GdkEventWindowState *event, gpointer du + return FALSE; + } + ++static void ++window_size_allocate_cb (EvWindow *window) ++{ ++ EvWindowPrivate *priv = GET_PRIVATE (window); ++ gboolean is_maximized, is_fullscreen; ++ gboolean is_narrow, is_mobile_landscape, is_mobile; ++ int width, height; ++ GdkDisplay *display; ++ GdkWindow *surface; ++ GdkMonitor *monitor = NULL; ++ GdkRectangle geometry = {}; ++ ++ gtk_window_get_size (GTK_WINDOW (window), &width, &height); ++ ++ /* Get the monitor to guess whether we are on a mobile or not. If not found, ++ * fallback to the window size. ++ */ ++ display = gtk_widget_get_display (GTK_WIDGET (window)); ++ surface = gtk_widget_get_window (GTK_WIDGET (window)); ++ ++ if (display != NULL && surface != NULL) ++ monitor = gdk_display_get_monitor_at_window (display, surface); ++ ++ if (monitor != NULL) ++ gdk_monitor_get_geometry (monitor, &geometry); ++ else ++ geometry.height = height; ++ ++ is_maximized = gtk_window_is_maximized (GTK_WINDOW (window)); ++ is_fullscreen = GDK_IS_WINDOW (surface) && (gdk_window_get_state (surface) & GDK_WINDOW_STATE_FULLSCREEN) > 0; ++ ++ is_narrow = width <= 600; ++ is_mobile_landscape = geometry.height <= 400 && ++ (is_maximized || is_fullscreen); ++ ++ is_mobile = is_narrow || is_mobile_landscape; ++ ++ hdy_flap_set_fold_policy (HDY_FLAP (priv->flap), ++ is_mobile ? HDY_FLAP_FOLD_POLICY_ALWAYS : HDY_FLAP_FOLD_POLICY_AUTO); ++ ev_toolbar_set_mobile (EV_TOOLBAR (priv->toolbar), is_mobile); ++} ++ + static gboolean + window_configure_event_cb (EvWindow *window, GdkEventConfigure *event, gpointer dummy) + { +@@ -7409,7 +7424,9 @@ ev_window_init (EvWindow *ev_window) + GtkBuilder *builder; + GError *error = NULL; + GtkWidget *sidebar_widget; ++ GtkWidget *separator; + GtkWidget *overlay; ++ GtkWidget *clamp; + GObject *mpkeys; + guint page_cache_mb; + gboolean allow_links_change_zoom; +@@ -7425,6 +7442,8 @@ ev_window_init (EvWindow *ev_window) + G_CALLBACK (window_configure_event_cb), NULL); + g_signal_connect (ev_window, "window_state_event", + G_CALLBACK (window_state_event_cb), NULL); ++ g_signal_connect (ev_window, "size-allocate", ++ G_CALLBACK (window_size_allocate_cb), NULL); + + priv = GET_PRIVATE (ev_window); + +@@ -7512,17 +7531,19 @@ ev_window_init (EvWindow *ev_window) + priv->annots_toolbar, FALSE, TRUE, 0); + + /* Search Bar */ +- priv->search_bar = gtk_search_bar_new (); ++ priv->search_bar = hdy_search_bar_new (); ++ ++ clamp = hdy_clamp_new (); ++ gtk_container_add (GTK_CONTAINER (priv->search_bar), clamp); ++ gtk_widget_show (clamp); + + priv->search_box = ev_search_box_new (priv->model); + search_entry = GTK_ENTRY (ev_search_box_get_entry (EV_SEARCH_BOX (priv->search_box))); +- gtk_entry_set_width_chars (search_entry, 32); +- gtk_entry_set_max_length (search_entry, 512); +- gtk_container_add (GTK_CONTAINER (priv->search_bar), ++ gtk_container_add (GTK_CONTAINER (clamp), + priv->search_box); + gtk_widget_show (priv->search_box); + +- /* We don't use gtk_search_bar_connect_entry, because it clears the entry when the ++ /* We don't use hdy_search_bar_connect_entry, because it clears the entry when the + * search is closed, but we want to keep the current search. + */ + gtk_box_pack_start (GTK_BOX (priv->main_box), +@@ -7530,22 +7551,26 @@ ev_window_init (EvWindow *ev_window) + gtk_widget_show (priv->search_bar); + + /* Add the main area */ +- priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL); +- g_signal_connect (priv->hpaned, +- "notify::position", +- G_CALLBACK (ev_window_sidebar_position_change_cb), +- ev_window); +- +- gtk_paned_set_position (GTK_PANED (priv->hpaned), SIDEBAR_DEFAULT_SIZE); +- gtk_box_pack_start (GTK_BOX (priv->main_box), priv->hpaned, ++ priv->flap = hdy_flap_new (); ++ hdy_flap_set_swipe_to_open (HDY_FLAP (priv->flap), FALSE); ++ hdy_flap_set_locked (HDY_FLAP (priv->flap), TRUE); ++ gtk_box_pack_start (GTK_BOX (priv->main_box), priv->flap, + TRUE, TRUE, 0); +- gtk_widget_show (priv->hpaned); ++ gtk_widget_show (priv->flap); ++ ++ priv->sidebar_stack = gtk_stack_new (); ++ hdy_flap_set_flap (HDY_FLAP (priv->flap), priv->sidebar_stack); ++ gtk_widget_set_size_request (priv->sidebar_stack, SIDEBAR_DEFAULT_SIZE, -1); ++ gtk_widget_set_hexpand (priv->sidebar_stack, FALSE); ++ gtk_widget_set_hexpand_set (priv->sidebar_stack, TRUE); ++ gtk_style_context_add_class (gtk_widget_get_style_context (priv->sidebar_stack), ++ "background"); ++ gtk_widget_show (priv->sidebar_stack); + + priv->sidebar = ev_sidebar_new (); + ev_sidebar_set_model (EV_SIDEBAR (priv->sidebar), + priv->model); +- gtk_paned_pack1 (GTK_PANED (priv->hpaned), +- priv->sidebar, FALSE, FALSE); ++ gtk_container_add (GTK_CONTAINER (priv->sidebar_stack), priv->sidebar); + gtk_widget_show (priv->sidebar); + + /* Stub sidebar, for now */ +@@ -7628,6 +7653,10 @@ ev_window_init (EvWindow *ev_window) + LAYERS_SIDEBAR_ID, _("Layers"), + LAYERS_SIDEBAR_ICON); + ++ separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL); ++ hdy_flap_set_separator (HDY_FLAP (priv->flap), separator); ++ gtk_widget_show (separator); ++ + priv->view_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + + overlay = gtk_overlay_new (); +@@ -7647,8 +7676,10 @@ ev_window_init (EvWindow *ev_window) + TRUE, TRUE, 0); + gtk_widget_show (overlay); + +- gtk_paned_add2 (GTK_PANED (priv->hpaned), +- priv->view_box); ++ hdy_flap_set_content (HDY_FLAP (priv->flap), priv->view_box); ++ hdy_flap_set_reveal_flap (HDY_FLAP (priv->flap), FALSE); ++ gtk_widget_set_size_request (priv->view_box, 360, -1); ++ gtk_widget_set_hexpand (priv->view_box, TRUE); + gtk_widget_show (priv->view_box); + + priv->view = ev_view_new (); +@@ -7734,6 +7765,8 @@ ev_window_init (EvWindow *ev_window) + "result-activated", + G_CALLBACK (find_sidebar_result_activated_cb), + ev_window); ++ gtk_container_add (GTK_CONTAINER (priv->sidebar_stack), priv->find_sidebar); ++ gtk_widget_show (priv->find_sidebar); + + /* We own a ref on these widgets, as we can swap them in and out */ + g_object_ref (priv->view); +@@ -7785,10 +7818,10 @@ ev_window_init (EvWindow *ev_window) + ev_window); + + /* Connect sidebar signals */ +- g_signal_connect (priv->sidebar, +- "notify::visible", +- G_CALLBACK (ev_window_sidebar_visibility_changed_cb), +- ev_window); ++ g_signal_connect_swapped (priv->flap, ++ "notify::reveal-flap", ++ G_CALLBACK (flap_reveal_changed_cb), ++ ev_window); + g_signal_connect (priv->sidebar, + "notify::current-page", + G_CALLBACK (ev_window_sidebar_current_page_changed_cb), +@@ -7969,5 +8002,5 @@ ev_window_set_divider_position (EvWindow *ev_window, + + priv = GET_PRIVATE (ev_window); + +- gtk_paned_set_position (GTK_PANED (priv->hpaned), sidebar_width); ++ gtk_widget_set_size_request (priv->sidebar_stack, sidebar_width, -1); + } diff --git a/evince-mobile/PKGBUILD b/evince-mobile/PKGBUILD new file mode 100644 index 0000000..777461e --- /dev/null +++ b/evince-mobile/PKGBUILD @@ -0,0 +1,93 @@ +# Maintainer: Danct12 +# Contributor: Kevin MacMartin +# Contributor: Jan Alexander Steffens (heftig) +# Contributor: Jan de Groot + +_pkgname=evince +pkgname=$_pkgname-mobile +pkgver=46.0 +pkgrel=1 +pkgdesc="Document viewer (PDF, PostScript, XPS, djvu, dvi, tiff, cbr, cbz, cb7, cbt)" +url="https://wiki.gnome.org/Apps/Evince" +arch=('x86_64' 'armv7h' 'aarch64') +license=('GPL-2.0-or-later') +depends=( + dconf + djvulibre + gnome-desktop + gsettings-desktop-schemas + gsfonts + gspell + gst-plugins-base-libs + gtk3 + gvfs + libarchive + libgxps + libhandy + libsecret + libspectre + libsynctex + libxml2 + poppler-glib +) +makedepends=( + appstream-glib + gi-docgen + git + gobject-introspection + meson + texlive-bin + yelp-tools +) +optdepends=('texlive-bin: DVI support') +provides=(libev{document,view}3.so $_pkgname) +conflicts=($_pkgname) +_commit=87a7a199c785e9b53279b2ba20134a341786ce3f # tags/46.0^0 +source=("git+https://gitlab.gnome.org/GNOME/evince.git#commit=$_commit" + '0001-toolbar-Allow-to-toggle-the-sidebar-button.patch' + '0002-toolbar-Allow-hiding-zoom-annotation-and-page-widgets.patch' + '0003-properties-view-Reduce-the-label-width-chars.patch' + '0004-window-Port-it-to-phones.patch') +sha256sums=('c1fb163ba552999714380c05d9189019f221b6de7b7554fb09d6dfbc74b5638d' + '22a5c037d60cce4869193a294f90c071dab2a47ff97f9632eb22ba0f8377b4a0' + '0153d21c3da3a65c28c246bc31a44b307c1af4e6e56f897b8e8ec15b92974df3' + 'b184beef8d11f3d1196869744865b94343b75440f326582e51cb7fb3f4beb176' + 'f125e441c0d5cc80599859347903f6b3e1d82cab25b30df508ed0bb6892c8a45') + +pkgver() { + cd $_pkgname + git describe --tags | sed 's/[^-]*-g/r&/;s/-/+/g' +} + +prepare() { + cd $_pkgname + + local src + for src in "${source[@]}"; do + src="${src%%::*}" + src="${src##*/}" + [[ $src = *.patch ]] || continue + echo "Applying patch $src..." + patch -Np1 < "../$src" + done +} + +build() { + local meson_options=( + -D ps=enabled + ) + + arch-meson $_pkgname build "${meson_options[@]}" + meson compile -C build +} + +check() { + meson test -C build --print-errorlogs +} + +package() { + meson install -C build --destdir "$pkgdir" + + # We don't need to provide evince-lib-docs. + rm -r "$pkgdir"/usr/share/doc/lib* +} diff --git a/feedbackd/PKGBUILD b/feedbackd/PKGBUILD new file mode 100644 index 0000000..2c5ebf3 --- /dev/null +++ b/feedbackd/PKGBUILD @@ -0,0 +1,41 @@ +# Maintainer: Danct12 +pkgname=feedbackd +pkgver=0.3.0 +pkgrel=1 +pkgdesc="A daemon to provide haptic, led and audio feedback triggered by application events" +url="https://source.puri.sm/Librem5/feedbackd" +arch=('x86_64' 'armv7h' 'aarch64') +license=('GPL-3.0-or-later AND LGPL-2.1-or-later') +depends=('gobject-introspection' 'gsound' 'json-glib' 'libgmobile' 'libgudev') +makedepends=('git' 'meson' 'vala') +_fbd_themes_name=feedbackd-device-themes +_fbd_themes_ver=0.1.0 +source=(https://source.puri.sm/Librem5/$pkgname/-/archive/v$pkgver/$pkgname-v$pkgver.tar.gz + https://source.puri.sm/Librem5/${_fbd_themes_name}/-/archive/v${_fbd_themes_ver}/${_fbd_themes_name}-v${_fbd_themes_ver}.tar.gz) + +build() { + arch-meson $pkgname-v${pkgver} output + ninja -C output +} + +check() { + ninja -C output test +} + +package() { + DESTDIR="$pkgdir" ninja -C output install + install -Dm644 "$srcdir"/$pkgname-v${pkgver}/debian/feedbackd.udev \ + "$pkgdir"/usr/lib/udev/rules.d/90-feedbackd.rules + sed -i 's/libexec/lib/g' "$pkgdir"/usr/lib/udev/rules.d/90-feedbackd.rules + + # FIXME: We aren't supposed to abuse video group, but we need to find a + # efficient way to add user to feedbackd group. + sed -i 's/-G feedbackd/-G video/g' "$pkgdir"/usr/lib/udev/rules.d/90-feedbackd.rules + + # It would make much more sense to bundle fbd device configuration with the pkg. + find ${srcdir}/${_fbd_themes_name}-v${_fbd_themes_ver}/data -name \*.json \ + -exec cp {} ${pkgdir}/usr/share/feedbackd/themes \; +} + +md5sums=('9203393ae6e2d9debdd58ec32a827a24' + 'bf51ba9cb3dbd19878781bd2544c4b02') diff --git a/gnome-calls/PKGBUILD b/gnome-calls/PKGBUILD new file mode 100644 index 0000000..79b97b5 --- /dev/null +++ b/gnome-calls/PKGBUILD @@ -0,0 +1,71 @@ +# Maintainer: Danct12 +pkgname=gnome-calls +pkgver=46.3 +pkgrel=1 +pkgdesc="Make and receive PSTN phone calls" +url="https://gitlab.gnome.org/GNOME/calls" +license=('GPL-3.0-or-later') +arch=('x86_64' 'armv7h' 'aarch64') +depends=( + 'callaudiod' + 'evolution-data-server' + 'feedbackd' + 'folks' + 'gobject-introspection' + 'gom' + 'gst-plugins-bad' + 'gst-plugins-good' + 'gtk3' + 'libhandy' + 'libpeas' + 'modemmanager' + 'sofia-sip' + 'wayland-protocols' + ) +makedepends=( + 'git' + 'glib2-devel' + 'meson' + 'ninja' + 'python-docutils' + 'python-packaging' + 'vala' + ) +checkdepends=('xorg-server-xvfb') +replaces=('calls') +_commit="f8c247148717bbad9414a9b246d88d1e685e68ed" # tags/v46.3 +source=("git+https://gitlab.gnome.org/GNOME/calls.git#commit=$_commit") +sha256sums=('4eddd4cbdd10c9f3f611573b05b5ce7275f1dab3f6ae1aeda9e4b2fc2ea2494b') + +pkgver() { + cd calls + git describe --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' +} + +prepare() { + cd calls + git submodule--helper update --init + + local src + for src in "${source[@]}"; do + src="${src%%::*}" + src="${src##*/}" + [[ $src = *.patch ]] || continue + echo "Applying patch $src..." + patch -Np1 < "../$src" + done +} + +build() { + arch-meson calls output + ninja -C output +} + +## SIP test hanging +#check() { +# xvfb-run ninja -C output test +#} + +package() { + DESTDIR="$pkgdir" ninja -C output install +} diff --git a/gnome-clocks-mobile/0001-timer-Use-name-that-can-be-added-to-the-event-naming.patch b/gnome-clocks-mobile/0001-timer-Use-name-that-can-be-added-to-the-event-naming.patch new file mode 100644 index 0000000..f70f277 --- /dev/null +++ b/gnome-clocks-mobile/0001-timer-Use-name-that-can-be-added-to-the-event-naming.patch @@ -0,0 +1,26 @@ +From 43940ccd1f5976b54fc39b0882512815cdf6a0c3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Guido=20G=C3=BCnther?= +Date: Mon, 24 Feb 2020 13:00:59 +0100 +Subject: [PATCH 01/16] timer: Use name that can be added to the event naming + spec + +--- + src/timer-face.vala | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/timer-face.vala b/src/timer-face.vala +index 5cad12f..8ee6732 100644 +--- a/src/timer-face.vala ++++ b/src/timer-face.vala +@@ -71,7 +71,7 @@ public class Face : Gtk.Stack, Clocks.Clock { + save (); + }); + +- bell = new Utils.Bell ("complete"); ++ bell = new Utils.Bell ("timeout-completed"); + notification = new GLib.Notification (_("Time is up!")); + notification.set_body (_("Timer countdown finished")); + notification.set_priority (HIGH); +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0002-Use-libfeedback-in-instead-of-GSound.patch b/gnome-clocks-mobile/0002-Use-libfeedback-in-instead-of-GSound.patch new file mode 100644 index 0000000..74ca953 --- /dev/null +++ b/gnome-clocks-mobile/0002-Use-libfeedback-in-instead-of-GSound.patch @@ -0,0 +1,151 @@ +From 91f0925ed8ffea4898840cd0c7e9c43c5487d2ca Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Guido=20G=C3=BCnther?= +Date: Sat, 22 Feb 2020 18:51:42 +0100 +Subject: [PATCH 02/16] Use libfeedback in instead of GSound + +This allows to use haptic (and later led) based +feedback on top of audio. +--- + meson.build | 2 +- + src/main.vala | 9 ++++++++- + src/meson.build | 3 ++- + src/utils.vala | 47 +++++++++++++++++++++-------------------------- + 4 files changed, 32 insertions(+), 29 deletions(-) + +diff --git a/meson.build b/meson.build +index 032f16d..a5ffc9b 100644 +--- a/meson.build ++++ b/meson.build +@@ -14,7 +14,7 @@ glib = dependency('glib-2.0', version: '>= 2.68') + gio = dependency('gio-2.0', version: '>= 2.58') + gobject = dependency('gobject-2.0', version: '>= 2.58') + gtk = dependency('gtk+-3.0', version: '>=3.20') +-gsound = dependency('gsound', version: '>=0.98') ++libfeedback = dependency('libfeedback-0.0', version: '>= 0.0.0') + gweather = dependency('gweather-3.0', version: '>=3.32.0') + gnomedesktop = dependency('gnome-desktop-3.0', version: '>=3.8') + geocodeglib = dependency('geocode-glib-1.0', version: '>=1.0') +diff --git a/src/main.vala b/src/main.vala +index 97d3350..905ef7f 100644 +--- a/src/main.vala ++++ b/src/main.vala +@@ -24,6 +24,13 @@ int main (string[] args) { + + Environment.set_application_name (_("Clocks")); + ++ try { ++ Lfb.init(Config.APP_ID); ++ } catch (GLib.Error e) { ++ warning ("Couldn't init libfeedback: %s", e.message); ++ } + var app = new Clocks.Application (); +- return app.run (args); ++ var ret = app.run (args); ++ Lfb.uninit(); ++ return ret; + } +diff --git a/src/meson.build b/src/meson.build +index 4c51188..e5b0edd 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -59,6 +59,7 @@ clocks_c_args = [ + '-include', 'config.h', + '-DGWEATHER_I_KNOW_THIS_IS_UNSTABLE', + '-DGNOME_DESKTOP_USE_UNSTABLE_API', ++ '-DLIBFEEDBACK_USE_UNSTABLE_API', + ] + + clocks_dependencies = [ +@@ -66,10 +67,10 @@ clocks_dependencies = [ + gio, + gobject, + gtk, +- gsound, + gweather, + gnomedesktop, + geocodeglib, ++ libfeedback, + libgeoclue, + libhandy, + math +diff --git a/src/utils.vala b/src/utils.vala +index d5594e7..1b38fba 100644 +--- a/src/utils.vala ++++ b/src/utils.vala +@@ -392,44 +392,31 @@ public class Weekdays { + } + + public class Bell : Object { +- private GSound.Context? gsound; + private GLib.Cancellable cancellable; ++ private Lfb.Event event; + private string soundtheme; +- private string sound; ++ private string eventname; + +- public Bell (string soundid) { +- try { +- gsound = new GSound.Context (); +- } catch (GLib.Error e) { +- warning ("Sound could not be initialized, error: %s", e.message); +- } +- +- var settings = new GLib.Settings ("org.gnome.desktop.sound"); ++ public Bell (string eventid) { ++ var settings = new GLib.Settings("org.gnome.desktop.sound"); + soundtheme = settings.get_string ("theme-name"); +- sound = soundid; +- cancellable = new GLib.Cancellable (); ++ eventname = eventid; ++ cancellable = new GLib.Cancellable(); + } + + private async void ring_real (bool repeat) { +- if (gsound == null) { ++ if (!Lfb.is_initted()) + return; +- } +- +- if (cancellable.is_cancelled ()) { +- cancellable.reset (); +- } + ++ event = new Lfb.Event (eventname); ++ if (repeat) ++ event.timeout = 0; + try { +- do { +- yield ((GSound.Context) gsound).play_full (cancellable, +- GSound.Attribute.EVENT_ID, sound, +- GSound.Attribute.CANBERRA_XDG_THEME_NAME, soundtheme, +- GSound.Attribute.MEDIA_ROLE, "alarm"); +- } while (repeat); ++ yield event.trigger_feedback_async (cancellable); + } catch (GLib.IOError.CANCELLED e) { + // ignore + } catch (GLib.Error e) { +- warning ("Error playing sound: %s", e.message); ++ warning ("Error triggering feedback for event %s: %s", eventname, e.message); + } + } + +@@ -442,7 +429,15 @@ public class Bell : Object { + } + + public void stop () { +- cancellable.cancel (); ++ event.end_feedback_async.begin (cancellable, (obj, res) => { ++ try { ++ event.end_feedback_async.end(res); ++ } catch (GLib.IOError.CANCELLED e) { ++ // ignore ++ } catch (GLib.Error e) { ++ warning ("Error ending feedback for event %s: %s", eventname, e.message); ++ } ++ }); + } + } + +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0003-timers-persist-running-timers.patch b/gnome-clocks-mobile/0003-timers-persist-running-timers.patch new file mode 100644 index 0000000..251eca2 --- /dev/null +++ b/gnome-clocks-mobile/0003-timers-persist-running-timers.patch @@ -0,0 +1,200 @@ +From 9a0a5995f58b07bd2a9aedbe34c712b07f801415 Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Thu, 26 Nov 2020 16:45:49 +0100 +Subject: [PATCH 03/16] timers: persist running timers + +Persist timer state between app starts by storing the remaining +time and the timestamp of when it was started. +--- + src/timer-face.vala | 2 ++ + src/timer-item.vala | 69 +++++++++++++++++++++++++++++++++++++-------- + src/timer-row.vala | 15 ++++++++-- + 3 files changed, 72 insertions(+), 14 deletions(-) + +diff --git a/src/timer-face.vala b/src/timer-face.vala +index 8ee6732..1e8e650 100644 +--- a/src/timer-face.vala ++++ b/src/timer-face.vala +@@ -56,6 +56,8 @@ public class Face : Gtk.Stack, Clocks.Clock { + ((Item)timer).ring.connect (() => ring ()); + ((Item)timer).notify["state"].connect (() => { + this.is_running = this.get_total_active_timers () != 0; ++ /* We need to save state changes */ ++ save (); + }); + return row; + }); +diff --git a/src/timer-item.vala b/src/timer-item.vala +index b226d83..e2a55a5 100644 +--- a/src/timer-item.vala ++++ b/src/timer-item.vala +@@ -41,6 +41,7 @@ public class Item : Object, ContentItem { + private int stored_minute; + private int stored_second; + ++ private GLib.DateTime? start_time; + + public signal void ring (); + public signal void countdown_updated (int hours, int minutes, int seconds); +@@ -52,6 +53,12 @@ public class Item : Object, ContentItem { + public void serialize (GLib.VariantBuilder builder) { + builder.open (new GLib.VariantType ("a{sv}")); + builder.add ("{sv}", "duration", new GLib.Variant.int32 (get_total_seconds ())); ++ if (span > 0) { ++ builder.add ("{sv}", "time_left", new GLib.Variant.int32 ((int32) Math.ceil (span))); ++ } ++ if (start_time != null) { ++ builder.add ("{sv}", "start_time", new GLib.Variant.int64 (((!) start_time).to_unix ())); ++ } + if (name != null) { + builder.add ("{sv}", "name", new GLib.Variant.string ((string) name)); + } +@@ -63,10 +70,18 @@ public class Item : Object, ContentItem { + Variant val; + int duration = 0; + string? name = null; ++ int span = 0; ++ GLib.DateTime? start_time = null; + + var iter = time_variant.iterator (); + while (iter.next ("{sv}", out key, out val)) { + switch (key) { ++ case "time_left": ++ span = (int32) val; ++ break; ++ case "start_time": ++ start_time = new GLib.DateTime.from_unix_local ((int64) val); ++ break; + case "duration": + duration = (int32) val; + break; +@@ -76,33 +91,63 @@ public class Item : Object, ContentItem { + } + } + +- return duration != 0 ? (Item?) new Item.from_seconds (duration, name) : null; ++ return duration != 0 ? (Item?) new Item.from_seconds (duration, name, start_time, (double) span) : null; + } + +- public Item.from_seconds (int seconds, string? name) { +- ++ public Item.from_seconds (int seconds, ++ string? name, ++ GLib.DateTime? start_time = null, ++ double time_left = 0) { + int rest = 0; + int h = seconds / 3600; + rest = seconds - h * 3600; + int m = rest / 60; + int s = rest - m * 60; + +- this (h, m, s, name); ++ this (h, m, s, name, start_time, time_left); + } + +- public Item (int h, int m, int s, string? name) { ++ public Item (int h, ++ int m, ++ int s, ++ string? name, ++ GLib.DateTime? start_time = null, ++ double time_left = 0) { + Object (name: name); + hours = h; + minutes = m; + seconds = s; + +- span = get_total_seconds (); + timer = new GLib.Timer (); + +- timeout_id = 0; ++ if (start_time != null) { ++ this.start_time = start_time; ++ start (); ++ } else if (time_left > 0) { ++ this.span = time_left; ++ state = State.PAUSED; ++ } ++ } ++ ++ public void update_countdown () { ++ int h, m, s; ++ if (state == State.STOPPED) { ++ countdown_updated (hours, minutes, seconds); ++ }else { ++ Utils.time_to_hms (span, out h, out m, out s, null); ++ countdown_updated (h, m, s); ++ } + } + + public virtual signal void start () { ++ if (start_time == null) { ++ start_time = new GLib.DateTime.now (); ++ if (span == 0) ++ span = get_total_seconds (); ++ } else { ++ span = get_total_seconds () - new GLib.DateTime.now ().difference ((!) start_time) / TimeSpan.SECOND; ++ } ++ + state = State.RUNNING; + timeout_id = GLib.Timeout.add (100, () => { + var e = timer.elapsed (); +@@ -134,16 +179,18 @@ public class Item : Object, ContentItem { + } + + public virtual signal void pause () { +- state = State.PAUSED; ++ start_time = null; + span -= timer.elapsed (); + timer.stop (); ++ state = State.PAUSED; + } + + public virtual signal void reset () { +- state = State.STOPPED; +- span = get_total_seconds (); ++ start_time = null; ++ span = 0; + timer.reset (); +- timeout_id = 0; ++ state = State.STOPPED; ++ update_countdown (); + } + } + +diff --git a/src/timer-row.vala b/src/timer-row.vala +index bec09e7..b5d7302 100644 +--- a/src/timer-row.vala ++++ b/src/timer-row.vala +@@ -78,7 +78,18 @@ public class Row : Gtk.ListBoxRow { + item.reset.connect (() => this.reset ()); + delete_button.clicked.connect (() => deleted ()); + +- reset (); ++ item.update_countdown (); ++ switch (item.state) { ++ case STOPPED: ++ reset (); ++ break; ++ case RUNNING: ++ this.start (); ++ break; ++ case PAUSED: ++ this.pause (); ++ break; ++ } + } + + [GtkCallback] +@@ -105,8 +116,6 @@ public class Row : Gtk.ListBoxRow { + countdown_label.get_style_context ().remove_class ("timer-running"); + start_stack.visible_child_name = "start"; + name_stack.visible_child_name = "edit"; +- +- update_countdown (item.hours, item.minutes, item.seconds); + } + + private void start () { +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0004-alarm-item-Make-sure-that-the-time-property-is-alway.patch b/gnome-clocks-mobile/0004-alarm-item-Make-sure-that-the-time-property-is-alway.patch new file mode 100644 index 0000000..8c42e73 --- /dev/null +++ b/gnome-clocks-mobile/0004-alarm-item-Make-sure-that-the-time-property-is-alway.patch @@ -0,0 +1,215 @@ +From e06420480258cda94e20b482529c788efab83a2f Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Thu, 12 Nov 2020 13:38:07 +0100 +Subject: [PATCH 04/16] alarm-item: Make sure that the time property is always + set + +The time property for an AlarmItem isn't nullable therefore it needs to +be set during construction. +--- + src/alarm-face.vala | 18 +++++++---- + src/alarm-item.vala | 12 ++++---- + src/alarm-setup-dialog.vala | 59 +++++++++++-------------------------- + 3 files changed, 36 insertions(+), 53 deletions(-) + +diff --git a/src/alarm-face.vala b/src/alarm-face.vala +index 0fe77cb..cf9a592 100644 +--- a/src/alarm-face.vala ++++ b/src/alarm-face.vala +@@ -108,7 +108,7 @@ public class Face : Gtk.Stack, Clocks.Clock { + } + + internal void edit (Item alarm) { +- var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), alarm, alarms); ++ var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), alarm, alarms, true); + + // Disable alarm while editing it and remember the original active state. + alarm.editing = true; +@@ -116,7 +116,7 @@ public class Face : Gtk.Stack, Clocks.Clock { + dialog.response.connect ((dialog, response) => { + alarm.editing = false; + if (response == Gtk.ResponseType.OK) { +- ((SetupDialog) dialog).apply_to_alarm (alarm); ++ ((SetupDialog) dialog).apply_to_alarm (); + save (); + } else if (response == DELETE_ALARM) { + alarms.delete_item (alarm); +@@ -137,11 +137,19 @@ public class Face : Gtk.Stack, Clocks.Clock { + } + + public void activate_new () { +- var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), null, alarms); ++ var wc = Utils.WallClock.get_default (); ++ var alarm = new Item ({ wc.date_time.get_hour (), wc.date_time.get_minute () }, false); ++ var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), alarm, alarms); ++ ++ // Disable alarm while editing it and remember the original active state. ++ alarm.editing = true; ++ + dialog.response.connect ((dialog, response) => { ++ alarm.editing = false; ++ // Enable the newly created alarm ++ alarm.active = true; + if (response == Gtk.ResponseType.OK) { +- var alarm = new Item (); +- ((SetupDialog) dialog).apply_to_alarm (alarm); ++ ((SetupDialog) dialog).apply_to_alarm (); + alarms.add (alarm); + save (); + } +diff --git a/src/alarm-item.vala b/src/alarm-item.vala +index 6103342..26f655f 100644 +--- a/src/alarm-item.vala ++++ b/src/alarm-item.vala +@@ -104,9 +104,12 @@ private class Item : Object, ContentItem { + private Utils.Bell bell; + private GLib.Notification notification; + +- public Item (string? id = null) { ++ public Item (AlarmTime time, bool active = true, Utils.Weekdays? days = null, string? id = null) { + var guid = id != null ? (string) id : GLib.DBus.generate_guid (); +- Object (id: guid); ++ Object (id: guid, ++ active: active, ++ time: time, ++ days: days); + } + + private void setup_bell () { +@@ -271,11 +274,8 @@ private class Item : Object, ContentItem { + } + + if (hour >= 0 && minute >= 0) { +- Item alarm = new Item (id); ++ Item alarm = new Item ({ hour, minute }, active, days, id); + alarm.name = name; +- alarm.active = active; +- alarm.time = { hour, minute }; +- alarm.days = days; + alarm.ring_minutes = ring_minutes; + alarm.snooze_minutes = snooze_minutes; + alarm.reset (); +diff --git a/src/alarm-setup-dialog.vala b/src/alarm-setup-dialog.vala +index 97cde1f..d20ec61 100644 +--- a/src/alarm-setup-dialog.vala ++++ b/src/alarm-setup-dialog.vala +@@ -75,6 +75,7 @@ private class DurationModel : ListModel, Object { + [GtkTemplate (ui = "/org/gnome/clocks/ui/alarm-setup-dialog.ui")] + private class SetupDialog : Gtk.Dialog { + private Utils.WallClock.Format format; ++ public Item alarm { get; set; } + [GtkChild] + private unowned Gtk.Grid time_grid; + [GtkChild] +@@ -103,20 +104,21 @@ private class SetupDialog : Gtk.Dialog { + typeof (DayPickerRow).ensure (); + } + +- public SetupDialog (Gtk.Window parent, Item? alarm, ListModel all_alarms) { ++ public SetupDialog (Gtk.Window parent, Item alarm, ListModel all_alarms, bool edit_alarm = false) { + Object (transient_for: parent, +- title: alarm != null ? _("Edit Alarm") : _("New Alarm"), ++ alarm: alarm, ++ title: edit_alarm ? _("Edit Alarm") : _("New Alarm"), + use_header_bar: 1); + + add_button (_("Cancel"), Gtk.ResponseType.CANCEL); +- if (alarm != null) { ++ if (edit_alarm) { + add_button (_("Done"), Gtk.ResponseType.OK); + } else { + add_button (_("Add"), Gtk.ResponseType.OK); + } + set_default_response (Gtk.ResponseType.OK); + +- delete_button.visible = alarm != null; ++ delete_button.visible = edit_alarm; + + other_alarms = new List (); + var n = all_alarms.get_n_items (); +@@ -158,39 +160,13 @@ private class SetupDialog : Gtk.Dialog { + am_pm_stack.visible_child = am_pm_button; + } + +- set_from_alarm (alarm); ++ set_from_alarm (); + } + + // Sets up the dialog to show the values of alarm. +- public void set_from_alarm (Item? alarm) { +- string? name; +- bool active; +- int hour; +- int minute; +- int snooze_minutes; +- int ring_minutes; +- unowned Utils.Weekdays? days; +- +- if (alarm == null) { +- var wc = Utils.WallClock.get_default (); +- // Not great but we can't null it +- name = ""; +- hour = wc.date_time.get_hour (); +- minute = wc.date_time.get_minute (); +- days = null; +- active = true; +- ring_minutes = 5; +- snooze_minutes = 10; +- } else { +- name = ((Item) alarm).name; +- hour = ((Item) alarm).time.hour; +- minute = ((Item) alarm).time.minute; +- days = ((Item) alarm).days; +- active = ((Item) alarm).active; +- ring_minutes = ((Item) alarm).ring_minutes; +- snooze_minutes = ((Item) alarm).snooze_minutes; +- } +- ++ public void set_from_alarm () { ++ var hour = alarm.time.hour; ++ var minute = alarm.time.minute; + // Set the time. + if (format == Utils.WallClock.Format.TWELVE) { + if (hour < 12) { +@@ -204,22 +180,22 @@ private class SetupDialog : Gtk.Dialog { + hour = 12; + } + } +- ring_duration.set_selected_index (duration_model.find_by_duration (ring_minutes)); +- snooze_duration.set_selected_index (duration_model.find_by_duration (snooze_minutes)); ++ ring_duration.set_selected_index (duration_model.find_by_duration (alarm.ring_minutes)); ++ snooze_duration.set_selected_index (duration_model.find_by_duration (alarm.snooze_minutes)); + + h_spinbutton.set_value (hour); + m_spinbutton.set_value (minute); + + // Set the name. +- name_entry.set_text ((string) name); ++ name_entry.set_text ((string) alarm.name); + +- if (days != null) { +- repeats.load ((Utils.Weekdays) days); ++ if (alarm.days != null) { ++ repeats.load ((Utils.Weekdays) alarm.days); + } + } + + // Sets alarm according to the current dialog settings. +- public void apply_to_alarm (Item alarm) { ++ public void apply_to_alarm () { + var name = name_entry.get_text (); + var hour = h_spinbutton.get_value_as_int (); + var minute = m_spinbutton.get_value_as_int (); +@@ -254,8 +230,7 @@ private class SetupDialog : Gtk.Dialog { + } + + private void avoid_duplicate_alarm () { +- var alarm = new Item (); +- apply_to_alarm (alarm); ++ apply_to_alarm (); + + var duplicate = alarm.check_duplicate_alarm (other_alarms); + this.set_response_sensitive (Gtk.ResponseType.OK, !duplicate); +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0005-alarm-remove-edit-property.patch b/gnome-clocks-mobile/0005-alarm-remove-edit-property.patch new file mode 100644 index 0000000..387fb3a --- /dev/null +++ b/gnome-clocks-mobile/0005-alarm-remove-edit-property.patch @@ -0,0 +1,64 @@ +From 329dcc1fdc1b620228457fe1544b62661698a044 Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Mon, 16 Nov 2020 11:36:29 +0100 +Subject: [PATCH 05/16] alarm: remove edit property + +--- + src/alarm-face.vala | 8 -------- + src/alarm-item.vala | 5 +++-- + 2 files changed, 3 insertions(+), 10 deletions(-) + +diff --git a/src/alarm-face.vala b/src/alarm-face.vala +index cf9a592..9cf1207 100644 +--- a/src/alarm-face.vala ++++ b/src/alarm-face.vala +@@ -110,11 +110,7 @@ public class Face : Gtk.Stack, Clocks.Clock { + internal void edit (Item alarm) { + var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), alarm, alarms, true); + +- // Disable alarm while editing it and remember the original active state. +- alarm.editing = true; +- + dialog.response.connect ((dialog, response) => { +- alarm.editing = false; + if (response == Gtk.ResponseType.OK) { + ((SetupDialog) dialog).apply_to_alarm (); + save (); +@@ -141,11 +137,7 @@ public class Face : Gtk.Stack, Clocks.Clock { + var alarm = new Item ({ wc.date_time.get_hour (), wc.date_time.get_minute () }, false); + var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), alarm, alarms); + +- // Disable alarm while editing it and remember the original active state. +- alarm.editing = true; +- + dialog.response.connect ((dialog, response) => { +- alarm.editing = false; + // Enable the newly created alarm + alarm.active = true; + if (response == Gtk.ResponseType.OK) { +diff --git a/src/alarm-item.vala b/src/alarm-item.vala +index 26f655f..9febf63 100644 +--- a/src/alarm-item.vala ++++ b/src/alarm-item.vala +@@ -34,7 +34,8 @@ private class Item : Object, ContentItem { + SNOOZING + } + +- public bool editing { get; set; default = false; } ++ // Missed can't be a state because we couldn't scheduale next alarms without override missed ++ public bool missed { get; set; default = false; } + + public string id { get; construct set; } + +@@ -184,7 +185,7 @@ private class Item : Object, ContentItem { + } + + private bool compare_with_item (Item i) { +- return (this.alarm_time.compare (i.alarm_time) == 0 && (this.active || this.editing) && i.active); ++ return (this.time.compare (i.time) == 0); + } + + public bool check_duplicate_alarm (List alarms) { +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0006-alarms-Make-alarms-persisted-and-add-missed-alarms-n.patch b/gnome-clocks-mobile/0006-alarms-Make-alarms-persisted-and-add-missed-alarms-n.patch new file mode 100644 index 0000000..74f478a --- /dev/null +++ b/gnome-clocks-mobile/0006-alarms-Make-alarms-persisted-and-add-missed-alarms-n.patch @@ -0,0 +1,504 @@ +From e8584352c152fc891fa82a0d3fceb1810cc6f4e0 Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Fri, 13 Nov 2020 17:59:06 +0100 +Subject: [PATCH 06/16] alarms: Make alarms persisted and add missed alarms + notation + +This stores the alarm state as well as the alarm and snooze time +to gsettings. This alllows us to tell the user about missed alarms. +A user could miss alarms for two reasons: + - Clocks wasn't running when the alarm went of. + - The user didn't stop the alarm within "ring-time" + +This also adds the baseline for starting Clocks via systemd user .timer +units by making Clocks checks at startup if any alarms need to go off. + +As a side effect: closing Clocks doesn't stop an alarm and when Clocks +is reopend within "ring-time" after an alarm or snooze the alarm starts +ringing again. +--- + src/alarm-face.vala | 5 +- + src/alarm-item.vala | 218 +++++++++++++++++++++++------------- + src/alarm-setup-dialog.vala | 12 +- + src/application.vala | 5 +- + src/window.vala | 3 + + 5 files changed, 156 insertions(+), 87 deletions(-) + +diff --git a/src/alarm-face.vala b/src/alarm-face.vala +index 9cf1207..8654e76 100644 +--- a/src/alarm-face.vala ++++ b/src/alarm-face.vala +@@ -66,7 +66,7 @@ public class Face : Gtk.Stack, Clocks.Clock { + }); + + listbox.bind_model (alarms, (item) => { +- item.notify["active"].connect (save); ++ item.notify["state"].connect (save); + return new Row ((Item) item, this); + }); + +@@ -134,12 +134,13 @@ public class Face : Gtk.Stack, Clocks.Clock { + + public void activate_new () { + var wc = Utils.WallClock.get_default (); +- var alarm = new Item ({ wc.date_time.get_hour (), wc.date_time.get_minute () }, false); ++ var alarm = new Item (wc.date_time.get_hour (), wc.date_time.get_minute ()); + var dialog = new SetupDialog ((Gtk.Window) get_toplevel (), alarm, alarms); + + dialog.response.connect ((dialog, response) => { + // Enable the newly created alarm + alarm.active = true; ++ + if (response == Gtk.ResponseType.OK) { + ((SetupDialog) dialog).apply_to_alarm (); + alarms.add (alarm); +diff --git a/src/alarm-item.vala b/src/alarm-item.vala +index 9febf63..ab9ca9b 100644 +--- a/src/alarm-item.vala ++++ b/src/alarm-item.vala +@@ -20,15 +20,9 @@ + namespace Clocks { + namespace Alarm { + +-private struct AlarmTime { +- public int hour; +- public int minute; +-} +- + private class Item : Object, ContentItem { +- // FIXME: should we add a "MISSED" state where the alarm stopped +- // ringing but we keep showing the ringing panel? + public enum State { ++ DISABLED, + READY, + RINGING, + SNOOZING +@@ -43,6 +37,12 @@ private class Item : Object, ContentItem { + + public int ring_minutes { get; set; default = 5; } + ++ public bool recurring { ++ get { ++ return days != null && !((!) days).empty; ++ } ++ } ++ + public string? name { + get { + return _name; +@@ -54,21 +54,34 @@ private class Item : Object, ContentItem { + } + } + +- public AlarmTime time { get; set; } +- + public Utils.Weekdays? days { get; set; } + +- public State state { get; private set; } ++ private State _state = State.DISABLED; ++ public State state { ++ get { ++ return _state; ++ } ++ private set { ++ if (_state == value) ++ return; ++ ++ _state = value; ++ notify_property ("active"); ++ } ++ } + + public string time_label { + owned get { +- return Utils.WallClock.get_default ().format_time (alarm_time); ++ return Utils.WallClock.get_default ().format_time (time); + } + } + + public string snooze_time_label { + owned get { +- return Utils.WallClock.get_default ().format_time (snooze_time); ++ if (snooze_time == null) ++ return Utils.WallClock.get_default ().format_time (time.add_minutes (snooze_minutes)); ++ else ++ return Utils.WallClock.get_default ().format_time ((!) snooze_time); + } + } + +@@ -78,37 +91,43 @@ private class Item : Object, ContentItem { + } + } + ++ public GLib.DateTime time { get; set; } ++ + [CCode (notify = false)] + public bool active { + get { +- return _active && !this.editing; ++ return this.state > State.DISABLED; + } +- + set { +- if (value != _active) { +- _active = value; +- if (_active) { +- reset (); +- } else if (state == State.RINGING) { +- stop (); +- } ++ if (this.state != State.DISABLED && !value) { ++ stop (); ++ this.state = State.DISABLED; ++ notify_property ("active"); ++ } else if (this.state == State.DISABLED && value) { ++ this.missed = false; ++ this.time = get_next_alarm_time (time.get_hour (), time.get_minute (), days); ++ this.state = State.READY; + notify_property ("active"); + } + } + } + + private string _name; +- private bool _active = true; +- private GLib.DateTime alarm_time; +- private GLib.DateTime snooze_time; +- private GLib.DateTime ring_end_time; ++ private GLib.DateTime? snooze_time; + private Utils.Bell bell; + private GLib.Notification notification; + +- public Item (AlarmTime time, bool active = true, Utils.Weekdays? days = null, string? id = null) { ++ public Item (int hour, int minute, Utils.Weekdays? days = null, string? id = null) { ++ var guid = id != null ? (string) id : GLib.DBus.generate_guid (); ++ var time = get_next_alarm_time (hour, minute, days); ++ Object (id: guid, ++ time: time, ++ days: days); ++ } ++ ++ public Item.for_specific_time (GLib.DateTime time, Utils.Weekdays? days = null, string? id = null) { + var guid = id != null ? (string) id : GLib.DBus.generate_guid (); + Object (id: guid, +- active: active, + time: time, + days: days); + } +@@ -122,24 +141,39 @@ private class Item : Object, ContentItem { + notification.add_button (_("Snooze"), "app.snooze-alarm::".concat (id)); + } + +- public void reset () { +- update_alarm_time (); +- update_snooze_time (alarm_time); +- state = State.READY; ++ private void show_missed_notification () { ++ var app = (Clocks.Application) GLib.Application.get_default (); ++ var notification = new GLib.Notification (_("Missed alarm")); ++ string label; ++ if (name != null && ((!) name).length > 0) { ++ // Translators: The first %s is the time and the second %s is the title ++ label = _("%s: %s").printf (time_label, (!) name); ++ } else { ++ // Translators: %s is a time ++ label = _("%s").printf (time_label); ++ } ++ ++ notification.set_body (label); ++ app.send_notification ("alarm-clock-missed", notification); ++ } ++ ++ public void set_alarm_time (int hour, int minute, Utils.Weekdays? days) { ++ this.days = days; ++ this.time = get_next_alarm_time (hour, minute, days); + } + +- private void update_alarm_time () { ++ private static GLib.DateTime get_next_alarm_time (int hour, int minute, Utils.Weekdays? days) { + var wallclock = Utils.WallClock.get_default (); + var now = wallclock.date_time; + var dt = new GLib.DateTime (wallclock.timezone, + now.get_year (), + now.get_month (), + now.get_day_of_month (), +- time.hour, +- time.minute, ++ hour, ++ minute, + 0); + +- if (days == null || ((Utils.Weekdays) days).empty) { ++ if (days == null || ((!) days).empty) { + // Alarm without days. + if (dt.compare (now) <= 0) { + // Time already passed, ring tomorrow. +@@ -148,16 +182,13 @@ private class Item : Object, ContentItem { + } else { + // Alarm with at least one day set. + // Find the next possible day for ringing +- while (dt.compare (now) <= 0 || ! ((Utils.Weekdays) days).get ((Utils.Weekdays.Day) (dt.get_day_of_week () - 1))) { ++ while (dt.compare (now) <= 0 || ++ ! ((Utils.Weekdays) days).get ((Utils.Weekdays.Day) (dt.get_day_of_week () - 1))) { + dt = dt.add_days (1); + } + } + +- alarm_time = dt; +- } +- +- private void update_snooze_time (GLib.DateTime start_time) { +- snooze_time = start_time.add_minutes (snooze_minutes); ++ return dt; + } + + public virtual signal void ring () { +@@ -167,30 +198,43 @@ private class Item : Object, ContentItem { + } + + private void start_ringing (GLib.DateTime now) { +- update_snooze_time (now); +- ring_end_time = now.add_minutes (ring_minutes); + state = State.RINGING; + ring (); + } + + public void snooze () { + bell.stop (); ++ if (snooze_time == null) ++ snooze_time = time.add_minutes (snooze_minutes); ++ else ++ snooze_time = ((!) snooze_time).add_minutes (snooze_minutes); ++ + state = State.SNOOZING; + } + + public void stop () { + bell.stop (); +- update_snooze_time (alarm_time); +- state = State.READY; ++ snooze_time = null; ++ ++ // scheduale the next alarm if recurring ++ if (recurring) { ++ time = get_next_alarm_time (time.get_hour (), time.get_minute (), days); ++ state = State.READY; ++ GLib.Timeout.add_seconds (120, () => { ++ missed = false; ++ return GLib.Source.REMOVE; ++ }); ++ } else { ++ state = State.DISABLED; ++ } + } + + private bool compare_with_item (Item i) { +- return (this.time.compare (i.time) == 0); ++ return (this.time.get_hour () == i.time.get_hour () && ++ this.time.get_minute () == i.time.get_minute ()); + } + + public bool check_duplicate_alarm (List alarms) { +- update_alarm_time (); +- + foreach (var item in alarms) { + if (this.compare_with_item (item)) { + return true; +@@ -199,11 +243,21 @@ private class Item : Object, ContentItem { + return false; + } + ++ private void start_ringing_or_missed (GLib.DateTime now, GLib.DateTime ring_end_time) { ++ if (now.compare (ring_end_time) > 0 ) { ++ missed = true; ++ show_missed_notification (); ++ stop (); ++ } else { ++ start_ringing (now); ++ } ++ } ++ + // Update the state and ringing time. Ring or stop + // depending on the current time. + // Returns true if the state changed, false otherwise. + public bool tick () { +- if (!active) { ++ if (state == State.DISABLED) { + return false; + } + +@@ -212,17 +266,28 @@ private class Item : Object, ContentItem { + var wallclock = Utils.WallClock.get_default (); + var now = wallclock.date_time; + +- if (state == State.RINGING && now.compare (ring_end_time) > 0) { +- stop (); +- } +- +- if (state == State.SNOOZING && now.compare (snooze_time) > 0) { +- start_ringing (now); +- } +- +- if (state == State.READY && now.compare (alarm_time) > 0) { +- start_ringing (now); +- update_alarm_time (); // reschedule for the next repeat ++ GLib.DateTime ring_end_time; ++ if (snooze_time != null) ++ ring_end_time = ((!) snooze_time).add_minutes (ring_minutes); ++ else ++ ring_end_time = time.add_minutes (ring_minutes); ++ ++ switch (state) { ++ case State.DISABLED: ++ break; ++ case State.RINGING: ++ // make sure the state changes ++ last_state = State.READY; ++ start_ringing_or_missed (now, ring_end_time); ++ break; ++ case State.SNOOZING: ++ if (snooze_time != null && now.compare ((!) snooze_time) > 0) ++ start_ringing_or_missed (now, ring_end_time); ++ break; ++ case State.READY: ++ if (now.compare (time) > 0) ++ start_ringing_or_missed (now, ring_end_time); ++ break; + } + + return state != last_state; +@@ -232,9 +297,10 @@ private class Item : Object, ContentItem { + builder.open (new GLib.VariantType ("a{sv}")); + builder.add ("{sv}", "name", new GLib.Variant.string ((string) name)); + builder.add ("{sv}", "id", new GLib.Variant.string (id)); +- builder.add ("{sv}", "active", new GLib.Variant.boolean (active)); +- builder.add ("{sv}", "hour", new GLib.Variant.int32 (time.hour)); +- builder.add ("{sv}", "minute", new GLib.Variant.int32 (time.minute)); ++ builder.add ("{sv}", "state", new GLib.Variant.int32 (state)); ++ builder.add ("{sv}", "time", new GLib.Variant.int64 (time.to_unix ())); ++ if (snooze_time != null) ++ builder.add ("{sv}", "snooze_time", new GLib.Variant.int64 (((!) snooze_time).to_unix ())); + builder.add ("{sv}", "days", ((Utils.Weekdays) days).serialize ()); + builder.add ("{sv}", "snooze_minutes", new GLib.Variant.int32 (snooze_minutes)); + builder.add ("{sv}", "ring_minutes", new GLib.Variant.int32 (ring_minutes)); +@@ -246,9 +312,9 @@ private class Item : Object, ContentItem { + Variant val; + string? name = null; + string? id = null; +- bool active = true; +- int hour = -1; +- int minute = -1; ++ State state = State.DISABLED; ++ GLib.DateTime? time = null; ++ GLib.DateTime? snooze_time = null; + int snooze_minutes = 10; + int ring_minutes = 5; + Utils.Weekdays? days = null; +@@ -259,12 +325,12 @@ private class Item : Object, ContentItem { + name = (string) val; + } else if (key == "id") { + id = (string) val; +- } else if (key == "active") { +- active = (bool) val; +- } else if (key == "hour") { +- hour = (int32) val; +- } else if (key == "minute") { +- minute = (int32) val; ++ } else if (key == "state") { ++ state = (State) val; ++ } else if (key == "time") { ++ time = new GLib.DateTime.from_unix_local ((int64) val); ++ } else if (key == "snooze_time") { ++ snooze_time = new GLib.DateTime.from_unix_local ((int64) val); + } else if (key == "days") { + days = Utils.Weekdays.deserialize (val); + } else if (key == "snooze_minutes") { +@@ -274,12 +340,14 @@ private class Item : Object, ContentItem { + } + } + +- if (hour >= 0 && minute >= 0) { +- Item alarm = new Item ({ hour, minute }, active, days, id); ++ if (time != null) { ++ Item alarm = new Item.for_specific_time ((!) time, days, id); ++ alarm.state = state; + alarm.name = name; ++ if (snooze_time != null) ++ alarm.snooze_time = (!) snooze_time; + alarm.ring_minutes = ring_minutes; + alarm.snooze_minutes = snooze_minutes; +- alarm.reset (); + return alarm; + } else { + warning ("Invalid alarm %s", name != null ? (string) name : "[unnamed]"); +diff --git a/src/alarm-setup-dialog.vala b/src/alarm-setup-dialog.vala +index d20ec61..2d826d0 100644 +--- a/src/alarm-setup-dialog.vala ++++ b/src/alarm-setup-dialog.vala +@@ -165,8 +165,8 @@ private class SetupDialog : Gtk.Dialog { + + // Sets up the dialog to show the values of alarm. + public void set_from_alarm () { +- var hour = alarm.time.hour; +- var minute = alarm.time.minute; ++ var hour = alarm.time.get_hour (); ++ var minute = alarm.time.get_minute (); + // Set the time. + if (format == Utils.WallClock.Format.TWELVE) { + if (hour < 12) { +@@ -211,21 +211,15 @@ private class SetupDialog : Gtk.Dialog { + } + } + +- AlarmTime time = { hour, minute }; +- + var days = repeats.store (); + + alarm.freeze_notify (); + + alarm.name = name; +- alarm.time = time; +- alarm.days = days; ++ alarm.set_alarm_time (hour, minute, days); + alarm.snooze_minutes = snooze_item.minutes; + alarm.ring_minutes = ring_item.minutes; + +- // Force update of alarm_time before notifying the changes +- alarm.reset (); +- + alarm.thaw_notify (); + } + +diff --git a/src/application.vala b/src/application.vala +index 2e67046..92aba34 100644 +--- a/src/application.vala ++++ b/src/application.vala +@@ -170,7 +170,10 @@ public class Application : Gtk.Application { + public new void send_notification (string notification_id, GLib.Notification notification) { + base.send_notification (notification_id, notification); + +- system_notifications.append (notification_id); ++ // We don't want to withdraw missed notifications ++ if (notification_id != "alarm-clock-missed") { ++ system_notifications.append (notification_id); ++ } + } + + private void withdraw_notifications () { +diff --git a/src/window.vala b/src/window.vala +index 55c7f2e..5c35967 100644 +--- a/src/window.vala ++++ b/src/window.vala +@@ -158,6 +158,9 @@ public class Window : Hdy.ApplicationWindow { + if (Config.PROFILE == "Devel") { + style.add_class ("devel"); + } ++ ++ // Immidiatly check if we need to notifiy the user about alarms ++ Utils.WallClock.get_default ().tick (); + } + + [Signal (action = true)] +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0007-Fixed-infinite-alarming.patch b/gnome-clocks-mobile/0007-Fixed-infinite-alarming.patch new file mode 100644 index 0000000..7e5ffcd --- /dev/null +++ b/gnome-clocks-mobile/0007-Fixed-infinite-alarming.patch @@ -0,0 +1,36 @@ +From b5b5ad980f72d2b7622d311f31fda5695f49ed8e Mon Sep 17 00:00:00 2001 +From: Steve Stevens +Date: Sun, 9 Jan 2022 12:06:47 -0700 +Subject: [PATCH 07/16] Fixed infinite alarming + +This issue is caused by the start_ringing() function being called every time +the tick() function is called. Thus causing multiple rings to start happening +if an alarm isn't stopped soon enough all from the same alarm. + +Origin: https://gitlab.gnome.org/GNOME/gnome-clocks/-/merge_requests/185 +Dependancy: alarms-Make-alarms-persisted-and-add-missed-alarms-n.patch +Applied-Upstream: False +--- + src/alarm-item.vala | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/alarm-item.vala b/src/alarm-item.vala +index ab9ca9b..6dcb73d 100644 +--- a/src/alarm-item.vala ++++ b/src/alarm-item.vala +@@ -198,8 +198,10 @@ private class Item : Object, ContentItem { + } + + private void start_ringing (GLib.DateTime now) { +- state = State.RINGING; +- ring (); ++ if ( state != State.RINGING ) { ++ state = State.RINGING; ++ ring (); ++ } + } + + public void snooze () { +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0008-Alarms-Fix-wiping-edit-data.patch b/gnome-clocks-mobile/0008-Alarms-Fix-wiping-edit-data.patch new file mode 100644 index 0000000..82ca5bc --- /dev/null +++ b/gnome-clocks-mobile/0008-Alarms-Fix-wiping-edit-data.patch @@ -0,0 +1,50 @@ +From bd2fce71df6d3eab84486a445f38e5ed38828f79 Mon Sep 17 00:00:00 2001 +From: Steve Stevens +Date: Sun, 9 Jan 2022 12:07:43 -0700 +Subject: [PATCH 08/16] Alarms: Fix wiping edit data + +The notifies called when setting up the alarm-setup-dialog would cause +the alarm item to be nulled out when attempting to update the alarm with +the data. Thus this patch suspends those notify actions until the +initial setup of the dialog is complete. + +Dependancy: alarms-Make-alarms-persisted-and-add-missed-alarms-n.patch +Applied-Upstream: False +--- + src/alarm-setup-dialog.vala | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/alarm-setup-dialog.vala b/src/alarm-setup-dialog.vala +index 2d826d0..85c9d06 100644 +--- a/src/alarm-setup-dialog.vala ++++ b/src/alarm-setup-dialog.vala +@@ -99,6 +99,7 @@ private class SetupDialog : Gtk.Dialog { + private unowned Gtk.Button delete_button; + private List other_alarms; + private DurationModel duration_model; ++ private bool lock_notify = true; + + static construct { + typeof (DayPickerRow).ensure (); +@@ -192,6 +193,8 @@ private class SetupDialog : Gtk.Dialog { + if (alarm.days != null) { + repeats.load ((Utils.Weekdays) alarm.days); + } ++ lock_notify = false; ++ avoid_duplicate_alarm (); + } + + // Sets alarm according to the current dialog settings. +@@ -224,6 +227,9 @@ private class SetupDialog : Gtk.Dialog { + } + + private void avoid_duplicate_alarm () { ++ if (lock_notify) { ++ return; ++ } + apply_to_alarm (); + + var duplicate = alarm.check_duplicate_alarm (other_alarms); +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0009-Don-t-show-numpad-when-setting-a-new-alarm-timer.patch b/gnome-clocks-mobile/0009-Don-t-show-numpad-when-setting-a-new-alarm-timer.patch new file mode 100644 index 0000000..7c38c07 --- /dev/null +++ b/gnome-clocks-mobile/0009-Don-t-show-numpad-when-setting-a-new-alarm-timer.patch @@ -0,0 +1,44 @@ +From 7f0a060e316ceb9e123ec71d74c7a7502d5dfc1b Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Wed, 2 Dec 2020 16:57:31 +0100 +Subject: [PATCH 09/16] Don't show numpad when setting a new alarm/timer + +Fixes https://source.puri.sm/Librem5/gnome-clocks/-/issues/26 +--- + src/alarm-setup-dialog.vala | 4 ++++ + src/timer-setup.vala | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/src/alarm-setup-dialog.vala b/src/alarm-setup-dialog.vala +index 85c9d06..5831cf3 100644 +--- a/src/alarm-setup-dialog.vala ++++ b/src/alarm-setup-dialog.vala +@@ -160,6 +160,10 @@ private class SetupDialog : Gtk.Dialog { + am_pm_stack.add (am_pm_button); + am_pm_stack.visible_child = am_pm_button; + } ++ /* Workaround: To keep the osk closed ++ * https://gitlab.gnome.org/GNOME/gtk/merge_requests/978#note_546576 */ ++ h_spinbutton.set ("im-module", "gtk-im-context-none", null); ++ m_spinbutton.set ("im-module", "gtk-im-context-none", null); + + set_from_alarm (); + } +diff --git a/src/timer-setup.vala b/src/timer-setup.vala +index 69129f9..4f460ce 100644 +--- a/src/timer-setup.vala ++++ b/src/timer-setup.vala +@@ -49,6 +49,10 @@ public class Setup : Gtk.Box { + insert_action_group ("timer-setup", actions); + + time_grid.set_direction (Gtk.TextDirection.LTR); ++ ++ h_spinbutton.set ("im-module", "gtk-im-context-none", null); ++ m_spinbutton.set ("im-module", "gtk-im-context-none", null); ++ s_spinbutton.set ("im-module", "gtk-im-context-none", null); + } + + private int get_duration () { +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0010-add-option-to-start-hidden.patch b/gnome-clocks-mobile/0010-add-option-to-start-hidden.patch new file mode 100644 index 0000000..eb8f202 --- /dev/null +++ b/gnome-clocks-mobile/0010-add-option-to-start-hidden.patch @@ -0,0 +1,63 @@ +From d09089c22fa81abac887006e1942674bcad736a9 Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Thu, 3 Dec 2020 22:54:42 +0100 +Subject: [PATCH 10/16] add option to start hidden + +--- + src/application.vala | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/application.vala b/src/application.vala +index 92aba34..4bc24c6 100644 +--- a/src/application.vala ++++ b/src/application.vala +@@ -21,6 +21,7 @@ namespace Clocks { + public class Application : Gtk.Application { + const OptionEntry[] OPTION_ENTRIES = { + { "version", 'v', 0, OptionArg.NONE, null, N_("Print version information and exit"), null }, ++ { "hidden", 0, 0, OptionArg.NONE, null, N_("Start without showing a window"), null }, + { (string) null } + }; + +@@ -36,6 +37,7 @@ public class Application : Gtk.Application { + private World.ShellWorldClocks world_clocks; + private uint world_clocks_id = 0; + private Window? window; ++ private bool start_hidden = false; + private List system_notifications; + + private Window ensure_window () ensures (window != null) { +@@ -96,7 +98,11 @@ public class Application : Gtk.Application { + base.activate (); + + var win = ensure_window (); +- win.present (); ++ if (!start_hidden) { ++ win.present (); ++ } else { ++ start_hidden = false; ++ } + + win.focus_in_event.connect (() => { + withdraw_notifications (); +@@ -142,6 +148,9 @@ public class Application : Gtk.Application { + print ("%s %s\n", (string) Environment.get_application_name (), Config.VERSION); + return 0; + } ++ if (options.contains("hidden")) { ++ start_hidden = true; ++ } + + return -1; + } +@@ -155,6 +164,7 @@ public class Application : Gtk.Application { + win.show_world (); + win.present (); + ++ + var world = GWeather.Location.get_world (); + if (world != null) { + // The result is actually nullable +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0011-autostart-gnome-clocks.patch b/gnome-clocks-mobile/0011-autostart-gnome-clocks.patch new file mode 100644 index 0000000..78e9492 --- /dev/null +++ b/gnome-clocks-mobile/0011-autostart-gnome-clocks.patch @@ -0,0 +1,61 @@ +From eef891c43eac9bade177f575ca78d867df31dc5c Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Fri, 27 Nov 2020 18:47:34 +0100 +Subject: [PATCH 11/16] autostart gnome-clocks + +--- + data/meson.build | 10 +++++++++- + data/org.gnome.clocks-daemon.desktop.in | 16 ++++++++++++++++ + 2 files changed, 25 insertions(+), 1 deletion(-) + create mode 100644 data/org.gnome.clocks-daemon.desktop.in + +diff --git a/data/meson.build b/data/meson.build +index c0817fd..497b3be 100644 +--- a/data/meson.build ++++ b/data/meson.build +@@ -46,6 +46,15 @@ if desktop_file_validate.found() + endif + + ++desktop_daemon_file = i18n.merge_file( ++ input : 'org.gnome.clocks-daemon.desktop.in', ++ output : '@0@-daemon.desktop'.format(app_id), ++ type : 'desktop', ++ po_dir : '../po', ++ install : true, ++ install_dir : join_paths(get_option('sysconfdir'), 'xdg/autostart') ++) ++ + dbusconf = configuration_data() + dbusconf.set('bindir', join_paths(get_option('prefix'), get_option('bindir'))) + dbusconf.set('name', app_id) +@@ -113,4 +122,3 @@ if glib_compile_schemas.found() + ] + ) + endif +- +diff --git a/data/org.gnome.clocks-daemon.desktop.in b/data/org.gnome.clocks-daemon.desktop.in +new file mode 100644 +index 0000000..49187ca +--- /dev/null ++++ b/data/org.gnome.clocks-daemon.desktop.in +@@ -0,0 +1,16 @@ ++[Desktop Entry] ++Name=Clocks ++GenericName=Clocks ++X-GNOME-FullName=GNOME Clocks ++Comment=Clocks for world times, plus alarms, stopwatch and a timer ++# Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++Keywords=time;timer;alarm;world clock;stopwatch;time zone; ++Exec=gnome-clocks --hidden ++# Translators: Do NOT translate or transliterate this text (this is an icon file name)! ++Icon=@icon@ ++Terminal=false ++Type=Application ++Categories=GNOME;GTK;Utility;Clock; ++StartupNotify=false ++NoDisplay=true ++X-GNOME-AutoRestart=true +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0012-alarm-setup-dialog-Allow-much-smaller-heights-useing.patch b/gnome-clocks-mobile/0012-alarm-setup-dialog-Allow-much-smaller-heights-useing.patch new file mode 100644 index 0000000..ef9b60c --- /dev/null +++ b/gnome-clocks-mobile/0012-alarm-setup-dialog-Allow-much-smaller-heights-useing.patch @@ -0,0 +1,359 @@ +From b7f9d6e3df2d8291194b5b5eacff1386b1b50dea Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Mon, 14 Dec 2020 17:56:13 +0100 +Subject: [PATCH 12/16] alarm-setup-dialog: Allow much smaller heights useing a + ScrolledWindow + +--- + data/ui/alarm-setup-dialog.ui | 298 ++++++++++++++++++---------------- + 1 file changed, 154 insertions(+), 144 deletions(-) + +diff --git a/data/ui/alarm-setup-dialog.ui b/data/ui/alarm-setup-dialog.ui +index f332c4a..2429ce5 100644 +--- a/data/ui/alarm-setup-dialog.ui ++++ b/data/ui/alarm-setup-dialog.ui +@@ -17,187 +17,197 @@ + True + center-on-parent + True +- 350 +- 350 + dialog + center + New Alarm + + + True ++ 0 + +- ++ + True +- 450 ++ True ++ True ++ never ++ True ++ True + +- ++ + True +- 12 +- vertical ++ 450 + +- ++ + True +- center +- 12 +- 6 ++ vertical ++ 12 + +- ++ + True +- 6 +- 6 +- +- +- 0 +- 0 +- +- +- +- +- True +- +- +- +- 2 +- 0 +- +- +- +- +- True +- 2 +- False +- 0 +- 0.5 +- number +- vertical +- m_adjustment +- True +- True +- 60 +- +- +- +- +- 3 +- 0 +- +- +- +- +- True +- 6 +- 6 ++ center ++ 6 + +- ++ + True +- False ++ 6 ++ 6 + ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ ++ ++ ++ 2 ++ 0 ++ ++ ++ ++ ++ True ++ 2 ++ False ++ 0 ++ 0.5 ++ number ++ vertical ++ m_adjustment ++ True ++ True ++ 60 ++ ++ ++ ++ ++ 3 ++ 0 ++ + +- +- +- 4 +- 0 +- +- +- +- +- True +- 2 +- False +- 0 +- 0.5 +- number +- vertical +- h_adjustment +- True +- True +- 60 +- +- +- +- +- 1 +- 0 +- +- +- +- +- +- +- +- True +- none +- +- +- True +- +- +- +- +- +- True +- False +- False +- Name +- Optional + +- ++ + True +- center +- True +- True +- ++ 6 ++ 6 ++ ++ ++ True ++ False ++ ++ + ++ ++ 4 ++ 0 ++ + ++ ++ ++ True ++ 2 ++ False ++ 0 ++ 0.5 ++ number ++ vertical ++ h_adjustment ++ True ++ True ++ 60 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ + + + +- ++ + True +- False +- False +- Ring Duration ++ none ++ 12 ++ ++ ++ True ++ ++ ++ ++ ++ ++ True ++ False ++ False ++ Name ++ Optional ++ ++ ++ True ++ center ++ True ++ True ++ ++ ++ ++ ++ ++ ++ ++ True ++ False ++ False ++ Ring Duration ++ ++ ++ ++ ++ True ++ False ++ False ++ Snooze Duration ++ ++ ++ + + + +- ++ + True +- False +- False +- Snooze Duration ++ R_emove Alarm ++ True ++ 12 ++ start ++ ++ + + +- +- +- +- +- +- True +- R_emove Alarm +- True +- 6 +- start +- +- +- +- +- +- +- True + +- ++ + True +- You already have an alarm for this time. ++ ++ ++ 12 ++ True ++ You already have an alarm for this time. ++ ++ + + + ++ + + + +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0013-timer-setup-remove-unused-lables.patch b/gnome-clocks-mobile/0013-timer-setup-remove-unused-lables.patch new file mode 100644 index 0000000..e81d1c9 --- /dev/null +++ b/gnome-clocks-mobile/0013-timer-setup-remove-unused-lables.patch @@ -0,0 +1,52 @@ +From 8828ebc1ddb39ae0730367b38344adc601692946 Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Mon, 14 Dec 2020 18:14:59 +0100 +Subject: [PATCH 13/16] timer-setup: remove unused lables + +--- + data/ui/timer-setup.ui | 22 ---------------------- + 1 file changed, 22 deletions(-) + +diff --git a/data/ui/timer-setup.ui b/data/ui/timer-setup.ui +index 8a2f3b1..588aedb 100644 +--- a/data/ui/timer-setup.ui ++++ b/data/ui/timer-setup.ui +@@ -206,17 +206,6 @@ + center + center + 10 +- +- +- True +- False +- True +- +- +- 0 +- 0 +- +- + + + True +@@ -325,17 +314,6 @@ + 0 + + +- +- +- True +- False +- True +- +- +- 6 +- 0 +- +- + + + True +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0014-timer-Allow-much-smaller-heights-useing-a-ScrolledWi.patch b/gnome-clocks-mobile/0014-timer-Allow-much-smaller-heights-useing-a-ScrolledWi.patch new file mode 100644 index 0000000..92e9ea9 --- /dev/null +++ b/gnome-clocks-mobile/0014-timer-Allow-much-smaller-heights-useing-a-ScrolledWi.patch @@ -0,0 +1,163 @@ +From 239add0b868bb338a0eb9998fa2e5d9b23550a99 Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Mon, 14 Dec 2020 18:34:46 +0100 +Subject: [PATCH 14/16] timer: Allow much smaller heights useing a + ScrolledWindow + +--- + data/ui/timer-face.ui | 81 +++++++++++++++++++++---------------- + data/ui/timer-setup.ui | 1 - + src/timer-setup-dialog.vala | 13 +++++- + 3 files changed, 57 insertions(+), 38 deletions(-) + +diff --git a/data/ui/timer-face.ui b/data/ui/timer-face.ui +index 123a8c5..87331ec 100644 +--- a/data/ui/timer-face.ui ++++ b/data/ui/timer-face.ui +@@ -7,55 +7,66 @@ + True + False + +- ++ + True +- False +- center +- center +- vertical +- 18 ++ True ++ True ++ never ++ True ++ True + +- ++ + True + False +- Select Duration +- +- +- +- False +- True +- 0 +- +- +- +- +- True +- True +- True + center + center ++ vertical ++ 18 ++ 12 + +- ++ + True + False ++ Select Duration ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True + center + center +- media-playback-start-symbolic ++ ++ ++ True ++ False ++ center ++ center ++ media-playback-start-symbolic ++ ++ ++ + ++ ++ False ++ True ++ 1 ++ + +- + +- +- False +- True +- 1 +- + + + +diff --git a/data/ui/timer-setup.ui b/data/ui/timer-setup.ui +index 588aedb..37a181d 100644 +--- a/data/ui/timer-setup.ui ++++ b/data/ui/timer-setup.ui +@@ -198,7 +198,6 @@ + True + False + 12 +- 12 + + + True +diff --git a/src/timer-setup-dialog.vala b/src/timer-setup-dialog.vala +index e360ad8..6e94b90 100644 +--- a/src/timer-setup-dialog.vala ++++ b/src/timer-setup-dialog.vala +@@ -25,14 +25,23 @@ public class SetupDialog: Gtk.Dialog { + + public SetupDialog (Gtk.Window parent) { + Object (modal: true, transient_for: parent, title: _("New Timer"), use_header_bar: 1); +- this.set_default_size (640, 360); + + add_button (_("Cancel"), Gtk.ResponseType.CANCEL); + var create_button = add_button (_("Add"), Gtk.ResponseType.ACCEPT); + create_button.get_style_context ().add_class ("suggested-action"); + + timer_setup = new Setup (); +- this.get_content_area ().add (timer_setup); ++ timer_setup.margin = 12; ++ var container = new Gtk.ScrolledWindow (null, null); ++ container.hexpand = true; ++ container.vexpand = true; ++ container.propagate_natural_height = true; ++ container.propagate_natural_width = true; ++ container.hscrollbar_policy = Gtk.PolicyType.NEVER; ++ container.border_width = 0; ++ container.visible = true; ++ container.add (timer_setup); ++ this.get_content_area ().add (container); + timer_setup.duration_changed.connect ((duration) => { + this.set_response_sensitive (Gtk.ResponseType.ACCEPT, duration != 0); + }); +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0015-alarm-make-ringing-panel-fit-to-small-window-heights.patch b/gnome-clocks-mobile/0015-alarm-make-ringing-panel-fit-to-small-window-heights.patch new file mode 100644 index 0000000..4d5cd43 --- /dev/null +++ b/gnome-clocks-mobile/0015-alarm-make-ringing-panel-fit-to-small-window-heights.patch @@ -0,0 +1,226 @@ +From 845abcf43c0f86ee9405ef7aeaee63adcc16e1d1 Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Tue, 15 Dec 2020 14:23:43 +0100 +Subject: [PATCH 15/16] alarm: make ringing panel fit to small window heights + +--- + data/ui/alarm-ringing-panel.ui | 181 ++++++++++++++++----------------- + 1 file changed, 90 insertions(+), 91 deletions(-) + +diff --git a/data/ui/alarm-ringing-panel.ui b/data/ui/alarm-ringing-panel.ui +index df04bc7..76ead33 100644 +--- a/data/ui/alarm-ringing-panel.ui ++++ b/data/ui/alarm-ringing-panel.ui +@@ -7,119 +7,118 @@ + + True + +- ++ + True + False +- 6 +- 6 +- 6 +- 6 +- True +- True +- 48 +- 24 + +- ++ + True + False +- center +- center +- True +- True +- 24 + 24 +- +- +- Stop +- 200 +- True +- True +- True +- +- +- +- 0 +- 0 +- +- +- +- +- Snooze +- 200 +- True +- True +- True +- +- +- +- 0 +- 1 +- +- +- +- +- 0 +- 1 +- +- +- +- +- True +- False +- center ++ 12 ++ 12 + center +- True +- True +- vertical + +- ++ + True + False +- center +- True +- 0.5 +- +- +- +- ++ 24 ++ 24 ++ 2 ++ True ++ ++ ++ True ++ False ++ ++ ++ Stop ++ 200 ++ True ++ True ++ True ++ ++ ++ ++ ++ ++ ++ ++ True ++ False ++ ++ ++ Snooze ++ 200 ++ True ++ True ++ True ++ ++ ++ ++ ++ + + +- False +- True +- 0 ++ 0 ++ 1 + + + +- ++ + True + False +- center +- True +- 24 +- ++ vertical ++ ++ ++ True ++ False ++ center ++ True ++ 0.5 ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ True ++ ++ ++ ++ False ++ True ++ 1 ++ ++ + + +- False +- True +- 1 ++ 0 ++ 0 + + + +- +- 0 +- 0 +- + + + +-- +2.34.1 + diff --git a/gnome-clocks-mobile/0016-world-standalone-allow-smaller-window-heights.patch b/gnome-clocks-mobile/0016-world-standalone-allow-smaller-window-heights.patch new file mode 100644 index 0000000..1548f6e --- /dev/null +++ b/gnome-clocks-mobile/0016-world-standalone-allow-smaller-window-heights.patch @@ -0,0 +1,39 @@ +From 7403c9567f2f89fd588ad1796b1a816d5d12bccf Mon Sep 17 00:00:00 2001 +From: Julian Sparber +Date: Tue, 15 Dec 2020 14:31:12 +0100 +Subject: [PATCH 16/16] world-standalone: allow smaller window heights + +--- + data/ui/world-standalone.ui | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/data/ui/world-standalone.ui b/data/ui/world-standalone.ui +index 46667d7..8f7acff 100644 +--- a/data/ui/world-standalone.ui ++++ b/data/ui/world-standalone.ui +@@ -38,22 +38,8 @@ + False + center + center +- 34 +- 34 +- 12 + True + True +- +- +- True +- False +- +- +- +- 0 +- 1 +- +- + + + True +-- +2.34.1 + diff --git a/gnome-clocks-mobile/PKGBUILD b/gnome-clocks-mobile/PKGBUILD new file mode 100644 index 0000000..4b2f741 --- /dev/null +++ b/gnome-clocks-mobile/PKGBUILD @@ -0,0 +1,81 @@ +# Maintainer: Danct12 +# Contributor: Jan Alexander Steffens (heftig) + +pkgname=gnome-clocks-mobile +_pkgname=gnome-clocks +pkgver=41.0 +pkgrel=3 +pkgdesc="Clocks applications for GNOME" +url="https://wiki.gnome.org/Apps/Clocks" +arch=(x86_64 armv7h aarch64) +license=(GPL) +depends=(gtk3 libgweather gnome-desktop geoclue2 geocode-glib feedbackd libhandy) +makedepends=(vala gobject-introspection yelp-tools git meson) +provides=(gnome-clocks) +conflicts=(gnome-clocks) +_commit=90d36119a5ac0bb86586e261a26562baea4d577c # tags/41.0^0 +source=("git+https://gitlab.gnome.org/GNOME/gnome-clocks.git#commit=$_commit" + '0001-timer-Use-name-that-can-be-added-to-the-event-naming.patch' + '0002-Use-libfeedback-in-instead-of-GSound.patch' + '0003-timers-persist-running-timers.patch' + '0004-alarm-item-Make-sure-that-the-time-property-is-alway.patch' + '0005-alarm-remove-edit-property.patch' + '0006-alarms-Make-alarms-persisted-and-add-missed-alarms-n.patch' + '0007-Fixed-infinite-alarming.patch' + '0008-Alarms-Fix-wiping-edit-data.patch' + '0009-Don-t-show-numpad-when-setting-a-new-alarm-timer.patch' + '0010-add-option-to-start-hidden.patch' + '0011-autostart-gnome-clocks.patch' + '0012-alarm-setup-dialog-Allow-much-smaller-heights-useing.patch' + '0013-timer-setup-remove-unused-lables.patch' + '0014-timer-Allow-much-smaller-heights-useing-a-ScrolledWi.patch' + '0015-alarm-make-ringing-panel-fit-to-small-window-heights.patch' + '0016-world-standalone-allow-smaller-window-heights.patch') +sha256sums=('SKIP' + '4aa66ae47df1d970ed6138e3d3cec7eea588af7dfa39f0940c13dfa5164052ad' + '9e692d5e340c81943b7312249054a74ee4f83c756a5bf510102a01f5f9ffc458' + '4d46e7968b54d7f16c89ec2d69a5e06c8952253e589bf58546d2dddf86f4d57a' + '10b5aec1a643e8210e410aed716c136a949aa5eacc2b9589fd81c97d99536b79' + 'a22e67d3d580c5291b706048c55410e7cbe2d9e59e57c29357e4bbdd00ceaf5f' + '5ac80e8d2379577e6f5f5b0e7862446d6a017b319401f7bdc2ce523d9ac55da6' + '0ae3d7354a491296c03f4102aace3eaf6f0193efda2311b462cf1afa3f9c7a37' + '73dea007e55d6fec12730fdb1cd7bf319c8b373b337f79e7b91d912ec3d8cc40' + 'c242f5fd594cc58ba5dd5b313cb5a057308503c94576bbaa58928181a77cf083' + '1f0a13d25aae7942859decb9167a1e53ce24060cc56ef17a0d0b2c10fb77204f' + 'dc9fe50c7b6c902eeeb2e67f4a81b017856f800c98b6ce68627db3e8fc5c39b7' + '8b15b617990827196c7444b4238c562af004dd5d98841e00d8829d12a70b0621' + '437bf6caa21232c7d8ec40d541ebd443e9343197cd21256e4ce8a1cab6045f6a' + 'bb0121b34c44b0515a9289704e0562871cd5da1544ca520fb04b80baa5c388fe' + '664515657ee315894be6e1b0b87c9308d9dc1de2eb00aebc29ecf87c133147ac' + '992d8868dc96d5b5742cafa26f119484d461a84ee29ac5cf1985ea7f51942d36') + +pkgver() { + cd $_pkgname + git describe --tags | sed 's/-/+/g' +} + +prepare() { + cd $_pkgname + + local src + for src in "${source[@]}"; do + src="${src%%::*}" + src="${src##*/}" + [[ $src = *.patch ]] || continue + echo "Applying patch $src..." + patch -Np1 < "../$src" + done +} + +build() { + arch-meson $_pkgname build + meson compile -C build +} + +check() { + meson test -C build --print-errorlogs +} + +package() { + meson install -C build --destdir "$pkgdir" +} diff --git a/gnome-contacts-mobile/0001-ContactSheet-Add-make-call-and-send-sms-button.patch b/gnome-contacts-mobile/0001-ContactSheet-Add-make-call-and-send-sms-button.patch new file mode 100644 index 0000000..97e4308 --- /dev/null +++ b/gnome-contacts-mobile/0001-ContactSheet-Add-make-call-and-send-sms-button.patch @@ -0,0 +1,68 @@ +From: Julian Sparber +Date: Wed, 13 Jul 2022 22:03:09 +0400 +Subject: contact-sheet: Add call and send sms buttons + +This adds a button to make calls via the default handler for tel: +and a button to send sms via the default handler for sms: + +The buttons are hidden when no handler is available. +--- + src/contacts-contact-sheet.vala | 15 +++++++++++++++ + src/contacts-utils.vala | 18 ++++++++++++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/src/contacts-contact-sheet.vala b/src/contacts-contact-sheet.vala +index e662ee0..c93370d 100644 +--- a/src/contacts-contact-sheet.vala ++++ b/src/contacts-contact-sheet.vala +@@ -245,6 +245,21 @@ public class Contacts.ContactSheet : Gtk.Widget { + var row = new ContactSheetRow (chunk, + phone.raw_number, + phone.get_phone_type ().display_name); ++ ++ // Show a call button when we have a handler for it ++ if (AppInfo.get_all_for_type ("x-scheme-handler/tel").length () > 0) { ++ var call_button = row.add_button ("call-start-symbolic"); ++ call_button.clicked.connect (() => { ++ Utils.start_call (phone.raw_number, get_root () as Gtk.Window); ++ }); ++ } ++ if (AppInfo.get_all_for_type ("x-scheme-handler/sms").length () > 0) { ++ var sms_button = row.add_button ("chat-message-new-symbolic"); ++ sms_button.clicked.connect (() => { ++ Utils.send_sms (phone.raw_number, get_root () as Gtk.Window); ++ }); ++ } ++ + group.add (row); + } + +diff --git a/src/contacts-utils.vala b/src/contacts-utils.vala +index a457a2e..2e6aeef 100644 +--- a/src/contacts-utils.vala ++++ b/src/contacts-utils.vala +@@ -19,6 +19,24 @@ using Folks; + + namespace Contacts.Utils { + ++ public void start_call (string number, Gtk.Window toplevel) { ++ var uri = "tel:" + Uri.escape_string (number, "+" , false); ++ try { ++ Gtk.show_uri (toplevel, uri, 0); ++ } catch (Error e) { ++ debug ("Couldn't launch URI \"%s\": %s", uri, e.message); ++ } ++ } ++ ++ public void send_sms (string number, Gtk.Window toplevel) { ++ var uri = "sms:" + Uri.escape_string (number, "+" , false); ++ try { ++ Gtk.show_uri (toplevel, uri, 0); ++ } catch (Error e) { ++ debug ("Couldn't launch URI \"%s\": %s", uri, e.message); ++ } ++ } ++ + public T? get_first (Gee.Collection collection) { + var i = collection.iterator(); + if (i.next()) diff --git a/gnome-contacts-mobile/PKGBUILD b/gnome-contacts-mobile/PKGBUILD new file mode 100644 index 0000000..ed369b7 --- /dev/null +++ b/gnome-contacts-mobile/PKGBUILD @@ -0,0 +1,75 @@ +# Maintainer: Danct12 +# Contributor: Jan Alexander Steffens (heftig) +# Contributor: Ionut Biru + +pkgname=gnome-contacts-mobile +_pkgname=gnome-contacts +pkgver=45.1 +pkgrel=1 +pkgdesc="Contacts Manager for GNOME - Forked for Purism patches" +url="https://wiki.gnome.org/Apps/Contacts" +arch=(x86_64 armv7h aarch64) +license=(GPL-2.0-or-later) +depends=( + cairo + dconf + evolution-data-server + folks + gdk-pixbuf2 + glib2 + gnome-online-accounts + gtk4 + hicolor-icon-theme + libadwaita + libgee + libgoa + libportal + libportal-gtk4 + pango + qrencode +) +makedepends=( + appstream-glib + git + gobject-introspection + meson + vala +) +provides=(gnome-contacts) +conflicts=(gnome-contacts) +_commit=aa0456c32a6ec8e766ea090e7f3fb85e0035f506 # tags/45.1^0 +source=("git+https://gitlab.gnome.org/GNOME/gnome-contacts.git#commit=$_commit" + '0001-ContactSheet-Add-make-call-and-send-sms-button.patch') +b2sums=('SKIP' + 'fa242d8e587486496502cafbb565423752c7f3d49c15bc364a26f64bb81ddbe070f900fa68c8c24d863a894123416ecef7b9b9902d2acbe077523a036d3ccf5c') + +pkgver() { + cd $_pkgname + git describe --tags | sed 's/-/+/g' +} + +prepare() { + cd $_pkgname + + local src + for src in "${source[@]}"; do + src="${src%%::*}" + src="${src##*/}" + [[ $src = *.patch ]] || continue + echo "Applying patch $src..." + patch -Np1 < "../$src" + done +} + +build() { + arch-meson $_pkgname build + meson compile -C build +} + +check() { + meson test -C build --print-errorlogs +} + +package() { + meson install -C build --destdir "$pkgdir" +} diff --git a/gnome-control-center-mobile/0001-avatar-chooser-Adapt-to-work-on-librem5.patch b/gnome-control-center-mobile/0001-avatar-chooser-Adapt-to-work-on-librem5.patch new file mode 100644 index 0000000..e760691 --- /dev/null +++ b/gnome-control-center-mobile/0001-avatar-chooser-Adapt-to-work-on-librem5.patch @@ -0,0 +1,41 @@ +From: Mohammed Sadiq +Date: Fri, 20 Sep 2019 16:11:07 +0530 +Subject: [PATCH 1/7] avatar-chooser: Adapt to work on librem5 + +--- + panels/system/users/cc-avatar-chooser.ui | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/panels/system/users/cc-avatar-chooser.ui b/panels/system/users/cc-avatar-chooser.ui +index 0f19c6e..d1ed9ae 100644 +--- a/panels/system/users/cc-avatar-chooser.ui ++++ b/panels/system/users/cc-avatar-chooser.ui +@@ -3,6 +3,11 @@ + + + diff --git a/gnome-control-center-mobile/0004-power-add-more-suspend-timing-options.patch b/gnome-control-center-mobile/0004-power-add-more-suspend-timing-options.patch new file mode 100644 index 0000000..ba17cae --- /dev/null +++ b/gnome-control-center-mobile/0004-power-add-more-suspend-timing-options.patch @@ -0,0 +1,27 @@ +From: Arnaud Ferraris +Date: Mon, 25 May 2020 21:03:38 +0200 +Subject: [PATCH 4/4] power: add more suspend timing options + +--- + panels/power/cc-power-panel.ui | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/panels/power/cc-power-panel.ui b/panels/power/cc-power-panel.ui +index b6efcd0..4e5bae1 100644 +--- a/panels/power/cc-power-panel.ui ++++ b/panels/power/cc-power-panel.ui +@@ -8,6 +8,14 @@ + + + ++ ++ 5 minutes ++ 300 ++ ++ ++ 10 minutes ++ 600 ++ + + 15 minutes + 900 diff --git a/gnome-control-center-mobile/Add-patches-to-check-if-phone.patch b/gnome-control-center-mobile/Add-patches-to-check-if-phone.patch new file mode 100644 index 0000000..52a9dcb --- /dev/null +++ b/gnome-control-center-mobile/Add-patches-to-check-if-phone.patch @@ -0,0 +1,37 @@ +From: Mohammed Sadiq +Date: Tue, 2 Mar 2021 16:45:32 +0530 +Subject: [PATCH 1/8] Add patches to check if phone + +--- + panels/common/pureos.h | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + create mode 100644 panels/common/pureos.h + +diff --git a/panels/common/pureos.h b/panels/common/pureos.h +new file mode 100644 +index 0000000..2e31d7e +--- /dev/null ++++ b/panels/common/pureos.h +@@ -0,0 +1,22 @@ ++#include ++ ++static inline gboolean ++pureos_get_is_phone (void) ++{ ++ GSettingsSchema *schema; ++ GSettings *gsettings; ++ gboolean is_phone; ++ ++ schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (), ++ "org.gtk.Settings.Purism", TRUE); ++ ++ if (!schema) ++ return FALSE; ++ ++ gsettings = g_settings_new_full (schema, NULL, NULL); ++ is_phone = g_settings_get_boolean (gsettings, "is-phone"); ++ g_object_unref (gsettings); ++ g_settings_schema_unref (schema); ++ ++ return is_phone; ++} diff --git a/gnome-control-center-mobile/PKGBUILD b/gnome-control-center-mobile/PKGBUILD new file mode 100644 index 0000000..a50beaa --- /dev/null +++ b/gnome-control-center-mobile/PKGBUILD @@ -0,0 +1,152 @@ +# Maintainer: Danct12 +# Contributor: Jan Alexander Steffens (heftig) +# Contributor: Jan de Groot + +_pkgname=gnome-control-center +pkgname=gnome-control-center-mobile +pkgver=46.0.1 +pkgrel=1 +pkgdesc="GNOME's main interface to configure various aspects of the desktop - Purism fork" +url="https://gitlab.gnome.org/GNOME/gnome-control-center" +license=(GPL-2.0-or-later) +arch=(x86_64 armv7h aarch64) +depends=( + accountsservice + bolt + cairo + colord-gtk4 + cups-pk-helper + dconf + fontconfig + gcc-libs + gcr-4 + gdk-pixbuf2 + glib2 + glibc + gnome-bluetooth-3.0 + gnome-color-manager + gnome-desktop-4 + gnome-online-accounts + gnome-settings-daemon + gnutls + graphene + gsettings-desktop-schemas + gsound + gtk4 + hicolor-icon-theme + json-glib + krb5 + libadwaita + libcolord + libcups + libepoxy + libgoa + libgtop + libgudev + libibus + libmm-glib + libnm + libnma-gtk4 + libpulse + libpwquality + libsecret + libsoup3 + libwacom + libx11 + libxi + libxml2 + modemmanager + pango + polkit + smbclient + sound-theme-freedesktop + tecla + udisks2 + upower +) +makedepends=( + docbook-xsl + git + meson + python + python-packaging +) +checkdepends=( + python-dbusmock + python-gobject + xorg-server-xvfb +) +optdepends=( + 'fwupd: device security panel' + 'gnome-remote-desktop: screen sharing' + + # Cannot be a depend because when gnome-shell checkdepends on + # gnome-control-center depends on gnome-shell depends on libmutter-12.so, it + # makes building gnome-shell against libmutter-13.so impossible + 'gnome-shell: multitasking panel' + + 'gnome-user-share: WebDAV file sharing' + 'networkmanager: network settings' + 'openssh: remote login' + 'power-profiles-daemon: power profiles' + 'rygel: media sharing' + 'system-config-printer: printer settings' +) +provides=(gnome-control-center) +conflicts=(gnome-control-center) +source=( + "git+https://gitlab.gnome.org/GNOME/gnome-control-center.git?signed#tag=$pkgver" + "git+https://gitlab.gnome.org/GNOME/libgnome-volume-control.git" + # purism + '0001-avatar-chooser-Adapt-to-work-on-librem5.patch' + 'Add-patches-to-check-if-phone.patch' + # mobian + '0004-power-add-more-suspend-timing-options.patch' + 'resize-connection-editor.patch' +) +sha256sums=('5ee40c5b39544aba9ff36156bc5e5e3258e065e92518a1c150a2936bafe3db0a' + 'SKIP' + 'c18c1b9fdab8e8b7aad8519a58996267377965dbe3d8d8dc9a9129fe80da01ef' + '09e36b0aa2c40d6b6f5be11fd9617223d5b142ff8b50db6fce0eeebc63007327' + '6f1906d58edfa87658c6396091601cab44f40046aced3a56bf5b4e46c0510fb6' + 'c006215f8e8c6ef523708089f246815f845d82d94e5f442460d4a4aafdfb617b') +validpgpkeys=( + 9B60FE7947F0A3C58136817F2C2A218742E016BE # Felipe Borges (GNOME) +) + +prepare() { + cd ${_pkgname} + + git submodule init subprojects/gvc + git submodule set-url subprojects/gvc "$srcdir/libgnome-volume-control" + git -c protocol.file.allow=always submodule update + + local src + for src in "${source[@]}"; do + src="${src%%::*}" + src="${src##*/}" + [[ $src = *.patch ]] || continue + echo "Applying patch $src..." + patch -Np1 < "../$src" + done +} + +build() { + local meson_options=( + -D documentation=true + ) + + arch-meson ${_pkgname} build "${meson_options[@]}" + meson compile -C build +} + +check() { + GTK_A11Y=none dbus-run-session xvfb-run -s '-nolisten local +iglx -noreset' \ + meson test -C build --print-errorlogs +} + +package() { + meson install -C build --destdir "$pkgdir" + + echo "X-Purism-FormFactor=Workstation;Mobile;" >> "$pkgdir/usr/share/applications/gnome-control-center.desktop" +} diff --git a/gnome-control-center-mobile/resize-connection-editor.patch b/gnome-control-center-mobile/resize-connection-editor.patch new file mode 100644 index 0000000..d4a13f0 --- /dev/null +++ b/gnome-control-center-mobile/resize-connection-editor.patch @@ -0,0 +1,614 @@ +From: Debian GNOME Maintainers + +Date: Thu, 2 Jun 2022 14:36:35 +0200 +Subject: resize-connection-editor + +=================================================================== +--- + .../connection-editor/8021x-security-page.ui | 6 +-- + .../connection-editor/ce-page-8021x-security.c | 2 +- + panels/network/connection-editor/ce-page-ip4.c | 4 +- + panels/network/connection-editor/ce-page-ip6.c | 4 +- + .../network/connection-editor/ce-page-security.c | 2 +- + .../network/connection-editor/connection-editor.ui | 4 +- + panels/network/connection-editor/details-page.ui | 9 +++-- + panels/network/connection-editor/ethernet-page.ui | 36 ++++++++--------- + panels/network/connection-editor/ip4-page.ui | 42 ++++++++++---------- + panels/network/connection-editor/ip6-page.ui | 46 +++++++++++----------- + panels/network/connection-editor/security-page.ui | 6 +-- + panels/network/connection-editor/vpn-page.ui | 6 +-- + panels/network/connection-editor/wifi-page.ui | 6 +-- + 13 files changed, 87 insertions(+), 86 deletions(-) + +diff --git a/panels/network/connection-editor/8021x-security-page.ui b/panels/network/connection-editor/8021x-security-page.ui +index 4880d99..2e774a3 100644 +--- a/panels/network/connection-editor/8021x-security-page.ui ++++ b/panels/network/connection-editor/8021x-security-page.ui +@@ -8,14 +8,14 @@ + True + + +- 50 +- 50 ++ 12 ++ 12 + 12 + 12 + True + True + 10 +- 6 ++ 2 + + + 1 +diff --git a/panels/network/connection-editor/ce-page-8021x-security.c b/panels/network/connection-editor/ce-page-8021x-security.c +index 3826946..97cd01a 100644 +--- a/panels/network/connection-editor/ce-page-8021x-security.c ++++ b/panels/network/connection-editor/ce-page-8021x-security.c +@@ -68,7 +68,7 @@ finish_setup (CEPage8021xSecurity *self, gpointer unused, GError *error, gpointe + if (error) + return; + +- self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); ++ self->group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + + self->security = nma_ws_802_1x_new (self->connection, FALSE, FALSE); + if (!self->security) { +diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c +index b7a687d..0aeed7c 100644 +--- a/panels/network/connection-editor/ce-page-ip4.c ++++ b/panels/network/connection-editor/ce-page-ip4.c +@@ -247,7 +247,7 @@ add_address_row (CEPageIP4 *self, + row = gtk_list_box_row_new (); + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); + +- row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); ++ row_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_add_css_class (row_box, "linked"); + + widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET)); +@@ -393,7 +393,7 @@ add_route_row (CEPageIP4 *self, + row = gtk_list_box_row_new (); + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); + +- row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); ++ row_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_add_css_class (row_box, "linked"); + + widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET)); +diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c +index a5e5dcb..0a02fc0 100644 +--- a/panels/network/connection-editor/ce-page-ip6.c ++++ b/panels/network/connection-editor/ce-page-ip6.c +@@ -231,7 +231,7 @@ add_address_row (CEPageIP6 *self, + row = gtk_list_box_row_new (); + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); + +- row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); ++ row_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_add_css_class (row_box, "linked"); + + widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET6)); +@@ -369,7 +369,7 @@ add_route_row (CEPageIP6 *self, + row = gtk_list_box_row_new (); + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); + +- row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); ++ row_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_add_css_class (row_box, "linked"); + + widget = GTK_WIDGET (ce_ip_address_entry_new (AF_INET6)); +diff --git a/panels/network/connection-editor/ce-page-security.c b/panels/network/connection-editor/ce-page-security.c +index fbc627a..2a51301 100644 +--- a/panels/network/connection-editor/ce-page-security.c ++++ b/panels/network/connection-editor/ce-page-security.c +@@ -234,7 +234,7 @@ finish_setup (CEPageSecurity *self) + sw = nm_connection_get_setting_wireless (self->connection); + g_assert (sw); + +- self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); ++ self->group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + + dev_caps = NM_WIFI_DEVICE_CAP_CIPHER_WEP40 + | NM_WIFI_DEVICE_CAP_CIPHER_WEP104 +diff --git a/panels/network/connection-editor/connection-editor.ui b/panels/network/connection-editor/connection-editor.ui +index 89f8418..0c3b116 100644 +--- a/panels/network/connection-editor/connection-editor.ui ++++ b/panels/network/connection-editor/connection-editor.ui +@@ -3,7 +3,7 @@ + diff --git a/gtk3-mobile/librem5-Make-GtkShortcutsWindow-adaptive.patch b/gtk3-mobile/librem5-Make-GtkShortcutsWindow-adaptive.patch new file mode 100644 index 0000000..08d4bb8 --- /dev/null +++ b/gtk3-mobile/librem5-Make-GtkShortcutsWindow-adaptive.patch @@ -0,0 +1,219 @@ +From: Alexander Mikhaylenko +Date: Thu, 18 Mar 2021 17:42:00 +0500 +Subject: librem5: Make GtkShortcutsWindow adaptive + +Fixes https://source.puri.sm/Librem5/debs/gtk/-/issues/30 +--- + gtk/gtkshortcutssection.c | 65 +++++++++++++++++++++++++++++++++++++++++------ + gtk/gtkshortcutswindow.c | 5 ++-- + 2 files changed, 60 insertions(+), 10 deletions(-) + +diff --git a/gtk/gtkshortcutssection.c b/gtk/gtkshortcutssection.c +index 9a61765..a3d4e85 100644 +--- a/gtk/gtkshortcutssection.c ++++ b/gtk/gtkshortcutssection.c +@@ -27,6 +27,7 @@ + #include "gtkstackswitcher.h" + #include "gtkstylecontext.h" + #include "gtkorientable.h" ++#include "gtkscrolledwindow.h" + #include "gtksizegroup.h" + #include "gtkwidget.h" + #include "gtkbindings.h" +@@ -62,7 +63,8 @@ struct _GtkShortcutsSection + gchar *view_name; + guint max_height; + +- GtkStack *stack; ++ GtkWidget *column; ++ GtkWidget *stack; + GtkStackSwitcher *switcher; + GtkWidget *show_all; + GtkWidget *footer; +@@ -117,10 +119,12 @@ static void gtk_shortcuts_section_maybe_reflow (GtkShortcutsSection *self); + static gboolean gtk_shortcuts_section_change_current_page (GtkShortcutsSection *self, + gint offset); + ++/* + static void gtk_shortcuts_section_pan_gesture_pan (GtkGesturePan *gesture, + GtkPanDirection direction, + gdouble offset, + GtkShortcutsSection *self); ++*/ + + static void + gtk_shortcuts_section_add (GtkContainer *container, +@@ -424,11 +428,14 @@ gtk_shortcuts_section_class_init (GtkShortcutsSectionClass *klass) + static void + gtk_shortcuts_section_init (GtkShortcutsSection *self) + { ++ GtkSizeGroup *group; ++ + self->max_height = 15; + + gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL); + gtk_box_set_homogeneous (GTK_BOX (self), FALSE); + gtk_box_set_spacing (GTK_BOX (self), 22); ++/* + gtk_container_set_border_width (GTK_CONTAINER (self), 24); + + self->stack = g_object_new (GTK_TYPE_STACK, +@@ -447,8 +454,38 @@ gtk_shortcuts_section_init (GtkShortcutsSection *self) + NULL); + + gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (self->switcher)), GTK_STYLE_CLASS_LINKED); ++*/ ++ ++ self->stack = g_object_new (GTK_TYPE_SCROLLED_WINDOW, ++ "propagate-natural-width", TRUE, ++ "vexpand", TRUE, ++ "visible", TRUE, ++ NULL); ++ GTK_CONTAINER_CLASS (gtk_shortcuts_section_parent_class)->add (GTK_CONTAINER (self), GTK_WIDGET (self->stack)); ++ ++ self->column = g_object_new (GTK_TYPE_BOX, ++ "orientation", GTK_ORIENTATION_VERTICAL, ++ "spacing", 24, ++ "margin", 24, ++ "halign", GTK_ALIGN_CENTER, ++ "visible", TRUE, ++ NULL); ++ gtk_container_add (GTK_CONTAINER (self->stack), self->column); ++ ++ group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); ++G_GNUC_BEGIN_IGNORE_DEPRECATIONS ++ gtk_size_group_set_ignore_hidden (group, TRUE); ++G_GNUC_END_IGNORE_DEPRECATIONS ++ g_object_set_data_full (G_OBJECT (self->column), "accel-size-group", group, g_object_unref); ++ ++ group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); ++G_GNUC_BEGIN_IGNORE_DEPRECATIONS ++ gtk_size_group_set_ignore_hidden (group, TRUE); ++G_GNUC_END_IGNORE_DEPRECATIONS ++ g_object_set_data_full (G_OBJECT (self->column), "title-size-group", group, g_object_unref); + + self->show_all = gtk_button_new_with_mnemonic (_("_Show All")); ++ g_object_set (self->show_all, "margin", 24, "margin-top", 0, NULL); + gtk_widget_set_no_show_all (self->show_all, TRUE); + g_signal_connect_swapped (self->show_all, "clicked", + G_CALLBACK (gtk_shortcuts_section_show_all), self); +@@ -456,13 +493,8 @@ gtk_shortcuts_section_init (GtkShortcutsSection *self) + self->footer = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20); + GTK_CONTAINER_CLASS (gtk_shortcuts_section_parent_class)->add (GTK_CONTAINER (self), self->footer); + +- gtk_box_set_center_widget (GTK_BOX (self->footer), GTK_WIDGET (self->switcher)); + gtk_box_pack_end (GTK_BOX (self->footer), self->show_all, TRUE, TRUE, 0); + gtk_widget_set_halign (self->show_all, GTK_ALIGN_END); +- +- self->pan_gesture = gtk_gesture_pan_new (GTK_WIDGET (self->stack), GTK_ORIENTATION_HORIZONTAL); +- g_signal_connect (self->pan_gesture, "pan", +- G_CALLBACK (gtk_shortcuts_section_pan_gesture_pan), self); + } + + static void +@@ -499,6 +531,7 @@ static void + gtk_shortcuts_section_add_group (GtkShortcutsSection *self, + GtkShortcutsGroup *group) + { ++/* + GList *children; + GtkWidget *page, *column; + +@@ -523,6 +556,14 @@ gtk_shortcuts_section_add_group (GtkShortcutsSection *self, + g_list_free (children); + + gtk_container_add (GTK_CONTAINER (column), GTK_WIDGET (group)); ++*/ ++ gtk_container_add (GTK_CONTAINER (self->column), GTK_WIDGET (group)); ++ ++ g_object_set (group, ++ "accel-size-group", g_object_get_data (G_OBJECT (self->column), "accel-size-group"), ++ "title-size-group", g_object_get_data (G_OBJECT (self->column), "title-size-group"), ++ NULL); ++ + self->groups = g_list_append (self->groups, group); + + gtk_shortcuts_section_maybe_reflow (self); +@@ -570,7 +611,7 @@ gtk_shortcuts_section_filter_groups (GtkShortcutsSection *self) + gtk_widget_set_visible (GTK_WIDGET (self->show_all), self->has_filtered_group); + gtk_widget_set_visible (gtk_widget_get_parent (GTK_WIDGET (self->show_all)), + gtk_widget_get_visible (GTK_WIDGET (self->show_all)) || +- gtk_widget_get_visible (GTK_WIDGET (self->switcher))); ++ TRUE); + } + + static void +@@ -606,6 +647,9 @@ gtk_shortcuts_section_reflow_groups (GtkShortcutsSection *self) + guint n_pages; + GtkWidget *current_page, *current_column; + ++ self->need_reflow = FALSE; ++ return; ++ + /* collect all groups from the current pages */ + groups = NULL; + pages = gtk_container_get_children (GTK_CONTAINER (self->stack)); +@@ -768,7 +812,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS + gchar *title; + + title = g_strdup_printf ("_%u", n_pages + 1); +- gtk_stack_add_titled (self->stack, page, title, title); ++ gtk_stack_add_titled (GTK_STACK (self->stack), page, title, title); + g_free (title); + } + +@@ -790,6 +834,7 @@ static gboolean + gtk_shortcuts_section_change_current_page (GtkShortcutsSection *self, + gint offset) + { ++/* + GtkWidget *child; + GList *children, *l; + +@@ -812,8 +857,11 @@ gtk_shortcuts_section_change_current_page (GtkShortcutsSection *self, + g_list_free (children); + + return TRUE; ++*/ ++ return FALSE; + } + ++/* + static void + gtk_shortcuts_section_pan_gesture_pan (GtkGesturePan *gesture, + GtkPanDirection direction, +@@ -832,3 +880,4 @@ gtk_shortcuts_section_pan_gesture_pan (GtkGesturePan *gesture, + + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED); + } ++*/ +diff --git a/gtk/gtkshortcutswindow.c b/gtk/gtkshortcutswindow.c +index 36f55f6..803b5d3 100644 +--- a/gtk/gtkshortcutswindow.c ++++ b/gtk/gtkshortcutswindow.c +@@ -871,7 +871,7 @@ gtk_shortcuts_window_init (GtkShortcutsWindow *self) + GtkWidget *empty; + PangoAttrList *attributes; + +- gtk_window_set_resizable (GTK_WINDOW (self), FALSE); ++ gtk_window_set_default_size (GTK_WINDOW (self), -1, 600); + gtk_window_set_type_hint (GTK_WINDOW (self), GDK_WINDOW_TYPE_HINT_DIALOG); + + g_signal_connect (self, "key-press-event", +@@ -952,6 +952,7 @@ gtk_shortcuts_window_init (GtkShortcutsWindow *self) + + priv->menu_label = g_object_new (GTK_TYPE_LABEL, + "visible", TRUE, ++ "ellipsize", PANGO_ELLIPSIZE_END, + NULL); + gtk_container_add (GTK_CONTAINER (menu_box), GTK_WIDGET (priv->menu_label)); + +@@ -986,7 +987,7 @@ gtk_shortcuts_window_init (GtkShortcutsWindow *self) + gtk_container_add (GTK_CONTAINER (priv->search_bar), GTK_WIDGET (priv->search_entry)); + g_object_set (priv->search_entry, + "placeholder-text", _("Search Shortcuts"), +- "width-chars", 40, ++ "width-chars", 30, + NULL); + g_signal_connect_object (priv->search_entry, + "search-changed", diff --git a/gtk3-mobile/messagedialog-Set-orientation-based-on-device.patch b/gtk3-mobile/messagedialog-Set-orientation-based-on-device.patch new file mode 100644 index 0000000..d6ec600 --- /dev/null +++ b/gtk3-mobile/messagedialog-Set-orientation-based-on-device.patch @@ -0,0 +1,234 @@ +From: Adrien Plazas +Date: Mon, 24 Jun 2019 14:49:07 +0200 +Subject: messagedialog: Set orientation based on device + +This makes the dialog work better with horizontally constrained screens. +--- + gtk/gtkmessagedialog.c | 39 ++++++++++++++++++++++++ + gtk/theme/Adwaita/_common.scss | 22 +++++++++++-- + gtk/theme/Adwaita/gtk-contained-dark.css | 12 ++++++-- + gtk/theme/Adwaita/gtk-contained.css | 12 ++++++-- + gtk/theme/HighContrast/gtk-contained-inverse.css | 12 ++++++-- + gtk/theme/HighContrast/gtk-contained.css | 12 ++++++-- + 6 files changed, 95 insertions(+), 14 deletions(-) + +diff --git a/gtk/gtkmessagedialog.c b/gtk/gtkmessagedialog.c +index e70c820..e3a6659 100644 +--- a/gtk/gtkmessagedialog.c ++++ b/gtk/gtkmessagedialog.c +@@ -36,6 +36,7 @@ + #include "gtkimage.h" + #include "gtkintl.h" + #include "gtkprivate.h" ++#include "gtkorientable.h" + #include "gtktypebuiltins.h" + + /** +@@ -108,6 +109,8 @@ struct _GtkMessageDialogPrivate + guint has_primary_markup : 1; + guint has_secondary_text : 1; + guint message_type : 3; ++ ++ GSettings *settings; + }; + + static void gtk_message_dialog_style_updated (GtkWidget *widget); +@@ -144,6 +147,31 @@ G_DEFINE_TYPE_WITH_CODE (GtkMessageDialog, gtk_message_dialog, GTK_TYPE_DIALOG, + + static GtkBuildableIface *parent_buildable_iface; + ++static void ++update_orientation (GtkMessageDialog *dialog) ++{ ++ GtkWidget *action_area; ++ ++ G_GNUC_BEGIN_IGNORE_DEPRECATIONS ++ action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog)); ++G_GNUC_END_IGNORE_DEPRECATIONS ++ ++ if (_gtk_get_is_phone ()) ++ gtk_orientable_set_orientation (GTK_ORIENTABLE (action_area), GTK_ORIENTATION_VERTICAL); ++ else ++ gtk_orientable_set_orientation (GTK_ORIENTABLE (action_area), GTK_ORIENTATION_HORIZONTAL); ++} ++ ++static void ++gtk_message_dialog_destroy (GtkWidget *widget) ++{ ++ GtkMessageDialog *dialog = GTK_MESSAGE_DIALOG (widget); ++ ++ g_clear_object (&dialog->priv->settings); ++ ++ GTK_WIDGET_CLASS (gtk_message_dialog_parent_class)->destroy (widget); ++} ++ + static void + gtk_message_dialog_buildable_interface_init (GtkBuildableIface *iface) + { +@@ -162,6 +190,7 @@ gtk_message_dialog_class_init (GtkMessageDialogClass *class) + gobject_class = G_OBJECT_CLASS (class); + + widget_class->style_updated = gtk_message_dialog_style_updated; ++ widget_class->destroy = gtk_message_dialog_destroy; + + gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_ALERT); + +@@ -327,6 +356,16 @@ gtk_message_dialog_init (GtkMessageDialog *dialog) + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog)); + G_GNUC_END_IGNORE_DEPRECATIONS ++ ++ priv->settings = _gtk_get_purism_settings (); ++ ++ if (priv->settings) ++ g_signal_connect_object (priv->settings, "changed::is-phone", ++ G_CALLBACK (update_orientation), dialog, ++ G_CONNECT_SWAPPED); ++ ++ update_orientation (dialog); ++ + gtk_button_box_set_layout (GTK_BUTTON_BOX (action_area), GTK_BUTTONBOX_EXPAND); + + settings = gtk_widget_get_settings (GTK_WIDGET (dialog)); +diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss +index e40e429..b6609f9 100644 +--- a/gtk/theme/Adwaita/_common.scss ++++ b/gtk/theme/Adwaita/_common.scss +@@ -3987,10 +3987,13 @@ messagedialog { // Message Dialog styling + + .dialog-action-area button { + padding: 10px 14px; // labels are not vertically centered on message dialog, this is a workaround +- border-right-style: none; +- border-bottom-style: none; + border-radius: 0; + -gtk-outline-radius: 0; ++ } ++ ++ .dialog-action-area.horizontal button { ++ border-right-style: none; ++ border-bottom-style: none; + + &:first-child { + border-left-style: none; +@@ -4003,6 +4006,21 @@ messagedialog { // Message Dialog styling + -gtk-outline-bottom-right-radius: $button_radius + 2; + } + } ++ ++ .dialog-action-area.vertical button { ++ border-right-style: none; ++ border-left-style: none; ++ border-radius: 0; ++ -gtk-outline-radius: 0; ++ ++ &:last-child { ++ border-bottom-style: none; ++ border-bottom-left-radius: $button_radius + 2; ++ border-bottom-right-radius: $button_radius + 2; ++ -gtk-outline-bottom-left-radius: $button_radius + 2; ++ -gtk-outline-bottom-right-radius: $button_radius + 2; ++ } ++ } + } + } + +diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css +index 3cd917d..76e816b 100644 +--- a/gtk/theme/Adwaita/gtk-contained-dark.css ++++ b/gtk/theme/Adwaita/gtk-contained-dark.css +@@ -1602,11 +1602,17 @@ messagedialog .titlebar { min-height: 20px; background-image: none; background-c + + messagedialog.csd.background { border-bottom-left-radius: 9px; border-bottom-right-radius: 9px; } + +-messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-right-style: none; border-bottom-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-radius: 0; -gtk-outline-radius: 0; } + +-messagedialog.csd .dialog-action-area button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button { border-right-style: none; border-bottom-style: none; } + +-messagedialog.csd .dialog-action-area button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.horizontal button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.vertical button { border-right-style: none; border-left-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++ ++messagedialog.csd .dialog-action-area.vertical button:last-child { border-bottom-style: none; border-bottom-left-radius: 7px; border-bottom-right-radius: 7px; -gtk-outline-bottom-left-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } + + filechooser .dialog-action-box { border-top: 1px solid #1b1b1b; } + +diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css +index 4eff74f..ffbd2ae 100644 +--- a/gtk/theme/Adwaita/gtk-contained.css ++++ b/gtk/theme/Adwaita/gtk-contained.css +@@ -1618,11 +1618,17 @@ messagedialog .titlebar { min-height: 20px; background-image: none; background-c + + messagedialog.csd.background { border-bottom-left-radius: 9px; border-bottom-right-radius: 9px; } + +-messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-right-style: none; border-bottom-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-radius: 0; -gtk-outline-radius: 0; } + +-messagedialog.csd .dialog-action-area button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button { border-right-style: none; border-bottom-style: none; } + +-messagedialog.csd .dialog-action-area button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.horizontal button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.vertical button { border-right-style: none; border-left-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++ ++messagedialog.csd .dialog-action-area.vertical button:last-child { border-bottom-style: none; border-bottom-left-radius: 7px; border-bottom-right-radius: 7px; -gtk-outline-bottom-left-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } + + filechooser .dialog-action-box { border-top: 1px solid #cdc7c2; } + +diff --git a/gtk/theme/HighContrast/gtk-contained-inverse.css b/gtk/theme/HighContrast/gtk-contained-inverse.css +index 5a2cf09..7e9f8ec 100644 +--- a/gtk/theme/HighContrast/gtk-contained-inverse.css ++++ b/gtk/theme/HighContrast/gtk-contained-inverse.css +@@ -1682,11 +1682,17 @@ messagedialog .titlebar { min-height: 20px; background-image: none; background-c + + messagedialog.csd.background { border-bottom-left-radius: 9px; border-bottom-right-radius: 9px; } + +-messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-right-style: none; border-bottom-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-radius: 0; -gtk-outline-radius: 0; } + +-messagedialog.csd .dialog-action-area button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button { border-right-style: none; border-bottom-style: none; } + +-messagedialog.csd .dialog-action-area button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.horizontal button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.vertical button { border-right-style: none; border-left-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++ ++messagedialog.csd .dialog-action-area.vertical button:last-child { border-bottom-style: none; border-bottom-left-radius: 7px; border-bottom-right-radius: 7px; -gtk-outline-bottom-left-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } + + filechooser .dialog-action-box { border-top: 1px solid #686868; } + +diff --git a/gtk/theme/HighContrast/gtk-contained.css b/gtk/theme/HighContrast/gtk-contained.css +index ba598cc..20fbd2c 100644 +--- a/gtk/theme/HighContrast/gtk-contained.css ++++ b/gtk/theme/HighContrast/gtk-contained.css +@@ -1698,11 +1698,17 @@ messagedialog .titlebar { min-height: 20px; background-image: none; background-c + + messagedialog.csd.background { border-bottom-left-radius: 9px; border-bottom-right-radius: 9px; } + +-messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-right-style: none; border-bottom-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++messagedialog.csd .dialog-action-area button { padding: 10px 14px; border-radius: 0; -gtk-outline-radius: 0; } + +-messagedialog.csd .dialog-action-area button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button { border-right-style: none; border-bottom-style: none; } + +-messagedialog.csd .dialog-action-area button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++messagedialog.csd .dialog-action-area.horizontal button:first-child { border-left-style: none; border-bottom-left-radius: 7px; -gtk-outline-bottom-left-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.horizontal button:last-child { border-bottom-right-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } ++ ++messagedialog.csd .dialog-action-area.vertical button { border-right-style: none; border-left-style: none; border-radius: 0; -gtk-outline-radius: 0; } ++ ++messagedialog.csd .dialog-action-area.vertical button:last-child { border-bottom-style: none; border-bottom-left-radius: 7px; border-bottom-right-radius: 7px; -gtk-outline-bottom-left-radius: 7px; -gtk-outline-bottom-right-radius: 7px; } + + filechooser .dialog-action-box { border-top: 1px solid #877b6e; } + diff --git a/gtk3-mobile/printunixdialog-Adapt-for-phones.patch b/gtk3-mobile/printunixdialog-Adapt-for-phones.patch new file mode 100644 index 0000000..4227125 --- /dev/null +++ b/gtk3-mobile/printunixdialog-Adapt-for-phones.patch @@ -0,0 +1,492 @@ +From: Alexander Mikhaylenko +Date: Mon, 12 Oct 2020 18:07:07 +0500 +Subject: printunixdialog: Adapt for phones + +This makes the dialog work better with horizontally constrained screens. +--- + gtk/gtkprinteroptionwidget.c | 40 ++++++++++++++++ + gtk/gtkprintunixdialog.c | 76 +++++++++++++++++++++++++++-- + gtk/ui/gtkprintunixdialog.ui | 111 +++++++++++++++++++++++++++++-------------- + 3 files changed, 186 insertions(+), 41 deletions(-) + +diff --git a/gtk/gtkprinteroptionwidget.c b/gtk/gtkprinteroptionwidget.c +index e4bf137..2465581 100644 +--- a/gtk/gtkprinteroptionwidget.c ++++ b/gtk/gtkprinteroptionwidget.c +@@ -69,6 +69,8 @@ struct GtkPrinterOptionWidgetPrivate + + /* the last location for save to file, that the user selected */ + gchar *last_location; ++ ++ GSettings *settings; + }; + + enum { +@@ -96,6 +98,17 @@ static void gtk_printer_option_widget_get_property (GObject *object, + static gboolean gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling); + ++static void ++gtk_printer_option_widget_destroy (GtkWidget *widget) ++{ ++ GtkPrinterOptionWidget *powidget = GTK_PRINTER_OPTION_WIDGET (widget); ++ GtkPrinterOptionWidgetPrivate *priv = powidget->priv; ++ ++ g_clear_object (&priv->settings); ++ ++ GTK_WIDGET_CLASS (gtk_printer_option_widget_parent_class)->destroy (widget); ++} ++ + static void + gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class) + { +@@ -109,6 +122,7 @@ gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class) + object_class->set_property = gtk_printer_option_widget_set_property; + object_class->get_property = gtk_printer_option_widget_get_property; + ++ widget_class->destroy = gtk_printer_option_widget_destroy; + widget_class->mnemonic_activate = gtk_printer_option_widget_mnemonic_activate; + + signals[CHANGED] = +@@ -748,6 +762,22 @@ alternative_append (GtkWidget *box, + return gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)); + } + ++static void ++update_is_phone (GtkPrinterOptionWidget *widget) ++{ ++ GtkPrinterOptionWidgetPrivate *priv = widget->priv; ++ gboolean is_phone; ++ ++ if (!priv->box) ++ return; ++ ++ is_phone = _gtk_get_is_phone (); ++ ++ gtk_box_set_spacing (GTK_BOX (priv->box), is_phone ? 6 : 12); ++ gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), ++ is_phone ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); ++} ++ + static void + construct_widgets (GtkPrinterOptionWidget *widget) + { +@@ -822,6 +852,16 @@ construct_widgets (GtkPrinterOptionWidget *widget) + case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE: + group = NULL; + priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); ++ ++ priv->settings = _gtk_get_purism_settings (); ++ ++ if (priv->settings) ++ g_signal_connect_object (priv->settings, "changed::is-phone", ++ G_CALLBACK (update_is_phone), widget, ++ G_CONNECT_SWAPPED); ++ ++ update_is_phone (widget); ++ + gtk_widget_set_valign (priv->box, GTK_ALIGN_BASELINE); + gtk_widget_show (priv->box); + gtk_box_pack_start (GTK_BOX (widget), priv->box, TRUE, TRUE, 0); +diff --git a/gtk/gtkprintunixdialog.c b/gtk/gtkprintunixdialog.c +index 936bbef..f2eaec4 100644 +--- a/gtk/gtkprintunixdialog.c ++++ b/gtk/gtkprintunixdialog.c +@@ -263,6 +263,7 @@ struct GtkPrintUnixDialogPrivate + { + GtkWidget *notebook; + ++ GtkWidget *printer_swin; + GtkWidget *printer_treeview; + GtkTreeViewColumn *printer_icon_column; + GtkTreeViewColumn *printer_name_column; +@@ -368,6 +369,8 @@ struct GtkPrintUnixDialogPrivate + gchar *format_for_printer; + + gint current_page; ++ ++ GSettings *settings; + }; + + G_DEFINE_TYPE_WITH_CODE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG, +@@ -480,6 +483,7 @@ gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class) + "/org/gtk/libgtk/ui/gtkprintunixdialog.ui"); + + /* GtkTreeView / GtkTreeModel */ ++ gtk_widget_class_bind_template_child_private (widget_class, GtkPrintUnixDialog, printer_swin); + gtk_widget_class_bind_template_child_private (widget_class, GtkPrintUnixDialog, printer_treeview); + gtk_widget_class_bind_template_child_private (widget_class, GtkPrintUnixDialog, printer_list); + gtk_widget_class_bind_template_child_private (widget_class, GtkPrintUnixDialog, printer_list_filter); +@@ -712,6 +716,44 @@ G_GNUC_END_IGNORE_DEPRECATIONS + return FALSE; + } + ++static void ++update_is_phone (GtkPrintUnixDialog *dialog) ++{ ++ GtkPrintUnixDialogPrivate *priv = gtk_print_unix_dialog_get_instance_private (dialog); ++ gboolean is_phone = _gtk_get_is_phone (); ++ GtkPrintCapabilities caps; ++ GtkWidget *button; ++ GList *children, *l; ++ ++ gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->extension_point), ++ is_phone ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); ++ ++ caps = priv->manual_capabilities | priv->printer_capabilities; ++ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY); ++ gtk_widget_set_visible (button, (caps & GTK_PRINT_CAPABILITY_PREVIEW) != 0 && !is_phone); ++ ++ children = gtk_container_get_children (GTK_CONTAINER (priv->extension_point)); ++ l = g_list_last (children); ++ if (l && l != children) ++ gtk_widget_set_halign (GTK_WIDGET (l->data), ++ is_phone ? GTK_ALIGN_FILL : GTK_ALIGN_END); ++ ++ for (l = children; l && l->data; l = l->next) ++ { ++ GtkWidget *hbox = l->data; ++ GtkWidget *widget = g_object_get_data (G_OBJECT (l->data), "gtk-external-label"); ++ ++ if (!widget) ++ continue; ++ ++ gtk_orientable_set_orientation (GTK_ORIENTABLE (hbox), ++ is_phone ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); ++ gtk_widget_set_margin_start (widget, is_phone ? 12 : 0); ++ } ++ ++ g_list_free (children); ++} ++ + static void + gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog) + { +@@ -805,6 +847,15 @@ gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog) + + gtk_css_node_set_name (gtk_widget_get_css_node (priv->collate_image), I_("paper")); + gtk_css_node_set_name (gtk_widget_get_css_node (priv->page_layout_preview), I_("paper")); ++ ++ priv->settings = _gtk_get_purism_settings (); ++ ++ if (priv->settings) ++ g_signal_connect_object (priv->settings, "changed::is-phone", ++ G_CALLBACK (update_is_phone), dialog, ++ G_CONNECT_SWAPPED); ++ ++ update_is_phone (dialog); + } + + static void +@@ -838,6 +889,8 @@ gtk_print_unix_dialog_destroy (GtkWidget *widget) + /* Make sure we don't destroy custom widgets owned by the backends */ + clear_per_printer_ui (dialog); + ++ g_clear_object (&dialog->priv->settings); ++ + GTK_WIDGET_CLASS (gtk_print_unix_dialog_parent_class)->destroy (widget); + } + +@@ -1359,6 +1412,15 @@ add_option_to_extension_point (GtkPrinterOption *option, + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + gtk_widget_show (hbox); + ++ g_object_set_data (G_OBJECT (hbox), "gtk-external-label", widget); ++ ++ if (_gtk_get_is_phone ()) ++ { ++ gtk_orientable_set_orientation (GTK_ORIENTABLE (hbox), ++ GTK_ORIENTATION_VERTICAL); ++ gtk_widget_set_margin_start (widget, 12); ++ } ++ + gtk_box_pack_start (GTK_BOX (extension_point), hbox, TRUE, TRUE, 0); + } + else +@@ -1600,7 +1662,7 @@ update_dialog_from_settings (GtkPrintUnixDialog *dialog) + */ + children = gtk_container_get_children (GTK_CONTAINER (priv->extension_point)); + l = g_list_last (children); +- if (l && l != children) ++ if (l && l != children && !_gtk_get_is_phone ()) + gtk_widget_set_halign (GTK_WIDGET (l->data), GTK_ALIGN_END); + g_list_free (children); + +@@ -1660,7 +1722,6 @@ update_dialog_from_capabilities (GtkPrintUnixDialog *dialog) + GtkPrintUnixDialogPrivate *priv = dialog->priv; + gboolean can_collate; + const gchar *copies; +- GtkWidget *button; + + copies = gtk_entry_get_text (GTK_ENTRY (priv->copies_spin)); + can_collate = (*copies != '\0' && atoi (copies) > 1); +@@ -1681,9 +1742,7 @@ update_dialog_from_capabilities (GtkPrintUnixDialog *dialog) + gtk_widget_set_sensitive (GTK_WIDGET (priv->pages_per_sheet), + caps & GTK_PRINT_CAPABILITY_NUMBER_UP); + +- button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY); +- gtk_widget_set_visible (button, (caps & GTK_PRINT_CAPABILITY_PREVIEW) != 0); +- ++ update_is_phone (dialog); + update_collate_icon (NULL, dialog); + + gtk_tree_model_filter_refilter (priv->printer_list_filter); +@@ -3749,6 +3808,13 @@ gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog, + GtkWidget *child, + GtkWidget *tab_label) + { ++ GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); ++ ++ gtk_container_add (GTK_CONTAINER (scrolled_window), child); ++ gtk_widget_show (child); ++ ++ child = scrolled_window; ++ + gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->priv->notebook), + child, tab_label, 2); + gtk_widget_show (child); +diff --git a/gtk/ui/gtkprintunixdialog.ui b/gtk/ui/gtkprintunixdialog.ui +index e4e552a..e2ba70b 100644 +--- a/gtk/ui/gtkprintunixdialog.ui ++++ b/gtk/ui/gtkprintunixdialog.ui +@@ -50,6 +50,8 @@ +