BlinkGTK Settings API Tutorial (C Language)

Target Audience: C Programmers, GTK4 Beginners to Intermediate
Last Updated: 2026-01-01
Language: English |

日本語


Table of Contents

  1. Introduction
  2. Basic Usage
  3. JavaScript Control
  4. User-Agent Modification
  5. Image Loading Control
  6. Local Storage Control
  7. Practical Examples
  8. Troubleshooting

Introduction

The BlinkGTK Settings API allows you to customize browser behavior in detail.

Prerequisites

Development Environment Setup

# Install required packages (Fedora/RHEL)
sudo dnf install gtk4-devel

# Build BlinkGTK (see separate documentation)

Basic Usage

Minimal Program

#include <blink_gtk/blink_gtk.h>
#include <gtk/gtk.h>

static void on_activate(GtkApplication* app, gpointer user_data) {
    // Create window
    GtkWidget* window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "BlinkGTK Settings Example");
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);

    // Create WebView
    GtkWidget* web_view = blink_web_view_new();
    gtk_window_set_child(GTK_WINDOW(window), web_view);

    // Load URL
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");

    // Show window
    gtk_window_present(GTK_WINDOW(window));
}

int main(int argc, char* argv[]) {
    // Initialize BlinkGTK
    if (!blink_gtk_init(&argc, &argv)) {
        g_critical("Failed to initialize BlinkGTK");
        return 1;
    }

    // Create application
    GtkApplication* app = gtk_application_new(
        "org.example.blinkgtk",
        G_APPLICATION_DEFAULT_FLAGS);

    g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL);

    /* Note g_application_run() は使用禁止 — Chromium RunLoop が飢餓状態になる
     * g_application_register/activate で GtkApplication シグナルを発火させてから
     * blink_gtk_run_main_loop() でChromium RunLoop を起動する */
    g_application_register(G_APPLICATION(app), NULL, NULL);
    g_application_activate(G_APPLICATION(app));
    int status = blink_gtk_run_main_loop();

    g_object_unref(app);
    blink_gtk_shutdown();

    return status;
}

Compilation

gcc -o example example.c \
    `pkg-config --cflags --libs gtk4` \
    -lblinkgtk

JavaScript Control

Disabling JavaScript

For security-critical cases or when JavaScript is not needed:

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "JavaScript Disabled");
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);

    GtkWidget* web_view = blink_web_view_new();

    // Disable JavaScript
    blink_web_view_set_javascript_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    gtk_window_set_child(GTK_WINDOW(window), web_view);
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");
    gtk_window_present(GTK_WINDOW(window));
}

JavaScript Toggle

Control JavaScript with toggle button:

static void on_js_toggle(GtkToggleButton* button, gpointer user_data) {
    GtkWidget* web_view = GTK_WIDGET(user_data);
    gboolean active = gtk_toggle_button_get_active(button);

    blink_web_view_set_javascript_enabled(BLINK_WEB_VIEW(web_view), active);

    if (active) {
        g_print("JavaScript enabled\n");
    } else {
        g_print("JavaScript disabled\n");
    }

    // Reload page to apply settings
    blink_web_view_reload(BLINK_WEB_VIEW(web_view));
}

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    GtkWidget* toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
    GtkWidget* web_view = blink_web_view_new();

    // JavaScript toggle button
    GtkWidget* js_toggle = gtk_toggle_button_new_with_label("Enable JavaScript");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(js_toggle), TRUE);
    g_signal_connect(js_toggle, "toggled", G_CALLBACK(on_js_toggle), web_view);

    gtk_box_append(GTK_BOX(toolbar), js_toggle);
    gtk_box_append(GTK_BOX(box), toolbar);
    gtk_box_append(GTK_BOX(box), web_view);
    gtk_widget_set_vexpand(web_view, TRUE);

    gtk_window_set_child(GTK_WINDOW(window), box);
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");
    gtk_window_present(GTK_WINDOW(window));
}

User-Agent Modification

Custom User-Agent

Set custom browser identifier:

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    GtkWidget* web_view = blink_web_view_new();

    // Set custom User-Agent
    blink_web_view_set_user_agent(web_view, "MyApp/1.0 (Linux; BlinkGTK)");

    gtk_window_set_child(GTK_WINDOW(window), web_view);

    // User-Agent test site
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://httpbin.org/user-agent");

    gtk_window_present(GTK_WINDOW(window));
}

Mobile User-Agent

Emulate mobile device:

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    GtkWidget* web_view = blink_web_view_new();

    // Android Chrome User-Agent
    const char* mobile_ua =
        "Mozilla/5.0 (Linux; Android 10; Pixel 4) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/151.0.0.0 Mobile Safari/537.36";

    blink_web_view_set_user_agent(web_view, mobile_ua);

    gtk_window_set_child(GTK_WINDOW(window), web_view);
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://www.google.com");
    gtk_window_present(GTK_WINDOW(window));
}

Getting User-Agent

Check current User-Agent:

static void print_user_agent(GtkWidget* web_view) {
    char* user_agent = blink_web_view_get_user_agent(web_view);
    g_print("Current User-Agent: %s\n", user_agent);
    g_free(user_agent);  // Important: Free memory
}

Image Loading Control

Disabling Image Loading

Show text only to reduce data usage:

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    GtkWidget* web_view = blink_web_view_new();

    // Disable image loading
    blink_web_view_set_images_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    gtk_window_set_child(GTK_WINDOW(window), web_view);
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");
    gtk_window_present(GTK_WINDOW(window));
}

Image Loading Toggle

Let users toggle image display:

static void on_images_toggle(GtkToggleButton* button, gpointer user_data) {
    GtkWidget* web_view = GTK_WIDGET(user_data);
    gboolean active = gtk_toggle_button_get_active(button);

    blink_web_view_set_images_enabled(BLINK_WEB_VIEW(web_view), active);

    if (active) {
        g_print("Images enabled\n");
    } else {
        g_print("Images disabled\n");
    }

    // Reload to apply
    blink_web_view_reload(BLINK_WEB_VIEW(web_view));
}

Local Storage Control

Disabling LocalStorage

Privacy protection mode:

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    GtkWidget* web_view = blink_web_view_new();

    // Disable LocalStorage
    blink_web_view_set_local_storage_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    gtk_window_set_child(GTK_WINDOW(window), web_view);
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");
    gtk_window_present(GTK_WINDOW(window));
}

Practical Examples

Example 1: Data Saver Mode

Bandwidth-saving browser:

static void enable_data_saver_mode(GtkWidget* web_view) {
    // Disable JavaScript
    blink_web_view_set_javascript_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    // Disable image loading
    blink_web_view_set_images_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    g_print("Data saver mode enabled\n");
}

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Data Saver Browser");

    GtkWidget* web_view = blink_web_view_new();
    enable_data_saver_mode(web_view);

    gtk_window_set_child(GTK_WINDOW(window), web_view);
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");
    gtk_window_present(GTK_WINDOW(window));
}

Example 2: Privacy Browser

Maximum security settings:

static void enable_privacy_mode(GtkWidget* web_view) {
    // Disable JavaScript
    blink_web_view_set_javascript_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    // Disable LocalStorage
    blink_web_view_set_local_storage_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    // Disable image loading
    blink_web_view_set_images_enabled(BLINK_WEB_VIEW(web_view), FALSE);

    g_print("Privacy mode enabled\n");
}

static void on_activate(GtkApplication* app, gpointer user_data) {
    GtkWidget* window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Privacy Browser");

    GtkWidget* web_view = blink_web_view_new();
    enable_privacy_mode(web_view);

    gtk_window_set_child(GTK_WINDOW(window), web_view);
    blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");
    gtk_window_present(GTK_WINDOW(window));
}

Example 3: Browser with Settings Panel

Complete example with toolbar:

#include <blink_gtk/blink_gtk.h>
#include <gtk/gtk.h>

typedef struct {
    GtkWidget* web_view;
    GtkWidget* js_toggle;
    GtkWidget* images_toggle;
    GtkWidget* storage_toggle;
} AppWidgets;

static void on_js_toggle(GtkToggleButton* button, gpointer user_data) {
    AppWidgets* widgets = (AppWidgets*)user_data;
    gboolean active = gtk_toggle_button_get_active(button);
    blink_web_view_set_javascript_enabled(BLINK_WEB_VIEW(widgets->web_view), active);
    blink_web_view_reload(BLINK_WEB_VIEW(widgets->web_view));
}

static void on_images_toggle(GtkToggleButton* button, gpointer user_data) {
    AppWidgets* widgets = (AppWidgets*)user_data;
    gboolean active = gtk_toggle_button_get_active(button);
    blink_web_view_set_images_enabled(BLINK_WEB_VIEW(widgets->web_view), active);
    blink_web_view_reload(BLINK_WEB_VIEW(widgets->web_view));
}

static void on_storage_toggle(GtkToggleButton* button, gpointer user_data) {
    AppWidgets* widgets = (AppWidgets*)user_data;
    gboolean active = gtk_toggle_button_get_active(button);
    blink_web_view_set_local_storage_enabled(BLINK_WEB_VIEW(widgets->web_view), active);
    blink_web_view_reload(BLINK_WEB_VIEW(widgets->web_view));
}

static void on_activate(GtkApplication* app, gpointer user_data) {
    AppWidgets* widgets = g_new0(AppWidgets, 1);

    // Window
    GtkWidget* window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "BlinkGTK Settings Demo");
    gtk_window_set_default_size(GTK_WINDOW(window), 1024, 768);

    // Layout
    GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    GtkWidget* toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
    gtk_widget_set_margin_start(toolbar, 6);
    gtk_widget_set_margin_end(toolbar, 6);
    gtk_widget_set_margin_top(toolbar, 6);
    gtk_widget_set_margin_bottom(toolbar, 6);

    // WebView
    widgets->web_view = blink_web_view_new();
    gtk_widget_set_vexpand(widgets->web_view, TRUE);

    // Toggle buttons
    widgets->js_toggle = gtk_toggle_button_new_with_label("JavaScript");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets->js_toggle), TRUE);
    g_signal_connect(widgets->js_toggle, "toggled", G_CALLBACK(on_js_toggle), widgets);

    widgets->images_toggle = gtk_toggle_button_new_with_label("Images");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets->images_toggle), TRUE);
    g_signal_connect(widgets->images_toggle, "toggled", G_CALLBACK(on_images_toggle), widgets);

    widgets->storage_toggle = gtk_toggle_button_new_with_label("LocalStorage");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets->storage_toggle), TRUE);
    g_signal_connect(widgets->storage_toggle, "toggled", G_CALLBACK(on_storage_toggle), widgets);

    // Build toolbar
    gtk_box_append(GTK_BOX(toolbar), widgets->js_toggle);
    gtk_box_append(GTK_BOX(toolbar), widgets->images_toggle);
    gtk_box_append(GTK_BOX(toolbar), widgets->storage_toggle);

    // Build layout
    gtk_box_append(GTK_BOX(box), toolbar);
    gtk_box_append(GTK_BOX(box), widgets->web_view);

    gtk_window_set_child(GTK_WINDOW(window), box);
    blink_web_view_load_uri(BLINK_WEB_VIEW(widgets->web_view), "https://example.com");
    gtk_window_present(GTK_WINDOW(window));
}

int main(int argc, char* argv[]) {
    if (!blink_gtk_init(&argc, &argv)) {
        g_critical("Failed to initialize BlinkGTK");
        return 1;
    }

    GtkApplication* app = gtk_application_new(
        "org.example.settings-demo",
        G_APPLICATION_DEFAULT_FLAGS);

    g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL);

    /* Note g_application_run() は使用禁止 — Chromium RunLoop が飢餓状態になる
     * g_application_register/activate で GtkApplication シグナルを発火させてから
     * blink_gtk_run_main_loop() でChromium RunLoop を起動する */
    g_application_register(G_APPLICATION(app), NULL, NULL);
    g_application_activate(G_APPLICATION(app));
    int status = blink_gtk_run_main_loop();

    g_object_unref(app);
    blink_gtk_shutdown();

    return status;
}

Troubleshooting

Settings Not Applied

Problem: Called Settings API but changes not reflected

Solution: Reload the page

blink_web_view_set_javascript_enabled(BLINK_WEB_VIEW(web_view), FALSE);
blink_web_view_reload(BLINK_WEB_VIEW(web_view));  // Reload to apply

Memory Leak

Problem: Memory leak with blink_web_view_get_user_agent()

Solution: Always free memory with g_free()

char* user_agent = blink_web_view_get_user_agent(web_view);
g_print("%s\n", user_agent);
g_free(user_agent);  // Don't forget this!

Compilation Error

Problem: blink_gtk.h not found

Solution: Use pkg-config

gcc example.c $(pkg-config --cflags --libs blinkgtk-0.1)

Summary

With Settings API, you can:

Next Steps


License: BSD-3-Clause
Project: BlinkGTK
Support: https://blinkgtk.org/ / https://github.com/daisy19gnu/blinkgtk-dist/issues