diff --git a/jwm.1.in b/jwm.1.in index ab3dc5a7..544b5fa7 100644 --- a/jwm.1.in +++ b/jwm.1.in @@ -1074,7 +1074,7 @@ that the value is relative to the bottom of the screen. .B "WINDOW STYLE" .RS The \fBWindowStyle\fP tag controls the look of window borders. -This tag supports the following attribute: +This tag supports the following attributes: .P .B decorations .RS @@ -1082,6 +1082,18 @@ The window decorations to use. Valid options are \fBflat\fP and \fBmotif\fP. \fBflat\fP is the default. .RE .P +.B showclient +.RS +Include the X client machine name (WM_CLIENT_MACHINE) in the window title. +Valid options are \fBtrue\fP and \fBfalse\fP. \fBfalse\fP is the default. +.RE +.P +.B delimiters +.RS +The two characters used to wrap the X client machine name in the window title. +The default characters are \fB()\fP. +.RE +.P Within this tag, the following tags are supported: .P .B Font @@ -1257,7 +1269,7 @@ respectively. .B "TASK LIST STYLE" .RS The \fBTaskListStyle\fP tag controls the look of task lists. -The following attributea are supported: +The following attributes are supported: .P .B decorations .RS @@ -1279,6 +1291,13 @@ Possible values are \fBdesktop\fP and \fBall\fP. The default is \fBdesktop\fP. .RE .P +.B showkill +.RS +Determines if the \fBKill\fP popup menu item is shown on task bars and +window title bars. Possible values are \fBtrue\fP and \fBfalse\fP. The default +is \fBtrue\fP. +.RE +.P Within this tag the following tags are supported: .P .B Font diff --git a/src/border.c b/src/border.c index df4245d9..9487cc67 100644 --- a/src/border.c +++ b/src/border.c @@ -451,7 +451,18 @@ void DrawBorderHelper(const ClientNode *np) if(np->name && np->name[0] && point.x < point.y) { unsigned titleWidth = point.y - point.x; const int sheight = GetStringHeight(FONT_BORDER); - const int textWidth = GetStringWidth(FONT_BORDER, np->name); + char *titleBuffer; + if (settings.showClientName && np->clientName && np->clientName[0]){ + /* Space for 2 delimiters, space, terminator, and strings */ + const size_t buffSize = strlen(np->name) + strlen(np->clientName) + 4; + titleBuffer = Allocate(buffSize); + sprintf(titleBuffer,"%s %c%s%c",np->name, + settings.clientNameDelimiters[0],np->clientName, + settings.clientNameDelimiters[1]); + } else { + titleBuffer = CopyString(np->name); + } + const int textWidth = GetStringWidth(FONT_BORDER,titleBuffer); unsigned titlex, titley; int xoffset = 0; @@ -474,7 +485,8 @@ void DrawBorderHelper(const ClientNode *np) titley += south - 1; } RenderString(canvas, FONT_BORDER, borderTextColor, - titlex, titley, titleWidth, np->name); + titlex, titley, titleWidth, titleBuffer); + Release(titleBuffer); } } diff --git a/src/client.c b/src/client.c index a6004896..4856fd43 100644 --- a/src/client.c +++ b/src/client.c @@ -1260,8 +1260,8 @@ void RemoveClient(ClientNode *np) if(np->className) { JXFree(np->className); } - if(np->machineName) { - Release(np->machineName); + if(np->clientName) { + Release(np->clientName); } RemoveClientFromTaskBar(np); diff --git a/src/client.h b/src/client.h index b13d0fc7..6be53537 100644 --- a/src/client.h +++ b/src/client.h @@ -147,7 +147,7 @@ typedef struct ClientNode { char *name; /**< Name of this window for display. */ char *instanceName; /**< Name of this window for properties. */ char *className; /**< Name of the window class. */ - char *machineName; /**< Name of the machine. */ + char *clientName; /**< Name of the client machine. */ ClientState state; /**< Window state. */ diff --git a/src/group.c b/src/group.c index e2be5481..f29acefc 100644 --- a/src/group.c +++ b/src/group.c @@ -21,7 +21,7 @@ typedef unsigned int MatchType; #define MATCH_NAME 0 /**< Match the window name. */ #define MATCH_CLASS 1 /**< Match the window class. */ #define MATCH_TYPE 2 /**< Match the window type. */ -#define MATCH_MACHINE 3 /**< Match the window machine. */ +#define MATCH_MACHINE 3 /**< Match the window client machine name. */ #define MATCH_TITLE 4 /**< Match the window title. */ /** List of match patterns for a group. */ @@ -152,7 +152,7 @@ void AddGroupType(GroupType *gp, const char *pattern) } } -/** Add a window machine to a group. */ +/** Add a window client machine to a group. */ void AddGroupMachine(GroupType *gp, const char *pattern) { Assert(gp); @@ -237,12 +237,12 @@ void ApplyGroups(ClientNode *np) char hasName; char hasTitle; char hasType; - char hasMachine; + char hasClient; char matchesClass; char matchesName; char matchesTitle; char matchesType; - char matchesMachine; + char matchesClient; static const StringMappingType windowTypeMapping[] = { { "desktop", WINDOW_TYPE_DESKTOP }, @@ -262,12 +262,12 @@ void ApplyGroups(ClientNode *np) hasName = 0; hasType = 0; hasTitle = 0; - hasMachine = 0; + hasClient = 0; matchesClass = 0; matchesName = 0; matchesTitle = 0; matchesType = 0; - matchesMachine = 0; + matchesClient = 0; for(lp = gp->patterns; lp; lp = lp->next) { if(lp->match == MATCH_CLASS) { if(Match(lp->pattern, np->className)) { @@ -291,10 +291,10 @@ void ApplyGroups(ClientNode *np) } hasType = 1; } else if(lp->match == MATCH_MACHINE) { - if(Match(lp->pattern, np->machineName)) { - matchesMachine = 1; + if(Match(lp->pattern, np->clientName)) { + matchesClient = 1; } - hasMachine = 1; + hasClient = 1; } else { Debug("invalid match in ApplyGroups: %d", lp->match); } @@ -303,7 +303,7 @@ void ApplyGroups(ClientNode *np) && hasClass == matchesClass && hasTitle == matchesTitle && hasType == matchesType - && hasMachine == matchesMachine) { + && hasClient == matchesClient) { ApplyGroup(gp, np); } } diff --git a/src/hint.c b/src/hint.c index ff00eff0..dc9c6d0a 100644 --- a/src/hint.c +++ b/src/hint.c @@ -788,26 +788,26 @@ void ReadWMName(ClientNode *np) } -/** Read the machine for a client. */ +/** Read the machine name of a client. */ void ReadWMMachine(ClientNode *np) { XTextProperty tprop; char **tlist; int tcount; - if(np->machineName) { - Release(np->machineName); + if(np->clientName) { + Release(np->clientName); } XGetWMClientMachine(display, np->window, &tprop); if(XmbTextPropertyToTextList(display, &tprop, &tlist, &tcount) == Success && tcount > 0) { const size_t len = strlen(tlist[0]) + 1; - np->machineName = Allocate(len); - memcpy(np->machineName, tlist[0], len); + np->clientName = Allocate(len); + memcpy(np->clientName, tlist[0], len); XFreeStringList(tlist); } else { - np->machineName = NULL; + np->clientName = NULL; } } diff --git a/src/parse.c b/src/parse.c index 5119f66d..0c70397c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -160,6 +160,9 @@ static const char *DYNAMIC_ATTRIBUTE = "dynamic"; static const char *SPACING_ATTRIBUTE = "spacing"; static const char *TIMEOUT_ATTRIBUTE = "timeout"; static const char *POPUP_ATTRIBUTE = "popup"; +static const char *CLIENTNAME_ATTRIBUTE = "showclient"; +static const char *CN_DELIMITERS_ATTRIBUTE = "delimiters"; +static const char *KILL_MENU_ATTRIBUTE = "showkill"; static const char *FALSE_VALUE = "false"; static const char *TRUE_VALUE = "true"; @@ -998,6 +1001,18 @@ void ParseWindowStyle(const TokenNode *tp) { const TokenNode *np; + const char *temp; + temp = FindAttribute(tp->attributes, CLIENTNAME_ATTRIBUTE); + if(temp){ + settings.showClientName = !strcmp(temp,TRUE_VALUE); + } + + temp = FindAttribute(tp->attributes, CN_DELIMITERS_ATTRIBUTE); + if(temp && strlen(temp)>=2) { + memcpy(settings.clientNameDelimiters, temp, + sizeof(settings.clientNameDelimiters)); + } + ParseDecorations(tp, &settings.windowDecorations); for(np = tp->subnodeHead; np; np = np->next) { switch(np->type) { @@ -1203,6 +1218,12 @@ void ParseTrayStyle(const TokenNode *tp, FontType font, ColorType fg) if(temp) { settings.listAllTasks = !strcmp(temp, "all"); } + + temp = FindAttribute(tp->attributes, KILL_MENU_ATTRIBUTE); + if(temp) { + settings.showKillMenuItem = !strcmp(temp, TRUE_VALUE); + } + } else if(tp->type == TOK_TRAYSTYLE) { ParseDecorations(tp, &settings.trayDecorations); } diff --git a/src/settings.c b/src/settings.c index b057519c..e9956772 100644 --- a/src/settings.c +++ b/src/settings.c @@ -22,6 +22,9 @@ static const MouseContextType DEFAULT_TITLE_BAR_LAYOUT[TBC_COUNT + 1] = { MC_NONE }; +/** Default characters for client machine name delimiters. */ +static const char DEFAULT_CLIENT_NAME_DELIMITERS[2] = {'(',')'}; + static void FixRange(unsigned int *value, unsigned int min_value, unsigned int max_value, @@ -61,6 +64,10 @@ void InitializeSettings(void) settings.groupTasks = 0; settings.listAllTasks = 0; settings.dockSpacing = 0; + settings.showClientName = 0; + memcpy(settings.clientNameDelimiters, DEFAULT_CLIENT_NAME_DELIMITERS, + sizeof(settings.clientNameDelimiters)); + settings.showKillMenuItem = 1; memcpy(settings.titleBarLayout, DEFAULT_TITLE_BAR_LAYOUT, sizeof(settings.titleBarLayout)); } diff --git a/src/settings.h b/src/settings.h index cb7733b2..4a803729 100644 --- a/src/settings.h +++ b/src/settings.h @@ -84,10 +84,11 @@ typedef unsigned char DesktopBackAndForthType; #define DBACKANDFORTH_OFF 0 /**< No back and forth */ #define DBACKANDFORTH_ON 1 /**< Enable back and forth */ -/** Maximimum number of title bar components +/** Maximum number of title bar components * For now, we allow each component to be used twice. */ #define TBC_COUNT 9 + /** Settings. */ typedef struct { unsigned doubleClickSpeed; @@ -122,6 +123,9 @@ typedef struct { MouseContextType titleBarLayout[TBC_COUNT + 1]; char groupTasks; char listAllTasks; + char showClientName; + char clientNameDelimiters[2]; + char showKillMenuItem; DesktopBackAndForthType desktopBackAndForth; } Settings; diff --git a/src/winmenu.c b/src/winmenu.c index ee7fbe9d..e236602c 100644 --- a/src/winmenu.c +++ b/src/winmenu.c @@ -46,7 +46,9 @@ Menu *CreateWindowMenu(ClientNode *np) if(!(np->state.status & STAT_WMDIALOG)) { AddWindowMenuItem(menu, _("Close"), MA_CLOSE, np, 0); - AddWindowMenuItem(menu, _("Kill"), MA_KILL, np, 0); + if (settings.showKillMenuItem){ + AddWindowMenuItem(menu, _("Kill"), MA_KILL, np, 0); + } AddWindowMenuItem(menu, NULL, MA_NONE, np, 0); }