This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project wmaker-crm.git.
The branch, next has been updated via c2290ef404dcc2f437b93dd9bbfffb696cf867d4 (commit) via 103cd9a13e62a24f46afab12f388f8436dc075aa (commit) via ef5f542eceb18702b4880d010421fa101381210b (commit) via 41d7f7f513aa362004ddddee99a74f496c66da83 (commit) via f328bfcdd2ad594535a7c8b9190fcc7f47f76f51 (commit) via f36849c24891d3e0f0290d2d0952756636b5f6c6 (commit) via 8c32dd7d321e16dfe83e03e944affd148add2830 (commit) via 118993bfd7304249d1bb1a196710fd4d625a80ac (commit) via 1a75270c0a50ca339a476b47c542ccfddf86c79f (commit) via 67ed6a40b401173474e3b6b5fc4b2a1c6a00a796 (commit) from c3ba9aeba3a3b92b9d804d2f2b3d0518d0d2fd9a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://repo.or.cz/w/wmaker-crm.git/commit/c2290ef404dcc2f437b93dd9bbfffb696cf867d4 commit c2290ef404dcc2f437b93dd9bbfffb696cf867d4 Author: Christophe CURIS <christophe.cu...@free.fr> Date: Thu May 14 15:07:04 2015 +0200 wmaker-check: rewrote parsing of structure fields for callback checker Doug Torrance reported a problem with some versions of AWK which caused the signed/unsigned attribute to not be properly ignored, because the regular expression was using a GNU extension to keep it simple. While trying to reproduce it, I discovered that mawk was chocking on one regexp used in parsing the type+names parsing of structure members. This patch is rewriting the parsing, because hacking regexp to make them fall working is still not the best solution for maintainability. There is now a clearer code which is also safer because it will handle more gracefully corner cases. Reported-by: Doug Torrance <dtorra...@monmouthcollege.edu> Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/script/check-wmaker-loaddef-callbacks.sh b/script/check-wmaker-loaddef-callbacks.sh index 1cc9541..57d4cda 100755 --- a/script/check-wmaker-loaddef-callbacks.sh +++ b/script/check-wmaker-loaddef-callbacks.sh @@ -163,8 +163,8 @@ function parse_structure(prefix) { } # skip line that define nothing interresting - if (/^[ \t]*$/) { continue; } gsub(/^[ \t]+/, ""); + if (/^$/) { continue; } if (/^#/) { continue; } gsub(/[ \t]+$/, ""); @@ -198,39 +198,79 @@ function parse_structure(prefix) { print "Warning: line " FILENAME ":" NR " not understood inside struct" > "/dev/stderr"; continue; } + gsub(/;$/, ""); # Skip the lines that define a bit-field because they cannot be safely # pointed to anyway if (/:/) { continue; } - # It looks like a valid line, separate the name from the type - gsub(/;$/, ""); - name = $0; - gsub(/([A-Z_a-z][A-Z_a-z0-9]*([ \t]*,[ \t]*)*)*$/, ""); - name = substr(name, length($0) + 1); + separate_type_and_names(); # In some rare case we cannot extract the name, that is likely a function pointer type - if (name == "") { continue; } - - # Remove the sign specification because it is not a real problem - gsub(/\<(un)?signed\>/, " "); - if (/^[^A-Za-z]*$/) { - # If there is no more character, that means that the sign declaration was the only type specified, so - # we use the "int" type which is what C will use - $0 = "int " $0; + if (type == "") { continue; } + + # Save this information in an array + for (i = 1; i <= nb_names; i++) { + # If it is an array, push that information into the type + idx = index(name_list[i], "["); + if (idx > 0) { + member[prefix ":" substr(name_list[i], 1, idx-1) ] = type substr(name_list[i], idx); + } else { + member[prefix ":" name_list[i] ] = type; + } } + } +} - # Pack the type to have something consistent - gsub(/^[ \t]+/, ""); - gsub(/[ \t]+$/, ""); - gsub(/[ \t]*\*[ \t]*/, "*"); - gsub(/[ \t]+/, " "); +# Separate the declaration of an member of the struct: its type and the list of names +# The result is returned through variables "name_list + nb_names" and "type" +function separate_type_and_names() { + # Separate by names first + nb_names = split($0, name_list, /[ \t]*,[ \t]*/); + + # Separate the type from the 1st name + if (name_list[1] ~ /\]$/) { + idx = index(name_list[1], "[") - 1; + } else { + idx = length(name_list[1]); + } + while (substr(name_list[1], idx, 1) ~ /[A-Za-z_0-9]/) { idx--; } - # Save this information in an array - nb_vars = split(name, var_list, /[ \t]*,[ \t]*/); - for (i = 1; i <= nb_vars; i++) { - member[prefix ":" var_list[i] ] = $0; + type = substr(name_list[1], 1, idx); + name_list[1] = substr(name_list[1], idx + 1); + + if (type ~ /\(/) { + # If therese is a parenthesis in the type, that means we are parsing a function pointer + # declaration. This is not supported at current time (not needed), so we silently ignore + type = ""; + return; + } + + # Remove size information from array declarations + for (i in name_list) { + gsub(/\[[^\]]+\]/, "[]", name_list[i]); + } + + # Parse the type to make it into a "standard" format + gsub(/[ \t]+$/, "", type); + nb_elem = split(type, type_list, /[ \t]+/); + type = ""; + for (i = 1; i <= nb_elem; i++) { + if (type_list[i] == "signed" || type_list[i] == "unsigned") { + # The sign information is not a problem for pointer compatibility, so we do not keep it + continue; } + if (type_list[i] ~ /^\*+$/) { + # If we have a pointer mark by itself, we glue it to the previous keyword + type = type type_list[i]; + } else { + type = type " " type_list[i]; + } + } + gsub(/^ /, "", type); + if (type ~ /^\*/ || type == "") { + # We have a signed/unsigned without explicit "int" specification, add it now + type = "int" type; } } @@ -364,7 +404,7 @@ function extract_string_to_element() { return content "\""; } -# Wherever a long C comment (/* comment */) is encounter, it is discarded +# Wherever a long C comment (/* comment */) is encountered, it is discarded function skip_long_comment() { while (1) { idx = index($0, "*/"); http://repo.or.cz/w/wmaker-crm.git/commit/103cd9a13e62a24f46afab12f388f8436dc075aa commit 103cd9a13e62a24f46afab12f388f8436dc075aa Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:08 2015 +0200 Add a configuration option to ignore Decoration Hints from GTK-based application As reported by Nerijus Baliunas and Paul Jakma, the GNOME application, which use the GTK toolkit, are asking to have no window decoration. This can be solved by editing the window's attributes in Window Maker, but this can be tedious when there are many GNOME application used. This patch adds a configuration option: Window Maker tries to detect for GTK-based windows and in this case ignore the decoration hints that were provided by the application. Suggested-by: Paul Jakma <p...@jakma.org> Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/FAQ b/FAQ index c458080..79ac476 100644 --- a/FAQ +++ b/FAQ @@ -740,6 +740,11 @@ The workaround is, for each application, to ask for Window Maker's window menu and click on the greyed "Disable titlebar" until it is white (the same can be done for other decoration attributes). +If you use a lot of GNOME applications, you may want to ask Window Maker to just +ignore the no-titlebar-and-all for all windows at once, which is done from +WPrefs by going to the "Expert" panel and checking the "Ignore decoration hints +for GTK applications" button. + -=-=-=-=-=-=-=- diff --git a/NEWS b/NEWS index 172c970..6561c4e 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,16 @@ Mini-Preview name. The setting is configurable with WPrefs in the Icon Preferences tab, the size is now expressed in pixels directly. +Ignore Decoration Hints from GNOME applications +----------------------------------------------- + +The GNOME applications ask Window Maker to get no title bar and no resize bar to +their windows by using "Hints". You can re-add them using the Attribute dialog +in the Window menu, but if you are using many GNOME applications you may want to +tell Window Maker to just ignore them. This is done with the new setting called +"IgnoreGtkHints", which is available in the "Expert" panel in WPrefs. + + --- 0.95.6 More image format supported diff --git a/WPrefs.app/Expert.c b/WPrefs.app/Expert.c index 7268002..6db1dfa 100644 --- a/WPrefs.app/Expert.c +++ b/WPrefs.app/Expert.c @@ -43,6 +43,9 @@ static const struct { { N_("Disable miniwindows (icons for minimized windows). For use with KDE/GNOME."), /* default: */ False, OPTION_WMAKER, "DisableMiniwindows" }, + { N_("Ignore decoration hints for GTK applications."), + /* default: */ False, OPTION_WMAKER, "IgnoreGtkHints" }, + { N_("Disable workspace pager."), /* default: */ False, OPTION_WMAKER, "DisableWorkspacePager" }, diff --git a/src/WindowMaker.h b/src/WindowMaker.h index ccdb6c8..3c2869c 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -394,6 +394,7 @@ extern struct WPreferences { char dont_confirm_kill; /* do not confirm Kill application */ char disable_miniwindows; char disable_workspace_pager; + char ignore_gtk_decoration_hints; char dont_blink; /* do not blink icon selection */ @@ -558,6 +559,11 @@ extern struct wmaker_global_variables { Atom titlebar_state; } gnustep; + /* Destkop-environment related */ + struct { + Atom gtk_object_path; + } desktop; + /* WindowMaker specific */ struct { Atom menu; diff --git a/src/defaults.c b/src/defaults.c index b6e855c..70fbeb5 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -518,6 +518,8 @@ WDefaultEntry optionList[] = { &wPreferences.panel_only_open, getBool, NULL, NULL, NULL}, {"MiniPreviewSize", "128", NULL, &wPreferences.minipreview_size, getInt, NULL, NULL, NULL}, + {"IgnoreGtkHints", "NO", NULL, + &wPreferences.ignore_gtk_decoration_hints, getBool, NULL, NULL, NULL}, /* * Backward Compatibility: diff --git a/src/startup.c b/src/startup.c index 5f43cfd..8e633b8 100644 --- a/src/startup.c +++ b/src/startup.c @@ -394,6 +394,8 @@ static char *atomNames[] = { GNUSTEP_WM_MINIATURIZE_WINDOW, GNUSTEP_TITLEBAR_STATE, + "_GTK_APPLICATION_OBJECT_PATH", + "WM_IGNORE_FOCUS_EVENTS" }; @@ -467,7 +469,9 @@ void StartUp(Bool defaultScreenOnly) w_global.atom.gnustep.wm_miniaturize_window = atom[18]; w_global.atom.gnustep.titlebar_state = atom[19]; - w_global.atom.wm.ignore_focus_events = atom[20]; + w_global.atom.desktop.gtk_object_path = atom[20]; + + w_global.atom.wm.ignore_focus_events = atom[21]; #ifdef USE_DOCK_XDND wXDNDInitializeAtoms(); diff --git a/src/window.c b/src/window.c index b1cbd30..532670c 100644 --- a/src/window.c +++ b/src/window.c @@ -288,6 +288,31 @@ static void setupGNUstepHints(WWindow *wwin, GNUstepWMAttributes *gs_hints) wwin->client_flags.no_appicon = 1; } +static void discard_hints_from_gtk(WWindow *wwin) +{ + Atom type; + int format; + unsigned long nb_item, nb_remain; + unsigned char *result; + int status; + + status = XGetWindowProperty(dpy, wwin->client_win, w_global.atom.desktop.gtk_object_path, 0, 16, False, + AnyPropertyType, &type, &format, &nb_item, &nb_remain, &result); + if (status != Success) + return; + + /* If we're here, that means the Property exists. We don't care what is inside, it means it is a GTK-based application */ + + if (result != NULL) + XFree(result); + + /* GTK is asking to remove these decorations: */ + wwin->client_flags.no_titlebar = 0; + wwin->client_flags.no_close_button = 0; + wwin->client_flags.no_miniaturize_button = 0; + wwin->client_flags.no_resizebar = 0; +} + void wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) { WScreen *scr = wwin->screen_ptr; @@ -351,6 +376,9 @@ void wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) wNETWMCheckClientHints(wwin, &tmp_level, &tmp_workspace); + if (wPreferences.ignore_gtk_decoration_hints) + discard_hints_from_gtk(wwin); + /* window levels are between INT_MIN+1 and INT_MAX, so if we still * have INT_MIN that means that no window level was requested. -Dan */ http://repo.or.cz/w/wmaker-crm.git/commit/ef5f542eceb18702b4880d010421fa101381210b commit ef5f542eceb18702b4880d010421fa101381210b Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:07 2015 +0200 doc: describe the GNOME application issue in the FAQ Now that Window Maker have been fixed to allow the user to properly control and save the title bar/resize bar/other decoration settings on the window, describe the problem reported (first) by Nerijus Baliunas, so more people may find the answer. Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/FAQ b/FAQ index 985e861..c458080 100644 --- a/FAQ +++ b/FAQ @@ -60,6 +60,7 @@ Summary of Contents: fonts. 3.10 When I set the root background with wmsetbg by hand it works, but when I do that from the configuration files it doesn't! + 3.11 When I run GNOME application they have no title bar. 4 - Configuration 4.1 What are those files inside my ~/GNUstep directory? @@ -345,7 +346,10 @@ The same is true for CDE. Now, answering the question: Yes, you can use WindowMaker in these environments. To use Window Maker with GNOME, you don't need to do -anything special. To use it with CDE, read the answer for "How do I switch +anything special, although you may want to look at the "When I run +GNOME application they have no title bar" below. + +To use it with CDE, read the answer for "How do I switch CDE's window manager to use Window Maker?" To use it with KDE, read it's documentation to get rid of kwm (and possibly @@ -724,6 +728,20 @@ These directories will be listed under the "Search Path" section of WPrefs. +3.11 When I run GNOME application they have no title bar. +---------------------------------- + +The GNOME toolkit decided to behave his own way, so it draws its own title bar +with buttons, and asks Window Maker to not draw anything (title bar, resize bar, +close and miniaturise button, ...). + +The workaround is, for each application, to ask for Window Maker's window menu +(that is likely <Ctrl>+<Escape> if you did not change it), get the Attributes, +and click on the greyed "Disable titlebar" until it is white (the same can be +done for other decoration attributes). + + + -=-=-=-=-=-=-=- Configuration: -=-=-=-=-=-=-=- http://repo.or.cz/w/wmaker-crm.git/commit/41d7f7f513aa362004ddddee99a74f496c66da83 commit 41d7f7f513aa362004ddddee99a74f496c66da83 Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:06 2015 +0200 wmaker: fix clearing of window attribute that was not saved properly As reported by Nerijus Baliunas, there was a problem when unchecking an attribute in the Window Inspector and saving it. The original code was meant to save an attribute that is being checked by user, but not one that is explicitly unchecked, which means than although it looked ok when using the "Apply" button, it was not remembered when restarting the application. In continuation to the clean-up started in the previous patches, this one is updating the Window Inspector to display 2 check-boxes, one read-only on the left, displaying the state requested by the application, and a second one which makes use of the new Tri-State button in WINGs to let the user specify if he wants to force-on, force-off, or leave as-is the attribute. The saving to the property list is then updated to take into account this new 3-state when saving to the file, so relaunching the application will remember correctly the user choice. Reported-by: Nerijus Baliunas <neri...@users.sourceforge.net> Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/src/winspector.c b/src/winspector.c index 9666363..0735caf 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -203,6 +203,7 @@ typedef struct InspectorPanel { /* second page. attributes */ WMFrame *attrFrm; + WMButton *attrClient[sizeof(window_attribute) / sizeof(window_attribute[0])]; WMButton *attrChk[sizeof(window_attribute) / sizeof(window_attribute[0])]; /* 3rd page. more attributes */ @@ -642,8 +643,27 @@ static void saveSettings(WMWidget *button, void *client_data) /* Attributes... --> Window Attributes */ for (i = 0; i < wlengthof(window_attribute); i++) { - value = (WMGetButtonSelected(panel->attrChk[i]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, pl_attribute[i], value, flags); + WMPropList *old_value; + int state; + + old_value = WMGetFromPLDictionary(winDic, pl_attribute[i]); + state = WMGetButtonSelected(panel->attrChk[i]); + if (state > 0) { + if ((old_value == NULL) || !getBool(old_value)) { + WMPutInPLDictionary(winDic, pl_attribute[i], Yes); + different |= 1; + } + } else if (state == 0) { + if ((old_value == NULL) || getBool(old_value)) { + WMPutInPLDictionary(winDic, pl_attribute[i], No); + different |= 1; + } + } else { /* (state < 0) */ + if (old_value != NULL) { + WMRemoveFromPLDictionary(winDic, pl_attribute[i]); + different |= 1; + } + } } /* Attributes... --> Advanced Options */ @@ -726,12 +746,19 @@ static void applySettings(WMWidget *button, void *client_data) /* Attributes... --> Window Attributes */ for (i = 0; i < wlengthof(window_attribute); i++) { - if (WMGetButtonSelected(panel->attrChk[i])) + int state; + + state = WMGetButtonSelected(panel->attrChk[i]); + + if (state > 0) set_attr_flag(&wwin->user_flags, &window_attribute[i].flag); else clear_attr_flag(&wwin->user_flags, &window_attribute[i].flag); - set_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag); + if (state < 0) + clear_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag); + else + set_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag); } /* Attributes... --> Advanced Options */ @@ -904,7 +931,7 @@ static void revertSettings(WMWidget *button, void *client_data) if (is_userdef) flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag); else - flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag); + flag = -1; WMSetButtonSelected(panel->attrChk[i], flag); } @@ -1315,15 +1342,31 @@ static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, i for (i = 0; i < wlengthof(window_attribute); i++) { int is_userdef, flag; + /* Read-only button to display the state requested by the application */ + flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag); + + panel->attrClient[i] = WMCreateSwitchButton(panel->attrFrm); + WMMoveWidget(panel->attrClient[i], 10, 20 * (i + 1)); + WMResizeWidget(panel->attrClient[i], 20, 20); + WMSetButtonText(panel->attrClient[i], NULL); + WMSetButtonSelected(panel->attrClient[i], flag); + WMSetButtonEnabled(panel->attrClient[i], False); + + WMSetBalloonTextForView(_("Show the state that was asked by the application.\n" + "You can use the checkbox on the right to change this setting;\n" + "when it is grayed it means to follow application's choice."), + WMWidgetView(panel->attrClient[i])); + + /* Button to let user override this choice */ is_userdef = get_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag); if (is_userdef) flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag); else - flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag); + flag = -1; - panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm); - WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1)); - WMResizeWidget(panel->attrChk[i], frame_width - 15, 20); + panel->attrChk[i] = WMCreateButton(panel->attrFrm, WBTTriState); + WMMoveWidget(panel->attrChk[i], 30, 20 * (i + 1)); + WMResizeWidget(panel->attrChk[i], frame_width - 45, 20); WMSetButtonSelected(panel->attrChk[i], flag); WMSetButtonText(panel->attrChk[i], _(window_attribute[i].caption)); http://repo.or.cz/w/wmaker-crm.git/commit/f328bfcdd2ad594535a7c8b9190fcc7f47f76f51 commit f328bfcdd2ad594535a7c8b9190fcc7f47f76f51 Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:05 2015 +0200 WINGs: create a new type of Tri-State Switch Button (to doc) There are some times when we need a Switch Button (aka CheckBox) with more than 2 states, generally to express check/uncheck/leave-as-is. This patch extends the Button widget to support the new WBTTriState type, similar to the existing WBTSwitch except it supports a 3rd state which is reported to application as '-1'. The implementation was done in order to not break the binary API. The version have been incremented in the WINGs header to reflect the change, but not the version in the 'configure.ac' because that have already been done in commit c6e323e75d for the next Window Maker release. Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/WINGs/WINGs/WINGs.h b/WINGs/WINGs/WINGs.h index 4798174..5235c20 100644 --- a/WINGs/WINGs/WINGs.h +++ b/WINGs/WINGs/WINGs.h @@ -26,7 +26,7 @@ #include <WINGs/WUtil.h> #include <X11/Xlib.h> -#define WINGS_H_VERSION 20141205 +#define WINGS_H_VERSION 20150508 #ifdef __cplusplus @@ -127,7 +127,8 @@ typedef enum { WBTRadio = 5, WBTMomentaryChange = 6, WBTOnOff = 7, - WBTMomentaryLight = 8 + WBTMomentaryLight = 8, + WBTTriState = 9 } WMButtonType; /* button behaviour masks */ diff --git a/WINGs/WINGs/WINGsP.h b/WINGs/WINGs/WINGsP.h index fc18b1c..4cbe0fc 100644 --- a/WINGs/WINGs/WINGsP.h +++ b/WINGs/WINGs/WINGsP.h @@ -268,6 +268,16 @@ typedef struct W_Screen { struct W_View *modalView; unsigned modalLoop:1; unsigned ignoreNextDoubleClick:1; + + /* + * New stuff in Window Maker 0.95.7 + * Added at the end of the structure to avoid breaking binary compatibility + * with previous versions of the toolkit + */ + W_Pixmap *tristateButtonImageOn; + W_Pixmap *tristateButtonImageOff; + W_Pixmap *tristateButtonImageTri; + } W_Screen; #define W_DRAWABLE(scr) (scr)->rcontext->drawable diff --git a/WINGs/wbutton.c b/WINGs/wbutton.c index 8c8e4dc..c8d78d9 100644 --- a/WINGs/wbutton.c +++ b/WINGs/wbutton.c @@ -17,6 +17,7 @@ typedef struct W_Button { W_Pixmap *image; W_Pixmap *altImage; + W_Pixmap *tsImage; W_Pixmap *dimage; @@ -37,7 +38,7 @@ typedef struct W_Button { WMImagePosition imagePosition:4; WMAlignment alignment:2; - unsigned int selected:1; + unsigned int selected:2; unsigned int enabled:1; @@ -183,6 +184,14 @@ WMButton *WMCreateButton(WMWidget * parent, WMButtonType type) bPtr->altImage = WMRetainPixmap(scrPtr->radioButtonImageOn); break; + case WBTTriState: + bPtr = WMCreateCustomButton(parent, WBBStateChangeMask); + bPtr->flags.bordered = 0; + bPtr->image = WMRetainPixmap(scrPtr->tristateButtonImageOff); + bPtr->altImage = WMRetainPixmap(scrPtr->tristateButtonImageOn); + bPtr->tsImage = WMRetainPixmap(scrPtr->tristateButtonImageTri); + break; + default: case WBTMomentaryLight: bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask | WBBPushLightMask); @@ -197,7 +206,7 @@ WMButton *WMCreateButton(WMWidget * parent, WMButtonType type) WMSetButtonText(bPtr, DEFAULT_RADIO_TEXT); bPtr->flags.alignment = DEFAULT_RADIO_ALIGNMENT; bPtr->flags.imagePosition = DEFAULT_RADIO_IMAGE_POSITION; - } else if (type == WBTSwitch) { + } else if (type == WBTSwitch || type == WBTTriState) { W_ResizeView(bPtr->view, DEFAULT_SWITCH_WIDTH, DEFAULT_SWITCH_HEIGHT); WMSetButtonText(bPtr, DEFAULT_SWITCH_TEXT); bPtr->flags.alignment = DEFAULT_SWITCH_ALIGNMENT; @@ -371,7 +380,10 @@ void WMSetButtonDisabledTextColor(WMButton * bPtr, WMColor * color) void WMSetButtonSelected(WMButton * bPtr, int isSelected) { - bPtr->flags.selected = isSelected ? 1 : 0; + if ((bPtr->flags.type == WBTTriState) && (isSelected < 0)) + bPtr->flags.selected = 2; + else + bPtr->flags.selected = isSelected ? 1 : 0; if (bPtr->view->flags.realized) { paintButton(bPtr); @@ -384,6 +396,9 @@ int WMGetButtonSelected(WMButton * bPtr) { CHECK_CLASS(bPtr, WC_Button); + if ((bPtr->flags.type == WBTTriState) && (bPtr->flags.selected == 2)) + return -1; + return bPtr->flags.selected; } @@ -558,7 +573,9 @@ static void paintButton(Button * bPtr) if (bPtr->flags.stateChange) { if (bPtr->altCaption) caption = bPtr->altCaption; - if (bPtr->altImage) + if (bPtr->flags.selected == 2) + image = bPtr->tsImage; + else if (bPtr->altImage) image = bPtr->altImage; if (bPtr->altTextColor) textColor = bPtr->altTextColor; @@ -659,6 +676,8 @@ static void handleActionEvents(XEvent * event, void *data) case ButtonPress: if (event->xbutton.button == Button1) { + static const unsigned int next_state[4] = { [0] = 1, [1] = 2, [2] = 0 }; + bPtr->flags.prevSelected = bPtr->flags.selected; bPtr->flags.wasPushed = 0; bPtr->flags.pushed = 1; @@ -667,7 +686,10 @@ static void handleActionEvents(XEvent * event, void *data) dopaint = 1; break; } - bPtr->flags.selected = !bPtr->flags.selected; + if (bPtr->flags.type == WBTTriState) + bPtr->flags.selected = next_state[bPtr->flags.selected]; + else + bPtr->flags.selected = !bPtr->flags.selected; dopaint = 1; if (bPtr->flags.continuous && !bPtr->timer) { @@ -748,5 +770,8 @@ static void destroyButton(Button * bPtr) if (bPtr->altImage) WMReleasePixmap(bPtr->altImage); + if (bPtr->tsImage) + WMReleasePixmap(bPtr->tsImage); + wfree(bPtr); } diff --git a/WINGs/widgets.c b/WINGs/widgets.c index 4c9c687..177ad3c 100644 --- a/WINGs/widgets.c +++ b/WINGs/widgets.c @@ -97,6 +97,66 @@ static char *RADIO_BUTTON_OFF[] = { "..... .....", }; +#define TRISTATE_BUTTON_ON_WIDTH 15 +#define TRISTATE_BUTTON_ON_HEIGHT 15 +static char *TRISTATE_BUTTON_ON[] = { + "%%%%%%%%%%%%%%.", + "%%%%%%%%%%%%%. ", + "%% . ", + "%% ## ## . ", + "%% ### ### . ", + "%% ### ### . ", + "%% ##### . ", + "%% ### . ", + "%% ##### . ", + "%% ### ### . ", + "%% ### ### . ", + "%% ## ## . ", + "%% . ", + "%............. ", + ". ", +}; + +#define TRISTATE_BUTTON_OFF_WIDTH 15 +#define TRISTATE_BUTTON_OFF_HEIGHT 15 +static char *TRISTATE_BUTTON_OFF[] = { + "%%%%%%%%%%%%%%.", + "%%%%%%%%%%%%%. ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%% . ", + "%............. ", + ". ", +}; + +#define TRISTATE_BUTTON_TRI_WIDTH 15 +#define TRISTATE_BUTTON_TRI_HEIGHT 15 +static char *TRISTATE_BUTTON_TRI[] = { + "%%%%%%%%%%%%%%.", + "%%%%%%%%%%%%%. ", + "%% . ", + "%% # # # # # . ", + "%% # # # # . ", + "%% # # # # # . ", + "%% # # # # . ", + "%% # # # # # . ", + "%% # # # # . ", + "%% # # # # # . ", + "%% # # # # . ", + "%% # # # # # . ", + "%% . ", + "%............. ", + ". ", +}; + static char *BUTTON_ARROW[] = { "..................", "....##....#### ...", @@ -729,6 +789,15 @@ WMScreen *WMCreateScreenWithRContext(Display * display, int screen, RContext * c scrPtr->radioButtonImageOff = makePixmap(scrPtr, RADIO_BUTTON_OFF, RADIO_BUTTON_OFF_WIDTH, RADIO_BUTTON_OFF_HEIGHT, False); + scrPtr->tristateButtonImageOn = makePixmap(scrPtr, TRISTATE_BUTTON_ON, + TRISTATE_BUTTON_ON_WIDTH, TRISTATE_BUTTON_ON_HEIGHT, False); + + scrPtr->tristateButtonImageOff = makePixmap(scrPtr, TRISTATE_BUTTON_OFF, + TRISTATE_BUTTON_OFF_WIDTH, TRISTATE_BUTTON_OFF_HEIGHT, False); + + scrPtr->tristateButtonImageTri = makePixmap(scrPtr, TRISTATE_BUTTON_TRI, + TRISTATE_BUTTON_TRI_WIDTH, TRISTATE_BUTTON_TRI_HEIGHT, False); + scrPtr->buttonArrow = makePixmap(scrPtr, BUTTON_ARROW, BUTTON_ARROW_WIDTH, BUTTON_ARROW_HEIGHT, False); scrPtr->pushedButtonArrow = makePixmap(scrPtr, BUTTON_ARROW2, http://repo.or.cz/w/wmaker-crm.git/commit/f36849c24891d3e0f0290d2d0952756636b5f6c6 commit f36849c24891d3e0f0290d2d0952756636b5f6c6 Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:04 2015 +0200 wmaker: honour MWM Hint to have no border to a window As there is already an attribute to allow changing this behaviour, and this is being using for the Net WM hints, there is no reason to not support it for MWM Hints also; contrary to the initial guess suggested by the comment it costs actually nothing to properly support that. Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/src/motif.c b/src/motif.c index 6537038..34f6847 100644 --- a/src/motif.c +++ b/src/motif.c @@ -93,13 +93,7 @@ static void setupMWMHints(WWindow *wwin, MWMHints *mwm_hints) } if (mwm_hints->decorations & MWM_DECOR_BORDER) { - /* - * WindowMaker is drawing only a discreet 1 pixel border without - * any decoration like a few other X window managers used to do, so - * we assume it is not worth spending the time to add extra - * complexity to handle this special request, considering also that - * the Motif toolkit is not used anymore nowadays. - */ + wwin->client_flags.no_border = 0; } if (mwm_hints->decorations & MWM_DECOR_RESIZEH) http://repo.or.cz/w/wmaker-crm.git/commit/8c32dd7d321e16dfe83e03e944affd148add2830 commit 8c32dd7d321e16dfe83e03e944affd148add2830 Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:03 2015 +0200 wmaker: fix misuse of 'user_flags' instead of 'client_flags' for window attributes The structure containing the information on windows contains 2 sets of attributes, client_flags which contains those asked by the application through Hints (like MWM Hints and others) and user_flags which was defined to allow the user to override them. Unfortunately many places of the code was using the wrong structure to save the attributes to (for example by using the WSETUFLAG macro) which was merely ok as the user_flags have priority, but when we want to provide a clean consistent behaviour to users, we need to get things in the right place. Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/src/client.c b/src/client.c index 9af875c..92912b9 100644 --- a/src/client.c +++ b/src/client.c @@ -524,14 +524,14 @@ void wClientCheckProperty(WWindow * wwin, XPropertyEvent * event) wwin->transient_for = new_owner; if (new_owner == None) { if (WFLAGP(wwin, no_miniaturizable)) { - WSETUFLAG(wwin, no_miniaturizable, 0); - WSETUFLAG(wwin, no_miniaturize_button, 0); + wwin->client_flags.no_miniaturizable = 0; + wwin->client_flags.no_miniaturize_button = 0; if (wwin->frame) wWindowConfigureBorders(wwin); } } else if (!WFLAGP(wwin, no_miniaturizable)) { - WSETUFLAG(wwin, no_miniaturizable, 1); - WSETUFLAG(wwin, no_miniaturize_button, 1); + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_miniaturize_button = 1; if (wwin->frame) wWindowConfigureBorders(wwin); } @@ -544,7 +544,7 @@ void wClientCheckProperty(WWindow * wwin, XPropertyEvent * event) PropGetProtocols(wwin->client_win, &wwin->protocols); - WSETUFLAG(wwin, kill_close, !wwin->protocols.DELETE_WINDOW); + wwin->client_flags.kill_close = !wwin->protocols.DELETE_WINDOW; if (wwin->frame) wWindowUpdateButtonImages(wwin); @@ -572,7 +572,7 @@ void wClientCheckProperty(WWindow * wwin, XPropertyEvent * event) wApplicationDestroy(wapp); while (foo) { if (foo->fake_group && foo->fake_group == fPtr) { - WSETUFLAG(foo, shared_appicon, 0); + foo->client_flags.shared_appicon = 0; foo->fake_group = NULL; if (foo->group_id != None) diff --git a/src/motif.c b/src/motif.c index b649f82..6537038 100644 --- a/src/motif.c +++ b/src/motif.c @@ -75,19 +75,21 @@ static void setupMWMHints(WWindow *wwin, MWMHints *mwm_hints) */ if (mwm_hints->flags & MWM_HINTS_DECORATIONS) { - WSETUFLAG(wwin, no_titlebar, 1); - WSETUFLAG(wwin, no_close_button, 1); - WSETUFLAG(wwin, no_miniaturize_button, 1); - WSETUFLAG(wwin, no_resizebar, 1); + wwin->client_flags.no_titlebar = 1; + wwin->client_flags.no_close_button = 1; + wwin->client_flags.no_miniaturize_button = 1; + wwin->client_flags.no_resizebar = 1; + wwin->client_flags.no_border = 1; if (mwm_hints->decorations & MWM_DECOR_ALL) { - WSETUFLAG(wwin, no_titlebar, 0); - WSETUFLAG(wwin, no_close_button, 0); - WSETUFLAG(wwin, no_closable, 0); - WSETUFLAG(wwin, no_miniaturize_button, 0); - WSETUFLAG(wwin, no_miniaturizable, 0); - WSETUFLAG(wwin, no_resizebar, 0); - WSETUFLAG(wwin, no_resizable, 0); + wwin->client_flags.no_titlebar = 0; + wwin->client_flags.no_close_button = 0; + wwin->client_flags.no_closable = 0; + wwin->client_flags.no_miniaturize_button = 0; + wwin->client_flags.no_miniaturizable = 0; + wwin->client_flags.no_resizebar = 0; + wwin->client_flags.no_resizable = 0; + wwin->client_flags.no_border = 0; } if (mwm_hints->decorations & MWM_DECOR_BORDER) { @@ -101,12 +103,12 @@ static void setupMWMHints(WWindow *wwin, MWMHints *mwm_hints) } if (mwm_hints->decorations & MWM_DECOR_RESIZEH) - WSETUFLAG(wwin, no_resizebar, 0); + wwin->client_flags.no_resizebar = 0; if (mwm_hints->decorations & MWM_DECOR_TITLE) { - WSETUFLAG(wwin, no_titlebar, 0); - WSETUFLAG(wwin, no_close_button, 0); - WSETUFLAG(wwin, no_closable, 0); + wwin->client_flags.no_titlebar = 0; + wwin->client_flags.no_close_button = 0; + wwin->client_flags.no_closable = 0; } if (mwm_hints->decorations * MWM_DECOR_MENU) { @@ -119,8 +121,8 @@ static void setupMWMHints(WWindow *wwin, MWMHints *mwm_hints) } if (mwm_hints->decorations & MWM_DECOR_MINIMIZE) { - WSETUFLAG(wwin, no_miniaturize_button, 0); - WSETUFLAG(wwin, no_miniaturizable, 0); + wwin->client_flags.no_miniaturize_button = 0; + wwin->client_flags.no_miniaturizable = 0; } if (mwm_hints->decorations & MWM_DECOR_MAXIMIZE) { @@ -132,17 +134,17 @@ static void setupMWMHints(WWindow *wwin, MWMHints *mwm_hints) } if (mwm_hints->flags & MWM_HINTS_FUNCTIONS) { - WSETUFLAG(wwin, no_closable, 1); - WSETUFLAG(wwin, no_miniaturizable, 1); - WSETUFLAG(wwin, no_resizable, 1); + wwin->client_flags.no_closable = 1; + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_resizable = 1; if (mwm_hints->functions & MWM_FUNC_ALL) { - WSETUFLAG(wwin, no_closable, 0); - WSETUFLAG(wwin, no_miniaturizable, 0); - WSETUFLAG(wwin, no_resizable, 0); + wwin->client_flags.no_closable = 0; + wwin->client_flags.no_miniaturizable = 0; + wwin->client_flags.no_resizable = 0; } if (mwm_hints->functions & MWM_FUNC_RESIZE) - WSETUFLAG(wwin, no_resizable, 0); + wwin->client_flags.no_resizable = 0; if (mwm_hints->functions & MWM_FUNC_MOVE) { /* @@ -152,14 +154,14 @@ static void setupMWMHints(WWindow *wwin, MWMHints *mwm_hints) } if (mwm_hints->functions & MWM_FUNC_MINIMIZE) - WSETUFLAG(wwin, no_miniaturizable, 0); + wwin->client_flags.no_miniaturizable = 0; if (mwm_hints->functions & MWM_FUNC_MAXIMIZE) { /* a window must be resizable to be maximizable */ - WSETUFLAG(wwin, no_resizable, 0); + wwin->client_flags.no_resizable = 0; } if (mwm_hints->functions & MWM_FUNC_CLOSE) - WSETUFLAG(wwin, no_closable, 0); + wwin->client_flags.no_closable = 0; } } diff --git a/src/window.c b/src/window.c index 7cbad9c..b1cbd30 100644 --- a/src/window.c +++ b/src/window.c @@ -293,7 +293,9 @@ void wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) WScreen *scr = wwin->screen_ptr; /* sets global default stuff */ - wDefaultFillAttributes(wwin->wm_instance, wwin->wm_class, &wwin->client_flags, NULL, True); + wDefaultFillAttributes(wwin->wm_instance, wwin->wm_class, &wwin->user_flags, NULL, True); + wwin->defined_user_flags = wwin->user_flags; + /* * Decoration setting is done in this precedence (lower to higher) * - use global default in the resource database @@ -302,25 +304,25 @@ void wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) * - set hints specified for the app in the resource DB * */ - WSETUFLAG(wwin, broken_close, 0); + wwin->client_flags.broken_close = 0; if (wwin->protocols.DELETE_WINDOW) - WSETUFLAG(wwin, kill_close, 0); + wwin->client_flags.kill_close = 0; else - WSETUFLAG(wwin, kill_close, 1); + wwin->client_flags.kill_close = 1; /* transients can't be iconified or maximized */ if (wwin->transient_for != None && wwin->transient_for != scr->root_win) { - WSETUFLAG(wwin, no_miniaturizable, 1); - WSETUFLAG(wwin, no_miniaturize_button, 1); + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_miniaturize_button = 1; } /* if the window can't be resized, remove the resizebar */ if (wwin->normal_hints->flags & (PMinSize | PMaxSize) && (wwin->normal_hints->min_width == wwin->normal_hints->max_width) && (wwin->normal_hints->min_height == wwin->normal_hints->max_height)) { - WSETUFLAG(wwin, no_resizable, 1); - WSETUFLAG(wwin, no_resizebar, 1); + wwin->client_flags.no_resizable = 1; + wwin->client_flags.no_resizebar = 1; } /* set GNUstep window attributes */ @@ -401,7 +403,9 @@ void wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) && wwin->user_flags.floating && wwin->defined_user_flags.floating) wwin->user_flags.sunken = 0; - WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar)); + /* A window that does not have a title cannot be Shaded and we don't let user override this */ + wwin->client_flags.no_shadeable = WFLAGP(wwin, no_titlebar); + wwin->defined_user_flags.no_shadeable = 0; /* windows that have takefocus=False shouldn't take focus at all */ if (wwin->focus_mode == WFM_NO_INPUT) @@ -724,22 +728,22 @@ WWindow *wManageWindow(WScreen *scr, Window window) wwin->orig_main_window = wwin->main_window; if (wwin->flags.is_gnustep) - WSETUFLAG(wwin, shared_appicon, 0); + wwin->client_flags.shared_appicon = 0; if (wwin->main_window) { XTextProperty text_prop; if (XGetTextProperty(dpy, wwin->main_window, &text_prop, w_global.atom.wmaker.menu)) - WSETUFLAG(wwin, shared_appicon, 0); + wwin->client_flags.shared_appicon = 0; } if (wwin->flags.is_dockapp) - WSETUFLAG(wwin, shared_appicon, 0); + wwin->client_flags.shared_appicon = 0; if (wwin->main_window) { WApplication *app = wApplicationOf(wwin->main_window); if (app && app->app_icon) - WSETUFLAG(wwin, shared_appicon, 0); + wwin->client_flags.shared_appicon = 0; } if (!withdraw && wwin->main_window && WFLAGP(wwin, shared_appicon)) { @@ -1320,10 +1324,10 @@ WWindow *wManageInternalWindow(WScreen *scr, Window window, Window owner, wwin->flags.internal_window = 1; - WSETUFLAG(wwin, omnipresent, 1); - WSETUFLAG(wwin, no_shadeable, 1); - WSETUFLAG(wwin, no_resizable, 1); - WSETUFLAG(wwin, no_miniaturizable, 1); + wwin->client_flags.omnipresent = 1; + wwin->client_flags.no_shadeable = 1; + wwin->client_flags.no_resizable = 1; + wwin->client_flags.no_miniaturizable = 1; wwin->focus_mode = WFM_PASSIVE; wwin->client_win = window; diff --git a/src/winspector.c b/src/winspector.c index edfa8d0..9666363 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -1241,8 +1241,8 @@ static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypo /* kluge to know who should get the key events */ panel->frame->client_leader = WMWidgetXID(panel->win); - WSETUFLAG(panel->frame, no_closable, 0); - WSETUFLAG(panel->frame, no_close_button, 0); + panel->frame->client_flags.no_closable = 0; + panel->frame->client_flags.no_close_button = 0; wWindowUpdateButtonImages(panel->frame); wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON); panel->frame->frame->on_click_right = destroyInspector; http://repo.or.cz/w/wmaker-crm.git/commit/118993bfd7304249d1bb1a196710fd4d625a80ac commit 118993bfd7304249d1bb1a196710fd4d625a80ac Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:02 2015 +0200 wmaker: moved the list of Application Attributes into an array, for the Window Inspector The Window Inspector is used to let user change a list of advanced options for all the windows of an application. This list was defined through many hard-coded things; by defining an array with everything at the beginning of the file it is easier to maintain (the code is simpler because it is more generic) and to make it evolve. Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/src/winspector.c b/src/winspector.c index 16ab168..edfa8d0 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -162,6 +162,20 @@ static const struct { ,{ "NoLanguageButton", { .no_language_button = 1 }, M_("Disable language button"), M_("Remove the `toggle language' button of the window.") } #endif + +}, application_attr[] = { + { "StartHidden", { .start_hidden = 1 }, M_("Start hidden"), + M_("Automatically hide application when it's started.") }, + + { "NoAppIcon", { .no_appicon = 1 }, M_("No application icon"), + M_("Disable the application icon for the application.\n" + "Note that you won't be able to dock it anymore,\n" + "and any icons that are already docked will stop\n" + "working correctly.") }, + + { "SharedAppIcon", { .shared_appicon = 1 }, M_("Shared application icon"), + M_("Use a single shared application icon for all of\n" + "the instances of this application.\n") } }; typedef struct InspectorPanel { @@ -207,7 +221,7 @@ typedef struct InspectorPanel { /* 5th page. application wide attributes */ WMFrame *appFrm; - WMButton *appChk[3]; + WMButton *appChk[sizeof(application_attr) / sizeof(application_attr[0])]; unsigned int done:1; unsigned int destroyed:1; @@ -225,15 +239,13 @@ static InspectorPanel *panelList = NULL; */ static WMPropList *pl_attribute[sizeof(window_attribute) / sizeof(window_attribute[0])] = { [0] = NULL }; static WMPropList *pl_advoptions[sizeof(advanced_option) / sizeof(advanced_option[0])]; +static WMPropList *pl_appattrib[sizeof(application_attr) / sizeof(application_attr[0])]; -static WMPropList *ANoAppIcon; static WMPropList *AAlwaysUserIcon; -static WMPropList *ASharedAppIcon; static WMPropList *AStartWorkspace; static WMPropList *AIcon; /* application wide options */ -static WMPropList *AStartHidden; static WMPropList *AnyWindow; static WMPropList *EmptyString; static WMPropList *Yes, *No; @@ -311,11 +323,11 @@ static void make_keys(void) for (i = 0; i < wlengthof(advanced_option); i++) pl_advoptions[i] = WMCreatePLString(advanced_option[i].key_name); + for (i = 0; i < wlengthof(application_attr); i++) + pl_appattrib[i] = WMCreatePLString(application_attr[i].key_name); + AIcon = WMCreatePLString("Icon"); - ANoAppIcon = WMCreatePLString("NoAppIcon"); AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon"); - AStartHidden = WMCreatePLString("StartHidden"); - ASharedAppIcon = WMCreatePLString("SharedAppIcon"); AStartWorkspace = WMCreatePLString("StartWorkspace"); @@ -640,15 +652,12 @@ static void saveSettings(WMWidget *button, void *client_data) different |= insertAttribute(dict, winDic, pl_advoptions[i], value, flags); } + /* Attributes... --> Application Specific */ if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) { - value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No; - different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags); - - value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No; - different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags); - - value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No; - different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags); + for (i = 0; i < wlengthof(application_attr); i++) { + value = (WMGetButtonSelected(panel->appChk[i]) != 0) ? Yes : No; + different2 |= insertAttribute(dict, appDic, pl_appattrib[i], value, flags); + } } if (wwin->fake_group) { @@ -780,9 +789,14 @@ static void applySettings(WMWidget *button, void *client_data) /* Can't apply emulate_appicon because it will probably cause problems. */ if (wapp) { /* do application wide stuff */ - WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0])); - WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1])); - WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2])); + for (i = 0; i < wlengthof(application_attr); i++) { + if (WMGetButtonSelected(panel->appChk[i])) + set_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag); + else + clear_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag); + + set_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag); + } if (WFLAGP(wapp->main_window_desc, no_appicon)) unpaint_app_icon(wapp); @@ -907,21 +921,18 @@ static void revertSettings(WMWidget *button, void *client_data) WMSetButtonSelected(panel->moreChk[i], flag); } + + /* Attributes... --> Application Specific */ if (panel->appFrm && wapp) { - for (i = 0; i < wlengthof(panel->appChk); i++) { - int flag = 0; - - switch (i) { - case 0: - flag = WFLAGP(wapp->main_window_desc, start_hidden); - break; - case 1: - flag = WFLAGP(wapp->main_window_desc, no_appicon); - break; - case 2: - flag = WFLAGP(wapp->main_window_desc, shared_appicon); - break; - } + for (i = 0; i < wlengthof(application_attr); i++) { + int is_userdef, flag = 0; + + is_userdef = get_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag); + if (is_userdef) + flag = get_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag); + else + flag = get_attr_flag(&wapp->main_window_desc->client_flags, &application_attr[i].flag); + WMSetButtonSelected(panel->appChk[i], flag); } } @@ -1414,9 +1425,7 @@ static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel) static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width) { WScreen *scr = wwin->screen_ptr; - int i = 0, flag = 0, tmp; - char *caption = NULL, *descr = NULL; - + int i = 0, tmp; if (wwin->main_window != None) { WApplication *wapp = wApplicationOf(wwin->main_window); @@ -1426,34 +1435,23 @@ static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int fr WMMoveWidget(panel->appFrm, 15, 50); WMResizeWidget(panel->appFrm, frame_width, 240); - for (i = 0; i < wlengthof(panel->appChk); i++) { - switch (i) { - case 0: - caption = _("Start hidden"); - flag = WFLAGP(wapp->main_window_desc, start_hidden); - descr = _("Automatically hide application when it's started."); - break; - case 1: - caption = _("No application icon"); - flag = WFLAGP(wapp->main_window_desc, no_appicon); - descr = _("Disable the application icon for the application.\n" - "Note that you won't be able to dock it anymore,\n" - "and any icons that are already docked will stop\n" - "working correctly."); - break; - case 2: - caption = _("Shared application icon"); - flag = WFLAGP(wapp->main_window_desc, shared_appicon); - descr = _("Use a single shared application icon for all of\n" - "the instances of this application.\n"); - break; - } + for (i = 0; i < wlengthof(application_attr); i++) { + int is_userdef, flag; + + is_userdef = get_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag); + if (is_userdef) + flag = get_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag); + else + flag = get_attr_flag(&wapp->main_window_desc->client_flags, &application_attr[i].flag); + panel->appChk[i] = WMCreateSwitchButton(panel->appFrm); WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1)); WMResizeWidget(panel->appChk[i], 205, 20); WMSetButtonSelected(panel->appChk[i], flag); - WMSetButtonText(panel->appChk[i], caption); - WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i])); + WMSetButtonText(panel->appChk[i], _(application_attr[i].caption)); + + WMSetBalloonTextForView(_(application_attr[i].description), + WMWidgetView(panel->appChk[i])); } if (WFLAGP(wwin, emulate_appicon)) { http://repo.or.cz/w/wmaker-crm.git/commit/1a75270c0a50ca339a476b47c542ccfddf86c79f commit 1a75270c0a50ca339a476b47c542ccfddf86c79f Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:01 2015 +0200 wmaker: moved the list of Advanced Options into an array, for the Window Inspector The Window Inspector is used to let user change a list of advanced options for a window. This list was defined through many hard-coded things; by defining an array with everything at the beginning of the file it is easier to maintain (the code is simpler because it is more generic) and to make it evolve in the future. Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/src/winspector.c b/src/winspector.c index 8413836..16ab168 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -108,6 +108,60 @@ static const struct { M_("Make the window use the whole screen space when it's\n" "maximized. The titlebar and resizebar will be moved\n" "to outside the screen.") } + +}, advanced_option[] = { + { "NoKeyBindings", { .no_bind_keys = 1 }, M_("Do not bind keyboard shortcuts"), + M_("Do not bind keyboard shortcuts from Window Maker\n" + "when this window is focused. This will allow the\n" + "window to receive all key combinations regardless\n" + "of your shortcut configuration.") }, + + { "NoMouseBindings", { .no_bind_mouse = 1 }, M_("Do not bind mouse clicks"), + M_("Do not bind mouse actions, such as `Alt'+drag\n" + "in the window (when Alt is the modifier you have\n" + "configured).") }, + + { "SkipWindowList", { .skip_window_list = 1 }, M_("Do not show in the window list"), + M_("Do not list the window in the window list menu.") }, + + { "SkipSwitchPanel", { .skip_switchpanel = 1 }, M_("Do not show in the switch panel"), + M_("Do not include in switch panel while cycling windows.") }, + + { "Unfocusable", { .no_focusable = 1 }, M_("Do not let it take focus"), + M_("Do not let the window take keyboard focus when you\n" + "click on it.") }, + + { "KeepInsideScreen", { .dont_move_off = 1 }, M_("Keep inside screen"), + M_("Do not allow the window to move itself completely\n" + "outside the screen. For bug compatibility.\n") }, + + { "NoHideOthers", { .no_hide_others = 1 }, M_("Ignore 'Hide Others'"), + M_("Do not hide the window when issuing the\n" + "`HideOthers' command.") }, + + { "DontSaveSession", { .dont_save_session = 1 }, M_("Ignore 'Save Session'"), + M_("Do not save the associated application in the\n" + "session's state, so that it won't be restarted\n" + "together with other applications when Window Maker\n" + "starts.") }, + + { "EmulateAppIcon", { .emulate_appicon = 1 }, M_("Emulate application icon"), + M_("Make this window act as an application that provides\n" + "enough information to Window Maker for a dockable\n" + "application icon to be created.") }, + + { "FocusAcrossWorkspace", { .focus_across_wksp = 1 }, M_("Focus across workspaces"), + M_("Allow Window Maker to switch workspace to satisfy\n" + "a focus request (annoying).") }, + + { "NoMiniaturizable", { .no_miniaturizable = 1 }, M_("Do not let it be minimized"), + M_("Do not let the window of this application be\n" + "minimized.\n") } + +#ifdef XKB_BUTTON_HINT + ,{ "NoLanguageButton", { .no_language_button = 1 }, M_("Disable language button"), + M_("Remove the `toggle language' button of the window.") } +#endif }; typedef struct InspectorPanel { @@ -139,11 +193,7 @@ typedef struct InspectorPanel { /* 3rd page. more attributes */ WMFrame *moreFrm; -#ifdef XKB_BUTTON_HINT - WMButton *moreChk[12]; -#else - WMButton *moreChk[11]; -#endif + WMButton *moreChk[sizeof(advanced_option) / sizeof(advanced_option[0])]; /* 4th page. icon and workspace */ WMFrame *iconFrm; @@ -174,24 +224,11 @@ static InspectorPanel *panelList = NULL; * one everytime. */ static WMPropList *pl_attribute[sizeof(window_attribute) / sizeof(window_attribute[0])] = { [0] = NULL }; +static WMPropList *pl_advoptions[sizeof(advanced_option) / sizeof(advanced_option[0])]; -static WMPropList *ANoHideOthers; -static WMPropList *ANoMouseBindings; -static WMPropList *ANoKeyBindings; static WMPropList *ANoAppIcon; -static WMPropList *ASkipWindowList; -static WMPropList *ASkipSwitchPanel; -static WMPropList *AKeepInsideScreen; -static WMPropList *AUnfocusable; -static WMPropList *AFocusAcrossWorkspace; static WMPropList *AAlwaysUserIcon; -static WMPropList *ADontSaveSession; -static WMPropList *AEmulateAppIcon; static WMPropList *ASharedAppIcon; -static WMPropList *ANoMiniaturizable; -#ifdef XKB_BUTTON_HINT -static WMPropList *ANoLanguageButton; -#endif static WMPropList *AStartWorkspace; static WMPropList *AIcon; @@ -271,26 +308,14 @@ static void make_keys(void) for (i = 0; i < wlengthof(window_attribute); i++) pl_attribute[i] = WMCreatePLString(window_attribute[i].key_name); + for (i = 0; i < wlengthof(advanced_option); i++) + pl_advoptions[i] = WMCreatePLString(advanced_option[i].key_name); AIcon = WMCreatePLString("Icon"); - ANoHideOthers = WMCreatePLString("NoHideOthers"); - ANoMouseBindings = WMCreatePLString("NoMouseBindings"); - ANoKeyBindings = WMCreatePLString("NoKeyBindings"); ANoAppIcon = WMCreatePLString("NoAppIcon"); - ASkipWindowList = WMCreatePLString("SkipWindowList"); - ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel"); - AKeepInsideScreen = WMCreatePLString("KeepInsideScreen"); - AUnfocusable = WMCreatePLString("Unfocusable"); - AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace"); AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon"); AStartHidden = WMCreatePLString("StartHidden"); - ADontSaveSession = WMCreatePLString("DontSaveSession"); - AEmulateAppIcon = WMCreatePLString("EmulateAppIcon"); ASharedAppIcon = WMCreatePLString("SharedAppIcon"); - ANoMiniaturizable = WMCreatePLString("NoMiniaturizable"); -#ifdef XKB_BUTTON_HINT - ANoLanguageButton = WMCreatePLString("NoLanguageButton"); -#endif AStartWorkspace = WMCreatePLString("StartWorkspace"); @@ -609,43 +634,11 @@ static void saveSettings(WMWidget *button, void *client_data) different |= insertAttribute(dict, winDic, pl_attribute[i], value, flags); } - value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AUnfocusable, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags); - - value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags); - -#ifdef XKB_BUTTON_HINT - value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags); -#endif + /* Attributes... --> Advanced Options */ + for (i = 0; i < wlengthof(advanced_option); i++) { + value = (WMGetButtonSelected(panel->moreChk[i]) != 0) ? Yes : No; + different |= insertAttribute(dict, winDic, pl_advoptions[i], value, flags); + } if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) { value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No; @@ -712,10 +705,10 @@ static void applySettings(WMWidget *button, void *client_data) InspectorPanel *panel = (InspectorPanel *) client_data; WWindow *wwin = panel->inspected; WApplication *wapp = wApplicationOf(wwin->main_window); - int skip_window_list; - int old_omnipresent, old_no_bind_keys, old_no_bind_mouse; + int old_skip_window_list, old_omnipresent, old_no_bind_keys, old_no_bind_mouse; int i; + old_skip_window_list = WFLAGP(wwin, skip_window_list); old_omnipresent = WFLAGP(wwin, omnipresent); old_no_bind_keys = WFLAGP(wwin, no_bind_keys); old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse); @@ -733,20 +726,15 @@ static void applySettings(WMWidget *button, void *client_data) } /* Attributes... --> Advanced Options */ - WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0])); - WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1])); - skip_window_list = WMGetButtonSelected(panel->moreChk[2]); - WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3])); - WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4])); - WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5])); - WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6])); - WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7])); - WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8])); - WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9])); - WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10])); -#ifdef XKB_BUTTON_HINT - WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11])); -#endif + for (i = 0; i < wlengthof(advanced_option); i++) { + if (WMGetButtonSelected(panel->moreChk[i])) + set_attr_flag(&wwin->user_flags, &advanced_option[i].flag); + else + clear_attr_flag(&wwin->user_flags, &advanced_option[i].flag); + + set_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag); + } + WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk)); if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded) @@ -767,9 +755,8 @@ static void applySettings(WMWidget *button, void *client_data) wwin->flags.omnipresent = 0; - if (WFLAGP(wwin, skip_window_list) != skip_window_list) { - WSETUFLAG(wwin, skip_window_list, skip_window_list); - UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD); + if (WFLAGP(wwin, skip_window_list) != old_skip_window_list) { + UpdateSwitchMenu(wwin->screen_ptr, wwin, WFLAGP(wwin, skip_window_list)?ACTION_REMOVE:ACTION_ADD); } else { if (WFLAGP(wwin, omnipresent) != old_omnipresent) WMPostNotificationName(WMNChangedState, wwin, "omnipresent"); @@ -908,49 +895,16 @@ static void revertSettings(WMWidget *button, void *client_data) WMSetButtonSelected(panel->attrChk[i], flag); } - for (i = 0; i < wlengthof(panel->moreChk); i++) { - int flag = 0; - - switch (i) { - case 0: - flag = WFLAGP(wwin, no_bind_keys); - break; - case 1: - flag = WFLAGP(wwin, no_bind_mouse); - break; - case 2: - flag = WFLAGP(wwin, skip_window_list); - break; - case 3: - flag = WFLAGP(wwin, skip_switchpanel); - break; - case 4: - flag = WFLAGP(wwin, no_focusable); - break; - case 5: - flag = WFLAGP(wwin, dont_move_off); - break; - case 6: - flag = WFLAGP(wwin, no_hide_others); - break; - case 7: - flag = WFLAGP(wwin, dont_save_session); - break; - case 8: - flag = WFLAGP(wwin, emulate_appicon); - break; - case 9: - flag = WFLAGP(wwin, focus_across_wksp); - break; - case 10: - flag = WFLAGP(wwin, no_miniaturizable); - break; -#ifdef XKB_BUTTON_HINT - case 11: - flag = WFLAGP(wwin, no_language_button); - break; -#endif - } + /* Attributes... --> Advanced Options */ + for (i = 0; i < wlengthof(advanced_option); i++) { + int is_userdef, flag; + + is_userdef = get_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag); + if (is_userdef) + flag = get_attr_flag(&wwin->user_flags, &advanced_option[i].flag); + else + flag = get_attr_flag(&wwin->client_flags, &advanced_option[i].flag); + WMSetButtonSelected(panel->moreChk[i], flag); } if (panel->appFrm && wapp) { @@ -1369,97 +1323,28 @@ static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, i static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width) { int i = 0; - char *caption = NULL, *descr = NULL; - int flag = 0; panel->moreFrm = WMCreateFrame(panel->win); WMSetFrameTitle(panel->moreFrm, _("Advanced")); WMMoveWidget(panel->moreFrm, 15, 45); WMResizeWidget(panel->moreFrm, frame_width, 265); - for (i = 0; i < wlengthof(panel->moreChk); i++) { - switch (i) { - case 0: - caption = _("Do not bind keyboard shortcuts"); - flag = WFLAGP(wwin, no_bind_keys); - descr = _("Do not bind keyboard shortcuts from Window Maker\n" - "when this window is focused. This will allow the\n" - "window to receive all key combinations regardless\n" - "of your shortcut configuration."); - break; - case 1: - caption = _("Do not bind mouse clicks"); - flag = WFLAGP(wwin, no_bind_mouse); - descr = _("Do not bind mouse actions, such as `Alt'+drag\n" - "in the window (when Alt is the modifier you have\n" "configured)."); - break; - case 2: - caption = _("Do not show in the window list"); - flag = WFLAGP(wwin, skip_window_list); - descr = _("Do not list the window in the window list menu."); - break; - case 3: - caption = _("Do not show in the switch panel"); - flag = WFLAGP(wwin, skip_switchpanel); - descr = _("Do not include in switch panel while cycling windows."); - break; - case 4: - caption = _("Do not let it take focus"); - flag = WFLAGP(wwin, no_focusable); - descr = _("Do not let the window take keyboard focus when you\n" "click on it."); - break; - case 5: - caption = _("Keep inside screen"); - flag = WFLAGP(wwin, dont_move_off); - descr = _("Do not allow the window to move itself completely\n" - "outside the screen. For bug compatibility.\n"); - break; - case 6: - caption = _("Ignore 'Hide Others'"); - flag = WFLAGP(wwin, no_hide_others); - descr = _("Do not hide the window when issuing the\n" "`HideOthers' command."); - break; - case 7: - caption = _("Ignore 'Save Session'"); - flag = WFLAGP(wwin, dont_save_session); - descr = _("Do not save the associated application in the\n" - "session's state, so that it won't be restarted\n" - "together with other applications when Window Maker\n" "starts."); - break; - case 8: - caption = _("Emulate application icon"); - flag = WFLAGP(wwin, emulate_appicon); - descr = _("Make this window act as an application that provides\n" - "enough information to Window Maker for a dockable\n" - "application icon to be created."); - break; - case 9: - caption = _("Focus across workspaces"); - flag = WFLAGP(wwin, focus_across_wksp); - descr = _("Allow Window Maker to switch workspace to satisfy\n" - "a focus request (annoying)."); - break; - case 10: - caption = _("Do not let it be minimized"); - flag = WFLAGP(wwin, no_miniaturizable); - descr = _("Do not let the window of this application be\n" - "minimized.\n"); - break; -#ifdef XKB_BUTTON_HINT - case 11: - caption = _("Disable language button"); - flag = WFLAGP(wwin, no_language_button); - descr = _("Remove the `toggle language' button of the window."); - break; -#endif - } + for (i = 0; i < wlengthof(advanced_option); i++) { + int is_userdef, flag; + + is_userdef = get_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag); + if (is_userdef) + flag = get_attr_flag(&wwin->user_flags, &advanced_option[i].flag); + else + flag = get_attr_flag(&wwin->client_flags, &advanced_option[i].flag); + panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm); - WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1)); + WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1) - 4); WMResizeWidget(panel->moreChk[i], frame_width - 15, 20); WMSetButtonSelected(panel->moreChk[i], flag); - WMSetButtonText(panel->moreChk[i], caption); + WMSetButtonText(panel->moreChk[i], _(advanced_option[i].caption)); - WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i])); + WMSetBalloonTextForView(_(advanced_option[i].description), WMWidgetView(panel->moreChk[i])); } } http://repo.or.cz/w/wmaker-crm.git/commit/67ed6a40b401173474e3b6b5fc4b2a1c6a00a796 commit 67ed6a40b401173474e3b6b5fc4b2a1c6a00a796 Author: Christophe CURIS <christophe.cu...@free.fr> Date: Sun May 10 19:56:00 2015 +0200 wmaker: moved the list of Window Attributes into an array, for the Window Inspector The Window Inspector is used to let user change the list of attributes for a window. This list of attributes was defined through many hard-coded things; by defining an array with everything at the beginning of the file it is easier to maintain (the code is simpler because it is more generic) and to make it evolve. Signed-off-by: Christophe CURIS <christophe.cu...@free.fr> diff --git a/src/winspector.c b/src/winspector.c index 78b5cd0..8413836 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -60,6 +60,56 @@ #define UPDATE_DEFAULTS 1 #define IS_BOOLEAN 2 + +static const struct { + const char *key_name; + WWindowAttributes flag; + const char *caption; + const char *description; +} window_attribute[] = { + { "NoTitlebar", { .no_titlebar = 1 }, M_("Disable titlebar"), + M_("Remove the titlebar of this window.\n" + "To access the window commands menu of a window\n" + "without it's titlebar, press Control+Esc (or the\n" + "equivalent shortcut, if you changed the default\n" + "settings).") }, + + { "NoResizebar", { .no_resizebar = 1 }, M_("Disable resizebar"), + M_("Remove the resizebar of this window.") }, + + { "NoCloseButton", { .no_close_button = 1 }, M_("Disable close button"), + M_("Remove the `close window' button of this window.") }, + + { "NoMiniaturizeButton", { .no_miniaturize_button = 1 }, M_("Disable miniaturize button"), + M_("Remove the `miniaturize window' button of the window.") }, + + { "NoBorder", { .no_border = 1 }, M_("Disable border"), + M_("Remove the 1 pixel black border around the window.") }, + + { "KeepOnTop", { .floating = 1 }, M_("Keep on top (floating)"), + M_("Keep the window over other windows, not allowing\n" + "them to cover it.") }, + + { "KeepOnBottom", { .sunken = 1 }, M_("Keep at bottom (sunken)"), + M_("Keep the window under all other windows.") }, + + { "Omnipresent", { .omnipresent = 1 }, M_("Omnipresent"), + M_("Make window present in all workspaces.") }, + + { "StartMiniaturized", { .start_miniaturized = 1 }, M_("Start miniaturized"), + M_("Make the window be automatically miniaturized when it's\n" + "first shown.") }, + + { "StartMaximized", { .start_maximized = 1 }, M_("Start maximized"), + M_("Make the window be automatically maximized when it's\n" + "first shown.") }, + + { "FullMaximize", { .full_maximize = 1 }, M_("Full screen maximization"), + M_("Make the window use the whole screen space when it's\n" + "maximized. The titlebar and resizebar will be moved\n" + "to outside the screen.") } +}; + typedef struct InspectorPanel { struct InspectorPanel *nextPtr; @@ -85,7 +135,7 @@ typedef struct InspectorPanel { /* second page. attributes */ WMFrame *attrFrm; - WMButton *attrChk[11]; + WMButton *attrChk[sizeof(window_attribute) / sizeof(window_attribute[0])]; /* 3rd page. more attributes */ WMFrame *moreFrm; @@ -115,29 +165,28 @@ typedef struct InspectorPanel { } InspectorPanel; static InspectorPanel *panelList = NULL; -static WMPropList *ANoTitlebar = NULL; -static WMPropList *ANoResizebar; -static WMPropList *ANoMiniaturizeButton; -static WMPropList *ANoCloseButton; -static WMPropList *ANoBorder; + +/* + * We are supposed to use the 'key_name' from the the 'window_attribute' structure when we want to + * save the user choice to the database, but as we will need to convert that name into a Property + * List, we use here a Cache of Property Lists, generated only once, which can be reused. It will + * also save on memory because of the re-use of the same storage space instead of allocating a new + * one everytime. + */ +static WMPropList *pl_attribute[sizeof(window_attribute) / sizeof(window_attribute[0])] = { [0] = NULL }; + static WMPropList *ANoHideOthers; static WMPropList *ANoMouseBindings; static WMPropList *ANoKeyBindings; static WMPropList *ANoAppIcon; -static WMPropList *AKeepOnTop; -static WMPropList *AKeepOnBottom; -static WMPropList *AOmnipresent; static WMPropList *ASkipWindowList; static WMPropList *ASkipSwitchPanel; static WMPropList *AKeepInsideScreen; static WMPropList *AUnfocusable; static WMPropList *AFocusAcrossWorkspace; static WMPropList *AAlwaysUserIcon; -static WMPropList *AStartMiniaturized; -static WMPropList *AStartMaximized; static WMPropList *ADontSaveSession; static WMPropList *AEmulateAppIcon; -static WMPropList *AFullMaximize; static WMPropList *ASharedAppIcon; static WMPropList *ANoMiniaturizable; #ifdef XKB_BUTTON_HINT @@ -162,36 +211,81 @@ static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel); static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width); +/* + * These 3 functions sets/clear/read a bit inside a bit-field in a generic manner; + * they uses binary operators to be as effiscient as possible, also counting on compiler's + * optimisations because the bit-field structure will fit in only 1 or 2 int but it is + * depending on the processor architecture. + */ +static inline void set_attr_flag(WWindowAttributes *target, const WWindowAttributes *flag) +{ + int i; + const unsigned char *src; + unsigned char *dst; + + src = (const unsigned char *) flag; + dst = (unsigned char *) target; + + for (i = 0; i < sizeof(*flag); i++) + dst[i] |= src[i]; +} + +static inline void clear_attr_flag(WWindowAttributes *target, const WWindowAttributes *flag) +{ + int i; + const unsigned char *src; + unsigned char *dst; + + src = (const unsigned char *) flag; + dst = (unsigned char *) target; + + for (i = 0; i < sizeof(*flag); i++) + dst[i] &= ~src[i]; +} + +static inline int get_attr_flag(const WWindowAttributes *from, const WWindowAttributes *flag) +{ + int i; + const unsigned char *xpect, *field; + + field = (const unsigned char *) from; + xpect = (const unsigned char *) flag; + + for (i = 0; i < sizeof(*flag); i++) + if (field[i] & xpect[i]) + return 1; + + return 0; +} + +/* + * This function is creating the Property List for the cache mentionned above + */ static void make_keys(void) { - if (ANoTitlebar != NULL) + int i; + + if (pl_attribute[0] != NULL) return; + for (i = 0; i < wlengthof(window_attribute); i++) + pl_attribute[i] = WMCreatePLString(window_attribute[i].key_name); + + AIcon = WMCreatePLString("Icon"); - ANoTitlebar = WMCreatePLString("NoTitlebar"); - ANoResizebar = WMCreatePLString("NoResizebar"); - ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton"); - 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"); AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace"); AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon"); - AStartMiniaturized = WMCreatePLString("StartMiniaturized"); - AStartMaximized = WMCreatePLString("StartMaximized"); AStartHidden = WMCreatePLString("StartHidden"); ADontSaveSession = WMCreatePLString("DontSaveSession"); AEmulateAppIcon = WMCreatePLString("EmulateAppIcon"); - AFullMaximize = WMCreatePLString("FullMaximize"); ASharedAppIcon = WMCreatePLString("SharedAppIcon"); ANoMiniaturizable = WMCreatePLString("NoMiniaturizable"); #ifdef XKB_BUTTON_HINT @@ -509,38 +603,11 @@ static void saveSettings(WMWidget *button, void *client_data) flags |= IS_BOOLEAN; - value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoResizebar, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, ANoBorder, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AOmnipresent, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AStartMaximized, value, flags); - - value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No; - different |= insertAttribute(dict, winDic, AFullMaximize, value, flags); + /* Attributes... --> Window Attributes */ + for (i = 0; i < wlengthof(window_attribute); i++) { + value = (WMGetButtonSelected(panel->attrChk[i]) != 0) ? Yes : No; + different |= insertAttribute(dict, winDic, pl_attribute[i], value, flags); + } value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No; different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags); @@ -645,8 +712,9 @@ static void applySettings(WMWidget *button, void *client_data) InspectorPanel *panel = (InspectorPanel *) client_data; WWindow *wwin = panel->inspected; WApplication *wapp = wApplicationOf(wwin->main_window); - int floating, sunken, skip_window_list; + int skip_window_list; int old_omnipresent, old_no_bind_keys, old_no_bind_mouse; + int i; old_omnipresent = WFLAGP(wwin, omnipresent); old_no_bind_keys = WFLAGP(wwin, no_bind_keys); @@ -655,17 +723,14 @@ static void applySettings(WMWidget *button, void *client_data) showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD); /* Attributes... --> Window Attributes */ - WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0])); - WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1])); - WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2])); - WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3])); - WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4])); - floating = WMGetButtonSelected(panel->attrChk[5]); - sunken = WMGetButtonSelected(panel->attrChk[6]); - WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7])); - WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8])); - WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9])); - WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10])); + for (i = 0; i < wlengthof(window_attribute); i++) { + if (WMGetButtonSelected(panel->attrChk[i])) + set_attr_flag(&wwin->user_flags, &window_attribute[i].flag); + else + clear_attr_flag(&wwin->user_flags, &window_attribute[i].flag); + + set_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag); + } /* Attributes... --> Advanced Options */ WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0])); @@ -689,19 +754,17 @@ static void applySettings(WMWidget *button, void *client_data) WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar)); - if (floating) { - if (!WFLAGP(wwin, floating)) - ChangeStackingLevel(wwin->frame->core, WMFloatingLevel); - } else if (sunken) { - if (!WFLAGP(wwin, sunken)) - ChangeStackingLevel(wwin->frame->core, WMSunkenLevel); - } else { - if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken)) - ChangeStackingLevel(wwin->frame->core, WMNormalLevel); - } + /* + * Update the window level according to AlwaysOnTop/AlwaysOnBotton + * if the level did not change, ChangeStackingLevel will do nothing anyway + */ + if (WFLAGP(wwin, floating)) + ChangeStackingLevel(wwin->frame->core, WMFloatingLevel); + else if (WFLAGP(wwin, sunken)) + ChangeStackingLevel(wwin->frame->core, WMSunkenLevel); + else + ChangeStackingLevel(wwin->frame->core, WMNormalLevel); - WSETUFLAG(wwin, sunken, sunken); - WSETUFLAG(wwin, floating, floating); wwin->flags.omnipresent = 0; if (WFLAGP(wwin, skip_window_list) != skip_window_list) { @@ -832,44 +895,16 @@ static void revertSettings(WMWidget *button, void *client_data) wWindowSetupInitialAttributes(wwin, &level, &workspace); - for (i = 0; i < wlengthof(panel->attrChk); i++) { - int flag = 0; + /* Attributes... --> Window Attributes */ + for (i = 0; i < wlengthof(window_attribute); i++) { + int is_userdef, flag; + + is_userdef = get_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag); + if (is_userdef) + flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag); + else + flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag); - switch (i) { - case 0: - flag = WFLAGP(wwin, no_titlebar); - break; - case 1: - flag = WFLAGP(wwin, no_resizebar); - break; - case 2: - flag = WFLAGP(wwin, no_close_button); - break; - case 3: - flag = WFLAGP(wwin, no_miniaturize_button); - break; - case 4: - flag = WFLAGP(wwin, no_border); - break; - case 5: - flag = WFLAGP(wwin, floating); - break; - case 6: - flag = WFLAGP(wwin, sunken); - break; - case 7: - flag = WFLAGP(wwin, omnipresent); - break; - case 8: - flag = WFLAGP(wwin, start_miniaturized); - break; - case 9: - flag = WFLAGP(wwin, start_maximized != 0); - break; - case 10: - flag = WFLAGP(wwin, full_maximize); - break; - } WMSetButtonSelected(panel->attrChk[i], flag); } @@ -1306,84 +1341,28 @@ void wCloseInspectorForWindow(WWindow *wwin) static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width) { int i = 0; - char *caption = NULL, *descr = NULL; - int flag = 0; panel->attrFrm = WMCreateFrame(panel->win); WMSetFrameTitle(panel->attrFrm, _("Attributes")); WMMoveWidget(panel->attrFrm, 15, 45); WMResizeWidget(panel->attrFrm, frame_width, 250); - for (i = 0; i < wlengthof(panel->attrChk); i++) { - switch (i) { - case 0: - caption = _("Disable titlebar"); - flag = WFLAGP(wwin, no_titlebar); - descr = _("Remove the titlebar of this window.\n" - "To access the window commands menu of a window\n" - "without it's titlebar, press Control+Esc (or the\n" - "equivalent shortcut, if you changed the default\n" "settings)."); - break; - case 1: - caption = _("Disable resizebar"); - flag = WFLAGP(wwin, no_resizebar); - descr = _("Remove the resizebar of this window."); - break; - case 2: - caption = _("Disable close button"); - flag = WFLAGP(wwin, no_close_button); - descr = _("Remove the `close window' button of this window."); - break; - case 3: - caption = _("Disable miniaturize button"); - flag = WFLAGP(wwin, no_miniaturize_button); - descr = _("Remove the `miniaturize window' button of the window."); - break; - case 4: - caption = _("Disable border"); - flag = WFLAGP(wwin, no_border); - descr = _("Remove the 1 pixel black border around the window."); - break; - case 5: - caption = _("Keep on top (floating)"); - flag = WFLAGP(wwin, floating); - descr = _("Keep the window over other windows, not allowing\n" "them to cover it."); - break; - case 6: - caption = _("Keep at bottom (sunken)"); - flag = WFLAGP(wwin, sunken); - descr = _("Keep the window under all other windows."); - break; - case 7: - caption = _("Omnipresent"); - flag = WFLAGP(wwin, omnipresent); - descr = _("Make window present in all workspaces."); - break; - case 8: - caption = _("Start miniaturized"); - flag = WFLAGP(wwin, start_miniaturized); - descr = _("Make the window be automatically miniaturized when it's\n" "first shown."); - break; - case 9: - caption = _("Start maximized"); - flag = WFLAGP(wwin, start_maximized != 0); - descr = _("Make the window be automatically maximized when it's\n" "first shown."); - break; - case 10: - caption = _("Full screen maximization"); - flag = WFLAGP(wwin, full_maximize); - descr = _("Make the window use the whole screen space when it's\n" - "maximized. The titlebar and resizebar will be moved\n" - "to outside the screen."); - break; - } + for (i = 0; i < wlengthof(window_attribute); i++) { + int is_userdef, flag; + + is_userdef = get_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag); + if (is_userdef) + flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag); + else + flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag); + panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm); WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1)); WMResizeWidget(panel->attrChk[i], frame_width - 15, 20); WMSetButtonSelected(panel->attrChk[i], flag); - WMSetButtonText(panel->attrChk[i], caption); + WMSetButtonText(panel->attrChk[i], _(window_attribute[i].caption)); - WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i])); + WMSetBalloonTextForView(_(window_attribute[i].description), WMWidgetView(panel->attrChk[i])); } } ----------------------------------------------------------------------- Summary of changes: FAQ | 25 +- NEWS | 10 + WINGs/WINGs/WINGs.h | 5 +- WINGs/WINGs/WINGsP.h | 10 + WINGs/wbutton.c | 35 +- WINGs/widgets.c | 69 +++ WPrefs.app/Expert.c | 3 + script/check-wmaker-loaddef-callbacks.sh | 88 +++- src/WindowMaker.h | 6 + src/client.c | 12 +- src/defaults.c | 2 + src/motif.c | 64 ++- src/startup.c | 6 +- src/window.c | 66 ++- src/winspector.c | 827 ++++++++++++++----------------- 15 files changed, 677 insertions(+), 551 deletions(-) repo.or.cz automatic notification. Contact project admin crma...@gmail.com if you want to unsubscribe, or site admin ad...@repo.or.cz if you receive no reply. -- wmaker-crm.git ("The Window Maker window manager") -- To unsubscribe, send mail to wmaker-dev-unsubscr...@lists.windowmaker.org.