### Run C Example Source: https://github.com/gnome/libhandy/blob/main/README.md Execute a C example provided by the Handy library. This command assumes the library has been built. ```sh _build/examples/example ``` -------------------------------- ### Building libhandy with Meson Source: https://context7.com/gnome/libhandy/llms.txt Commands to configure, build, install, and run libhandy and its examples using the Meson build system. Enables documentation, examples, tests, and introspection. ```sh # Configure build (enable docs and examples) meson setup _build \ -Dgtk_doc=true \ -Dexamples=true \ -Dtests=true \ -Dintrospection=enabled \ -Dvapi=true # Build ninja -C _build # Install system-wide sudo ninja -C _build install # Run the demo application _build/examples/handy-demo # Run Python example (sets up GI search paths automatically) _build/run examples/example.py # Run tests ninja -C _build test # Open Glade with the Handy catalog loaded _build/run glade ``` -------------------------------- ### Run Python Example Source: https://github.com/gnome/libhandy/blob/main/README.md Execute a Python example provided by the Handy library. Use the provided run script to set necessary environment variables. ```sh _build/run examples/example.py ``` -------------------------------- ### Build and Install Libhandy Source: https://github.com/gnome/libhandy/blob/main/doc/build-howto.md Clone the Libhandy repository, configure the build with Meson, and build and install using Ninja. ```bash git clone https://gitlab.gnome.org/GNOME/libhandy.git cd libhandy meson . _build ninja -C _build test ninja -C _build install ``` -------------------------------- ### Build Handy Library with Meson Source: https://github.com/gnome/libhandy/blob/main/README.md Standard commands to build and install the Handy library using Meson and Ninja. Ensure you are in the project's root directory. ```sh meson . _build ninja -C _build ninja -C _build install ``` -------------------------------- ### Bundle Libhandy as a Meson Subproject Source: https://github.com/gnome/libhandy/blob/main/doc/build-howto.md Configure your Meson build to bundle Libhandy as a subproject if it's not installed, disabling examples and tests. ```meson libhandy_dep = dependency('libhandy-1', version: '>= 1', required: false) if not libhandy_dep.found() libhandy = subproject( 'libhandy', install: false, default_options: [ 'examples=false', 'package_subdir=my-project-name', 'tests=false', ] ) libhandy_dep = libhandy.get_variable('libhandy_dep') endif ``` -------------------------------- ### Install Build Dependencies on macOS with Brew Source: https://github.com/gnome/libhandy/blob/main/doc/build-howto.md Install necessary build tools and libraries for Libhandy on macOS using the Homebrew package manager. ```bash brew install pkg-config gtk+3 adwaita-icon-theme meson glade gobject-introspection vala ``` -------------------------------- ### Run Glade Interface Designer Source: https://github.com/gnome/libhandy/blob/main/README.md Launch Glade with Handy widgets available for use without installing the library. This command uses the provided run script. ```sh _build/run glade ``` -------------------------------- ### Control Application Color Scheme with HdyStyleManager Source: https://context7.com/gnome/libhandy/llms.txt Shows how to get the default style manager, check system support for color schemes, and set the application's color scheme to force dark, prefer light, or use the system default. Also demonstrates querying the current dark and high-contrast status. ```c #include HdyStyleManager *manager = hdy_style_manager_get_default (); /* Check if the system exposes a color scheme preference */ if (hdy_style_manager_get_system_supports_color_schemes (manager)) { g_print ("System supports color scheme preference\n"); } /* Force the app to always use dark theme */ hdy_style_manager_set_color_scheme (manager, HDY_COLOR_SCHEME_FORCE_DARK); /* Or follow the system preference, preferring light if unavailable */ hdy_style_manager_set_color_scheme (manager, HDY_COLOR_SCHEME_PREFER_LIGHT); /* Query current appearance */ gboolean is_dark = hdy_style_manager_get_dark (manager); gboolean is_hc = hdy_style_manager_get_high_contrast (manager); g_print ("Dark: %s, High contrast: %s\n", is_dark ? "yes" : "no", is_hc ? "yes" : "no"); /* Per-display style manager */ GdkDisplay *display = gdk_display_get_default (); HdyStyleManager *display_mgr = hdy_style_manager_get_for_display (display); hdy_style_manager_set_color_scheme (display_mgr, HDY_COLOR_SCHEME_DEFAULT); ``` -------------------------------- ### Constrain Widget Width with HdyClamp Source: https://context7.com/gnome/libhandy/llms.txt This example shows how to use HdyClamp to limit a child widget's maximum width and define a tightening threshold for responsive design. It also demonstrates querying the current settings. ```c #include GtkWidget *clamp = hdy_clamp_new (); /* Maximum content width: 600px */ hdy_clamp_set_maximum_size (HDY_CLAMP (clamp), 600); /* Start tightening at 400px */ hdy_clamp_set_tightening_threshold (HDY_CLAMP (clamp), 400); /* Add any widget as content */ GtkWidget *list_box = gtk_list_box_new (); gtk_container_add (GTK_CONTAINER (clamp), list_box); /* Query current settings */ g_print ("Max size: %d, threshold: %d\n", hdy_clamp_get_maximum_size (HDY_CLAMP (clamp)), hdy_clamp_get_tightening_threshold (HDY_CLAMP (clamp))); ``` -------------------------------- ### Braces Style - Good Example Source: https://github.com/gnome/libhandy/blob/main/HACKING.md For code blocks other than functions and structs, place the opening curly brace on the same line as the control statement. This is the preferred style. ```c if (i < 0) { ... } ``` -------------------------------- ### Create and Configure HdyKeypad Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates creating a HdyKeypad, linking it to a GtkEntry, and setting custom action buttons. Ensure symbols and letters are visible as needed. ```c #include GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); GtkWidget *entry = gtk_entry_new (); gtk_entry_set_placeholder_text (GTK_ENTRY (entry), "Phone number"); /* symbols_visible: show *, # ; letters_visible: show ABC, DEF... */ GtkWidget *keypad = hdy_keypad_new (TRUE, TRUE); hdy_keypad_set_entry (HDY_KEYPAD (keypad), GTK_ENTRY (entry)); /* Adjust spacing */ hdy_keypad_set_row_spacing (HDY_KEYPAD (keypad), 6); hdy_keypad_set_column_spacing (HDY_KEYPAD (keypad), 6); /* Custom action buttons */ GtkWidget *call_btn = gtk_button_new_from_icon_name ("call-start-symbolic", GTK_ICON_SIZE_BUTTON); hdy_keypad_set_end_action (HDY_KEYPAD (keypad), call_btn); GtkWidget *del_btn = gtk_button_new_from_icon_name ("edit-clear-symbolic", GTK_ICON_SIZE_BUTTON); hdy_keypad_set_start_action (HDY_KEYPAD (keypad), del_btn); gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (box), keypad, TRUE, TRUE, 0); ``` -------------------------------- ### Build Handy Library with Documentation Source: https://github.com/gnome/libhandy/blob/main/README.md Command to build the Handy library with documentation enabled using Meson. This requires setting the gtk_doc option to true. ```sh meson . _build -Dgtk_doc=true ninja -C _build ``` -------------------------------- ### Create and Manage HdyTabView and HdyTabBar Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates the creation of a tab view and tab bar, adding pages, setting properties like pinned tabs and loading indicators, and handling page closing. Ensure necessary includes for Handys and GTK. ```c #include /* Create tab view and bar */ HdyTabView *view = hdy_tab_view_new (); HdyTabBar *bar = hdy_tab_bar_new (); hdy_tab_bar_set_view (bar, view); hdy_tab_bar_set_autohide (bar, FALSE); /* Always show bar */ hdy_tab_bar_set_expand_tabs (bar, TRUE); /* Tabs fill the bar width */ /* Add pages */ GtkWidget *page1_content = gtk_label_new ("Browser Tab 1"); HdyTabPage *page1 = hdy_tab_view_append (view, page1_content); hdy_tab_page_set_title (page1, "New Tab"); hdy_tab_page_set_icon (page1, g_themed_icon_new ("text-html-symbolic")); GtkWidget *page2_content = gtk_label_new ("Browser Tab 2"); HdyTabPage *page2 = hdy_tab_view_append (view, page2_content); hdy_tab_page_set_title (page2, "Wikipedia"); hdy_tab_page_set_loading (page2, TRUE); /* Show loading spinner */ /* Pin a tab (pinned tabs appear first, no close button) */ hdy_tab_view_set_page_pinned (view, page1, TRUE); /* Select a page */ hdy_tab_view_set_selected_page (view, page2); /* Close a page with confirmation */ g_signal_connect (view, "close-page", G_CALLBACK (on_close_page), NULL); static gboolean on_close_page (HdyTabView *view, HdyTabPage *page, gpointer data) { /* Return TRUE to stop default handling and confirm manually */ hdy_tab_view_close_page_finish (view, page, TRUE /* confirm close */); return TRUE; } /* Transfer page to another window's view */ HdyTabView *other_view = get_other_window_view (); hdy_tab_view_transfer_page (view, page2, other_view, 0); /* Get all pages as GListModel */ GListModel *pages = hdy_tab_view_get_pages (view); g_print ("Total tabs: %d, Pinned: %d\n", hdy_tab_view_get_n_pages (view), hdy_tab_view_get_n_pinned_pages (view)); ``` -------------------------------- ### Implement Floating Search Bar with HdySearchBar Source: https://context7.com/gnome/libhandy/llms.txt Shows how to create and configure an HdySearchBar, connect it to a search entry, and handle key events for automatic activation. Ensure the window is passed for event forwarding. ```c #include GtkWidget *search_bar = hdy_search_bar_new (); /* Create and connect the entry */ GtkWidget *entry = gtk_search_entry_new (); hdy_search_bar_connect_entry (HDY_SEARCH_BAR (search_bar), GTK_ENTRY (entry)); gtk_container_add (GTK_CONTAINER (search_bar), entry); /* Show a close button */ hdy_search_bar_set_show_close_button (HDY_SEARCH_BAR (search_bar), TRUE); /* Toggle search mode programmatically */ hdy_search_bar_set_search_mode (HDY_SEARCH_BAR (search_bar), TRUE); /* Forward key events from the window so typing activates search */ static gboolean on_key_press (GtkWidget *widget, GdkEvent *event, HdySearchBar *bar) { return hdy_search_bar_handle_event (bar, event); } g_signal_connect (window, "key-press-event", G_CALLBACK (on_key_press), search_bar); /* React to search text changes */ g_signal_connect (entry, "search-changed", G_CALLBACK (on_search_changed), model); ``` -------------------------------- ### hdy_init Source: https://context7.com/gnome/libhandy/llms.txt Initializes the Handy library. This function must be called once before using any Handy widgets to register types, load themes, and set up internal state. ```APIDOC ## hdy_init — Library Initialization Must be called once before using any Handy widget. It registers all widget types, loads CSS themes, and initializes internal state. In Python, call `Handy.init()` after importing the `Handy` GI module. ```c #include int main (int argc, char *argv[]) { gtk_init (&argc, &argv); hdy_init (); /* Must be called before creating any Handy widget */ GtkWidget *window = hdy_window_new (); gtk_window_set_title (GTK_WINDOW (window), "My App"); gtk_widget_show_all (window); gtk_main (); return 0; } ``` ```python import gi gi.require_version('Gtk', '3.0') gi.require_version('Handy', '1') from gi.repository import Gtk, Handy Handy.init() window = Handy.Window() window.connect("destroy", Gtk.main_quit) window.show_all() Gtk.main() ``` ``` -------------------------------- ### Initialize Handy Library Source: https://context7.com/gnome/libhandy/llms.txt Must be called once before using any Handy widget. In Python, call Handy.init() after importing the Handy GI module. ```c #include int main (int argc, char *argv[]) { gtk_init (&argc, &argv); hdy_init (); /* Must be called before creating any Handy widget */ GtkWidget *window = hdy_window_new (); gtk_window_set_title (GTK_WINDOW (window), "My App"); gtk_widget_show_all (window); gtk_main (); return 0; } ``` ```python import gi gi.require_version('Gtk', '3.0') gi.require_version('Handy', '1') from gi.repository import Gtk, Handy Handy.init() window = Handy.Window() window.connect("destroy", Gtk.main_quit) window.show_all() Gtk.main() ``` -------------------------------- ### Configure HdySqueezer for Adaptive Layouts Source: https://context7.com/gnome/libhandy/llms.txt Illustrates setting up an HdySqueezer with transition effects and adding child widgets that adapt to available space. Use HdyViewSwitcher for wide layouts and simpler widgets for narrow ones. Ensure the stack widget is properly initialized. ```c #include GtkWidget *squeezer = hdy_squeezer_new (); hdy_squeezer_set_transition_type (HDY_SQUEEZER (squeezer), HDY_SQUEEZER_TRANSITION_TYPE_CROSSFADE); hdy_squeezer_set_transition_duration (HDY_SQUEEZER (squeezer), 200); /* Wide child: full view switcher */ GtkWidget *wide_switcher = hdy_view_switcher_new (); hdy_view_switcher_set_policy (HDY_VIEW_SWITCHER (wide_switcher), HDY_VIEW_SWITCHER_POLICY_WIDE); hdy_view_switcher_set_stack (HDY_VIEW_SWITCHER (wide_switcher), GTK_STACK (stack)); /* Narrow child: just a label */ GtkWidget *narrow_label = gtk_label_new ("Mail"); gtk_container_add (GTK_CONTAINER (squeezer), wide_switcher); gtk_container_add (GTK_CONTAINER (squeezer), narrow_label); /* Disable a child from the competition (always skip it) */ hdy_squeezer_set_child_enabled (HDY_SQUEEZER (squeezer), narrow_label, TRUE); /* Query which child is currently visible */ GtkWidget *visible = hdy_squeezer_get_visible_child (HDY_SQUEEZER (squeezer)); ``` -------------------------------- ### Create and Configure HdyAvatar Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates creating an HdyAvatar with initials, changing its size and text, loading a custom image via GLoadableIcon, and exporting to GdkPixbuf. ```c #include /* Create avatar with initials fallback */ GtkWidget *avatar = hdy_avatar_new (48, /* size in pixels */ "Alice Example", /* text for initials */ TRUE); /* show_initials */ /* Change size and text */ hdy_avatar_set_size (HDY_AVATAR (avatar), 64); hdy_avatar_set_text (HDY_AVATAR (avatar), "Bob Smith"); /* Load a custom image via GLoadableIcon (since 1.2) */ GFile *file = g_file_new_for_path ("/path/to/profile.png"); GLoadableIcon *icon = G_LOADABLE_ICON (g_file_icon_new (file)); hdy_avatar_set_loadable_icon (HDY_AVATAR (avatar), icon); g_object_unref (icon); g_object_unref (file); /* Export the rendered avatar to a pixbuf (for saving) */ GdkPixbuf *pixbuf = hdy_avatar_draw_to_pixbuf (HDY_AVATAR (avatar), 128, /* export size */ 1); /* scale factor */ if (pixbuf) { gdk_pixbuf_save (pixbuf, "/tmp/avatar.png", "png", NULL, NULL); g_object_unref (pixbuf); } /* Async export */ hdy_avatar_draw_to_pixbuf_async (HDY_AVATAR (avatar), 128, 1, NULL, /* cancellable */ on_pixbuf_ready, NULL); ``` -------------------------------- ### Implement Adaptive View Switching with HdyViewSwitcher Widgets Source: https://context7.com/gnome/libhandy/llms.txt This snippet demonstrates how to set up HdyViewSwitcherTitle for a header bar and HdyViewSwitcherBar for a bottom bar, linked to a GtkStack. It includes binding their visibility policies for adaptive behavior. ```c #include /* Create the page stack */ GtkWidget *stack = gtk_stack_new (); gtk_stack_add_titled (GTK_STACK (stack), gtk_label_new ("Inbox"), "inbox", "Inbox"); gtk_stack_child_set (GTK_STACK (stack), gtk_stack_get_child_by_name (GTK_STACK (stack), "inbox"), "icon-name", "mail-inbox-symbolic", NULL); gtk_stack_add_titled (GTK_STACK (stack), gtk_label_new ("Sent"), "sent", "Sent"); /* Header bar with integrated view switcher title */ GtkWidget *header = hdy_header_bar_new (); hdy_header_bar_set_show_close_button (HDY_HEADER_BAR (header), TRUE); HdyViewSwitcherTitle *title = hdy_view_switcher_title_new (); hdy_view_switcher_title_set_stack (title, GTK_STACK (stack)); hdy_view_switcher_title_set_title (title, "Mail"); hdy_view_switcher_title_set_policy (title, HDY_VIEW_SWITCHER_POLICY_AUTO); hdy_header_bar_set_custom_title (HDY_HEADER_BAR (header), GTK_WIDGET (title)); /* Bottom bar shown only when header switcher is hidden (narrow) */ HdyViewSwitcherBar *bar = HDY_VIEW_SWITCHER_BAR (hdy_view_switcher_bar_new ()); hdy_view_switcher_bar_set_stack (bar, GTK_STACK (stack)); hdy_view_switcher_bar_set_policy (bar, HDY_VIEW_SWITCHER_POLICY_AUTO); /* Bind bar visibility to title's title-visible property */ g_object_bind_property (title, "title-visible", bar, "reveal", G_BINDING_SYNC_CREATE); ``` -------------------------------- ### Create Adaptive Application Window Source: https://context7.com/gnome/libhandy/llms.txt Uses HdyApplicationWindow as a drop-in replacement for GtkApplicationWindow, supporting rounded corners and content clipping for mobile form factors. ```c #include static void activate (GtkApplication *app, gpointer user_data) { GtkWidget *window = hdy_application_window_new (); gtk_window_set_application (GTK_WINDOW (window), app); gtk_window_set_title (GTK_WINDOW (window), "Adaptive App"); gtk_window_set_default_size (GTK_WINDOW (window), 360, 720); GtkWidget *header = hdy_header_bar_new (); hdy_header_bar_set_show_close_button (HDY_HEADER_BAR (header), TRUE); hdy_header_bar_set_title (HDY_HEADER_BAR (header), "Adaptive App"); GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start (GTK_BOX (box), header, FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (window), box); gtk_widget_show_all (window); } int main (int argc, char *argv[]) { GtkApplication *app = gtk_application_new ("org.example.App", G_APPLICATION_DEFAULT_FLAGS); hdy_init (); g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); return g_application_run (G_APPLICATION (app), argc, argv); } ``` -------------------------------- ### Python (PyGObject) Usage of libhandy Widgets Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates how to use various libhandy widgets like ApplicationWindow, Leaflet, HeaderBar, and Keypad in a Python application. Requires Gtk and Handy GObject Introspection bindings. ```python import gi gi.require_version('Gtk', '3.0') gi.require_version('Handy', '1') from gi.repository import Gtk, Handy, Gio Handy.init() class MyApp(Gtk.Application): def __init__(self): super().__init__(application_id='org.example.MyApp') def do_activate(self): # Adaptive window window = Handy.ApplicationWindow(application=self) window.set_default_size(360, 720) # Leaflet for adaptive navigation leaflet = Handy.Leaflet() leaflet.set_transition_type(Handy.LeafletTransitionType.OVER) leaflet.set_can_swipe_back(True) # Sidebar sidebar_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) header1 = Handy.HeaderBar() header1.set_title("Sidebar") header1.set_show_close_button(True) sidebar_box.pack_start(header1, False, False, 0) sidebar_box.pack_start(Gtk.ListBox(), True, True, 0) # Content content_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) header2 = Handy.HeaderBar() header2.set_title("Content") header2.set_show_close_button(True) content_box.pack_start(header2, False, False, 0) content_box.pack_start(Gtk.Label(label="Select an item"), True, True, 0) leaflet.add(sidebar_box) leaflet.add(content_box) # Style manager: prefer dark manager = Handy.StyleManager.get_default() manager.set_color_scheme(Handy.ColorScheme.PREFER_DARK) # Keypad example keypad_win = Gtk.Window(title="Keypad") entry = Gtk.Entry() keypad = Handy.Keypad(symbols_visible=True, letters_visible=True) keypad.set_entry(entry) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) vbox.set_margin_start(18) vbox.set_margin_end(18) vbox.set_margin_top(18) vbox.set_margin_bottom(18) vbox.pack_start(entry, False, False, 0) vbox.pack_start(keypad, True, True, 0) window.add(leaflet) window.show_all() app = MyApp() app.run(None) ``` -------------------------------- ### Build HdyPreferencesWindow Hierarchy Source: https://context7.com/gnome/libhandy/llms.txt Illustrates constructing a preferences UI using HdyPreferencesWindow, HdyPreferencesPage, and HdyPreferencesGroup. Includes adding action rows and presenting/closing subpages. ```c #include /* Build the preferences window */ GtkWidget *prefs = hdy_preferences_window_new (); hdy_preferences_window_set_search_enabled (HDY_PREFERENCES_WINDOW (prefs), TRUE); hdy_preferences_window_set_can_swipe_back (HDY_PREFERENCES_WINDOW (prefs), TRUE); /* Create a page */ GtkWidget *page = hdy_preferences_page_new (); hdy_preferences_page_set_title (HDY_PREFERENCES_PAGE (page), "General"); hdy_preferences_page_set_icon_name (HDY_PREFERENCES_PAGE (page), "preferences-system-symbolic"); /* Create a group */ GtkWidget *group = hdy_preferences_group_new (); hdy_preferences_group_set_title (HDY_PREFERENCES_GROUP (group), "Appearance"); hdy_preferences_group_set_description (HDY_PREFERENCES_GROUP (group), "Customize how the app looks."); /* Add an action row to the group */ GtkWidget *row = hdy_action_row_new (); gt k_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE); hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (row), "Dark Mode"); hdy_action_row_set_subtitle (HDY_ACTION_ROW (row), "Use dark color scheme"); GtkWidget *toggle = gtk_switch_new (); gt k_widget_set_valign (toggle, GTK_ALIGN_CENTER); hdy_action_row_add_prefix (HDY_ACTION_ROW (row), toggle); hdy_action_row_set_activatable_widget (HDY_ACTION_ROW (row), toggle); gt k_container_add (GTK_CONTAINER (group), row); gt k_container_add (GTK_CONTAINER (page), group); gt k_container_add (GTK_CONTAINER (prefs), page); /* Present a subpage (e.g. an advanced settings page) */ GtkWidget *sub = gtk_label_new ("Advanced settings here"); hdy_preferences_window_present_subpage (HDY_PREFERENCES_WINDOW (prefs), sub); /* Close it later */ hdy_preferences_window_close_subpage (HDY_PREFERENCES_WINDOW (prefs)); gt k_window_present (GTK_WINDOW (prefs)); ``` -------------------------------- ### HdyTabView and HdyTabBar Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates the creation and manipulation of tab views and tab bars, including adding pages, setting properties like pinned tabs and loading indicators, and handling tab closing events. ```APIDOC ## `HdyTabView` / `HdyTabBar` — Modern Tab Interface (since 1.2) A full-featured tab implementation with drag-and-drop reordering, pinned tabs, tab transfer between windows, loading indicators, attention badges, and a context menu. `HdyTabBar` renders the visual tab strip for a `HdyTabView`. ```c #include /* Create tab view and bar */ HdyTabView *view = hdy_tab_view_new (); HdyTabBar *bar = hdy_tab_bar_new (); hdy_tab_bar_set_view (bar, view); hdy_tab_bar_set_autohide (bar, FALSE); /* Always show bar */ hdy_tab_bar_set_expand_tabs (bar, TRUE); /* Tabs fill the bar width */ /* Add pages */ GtkWidget *page1_content = gtk_label_new ("Browser Tab 1"); HdyTabPage *page1 = hdy_tab_view_append (view, page1_content); hdy_tab_page_set_title (page1, "New Tab"); hdy_tab_page_set_icon (page1, g_themed_icon_new ("text-html-symbolic")); GtkWidget *page2_content = gtk_label_new ("Browser Tab 2"); HdyTabPage *page2 = hdy_tab_view_append (view, page2_content); hdy_tab_page_set_title (page2, "Wikipedia"); hdy_tab_page_set_loading (page2, TRUE); /* Show loading spinner */ /* Pin a tab (pinned tabs appear first, no close button) */ hdy_tab_view_set_page_pinned (view, page1, TRUE); /* Select a page */ hdy_tab_view_set_selected_page (view, page2); /* Close a page with confirmation */ g_signal_connect (view, "close-page", G_CALLBACK (on_close_page), NULL); static gboolean on_close_page (HdyTabView *view, HdyTabPage *page, gpointer data) { /* Return TRUE to stop default handling and confirm manually */ hdy_tab_view_close_page_finish (view, page, TRUE /* confirm close */); return TRUE; } /* Transfer page to another window's view */ HdyTabView *other_view = get_other_window_view (); hdy_tab_view_transfer_page (view, page2, other_view, 0); /* Get all pages as GListModel */ GListModel *pages = hdy_tab_view_get_pages (view); g_print ("Total tabs: %d, Pinned: %d\n", hdy_tab_view_get_n_pages (view), hdy_tab_view_get_n_pinned_pages (view)); ``` ``` -------------------------------- ### Create and Configure HdyStatusPage Source: https://context7.com/gnome/libhandy/llms.txt Illustrates creating a HdyStatusPage, setting its icon, title, and description. This widget is useful for displaying empty states, welcome messages, or error information. ```c #include GtkWidget *status = hdy_status_page_new (); hdy_status_page_set_icon_name (HDY_STATUS_PAGE (status), "folder-documents-symbolic"); hdy_status_page_set_title (HDY_STATUS_PAGE (status), "No Documents"); hdy_status_page_set_description (HDY_STATUS_PAGE (status), "Create or import a document to get started."); /* Use as a placeholder in a GtkStack */ GtkWidget *stack = gtk_stack_new (); GtkWidget *list = gtk_list_box_new (); /* real content */ gtk_stack_add_named (GTK_STACK (stack), list, "content"); gtk_stack_add_named (GTK_STACK (stack), status, "empty"); /* Show empty state when list has no rows */ static void update_view (GtkListBox *box, GtkStack *stack) { gboolean has_rows = gtk_list_box_get_row_at_index (box, 0) != NULL; gtk_stack_set_visible_child_name (stack, has_rows ? "content" : "empty"); } ``` -------------------------------- ### Create and Configure HdyLeaflet for Adaptive Navigation Source: https://context7.com/gnome/libhandy/llms.txt Use HdyLeaflet to build master/detail interfaces. Configure transition types and swipe gestures for intuitive navigation. Connect to the 'folded' signal to react to layout changes. ```c #include GtkWidget *leaflet = hdy_leaflet_new (); /* Create sidebar and content panes */ GtkWidget *sidebar = gtk_list_box_new (); GtkWidget *content = gtk_label_new ("Select an item"); gtk_widget_set_name (sidebar, "sidebar"); gtk_widget_set_name (content, "content"); gtk_container_add (GTK_CONTAINER (leaflet), sidebar); gtk_container_add (GTK_CONTAINER (leaflet), content); /* Use 'over' transition for a natural overlay effect */ hdy_leaflet_set_transition_type (HDY_LEAFLET (leaflet), HDY_LEAFLET_TRANSITION_TYPE_OVER); hdy_leaflet_set_can_swipe_back (HDY_LEAFLET (leaflet), TRUE); /* React to fold state change */ g_signal_connect_swapped (leaflet, "notify::folded", G_CALLBACK (on_folded_changed), leaflet); /* Navigate forward when list item clicked */ static void on_item_clicked (GtkListBox *box, GtkListBoxRow *row, HdyLeaflet *leaflet) { hdy_leaflet_set_visible_child_name (leaflet, "content"); } /* Navigate back */ static void on_back_clicked (GtkButton *btn, HdyLeaflet *leaflet) { hdy_leaflet_navigate (leaflet, HDY_NAVIGATION_DIRECTION_BACK); } ``` -------------------------------- ### HdyAvatar Widget Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates the creation and usage of the HdyAvatar widget, including setting size, text, loading images, and exporting to pixbuf. ```APIDOC ## `HdyAvatar` — User/Contact Avatar Widget Renders a circular avatar that auto-generates a colored initial-letter placeholder when no image is available. Supports loading images via `GLoadableIcon` (since 1.2) and can export to `GdkPixbuf` for saving/sharing. ```c #include /* Create avatar with initials fallback */ GtkWidget *avatar = hdy_avatar_new (48, /* size in pixels */ "Alice Example", /* text for initials */ TRUE); /* show_initials */ /* Change size and text */ hdy_avatar_set_size (HDY_AVATAR (avatar), 64); hdy_avatar_set_text (HDY_AVATAR (avatar), "Bob Smith"); /* Load a custom image via GLoadableIcon (since 1.2) */ GFile *file = g_file_new_for_path ("/path/to/profile.png"); GLoadableIcon *icon = G_LOADABLE_ICON (g_file_icon_new (file)); hdy_avatar_set_loadable_icon (HDY_AVATAR (avatar), icon); g_object_unref (icon); g_object_unref (file); /* Export the rendered avatar to a pixbuf (for saving) */ GdkPixbuf *pixbuf = hdy_avatar_draw_to_pixbuf (HDY_AVATAR (avatar), 128, /* export size */ 1); /* scale factor */ if (pixbuf) { gdk_pixbuf_save (pixbuf, "/tmp/avatar.png", "png", NULL, NULL); g_object_unref (pixbuf); } /* Async export */ hdy_avatar_draw_to_pixbuf_async (HDY_AVATAR (avatar), 128, 1, NULL, /* cancellable */ on_pixbuf_ready, NULL); ``` ``` -------------------------------- ### Run Tests with Ninja Source: https://github.com/gnome/libhandy/blob/main/HACKING.md Before submitting a pull request, ensure all tests pass by running the ninja build system. This command executes the test suite. ```sh ninja -C _build test ``` -------------------------------- ### Create and Configure HdyExpanderRow Source: https://context7.com/gnome/libhandy/llms.txt Shows how to create a collapsible row for grouping settings. Use when a parent setting should reveal related sub-settings. Supports an optional enable/disable switch for the group. ```c #include GtkWidget *expander = hdy_expander_row_new (); hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (expander), "Advanced Options"); hdy_action_row_set_subtitle (HDY_ACTION_ROW (expander), "Fine-grained control settings"); hdy_expander_row_set_expanded (HDY_EXPANDER_ROW (expander), FALSE); /* Show enable switch to allow disabling the whole group */ hdy_expander_row_set_show_enable_switch (HDY_EXPANDER_ROW (expander), TRUE); hdy_expander_row_set_enable_expansion (HDY_EXPANDER_ROW (expander), TRUE); /* Add child rows inside the expander */ GtkWidget *child_row = hdy_action_row_new (); hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (child_row), "Enable Logging"); GtkWidget *child_switch = gtk_switch_new (); gtk_widget_set_valign (child_switch, GTK_ALIGN_CENTER); hdy_action_row_add_prefix (HDY_ACTION_ROW (child_row), child_switch); gtk_container_add (GTK_CONTAINER (expander), child_row); /* Add an action widget (appears before the arrow) */ GtkWidget *info_btn = gtk_button_new_from_icon_name ("dialog-information-symbolic", GTK_ICON_SIZE_BUTTON); hdy_expander_row_add_action (HDY_EXPANDER_ROW (expander), info_btn); ``` -------------------------------- ### Create and Configure HdyComboRow Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates creating a dropdown selection row. Use for choosing from a list of options. Supports binding to a GListModel or populating directly from a GType enum. ```c #include GtkWidget *combo = hdy_combo_row_new (); hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (combo), "Theme"); /* Option 1: Bind to a string list model */ GtkStringList *model = gtk_string_list_new (NULL); /* Build a GListStore of HdyValueObject for simple string lists */ GListStore *store = g_list_store_new (HDY_TYPE_VALUE_OBJECT); const char *themes[] = { "Default", "Dark", "Light", NULL }; for (int i = 0; themes[i]; i++) { GValue val = G_VALUE_INIT; g_value_init (&val, G_TYPE_STRING); g_value_set_string (&val, themes[i]); HdyValueObject *obj = hdy_value_object_new (&val); g_list_store_append (store, obj); g_object_unref (obj); } hdy_combo_row_bind_name_model (HDY_COMBO_ROW (combo), G_LIST_MODEL (store), (HdyComboRowGetNameFunc) hdy_value_object_dup_string, NULL, NULL); /* Option 2: Populate from a GType enum */ GtkWidget *combo2 = hdy_combo_row_new (); hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (combo2), "Color Scheme"); hdy_combo_row_set_for_enum (HDY_COMBO_ROW (combo2), HDY_TYPE_COLOR_SCHEME, hdy_enum_value_row_name, NULL, NULL); /* Query/set selection */ gint idx = hdy_combo_row_get_selected_index (HDY_COMBO_ROW (combo)); hdy_combo_row_set_selected_index (HDY_COMBO_ROW (combo), 1); /* Show selection as subtitle */ hdy_combo_row_set_use_subtitle (HDY_COMBO_ROW (combo), TRUE); ``` -------------------------------- ### Flatpak Manifest for Libhandy Source: https://github.com/gnome/libhandy/blob/main/doc/build-howto.md Include Libhandy as a module in your Flatpak manifest, specifying the build system and source repository. ```json { "name" : "libhandy", "buildsystem" : "meson", "config-opts": [ "-Dexamples=false", "-Dtests=false" ], "sources" : [ { "type" : "git", "url" : "https://gitlab.gnome.org/GNOME/libhandy.git" } ] } ``` -------------------------------- ### HdyWindow / HdyApplicationWindow Source: https://context7.com/gnome/libhandy/llms.txt Adaptive Window Base Classes. These classes are replacements for GtkWindow and GtkApplicationWindow, offering support for rounded corners and proper content clipping suitable for mobile form factors. ```APIDOC ## HdyWindow / HdyApplicationWindow — Adaptive Window Base Classes `HdyWindow` and `HdyApplicationWindow` are drop-in replacements for `GtkWindow` and `GtkApplicationWindow` that support rounded window corners and proper content clipping required for mobile form factors. They serve as the recommended top-level container for Handy applications. ```c #include static void activate (GtkApplication *app, gpointer user_data) { GtkWidget *window = hdy_application_window_new (); gtk_window_set_application (GTK_WINDOW (window), app); gtk_window_set_title (GTK_WINDOW (window), "Adaptive App"); gtk_window_set_default_size (GTK_WINDOW (window), 360, 720); GtkWidget *header = hdy_header_bar_new (); hdy_header_bar_set_show_close_button (HDY_HEADER_BAR (header), TRUE); hdy_header_bar_set_title (HDY_HEADER_BAR (header), "Adaptive App"); GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start (GTK_BOX (box), header, FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (window), box); gtk_widget_show_all (window); } int main (int argc, char *argv[]) { GtkApplication *app = gtk_application_new ("org.example.App", G_APPLICATION_DEFAULT_FLAGS); hdy_init (); g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); return g_application_run (G_APPLICATION (app), argc, argv); } ``` ``` -------------------------------- ### Create and Configure HdyActionRow Source: https://context7.com/gnome/libhandy/llms.txt Demonstrates creating a basic action row with title, subtitle, icon, and prefix widget. Use for list items requiring text and optional leading elements. Supports setting text line limits. ```c #include GtkWidget *list = gtk_list_box_new (); /* Basic action row with icon and subtitle */ GtkWidget *row = hdy_action_row_new (); hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (row), "Notifications"); hdy_action_row_set_subtitle (HDY_ACTION_ROW (row), "Show alerts for new messages"); hdy_action_row_set_icon_name (HDY_ACTION_ROW (row), "notification-symbolic"); /* Prefix widget (leading, before title) */ GtkWidget *icon = gtk_image_new_from_icon_name ("emblem-important-symbolic", GTK_ICON_SIZE_BUTTON); hdy_action_row_add_prefix (HDY_ACTION_ROW (row), icon); /* Activatable widget (the row activates this widget on click) */ GtkWidget *sw = gtk_switch_new (); gtk_widget_set_valign (sw, GTK_ALIGN_CENTER); hdy_action_row_set_activatable_widget (HDY_ACTION_ROW (row), sw); gtk_container_add (GTK_CONTAINER (row), sw); /* Limit text to 2 lines */ hdy_action_row_set_title_lines (HDY_ACTION_ROW (row), 1); hdy_action_row_set_subtitle_lines (HDY_ACTION_ROW (row), 2); gtk_container_add (GTK_CONTAINER (list), row); /* Programmatic activation */ hdy_action_row_activate (HDY_ACTION_ROW (row)); ``` -------------------------------- ### HdySqueezer Source: https://context7.com/gnome/libhandy/llms.txt Explains how to use the HdySqueezer widget to display adaptive content, including setting transition types and durations, adding child widgets, and querying the currently visible child. ```APIDOC ## `HdySqueezer` — Adaptive Widget Selector Displays the largest child widget that fits within the available width, automatically switching to smaller alternatives as space shrinks. Ideal for adaptive title bars that swap a full view-switcher for a compact label on narrow screens. ```c #include GtkWidget *squeezer = hdy_squeezer_new (); hdy_squeezer_set_transition_type (HDY_SQUEEZER (squeezer), HDY_SQUEEZER_TRANSITION_TYPE_CROSSFADE); hdy_squeezer_set_transition_duration (HDY_SQUEEZER (squeezer), 200); /* Wide child: full view switcher */ GtkWidget *wide_switcher = hdy_view_switcher_new (); hdy_view_switcher_set_policy (HDY_VIEW_SWITCHER (wide_switcher), HDY_VIEW_SWITCHER_POLICY_WIDE); hdy_view_switcher_set_stack (HDY_VIEW_SWITCHER (wide_switcher), GTK_STACK (stack)); /* Narrow child: just a label */ GtkWidget *narrow_label = gtk_label_new ("Mail"); gtk_container_add (GTK_CONTAINER (squeezer), wide_switcher); gtk_container_add (GTK_CONTAINER (squeezer), narrow_label); /* Disable a child from the competition (always skip it) */ hdy_squeezer_set_child_enabled (HDY_SQUEEZER (squeezer), narrow_label, TRUE); /* Query which child is currently visible */ GtkWidget *visible = hdy_squeezer_get_visible_child (HDY_SQUEEZER (squeezer)); ``` ``` -------------------------------- ### Link Application with Libhandy on macOS Source: https://github.com/gnome/libhandy/blob/main/doc/build-howto.md Compile your C application, linking against GTK+3 and Libhandy using pkg-config. ```bash gcc $(pkg-config --cflags --libs gtk+-3.0) $(pkg-config --cflags --libs libhandy-1) main.c -o main ``` -------------------------------- ### Check Libhandy Module with Autoconf Source: https://github.com/gnome/libhandy/blob/main/doc/build-howto.md Use PKG_CHECK_MODULES in your configure.ac script to check for the libhandy-1 package and substitute its CFLAGS and LIBS. ```autoconf PKG_CHECK_MODULES(LIBHANDY, [libhandy-1]) AC_SUBST(LIBHANDY_CFLAGS) AC_SUBST(LIBHANDY_LIBS) ``` -------------------------------- ### HdyPreferencesWindow Hierarchy Source: https://context7.com/gnome/libhandy/llms.txt Illustrates the construction of preference UIs using HdyPreferencesWindow, HdyPreferencesPage, and HdyPreferencesGroup. ```APIDOC ## `HdyPreferencesWindow` / `HdyPreferencesPage` / `HdyPreferencesGroup` — Preferences UI Hierarchy A three-level widget hierarchy for building GNOME-style preferences dialogs. `HdyPreferencesWindow` provides search, subpage navigation, and swipe-back. `HdyPreferencesPage` holds groups, and `HdyPreferencesGroup` organizes related preference rows. ```c #include /* Build the preferences window */ GtkWidget *prefs = hdy_preferences_window_new (); hdy_preferences_window_set_search_enabled (HDY_PREFERENCES_WINDOW (prefs), TRUE); hdy_preferences_window_set_can_swipe_back (HDY_PREFERENCES_WINDOW (prefs), TRUE); /* Create a page */ GtkWidget *page = hdy_preferences_page_new (); hdy_preferences_page_set_title (HDY_PREFERENCES_PAGE (page), "General"); hdy_preferences_page_set_icon_name (HDY_PREFERENCES_PAGE (page), "preferences-system-symbolic"); /* Create a group */ GtkWidget *group = hdy_preferences_group_new (); hdy_preferences_group_set_title (HDY_PREFERENCES_GROUP (group), "Appearance"); hdy_preferences_group_set_description (HDY_PREFERENCES_GROUP (group), "Customize how the app looks."); /* Add an action row to the group */ GtkWidget *row = hdy_action_row_new (); gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE); hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (row), "Dark Mode"); hdy_action_row_set_subtitle (HDY_ACTION_ROW (row), "Use dark color scheme"); GtkWidget *toggle = gtk_switch_new (); gtk_widget_set_valign (toggle, GTK_ALIGN_CENTER); hdy_action_row_add_prefix (HDY_ACTION_ROW (row), toggle); hdy_action_row_set_activatable_widget (HDY_ACTION_ROW (row), toggle); gtk_container_add (GTK_CONTAINER (group), row); gtk_container_add (GTK_CONTAINER (page), group); gtk_container_add (GTK_CONTAINER (prefs), page); /* Present a subpage (e.g. an advanced settings page) */ GtkWidget *sub = gtk_label_new ("Advanced settings here"); hdy_preferences_window_present_subpage (HDY_PREFERENCES_WINDOW (prefs), sub); /* Close it later */ hdy_preferences_window_close_subpage (HDY_PREFERENCES_WINDOW (prefs)); gtk_window_present (GTK_WINDOW (prefs)); ``` ``` -------------------------------- ### HdyStatusPage Source: https://context7.com/gnome/libhandy/llms.txt A centered placeholder widget for empty states, welcome screens, and error pages. Displays a large icon, title, and optional description text following the GNOME HIG design. ```APIDOC ## `hdy_status_page_new` ### Description Creates a new `HdyStatusPage` widget. ### Returns A new `GtkWidget` representing the status page. ``` ```APIDOC ## `hdy_status_page_set_icon_name` ### Description Sets the icon name for the status page. ### Parameters - `status_page` (HdyStatusPage) - The status page widget. - `icon_name` (string) - The name of the icon to display. ``` ```APIDOC ## `hdy_status_page_set_title` ### Description Sets the title text for the status page. ### Parameters - `status_page` (HdyStatusPage) - The status page widget. - `title` (string) - The title text. ``` ```APIDOC ## `hdy_status_page_set_description` ### Description Sets the description text for the status page. ### Parameters - `status_page` (HdyStatusPage) - The status page widget. - `description` (string) - The description text. ```