/* wdefaults.c - window specific defaults * * Window Maker window manager * * Copyright (c) 1997-2003 Alfredo K. Kojima * * 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; either version 2 of the License, or * (at your option) any later version. * * 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, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "wconfig.h" #include #include #include #include #include #include #include #include #include #include #include "WindowMaker.h" #include "window.h" #include "appicon.h" #include "screen.h" #include "funcs.h" #include "workspace.h" #include "defaults.h" #include "icon.h" #define APPLY_VAL(value, flag, attrib) \ if (value) {attr->flag = getBool(attrib, value); \ if (mask) mask->flag = 1;} /* Global stuff */ extern WPreferences wPreferences; extern WDDomain *WDWindowAttributes; /* Local stuff */ /* type converters */ static int getBool(WMPropList *, WMPropList *); static char *getString(WMPropList *, WMPropList *); static WMPropList *ANoTitlebar = NULL; static WMPropList *ANoResizebar; static WMPropList *ANoMiniaturizeButton; static WMPropList *ANoMiniaturizable; static WMPropList *ANoCloseButton; static WMPropList *ANoBorder; static WMPropList *ANoHideOthers; static WMPropList *ANoMouseBindings; static WMPropList *ANoKeyBindings; static WMPropList *ANoAppIcon; /* app */ static WMPropList *AKeepOnTop; static WMPropList *AKeepOnBottom; static WMPropList *AOmnipresent; static WMPropList *ASkipWindowList; static WMPropList *ASkipSwitchPanel; static WMPropList *AKeepInsideScreen; static WMPropList *AUnfocusable; static WMPropList *AAlwaysUserIcon; static WMPropList *AStartMiniaturized; static WMPropList *AStartMaximized; static WMPropList *AStartHidden; /* app */ static WMPropList *ADontSaveSession; /* app */ static WMPropList *AEmulateAppIcon; static WMPropList *AFocusAcrossWorkspace; static WMPropList *AFullMaximize; static WMPropList *ASharedAppIcon; /* app */ #ifdef XKB_BUTTON_HINT static WMPropList *ANoLanguageButton; #endif static WMPropList *AStartWorkspace; static WMPropList *AIcon; static WMPropList *AnyWindow; static WMPropList *No; static void init_wdefaults(void) { AIcon = WMCreatePLString("Icon"); ANoTitlebar = WMCreatePLString("NoTitlebar"); ANoResizebar = WMCreatePLString("NoResizebar"); ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton"); ANoMiniaturizable = WMCreatePLString("NoMiniaturizable"); ANoCloseButton = WMCreatePLString("NoCloseButton"); ANoBorder = WMCreatePLString("NoBorder"); ANoHideOthers = WMCreatePLString("NoHideOthers"); ANoMouseBindings = WMCreatePLString("NoMouseBindings"); ANoKeyBindings = WMCreatePLString("NoKeyBindings"); ANoAppIcon = WMCreatePLString("NoAppIcon"); AKeepOnTop = WMCreatePLString("KeepOnTop"); AKeepOnBottom = WMCreatePLString("KeepOnBottom"); AOmnipresent = WMCreatePLString("Omnipresent"); ASkipWindowList = WMCreatePLString("SkipWindowList"); ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel"); AKeepInsideScreen = WMCreatePLString("KeepInsideScreen"); AUnfocusable = WMCreatePLString("Unfocusable"); AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon"); AStartMiniaturized = WMCreatePLString("StartMiniaturized"); AStartHidden = WMCreatePLString("StartHidden"); AStartMaximized = WMCreatePLString("StartMaximized"); ADontSaveSession = WMCreatePLString("DontSaveSession"); AEmulateAppIcon = WMCreatePLString("EmulateAppIcon"); AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace"); AFullMaximize = WMCreatePLString("FullMaximize"); ASharedAppIcon = WMCreatePLString("SharedAppIcon"); #ifdef XKB_BUTTON_HINT ANoLanguageButton = WMCreatePLString("NoLanguageButton"); #endif AStartWorkspace = WMCreatePLString("StartWorkspace"); AnyWindow = WMCreatePLString("*"); No = WMCreatePLString("No"); } /* Returns the correct WMPropList, using instance+class or instance, or class, or default */ static WMPropList *get_value(WMPropList * dict_win, WMPropList * dict_class, WMPropList * dict_name, WMPropList * dict_any, WMPropList * option, WMPropList * default_value, Bool useGlobalDefault) { WMPropList *value; if (dict_win) { value = WMGetFromPLDictionary(dict_win, option); if (value) return value; } if (dict_name) { value = WMGetFromPLDictionary(dict_name, option); if (value) return value; } if (dict_class) { value = WMGetFromPLDictionary(dict_class, option); if (value) return value; } if (!useGlobalDefault) return NULL; if (dict_any) { value = WMGetFromPLDictionary(dict_any, option); if (value) return value; } return default_value; } static WMPropList *get_value_from_instanceclass(char *value) { WMPropList *key, *val = NULL; if (!value) return NULL; key = WMCreatePLString(value); WMPLSetCaseSensitive(True); if (WDWindowAttributes->dictionary) val = key ? WMGetFromPLDictionary(WDWindowAttributes->dictionary, key) : NULL; if (key) WMReleasePropList(key); WMPLSetCaseSensitive(False); return val; } /* *---------------------------------------------------------------------- * wDefaultFillAttributes-- * Retrieves attributes for the specified instance/class and * fills attr with it. Values that are actually defined are also * set in mask. If useGlobalDefault is True, the default for * all windows ("*") will be used for when no values are found * for that instance/class. * *---------------------------------------------------------------------- */ void wDefaultFillAttributes(char *instance, char *class, WWindowAttributes *attr, WWindowAttributes *mask, Bool useGlobalDefault) { WMPropList *value, *dw, *dc, *dn, *da; char *buffer; dw = dc = dn = da = NULL; if (!ANoTitlebar) init_wdefaults(); if (class && instance) { buffer = StrConcatDot(instance, class); dw = get_value_from_instanceclass(buffer); wfree(buffer); } dn = get_value_from_instanceclass(instance); dc = get_value_from_instanceclass(class); WMPLSetCaseSensitive(True); if ((WDWindowAttributes->dictionary) && (useGlobalDefault)) da = WMGetFromPLDictionary(WDWindowAttributes->dictionary, AnyWindow); /* get the data */ value = get_value(dw, dc, dn, da, ANoTitlebar, No, useGlobalDefault); APPLY_VAL(value, no_titlebar, ANoTitlebar); value = get_value(dw, dc, dn, da, ANoResizebar, No, useGlobalDefault); APPLY_VAL(value, no_resizebar, ANoResizebar); value = get_value(dw, dc, dn, da, ANoMiniaturizeButton, No, useGlobalDefault); APPLY_VAL(value, no_miniaturize_button, ANoMiniaturizeButton); value = get_value(dw, dc, dn, da, ANoMiniaturizable, No, useGlobalDefault); APPLY_VAL(value, no_miniaturizable, ANoMiniaturizable); value = get_value(dw, dc, dn, da, ANoCloseButton, No, useGlobalDefault); APPLY_VAL(value, no_close_button, ANoCloseButton); value = get_value(dw, dc, dn, da, ANoBorder, No, useGlobalDefault); APPLY_VAL(value, no_border, ANoBorder); value = get_value(dw, dc, dn, da, ANoHideOthers, No, useGlobalDefault); APPLY_VAL(value, no_hide_others, ANoHideOthers); value = get_value(dw, dc, dn, da, ANoMouseBindings, No, useGlobalDefault); APPLY_VAL(value, no_bind_mouse, ANoMouseBindings); value = get_value(dw, dc, dn, da, ANoKeyBindings, No, useGlobalDefault); APPLY_VAL(value, no_bind_keys, ANoKeyBindings); value = get_value(dw, dc, dn, da, ANoAppIcon, No, useGlobalDefault); APPLY_VAL(value, no_appicon, ANoAppIcon); value = get_value(dw, dc, dn, da, ASharedAppIcon, No, useGlobalDefault); APPLY_VAL(value, shared_appicon, ASharedAppIcon); value = get_value(dw, dc, dn, da, AKeepOnTop, No, useGlobalDefault); APPLY_VAL(value, floating, AKeepOnTop); value = get_value(dw, dc, dn, da, AKeepOnBottom, No, useGlobalDefault); APPLY_VAL(value, sunken, AKeepOnBottom); value = get_value(dw, dc, dn, da, AOmnipresent, No, useGlobalDefault); APPLY_VAL(value, omnipresent, AOmnipresent); value = get_value(dw, dc, dn, da, ASkipWindowList, No, useGlobalDefault); APPLY_VAL(value, skip_window_list, ASkipWindowList); value = get_value(dw, dc, dn, da, ASkipSwitchPanel, No, useGlobalDefault); APPLY_VAL(value, skip_switchpanel, ASkipSwitchPanel); value = get_value(dw, dc, dn, da, AKeepInsideScreen, No, useGlobalDefault); APPLY_VAL(value, dont_move_off, AKeepInsideScreen); value = get_value(dw, dc, dn, da, AUnfocusable, No, useGlobalDefault); APPLY_VAL(value, no_focusable, AUnfocusable); value = get_value(dw, dc, dn, da, AAlwaysUserIcon, No, useGlobalDefault); APPLY_VAL(value, always_user_icon, AAlwaysUserIcon); value = get_value(dw, dc, dn, da, AStartMiniaturized, No, useGlobalDefault); APPLY_VAL(value, start_miniaturized, AStartMiniaturized); value = get_value(dw, dc, dn, da, AStartHidden, No, useGlobalDefault); APPLY_VAL(value, start_hidden, AStartHidden); value = get_value(dw, dc, dn, da, AStartMaximized, No, useGlobalDefault); APPLY_VAL(value, start_maximized, AStartMaximized); value = get_value(dw, dc, dn, da, ADontSaveSession, No, useGlobalDefault); APPLY_VAL(value, dont_save_session, ADontSaveSession); value = get_value(dw, dc, dn, da, AEmulateAppIcon, No, useGlobalDefault); APPLY_VAL(value, emulate_appicon, AEmulateAppIcon); value = get_value(dw, dc, dn, da, AFocusAcrossWorkspace, No, useGlobalDefault); APPLY_VAL(value, focus_across_wksp, AFocusAcrossWorkspace); value = get_value(dw, dc, dn, da, AFullMaximize, No, useGlobalDefault); APPLY_VAL(value, full_maximize, AFullMaximize); #ifdef XKB_BUTTON_HINT value = get_value(dw, dc, dn, da, ANoLanguageButton, No, useGlobalDefault); APPLY_VAL(value, no_language_button, ANoLanguageButton); #endif /* clean up */ WMPLSetCaseSensitive(False); } static WMPropList *get_generic_value(char *instance, char *class, WMPropList *option, Bool noDefault) { WMPropList *value, *key, *dict; value = NULL; WMPLSetCaseSensitive(True); /* Search the icon name using class and instance */ if (class && instance) { char *buffer; buffer = wmalloc(strlen(class) + strlen(instance) + 2); sprintf(buffer, "%s.%s", instance, class); key = WMCreatePLString(buffer); wfree(buffer); dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key); WMReleasePropList(key); if (dict) value = WMGetFromPLDictionary(dict, option); } /* Search the icon name using instance */ if (!value && instance) { key = WMCreatePLString(instance); dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key); WMReleasePropList(key); if (dict) value = WMGetFromPLDictionary(dict, option); } /* Search the icon name using class */ if (!value && class) { key = WMCreatePLString(class); dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key); WMReleasePropList(key); if (dict) value = WMGetFromPLDictionary(dict, option); } /* Search the default icon name - See noDefault argument! */ if (!value && !noDefault) { /* AnyWindow is "*" - see wdefaults.c */ dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, AnyWindow); if (dict) value = WMGetFromPLDictionary(dict, option); } WMPLSetCaseSensitive(False); return value; } /* Get the file name of the image, using instance and class */ char *get_default_icon_filename(WScreen *scr, char *winstance, char *wclass, char *command, Bool noDefault) { char *file_name = NULL; char *file_path = NULL; /* Get the file name of the image, using instance and class */ file_name = wDefaultGetIconFile(winstance, wclass, noDefault); /* If the specific (or generic if noDefault is False) icon filename * is not found, and command is specified, then include the .app icons * and re-do the search, but now always including the default icon * so the icon is found always. The .app is selected before default */ if (!file_name && scr && command) { wApplicationExtractDirPackIcon(scr, command, winstance, wclass); file_name = wDefaultGetIconFile(winstance, wclass, False); } /* Get the full path for the image file */ if (file_name) { file_path = FindImage(wPreferences.icon_path, file_name); if (!file_path) wwarning(_("could not find icon file \"%s\""), file_name); /* FIXME: Here, if file_path don't exists, then the icon is in the * "icon database" (WDWindowAttributes->dictionary), but the icon * is not en disk. Therefore, we should remove it from the icon * database. * OTOH, probably the correct message should be "could not find the * icon file %s, please, check your configuration files", because * the icons are loaded in the icon database from the configuration * files */ /* Don't wfree(file_name) here, because is a pointer to the icon * dictionary (WDWindowAttributes->dictionary) value. */ } return file_path; } /* This function returns the image picture for the file_name file */ RImage *get_default_icon_rimage(WScreen *scr, char *file_name, int max_size) { RImage *image = NULL; if (!file_name) return NULL; image = RLoadImage(scr->rcontext, file_name, 0); if (!image) wwarning(_("error loading image file \"%s\": %s"), file_name, RMessageForError(RErrorCode)); image = wIconValidateIconSize(image, max_size); return image; } RImage *wDefaultGetImage(WScreen * scr, char *winstance, char *wclass, int max_size) { char *file_name = NULL; /* Get the file name of the image, using instance and class */ file_name = get_default_icon_filename(scr, winstance, wclass, NULL, False); if (!file_name) return NULL; return get_default_icon_rimage(scr, file_name, max_size); } int wDefaultGetStartWorkspace(WScreen * scr, char *instance, char *class) { WMPropList *value; int w; char *tmp; if (!ANoTitlebar) init_wdefaults(); if (!WDWindowAttributes->dictionary) return -1; value = get_generic_value(instance, class, AStartWorkspace, False); if (!value) return -1; tmp = getString(AStartWorkspace, value); if (!tmp || strlen(tmp) == 0) return -1; /* Get the workspace number for the workspace name */ w = wGetWorkspaceNumber(scr, tmp); return w; } /* Get the name of the Icon File. If noDefault is False, then, default value included */ char *wDefaultGetIconFile(char *instance, char *class, Bool noDefault) { WMPropList *value; char *tmp; if (!ANoTitlebar) init_wdefaults(); if (!WDWindowAttributes || !WDWindowAttributes->dictionary) return NULL; value = get_generic_value(instance, class, AIcon, noDefault); if (!value) return NULL; tmp = getString(AIcon, value); return tmp; } void wDefaultChangeIcon(WScreen * scr, char *instance, char *class, char *file) { WDDomain *db = WDWindowAttributes; WMPropList *icon_value = NULL, *value, *attr, *key, *def_win, *def_icon = NULL; WMPropList *dict = db->dictionary; int same = 0; if (!dict) { dict = WMCreatePLDictionary(NULL, NULL); if (dict) db->dictionary = dict; else return; } WMPLSetCaseSensitive(True); if (instance && class) { char *buffer; buffer = StrConcatDot(instance, class); key = WMCreatePLString(buffer); wfree(buffer); } else if (instance) { key = WMCreatePLString(instance); } else if (class) { key = WMCreatePLString(class); } else { key = WMRetainPropList(AnyWindow); } if (file) { value = WMCreatePLString(file); icon_value = WMCreatePLDictionary(AIcon, value, NULL); WMReleasePropList(value); if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) def_icon = WMGetFromPLDictionary(def_win, AIcon); if (def_icon && !strcmp(WMGetFromPLString(def_icon), file)) same = 1; } if ((attr = WMGetFromPLDictionary(dict, key)) != NULL) { if (WMIsPLDictionary(attr)) { if (icon_value != NULL && !same) WMMergePLDictionaries(attr, icon_value, False); else WMRemoveFromPLDictionary(attr, AIcon); } } else if (icon_value != NULL && !same) { WMPutInPLDictionary(dict, key, icon_value); } if (!wPreferences.flags.noupdates) UpdateDomainFile(db); WMReleasePropList(key); if (icon_value) WMReleasePropList(icon_value); WMPLSetCaseSensitive(False); } /* --------------------------- Local ----------------------- */ static int getBool(WMPropList * key, WMPropList * value) { char *val; if (!WMIsPLString(value)) { wwarning(_("Wrong option format for key \"%s\". Should be %s."), WMGetFromPLString(key), "Boolean"); return 0; } val = WMGetFromPLString(value); if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1')) || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) { return 1; } else if ((val[1] == '\0' && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0')) || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) { return 0; } else { wwarning(_("can't convert \"%s\" to boolean"), val); /* We return False if we can't convert to BOOLEAN. * This is because all options defaults to False. * -1 is not checked and thus is interpreted as True, * which is not good.*/ return 0; } } /* WARNING: Do not free the value returned by this function!! */ static char *getString(WMPropList * key, WMPropList * value) { if (!WMIsPLString(value)) { wwarning(_("Wrong option format for key \"%s\". Should be %s."), WMGetFromPLString(key), "String"); return NULL; } return WMGetFromPLString(value); }