GTK3 Gadget CSS-Provider

Linux specific forum
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

GTK3 Gadget CSS-Provider

Post by mk-soft »

Sorry, I forgot to publish.

Change of CSS styles like minimum gadget sizes, coloring and more.

Code: Select all

;-TOP

; Comment : Linux GTK3 Gadget CSS-Provider
; Author  : mk-soft
; Version : v1.02.1
; Create  : 28.12.2018
; Update  : 23.01.2022

DeclareModule GtkGadgetStyle
  
  Declare AddCssProvider(Widget, StyleID, CSSData.s)
  Declare RemoveCssProvider(Widget, StyleID)
  Declare AddCssProviderForScreen(Widget, StyleID, CSSData.s)
  Declare RemoveCssProviderForScreen(Widget, StyleID)
  
  Declare.s CSSColorString(color.l)
  Declare.s CSSColorStringAlpha(color.l, alpha.a = 255)
  
EndDeclareModule

Module GtkGadgetStyle
  
  EnableExplicit
  
  CompilerIf Not Defined(PB_Compiler_Backend, #PB_Constant)
    #PB_Compiler_Backend = 0
    #PB_Backend_Asm = 0
    #PB_Backend_C = 1
  CompilerEndIf
  
  ;- Imports
  ImportC ""
    gtk_widget_get_screen(*Widget.GtkWidget)
    gtk_widget_get_style_context(*Widget.GtkWidget)
    gtk_css_provider_new()
    gtk_css_provider_load_from_data(*CSSProvider, CSSData.P-UTF8, Length, *Error.GError)
    gtk_style_context_add_provider(*CSSContext, *CSSProvider, Priority)
    gtk_style_context_remove_provider(*CSSContext, *CSSProvider)
    gtk_style_context_add_provider_for_screen(*CSSContext, *CSSProvider, Priority)
    gtk_style_context_remove_provider_for_screen(*CSSContext, *CSSProvider)
  EndImport
  
  ;- Constants
  #GTK_STYLE_PROVIDER_PRIORITY_FALLBACK = 1
  #GTK_STYLE_PROVIDER_PRIORITY_THEME = 200
  #GTK_STYLE_PROVIDER_PRIORITY_SETTINGS = 400
  #GTK_STYLE_PROVIDER_PRIORITY_APPLICATION = 600
  #GTK_STYLE_PROVIDER_PRIORITY_USER  = 800
  
  ;- Maps
  Global NewMap mapCssProvider()
  Global NewMap mapCssProviderForScreen()
  
  ; ---------------------------------------------------------------------------
  
  Procedure AddCssProvider(Widget, StyleID, CSSData.s)
    Protected CSSProvider, CSSContext, CSSKey.s
    CSSProvider = gtk_css_provider_new()
    CSSContext = gtk_widget_get_style_context(Widget)
    CSSKey = Str(Widget) + "/" + Str(StyleID)
    If FindMapElement(mapCssProvider(), CSSKey)
      gtk_style_context_remove_provider(CSSContext, mapCssProvider())
    EndIf
    mapCssProvider(CSSKey) = CSSProvider
    gtk_css_provider_load_from_data(CSSProvider, CSSData, -1, 0)
    gtk_style_context_add_provider(CSSContext, CSSProvider, #GTK_STYLE_PROVIDER_PRIORITY_USER)
    g_object_unref_(CSSProvider)
  EndProcedure
  
  ; ---------------------------------------------------------------------------
  
  Procedure RemoveCssProvider(Widget, StyleID)
    Protected CSSContext, CSSKey.s
    CSSKey = Str(Widget) + "/" + Str(StyleID)
    If FindMapElement(mapCssProvider(), CSSKey)
      CSSContext = gtk_widget_get_style_context(Widget)
      gtk_style_context_remove_provider(CSSContext, mapCssProvider())
      DeleteMapElement(mapCssProvider())
    EndIf
  EndProcedure
  
  ; ---------------------------------------------------------------------------
  
  Procedure AddCssProviderForScreen(Widget, StyleID, CSSData.s)
    Protected CSSProvider, CSSContext, CSSKey.s
    CSSProvider = gtk_css_provider_new()
    CSSContext = gtk_widget_get_screen(Widget)
    CSSKey = Str(Widget) + "/" + Str(StyleID)
    If FindMapElement(mapCssProviderForScreen(), CSSKey)
      gtk_style_context_remove_provider_for_screen(CSSContext, mapCssProviderForScreen())
    EndIf
    mapCssProviderForScreen(CSSKey) = CSSProvider
    gtk_css_provider_load_from_data(CSSProvider, CSSData, -1, 0)
    gtk_style_context_add_provider_for_screen(CSSContext, CSSProvider, #GTK_STYLE_PROVIDER_PRIORITY_APPLICATION)
    g_object_unref_(CSSProvider)
  EndProcedure
  
  ; ---------------------------------------------------------------------------
  
  Procedure RemoveCssProviderForScreen(Widget, StyleID)
    Protected CSSContext, CSSKey.s
    CSSKey = Str(Widget) + "/" + Str(StyleID)
    If FindMapElement(mapCssProviderForScreen(), CSSKey)
      CSSContext = gtk_widget_get_screen(Widget)
      gtk_style_context_remove_provider_for_screen(CSSContext, mapCssProviderForScreen())
      DeleteMapElement(mapCssProviderForScreen())
    EndIf
  EndProcedure
  
  ; ---------------------------------------------------------------------------
  
  Procedure.s CSSColorString(color.l)
    CompilerIf #PB_Compiler_Backend = #PB_Backend_Asm
      !mov eax, dword [p.v_color]
      !bswap eax
      !shr eax, 8
      !mov dword [p.v_color], eax
    CompilerElse
      !v_color=__builtin_bswap32(v_color);
      !v_color=((unsigned int)v_color >> 8);
    CompilerEndIf
    ProcedureReturn "#" + RSet(Hex(Color, #PB_Long), 6, "0")
  EndProcedure
  
  ; ---------------------------------------------------------------------------
  
  Procedure.s CSSColorStringAlpha(color.l, alpha.a = 255)
    CompilerIf #PB_Compiler_Backend = #PB_Backend_Asm
      !mov eax, dword [p.v_color]
      !shl eax, 8
      !or  eax, dword [p.v_alpha]
      !bswap eax
      !mov dword [p.v_color], eax
    CompilerElse
      !v_color=((v_color<<8)|v_alpha);
      !v_color=__builtin_bswap32(v_color);
    CompilerEndIf
    ProcedureReturn "#" + RSet(Hex(Color, #PB_Long), 8, "0")
  EndProcedure
  
  ; ---------------------------------------------------------------------------
  
EndModule

; *******************************************************************************

; *******************************************************************************

; Workaround  : GTK3 v3.24.33 (Ubuntu 22.04 Wayland)
; Version     : v1.02.2

Global IsWayland = Bool(GetEnvironmentVariable("XDG_SESSION_TYPE") = "wayland")

Procedure GTK3_FixWindowSize(Window)
  Protected win, dx, dy, hints.GdkGeometry
  
  If IsWayland
    win = WindowID(Window)
    If Not gtk_window_get_resizable_(win)
      dx = WindowWidth(Window)
      dy = WindowHeight(Window)
      hints\max_width = 4096; 4k
      hints\max_height = 2160; 4k
      gtk_window_set_geometry_hints_(win, win, @hints, #GDK_HINT_MAX_SIZE);
      gtk_window_set_default_size_(win, dx, dy);
      gtk_window_resize_(win, dx, dy)
    EndIf
  EndIf
EndProcedure

Procedure GTK3_WindowWidth(Window)
  Protected r1
  gtk_window_get_size_(WindowID(Window), @r1, 0)
  ProcedureReturn r1
EndProcedure

Procedure GTK3_WindowHeight(Window)
  Protected r1
  gtk_window_get_size_(WindowID(Window), 0, @r1)
  ProcedureReturn r1
EndProcedure

Macro WindowWidth(Window)
  GTK3_WindowWidth(Window)
EndMacro

Macro WindowHeight(Window)
  GTK3_WindowHeight(Window)
EndMacro

; *******************************************************************************

CompilerIf #PB_Compiler_IsMainFile
  
  UseModule GtkGadgetStyle
  
  Define css_string.s, css_all.s, css_all_button.s, css_fr.s, css_bg1.s, css_bg2.s
  Define css_color.s
  
  If OpenWindow(0, 0, 0, 270, 140, "CSS-Gadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
    GTK3_FixWindowSize(0)
    
    css_all = "button, entry {min-height: 20px;} "
    css_all + "tab {min-height: 20px;} "
    css_all + "button, scale {padding-bottom: 2px; padding-left: 2px; padding-right: 2px; padding-top: 2px} "
    AddCssProviderForScreen(WindowID(0), 0, css_all)
    
    StringGadget(0, 10, 10, 250, 20, "StringGadget")
    ButtonGadget(1, 10, 45, 120, 20, "Toggle", #PB_Button_Toggle)  
    ButtonGadget(2, 140, 45, 120, 20, "Remove")  
    
    css_color = CSSColorString(RGB(255,128,0))
    
    css_string = "entry {color: darkred; background-color: gray} entry > selection {background-color: " + css_color + "}"
    css_fr = "button {color: blue}"
    css_bg1 = "button {background: yellow;}"
    css_bg2 = "button {background: green;}"
    
    AddCssProviderForScreen(WindowID(0), 3, css_fr) ; Gilt für alle Gadgets ab den Level
    
    AddCssProvider(GadgetID(0), 1, css_string)
    AddCssProvider(GadgetID(1), 2, css_bg1)
    AddCssProvider(GadgetID(2), 3, css_bg2)
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 1
              If GetGadgetState(1)
                AddCssProvider(GadgetID(1), 2, css_bg2)
              Else
                AddCssProvider(GadgetID(1), 2, css_bg1)
              EndIf  
            Case 2
              RemoveCssProvider(GadgetID(1), 2)
          EndSelect
      EndSelect
    ForEver
  EndIf
  
CompilerEndIf

See more for coloring: GTK3 SetGadgetColor

Using of Linux Inspector (GTK3)

Activate on Terminal:
gsettings set org.gtk.Settings.Debug enable-inspector-keybinding true

Start:
- Focus on gtk3 program
- <Shift><Ctrl><i>

Inspector:
- Open tree and select GtkEntry or GtkButton or ...
- ToolBar (i)
- Combobox Detail -> CSS-Node
Last edited by mk-soft on Mon Apr 25, 2022 1:51 pm, edited 2 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: GTK3 Gadget CSS-Provider

Post by mk-soft »

Update
- Added: Workaround 'GTK3_FixWindowSize (Ubuntu 22.04 Wayland)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply