/* $Id$ */ /* Copyright (c) 2012-2022 Pierre Pronchery */ /* This file is part of DeforaOS Desktop Panel */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "../src/window.h" #include "../config.h" /* constants */ #ifndef PREFIX # define PREFIX "/usr/local" #endif #ifndef LIBDIR # define LIBDIR PREFIX "/lib" #endif /* private */ /* types */ struct _Panel { Config * config; PanelPrefs prefs; PanelAppletHelper helper[PANEL_POSITION_COUNT]; PanelWindow * windows[PANEL_POSITION_COUNT]; GdkScreen * screen; GdkWindow * root; gint root_width; /* width of the root window */ gint root_height; /* height of the root window */ guint source; guint timeout; /* dialogs */ GtkWidget * ab_window; GtkWidget * lk_window; GtkWidget * lo_window; GtkWidget * sh_window; GtkWidget * su_window; }; /* constants */ static char const * _authors[] = { "Pierre Pronchery ", NULL }; /* prototypes */ /* Panel */ static int _panel_init(Panel * panel, PanelWindowPosition position, PanelWindowType type, GtkIconSize iconsize); static void _panel_destroy(Panel * panel); /* accessors */ static void _panel_set_title(Panel * panel, char const * title); /* useful */ #define HELPER_POSITION_MENU_WIDGET #include "../src/helper.c" static int _panel_append(Panel * panel, PanelPosition position, char const * applet); static void _panel_show(Panel * panel, gboolean show); static int _applet_list(void); static char * _config_get_filename(void); static int _error(char const * message, int ret); /* helper */ /* essential */ static void _helper_init(PanelAppletHelper * helper, Panel * panel, PanelWindowType type, GtkIconSize iconsize); /* public */ /* functions */ /* accessors */ /* panel_get_config */ char const * panel_get_config(Panel * panel, char const * section, char const * variable) { return config_get(panel->config, section, variable); } /* useful */ /* panel_error */ int panel_error(Panel * panel, char const * message, int ret) { (void) panel; fprintf(stderr, "%s: %s\n", PROGNAME, (message != NULL) ? message : error_get(NULL)); return ret; } /* panel_show_preferences */ void panel_show_preferences(Panel * panel, gboolean show) { (void) panel; (void) show; /* XXX just a stub */ } /* private */ /* functions */ /* Panel */ /* panel_init */ static int _panel_init(Panel * panel, PanelWindowPosition position, PanelWindowType type, GtkIconSize iconsize) { const PanelPosition top = PANEL_POSITION_TOP; char * filename; GdkRectangle rect; size_t i; if((panel->config = config_new()) == NULL) return -1; if((filename = _config_get_filename()) != NULL && config_load(panel->config, filename) != 0) error_print(PROGNAME); free(filename); panel->prefs.iconsize = NULL; panel->prefs.monitor = -1; /* root window */ panel->screen = gdk_screen_get_default(); panel->root = gdk_screen_get_root_window(panel->screen); gdk_screen_get_monitor_geometry(panel->screen, 0, &rect); panel->root_height = rect.height; panel->root_width = rect.width; /* panel window */ _helper_init(&panel->helper[top], panel, type, iconsize); panel->windows[top] = panel_window_new(&panel->helper[top], PANEL_WINDOW_TYPE_NORMAL, position, iconsize, &rect); panel->helper[top].window = panel->windows[top]; for(i = 0; i < sizeof(panel->windows) / sizeof(*panel->windows); i++) if(i != top) panel->windows[i] = NULL; panel->source = 0; panel->timeout = 0; panel->ab_window = NULL; panel->lk_window = NULL; panel->lo_window = NULL; panel->sh_window = NULL; panel->su_window = NULL; return 0; } /* panel_destroy */ static void _panel_destroy(Panel * panel) { size_t i; if(panel->timeout != 0) g_source_remove(panel->timeout); if(panel->source != 0) g_source_remove(panel->source); for(i = 0; i < sizeof(panel->windows) / sizeof(*panel->windows); i++) if(panel->windows[i] != NULL) panel_window_delete(panel->windows[i]); if(panel->ab_window != NULL) gtk_widget_destroy(panel->ab_window); if(panel->lk_window != NULL) gtk_widget_destroy(panel->lk_window); if(panel->lo_window != NULL) gtk_widget_destroy(panel->lo_window); if(panel->sh_window != NULL) gtk_widget_destroy(panel->sh_window); if(panel->su_window != NULL) gtk_widget_destroy(panel->su_window); } /* accessors */ /* panel_set_title */ static void _panel_set_title(Panel * panel, char const * title) { panel_window_set_title(panel->windows[PANEL_POSITION_TOP], title); } /* useful */ /* panel_append */ static int _panel_append(Panel * panel, PanelPosition position, char const * applet) { if(position == PANEL_POSITION_TOP) return panel_window_append(panel->windows[PANEL_POSITION_TOP], applet); return -error_set_code(1, "%s", _("Invalid panel position")); } /* panel_show */ static void _panel_show(Panel * panel, gboolean show) { panel_window_show(panel->windows[PANEL_POSITION_TOP], show); } /* applet_list */ static int _applet_list(void) { char const path[] = LIBDIR "/Panel/applets"; DIR * dir; struct dirent * de; size_t len; char const * sep = ""; #ifdef __APPLE__ char const ext[] = ".dylib"; #else char const ext[] = ".so"; #endif puts(_("Applets available:")); if((dir = opendir(path)) == NULL) return _error(path, 1); while((de = readdir(dir)) != NULL) { len = strlen(de->d_name); if(len < sizeof(ext) || strcmp(&de->d_name[ len - sizeof(ext) + 1], ext) != 0) continue; de->d_name[len - 3] = '\0'; printf("%s%s", sep, de->d_name); sep = ", "; } putchar('\n'); closedir(dir); return 0; } /* config_get_filename */ static char * _config_get_filename(void) { String const * homedir; if((homedir = getenv("HOME")) == NULL) homedir = g_get_home_dir(); return string_new_append(homedir, "/", PANEL_CONFIG_FILE, NULL); } /* error */ static int _error(char const * message, int ret) { return _panel_helper_error(NULL, message, ret); } /* helpers */ /* essential */ /* helper_init */ static int _init_can_shutdown(void); static int _init_can_suspend(void); static void _helper_init(PanelAppletHelper * helper, Panel * panel, PanelWindowType type, GtkIconSize iconsize) { char const * p; (void) panel; (void) type; (void) iconsize; memset(helper, 0, sizeof(*helper)); helper->panel = panel; helper->config_get = _panel_helper_config_get; helper->config_set = _panel_helper_config_set; helper->error = _panel_helper_error; helper->about_dialog = _panel_helper_about_dialog; helper->lock = _panel_helper_lock; helper->lock_dialog = _panel_helper_lock_dialog; helper->logout = _panel_helper_logout; #ifndef EMBEDDED if((p = config_get(panel->config, NULL, "logout")) == NULL || strtol(p, NULL, 0) != 0) #else if((p = config_get(panel->config, NULL, "logout")) != NULL && strtol(p, NULL, 0) != 0) #endif helper->logout_dialog = _panel_helper_logout_dialog; else helper->logout_dialog = NULL; helper->position_menu = _panel_helper_position_menu_widget; helper->preferences_dialog = _panel_helper_preferences_dialog; helper->rotate_screen = _panel_helper_rotate_screen; helper->shutdown = _init_can_shutdown() ? _panel_helper_shutdown : NULL; helper->shutdown_dialog = (helper->shutdown != NULL) ? _panel_helper_shutdown_dialog : NULL; helper->suspend = _init_can_suspend() ? _panel_helper_suspend : NULL; helper->suspend_dialog = (helper->suspend != NULL) ? _panel_helper_suspend_dialog : NULL; } static int _init_can_shutdown(void) { /* XXX code duplicated from ../src/panel.c */ char const shutdown[] = "/sbin/shutdown"; if(geteuid() == 0) return 1; return (access(shutdown, R_OK | X_OK) == 0) ? 1 : 0; } static int _init_can_suspend(void) { /* XXX code duplicated from ../src/panel.c */ #ifdef __NetBSD__ char const * names[] = { "machdep.sleep_state", "hw.acpi.sleep.state" }; int sleep_state = -1; size_t size = sizeof(sleep_state); /* FIXME check that this works properly */ if(sysctlbyname(names[0], &sleep_state, &size, NULL, 0) == 0 && sleep_state == 0 && sysctlbyname(names[0], &sleep_state, &size, &sleep_state, size) == 0) return 1; if(sysctlbyname(names[1], &sleep_state, &size, NULL, 0) == 0 && sleep_state == 0 && sysctlbyname(names[1], &sleep_state, &size, &sleep_state, size) == 0) return 1; #else struct stat st; if(access("/sys/power/state", W_OK) == 0) return 1; if(lstat("/proc/apm", &st) == 0) return 1; #endif return 0; }