Target Audience: C Programmers, GTK4 Beginners to
Intermediate
Last Updated: 2026-01-01
Language: English |
The BlinkGTK Settings API allows you to customize browser behavior in detail.
# Install required packages (Fedora/RHEL)
sudo dnf install gtk4-devel
# Build BlinkGTK (see separate documentation)#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;
}gcc -o example example.c \
`pkg-config --cflags --libs gtk4` \
-lblinkgtkFor 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));
}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));
}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));
}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));
}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
}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));
}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));
}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));
}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));
}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));
}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;
}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 applyProblem: 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!Problem: blink_gtk.h not found
Solution: Use pkg-config
gcc example.c $(pkg-config --cflags --libs blinkgtk-0.1)With Settings API, you can:
License: BSD-3-Clause
Project: BlinkGTK
Support: https://blinkgtk.org/ / https://github.com/daisy19gnu/blinkgtk-dist/issues