1

I'm developing a C++ GTK application and I'm trying to implement a dark mode theme using CSS. I've created a style.css file with the necessary styles, but I'm having trouble applying these styles to specific GTK elements such as GtkTextView and GtkSidebar.

The styles defined in my CSS file are not being applied to the GTK elements as expected. I'm using IDs and class selectors to target the elements, but the elements appear unchanged (the only thing that is being affected is the background.)

app

Main file:

void load_css(void) {
    GtkCssProvider *provider;
    GdkDisplay *display;
    GdkScreen *screen;

    provider = gtk_css_provider_new();
    display = gdk_display_get_default();
    screen = gdk_display_get_default_screen(display);

    gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

    const gchar *css_file = "src/style.css";
    GError *error = 0;
    gtk_css_provider_load_from_file(provider, g_file_new_for_path(css_file), &error);

    if (error) {
        g_warning("%s", error->message);
        g_clear_error(&error);
    }

    g_object_unref(provider);
}

int main(int argc, char *argv[]) {
    gtk_init(&argc, &argv);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "yarncode");
    gtk_window_set_default_size(GTK_WINDOW(window), 600, 800);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add(GTK_CONTAINER(window), box);

    GtkWidget *header = gtk_header_bar_new();
    gtk_box_pack_start(GTK_BOX(box), header, FALSE, FALSE, 0);

    GtkWidget *button = gtk_button_new_with_label("<<");
    gtk_header_bar_pack_start(GTK_HEADER_BAR(header), button);

    GtkWidget *content_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_box_pack_start(GTK_BOX(box), content_box, TRUE, TRUE, 0);

    GtkWidget *paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
    gtk_box_pack_start(GTK_BOX(content_box), paned, TRUE, TRUE, 0);

    text_view = gtk_source_view_new();
    gtk_widget_set_name(text_view, "text-view");
    gtk_source_view_set_show_line_numbers(GTK_SOURCE_VIEW(text_view), TRUE);
    gtk_source_view_set_highlight_current_line(GTK_SOURCE_VIEW(text_view), TRUE);

    GtkWidget *text_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_container_add(GTK_CONTAINER(text_scrolled_window), text_view);
    gtk_paned_add2(GTK_PANED(paned), text_scrolled_window);

    sidebar_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_widget_set_name(sidebar_window, "sidebar-window");
    gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(sidebar_window), 200);
    gtk_widget_set_size_request(sidebar_window, 200, -1);
    gtk_paned_add1(GTK_PANED(paned), sidebar_window);

    gtk_paned_set_position(GTK_PANED(paned), 200); 

    GtkTreeStore* store = gtk_tree_store_new(1, G_TYPE_STRING);
    GtkWidget* tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
    gtk_container_add(GTK_CONTAINER(sidebar_window), tree_view);

    GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Files", gtk_cell_renderer_text_new(), "text", 0, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);

    GtkTreeIter root_iter;
    gtk_tree_store_append(store, &root_iter, NULL);
    gtk_tree_store_set(store, &root_iter, 0, ".", -1);
    populate_file_tree(store, &root_iter, ".");

    GtkTreePath* root_path = gtk_tree_path_new_from_string("0");
    gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), root_path, FALSE);
    gtk_tree_path_free(root_path);

    GtkWidget *command_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_box_pack_start(GTK_BOX(box), command_box, FALSE, FALSE, 0);

    output_label = gtk_label_new("");
    gtk_widget_set_name(output_label, "label");
    gtk_widget_set_opacity(output_label, 0.0);
    gtk_box_pack_start(GTK_BOX(command_box), output_label, FALSE, FALSE, 0);

    GtkWidget *entry = gtk_entry_new();
    gtk_box_pack_start(GTK_BOX(command_box), entry, FALSE, FALSE, 0);
    gtk_entry_set_placeholder_text(GTK_ENTRY(entry), "Enter command...");
    g_signal_connect(entry, "activate", G_CALLBACK(on_entry_activate), NULL);

    load_css();

    gtk_widget_show_all(window);

    g_signal_connect(button, "clicked", G_CALLBACK(toggle_sidebar), sidebar_window);
    g_signal_connect(entry, "key-press-event", G_CALLBACK(on_entry_key_press), NULL);

    gtk_main();

    return 0;
}

style.css:

window {
    background-color: #ff0000;
}

#text-view {
    background-color: #ff0000;
}

#sidebar {
    background-color: #ff0000;
    color: #ffffff;
}

#output-label {
    background-color: #ff0000;
    color: #ffcc00; 
}

#entry {
    background-color: #ff0000;
    color: #ffffff;
}

#sidebar-tree-view {
    background-color: #333333;
    color: #ffffff;
}

#sidebar-tree-view row {
    background-color: #e40000;
    color: #ffffff;
}

Not sure if applying CSS right, some of it is invisible.

1
  • window.background { background-color: #ff0000; } Commented Jul 13, 2024 at 6:37

2 Answers 2

2

This is a common misconception, GTK "ID" does not correspond to CSS "ID". To use CSS element reference by ID, you need to add a "name" property to the GTK widget. This "name" property will be treated as "ID" for CSS selector purposes.

Sign up to request clarification or add additional context in comments.

Comments

0

Although the question is indicated with GTK4, the code is in GTK3. Since I only work with GTK4, I have transferred it accordingly.

css-cpp.c

#inlude"css-cpp.h"
#include<gtksourceview/gtksource.h>

G_GNUC_BEGIN_IGNORE_DEPRECATIONS

void load_css(void) {
    GtkCssProvider *provider;
    GdkDisplay *display;

    provider = gtk_css_provider_new();
    display = gdk_display_get_default();

    gtk_style_context_add_provider_for_display(display, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

    const gchar *css_file = "style.css";

    gtk_css_provider_load_from_file(provider, g_file_new_for_path(css_file));

    g_object_unref(provider);
}

void activate (GtkApplication *app, gpointer data)
{
  GtkWidget *window;

  window =gtk_application_window_new(app);
  gtk_widget_set_size_request(window,600,800);
  gtk_window_set_title(GTK_WINDOW(window), "yarncode");
  gtk_window_set_decorated(GTK_WINDOW(window),FALSE);
  GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);

    GtkWidget *header = gtk_header_bar_new();

    gtk_box_append(GTK_BOX(box),header);

    
    GtkWidget *button = gtk_button_new_with_label("<<");
    gtk_header_bar_pack_start(GTK_HEADER_BAR(header), button);

    GtkWidget *content_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_box_append(GTK_BOX(box), content_box);

    GtkWidget *paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
    gtk_box_append(GTK_BOX(content_box), paned );
    
    GtkWidget *text_view = gtk_source_view_new();
    gtk_widget_set_name(text_view, "text-view");

    gtk_source_view_set_show_line_numbers(GTK_SOURCE_VIEW(text_view), TRUE);
    gtk_source_view_set_highlight_current_line(GTK_SOURCE_VIEW(text_view), TRUE);

    GtkWidget *text_scrolled_window = gtk_scrolled_window_new();
    gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(text_scrolled_window),text_view);
    gtk_paned_set_end_child(GTK_PANED(paned),text_scrolled_window);
    GtkWidget *sidebar_window = gtk_scrolled_window_new();  
    gtk_widget_set_name(sidebar_window, "sidebar-window");
    gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(sidebar_window), 200);
    gtk_widget_set_size_request(sidebar_window, 200, -1);
    gtk_paned_set_start_child(GTK_PANED(paned),sidebar_window);
    gtk_paned_set_position(GTK_PANED(paned), 200); 

    GtkTreeStore* store = gtk_tree_store_new(1, G_TYPE_STRING);
    GtkWidget* tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
    gtk_widget_set_name(tree_view, "sidebar-tree-view");
    gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sidebar_window),tree_view);
    GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Files", gtk_cell_renderer_text_new(), "text", 0, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);

    GtkTreeIter root_iter;
    gtk_tree_store_append(store, &root_iter, NULL);
    gtk_tree_store_set(store, &root_iter, 0, ".", -1);
//    populate_file_tree(store, &root_iter, ".");

    GtkTreePath* root_path = gtk_tree_path_new_from_string("0");
    gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), root_path, FALSE);
    gtk_tree_path_free(root_path);

    GtkWidget *command_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_box_append(GTK_BOX(box), command_box);
    

    GtkWidget *output_label = gtk_label_new(NULL);
    gtk_widget_set_name(output_label, "label");
    gtk_widget_set_opacity(output_label, 0.0); // fully transparent
    gtk_box_append(GTK_BOX(command_box), output_label);

    GtkWidget *entry = gtk_entry_new();
    gtk_widget_set_name(entry,"entry");
    gtk_box_append(GTK_BOX(command_box), entry);
    gtk_entry_set_placeholder_text(GTK_ENTRY(entry), "Enter command...");
//    g_signal_connect(entry, "activate", G_CALLBACK(on_entry_activate), NULL);

    load_css();

//    g_signal_connect(button, "clicked", G_CALLBACK(toggle_sidebar), sidebar_window);
//    g_signal_connect(entry, "key-press-event", G_CALLBACK(on_entry_key_press), NULL);


   gtk_window_set_child(GTK_WINDOW(window),box);

   gtk_widget_set_visible(window,TRUE);
}

style.css

window {
    background-color: #ff0000;
}

#text-view  text{
    background-color: #ff0000;
}

#sidebar-window {
    background-color: #ff0000;
    color: #ffffff;
}

#label {
    background-color: #ff0000;
    color: #ffcc00; 
}

#entry {
    background-color: #ff0000;
    color: #ffffff;
}

#sidebar-tree-view {
    background-color: #333333;
    color: #ffffff;
}

#sidebar-tree-view header button{
    background-color: #e40000;
    color: #ffffff;
}

For completeness here:

css-cpp.h

#include<gtk/gtk.h>

void activate(GtkApplication *app, gpointer data);

and

main-css-ccp.c

 
#include"css-cpp.h"



int
main (int argc, char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new ("holger.gtk.css-cpp", G_APPLICATION_DEFAULT_FLAGS);
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}

I admit, however, that the layout is a bit confusing for me. So if I didn't really interpret something, You are welcome to ask another question.

Greetings

Holger

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.