├── po ├── LINGUAS └── meson.build ├── .github ├── sfwbar.png ├── sfwbar-dark.png ├── sfwbar-mpd.png ├── sfwbar-tray.png ├── sfwbar-oneline.png ├── sfwbar-preview.png ├── sfwbar-switch.png └── workflows │ ├── freebsd.yml │ ├── coverity.yml │ └── main.yml ├── src ├── ipc │ └── sway.h ├── locale1.h ├── util │ ├── file.h │ ├── datalist.h │ ├── string.h │ ├── hash.h │ ├── json.h │ ├── datalist.c │ ├── file.c │ └── hash.c ├── gui │ ├── menu.h │ ├── filter.h │ ├── monitor.h │ ├── popup.h │ ├── css.h │ ├── image.h │ ├── label.h │ ├── scale.h │ ├── cchart.h │ ├── button.h │ ├── chart.h │ ├── image.c │ ├── switcher.h │ ├── tray.h │ ├── cchart.c │ ├── button.c │ ├── trayitem.h │ ├── pageritem.h │ ├── grid.h │ ├── taskbar.h │ ├── pager.h │ ├── switcheritem.h │ ├── taskbaritem.h │ ├── label.c │ ├── taskbarpager.h │ ├── taskbarpopup.h │ ├── filter.c │ ├── taskbarshell.h │ ├── taskbar.c │ ├── scaleimage.h │ ├── scale.c │ ├── tray.c │ ├── flowitem.h │ └── flowgrid.h ├── window.h ├── sfwbar.h ├── wayland.h ├── appinfo.h ├── input.h ├── trigger.h ├── client.h ├── module.h ├── vm │ ├── expr.h │ ├── func.c │ └── value.h ├── input.c ├── signal.c ├── wayland.c ├── sni.h ├── window.c └── workspace.h ├── packaging ├── freebsd │ ├── distinfo │ ├── pkg-descr │ ├── files │ │ └── pkg-message.in │ └── Makefile ├── PKGBUILD └── sfwbar-1.0_beta10.ebuild ├── config ├── wbar-memory.widget ├── swap.source ├── wbar-cpu.widget ├── startmenu.widget ├── cpu.widget ├── cpu-temp.source ├── memory.widget ├── cpu-temp.widget ├── wbar-bluetooth.widget ├── privacy.widget ├── idle.widget ├── mb-temp.widget ├── rfkill-bt.widget ├── mpd.source ├── wbar-idleinhibit.widget ├── rfkill-wifi.widget ├── wbar-battery.widget ├── bluez.widget ├── fan-rpm.widget ├── battery.widget ├── lan-bps.widget ├── clock.widget ├── wbar-backlight.widget ├── wbar-sway-lang.widget ├── wbar-temp.widget ├── weather.widget ├── memory.source ├── winops.widget ├── sway-lang.widget ├── mpd.widget ├── rfkill.source ├── wbar-net.widget ├── mpd-mini.widget ├── cpu.source ├── usage.widget ├── alsa.widget ├── language.widget ├── switcher.config ├── wbar-mpd.widget ├── wbar-pulse.widget ├── showdesktop.widget ├── backlight.source ├── battery-svg.widget ├── upower.widget ├── battery.source └── backlight.widget ├── meson.h.meson ├── icons ├── misc │ ├── hibernate.svg │ ├── suspend.svg │ ├── stop.svg │ ├── play.svg │ ├── rewind.svg │ ├── fforward.svg │ ├── lock-symbolic.svg │ ├── unlock-symbolic.svg │ ├── missing.svg │ ├── lan.svg │ ├── music-player.svg │ ├── music-player-symbolic.svg │ └── comp.svg ├── weather │ ├── clearsky_night.svg │ ├── LICENSE │ ├── cloudy.svg │ ├── clearsky_day.svg │ ├── lightrain.svg │ ├── rain.svg │ ├── fog.svg │ ├── lightsnow.svg │ ├── clearsky_polartwilight.svg │ ├── snow.svg │ ├── heavyrain.svg │ ├── lightsleet.svg │ ├── sleet.svg │ ├── fair_night.svg │ ├── heavysnow.svg │ ├── partlycloudy_night.svg │ ├── lightrainandthunder.svg │ ├── heavysleet.svg │ ├── rainandthunder.svg │ └── lightsnowandthunder.svg └── sfwbar.svg ├── doc ├── sfwbar-bsdctl.rst ├── sfwbar-xkbmap.rst ├── sfwbar-idle.rst ├── sfwbar-appmenu.rst ├── sfwbar-bsdctl.1 ├── sfwbar-idleinhibit.rst ├── sfwbar-xkbmap.1 ├── sfwbar-idle.1 ├── sfwbar-appmenu.1 ├── sfwbar-network.rst ├── sfwbar-mpd.rst └── sfwbar-idleinhibit.1 ├── meson_options.txt ├── data └── desktop-directories │ └── Settings.directory └── modules └── idleinhibit.c /po/LINGUAS: -------------------------------------------------------------------------------- 1 | pl ru zh_CN zh_TW 2 | -------------------------------------------------------------------------------- /.github/sfwbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LBCrion/sfwbar/HEAD/.github/sfwbar.png -------------------------------------------------------------------------------- /.github/sfwbar-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LBCrion/sfwbar/HEAD/.github/sfwbar-dark.png -------------------------------------------------------------------------------- /.github/sfwbar-mpd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LBCrion/sfwbar/HEAD/.github/sfwbar-mpd.png -------------------------------------------------------------------------------- /.github/sfwbar-tray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LBCrion/sfwbar/HEAD/.github/sfwbar-tray.png -------------------------------------------------------------------------------- /.github/sfwbar-oneline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LBCrion/sfwbar/HEAD/.github/sfwbar-oneline.png -------------------------------------------------------------------------------- /.github/sfwbar-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LBCrion/sfwbar/HEAD/.github/sfwbar-preview.png -------------------------------------------------------------------------------- /.github/sfwbar-switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LBCrion/sfwbar/HEAD/.github/sfwbar-switch.png -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n = import('i18n') 2 | add_project_arguments('-DGETTEXT_PACKAGE="sfwbar"', language:'c') 3 | i18n.gettext(meson.project_name()) 4 | -------------------------------------------------------------------------------- /src/ipc/sway.h: -------------------------------------------------------------------------------- 1 | #ifndef __SWAY_IPC_H__ 2 | #define __SWAY_IPC_H__ 3 | 4 | #include "scanner.h" 5 | 6 | void sway_ipc_init ( void ); 7 | source_t *sway_ipc_client_init ( void ); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/locale1.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOCALE1_H__ 2 | #define __LOCALE1_H__ 3 | 4 | #include 5 | 6 | void locale1_init ( void ); 7 | const gchar *locale1_get_locale ( void ); 8 | 9 | #endif 10 | 11 | -------------------------------------------------------------------------------- /packaging/freebsd/distinfo: -------------------------------------------------------------------------------- 1 | TIMESTAMP = 1691478313 2 | SHA256 (LBCrion-sfwbar-v1.0_beta12_GH0.tar.gz) = 98dfdc9915d57c17588e71a8c50964891e8aa6fcda8077ef390924fe28445eda 3 | SIZE (LBCrion-sfwbar-v1.0_beta12_GH0.tar.gz) = 362373 4 | -------------------------------------------------------------------------------- /config/wbar-memory.widget: -------------------------------------------------------------------------------- 1 | include("memory.source") 2 | 3 | layout { 4 | label { 5 | style = if(XMemPresent,"memory","hidden") 6 | interval = 30000 7 | value = Str(XMemUtilization*100) + '% ' 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/util/file.h: -------------------------------------------------------------------------------- 1 | #ifndef __SFWBAR_FILE__ 2 | #define __SFWBAR_FILE__ 3 | 4 | #include 5 | 6 | gboolean file_test_read ( gchar *filename ); 7 | gchar *get_xdg_config_file ( gchar *fname, gchar *extra ); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /config/swap.source: -------------------------------------------------------------------------------- 1 | Scanner { 2 | # Add up total and used swap capacity across all partitions 3 | file("/proc/swaps") { 4 | SwapTotal = RegEx("[\t ]([0-9]+)",Sum) 5 | SwapUsed = RegEx("[\t ][0-9]+[\t ]([0-9]+)",Sum) 6 | } 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /meson.h.meson: -------------------------------------------------------------------------------- 1 | 2 | #define GTK_LAYER_VER_MAJOR @glsh_major@ 3 | #define GTK_LAYER_VER_MINOR @glsh_minor@ 4 | #define GTK_LAYER_VER_MICRO @glsh_micro@ 5 | #define MODULE_DIR "@module_dir@" 6 | #define SYSTEM_CONF_DIR "@conf_dir@" 7 | #define LOCALE_DIR "@locale_dir@" 8 | -------------------------------------------------------------------------------- /config/wbar-cpu.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | include("cpu.source") 4 | 5 | Private { 6 | Var icon = ''; 7 | 8 | layout { 9 | label { 10 | style = if(XCpuPresent,"cpu","hidden") 11 | interval = 10000 12 | value = Str(XCpuUtilization*100) + '% ' + icon 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/startmenu.widget: -------------------------------------------------------------------------------- 1 | module("appmenu") 2 | 3 | Private { 4 | 5 | Var icon = "open-menu"; 6 | 7 | layout { 8 | button { 9 | value = icon; 10 | style = "startmenu" 11 | action = Menu("app_menu_system") 12 | tooltip = GT("Application menu") 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/cpu.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | include("cpu.source") 4 | 5 | widget_grid { 6 | chart { 7 | interval = 1000 8 | style = If(XCpuPresent,"cpu_chart","hidden") 9 | value = XCpuUtilization 10 | tooltip = "CPU: " + Str(XCpuUtilization*100) + '%' 11 | action = Exec($Term + " -e top") 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/gui/menu.h: -------------------------------------------------------------------------------- 1 | #ifndef __MENU_H__ 2 | #define __MENU_H__ 3 | 4 | #include 5 | 6 | GtkWidget *menu_from_name ( gchar *name ); 7 | GtkWidget *menu_new ( gchar *name ); 8 | void menu_remove ( gchar *name ); 9 | void menu_popup ( GtkWidget *, GtkWidget *, GdkEvent *, gpointer, guint16 * ); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /icons/misc/hibernate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /config/cpu-temp.source: -------------------------------------------------------------------------------- 1 | file("/sys/class/hwmon/hwmon1/temp1_input") { 2 | CPUTemp = Grab() 3 | } 4 | 5 | module("bsdctl") 6 | 7 | Set BsdCPUTemp = BSDCtl("dev.cpu.0.temperature") 8 | Set XCpuTemp = If(!Ident(BSDCtl), CPUTemp/1000, BsdCPUTemp/10-273.2) 9 | Set XCpuTempPresent = If(Ident(BSDCtl), $BsdCPUTemp!="", CPUTemp.count) 10 | -------------------------------------------------------------------------------- /config/memory.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | include("memory.source") 4 | 5 | widget_grid { 6 | scale { 7 | interval = 1000 8 | style = If(XMemPresent,"memory","hidden") 9 | value = XMemUtilization 10 | tooltip = GT("Memory") + ": " + Str(XMemUtilization*100) + "%" 11 | action = Exec($Term + " -e top -o %MEM") 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /icons/misc/suspend.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /config/cpu-temp.widget: -------------------------------------------------------------------------------- 1 | include("cpu-temp.source") 2 | 3 | layout { 4 | css = "* { -GtkWidget-direction: right; -GtkWidget-vexpand: true; -GtkWidget-hexpand: true; }" 5 | image { 6 | style = "value_icon" 7 | value = "icons/misc/cpu.svg" 8 | } 9 | label { 10 | style = "value" 11 | interval = 1000 12 | value = Str(XCpuTemp, 0)+"°C" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/gui/filter.h: -------------------------------------------------------------------------------- 1 | #ifndef __FILTER_H__ 2 | #define __FILTER_H__ 3 | 4 | #include 5 | #include "wintree.h" 6 | 7 | enum WindowFilter { 8 | FILTER_FLOATING = 1, 9 | FILTER_MINIMIZED = 2, 10 | FILTER_OUTPUT = 4, 11 | FILTER_WORKSPACE = 8, 12 | }; 13 | 14 | GType filter_type_get ( void ); 15 | gboolean filter_window_check ( GtkWidget *parent, window_t *win ); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/window.h: -------------------------------------------------------------------------------- 1 | #ifndef __WINDOW_H__ 2 | #define __WINDOW_H__ 3 | 4 | #include 5 | 6 | void window_ref ( GtkWidget *self, GtkWidget *ref ); 7 | void window_unref ( GtkWidget *ref, GtkWidget *self ); 8 | gboolean window_ref_check ( GtkWidget *self ); 9 | void window_set_unref_func ( GtkWidget *self, void (*func)(gpointer) ); 10 | void window_collapse_popups ( GtkWidget *self ); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /config/wbar-bluetooth.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("bluez-popup.widget") 6 | 7 | Var icon = ""; 8 | 9 | layout { 10 | label { 11 | style = If(BluezAdapter("Count"), "bluetooth", "hidden"); 12 | value = icon + " "; 13 | trigger = "bluez_adapter"; 14 | action[LeftClick] = XBluezPop(); 15 | action[RightClick] = Menu("XBluezAdapter") 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/sfwbar.h: -------------------------------------------------------------------------------- 1 | #ifndef __SFWBAR_H__ 2 | #define __SFWBAR_H__ 3 | 4 | #include 5 | #include 6 | 7 | #if GLIB_MINOR_VERSION < 68 8 | #define g_memdup2(x,y) g_memdup(x,y) 9 | #endif 10 | 11 | void signal_subscribe ( void ); 12 | void action_lib_init ( void ); 13 | void hypr_ipc_init ( void ); 14 | void wayfire_ipc_init ( void ); 15 | void scanner_init ( void ); 16 | void expr_init ( void ); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /config/privacy.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | module("pipewire") 4 | 5 | layout { 6 | button{ 7 | style = if(PipewireCount("AudioIn"), "module", "hidden") 8 | trigger = "pipewire" 9 | value = "audio-input-microphone"; 10 | css = "* { color: red; }" 11 | } 12 | button{ 13 | style = if(PipewireCount("VideoIn"), "module", "hidden") 14 | trigger = "pipewire" 15 | value = "camera-web"; 16 | css = "* { color: red; }" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /config/idle.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Module("idleinhibit"); 4 | 5 | Private { 6 | Var icon_active = "icons/misc/lock-symbolic"; 7 | Var icon_inactive = "icons/misc/unlock-symbolic"; 8 | 9 | export button { 10 | style = If(Ident(IdleInhibitState), "module", "hidden") 11 | value = If(IdleInhibitState()="on", icon_active, icon_inactive) 12 | local = true 13 | trigger = "idleinhibitor" 14 | action[1] = SetIdleInhibitor("toggle") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /config/mb-temp.widget: -------------------------------------------------------------------------------- 1 | scanner { 2 | # Poll motherboard temperature 3 | file("/sys/class/hwmon/hwmon2/temp1_input") { 4 | MBTemp = Grab(First) 5 | } 6 | } 7 | 8 | layout { 9 | css = "* { -GtkWidget-direction: right; -GtkWidget-vexpand: true; -GtkWidget-hexpand: true; }" 10 | image { 11 | style = "value_icon" 12 | value = "icons/misc/comp.svg" 13 | } 14 | label { 15 | style = "value" 16 | interval = 1000 17 | value = Str(MBTemp/1000,0)+"C" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packaging/freebsd/pkg-descr: -------------------------------------------------------------------------------- 1 | SFWBar (S* Floating Window Bar) is a flexible taskbar application for 2 | wayland compositors, designed with a stacking layout in mind. 3 | Originally developed for Sway, SFWBar will work with any wayland compositor 4 | supporting layer shell protocol, the taskbar and window switcher functionality 5 | shall work with any compositor supportinig foreign toplevel protocol, 6 | but the pager, and window placement functionality require sway 7 | (or at least i3 IPC support). 8 | -------------------------------------------------------------------------------- /src/gui/monitor.h: -------------------------------------------------------------------------------- 1 | #ifndef __OUTPUT_H__ 2 | #define __OUTPUT_H__ 3 | 4 | #include 5 | #include 6 | 7 | GdkMonitor *monitor_from_widget ( GtkWidget *self ); 8 | gboolean xdg_output_check ( void ); 9 | GdkMonitor *monitor_default_get ( void ); 10 | gchar *monitor_get_name ( GdkMonitor *monitor ); 11 | GdkMonitor *monitor_from_name ( gchar *name ); 12 | GdkMonitor *monitor_from_wl_output ( struct wl_output *output ); 13 | void monitor_init ( gchar * ); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/wayland.h: -------------------------------------------------------------------------------- 1 | #ifndef __WAYLAND_H__ 2 | #define __WAYLAND_H__ 3 | 4 | #include 5 | 6 | typedef struct _wayland_iface { 7 | gchar *iface; 8 | guint32 global; 9 | guint32 version; 10 | } wayland_iface_t; 11 | 12 | void wayland_init ( void ); 13 | gpointer wayland_iface_register ( const gchar *interface, 14 | guint32 min_ver, guint32 max_ver, const void *impl ); 15 | void foreign_toplevel_init ( void ); 16 | void cw_init ( void ); 17 | void ew_init ( void ); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/appinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef __APPINFO_H__ 2 | #define __APPINFO_H__ 3 | 4 | #include 5 | 6 | typedef void (*AppInfoHandler)( const gchar * ); 7 | 8 | void app_info_init ( void ); 9 | void app_info_add_handlers ( AppInfoHandler add, AppInfoHandler del ); 10 | void app_info_remove_handlers ( AppInfoHandler add, AppInfoHandler del ); 11 | void app_icon_map_add ( gchar *appid, gchar *icon ); 12 | gchar *app_info_icon_lookup ( gchar *app_id, gboolean prefer_symbolic ); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /config/rfkill-bt.widget: -------------------------------------------------------------------------------- 1 | include("rfkill.source") 2 | 3 | 4 | layout { 5 | button { 6 | style = If(!XRfKillBTPresent, "hidden","module") 7 | value = If(XRfKillBTSoft = 1, 8 | "bluetooth-disabled", 9 | "bluetooth-active") 10 | tooltip = "Bluetooth: Soft" + If(XRfKillBTSoft,"","Un")+"blocked" + 11 | ", Hard" + If(XRfKillBTHard,"","Un")+"blocked" 12 | trigger = "rfkill" 13 | action = Exec "rfkill " + If(XRfKillBTSoft,"un","") + "block bluetooth" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/mpd.source: -------------------------------------------------------------------------------- 1 | Scanner { 2 | MpdClient("") { 3 | MpdTitle = RegEx("Title: (.*)") 4 | MpdAlbum = RegEx("Album: (.*)") 5 | MpdArtist = RegEx("Artist: (.*)") 6 | MpdState = RegEx("state: (.*)") 7 | MpdRandom = RegEx("random:(.*)") 8 | MpdRepeat = RegEx("repeat:(.*)") 9 | MpdElapsed = RegEx("elapsed:(.*)") 10 | MpdDuration = RegEx("duration:(.*)") 11 | MpdVolume = RegEx("volume:(.*)") 12 | MpdQPos = RegEx("song: (.*)") 13 | MpdQLen = RegEx("playlistlength: (.*)") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /config/wbar-idleinhibit.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Module("idleinhibit"); 4 | 5 | Private { 6 | 7 | layout { 8 | label { 9 | style = If(!Ident(IdleInhibitState),"hidden", 10 | If(IdleInhibitState()="on", 11 | "idle_inhibitor_activated", "idle_inhibitor")) 12 | value = If(IdleInhibitState()="on", "", "") 13 | tooltip = If(IdleInhibitState()="on", "activated", "deactivated") 14 | trigger = "idleinhibitor" 15 | action[1] = SetIdleInhibitor("toggle") 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /config/rfkill-wifi.widget: -------------------------------------------------------------------------------- 1 | include("rfkill.source") 2 | 3 | layout { 4 | button { 5 | style = If(!XRfKillWifiPresent, "hidden","module") 6 | value = If(XRfKillWifiSoft = 1, 7 | "network-wireless-hardware-disabled", 8 | "network-wireless-connected") 9 | tooltip = "WiFi: Soft" + If(XRfKillWifiSoft,"","Un")+"blocked" + 10 | ", Hard" + If(XRfKillWifiHard,"","Un")+"blocked" 11 | trigger = "rfkill" 12 | action = Exec "rfkill " + If(XRfKillWifiSoft,"un","") + "block wifi" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/util/datalist.h: -------------------------------------------------------------------------------- 1 | #ifndef __DATALIST_H__ 2 | #define __DATALIST_H__ 3 | 4 | #include 5 | 6 | typedef struct _datalist_t { 7 | GData *data; 8 | GMutex mutex; 9 | gint refcount; 10 | } datalist_t; 11 | 12 | datalist_t *datalist_new ( void ); 13 | datalist_t *datalist_ref ( datalist_t *dlist ); 14 | void datalist_unref ( datalist_t *dlist ); 15 | gpointer datalist_get ( datalist_t *dlist, GQuark id ); 16 | void datalist_set ( datalist_t *dlist, GQuark id, gpointer d ); 17 | void datalist_foreach ( datalist_t *dlist, GDataForeachFunc func, void *d ); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /config/wbar-battery.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("battery.source") 6 | 7 | widget_grid { 8 | label { 9 | style = If(!Ident($XBatteryState) & !Ident(BSDCtl), "hidden", "battery") 10 | interval = 60000 11 | value = Str(Level) + '% ' + 12 | if(Discharging, Lookup(Level,80,"",60,"",40,"",20,"",""), "") 13 | tooltip = GT("Battery") + ": " + Str(Level) + "%" + If(Time, " " + 14 | Str(Time/60 - Time%60/60) + GT("h") + 15 | Str(Time%60) + GT("m"), "") 16 | action[0] = XBatteryInit() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/bluez.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("bluez-popup.widget") 6 | 7 | layout { 8 | style = If(BluezAdapter("Count"), "module", "hidden") 9 | trigger = "bluez-adapter" 10 | button "XBluezWidget" { 11 | style = "module" 12 | value = If(!BluezAdapter("Powered"), "bluetooth-disabled", 13 | if(BluezAdapter("Discovering"), "bluetooth-acquiring", "bluetooth-active")) 14 | action = XBluezPop() 15 | action[RightClick] = Menu("XBluezAdapter") 16 | tooltip = GT("Bluetooth") 17 | trigger = "bluez-adapter" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /config/fan-rpm.widget: -------------------------------------------------------------------------------- 1 | scanner { 2 | # Poll CPU fan rpm 3 | file("/sys/devices/platform/it87*/hwmon/hwmon2/fan2_input") { 4 | CPUFan = Grab() 5 | } 6 | 7 | # Poll MB fan rpm 8 | file("/sys/devices/platform/it87*/hwmon/hwmon2/fan1_input") { 9 | MBFan = Grab() 10 | } 11 | } 12 | 13 | layout { 14 | css = "* { -GtkWidget-direction: right; -GtkWidget-vexpand: true; -GtkWidget-hexpand: true; }" 15 | image { 16 | style = "value_icon" 17 | value = "icons/misc/fan.svg" 18 | } 19 | label { 20 | style = "value" 21 | interval = 1000 22 | value = Str(CPUFan,0) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /config/battery.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("battery.source") 6 | 7 | widget_grid { 8 | style = "module" 9 | button "battery" { 10 | action[0] = XBatteryInit() 11 | style = If(!Ident($XBatteryState) & !Ident(BSDCtl), "hidden", "module") 12 | tooltip = GT("Battery") + ": " + Str(Level) + "%" + If(Time, " " + 13 | Str(Time/60 - Time%60/60) + GT("h") + 14 | Str(Time%60) + GT("m"), "") 15 | value = "battery-level-" + Str(Level/10,0) + "0" + 16 | If($XBatteryState = "Discharging","","-charging") 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/lan-bps.widget: -------------------------------------------------------------------------------- 1 | scanner { 2 | # Add up received and transmitted bytes cross all enp* interfaces 3 | file("/proc/net/dev") { 4 | EthRcvd = RegEx("wlp.*:[\t ]*([0-9]+)",Sum) 5 | EthSent = RegEx("wlp.*:(?:[\t ]*[0-9]+){8}[\t ]([0-9]+)",Sum) 6 | } 7 | } 8 | 9 | layout { 10 | css = "* { -GtkWidget-direction: right; -GtkWidget-vexpand: true; -GtkWidget-hexpand: true; }" 11 | image { 12 | style = "value_icon" 13 | value = "icons/misc/lan.svg" 14 | } 15 | label { 16 | style = "value" 17 | interval = 1000 18 | value = Str((EthRcvd-EthRcvd.pval)/0.001024/EthRcvd.time,0)+"K/s" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/input.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUT_H__ 2 | #define __INPUT_H__ 3 | 4 | #include 5 | 6 | struct input_api { 7 | void (*layout_next) ( void ); 8 | void (*layout_prev) ( void ); 9 | void (*layout_set) ( gchar * ); 10 | }; 11 | 12 | void input_api_register ( struct input_api *new ); 13 | gboolean input_api_check ( void ); 14 | void input_layout_set ( const gchar *new_layout ); 15 | const gchar *input_layout_get ( void ); 16 | void input_layout_next ( void ); 17 | void input_layout_prev ( void ); 18 | void input_layout_change ( gchar *layout ); 19 | void input_layout_list_set ( gchar **new ); 20 | gchar **input_layout_list_get ( void ); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/trigger.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRIGGER_H__ 2 | #define __TRIGGER_H__ 3 | 4 | #include 5 | #include "vm/vm.h" 6 | 7 | typedef void(*trigger_func_t)(void *, vm_store_t *); 8 | 9 | const gchar *trigger_add ( gchar *name, trigger_func_t func, void *data ); 10 | void trigger_remove ( gchar *name, trigger_func_t func, void *data ); 11 | void trigger_action_cb ( vm_closure_t *closure, vm_store_t *store ); 12 | const gchar *trigger_name_intern ( gchar *name ); 13 | void trigger_emit_with_data ( gchar *name, vm_store_t *store ); 14 | void trigger_emit_with_string ( gchar *name, gchar *var, gchar *val ); 15 | gboolean trigger_emit ( gchar *name ); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /icons/misc/stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /icons/misc/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /config/clock.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("cal.widget") 6 | 7 | Var week_starts_on_sunday = 0; 8 | Var time_format = "%H:%M" 9 | Var tooltip_format = "%k:%M\n%x" 10 | Var reset_on_popup = TRUE; 11 | 12 | widget_grid { 13 | label { 14 | value = Time(time_format) 15 | style ="clock" 16 | tooltip = Time(tooltip_format) 17 | action = { 18 | If reset_on_popup 19 | EmitTrigger("calendar-reset") 20 | PopUp("Xcal") 21 | } 22 | } 23 | } 24 | } 25 | 26 | #CSS 27 | 28 | label#clock { 29 | padding-left: 2px; 30 | padding-right: 2px; 31 | -GtkWidget-vexpand: true; 32 | -GtkWidget-valign: center; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/gui/popup.h: -------------------------------------------------------------------------------- 1 | #ifndef __POPUP_H__ 2 | #define __POPUP_H__ 3 | 4 | G_BEGIN_DECLS 5 | 6 | #define POPUP_TYPE_WINDOW popup_window_get_type () 7 | G_DECLARE_FINAL_TYPE(PopupWindow, popup_window, POPUP, WINDOW, GtkWindow) 8 | 9 | typedef struct _PopupWindow { 10 | GtkWindow parent; 11 | } PopupWindow; 12 | 13 | G_END_DECLS 14 | 15 | GtkWidget *popup_new ( gchar *name ); 16 | GtkWidget *popup_from_name ( gchar *name ); 17 | void popup_trigger ( GtkWidget *parent, gchar *name, GdkEvent *ev ); 18 | void popup_show ( GtkWidget *parent, GtkWidget *popup, GdkSeat *seat ); 19 | void popup_get_gravity ( GtkWidget *widget, GdkGravity *, GdkGravity * ); 20 | void popup_popdown_autoclose ( void ); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /config/wbar-backlight.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("backlight.source") 6 | 7 | Var format = "{percent}% {icon}"; 8 | Var icon = ""; 9 | Var Step = 0.005; 10 | 11 | widget_grid { 12 | label { 13 | style = if(BacklightPresent, "backlight", "hidden") 14 | action[0] = BacklightInit() 15 | action[ScrollUp] = SetBacklight(BacklightPct+Step) 16 | action[ScrollDown] = SetBacklight(BacklightPct-Step) 17 | action[LeftClick] = PopUp("BacklightPopup") 18 | value = ReplaceAll(format, "{percent}", Str(BacklightPct *100), "{icon}", icon); 19 | tooltip = ReplaceAll(format, "{percent}", Str(BacklightPct *100), "{icon}", icon); 20 | trigger = "backlight" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/gui/css.h: -------------------------------------------------------------------------------- 1 | #ifndef __CSS_H__ 2 | #define __CSS_H__ 3 | 4 | #include 5 | 6 | void css_init ( gchar * ); 7 | void css_file_load ( gchar * ); 8 | GtkCssProvider *css_widget_apply ( GtkWidget *widget, gchar *css ); 9 | void css_widget_cascade ( GtkWidget *widget, gpointer data ); 10 | void css_add_class ( GtkWidget *widget, gchar *css_class ); 11 | void css_remove_class ( GtkWidget *widget, gchar *css_class ); 12 | void css_set_class ( GtkWidget *widget, gchar *css_class, gboolean state ); 13 | gchar *css_legacy_preprocess ( gchar *css_string, gchar *fname ); 14 | void css_provider_add ( gchar *css ); 15 | 16 | void widget_set_css ( GtkWidget *, gpointer ); 17 | void widget_parse_css ( GtkWidget *widget, gchar *css ); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /config/wbar-sway-lang.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | module("xkbmap") 4 | 5 | Private { 6 | 7 | Var command = "input type:keyboard xkb_switch_layout next"; 8 | 9 | SwayClient("") { 10 | SwayXkbLayout = Json(".input.input.xkb_active_layout_name") 11 | } 12 | 13 | Function XSwayLangInit() { 14 | SwayCmd("input type:keyboard xkb_switch_layout next"); 15 | SwayCmd("input type:keyboard xkb_switch_layout prev"); 16 | } 17 | 18 | layout { 19 | label { 20 | action[0] = XSwayLangInit() 21 | action[LeftClick] = SwayCmd(command) 22 | style = If(Ident(SwayXkbLayout) & $SwayXkbLayout!="", "language", "hidden") 23 | value = XkbMap($SwayXkbLayout, "description" ,"name") 24 | trigger = "sway" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /config/wbar-temp.widget: -------------------------------------------------------------------------------- 1 | Private { 2 | 3 | Var thresholds = [40,20]; 4 | Var icons = ["","",""]; 5 | Var format = "{temperatureC}°C {icon}" 6 | 7 | Function IconLookup ( x, thresholds, icons ) { 8 | Var result = icons[arraysize(icons)-1], i = 0; 9 | 10 | while ithresholds[i] 12 | result = icons[i]; 13 | i=i+1; 14 | } 15 | Return result; 16 | } 17 | 18 | include("cpu-temp.source") 19 | 20 | layout { 21 | label { 22 | style = if(XCpuTempPresent,"temperature","hidden") 23 | value = ReplaceAll(format, "{temperatureC}", Str(XCpuTemp), 24 | "{icon}", ArrayLookup(XCpuTemp, thresholds, icons)) 25 | interval = 10000 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /doc/sfwbar-bsdctl.rst: -------------------------------------------------------------------------------- 1 | sfwbar-bsdctl 2 | ############# 3 | 4 | ######################## 5 | Sfwbar BSD sysctl module 6 | ######################## 7 | 8 | :Copyright: GPLv3+ 9 | :Manual section: 1 10 | 11 | Filename: bsdctl.so 12 | 13 | Requires: BSD libc 14 | 15 | SYNOPSIS 16 | ======== 17 | 18 | The BSDCtl module provides an interface to query BSD sysctl values 19 | 20 | Expression Functions 21 | ==================== 22 | 23 | BSDCtl(Query) 24 | ------------- 25 | 26 | function BSDCtl queries the value of a sysctl variable. It's equivalent to 27 | calling sysctl program on BSD system. Please note that you can only query 28 | individual nodes rather than groups. 29 | 30 | Actions 31 | ======= 32 | 33 | None 34 | 35 | Triggers 36 | ======== 37 | 38 | None 39 | -------------------------------------------------------------------------------- /.github/workflows/freebsd.yml: -------------------------------------------------------------------------------- 1 | name: FreeBSD_CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-24.04 8 | name: FreeBSD CI 9 | timeout-minutes: 20 10 | steps: 11 | - uses: actions/checkout@v3 12 | - name: Test in FreeBSD 13 | id: test 14 | uses: vmactions/freebsd-vm@v1 15 | with: 16 | usesh: true 17 | prepare: | 18 | pkg install -y curl meson ninja pkgconf gtk3 wayland-protocols gtk-layer-shell wayland json-c libmpdclient pulseaudio libxkbcommon alsa-lib 19 | 20 | run: | 21 | meson setup build --werror -Dpulse=enabled -Dmpd=enabled -Dnetwork=enabled -Dalsa=enabled -Dbluez=enabled -Dxkb=enabled -Didleinhibit=enabled -Dbsdctl=enabled 22 | ninja -C build 23 | DESTDIR=./install ninja -C build install 24 | -------------------------------------------------------------------------------- /config/weather.widget: -------------------------------------------------------------------------------- 1 | # Parse met.no weather forecast 2 | scanner { 3 | Exec("wget -O - \"https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=51.8711&lon=0.1587\"") { 4 | WthrTemp= Json(".properties.timeseries.1.data.instant.details.air_temperature") 5 | WthrCond= Json(".properties.timeseries.1.data.next_12_hours.summary.symbol_code") 6 | } 7 | } 8 | 9 | layout { 10 | style = "frame" 11 | label { 12 | interval = 300000 13 | css = "* { font: 0.5cm Sans; font-weight: 700; -GtkWidget-align: 0.5; padding-left: 1mm; padding-right: 1mm; }" 14 | value = Str(WthrTemp.val,1) 15 | } 16 | image { 17 | interval = 300000 18 | css = "* { -GtkWidget-hexpand: true; -GtkWidget-vexpand: true; padding-left: 1mm; padding-right: 1mm; }" 19 | value = 'icons/weather/'+$WthrCond+'.svg' 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /icons/weather/clearsky_night.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /doc/sfwbar-xkbmap.rst: -------------------------------------------------------------------------------- 1 | sfwbar-xkbmap 2 | ############# 3 | 4 | ############################## 5 | Sfwbar xkbcommon layout module 6 | ############################## 7 | 8 | :Copyright: GPLv3+ 9 | :Manual section: 1 10 | 11 | Filename: xkbmap.so 12 | 13 | Requires: libxkbregistry 14 | 15 | SYNOPSIS 16 | ======== 17 | 18 | The XkbMap module provides an interface to convert between keyboard layout 19 | types. 20 | 21 | Expression Functions 22 | ==================== 23 | 24 | XkbMap(Name,SourceType,DestType) 25 | -------------------------------- 26 | 27 | Function XkbMap converts between various name types for an XkbLayout. The 28 | function converts layout name Name from SourceType to DestType, the supported 29 | types are: "description","name","variant" and "brief". 30 | 31 | Actions 32 | ======= 33 | 34 | None 35 | 36 | Triggers 37 | ======== 38 | 39 | None 40 | -------------------------------------------------------------------------------- /.github/workflows/coverity.yml: -------------------------------------------------------------------------------- 1 | # GitHub actions workflow. 2 | # https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions 3 | 4 | # https://scan.coverity.com/projects/openrc-openrc 5 | name: Coverity Scan 6 | 7 | on: 8 | push: 9 | branches: [main] 10 | 11 | jobs: 12 | coverity: 13 | runs-on: ubuntu-24.04 14 | steps: 15 | - uses: actions/checkout@v2 16 | - run: sudo apt-get update 17 | - run: sudo apt-get -y install libgtk-3-dev meson libgtk-layer-shell-dev libjson-c-dev libmpdclient-dev libpulse-dev 18 | - run: meson setup builddir/ -Dpulse=enabled -Dmpd=enabled -Dnetwork=enabled 19 | env: 20 | CC: gcc 21 | - uses: vapier/coverity-scan-action@v1 22 | with: 23 | command: ninja -C builddir 24 | email: ${{ secrets.COVERITY_SCAN_EMAIL }} 25 | token: ${{ secrets.COVERITY_SCAN_TOKEN }} 26 | -------------------------------------------------------------------------------- /src/gui/image.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMAGE_H__ 2 | #define __IMAGE_H__ 3 | 4 | #include "basewidget.h" 5 | 6 | #define IMAGE_TYPE (image_get_type()) 7 | #define IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), IMAGE_TYPE, Image)) 8 | #define IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), IMAGE_TYPE, ImageClass)) 9 | #define IS_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), IMAGE_TYPE)) 10 | #define IS_IMAGECLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), IMAGE_TYPE)) 11 | 12 | typedef struct _Image Image; 13 | typedef struct _ImageClass ImageClass; 14 | 15 | struct _Image 16 | { 17 | BaseWidget item; 18 | }; 19 | 20 | struct _ImageClass 21 | { 22 | BaseWidgetClass parent_class; 23 | }; 24 | 25 | typedef struct _ImagePrivate ImagePrivate; 26 | 27 | struct _ImagePrivate 28 | { 29 | GtkWidget *image; 30 | }; 31 | 32 | GType image_get_type ( void ); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/gui/label.h: -------------------------------------------------------------------------------- 1 | #ifndef __LABEL_H__ 2 | #define __LABEL_H__ 3 | 4 | #include "basewidget.h" 5 | 6 | #define LABEL_TYPE (label_get_type()) 7 | #define LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LABEL_TYPE, Label)) 8 | #define LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), LABEL_TYPE, LabelClass)) 9 | #define IS_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), LABEL_TYPE)) 10 | #define IS_LABELCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), LABEL_TYPE)) 11 | 12 | typedef struct _Label Label; 13 | typedef struct _LabelClass LabelClass; 14 | 15 | struct _Label 16 | { 17 | BaseWidget item; 18 | }; 19 | 20 | struct _LabelClass 21 | { 22 | BaseWidgetClass parent_class; 23 | }; 24 | 25 | typedef struct _LabelPrivate LabelPrivate; 26 | 27 | struct _LabelPrivate 28 | { 29 | GtkWidget *label; 30 | }; 31 | 32 | GType label_get_type ( void ); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /config/memory.source: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | module("bsdctl") 4 | 5 | file("/proc/meminfo") { 6 | MemTotal = RegEx("^MemTotal:[\t ]*([0-9]+)[\t ]") 7 | MemFree = RegEx("^MemFree:[\t ]*([0-9]+)[\t ]") 8 | MemCache = RegEx( "^Cached:[\t ]*([0-9]+)[\t ]") 9 | MemBuff = Regex("^Buffers:[\t ]*([0-9]+)[\t ]") 10 | } 11 | 12 | Set XPageSize = BSDCtl("vm.stats.vm.v_page_size") 13 | Set XMemTotal = If(!Ident(BSDCtl),MemTotal,Val(BSDCtl("vm.stats.vm.v_page_count"))*XPageSize) 14 | Set XMemFree = If(!Ident(BSDCtl),MemFree,Val(BSDCtl("vm.stats.vm.v_free_count"))*XPageSize) 15 | Set XMemCache = If(!Ident(BSDCtl),MemCache,Val(BSDCtl("vm.stats.vm.v_inactive_count"))*XPageSize) 16 | Set XMemBuff = If(!Ident(BSDCtl),MemBuff,Val(BSDCtl("vm.stats.vm_laundry_count"))*XPageSize) 17 | Set XMemUtilization = (XMemTotal-XMemFree-XMemCache-XMemBuff)/XMemTotal 18 | Set XMemPresent = If(Ident(BSDCtl),$XPageSize!="",MemTotal.count) 19 | -------------------------------------------------------------------------------- /src/client.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLIENT_H__ 2 | #define __CLIENT_H__ 3 | 4 | #include 5 | #include "scanner.h" 6 | 7 | typedef struct _Client Client; 8 | struct _Client { 9 | source_t *src; 10 | GSocketConnection *scon; 11 | GSocketConnectable *addr; 12 | GSocketClient *sclient; 13 | GIOChannel *in,*out; 14 | void *data; 15 | gchar *trigger; 16 | gboolean (*connect) ( Client * ); 17 | GIOStatus (*respond) ( Client * ); 18 | GIOStatus (*consume) ( Client *, gsize *size ); 19 | }; 20 | 21 | source_t *client_exec ( gchar *fname, gchar *trigger ); 22 | source_t *client_socket ( gchar *fname, gchar *trigger ); 23 | source_t *client_mpd ( gchar *fname ); 24 | void client_attach ( Client *client ); 25 | gboolean client_socket_connect ( Client *client ); 26 | GIOStatus client_source_update ( Client *client, gsize *size ); 27 | void client_send ( gchar *addr, gchar *command ); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /config/winops.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | function ToggleMinimize() { 4 | If !WindowInfo("minimized") 5 | Minimize(); 6 | Else 7 | UnMinimize(); 8 | } 9 | 10 | function ToggleMaximize() { 11 | If !WindowInfo("maximized") 12 | Maximize(); 13 | Else 14 | UnMaximize(); 15 | } 16 | 17 | menu("winops") { 18 | item { 19 | value = GT("focus"); 20 | icon = "focus-windows-symbolic"; 21 | action = Focus(); 22 | } 23 | item { 24 | value = GT("close"); 25 | icon = "window-close-symbolic"; 26 | action = Close(); 27 | } 28 | item { 29 | value = GT("(un)minimize"); 30 | icon = "window-minimize-symbolic"; 31 | action = ToggleMinimize(); 32 | } 33 | item { 34 | value = GT("(un)maximize"); 35 | icon = "window-maximize-symbolic"; 36 | action = ToggleMaximize(); 37 | } 38 | } 39 | 40 | #CSS 41 | 42 | menuitem label { 43 | padding-left: 5px; 44 | } 45 | -------------------------------------------------------------------------------- /src/gui/scale.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCALE_H__ 2 | #define __SCALE_H__ 3 | 4 | #include "basewidget.h" 5 | 6 | #define SCALE_TYPE (scale_get_type()) 7 | #define SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SCALE_TYPE, Scale)) 8 | #define SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SCALE_TYPE, ScaleClass)) 9 | #define IS_SCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SCALE_TYPE)) 10 | #define IS_SCALECLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SCALE_TYPE)) 11 | 12 | typedef struct _Scale Scale; 13 | typedef struct _ScaleClass ScaleClass; 14 | 15 | struct _Scale 16 | { 17 | BaseWidget item; 18 | }; 19 | 20 | struct _ScaleClass 21 | { 22 | BaseWidgetClass parent_class; 23 | }; 24 | 25 | typedef struct _ScalePrivate ScalePrivate; 26 | 27 | struct _ScalePrivate 28 | { 29 | GtkWidget *scale; 30 | gint dir; 31 | }; 32 | 33 | GType scale_get_type ( void ); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /icons/misc/rewind.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 11 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /icons/misc/fforward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 11 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /packaging/freebsd/files/pkg-message.in: -------------------------------------------------------------------------------- 1 | [ 2 | { type: install 3 | message: < 6 | 7 | #define MODULE_API_VERSION 3 8 | 9 | typedef void (*ModuleInvalidator)( void ); 10 | typedef gboolean (*ModuleInitializer)( void ); 11 | 12 | typedef struct { 13 | gboolean ready; 14 | gboolean active; 15 | gchar *interface; 16 | gchar *provider; 17 | void (*activate) (void); 18 | void (*deactivate) (void); 19 | void (*finalize) (void); 20 | } ModuleInterfaceV1; 21 | 22 | typedef struct { 23 | GList *list; 24 | ModuleInterfaceV1 *active; 25 | } ModuleInterfaceList; 26 | 27 | gboolean module_load ( gchar *name ); 28 | void module_invalidate_all ( void ); 29 | void module_interface_select ( gchar *interface ); 30 | void module_interface_activate ( ModuleInterfaceV1 *iface ); 31 | void module_interface_deactivate ( ModuleInterfaceV1 *iface ); 32 | gchar *module_interface_provider_get ( gchar *interface ); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/util/string.h: -------------------------------------------------------------------------------- 1 | #ifndef __SFWBAR_STRING_H__ 2 | #define __SFWBAR_STRING_H__ 3 | 4 | #include 5 | 6 | #define str_get(x) g_atomic_pointer_get(&(x)) 7 | 8 | guint str_nhash ( gchar *str ); 9 | gint64 str_ascii_toll ( const gchar *str, gchar **end, guint base ); 10 | guint64 str_ascii_toull ( const gchar *str, gchar **end, guint base ); 11 | gboolean str_nequal ( gchar *str1, gchar *str2 ); 12 | void str_assign ( gchar **old, gchar *new ); 13 | gchar *str_replace ( gchar *str, gchar *old, gchar *new ); 14 | gchar *str_escape ( gchar *string ); 15 | void *ptr_pass ( void *ptr ); 16 | gint strv_index ( gchar **strv, gchar *key ); 17 | int md5_file( gchar *path, guchar output[16] ); 18 | gchar *numeric_to_string ( double num, gint dec ); 19 | gboolean pattern_match ( gchar **dict, gchar *string ); 20 | gboolean regex_match_list ( GList *dict, gchar *string ); 21 | void regex_list_add ( GList **list, gchar *pattern ); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/gui/button.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUTTON_H__ 2 | #define __BUTTON_H__ 3 | 4 | #include "basewidget.h" 5 | 6 | #define BUTTON_TYPE (button_get_type()) 7 | #define BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), BUTTON_TYPE, Button)) 8 | #define BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), BUTTON_TYPE, ButtonClass)) 9 | #define IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BUTTON_TYPE)) 10 | #define IS_BUTTONCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), BUTTON_TYPE)) 11 | 12 | typedef struct _Button Button; 13 | typedef struct _ButtonClass ButtonClass; 14 | 15 | struct _Button 16 | { 17 | BaseWidget item; 18 | }; 19 | 20 | struct _ButtonClass 21 | { 22 | BaseWidgetClass parent_class; 23 | }; 24 | 25 | typedef struct _ButtonPrivate ButtonPrivate; 26 | 27 | struct _ButtonPrivate 28 | { 29 | GtkWidget *button; 30 | GtkWidget *image; 31 | }; 32 | 33 | GType button_get_type ( void ); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /config/mpd.widget: -------------------------------------------------------------------------------- 1 | include("mpd.source") 2 | 3 | layout { 4 | style = If(MpdState.count=0,"hidden","frame") 5 | label { 6 | style = "mpd" 7 | interval = 100 8 | value = $MpdTitle 9 | loc(1,1,4,1) 10 | } 11 | label { 12 | style = "mpd" 13 | interval = 100 14 | value = $MpdArtist 15 | loc(1,2,4,1) 16 | } 17 | image { 18 | style="mpd" 19 | value = "icons/misc/rewind.svg" 20 | loc(1,3,1,1) 21 | action = MpdCmd "previous" 22 | } 23 | image { 24 | style="mpd" 25 | value = "icons/misc/play.svg" 26 | loc(2,3,1,1) 27 | action = MpdCmd "play" 28 | } 29 | image { 30 | style="mpd" 31 | value = "icons/misc/stop.svg" 32 | loc(3,3,1,1) 33 | action = MpdCmd "stop" 34 | } 35 | image { 36 | style="mpd" 37 | value = "icons/misc/fforward.svg" 38 | loc(4,3,1,1) 39 | action = MpdCmd "next" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/util/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASH_TABLE_H__ 2 | #define __HASH_TABLE_H__ 3 | 4 | #include 5 | 6 | typedef struct _hash_table { 7 | GHashTable *table; 8 | GRecMutex mutex; 9 | } hash_table_t; 10 | 11 | hash_table_t *hash_table_new(GHashFunc hash, GEqualFunc equal ); 12 | hash_table_t *hash_table_new_full(GHashFunc hash, GEqualFunc equal, 13 | GDestroyNotify destroy_key, GDestroyNotify destroy_value); 14 | gboolean hash_table_insert ( hash_table_t *hash, gpointer key, gpointer val ); 15 | gpointer hash_table_lookup ( hash_table_t *hash, gconstpointer key ); 16 | gboolean hash_table_remove ( hash_table_t *hash, gconstpointer key ); 17 | void hash_table_remove_all ( hash_table_t *hash ); 18 | gpointer hash_table_find ( hash_table_t *hash, GHRFunc pred, gpointer key); 19 | void hash_table_foreach( hash_table_t *hash, GHFunc func, gpointer d ); 20 | void hash_table_lock( hash_table_t *hash ); 21 | void hash_table_unlock( hash_table_t *hash ); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /config/rfkill.source: -------------------------------------------------------------------------------- 1 | scanner { 2 | ExecClient("stdbuf -oL rfkill event","rfkill") { 3 | RfkillWifiSoft = RegEx("type 1 op [0-9]+ soft ([0-9]+)") 4 | RfkillWifiHard = RegEx("type 1 op [0-9]+ soft [0-9]+ hard ([0-9]+)") 5 | RfkillBluetoothSoft = RegEx("type 2 op [0-9]+ soft ([0-9]+)") 6 | RfkillBluetoothHard = RegEx("type 2 op [0-9]+ soft [0-9]+ hard ([0-9]+)") 7 | } 8 | } 9 | 10 | Set XRfKillBTPresent = Cached(XRfKillBTPresent) | RfKillBluetoothSoft.count 11 | Set XRfKillBTSoft = If(RfKillBluetoothSoft.count, 12 | RfKillBluetoothSoft, 13 | Cached(XRfKillBTSoft)) 14 | Set XRfKillBTHard = If(RfKillBluetoothHard.count, 15 | RfKillBluetoothHard, 16 | Cached(XRfKillBTHard)) 17 | Set XRfKillWifiPresent = Cached(XRfKillWifiPresent) | RfKillWifiSoft.count 18 | Set XRfKillWifiSoft = If(RfKillWifiSoft.count, 19 | RfKillWifiSoft, 20 | Cached(XRfKillWifiSoft)) 21 | Set XRfKillWifiHard = If(RfKillWifiHard.count, 22 | RfKillWifiHard, 23 | Cached(XRfKillWifiHard)) 24 | -------------------------------------------------------------------------------- /config/wbar-net.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Module("network") 4 | 5 | Private { 6 | include("wifi.widget") 7 | 8 | function ToggleNet() { 9 | UserState(If(WidgetState(1)=0,"on","off")); 10 | UpdateWidget(); 11 | } 12 | 13 | layout { 14 | label { 15 | style = If(!Ident(NetInfo), "hidden", 16 | If(NetInfo("ip")="", 17 | "network_disconnected", 18 | "network" 19 | )) 20 | value = If(NetInfo('ip')='', 'Disconnected ⚠', 21 | If(WidgetState(1), 22 | NetInfo("interface") + ": " + NetInfo("ip") + "/" + NetInfo("cidr"), 23 | If(NetInfo("Essid")="", 24 | NetInfo("ip") + ": " + NetInfo("cidr") + " ", 25 | NetInfo("Essid") + " (" + Str(NetStat("signal")) + "%) " 26 | ) 27 | ) 28 | ) 29 | trigger = "network" 30 | action[LeftClick] = ToggleNet() 31 | action[RightClick] = Popup("XWifiWindow") 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/gui/chart.h: -------------------------------------------------------------------------------- 1 | #ifndef __CHART_H__ 2 | #define __CHART_H__ 3 | 4 | #include 5 | 6 | #define CHART_TYPE (chart_get_type()) 7 | #define CHART(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CHART_TYPE, Chart)) 8 | #define CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CHART_TYPE, ChartClass)) 9 | #define IS_CHART(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), CHART_TYPE)) 10 | #define IS_CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), CHART_TYPE)) 11 | 12 | typedef struct _Chart Chart; 13 | typedef struct _ChartClass ChartClass; 14 | 15 | struct _Chart 16 | { 17 | GtkBox parent_class; 18 | }; 19 | 20 | struct _ChartClass 21 | { 22 | GtkBoxClass parent_class; 23 | }; 24 | 25 | typedef struct _ChartPrivate ChartPrivate; 26 | 27 | struct _ChartPrivate 28 | { 29 | GQueue *data; 30 | GtkWidget *chart; 31 | }; 32 | 33 | GType chart_get_type ( void ); 34 | 35 | GtkWidget *chart_new( void ); 36 | int chart_update ( GtkWidget *widget, gdouble n ); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/gui/image.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2022- sfwbar maintainers 4 | */ 5 | 6 | #include "basewidget.h" 7 | #include "image.h" 8 | #include "scaleimage.h" 9 | 10 | G_DEFINE_TYPE_WITH_CODE (Image, image, BASE_WIDGET_TYPE, G_ADD_PRIVATE (Image)) 11 | 12 | static void image_update_value ( GtkWidget *self ) 13 | { 14 | ImagePrivate *priv; 15 | 16 | g_return_if_fail(IS_IMAGE(self)); 17 | priv = image_get_instance_private(IMAGE(self)); 18 | 19 | scale_image_set_image(GTK_WIDGET(priv->image), 20 | base_widget_get_value(self),NULL); 21 | } 22 | 23 | static void image_class_init ( ImageClass *kclass ) 24 | { 25 | BASE_WIDGET_CLASS(kclass)->update_value = image_update_value; 26 | } 27 | 28 | static void image_init ( Image *self ) 29 | { 30 | ImagePrivate *priv; 31 | 32 | priv = image_get_instance_private(IMAGE(self)); 33 | 34 | priv->image = scale_image_new(); 35 | gtk_container_add(GTK_CONTAINER(self),priv->image); 36 | } 37 | -------------------------------------------------------------------------------- /config/mpd-mini.widget: -------------------------------------------------------------------------------- 1 | Scanner { 2 | MpdClient("") { 3 | MpdTitle = RegEx("Title: (.*)") 4 | MpdArtist = RegEx("Artist: (.*)") 5 | MpdState = RegEx("state: (.*)") 6 | } 7 | } 8 | 9 | layout { 10 | style = If(MpdState.count=0,"hidden","frame") 11 | css = "* { -GtkWidget-direction: right; }" 12 | image { 13 | style="mpd" 14 | value = "icons/misc/rewind.svg" 15 | action = MpdCmd "previous" 16 | tooltip = $MpdArtist + "\n" + $MpdTitle 17 | } 18 | image { 19 | style="mpd" 20 | value = "icons/misc/play.svg" 21 | action = MpdCmd "play" 22 | tooltip = $MpdArtist + "\n" + $MpdTitle 23 | } 24 | image { 25 | style="mpd" 26 | value = "icons/misc/stop.svg" 27 | action = MpdCmd "stop" 28 | tooltip = $MpdArtist + "\n" + $MpdTitle 29 | } 30 | image { 31 | style="mpd" 32 | value = "icons/misc/fforward.svg" 33 | action = MpdCmd "next" 34 | tooltip = $MpdArtist + "\n" + $MpdTitle 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/util/json.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSON_H__ 2 | #define __JSON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | gint socket_connect ( const gchar *sockaddr, gint to ); 9 | gboolean recv_retry ( gint sock, gpointer buff, gsize len ); 10 | json_object *recv_json ( gint sock, gssize len ); 11 | 12 | const gchar *json_string_by_name ( struct json_object *obj, gchar *name ); 13 | gint64 json_int_by_name ( struct json_object *obj, gchar *name, gint64 defval); 14 | gboolean json_bool_by_name ( struct json_object *obj, gchar *name, gboolean defval); 15 | gdouble json_double_by_name ( struct json_object *obj, gchar *name, gdouble defval); 16 | struct json_object *json_array_by_name ( struct json_object *obj, gchar *key ); 17 | struct json_object *json_node_by_name ( struct json_object *json, gchar *key ); 18 | GdkRectangle json_rect_get ( struct json_object *json ); 19 | gboolean json_array_to_strv ( struct json_object *json, gchar ***strv ); 20 | 21 | struct json_object *jpath_parse ( gchar *path, struct json_object *obj ); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /config/cpu.source: -------------------------------------------------------------------------------- 1 | # Add up CPU utilization stats across all CPUs 2 | file("/proc/stat") { 3 | CpuUser = RegEx("^cpu [\t ]*([0-9]+)",Sum) 4 | CpuNice = RegEx("^cpu [\t ]*[0-9]+ ([0-9]+)",Sum) 5 | CpuSystem = RegEx("^cpu [\t ]*(?:[0-9]+ ){2}([0-9]+)",Sum) 6 | CpuIdle = RegEx("^cpu [\t ]*(?:[0-9]+ ){3}([0-9]+)",Sum) 7 | } 8 | 9 | module("bsdctl") 10 | 11 | Set XCpuBSD = BSDCtl("kern.cp_time") 12 | Set XCpuUser = If(!Ident(BSDCtl),CpuUser,Extract($XCpuBSD,"([0-9]+)")) 13 | Set XCpuSystem = If(!Ident(BSDCtl),CpuSystem,Extract($XCpuBSD,"[0-9]+ ([0-9]+)")) 14 | Set XCpuNice = If(!Ident(BSDCtl),CpuNice,Extract($XCpuBSD,"(?:[0-9]+ ){2}([0-9]+)")) 15 | Set XCpuIntr = If(!Ident(BSDCtl),0,Extract($XCpuBSD,"(?:[0-9]+ ){3}([0-9]+)")) 16 | Set XCpuIdle = If(!Ident(BSDCtl),CpuIdle,Extract($XCpuBSD,"(?:[0-9]+ ){4}([0-9]+)")) 17 | Set XCpuUtilization = (XCpuUser-XCpuUser.pval)/ 18 | (XCpuUser+XCpuNice+XCpuSystem+XCpuIntr+XCpuIdle- 19 | XCpuUser.pval-XCpuNice.pval-XCpuSystem.pval-XCpuIntr.pval-XCpuIdle.pval) 20 | Set XCpuPresent = If(Ident(BSDCtl),$XCpuBSD!="",CpuIdle.count) 21 | -------------------------------------------------------------------------------- /packaging/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Lev Babiev 2 | 3 | pkgname=sfwbar 4 | pkgver=1.0_beta10 5 | pkgrel=1 6 | 7 | pkgdesc='S* Floating Window taskBar' 8 | arch=('x86_64') 9 | url='https://github.com/LBCrion/sfwbar' 10 | license=('GPL3') 11 | depends=( 12 | 'wayland' 13 | 'gtk3' 14 | 'json-c' 15 | 'gtk-layer-shell' 16 | 'wayland-protocols' 17 | ) 18 | optdepends=( 19 | 'libpulse: pulse audio volume control', 20 | 'libmpdclient: music player daemon control', 21 | 'libxkbcommon: xkb layout conversion support' 22 | ) 23 | makedepends=( 24 | 'meson' 25 | ) 26 | 27 | source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz") 28 | 29 | sha256sums=('88d192940c8f4c74fbeab6f054fa9ec57b42f7053859317c9a0de9cf6995b2a3') 30 | 31 | build() { 32 | cd "$pkgname-$pkgver" 33 | meson --prefix=/usr \ 34 | --buildtype=plain \ 35 | build 36 | ninja -C build 37 | } 38 | 39 | package() { 40 | cd "$pkgname-$pkgver" 41 | DESTDIR="$pkgdir" ninja -C build install 42 | } 43 | -------------------------------------------------------------------------------- /src/gui/switcher.h: -------------------------------------------------------------------------------- 1 | #ifndef __SWITCHER_H__ 2 | #define __SWITCHER_H__ 3 | 4 | #include "flowgrid.h" 5 | 6 | #define SWITCHER_TYPE (switcher_get_type()) 7 | #define SWITCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SWITCHER_TYPE, Switcher)) 8 | #define SWITCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SWITCHER_TYPE, SwitcherClass)) 9 | #define IS_SWITCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SWITCHER_TYPE)) 10 | #define IS_SWITCHERCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SWITCHER_TYPE)) 11 | 12 | typedef struct _Switcher Switcher; 13 | typedef struct _SwitcherClass SwitcherClass; 14 | 15 | struct _Switcher 16 | { 17 | FlowGrid item; 18 | }; 19 | 20 | struct _SwitcherClass 21 | { 22 | FlowGridClass parent_class; 23 | }; 24 | 25 | typedef struct _SwitcherPrivate SwitcherPrivate; 26 | 27 | struct _SwitcherPrivate 28 | { 29 | GtkWidget *switcher; 30 | gint filter; 31 | }; 32 | 33 | GType switcher_get_type ( void ); 34 | 35 | GtkWidget *switcher_new(); 36 | gboolean switcher_is_focused ( gpointer uid ); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /config/usage.widget: -------------------------------------------------------------------------------- 1 | include("cpu.source") 2 | include("memory.source") 3 | 4 | scanner { 5 | # Get total and remaining battery charge 6 | file("/sys/class/power_supply/BAT0/charge_full") { 7 | BatteryTotal = Grab(Sum) 8 | } 9 | file("/sys/class/power_supply/BAT0/charge_now") { 10 | BatteryLeft = Grab(Sum) 11 | } 12 | file("/sys/class/power_supply/AC/online") { 13 | ACOnline = Grab(Sum) 14 | } 15 | } 16 | 17 | layout { 18 | # add a sub-grid to house scales 19 | style = "scales" 20 | scale { 21 | style = if(XCpuPresent,"","hidden") 22 | css = "progressbar progress { background-color: #0000ff;}" 23 | value = XCpuUtilization 24 | } 25 | scale { 26 | style = if(XMemoryPresent,"","hidden") 27 | css = "progressbar progress { background-color: #00ff00;}" 28 | value= XMemoryUtilization 29 | } 30 | scale { 31 | value = BatteryLeft/BatteryTotal 32 | style = ACOnline 33 | css = "progressbar#1 progress { background-color: #ff0000;} \ 34 | progressbar#0 progress { background-color: #ffff00;}" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /config/alsa.widget: -------------------------------------------------------------------------------- 1 | scanner { 2 | ExecClient("stdbuf -oL amixer sevents","alsactl") {} 3 | Exec("amixer sget Master") { 4 | AlsaVolume = RegEx(".*[[](.[0-9]+)%") 5 | AlsaMuted = RegEx(".*[[].*[[]([A-Za-z].*)[]]") 6 | } 7 | } 8 | 9 | set AlsaMutedIcon = "audio-volume-muted-symbolic" 10 | set AlsaVolumeIcon = Lookup(AlsaVolume, 11 | 80, "audio-volume-high-symbolic", 12 | 50, "audio-volume-medium-symbolic", 13 | 0, "audio-volume-low-symbolic", 14 | $AlsaMutedIcon) 15 | set AlsaIcon = If($AlsaMuted = "off",$AlsaMutedIcon,$AlsaVolumeIcon) 16 | 17 | layout { 18 | style = "module" 19 | button { 20 | value = $AlsaIcon 21 | tooltip = GT("Volume") + ": " + Str(AlsaVolume,0) + "%" + If(AlsaMuted," (" + GT("muted") + ")","") 22 | style = If(Ident($AlsaVolume),"module","hidden") 23 | trigger = "alsactl" 24 | action[LeftClick] = Exec "amixer sset Master toggle\n" 25 | action[RightClick] = Exec $Term + " -e alsamixer" 26 | action[ScrollUp] = Exec "amixer sset Master 5%+\n" 27 | action[ScrollDown] = Exec "amixer sset Master 5%-\n" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /doc/sfwbar-idle.rst: -------------------------------------------------------------------------------- 1 | sfwbar-idle 2 | ########### 3 | 4 | ########################### 5 | Sfwbar Idle notifier module 6 | ########################### 7 | 8 | :Copyright: GPLv3+ 9 | :Manual section: 1 10 | 11 | Filename: idle.so 12 | 13 | Requires: none 14 | 15 | SYNOPSIS 16 | ======== 17 | 18 | The idle notifier module, provides support for idle triggers, i.e. triggers 19 | that are emitted if the user has been idle for a specified period of time. 20 | 21 | Expression Functions 22 | ==================== 23 | 24 | None. 25 | 26 | Actions 27 | ======= 28 | 29 | IdleTimeout Trigger, Timeout 30 | ----------------------------- 31 | 32 | Create a new trigger with a name Trigger that will be emitted after Timeout 33 | seconds of idleness. I.e. `IdleTimeout "timeout1", "10"`. A trigger can be 34 | removed by invoking this action again with a Timeout value of zero. 35 | 36 | Triggers 37 | ======== 38 | 39 | The idle module defines trigger `resumed` by default. This trigger is emitted 40 | on the first user interaction after a timeout. Timeout triggers are defined 41 | using the `IdleTimeout` action. 42 | -------------------------------------------------------------------------------- /src/gui/tray.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRAY_H__ 2 | #define __TRAY_H__ 3 | 4 | #include "flowgrid.h" 5 | #include "sni.h" 6 | 7 | #define TRAY_TYPE (tray_get_type()) 8 | #define TRAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TRAY_TYPE, Tray)) 9 | #define TRAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TRAY_TYPE, TrayClass)) 10 | #define IS_TRAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TRAY_TYPE)) 11 | #define IS_TRAYCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TRAY_TYPE)) 12 | 13 | typedef struct _Tray Tray; 14 | typedef struct _TrayClass TrayClass; 15 | 16 | struct _Tray 17 | { 18 | FlowGrid item; 19 | }; 20 | 21 | struct _TrayClass 22 | { 23 | FlowGridClass parent_class; 24 | }; 25 | 26 | typedef struct _TrayPrivate TrayPrivate; 27 | 28 | struct _TrayPrivate 29 | { 30 | guint timer_h; 31 | }; 32 | 33 | GType tray_get_type ( void ); 34 | 35 | GtkWidget *tray_new(); 36 | void tray_item_init_for_all ( sni_item_t *sni ); 37 | void tray_item_destroy ( sni_item_t *sni ); 38 | void tray_update ( void ); 39 | void tray_invalidate_all ( sni_item_t *sni ); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/vm/expr.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXPR_H__ 2 | #define __EXPR_H__ 3 | 4 | #include 5 | 6 | typedef struct _expr_cache { 7 | gint refcount; 8 | gboolean invalid; 9 | gchar *definition; 10 | gchar *cache; 11 | GBytes *code; 12 | gboolean always_update; 13 | GtkWidget *widget; 14 | GdkEvent *event; 15 | gint stack_depth; 16 | GQuark quark; 17 | void *store; 18 | } expr_cache_t; 19 | 20 | typedef struct _expr_dep { 21 | GList *list; 22 | GMutex mutex; 23 | } expr_dep_t; 24 | 25 | #define EXPR_CACHE(x) ((expr_cache_t *)(x)) 26 | 27 | void expr_lib_init ( void ); 28 | expr_cache_t *expr_cache_new ( void ); 29 | expr_cache_t *expr_cache_new_with_code ( GBytes *code ); 30 | void expr_update ( expr_cache_t **expr, GBytes *code ); 31 | void expr_cache_set ( expr_cache_t *expr, gchar *def ); 32 | expr_cache_t *expr_cache_ref ( expr_cache_t *expr ); 33 | void expr_cache_unref ( expr_cache_t *expr ); 34 | void expr_dep_add ( GQuark quark, expr_cache_t *expr ); 35 | void expr_dep_remove ( expr_cache_t *expr ); 36 | void expr_dep_trigger ( GQuark quark ); 37 | void expr_dep_dump ( void ); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/gui/cchart.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2022- sfwbar maintainers 4 | */ 5 | 6 | #include "cchart.h" 7 | #include "chart.h" 8 | 9 | G_DEFINE_TYPE_WITH_CODE (CChart, cchart, BASE_WIDGET_TYPE, 10 | G_ADD_PRIVATE (CChart)) 11 | 12 | static void cchart_update_value ( GtkWidget *self ) 13 | { 14 | CChartPrivate *priv; 15 | gchar *value; 16 | 17 | g_return_if_fail(IS_CCHART(self)); 18 | priv = cchart_get_instance_private(CCHART(self)); 19 | 20 | value = base_widget_get_value(self); 21 | 22 | if(!g_strrstr(value, "nan")) 23 | chart_update(priv->chart, g_ascii_strtod(value, NULL)); 24 | } 25 | 26 | static void cchart_class_init ( CChartClass *kclass ) 27 | { 28 | BASE_WIDGET_CLASS(kclass)->update_value = cchart_update_value; 29 | BASE_WIDGET_CLASS(kclass)->always_update = TRUE; 30 | } 31 | 32 | static void cchart_init ( CChart *self ) 33 | { 34 | CChartPrivate *priv; 35 | 36 | priv = cchart_get_instance_private(CCHART(self)); 37 | 38 | priv->chart = chart_new(); 39 | gtk_container_add(GTK_CONTAINER(self), priv->chart); 40 | } 41 | -------------------------------------------------------------------------------- /src/gui/button.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2022- sfwbar maintainers 4 | */ 5 | 6 | #include "basewidget.h" 7 | #include "button.h" 8 | #include "scaleimage.h" 9 | 10 | G_DEFINE_TYPE_WITH_CODE (Button, button, BASE_WIDGET_TYPE, G_ADD_PRIVATE (Button)) 11 | 12 | static void button_update_value ( GtkWidget *self ) 13 | { 14 | ButtonPrivate *priv; 15 | 16 | g_return_if_fail(IS_BUTTON(self)); 17 | priv = button_get_instance_private(BUTTON(self)); 18 | 19 | scale_image_set_image(GTK_WIDGET(priv->image), base_widget_get_value(self), 20 | NULL); 21 | } 22 | 23 | static void button_class_init ( ButtonClass *kclass ) 24 | { 25 | BASE_WIDGET_CLASS(kclass)->update_value = button_update_value; 26 | } 27 | 28 | static void button_init ( Button *self ) 29 | { 30 | ButtonPrivate *priv; 31 | 32 | priv = button_get_instance_private(BUTTON(self)); 33 | 34 | priv->button = gtk_button_new(); 35 | priv->image = scale_image_new(); 36 | gtk_container_add(GTK_CONTAINER(priv->button), priv->image); 37 | gtk_container_add(GTK_CONTAINER(self), priv->button); 38 | } 39 | -------------------------------------------------------------------------------- /icons/misc/lock-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /icons/weather/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 Yr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /icons/misc/unlock-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/gui/trayitem.h: -------------------------------------------------------------------------------- 1 | #ifndef __SNIITEM_H__ 2 | #define __SNIITEM_H__ 3 | 4 | #include "flowitem.h" 5 | #include "sni.h" 6 | 7 | #define TRAY_ITEM_TYPE (tray_item_get_type()) 8 | #define TRAY_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TRAY_ITEM_TYPE, TrayItem)) 9 | #define TRAY_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TRAY_ITEM_TYPE, TrayItemClass)) 10 | #define IS_TRAY_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TRAY_ITEM_TYPE)) 11 | #define IS_TRAY_ITEMCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TRAY_ITEM_TYPE)) 12 | 13 | typedef struct _TrayItem TrayItem; 14 | typedef struct _TrayItemClass TrayItemClass; 15 | 16 | struct _TrayItem 17 | { 18 | FlowItem item; 19 | }; 20 | 21 | struct _TrayItemClass 22 | { 23 | FlowItemClass parent_class; 24 | }; 25 | 26 | typedef struct _TrayItemPrivate TrayItemPrivate; 27 | 28 | struct _TrayItemPrivate 29 | { 30 | sni_item_t *sni; 31 | GtkWidget *button; 32 | GtkWidget *icon; 33 | GtkWidget *label; 34 | GtkWidget *tray; 35 | gboolean invalid; 36 | }; 37 | 38 | GType tray_item_get_type ( void ); 39 | 40 | GtkWidget *tray_item_new( sni_item_t *win, GtkWidget *tray ); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/gui/pageritem.h: -------------------------------------------------------------------------------- 1 | #ifndef __PAGERITEM_H__ 2 | #define __PAGERITEM_H__ 3 | 4 | #include "flowitem.h" 5 | #include "pager.h" 6 | 7 | #define PAGER_ITEM_TYPE (pager_item_get_type()) 8 | #define PAGER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PAGER_ITEM_TYPE, PagerItem)) 9 | #define PAGER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PAGER_ITEM_TYPE, PagerItemClass)) 10 | #define IS_PAGER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PAGER_ITEM_TYPE)) 11 | #define IS_PAGER_ITEMCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PAGER_ITEM_TYPE)) 12 | 13 | typedef struct _PagerItem PagerItem; 14 | typedef struct _PagerItemClass PagerItemClass; 15 | 16 | struct _PagerItem 17 | { 18 | FlowItem item; 19 | }; 20 | 21 | struct _PagerItemClass 22 | { 23 | FlowItemClass parent_class; 24 | }; 25 | 26 | typedef struct _PagerItemPrivate PagerItemPrivate; 27 | 28 | struct _PagerItemPrivate 29 | { 30 | GtkWidget *button; 31 | GtkWidget *label; 32 | GtkWidget *pager; 33 | workspace_t *ws; 34 | gboolean invalid; 35 | }; 36 | 37 | GType pager_item_get_type ( void ); 38 | 39 | void pager_item_new( workspace_t *ws, GtkWidget *pager ); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /packaging/sfwbar-1.0_beta10.ebuild: -------------------------------------------------------------------------------- 1 | # Copyright 2020-2022 Gentoo Authors 2 | # Distributed under the terms of the GNU General Public License v2 3 | 4 | EAPI=8 5 | 6 | inherit meson xdg-utils 7 | 8 | DESCRIPTION="S* Floating Window Bar" 9 | HOMEPAGE="https://github.com/LBCrion/sfwbar" 10 | SRC_URI="https://github.com/LBCrion/sfwbar/archive/v${PV}.tar.gz -> ${P}.tar.gz" 11 | KEYWORDS="~amd64" 12 | 13 | LICENSE="GPL-3" 14 | SLOT="0" 15 | IUSE="+mpd +pulse +net +xkb" 16 | 17 | DEPEND=" 18 | mpd? ( media-libs/libmpdclient ) 19 | pulse? ( media-libs/libpulse ) 20 | xkb? ( x11-libs/libxkbcommon ) 21 | >=x11-libs/gtk+-3.22.0:3[introspection,wayland] 22 | gui-libs/gtk-layer-shell 23 | dev-libs/json-c 24 | dev-util/wayland-scanner 25 | virtual/freedesktop-icon-theme 26 | >=dev-libs/wayland-protocols-1.17 27 | " 28 | RDEPEND="${DEPEND}" 29 | BDEPEND=" 30 | virtual/pkgconfig 31 | " 32 | 33 | src_configure() { 34 | local emesonargs=( 35 | $(meson_feature mpd) 36 | $(meson_feature pulse) 37 | $(meson_feature net network) 38 | ) 39 | 40 | meson_src_configure 41 | } 42 | 43 | pkg_postinst() { 44 | xdg_icon_cache_update 45 | } 46 | 47 | pkg_postrm() { 48 | xdg_icon_cache_update 49 | } 50 | -------------------------------------------------------------------------------- /src/gui/grid.h: -------------------------------------------------------------------------------- 1 | #ifndef __GRID_H__ 2 | #define __GRID_H__ 3 | 4 | #include "basewidget.h" 5 | 6 | #define GRID_TYPE (grid_get_type()) 7 | #define GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GRID_TYPE, Grid)) 8 | #define GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GRID_TYPE, GridClass)) 9 | #define IS_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GRID_TYPE)) 10 | #define IS_GRIDCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GRID_TYPE)) 11 | 12 | typedef struct _Grid Grid; 13 | typedef struct _GridClass GridClass; 14 | 15 | struct _Grid 16 | { 17 | BaseWidget item; 18 | }; 19 | 20 | struct _GridClass 21 | { 22 | BaseWidgetClass parent_class; 23 | }; 24 | 25 | typedef struct _GridPrivate GridPrivate; 26 | 27 | struct _GridPrivate 28 | { 29 | GtkWidget *grid; 30 | GtkWidget *scroller; 31 | GList *last; 32 | GList *children; 33 | gint dir; 34 | gboolean hscroll, vscroll; 35 | }; 36 | 37 | GType grid_get_type ( void ); 38 | 39 | GtkWidget *grid_new(); 40 | gboolean grid_attach ( GtkWidget *self, GtkWidget *child ); 41 | void grid_detach( GtkWidget *child, GtkWidget *self ); 42 | void grid_mirror_child ( GtkWidget *self, GtkWidget *child ); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/gui/taskbar.h: -------------------------------------------------------------------------------- 1 | #ifndef __TASKBAR_H__ 2 | #define __TASKBAR_H__ 3 | 4 | #include "flowgrid.h" 5 | 6 | #define TASKBAR_TYPE (taskbar_get_type()) 7 | #define TASKBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TASKBAR_TYPE, Taskbar)) 8 | #define TASKBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TASKBAR_TYPE, TaskbarClass)) 9 | #define IS_TASKBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TASKBAR_TYPE)) 10 | #define IS_TASKBARCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TASKBAR_TYPE)) 11 | #define TASKBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TASKBAR_TYPE, TaskbarClass)) 12 | 13 | typedef struct _Taskbar Taskbar; 14 | typedef struct _TaskbarClass TaskbarClass; 15 | 16 | struct _Taskbar 17 | { 18 | FlowGrid item; 19 | }; 20 | 21 | struct _TaskbarClass 22 | { 23 | FlowGridClass parent_class; 24 | }; 25 | 26 | typedef struct _TaskbarPrivate TaskbarPrivate; 27 | 28 | struct _TaskbarPrivate 29 | { 30 | GtkWidget *parent; 31 | }; 32 | 33 | GType taskbar_get_type ( void ); 34 | 35 | GtkWidget *taskbar_new( GtkWidget *parent ); 36 | GtkWidget *taskbar_get_parent ( GtkWidget *self ); 37 | GtkWidget *taskbar_get_taskbar ( GtkWidget *, window_t *, gboolean ); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /config/language.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | module("xkbmap") 4 | 5 | TriggerAction "language-list", LayoutMenuBuild(); 6 | 7 | Var LayoutMenuTmpl = " 8 | Menu('LayoutList') { 9 | Item { 10 | value = '%NAME%'; 11 | action = SetLayout('%LAYOUT%'); 12 | } 13 | }" 14 | 15 | Function LayoutName ( lang ) 16 | { 17 | if(CustomIPC() = "hyprland") 18 | Return XkbMap(lang, "name", "description"); 19 | Else 20 | Return lang; 21 | } 22 | 23 | Function LayoutMenuBuild() 24 | { 25 | Var i, l = LayoutList(); 26 | 27 | MenuClear("LayoutList"); 28 | i = 0; 29 | While i','') 5 | 6 | function("SetMpd") { 7 | SetValue "Mpd", 8 | If($MpdState="disconnected", 9 | "Disconnected", 10 | Map($MpdState,"pause"," ","play","","") + 11 | $XMpdRandom + " "+ '' + If(!MpdRepeat,""," ")+ 12 | if($MpdState="stop","Stopped", 13 | $MpdArtist + " - " + 14 | $MpdAlbum + " - " + 15 | $MpdTitle + " (" + 16 | Pad(Str((XMpdElapsed-XMpdElapsed%60)/60),2,"0") + ":" + 17 | Pad(Str(XMpdElapsed%60),2,"0") + 18 | "/" + 19 | Pad(Str((MpdDuration-MpdDuration%60)/60),2,"0") + ":" + 20 | Pad(Str(MpdDuration%60),2,"0") + 21 | ") " + " ⸨" + $MpdQPos + "|" + $MpdQLen + "⸩ " + Str(MpdVolume) + "%" 22 | ) 23 | ) + " " 24 | } 25 | 26 | TriggerAction "mpd", Function "SetMpd" 27 | 28 | layout { 29 | label "Mpd" { 30 | interval = 1000 31 | style = Map($MpdState, 32 | "play", "mpd_play", 33 | "pause", "mpd_paused", 34 | "stop", "mpd_stopped", 35 | "mpd_disconnected" 36 | ) 37 | action[0] = Function "SetMpd" 38 | action = MpdCmd "pause" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/gui/taskbaritem.h: -------------------------------------------------------------------------------- 1 | #ifndef __TASKBARITEM_H__ 2 | #define __TASKBARITEM_H__ 3 | 4 | #include "flowitem.h" 5 | 6 | #define TASKBAR_ITEM_TYPE (taskbar_item_get_type()) 7 | #define TASKBAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TASKBAR_ITEM_TYPE, TaskbarItem)) 8 | #define TASKBAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TASKBAR_ITEM_TYPE, TaskbarItemClass)) 9 | #define IS_TASKBAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TASKBAR_ITEM_TYPE)) 10 | #define IS_TASKBAR_ITEMCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TASKBAR_ITEM_TYPE)) 11 | 12 | typedef struct _TaskbarItem TaskbarItem; 13 | typedef struct _TaskbarItemClass TaskbarItemClass; 14 | 15 | struct _TaskbarItem 16 | { 17 | FlowItem item; 18 | }; 19 | 20 | struct _TaskbarItemClass 21 | { 22 | FlowItemClass parent_class; 23 | }; 24 | 25 | typedef struct _TaskbarItemPrivate TaskbarItemPrivate; 26 | 27 | struct _TaskbarItemPrivate 28 | { 29 | GtkWidget *icon; 30 | GtkWidget *label; 31 | GtkWidget *box; 32 | GtkWidget *taskbar; 33 | window_t *win; 34 | gboolean invalid; 35 | GdkModifierType saved_modifiers; 36 | }; 37 | 38 | GType taskbar_item_get_type ( void ); 39 | 40 | GtkWidget *taskbar_item_new( window_t *win, GtkWidget *taskbar ); 41 | void taskbar_item_set_image ( GtkWidget *icon, gchar *appid ); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /config/wbar-pulse.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | module("pulsectl") 4 | module("alsactl") 5 | 6 | Private { 7 | 8 | Var format = "" 9 | Var wbar_sink_forms = ["headphones", "hands-free", "headset", "phone", "portable", "car" ]; 10 | Var wbar_sink_icons = [ "", "", "", "", "", "" ]; 11 | Var wbar_volume_thresholds = [66, 33, 0]; 12 | Var wbar_volume_icons = ["", "", "" ]; 13 | Var wbar_volume_muted = ""; 14 | 15 | include("volume-popup.widget") 16 | 17 | Function VolumeString() { 18 | Return If(Volume("sink-mute"), 19 | wbar_volume_muted, 20 | Str(Volume("sink-volume")) + "% ") + 21 | ArrayMap(VolumeInfo("sink-form"), 22 | wbar_sink_forms, 23 | wbar_sink_icons, 24 | ArrayLookup(Volume("sink-volume"), 25 | wbar_volume_thresholds, 26 | wbar_volume_icons, 27 | wbar_volume_muted)) + 28 | " " + Str(Volume("source-volume")) + "% "; 29 | } 30 | 31 | layout { 32 | label { 33 | style = If(Ident(Volume),If(Volume("sink-mute"),"pulseaudio_muted","pulseaudio"),"hidden"); 34 | trigger = "volume"; 35 | value = VolumeString(); 36 | action[ScrollUp] = VolumeCtl("sink-volume +1"); 37 | action[ScrollDown] = VolumeCtl("sink-volume -1"); 38 | action[LeftClick] = PopUp("XVolumeWindow"); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('alsa',type:'feature',value:'auto',description:'ALSA module') 2 | option('appmenu',type:'feature',value:'enabled',description:'Application menu generator') 3 | option('bluez',type:'feature',value:'auto',description:'Bluez module') 4 | option('dbus',type:'feature',value:'auto',description:'DBus interface module') 5 | option('iwd',type:'feature',value:'auto',description:'IWD wifi module') 6 | option('nm',type:'feature',value:'auto',description:'Network Manager wifi module') 7 | option('ncenter',type:'feature',value:'auto',description:'Notification Center module') 8 | option('bsdctl',type:'feature',value:'disabled',description:'BSD sysctl module') 9 | option('idle',type:'feature',value:'auto',description:'Idle notification support') 10 | option('idleinhibit',type:'feature',value:'auto',description:'Idle inhibit protocol support') 11 | option('network',type:'feature',value:'auto',description:'Network module') 12 | option('pulse',type:'feature',value:'auto',description:'Pulse Audio module') 13 | option('pipewire',type:'feature',value:'auto',description:'Pipewire module') 14 | option('mpd',type:'feature',value:'auto',description:'Music Player Daemon module') 15 | option('xkb',type:'feature',value:'auto',description:'xkbcommon layout lookup') 16 | option('build-docs',type:'feature',value:'auto',description:'rebuild man pages from rst files') 17 | -------------------------------------------------------------------------------- /src/gui/label.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2022- sfwbar maintainers 4 | */ 5 | 6 | #include "basewidget.h" 7 | #include "label.h" 8 | 9 | G_DEFINE_TYPE_WITH_CODE (Label, label, BASE_WIDGET_TYPE, G_ADD_PRIVATE (Label)) 10 | 11 | static void label_update_value ( GtkWidget *self ) 12 | { 13 | LabelPrivate *priv; 14 | gchar *value; 15 | 16 | g_return_if_fail(IS_LABEL(self)); 17 | priv = label_get_instance_private(LABEL(self)); 18 | 19 | value = base_widget_get_value(self); 20 | if(value && pango_parse_markup(value, -1, 0, NULL, NULL, NULL, NULL)) 21 | gtk_label_set_markup(GTK_LABEL(priv->label), value); 22 | else 23 | gtk_label_set_text(GTK_LABEL(priv->label), value); 24 | } 25 | 26 | static void label_class_init ( LabelClass *kclass ) 27 | { 28 | BASE_WIDGET_CLASS(kclass)->update_value = label_update_value; 29 | } 30 | 31 | static void label_init ( Label *self ) 32 | { 33 | LabelPrivate *priv; 34 | 35 | priv = label_get_instance_private(LABEL(self)); 36 | 37 | priv->label = gtk_label_new(""); 38 | gtk_label_set_ellipsize(GTK_LABEL(priv->label), PANGO_ELLIPSIZE_END); 39 | gtk_label_set_line_wrap(GTK_LABEL(priv->label), TRUE); 40 | gtk_label_set_line_wrap_mode(GTK_LABEL(priv->label), PANGO_WRAP_WORD_CHAR); 41 | gtk_container_add(GTK_CONTAINER(self), priv->label); 42 | } 43 | -------------------------------------------------------------------------------- /config/showdesktop.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | Var FocusedWindow; 6 | Function ShowWindows() { 7 | Var i, wins; 8 | 9 | wins = WidgetChildren("target"); 10 | i = 0; 11 | While i 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/input.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2025- sfwbar maintainers 4 | */ 5 | 6 | #include 7 | #include "input.h" 8 | #include "trigger.h" 9 | #include "util/string.h" 10 | 11 | static gchar *layout; 12 | static gchar **layout_list; 13 | static struct input_api *api; 14 | 15 | void input_api_register ( struct input_api *new ) 16 | { 17 | api = new; 18 | } 19 | 20 | gboolean input_api_check ( void ) 21 | { 22 | return !!api; 23 | } 24 | 25 | void input_layout_set ( const gchar *new_layout ) 26 | { 27 | if(!g_strcmp0(layout, new_layout)) 28 | return; 29 | str_assign(&layout, g_strdup(new_layout)); 30 | trigger_emit("language"); 31 | } 32 | 33 | const gchar *input_layout_get ( void ) 34 | { 35 | return layout; 36 | } 37 | 38 | void input_layout_prev ( void ) 39 | { 40 | if(api && api->layout_prev) 41 | api->layout_prev(); 42 | } 43 | 44 | void input_layout_next ( void ) 45 | { 46 | if(api && api->layout_next) 47 | api->layout_next(); 48 | } 49 | 50 | void input_layout_change ( gchar *layout ) 51 | { 52 | if(api && api->layout_set) 53 | api->layout_set(layout); 54 | } 55 | 56 | void input_layout_list_set ( gchar **new ) 57 | { 58 | g_atomic_pointer_set(&layout_list, new); 59 | trigger_emit("language-list"); 60 | } 61 | 62 | gchar **input_layout_list_get ( void ) 63 | { 64 | return g_atomic_pointer_get(&layout_list); 65 | } 66 | -------------------------------------------------------------------------------- /src/gui/taskbarpager.h: -------------------------------------------------------------------------------- 1 | #ifndef __TASKBARDESK_H__ 2 | #define __TASKBARDESK_H__ 3 | 4 | #include "flowitem.h" 5 | #include "workspace.h" 6 | #include "taskbar.h" 7 | 8 | #define TASKBAR_PAGER_TYPE (taskbar_pager_get_type()) 9 | #define TASKBAR_PAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TASKBAR_PAGER_TYPE, TaskbarPager)) 10 | #define TASKBAR_PAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TASKBAR_PAGER_TYPE, TaskbarPagerClass)) 11 | #define IS_TASKBAR_PAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TASKBAR_PAGER_TYPE)) 12 | #define IS_TASKBAR_PAGERCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TASKBAR_PAGER_TYPE)) 13 | 14 | typedef struct _TaskbarPager TaskbarPager; 15 | typedef struct _TaskbarPagerClass TaskbarPagerClass; 16 | 17 | struct _TaskbarPager 18 | { 19 | FlowItem item; 20 | }; 21 | 22 | struct _TaskbarPagerClass 23 | { 24 | FlowItemClass parent_class; 25 | }; 26 | 27 | typedef struct _TaskbarPagerPrivate TaskbarPagerPrivate; 28 | 29 | struct _TaskbarPagerPrivate 30 | { 31 | GtkWidget *button; 32 | GtkWidget *grid; 33 | GtkWidget *shell; 34 | GtkWidget *taskbar; 35 | workspace_t *ws; 36 | gboolean invalid; 37 | gboolean single; 38 | GList *holds; 39 | }; 40 | 41 | GType taskbar_pager_get_type ( void ); 42 | 43 | GtkWidget *taskbar_pager_new( workspace_t *ws, GtkWidget *taskbar ); 44 | GtkWidget *taskbar_pager_get_taskbar ( GtkWidget *, window_t *, gboolean ); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /doc/sfwbar-bsdctl.1: -------------------------------------------------------------------------------- 1 | .\" Man page generated from reStructuredText. 2 | . 3 | . 4 | .nr rst2man-indent-level 0 5 | . 6 | .de1 rstReportMargin 7 | \\$1 \\n[an-margin] 8 | level \\n[rst2man-indent-level] 9 | level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] 10 | - 11 | \\n[rst2man-indent0] 12 | \\n[rst2man-indent1] 13 | \\n[rst2man-indent2] 14 | .. 15 | .de1 INDENT 16 | .\" .rstReportMargin pre: 17 | . RS \\$1 18 | . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] 19 | . nr rst2man-indent-level +1 20 | .\" .rstReportMargin post: 21 | .. 22 | .de UNINDENT 23 | . RE 24 | .\" indent \\n[an-margin] 25 | .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] 26 | .nr rst2man-indent-level -1 27 | .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] 28 | .in \\n[rst2man-indent\\n[rst2man-indent-level]]u 29 | .. 30 | .TH "SFWBAR-BSDCTL" 1 "" "" "" 31 | .SH NAME 32 | sfwbar-bsdctl \- Sfwbar BSD sysctl module 33 | .sp 34 | Filename: bsdctl.so 35 | .sp 36 | Requires: BSD libc 37 | .SH SYNOPSIS 38 | .sp 39 | The BSDCtl module provides an interface to query BSD sysctl values 40 | .SH EXPRESSION FUNCTIONS 41 | .SS BSDCtl(Query) 42 | .sp 43 | function BSDCtl queries the value of a sysctl variable. It\(aqs equivalent to 44 | calling sysctl program on BSD system. Please note that you can only query 45 | individual nodes rather than groups. 46 | .SH ACTIONS 47 | .sp 48 | None 49 | .SH TRIGGERS 50 | .sp 51 | None 52 | .SH COPYRIGHT 53 | GPLv3+ 54 | .\" Generated by docutils manpage writer. 55 | . 56 | -------------------------------------------------------------------------------- /icons/weather/clearsky_day.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/sfwbar-idleinhibit.rst: -------------------------------------------------------------------------------- 1 | sfwbar-idleinhibit 2 | ################## 3 | 4 | ########################### 5 | Sfwbar IdleInhibitor module 6 | ########################### 7 | 8 | :Copyright: GPLv3+ 9 | :Manual section: 1 10 | 11 | Filename: idleinhibit.so 12 | 13 | Requires: none 14 | 15 | SYNOPSIS 16 | ======== 17 | 18 | The IdleInhibit module, allows attaching idle inhibitor to any widget in the 19 | taskbar. If an idle inhibitor is active on a visible widget, it will prevent 20 | the compositor to going into an idle state (i.e. blanking a screen, 21 | going into a suspend mode or activating a screensaver) 22 | 23 | Expression Functions 24 | ==================== 25 | 26 | IdleInhibitState() 27 | ------------------------ 28 | 29 | Query an idle inhibitor state on a calling widget. It return a string with 30 | possible values of "On", if an idle inhibitor is set on the widget or "Off" 31 | if it isn't. If the function is called from an expression which isn't attached 32 | to a widget, the returned value will be "Off". 33 | 34 | Actions 35 | ======= 36 | 37 | SetIdleInhibitor Command 38 | ----------------------------- 39 | 40 | Set idle inhibitor state for a widget. The possible command values are: 41 | 42 | "On" 43 | turn on an idle inhibitor 44 | "Off" 45 | turn off an idle inhibitor 46 | "Toggle" 47 | toggle the state of an idle inhibitor 48 | 49 | Triggers 50 | ======== 51 | 52 | The module defines one trigger "IdleInhibitor" which is emitted whenever the 53 | state of any idle inhibitor changes. 54 | -------------------------------------------------------------------------------- /packaging/freebsd/Makefile: -------------------------------------------------------------------------------- 1 | PORTNAME= sfwbar 2 | DISTVERSIONPREFIX= v 3 | DISTVERSION= 1.0_beta13 4 | CATEGORIES= x11 wayland 5 | 6 | MAINTAINER= tino.engel@mail.de 7 | COMMENT= Flexible taskbar application for wayland compositors 8 | WWW= https://github.com/LBCrion/sfwbar 9 | 10 | LICENSE= GPLv3 11 | LICENSE_FILE= ${WRKSRC}/LICENSE 12 | 13 | BUILD_DEPENDS= wayland-protocols>0:graphics/wayland-protocols 14 | LIB_DEPENDS= libgtk-layer-shell.so:x11-toolkits/gtk-layer-shell \ 15 | libwayland-client.so:graphics/wayland \ 16 | libjson-c.so:devel/json-c 17 | 18 | USES= gnome meson pkgconfig 19 | USE_GNOME= cairo gdkpixbuf2 gtk30 20 | 21 | USE_GITHUB= yes 22 | GH_ACCOUNT= LBCrion 23 | 24 | MESON_ARGS= -Dbsdctl=enabled -Dnetwork=enabled -Dbluez=enabled -Didleinhibit=enabled 25 | 26 | OPTIONS_DEFINE= MPD PULSEAUDIO XKB ALSA 27 | OPTIONS_DEFAULT= MPD PULSEAUDIO XKB ALSA 28 | OPTIONS_SUB= yes 29 | 30 | MPD_DESC= Music player daemon control 31 | MPD_LIB_DEPENDS= libmpdclient.so:audio/libmpdclient 32 | MPD_MESON_ENABLED= mpd 33 | 34 | PULSEAUDIO_DESC= Pulse audio volume control 35 | PULSEAUDIO_LIB_DEPENDS= libpulse.so:audio/pulseaudio 36 | PULSEAUDIO_MESON_ENABLED= pulse 37 | 38 | XKB_DESC= XkbCommon keyboard layout conversion support 39 | XKB_LIB_DEPENDS= libxkbregistry.so:x11/libxkbcommon 40 | XKB_MESON_ENABLED= xkb 41 | 42 | ALSA_DESC= ALSA audio volume control 43 | ALSA_LIB_DEPENDS= libasound.so:audio/alsa-lib 44 | ALSA_MESON_ENABLED= alsa 45 | 46 | SUB_FILES= pkg-message 47 | 48 | .include 49 | -------------------------------------------------------------------------------- /src/gui/taskbarpopup.h: -------------------------------------------------------------------------------- 1 | #ifndef __TASKBARPOPUP_H__ 2 | #define __TASKBARPOPUP_H__ 3 | 4 | #include "flowitem.h" 5 | #include "taskbar.h" 6 | 7 | #define TASKBAR_POPUP_TYPE (taskbar_popup_get_type()) 8 | #define TASKBAR_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TASKBAR_POPUP_TYPE, TaskbarPopup)) 9 | #define TASKBAR_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TASKBAR_POPUP_TYPE, TaskbarPopupClass)) 10 | #define IS_TASKBAR_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TASKBAR_POPUP_TYPE)) 11 | #define IS_TASKBAR_POPUPCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TASKBAR_POPUP_TYPE)) 12 | 13 | typedef struct _TaskbarPopup TaskbarPopup; 14 | typedef struct _TaskbarPopupClass TaskbarPopupClass; 15 | 16 | struct _TaskbarPopup 17 | { 18 | FlowItem item; 19 | }; 20 | 21 | struct _TaskbarPopupClass 22 | { 23 | FlowItemClass parent_class; 24 | }; 25 | 26 | typedef struct _TaskbarPopupPrivate TaskbarPopupPrivate; 27 | 28 | struct _TaskbarPopupPrivate 29 | { 30 | GtkWidget *icon; 31 | GtkWidget *label; 32 | GtkWidget *button; 33 | GtkWidget *shell; 34 | GtkWidget *tgroup; 35 | GtkWidget *popover; 36 | gchar *appid; 37 | gboolean invalid; 38 | gboolean single; 39 | }; 40 | 41 | GType taskbar_popup_get_type ( void ); 42 | 43 | GtkWidget *taskbar_popup_new( const gchar *appid, GtkWidget *taskbar ); 44 | void taskbar_popup_pop_child ( GtkWidget *self, GtkWidget *child ); 45 | GtkWidget *taskbar_popup_get_taskbar ( GtkWidget *, window_t *, gboolean ); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the "main" branch 8 | push: 9 | branches: [ "main" ] 10 | pull_request: 11 | branches: [ "main" ] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-24.04 22 | 23 | # Steps represent a sequence of tasks that will be executed as part of the job 24 | steps: 25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 26 | - uses: actions/checkout@v3 27 | 28 | # Runs a set of commands using the runners shell 29 | - name: Run a multi-line script 30 | run: | 31 | sudo apt-get update 32 | sudo apt-get -y install libgtk-3-dev meson libgtk-layer-shell-dev libjson-c-dev libmpdclient-dev libpulse-dev bluez libbluetooth-dev libasound2-dev libxkbregistry-dev wayland-protocols gettext 33 | meson setup build --werror -Dpulse=enabled -Dmpd=enabled -Dnetwork=enabled -Dalsa=enabled -Dbluez=enabled -Dxkb=enabled -Didleinhibit=enabled 34 | ninja -C build 35 | DESTDIR=./install ninja -C build install 36 | -------------------------------------------------------------------------------- /src/gui/filter.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2025- sfwbar maintainers 4 | */ 5 | 6 | #include "gui/bar.h" 7 | #include "gui/basewidget.h" 8 | #include "gui/filter.h" 9 | 10 | static GEnumValue filter_enum[] = { 11 | { 0, "none", "none" }, 12 | { FILTER_FLOATING, "floating", "floating" }, 13 | { FILTER_MINIMIZED, "minimized", "minimized" }, 14 | { FILTER_OUTPUT, "output", "output" }, 15 | { FILTER_WORKSPACE, "workspace", "workspace" }, 16 | { 0, NULL, NULL }, 17 | }; 18 | 19 | GType filter_type; 20 | 21 | GType filter_type_get ( void ) 22 | { 23 | if(!filter_type) 24 | filter_type = g_enum_register_static("window_filter", filter_enum); 25 | 26 | return filter_type; 27 | } 28 | 29 | gboolean filter_window_check ( GtkWidget *parent, window_t *win ) 30 | { 31 | gint filter; 32 | 33 | g_return_val_if_fail(GTK_IS_WIDGET(parent), FALSE); 34 | g_return_val_if_fail(win, FALSE); 35 | 36 | g_object_get(G_OBJECT(parent), "filter", &filter, NULL); 37 | 38 | if(filter & FILTER_FLOATING && !win->floating) 39 | return FALSE; 40 | if(filter & FILTER_MINIMIZED && !(win->state & WS_MINIMIZED)) 41 | return FALSE; 42 | if(filter & FILTER_OUTPUT && win->outputs && !g_list_find_custom( 43 | win->outputs, bar_get_output(parent), (GCompareFunc)g_strcmp0)) 44 | return FALSE; 45 | if(filter & FILTER_WORKSPACE && win->workspace && 46 | win->workspace->id != workspace_get_active(parent)) 47 | return FALSE; 48 | return !wintree_is_filtered(win); 49 | } 50 | -------------------------------------------------------------------------------- /src/gui/taskbarshell.h: -------------------------------------------------------------------------------- 1 | #ifndef __TASKBARSHELL_H__ 2 | #define __TASKBARSHELL_H__ 3 | 4 | #include "taskbar.h" 5 | 6 | #define TASKBAR_SHELL_TYPE (taskbar_shell_get_type()) 7 | #define TASKBAR_SHELL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TASKBAR_SHELL_TYPE, TaskbarShell)) 8 | #define TASKBAR_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TASKBAR_SHELL_TYPE, TaskbarShellClass)) 9 | #define IS_TASKBAR_SHELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TASKBAR_SHELL_TYPE)) 10 | #define IS_TASKBARSHELLCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TASKBAR_SHELL_TYPE)) 11 | 12 | typedef struct _TaskbarShell TaskbarShell; 13 | typedef struct _TaskbarShellClass TaskbarShellClass; 14 | 15 | extern GEnumValue taskbar_shell_filter[]; 16 | 17 | struct _TaskbarShell 18 | { 19 | Taskbar item; 20 | }; 21 | 22 | struct _TaskbarShellClass 23 | { 24 | TaskbarClass parent_class; 25 | }; 26 | 27 | typedef struct _TaskbarShellPrivate TaskbarShellPrivate; 28 | 29 | struct _TaskbarShellPrivate 30 | { 31 | GtkWidget *(*get_taskbar)(GtkWidget *, window_t *, gboolean); 32 | gboolean icons, labels, sort, floating_filter; 33 | gint rows, cols, filter, title_width, primary_axis, api_id; 34 | gboolean tooltips; 35 | guint timer_h; 36 | GBytes *style; 37 | gchar *css; 38 | }; 39 | 40 | GType taskbar_shell_get_type ( void ); 41 | 42 | void taskbar_shell_init_child ( GtkWidget *self, GtkWidget *child ); 43 | void taskbar_shell_invalidate ( GtkWidget *self ); 44 | gboolean taskbar_shell_check_filter ( GtkWidget *self, window_t *win ); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /doc/sfwbar-xkbmap.1: -------------------------------------------------------------------------------- 1 | .\" Man page generated from reStructuredText. 2 | . 3 | . 4 | .nr rst2man-indent-level 0 5 | . 6 | .de1 rstReportMargin 7 | \\$1 \\n[an-margin] 8 | level \\n[rst2man-indent-level] 9 | level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] 10 | - 11 | \\n[rst2man-indent0] 12 | \\n[rst2man-indent1] 13 | \\n[rst2man-indent2] 14 | .. 15 | .de1 INDENT 16 | .\" .rstReportMargin pre: 17 | . RS \\$1 18 | . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] 19 | . nr rst2man-indent-level +1 20 | .\" .rstReportMargin post: 21 | .. 22 | .de UNINDENT 23 | . RE 24 | .\" indent \\n[an-margin] 25 | .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] 26 | .nr rst2man-indent-level -1 27 | .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] 28 | .in \\n[rst2man-indent\\n[rst2man-indent-level]]u 29 | .. 30 | .TH "SFWBAR-XKBMAP" 1 "" "" "" 31 | .SH NAME 32 | sfwbar-xkbmap \- Sfwbar xkbcommon layout module 33 | .sp 34 | Filename: xkbmap.so 35 | .sp 36 | Requires: libxkbregistry 37 | .SH SYNOPSIS 38 | .sp 39 | The XkbMap module provides an interface to convert between keyboard layout 40 | types. 41 | .SH EXPRESSION FUNCTIONS 42 | .SS XkbMap(Name,SourceType,DestType) 43 | .sp 44 | Function XkbMap converts between various name types for an XkbLayout. The 45 | function converts layout name Name from SourceType to DestType, the supported 46 | types are: \(dqdescription\(dq,\(dqname\(dq,\(dqvariant\(dq and \(dqbrief\(dq. 47 | .SH ACTIONS 48 | .sp 49 | None 50 | .SH TRIGGERS 51 | .sp 52 | None 53 | .SH COPYRIGHT 54 | GPLv3+ 55 | .\" Generated by docutils manpage writer. 56 | . 57 | -------------------------------------------------------------------------------- /src/gui/taskbar.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2020- sfwbar maintainers 4 | */ 5 | 6 | #include "flowgrid.h" 7 | #include "taskbaritem.h" 8 | #include "taskbarpopup.h" 9 | #include "taskbarpager.h" 10 | #include "taskbarshell.h" 11 | #include "taskbar.h" 12 | #include "wintree.h" 13 | #include "config/config.h" 14 | #include "vm/vm.h" 15 | 16 | G_DEFINE_TYPE_WITH_CODE (Taskbar, taskbar, FLOW_GRID_TYPE, 17 | G_ADD_PRIVATE (Taskbar)) 18 | 19 | GtkWidget *taskbar_get_taskbar ( GtkWidget *shell, window_t *win, 20 | gboolean create ) 21 | { 22 | return shell; 23 | } 24 | 25 | static void taskbar_class_init ( TaskbarClass *kclass ) 26 | { 27 | BASE_WIDGET_CLASS(kclass)->action_exec = NULL; 28 | } 29 | 30 | static void taskbar_init ( Taskbar *self ) 31 | { 32 | g_object_set(G_OBJECT(self), "action", base_widget_attachment_new_array( 33 | parser_function_call_build("taskbaritemdefault"), 1, 0), NULL); 34 | flow_grid_invalidate(GTK_WIDGET(self)); 35 | } 36 | 37 | GtkWidget *taskbar_new ( GtkWidget *parent ) 38 | { 39 | GtkWidget *self; 40 | TaskbarPrivate *priv; 41 | 42 | self = GTK_WIDGET(g_object_new(taskbar_get_type(), NULL)); 43 | priv = taskbar_get_instance_private(TASKBAR(self)); 44 | priv->parent = parent; 45 | 46 | return self; 47 | } 48 | 49 | GtkWidget *taskbar_get_parent ( GtkWidget *self ) 50 | { 51 | TaskbarPrivate *priv; 52 | 53 | g_return_val_if_fail(IS_TASKBAR(self), NULL); 54 | priv = taskbar_get_instance_private(TASKBAR(self)); 55 | 56 | return priv->parent; 57 | } 58 | -------------------------------------------------------------------------------- /icons/sfwbar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /icons/misc/missing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/util/datalist.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2025- sfwbar maintainers 4 | */ 5 | 6 | #include "util/datalist.h" 7 | 8 | datalist_t *datalist_new ( void ) 9 | { 10 | datalist_t *dlist; 11 | 12 | dlist = g_malloc0(sizeof(datalist_t)); 13 | g_datalist_init(&dlist->data); 14 | dlist->refcount = 1; 15 | 16 | return dlist; 17 | } 18 | 19 | datalist_t *datalist_ref ( datalist_t *dlist ) 20 | { 21 | g_mutex_lock(&dlist->mutex); 22 | dlist->refcount++; 23 | g_mutex_unlock(&dlist->mutex); 24 | 25 | return dlist; 26 | } 27 | 28 | void datalist_unref ( datalist_t *dlist ) 29 | { 30 | gint count; 31 | 32 | g_mutex_lock(&dlist->mutex); 33 | dlist->refcount--; 34 | count = dlist->refcount; 35 | g_mutex_unlock(&dlist->mutex); 36 | if(!count) 37 | { 38 | /* all refs are dropped, don't care abount concurrent access */ 39 | g_datalist_clear(&dlist->data); 40 | g_free(dlist); 41 | } 42 | } 43 | 44 | gpointer datalist_get ( datalist_t *dlist, GQuark id ) 45 | { 46 | gpointer result; 47 | 48 | g_mutex_lock(&dlist->mutex); 49 | result = g_datalist_id_get_data(&dlist->data, id); 50 | g_mutex_unlock(&dlist->mutex); 51 | 52 | return result; 53 | } 54 | 55 | void datalist_set ( datalist_t *dlist, GQuark id, gpointer d ) 56 | { 57 | g_mutex_lock(&dlist->mutex); 58 | g_datalist_id_set_data(&dlist->data, id, d); 59 | g_mutex_unlock(&dlist->mutex); 60 | } 61 | 62 | void datalist_foreach ( datalist_t *dlist, GDataForeachFunc func, void *d ) 63 | { 64 | g_mutex_lock(&dlist->mutex); 65 | g_datalist_foreach(&dlist->data, func, d); 66 | g_mutex_unlock(&dlist->mutex); 67 | } 68 | -------------------------------------------------------------------------------- /src/gui/scaleimage.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCALEIMAGE_H__ 2 | #define __SCALEIMAGE_H__ 3 | 4 | #include 5 | 6 | #define SCALE_IMAGE_TYPE (scale_image_get_type()) 7 | #define SCALE_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SCALE_IMAGE_TYPE, ScaleImage)) 8 | #define SCALE_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SCALE_IMAGE_TYPE, ScaleImageClass)) 9 | #define IS_SCALE_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SCALE_IMAGE_TYPE)) 10 | #define IS_SCALE_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SCALE_IMAGE_TYPE)) 11 | 12 | typedef struct _ScaleImage ScaleImage; 13 | typedef struct _ScaleImageClass ScaleImageClass; 14 | 15 | struct _ScaleImage 16 | { 17 | GtkImage parent_class; 18 | }; 19 | 20 | struct _ScaleImageClass 21 | { 22 | GtkImageClass parent_class; 23 | }; 24 | 25 | typedef struct _ScaleImagePrivate ScaleImagePrivate; 26 | 27 | struct _ScaleImagePrivate 28 | { 29 | gint ftype; 30 | gint width, height; 31 | gint radius, shadow_dx, shadow_dy; 32 | GdkRGBA *color; 33 | GdkRGBA *shadow_color; 34 | gboolean shadow_clip; 35 | gboolean fallback; 36 | gboolean symbolic; 37 | gboolean symbolic_pref; 38 | gchar *file; 39 | gchar *extra; 40 | gchar *fname; 41 | GtkIconTheme *theme; 42 | GdkPixbuf *pixbuf; 43 | cairo_surface_t *cs, *shadow; 44 | }; 45 | 46 | enum { 47 | SI_NONE, 48 | SI_ICON, 49 | SI_FILE, 50 | SI_BUFF, 51 | SI_DATA 52 | }; 53 | 54 | GType scale_image_get_type ( void ); 55 | gboolean scale_image_set_image ( GtkWidget *, const gchar *, gchar *); 56 | GtkWidget *scale_image_new(); 57 | int scale_image_update ( GtkWidget *widget ); 58 | gboolean scale_image_cache_insert ( gchar *name, GdkPixbuf *pb ); 59 | gboolean scale_image_cache_remove ( gchar *name ); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /doc/sfwbar-idle.1: -------------------------------------------------------------------------------- 1 | .\" Man page generated from reStructuredText. 2 | . 3 | . 4 | .nr rst2man-indent-level 0 5 | . 6 | .de1 rstReportMargin 7 | \\$1 \\n[an-margin] 8 | level \\n[rst2man-indent-level] 9 | level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] 10 | - 11 | \\n[rst2man-indent0] 12 | \\n[rst2man-indent1] 13 | \\n[rst2man-indent2] 14 | .. 15 | .de1 INDENT 16 | .\" .rstReportMargin pre: 17 | . RS \\$1 18 | . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] 19 | . nr rst2man-indent-level +1 20 | .\" .rstReportMargin post: 21 | .. 22 | .de UNINDENT 23 | . RE 24 | .\" indent \\n[an-margin] 25 | .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] 26 | .nr rst2man-indent-level -1 27 | .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] 28 | .in \\n[rst2man-indent\\n[rst2man-indent-level]]u 29 | .. 30 | .TH "SFWBAR-IDLE" "1" "" "" 31 | .SH NAME 32 | sfwbar-idle \- Sfwbar Idle notifier module 33 | .sp 34 | Filename: idle.so 35 | .sp 36 | Requires: none 37 | .SH SYNOPSIS 38 | .sp 39 | The idle notifier module, provides support for idle triggers, i.e. triggers 40 | that are emitted if the user has been idle for a specified period of time. 41 | .SH EXPRESSION FUNCTIONS 42 | .sp 43 | None. 44 | .SH ACTIONS 45 | .SS IdleTimeout Trigger, Timeout 46 | .sp 47 | Create a new trigger with a name Trigger that will be emitted after Timeout 48 | seconds of idleness. I.e. \fIIdleTimeout \(dqtimeout1\(dq, \(dq10\(dq\fP\&. A trigger can be 49 | removed by invoking this action again with a Timeout value of zero. 50 | .SH TRIGGERS 51 | .sp 52 | The idle module defines trigger \fIresumed\fP by default. This trigger is emitted 53 | on the first user interaction after a timeout. Timeout triggers are defined 54 | using the \fIIdleTimeout\fP action. 55 | .SH COPYRIGHT 56 | GPLv3+ 57 | .\" Generated by docutils manpage writer. 58 | . 59 | -------------------------------------------------------------------------------- /icons/weather/lightrain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /config/backlight.source: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | module("dbus") 4 | module("bsdctl") 5 | 6 | Var BacklightSrc, BacklightMax, BacklightName; 7 | 8 | Set BacklightPresent = (ident(DbusCall) & BacklightSrc!='') | 9 | (ident(BSDCtl) & BSDCtl("hw.acpi.video.lcd0.brightness")!=''); 10 | 11 | Set BacklightPct = Val(Read(BacklightSrc))/BacklightMax; 12 | 13 | Function BacklightInit() { 14 | Var base = "/sys/class/backlight"; 15 | Var dirs = ls(base); 16 | Var i = 0; 17 | 18 | BacklightSrc='' 19 | while i 0 { 41 | DBusCall(SessionInterface, "SetBrightness", "(ssu)", 42 | ["backlight", BacklightName, 43 | BacklightMax * Min(1, Max(0.3, pct ))]) 44 | EmitTrigger("backlight") 45 | } 46 | } 47 | 48 | PopUp("BacklightPopup") { 49 | style = "backlight_popup" 50 | image { 51 | value = "display-brightness" 52 | } 53 | scale { 54 | style = 'volume_scale' 55 | value = Val(Read(BacklightSrc))/BacklightMax 56 | trigger = "backlight" 57 | action[LeftClick] = SetBacklight(GtkEvent("dir")) 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/gui/scale.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2022- sfwbar maintainers 4 | */ 5 | 6 | #include "basewidget.h" 7 | #include "scale.h" 8 | 9 | G_DEFINE_TYPE_WITH_CODE (Scale, scale, BASE_WIDGET_TYPE, G_ADD_PRIVATE (Scale)) 10 | 11 | static void scale_update_value ( GtkWidget *self ) 12 | { 13 | ScalePrivate *priv; 14 | gchar *value; 15 | 16 | g_return_if_fail(IS_SCALE(self)); 17 | priv = scale_get_instance_private(SCALE(self)); 18 | 19 | value = base_widget_get_value(self); 20 | 21 | if(!g_strrstr(value, "nan")) 22 | gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(priv->scale), 23 | g_ascii_strtod(value, NULL)); 24 | } 25 | 26 | static void scale_style_updated ( GtkWidget *widget, GtkWidget *self ) 27 | { 28 | ScalePrivate *priv; 29 | gint dir; 30 | 31 | priv = scale_get_instance_private(SCALE(self)); 32 | gtk_widget_style_get(priv->scale, "direction", &dir, NULL); 33 | if(priv->dir == dir) 34 | return; 35 | priv->dir = dir; 36 | gtk_orientable_set_orientation(GTK_ORIENTABLE(priv->scale), 37 | (dir==GTK_POS_LEFT || dir==GTK_POS_RIGHT)? 38 | GTK_ORIENTATION_HORIZONTAL:GTK_ORIENTATION_VERTICAL); 39 | gtk_progress_bar_set_inverted(GTK_PROGRESS_BAR(priv->scale), 40 | ( priv->dir==GTK_POS_TOP || priv->dir==GTK_POS_LEFT )); 41 | } 42 | 43 | static void scale_class_init ( ScaleClass *kclass ) 44 | { 45 | BASE_WIDGET_CLASS(kclass)->update_value = scale_update_value; 46 | } 47 | 48 | static void scale_init ( Scale *self ) 49 | { 50 | ScalePrivate *priv; 51 | 52 | priv = scale_get_instance_private(SCALE(self)); 53 | 54 | priv->scale = gtk_progress_bar_new(); 55 | gtk_container_add(GTK_CONTAINER(self), priv->scale); 56 | g_signal_connect(G_OBJECT(priv->scale), "style_updated", 57 | (GCallback)scale_style_updated, self); 58 | } 59 | -------------------------------------------------------------------------------- /icons/misc/lan.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 11 | 13 | 15 | 17 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/sfwbar-appmenu.1: -------------------------------------------------------------------------------- 1 | .\" Man page generated from reStructuredText. 2 | . 3 | . 4 | .nr rst2man-indent-level 0 5 | . 6 | .de1 rstReportMargin 7 | \\$1 \\n[an-margin] 8 | level \\n[rst2man-indent-level] 9 | level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] 10 | - 11 | \\n[rst2man-indent0] 12 | \\n[rst2man-indent1] 13 | \\n[rst2man-indent2] 14 | .. 15 | .de1 INDENT 16 | .\" .rstReportMargin pre: 17 | . RS \\$1 18 | . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] 19 | . nr rst2man-indent-level +1 20 | .\" .rstReportMargin post: 21 | .. 22 | .de UNINDENT 23 | . RE 24 | .\" indent \\n[an-margin] 25 | .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] 26 | .nr rst2man-indent-level -1 27 | .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] 28 | .in \\n[rst2man-indent\\n[rst2man-indent-level]]u 29 | .. 30 | .TH "SFWBAR-APPMENU" "1" "" "" 31 | .SH NAME 32 | sfwbar-appmenu \- Sfwbar Application menu module 33 | .sp 34 | Filename: appmenu.so 35 | .sp 36 | Requires: none 37 | .SH SYNOPSIS 38 | .sp 39 | The application menu module creates and maintains the applications menu object. 40 | This module has no triggers, actions or expression functions. The application 41 | menu is named \fIapp_menu_system\fP\&. 42 | .SH ACTIONS 43 | .SS AppMenuFilter Filename 44 | .sp 45 | Don\(aqt add a program with a .desktop file matching Filename. The Filename should 46 | include the .desktop extension. 47 | .SS AppMenuItemTop Title, Command 48 | .sp 49 | Add a custom item to the top of the application menu. The Title parameter is 50 | the name of the item (it can include a \(aq%\(aq separated icon name). The command 51 | is the command to execute upon the item activation. 52 | .SS AppMenuItemBottom Title, Command 53 | .sp 54 | Add a custom item to the bottom of the application menu. The parameters are 55 | the same as for AppMenuItemTop action. 56 | .SH COPYRIGHT 57 | GPLv3+ 58 | .\" Generated by docutils manpage writer. 59 | . 60 | -------------------------------------------------------------------------------- /icons/misc/music-player.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /icons/misc/music-player-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /icons/weather/rain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /icons/weather/fog.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/util/file.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2020- sfwbar maintainers 4 | */ 5 | 6 | #include 7 | #include 8 | #include "meson.h" 9 | 10 | gchar *confname; 11 | gchar *sockname; 12 | 13 | gboolean file_test_read ( gchar *filename ) 14 | { 15 | if( !filename || !g_file_test(filename, G_FILE_TEST_EXISTS) ) 16 | return FALSE; 17 | if( access(filename, R_OK) == -1 ) 18 | return FALSE; 19 | return TRUE; 20 | } 21 | 22 | /* get xdg config file name, first try user xdg config directory, 23 | * if file doesn't exist, try system xdg data dirs */ 24 | gchar *get_xdg_config_file ( gchar *fname, gchar *extra ) 25 | { 26 | gchar *full, *dir; 27 | const gchar * const *xdg_data; 28 | gint i; 29 | 30 | if(fname && *fname == '/') 31 | { 32 | if(file_test_read(fname)) 33 | return g_strdup(fname); 34 | else 35 | return NULL; 36 | } 37 | 38 | if(confname) 39 | { 40 | dir = g_path_get_dirname(confname); 41 | full = g_build_filename ( dir, fname, NULL ); 42 | g_free(dir); 43 | if( file_test_read(full) ) 44 | return full; 45 | g_free(full); 46 | } 47 | 48 | full = g_build_filename ( g_get_user_config_dir(), "sfwbar", fname, NULL ); 49 | if( file_test_read(full) ) 50 | return full; 51 | g_free(full); 52 | 53 | xdg_data = g_get_system_data_dirs(); 54 | for(i=0;xdg_data[i];i++) 55 | { 56 | full = g_build_filename ( xdg_data[i], "sfwbar", fname, NULL ); 57 | if( file_test_read(full) ) 58 | return full; 59 | g_free(full); 60 | } 61 | 62 | full = g_build_filename( SYSTEM_CONF_DIR, fname, NULL); 63 | if( file_test_read(full) ) 64 | return full; 65 | g_free(full); 66 | 67 | if(!extra) 68 | return NULL; 69 | full = g_build_filename ( extra, fname, NULL ); 70 | if( file_test_read(full) ) 71 | return full; 72 | g_free(full); 73 | 74 | return NULL; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/gui/tray.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2022- sfwbar maintainers 4 | */ 5 | 6 | #include "trayitem.h" 7 | #include "tray.h" 8 | 9 | G_DEFINE_TYPE_WITH_CODE (Tray, tray, FLOW_GRID_TYPE, G_ADD_PRIVATE (Tray)) 10 | 11 | static void tray_destroy ( GtkWidget *self ) 12 | { 13 | TrayPrivate *priv; 14 | 15 | g_return_if_fail(IS_TRAY(self)); 16 | priv = tray_get_instance_private(TRAY(self)); 17 | if(priv->timer_h) 18 | { 19 | g_source_remove(priv->timer_h); 20 | priv->timer_h = 0; 21 | } 22 | GTK_WIDGET_CLASS(tray_parent_class)->destroy(self); 23 | } 24 | 25 | static void tray_class_init ( TrayClass *kclass ) 26 | { 27 | GTK_WIDGET_CLASS(kclass)->destroy = tray_destroy; 28 | BASE_WIDGET_CLASS(kclass)->action_exec = NULL; 29 | sni_init(); 30 | } 31 | 32 | static void tray_invalidate_item ( sni_item_t *sni, GtkWidget *self ) 33 | { 34 | flow_item_invalidate(flow_grid_find_child(self, sni)); 35 | } 36 | 37 | static void tray_destroy_item ( sni_item_t *sni, GtkWidget *self ) 38 | { 39 | flow_grid_delete_child(self, sni); 40 | } 41 | 42 | static sni_listener_t tray_sni_listener = { 43 | .sni_new = (void (*)(sni_item_t *, void *))tray_item_new, 44 | .sni_invalidate = (void (*)(sni_item_t *, void *))tray_invalidate_item, 45 | .sni_destroy = (void (*)(sni_item_t *, void *))tray_destroy_item, 46 | }; 47 | 48 | static void tray_init ( Tray *self ) 49 | { 50 | TrayPrivate *priv; 51 | 52 | sni_listener_register(&tray_sni_listener, self); 53 | priv = tray_get_instance_private(TRAY(self)); 54 | priv->timer_h = g_timeout_add(100, (GSourceFunc)flow_grid_update, self); 55 | gtk_grid_set_column_homogeneous( 56 | GTK_GRID(base_widget_get_child(GTK_WIDGET(self))), FALSE); 57 | 58 | g_list_foreach(sni_item_get_list(), (GFunc)tray_item_new, self); 59 | } 60 | 61 | GtkWidget *tray_new ( void ) 62 | { 63 | return GTK_WIDGET(g_object_new(tray_get_type(), NULL)); 64 | } 65 | -------------------------------------------------------------------------------- /doc/sfwbar-network.rst: -------------------------------------------------------------------------------- 1 | sfwbar-network 2 | ############## 3 | 4 | ##################### 5 | Sfwbar Network module 6 | ##################### 7 | 8 | :Copyright: GPLv3+ 9 | :Manual section: 1 10 | 11 | Filename: network.so 12 | 13 | Requires: none 14 | 15 | SYNOPSIS 16 | ======== 17 | 18 | The network module tracks the state of the current network connection. 19 | 20 | Expression Functions 21 | ==================== 22 | 23 | NetInfo(Query[,Interface]) 24 | -------------------------- 25 | 26 | Function NetInfo queries the parameter of the connection on the network 27 | interface specified. If Interface is not specified, NetInfo will query the 28 | interface of the default gateway (if one exists). The queries supported are: 29 | 30 | "ip" 31 | IP address of the interface. 32 | "mask" 33 | Net mask of the interface. 34 | "cidr" 35 | Net mask in the CIDR notation. 36 | "gateway" 37 | The default gateway (not necessarily associated with the interface). 38 | "ip6" 39 | IPv6 IP address of the interface. 40 | "mask6" 41 | IPv6 netmask of the interfce. 42 | "gateway6" 43 | The default IPv6 gateway. 44 | "essid" 45 | ESSID of the wireless connection (if applicable for the interface). 46 | 47 | NetInfo returns a string value. 48 | 49 | NetStat(Query[,Interface]) 50 | -------------------------- 51 | 52 | Function NetStat queries statistics of the interface. If the interface 53 | isn't specified, it will be applied to the interface of the default gateway. 54 | The queries supported are: 55 | 56 | "rxrate" 57 | Receive data rate on the interface (in bps). 58 | "txrate" 59 | Transmit data rate on the interface (in bps). 60 | "signal" 61 | Signal strength of the wifi connection (if applicable). 62 | 63 | NetState returns a numeric value. 64 | 65 | 66 | Actions 67 | ======= 68 | None 69 | 70 | Triggers 71 | ======== 72 | The module defines one trigger "network" which is emitted whenever the interface 73 | data is changes (i.e. ip, netmask, default gateway, wifi essid). 74 | -------------------------------------------------------------------------------- /icons/misc/comp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 14 | 16 | 17 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/signal.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2023- sfwbar maintainers 4 | */ 5 | 6 | #include 7 | #include "trigger.h" 8 | 9 | static gint signal_counter[255]; 10 | static gint signal_flag; 11 | 12 | static void signal_handler ( gint sig ) 13 | { 14 | if(sigSIGRTMAX) 15 | return; 16 | 17 | g_atomic_int_inc(&signal_counter[sig-SIGRTMIN]); 18 | g_atomic_int_set(&signal_flag, 1); 19 | } 20 | 21 | static gboolean signal_source_prepare( GSource *source, gint *timeout) 22 | { 23 | *timeout = -1; 24 | return signal_flag; 25 | } 26 | 27 | static gboolean signal_source_check( GSource *source ) 28 | { 29 | return signal_flag; 30 | } 31 | 32 | static gboolean signal_source_dispatch( GSource *source, GSourceFunc cb, 33 | gpointer data) 34 | { 35 | gchar *trigger; 36 | gint sig; 37 | 38 | g_atomic_int_set(&signal_flag, 0); 39 | for(sig=SIGRTMIN; signame = g_strdup(name); 33 | g_mutex_lock(&func_mutex); 34 | g_hash_table_insert(vm_func_table, func->name, func); 35 | g_mutex_unlock(&func_mutex); 36 | 37 | return func; 38 | } 39 | 40 | void vm_func_add ( gchar *name, vm_func_t func, gboolean det, gboolean safe ) 41 | { 42 | vm_function_t *func_o; 43 | 44 | func_o = vm_func_lookup(name); 45 | 46 | func_o->ptr.function = func; 47 | func_o->flags |= (det? VM_FUNC_DETERMINISTIC : 0); 48 | func_o->flags |= (safe? VM_FUNC_THREADSAFE : 0); 49 | expr_dep_trigger(g_quark_from_string(name)); 50 | g_debug("function: registered '%s'", name); 51 | } 52 | 53 | void vm_func_add_user ( gchar *name, GBytes *code, guint8 arity ) 54 | { 55 | vm_function_t *func; 56 | 57 | func = vm_func_lookup(name); 58 | func->ptr.code = code; 59 | func->flags = VM_FUNC_USERDEFINED; 60 | func->arity = arity; 61 | expr_dep_trigger(g_quark_from_string(name)); 62 | g_debug("function: registered '%s'", name); 63 | } 64 | 65 | void vm_func_remove ( gchar *name ) 66 | { 67 | vm_function_t *func; 68 | 69 | g_mutex_lock(&func_mutex); 70 | func = g_hash_table_lookup(vm_func_table, name); 71 | g_mutex_unlock(&func_mutex); 72 | 73 | if(func) 74 | func->ptr.function = NULL; 75 | } 76 | -------------------------------------------------------------------------------- /icons/weather/lightsnow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /icons/weather/clearsky_polartwilight.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/vm/value.h: -------------------------------------------------------------------------------- 1 | #ifndef __VALUE_H__ 2 | #define __VALUE_H__ 3 | 4 | #include 5 | 6 | enum expr_type_t { 7 | EXPR_TYPE_NUMERIC, 8 | EXPR_TYPE_STRING, 9 | EXPR_TYPE_ARRAY, 10 | EXPR_TYPE_BOOLEAN, // Not in use 11 | EXPR_TYPE_NA 12 | }; 13 | 14 | typedef struct { 15 | guint8 type; 16 | union { 17 | gboolean boolean; 18 | gdouble numeric; 19 | gchar *string; 20 | GArray *array; 21 | } value; 22 | } value_t; 23 | 24 | extern const value_t value_na; 25 | 26 | #define value_new_string(v) \ 27 | ((value_t){.type=EXPR_TYPE_STRING, .value.string=(v)}) 28 | #define value_new_numeric(v) \ 29 | ((value_t){.type=EXPR_TYPE_NUMERIC, .value.numeric=(v)}) 30 | #define value_new_array(v) \ 31 | ((value_t){.type=EXPR_TYPE_ARRAY, .value.array=(v)}) 32 | #define value_new_na() (value_na) 33 | 34 | #define value_is_string(v) ((v).type == EXPR_TYPE_STRING) 35 | #define value_is_numeric(v) ((v).type == EXPR_TYPE_NUMERIC) 36 | #define value_is_na(v) ((v).type == EXPR_TYPE_NA) 37 | #define value_is_array(v) ((v).type == EXPR_TYPE_ARRAY) 38 | 39 | #define value_like_string(v) (value_is_string(v) || value_is_na(v)) 40 | #define value_like_numeric(v) (value_is_numeric(v) || value_is_na(v)) 41 | #define value_like_array(v) (value_is_array(v) || value_is_na(v)) 42 | 43 | #define value_get_string(v) \ 44 | ((value_is_string(v)&&v.value.string)?v.value.string:"") 45 | #define value_get_numeric(v) (value_is_numeric(v)?v.value.numeric:0) 46 | #define value_get_array(v) (value_is_array(v)?v.value.array:NULL) 47 | 48 | #define value_as_numeric(v) (value_like_numeric(v)? value_get_numeric(v) : \ 49 | (value_is_string(v)? g_ascii_strtod(v.value.string, NULL) : 0)) 50 | 51 | void value_free ( value_t ); 52 | void value_free_ptr ( value_t *v1 ); 53 | value_t value_dup ( value_t ); 54 | gboolean value_compare ( value_t v1, value_t v2 ); 55 | value_t value_array_concat ( value_t v1, value_t v2 ); 56 | gchar *value_array_to_string ( value_t value ); 57 | gchar *value_to_string ( value_t v1, gint prec ); 58 | value_t value_array_from_strv ( gchar **strv ); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/gui/flowitem.h: -------------------------------------------------------------------------------- 1 | #ifndef __FLOWITEM_H__ 2 | #define __FLOWITEM_H__ 3 | 4 | #include 5 | #include "basewidget.h" 6 | 7 | #define FLOW_ITEM_TYPE (flow_item_get_type()) 8 | #define FLOW_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FLOW_ITEM_TYPE, FlowItemClass)) 9 | #define FLOW_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FLOW_ITEM_TYPE, FlowItem)) 10 | #define IS_FLOW_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FLOW_ITEM_TYPE)) 11 | #define IS_FLOW_TEMCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FLOW_ITEM_TYPE)) 12 | #define FLOW_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FLOW_ITEM_TYPE, FlowItemClass)) 13 | 14 | typedef struct _FlowItem FlowItem; 15 | typedef struct _FlowItemClass FlowItemClass; 16 | 17 | struct _FlowItem 18 | { 19 | BaseWidget widget; 20 | }; 21 | 22 | struct _FlowItemClass 23 | { 24 | BaseWidgetClass parent_class; 25 | 26 | void (*update) ( GtkWidget *self ); 27 | void (*invalidate) ( GtkWidget *self ); 28 | void* (*get_source) ( GtkWidget *self ); 29 | gint (*compare) (GtkWidget *, GtkWidget *, GtkWidget *); 30 | void (*dnd_dest) ( GtkWidget *self, GtkWidget *src, gint x, gint y ); 31 | GCompareFunc comp_source; 32 | }; 33 | 34 | typedef struct _FlowItemPrivate FlowItemPrivate; 35 | 36 | struct _FlowItemPrivate 37 | { 38 | gboolean active; 39 | GBinding *store_binding; 40 | GtkWidget *parent; 41 | }; 42 | 43 | GType flow_item_get_type ( void ); 44 | 45 | void flow_item_update ( GtkWidget *self ); 46 | void flow_item_invalidate ( GtkWidget *self ); 47 | void *flow_item_get_source ( GtkWidget *self ); 48 | void flow_item_set_parent ( GtkWidget *self, GtkWidget *parent ); 49 | void flow_item_set_active ( GtkWidget *self, gboolean ); 50 | GtkWidget *flow_item_get_parent ( GtkWidget *self ); 51 | gboolean flow_item_get_active ( GtkWidget *self ); 52 | gint flow_item_compare ( GtkWidget *p1, GtkWidget *p2, GtkWidget *parent ); 53 | void flow_item_dnd_dest ( GtkWidget *self, GtkWidget *src, gint x, gint y ); 54 | gint flow_item_check_source ( GtkWidget *self, gconstpointer source ); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /icons/weather/snow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /doc/sfwbar-mpd.rst: -------------------------------------------------------------------------------- 1 | sfwbar-mpd 2 | ############ 3 | 4 | ################################# 5 | Sfwbar Music Player Daemon module 6 | ################################# 7 | 8 | :Copyright: GPLv3+ 9 | :Manual section: 1 10 | 11 | Filename: mpd.so 12 | 13 | Requires: libmpdclient 14 | 15 | SYNOPSIS 16 | ======== 17 | 18 | The Music Player Daemon module provides an interface to control an MPD server. 19 | 20 | Expression Functions 21 | ==================== 22 | 23 | Mpd(Query) 24 | ------------------------ 25 | 26 | Function Mpd queries the state of the MPD server. The function returns a string. 27 | the following queries are supported: 28 | 29 | "title" 30 | The title of current song. 31 | "track" 32 | Track number of the current song. 33 | "artist" 34 | Artist of the current song. 35 | "album" 36 | Album of the current song. 37 | "genre" 38 | Genre of the current song. 39 | "volume" 40 | Current playback volume. 41 | "repeat" 42 | Repeat flag of the current playlist: "1"/"0". 43 | "random" 44 | Random flag of the current playlist: "1"/"0". 45 | "queue_len" 46 | Length of the current playlist. 47 | "queue_pos" 48 | Number of the current song in the playlist. 49 | "elapsed" 50 | Elapsed time since the beginning of the song. 51 | "length" 52 | Length of the current song. 53 | "rate" 54 | Sample rate of the current song (in kbps). 55 | "state" 56 | State of the player: "play","pause","stop","unknown". 57 | 58 | Actions 59 | ======= 60 | 61 | MpdSetPassword "Password" 62 | ------------------------- 63 | 64 | Specify a password used to connect to the MPD server. 65 | 66 | MpdCommand "Command" 67 | -------------------- 68 | 69 | Send a command to the MPD server. The supported commands are: 70 | 71 | "play" 72 | Play the current song. 73 | "pause" 74 | Pause playback. 75 | "stop" 76 | Stop playback. 77 | "prev" 78 | Switch to the previous song in the playlist. 79 | "next" 80 | Switch to the next song in the playlist. 81 | 82 | Triggers 83 | ======== 84 | 85 | The module defines two triggers: 86 | 87 | "mpd" 88 | Emitted whenever the state of the MPD server changes. 89 | "mpd-progress" 90 | Emitted every second while player is in "play" state. 91 | -------------------------------------------------------------------------------- /icons/weather/heavyrain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /config/battery-svg.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("battery.source") 6 | 7 | Var pretty_icon = TRUE; 8 | 9 | Var Minus = ''; 11 | Var Plus = '' 13 | Var BatterySvg = ' 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 24 | 27 | @SIGN@ 28 | ' 29 | 30 | Function BatteryIcon() { 31 | If pretty_icon 32 | Return ReplaceAll(BatterySvg, 33 | '@GRADIENT_START@', Str(Max(0, 100 - Level)), 34 | '@GRADIENT_END@', Str(100 - Level), 35 | '@RED_LEVEL@', Str(Min(256, 512-5.12*Level)), 36 | '@BLUE_LEVEL@', Str(Min(256, 5.12*Level)), 37 | '@SIGN@', If(Discharging, Minus, Plus)); 38 | Else 39 | Return "battery-level-" + Str(Level/10,0) + "0" + 40 | If(Discharging, "", "-charging"); 41 | } 42 | 43 | widget_grid { 44 | style = "module" 45 | button "XBatteryModule" { 46 | action[0] = XBatteryInit() 47 | value = BatteryIcon() 48 | style = If(!Ident($XBatteryState) & !Ident(BSDCtl),"hidden","module") 49 | tooltip = GT("Battery") + ": " + Str(Level) + "%" + If(Time, " " + 50 | Str(Time/60 - Time%60/60) + GT("h") + 51 | Str(Time%60) + GT("m"), "") 52 | interval = 1000 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /icons/weather/lightsleet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /doc/sfwbar-idleinhibit.1: -------------------------------------------------------------------------------- 1 | .\" Man page generated from reStructuredText. 2 | . 3 | . 4 | .nr rst2man-indent-level 0 5 | . 6 | .de1 rstReportMargin 7 | \\$1 \\n[an-margin] 8 | level \\n[rst2man-indent-level] 9 | level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] 10 | - 11 | \\n[rst2man-indent0] 12 | \\n[rst2man-indent1] 13 | \\n[rst2man-indent2] 14 | .. 15 | .de1 INDENT 16 | .\" .rstReportMargin pre: 17 | . RS \\$1 18 | . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] 19 | . nr rst2man-indent-level +1 20 | .\" .rstReportMargin post: 21 | .. 22 | .de UNINDENT 23 | . RE 24 | .\" indent \\n[an-margin] 25 | .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] 26 | .nr rst2man-indent-level -1 27 | .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] 28 | .in \\n[rst2man-indent\\n[rst2man-indent-level]]u 29 | .. 30 | .TH "SFWBAR-IDLEINHIBIT" 1 "" "" 31 | .SH NAME 32 | sfwbar-idleinhibit \- Sfwbar IdleInhibitor module 33 | .sp 34 | Filename: idleinhibit.so 35 | .sp 36 | Requires: none 37 | .SH SYNOPSIS 38 | .sp 39 | The IdleInhibit module, allows attaching idle inhibitor to any widget in the 40 | taskbar. If an idle inhibitor is active on a visible widget, it will prevent 41 | the compositor to going into an idle state (i.e. blanking a screen, 42 | going into a suspend mode or activating a screensaver) 43 | .SH EXPRESSION FUNCTIONS 44 | .SS IdleInhibitState() 45 | .sp 46 | Query an idle inhibitor state on a calling widget. It return a string with 47 | possible values of \(dqOn\(dq, if an idle inhibitor is set on the widget or \(dqOff\(dq 48 | if it isn\(aqt. If the function is called from an expression which isn\(aqt attached 49 | to a widget, the returned value will be \(dqOff\(dq. 50 | .SH ACTIONS 51 | .SS SetIdleInhibitor Command 52 | .sp 53 | Set idle inhibitor state for a widget. The possible command values are: 54 | .INDENT 0.0 55 | .TP 56 | .B \(dqOn\(dq 57 | turn on an idle inhibitor 58 | .TP 59 | .B \(dqOff\(dq 60 | turn off an idle inhibitor 61 | .TP 62 | .B \(dqToggle\(dq 63 | toggle the state of an idle inhibitor 64 | .UNINDENT 65 | .SH TRIGGERS 66 | .sp 67 | The module defines one trigger \(dqIdleInhibitor\(dq which is emitted whenever the 68 | state of any idle inhibitor changes. 69 | .SH COPYRIGHT 70 | GPLv3+ 71 | .\" Generated by docutils manpage writer. 72 | . 73 | -------------------------------------------------------------------------------- /src/wayland.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2023- sfwbar maintainers 4 | */ 5 | 6 | #include 7 | #include "wayland.h" 8 | #include "gui/monitor.h" 9 | #include "xdg-output-unstable-v1.h" 10 | #include "wlr-foreign-toplevel-management-unstable-v1.h" 11 | #include "wlr-layer-shell-unstable-v1.h" 12 | 13 | static GList *wayland_ifaces; 14 | static struct wl_registry *wayland_registry; 15 | static gboolean wayland_init_complete; 16 | 17 | static void handle_global(void *data, struct wl_registry *registry, 18 | uint32_t name, const gchar *interface, uint32_t version) 19 | { 20 | wayland_iface_t *iface; 21 | 22 | if(wayland_init_complete) 23 | return; 24 | 25 | iface = g_malloc0(sizeof(wayland_iface_t)); 26 | iface->iface = g_strdup(interface); 27 | iface->global = name; 28 | iface->version = version; 29 | wayland_ifaces = g_list_append(wayland_ifaces, iface); 30 | } 31 | 32 | gpointer wayland_iface_register ( const gchar *interface, 33 | guint32 min_ver, guint32 max_ver, const void *impl ) 34 | { 35 | GList *iter; 36 | wayland_iface_t *iface; 37 | 38 | for(iter=wayland_ifaces; iter; iter=g_list_next(iter)) 39 | { 40 | iface = iter->data; 41 | if(iface->version >= min_ver && !g_strcmp0(iface->iface, interface)) 42 | return wl_registry_bind(wayland_registry, iface->global, impl, 43 | MIN(iface->version, max_ver)); 44 | } 45 | return NULL; 46 | } 47 | 48 | static void handle_global_remove(void *data, struct wl_registry *registry, 49 | uint32_t name) 50 | { 51 | } 52 | 53 | static const struct wl_registry_listener registry_listener = { 54 | .global = handle_global, 55 | .global_remove = handle_global_remove 56 | }; 57 | 58 | void wayland_init ( void ) 59 | { 60 | struct wl_display *wdisp; 61 | 62 | if(!(wdisp = gdk_wayland_display_get_wl_display(gdk_display_get_default())) ) 63 | g_error("Can't get wayland display\n"); 64 | 65 | wayland_registry = wl_display_get_registry(wdisp); 66 | wl_registry_add_listener(wayland_registry, ®istry_listener, NULL); 67 | wl_display_roundtrip(wdisp); 68 | wayland_init_complete = TRUE; 69 | 70 | wl_display_roundtrip(wdisp); 71 | wl_display_roundtrip(wdisp); 72 | } 73 | -------------------------------------------------------------------------------- /icons/weather/sleet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/sni.h: -------------------------------------------------------------------------------- 1 | #ifndef __SNI_H__ 2 | #define __SNI_H__ 3 | 4 | #define SNI_MAX_STRING (SNI_PROP_ATTNPIX+1) 5 | 6 | enum { 7 | SNI_PROP_CATEGORY = 0, 8 | SNI_PROP_ID = 1, 9 | SNI_PROP_TITLE = 2, 10 | SNI_PROP_STATUS = 3, 11 | SNI_PROP_ICON = 4, 12 | SNI_PROP_OVLAY = 5, 13 | SNI_PROP_ATTN = 6, 14 | SNI_PROP_ATTNMOV = 7, 15 | SNI_PROP_ICONACC = 8, 16 | SNI_PROP_ATTNACC = 9, 17 | SNI_PROP_LABEL = 10, 18 | SNI_PROP_LGUIDE = 11, 19 | SNI_PROP_THEME = 12, 20 | SNI_PROP_ICONPIX = 13, 21 | SNI_PROP_OVLAYPIX = 14, 22 | SNI_PROP_ATTNPIX = 15, 23 | SNI_PROP_WINDOWID = 16, 24 | SNI_PROP_TOOLTIP = 17, 25 | SNI_PROP_ISMENU = 18, 26 | SNI_PROP_MENU = 19, 27 | SNI_PROP_ORDER = 20, 28 | SNI_PROP_MAX = 21 29 | }; 30 | 31 | typedef struct sni_host { 32 | gchar *iface; 33 | gchar *watcher; 34 | gchar *item_iface; 35 | GList *items; 36 | } sni_host_t; 37 | 38 | typedef struct sni_watcher { 39 | guint regid; 40 | gboolean watcher_registered; 41 | gchar *iface; 42 | GList *items; 43 | GDBusNodeInfo *idata; 44 | sni_host_t *host; 45 | } sni_watcher_t; 46 | 47 | typedef struct sni_item { 48 | gchar *uid; 49 | gchar *iface; 50 | gchar *udest; 51 | gchar *dest; 52 | gchar *path; 53 | gchar *string[SNI_MAX_STRING]; 54 | gchar *menu_path; 55 | gchar *tooltip; 56 | gboolean menu; 57 | gint ref; 58 | guint signal; 59 | guint32 order; 60 | GCancellable *cancel; 61 | GtkWidget *menu_obj; 62 | } sni_item_t; 63 | 64 | typedef struct _sni_listener_t { 65 | void (*sni_new)(sni_item_t *, void *); 66 | void (*sni_invalidate)(sni_item_t *, void *); 67 | void (*sni_destroy)(sni_item_t *, void *); 68 | void *data; 69 | } sni_listener_t; 70 | 71 | #define SNI_LISTENER(x) ((sni_listener_t *)(x)) 72 | 73 | void sni_init ( void ); 74 | void sni_listener_register ( sni_listener_t *listener, void *data ); 75 | void sni_listener_remove ( void * ); 76 | void sni_update ( void ); 77 | GDBusConnection *sni_get_connection ( void ); 78 | void sni_get_menu ( GtkWidget *widget, GdkEvent *event ); 79 | sni_item_t *sni_item_new (GDBusConnection *, gchar *, const gchar *); 80 | void sni_item_free ( sni_item_t *sni ); 81 | GList *sni_item_get_list ( void ); 82 | gchar *sni_item_tooltip ( sni_item_t *item ); 83 | gchar *sni_item_icon ( sni_item_t *item ); 84 | void sni_menu_init ( sni_item_t *sni ); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /icons/weather/fair_night.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /config/upower.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Var UPowerPropInterface = ["system", 4 | "org.freedesktop.UPower.PowerProfiles", 5 | "/org/freedesktop/UPower/PowerProfiles", 6 | "org.freedesktop.DBus.Properties"]; 7 | 8 | Var UPowerMenuTmpl = "Menu 'power-profile-selector' { 9 | item { 10 | value = '@PROFILE_NAME@'; 11 | action = UPowerSetProfile('@PROFILE_NAME@'); 12 | } 13 | }" 14 | 15 | Private { 16 | 17 | TriggerAction "power_event", PowerEventHandle(); 18 | TriggerAction "power_appeared", PowerProfilesInit(); 19 | Var ActiveProfile; 20 | 21 | Function UPowerSetProfile ( profile ) 22 | { 23 | DBusCall(UPowerPropInterface, "Set", "(ssvs)", 24 | ["org.freedesktop.UPower.PowerProfiles", "ActiveProfile", profile]); 25 | } 26 | 27 | Function PowerEventHandle() { 28 | Var i = 0; 29 | While(i 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /icons/weather/partlycloudy_night.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/window.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2023- sfwbar maintainers 4 | */ 5 | 6 | #include "window.h" 7 | 8 | void window_ref_free ( GtkWidget *self ) 9 | { 10 | GList **refs; 11 | 12 | refs = g_object_get_data(G_OBJECT(self),"window_refs"); 13 | 14 | if(!refs) 15 | return; 16 | 17 | g_list_free(*refs); 18 | g_free(refs); 19 | g_object_set_data(G_OBJECT(self),"window_refs", NULL); 20 | } 21 | 22 | void window_ref ( GtkWidget *self, GtkWidget *ref ) 23 | { 24 | GList **refs; 25 | 26 | refs = g_object_get_data(G_OBJECT(self),"window_refs"); 27 | if(!refs) 28 | { 29 | g_object_set_data_full(G_OBJECT(self),"window_refs", 30 | g_malloc0(sizeof(GList *)),(GDestroyNotify)window_ref_free); 31 | refs = g_object_get_data(G_OBJECT(self),"window_refs"); 32 | } 33 | 34 | if(refs && !g_list_find(*refs, ref)) 35 | *refs = g_list_prepend(*refs ,ref); 36 | g_signal_connect(G_OBJECT(ref),"unmap",G_CALLBACK(window_unref),self); 37 | } 38 | 39 | void window_unref ( GtkWidget *ref, GtkWidget *self ) 40 | { 41 | GList **refs; 42 | void (*unref_func)( gpointer); 43 | 44 | refs = g_object_get_data(G_OBJECT(self),"window_refs"); 45 | if(!refs) 46 | return; 47 | 48 | *refs = g_list_remove(*refs, ref); 49 | if(!*refs && (unref_func = g_object_get_data(G_OBJECT(self), "unref_func"))) 50 | unref_func(self); 51 | } 52 | 53 | gboolean window_ref_check ( GtkWidget *self ) 54 | { 55 | GList **refs; 56 | 57 | refs = g_object_get_data(G_OBJECT(self),"window_refs"); 58 | 59 | return !!(refs && *refs); 60 | } 61 | 62 | void window_set_unref_func ( GtkWidget *self, void (*func)(gpointer) ) 63 | { 64 | g_object_set_data(G_OBJECT(self), "unref_func", func); 65 | } 66 | 67 | void window_collapse_popups ( GtkWidget *self ) 68 | { 69 | GList *iter, **refs; 70 | 71 | refs = g_object_get_data(G_OBJECT(self),"window_refs"); 72 | if(!refs) 73 | return; 74 | 75 | for(iter=*refs; iter; iter=g_list_next(iter)) 76 | { 77 | if(iter->data == self) 78 | continue; 79 | if(GTK_IS_WINDOW(iter->data) && 80 | gtk_window_get_window_type(GTK_WINDOW(iter->data)) == GTK_WINDOW_POPUP) 81 | window_collapse_popups(iter->data); 82 | 83 | if(GTK_IS_WINDOW(iter->data)) 84 | gtk_widget_hide(iter->data); 85 | if(GTK_IS_MENU(iter->data)) 86 | { 87 | gtk_menu_popdown(iter->data); 88 | iter = *refs; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /icons/weather/lightrainandthunder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /config/battery.source: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | module("bsdctl"); 4 | 5 | Var device = ''; 6 | 7 | Function XBatteryInit() { 8 | Var base, dir, sub, file, i, j; 9 | Var file_full, file_status, file_charge, file_current, file_uevent; 10 | Var BatteryConf = "file('%file_full%') { XBatteryTotal = Grab(First) }; 11 | file('%file_charge%') { XBatteryLeft = Grab(First) }; 12 | file ('%file_status%') { XBatteryState = RegEx('^(.*)$',First) };" 13 | 14 | If(Ident("BSDCtl")) 15 | return; 16 | 17 | base = "/sys/class/power_supply"; 18 | if device != '' 19 | dir = [ device ]; 20 | else 21 | dir = ls(base); 22 | i = 0; 23 | 24 | while i 5 | #include "flowitem.h" 6 | 7 | #define FLOW_GRID_TYPE (flow_grid_get_type()) 8 | #define FLOW_GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FLOW_GRID_TYPE, FlowGrid)) 9 | #define FLOW_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FLOW_GRID_TYPE, FlowGridClass)) 10 | #define IS_FLOW_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FLOW_GRID_TYPE)) 11 | #define IS_FLOW_GRIDCLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FLOW_GRID_TYPE)) 12 | #define FLOW_GRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FLOW_GRID_TYPE, FlowGridClass)) 13 | 14 | enum { 15 | /* drag_dest_add_(image|text|uri)_targets sets info to 0 */ 16 | SFWB_DND_TARGET_GENERIC_GTK_API, 17 | SFWB_DND_TARGET_FLOW_ITEM 18 | }; 19 | 20 | enum { 21 | FLOW_GRID_AXIS_DEFAULT = 0, 22 | FLOW_GRID_AXIS_ROWS, 23 | FLOW_GRID_AXIS_COLS, 24 | }; 25 | 26 | typedef struct _FlowGrid FlowGrid; 27 | typedef struct _FlowGridClass FlowGridClass; 28 | 29 | struct _FlowGrid 30 | { 31 | BaseWidget item; 32 | }; 33 | 34 | struct _FlowGridClass 35 | { 36 | BaseWidgetClass parent_class; 37 | 38 | gboolean limit; 39 | }; 40 | 41 | typedef struct _FlowGridPrivate FlowGridPrivate; 42 | 43 | struct _FlowGridPrivate 44 | { 45 | gint cols,rows; 46 | gint primary_axis; 47 | gboolean icons, labels, tooltips; 48 | gint title_width; 49 | gboolean invalid; 50 | gboolean sort; 51 | GList *children; 52 | gint (*comp)( GtkWidget *, GtkWidget *, GtkWidget * ); 53 | GtkTargetEntry *dnd_target; 54 | GtkWidget *parent; 55 | GtkWidget *grid; 56 | }; 57 | 58 | GType flow_grid_get_type ( void ); 59 | 60 | void flow_grid_add_child ( GtkWidget *self, GtkWidget *child ); 61 | gboolean flow_grid_update ( GtkWidget *self ); 62 | void flow_grid_invalidate ( GtkWidget *self ); 63 | void flow_grid_delete_child ( GtkWidget *, void *parent ); 64 | guint flow_grid_n_children ( GtkWidget *self ); 65 | gpointer flow_grid_find_child ( GtkWidget *, gconstpointer parent ); 66 | void flow_grid_child_dnd_enable ( GtkWidget *, GtkWidget *, GtkWidget *); 67 | GtkWidget *flow_grid_get_parent ( GtkWidget *self ); 68 | void flow_grid_set_parent ( GtkWidget *self, GtkWidget *parent ); 69 | void flow_grid_set_dnd_target ( GtkWidget *self, GtkTargetEntry *target ); 70 | GtkTargetEntry *flow_grid_get_dnd_target ( GtkWidget *self ); 71 | void flow_grid_children_order ( GtkWidget *self, GtkWidget *ref, 72 | GtkWidget *child, gboolean after ); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /icons/weather/heavysleet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /icons/weather/rainandthunder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/util/hash.c: -------------------------------------------------------------------------------- 1 | #include "util/hash.h" 2 | 3 | hash_table_t *hash_table_new(GHashFunc hash_func, GEqualFunc equal_func ) 4 | { 5 | return hash_table_new_full(hash_func, equal_func, NULL, NULL); 6 | } 7 | 8 | hash_table_t *hash_table_new_full(GHashFunc hash_func, GEqualFunc equal_func, 9 | GDestroyNotify destroy_key, GDestroyNotify destroy_value) 10 | { 11 | hash_table_t *hash = g_malloc0(sizeof(hash_table_t)); 12 | hash->table = g_hash_table_new_full(hash_func, equal_func, destroy_key, 13 | destroy_value); 14 | return hash; 15 | } 16 | 17 | gboolean hash_table_insert ( hash_table_t *hash, gpointer key, gpointer val ) 18 | { 19 | gboolean result; 20 | 21 | if(!hash) 22 | return FALSE; 23 | 24 | hash_table_lock(hash); 25 | result = g_hash_table_insert(hash->table, key, val); 26 | hash_table_unlock(hash); 27 | 28 | return result; 29 | } 30 | 31 | gpointer hash_table_lookup ( hash_table_t *hash, gconstpointer key ) 32 | { 33 | gpointer value; 34 | 35 | if(!hash || !key) 36 | return NULL; 37 | 38 | hash_table_lock(hash); 39 | value = g_hash_table_lookup(hash->table, key); 40 | hash_table_unlock(hash); 41 | 42 | return value; 43 | } 44 | 45 | gboolean hash_table_remove ( hash_table_t *hash, gconstpointer key ) 46 | { 47 | gboolean result; 48 | 49 | if(!hash) 50 | return FALSE; 51 | 52 | hash_table_lock(hash); 53 | result = g_hash_table_remove(hash->table, key); 54 | hash_table_unlock(hash); 55 | 56 | return result; 57 | } 58 | 59 | void hash_table_remove_all ( hash_table_t *hash ) 60 | { 61 | if(!hash) 62 | return; 63 | 64 | hash_table_lock(hash); 65 | g_hash_table_remove_all(hash->table); 66 | hash_table_unlock(hash); 67 | g_free(hash); 68 | } 69 | 70 | gpointer hash_table_find ( hash_table_t *hash, GHRFunc pred, gpointer key) 71 | { 72 | gpointer value; 73 | 74 | if(!hash) 75 | return NULL; 76 | 77 | hash_table_lock(hash); 78 | value = g_hash_table_find(hash->table, pred, key); 79 | hash_table_unlock(hash); 80 | 81 | return value; 82 | } 83 | 84 | void hash_table_foreach( hash_table_t *hash, GHFunc func, gpointer d ) 85 | { 86 | if(!hash) 87 | return; 88 | 89 | hash_table_lock(hash); 90 | g_hash_table_foreach(hash->table, func, d); 91 | hash_table_unlock(hash); 92 | } 93 | 94 | void hash_table_lock( hash_table_t *hash ) 95 | { 96 | if(hash) 97 | g_rec_mutex_lock(&hash->mutex); 98 | } 99 | 100 | void hash_table_unlock( hash_table_t *hash ) 101 | { 102 | if(hash) 103 | g_rec_mutex_unlock(&hash->mutex); 104 | } 105 | -------------------------------------------------------------------------------- /modules/idleinhibit.c: -------------------------------------------------------------------------------- 1 | /* This entire file is licensed under GNU General Public License v3.0 2 | * 3 | * Copyright 2023- Sfwbar maintainers 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "module.h" 10 | #include "trigger.h" 11 | #include "wayland.h" 12 | #include "idle-inhibit-unstable-v1.h" 13 | #include "vm/vm.h" 14 | #include "gui/basewidget.h" 15 | 16 | gint64 sfwbar_module_signature = 0x73f4d956a1; 17 | guint16 sfwbar_module_version = MODULE_API_VERSION; 18 | static struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; 19 | 20 | static value_t idle_inhibit_state ( vm_t *vm, value_t p[], gint np ) 21 | { 22 | GtkWidget *widget = vm_widget_get(vm, NULL); 23 | return value_new_string(g_strdup((widget && g_object_get_data( 24 | G_OBJECT(widget), "inhibitor"))? "on" : "off")); 25 | } 26 | 27 | static value_t idle_inhibitor_action ( vm_t *vm, value_t p[], gint np ) 28 | { 29 | GtkWidget *widget = vm_widget_get(vm, NULL); 30 | struct wl_surface *surface; 31 | struct zwp_idle_inhibitor_v1 *inhibitor; 32 | gboolean inhibit; 33 | 34 | vm_param_check_np(vm, np, 1, "SetIdleInhibitor"); 35 | vm_param_check_string(vm, p, 0, "SetIdleInhibitor"); 36 | 37 | inhibitor = g_object_get_data(G_OBJECT(widget), "inhibitor"); 38 | 39 | if(!g_ascii_strcasecmp(value_get_string(p[0]), "on")) 40 | inhibit = TRUE; 41 | else if(!g_ascii_strcasecmp(value_get_string(p[0]), "off")) 42 | inhibit = FALSE; 43 | else if(!g_ascii_strcasecmp(value_get_string(p[0]), "toggle")) 44 | inhibit = !inhibitor; 45 | else 46 | return value_na; 47 | 48 | if(inhibit && !inhibitor) 49 | { 50 | if( !(surface = gdk_wayland_window_get_wl_surface( 51 | gtk_widget_get_window(widget))) ) 52 | return value_na; 53 | 54 | inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor( 55 | idle_inhibit_manager, surface ); 56 | g_object_set_data(G_OBJECT(widget), "inhibitor", inhibitor); 57 | trigger_emit("idleinhibitor"); 58 | } 59 | else if( !inhibit && inhibitor ) 60 | { 61 | g_object_set_data(G_OBJECT(widget), "inhibitor", NULL); 62 | zwp_idle_inhibitor_v1_destroy(inhibitor); 63 | trigger_emit("idleinhibitor"); 64 | } 65 | return value_na; 66 | } 67 | 68 | gboolean sfwbar_module_init ( void ) 69 | { 70 | vm_func_add("idleinhibitstate", idle_inhibit_state, FALSE, FALSE); 71 | vm_func_add("setidleinhibitor", idle_inhibitor_action, TRUE, FALSE); 72 | idle_inhibit_manager = wayland_iface_register( 73 | zwp_idle_inhibit_manager_v1_interface.name, 1, 1, 74 | &zwp_idle_inhibit_manager_v1_interface); 75 | return TRUE; 76 | } 77 | -------------------------------------------------------------------------------- /config/backlight.widget: -------------------------------------------------------------------------------- 1 | #Api2 2 | 3 | Private { 4 | 5 | include("backlight.source") 6 | 7 | Var Step = 0.05; 8 | 9 | Var BacklightTmpl = ' 10 | 11 | 13 | 14 | 17 | 19 | 21 | ' 22 | 23 | Var BacklightSvg = ' 24 | 25 | 27 | 30 | ' 31 | 32 | widget_grid { 33 | style = "module" 34 | button { 35 | style = if(BacklightPresent, "module", "hidden") 36 | value = Replace(BacklightTmpl, "@BRIGHTNESS@", Str(BacklightPct*492)) 37 | action[ScrollUp] = SetBacklight(BacklightPct+Step) 38 | action[ScrollDown] = SetBacklight(BacklightPct-Step) 39 | action[LeftClick] = PopUp("BacklightPopup") 40 | action[0] = BacklightInit() 41 | trigger = "backlight" 42 | } 43 | } 44 | } 45 | 46 | #CSS 47 | 48 | window#BacklightPopup { 49 | background: rgba(0,0,0,0); 50 | } 51 | 52 | grid#backlight_popup { 53 | border-radius: 10px; 54 | border: 1px solid @borders; 55 | margin: 5px; 56 | padding: 10px; 57 | background-color: @theme_bg_color; 58 | -GtkWidget-hexpand: true; 59 | -GtkWidget-vexpand: false; 60 | -GtkWidget-direction: right; 61 | } 62 | 63 | image#backlight_icon { 64 | min-height: 12px; 65 | min-width: 12px; 66 | } 67 | 68 | #backlight_scale { 69 | margin: 5px; 70 | -GtkWidget-direction: right; 71 | -GtkWidget-valign: center; 72 | -GtkWidget-hexpand: true; 73 | } 74 | 75 | #backlight_scale progress, 76 | #backlight_scale trough { 77 | min-height: 10px; 78 | } 79 | -------------------------------------------------------------------------------- /src/workspace.h: -------------------------------------------------------------------------------- 1 | #ifndef __WORKSPACE_H__ 2 | #define __WORKSPACE_H__ 3 | 4 | #include 5 | 6 | enum { 7 | WS_STATE_FOCUSED = 0x0001, 8 | WS_STATE_VISIBLE = 0x0002, 9 | WS_STATE_URGENT = 0x0004, 10 | WS_STATE_INVALID = 0x0080, 11 | WS_STATE_ALL = 0x00ff, 12 | 13 | WS_CAP_ACTIVATE = 0x0100, 14 | WS_CAP_ALL = 0xff00, 15 | }; 16 | 17 | typedef struct workspace_s { 18 | gpointer id; 19 | gchar *name; 20 | guint32 state; 21 | gint refcount; 22 | void *data; 23 | } workspace_t; 24 | 25 | struct workspace_api { 26 | void (*set_workspace) ( workspace_t * ); 27 | guint (*get_geom) ( gpointer, GdkRectangle *, gpointer, GdkRectangle **, 28 | GdkRectangle *, gint * ); 29 | gboolean (*get_can_create) ( void ); 30 | gboolean (*check_monitor) ( gpointer, gchar * ); 31 | }; 32 | 33 | typedef struct _workspace_listener { 34 | void (*workspace_new) ( workspace_t *, void *); 35 | void (*workspace_invalidate) ( workspace_t *, void *); 36 | void (*workspace_destroy) ( workspace_t *, void *); 37 | void *data; 38 | } workspace_listener_t; 39 | 40 | #define WORKSPACE_LISTENER(x) ((workspace_listener_t *)(x)) 41 | #define PAGER_PIN_ID (GINT_TO_POINTER(-1)) 42 | #define WORKSPACE(x) ((workspace_t *)(x)) 43 | 44 | void workspace_api_register ( struct workspace_api *new ); 45 | gboolean workspace_api_check ( void ); 46 | void workspace_listener_register ( workspace_listener_t *, gpointer ); 47 | void workspace_listener_remove ( void *data ); 48 | workspace_t *workspace_new ( gpointer id ); 49 | void workspace_commit ( workspace_t *ws ); 50 | void workspace_change_focus ( gpointer id ); 51 | //void workspace_set_state ( workspace_t *ws, guint32 state ); 52 | void workspace_mod_state ( gpointer id, gint32 mask, gboolean state ); 53 | void workspace_set_caps ( workspace_t *ws, guint32 caps ); 54 | void workspace_set_name ( workspace_t *ws, const gchar *name ); 55 | void workspace_set_active ( workspace_t *ws, const gchar *output ); 56 | gpointer workspace_get_active ( GtkWidget *widget ); 57 | gpointer workspace_id_from_name ( const gchar *name ); 58 | workspace_t *workspace_from_id ( gpointer id ); 59 | gpointer workspace_get_focused ( void ); 60 | void workspace_activate ( workspace_t *ws ); 61 | guint workspace_get_geometry ( gpointer wid, GdkRectangle *wloc, gpointer wsid, 62 | GdkRectangle **wins, GdkRectangle *spc, gint *focus); 63 | gboolean workspace_check_monitor ( gpointer wsid, gchar *output ); 64 | gboolean workspace_get_can_create ( void ); 65 | void workspace_pin_add ( gchar *pin ); 66 | GList *workspace_get_list ( void ); 67 | workspace_t *workspace_from_name ( const gchar *name ); 68 | void workspace_ref ( gpointer id ); 69 | void workspace_unref ( gpointer id ); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /icons/weather/lightsnowandthunder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | --------------------------------------------------------------------------------