217
223
XGetTextProperty(dpy, w, &text_prop, prop);
218
if(text_prop.value != NULL) {
224
if(text_prop.value == NULL) {
228
if(text_prop.encoding == XA_STRING
229
|| text_prop.encoding == XA_UTF8_STRING
230
|| text_prop.encoding == XA_COMPOUND_TEXT) {
231
/* property is encoded as compound text - convert to locale string */
219
232
char **text_list;
220
233
int text_list_count;
222
if(text_prop.encoding == XA_STRING
223
|| text_prop.encoding == XA_COMPOUND_TEXT) {
224
/* property is encoded as compound text - convert to locale string */
225
int status = XmbTextPropertyToTextList(dpy, &text_prop, &text_list,
227
if(text_list_count == 0) {
230
else if(text_list == NULL) {
233
else if(text_list [0] == NULL) {
236
else if(status < 0 || text_list_count < 0) {
238
case XConverterNotFound:
240
"%s: Converter not found; unable to convert property %s of window ID %lx.\n",
241
ProgramName, XGetAtomName(dpy, prop), w);
245
"%s: Insufficient memory; unable to convert property %s of window ID %lx.\n",
246
ProgramName, XGetAtomName(dpy, prop), w);
248
case XLocaleNotSupported:
250
"%s: Locale not supported; unable to convert property %s of window ID %lx.\n",
251
ProgramName, XGetAtomName(dpy, prop), w);
256
don't call XFreeStringList - text_list appears to have
257
invalid address if status is bad
258
XFreeStringList(text_list);
262
stringptr = strdup(text_list[0]);
263
XFreeStringList(text_list);
236
/* Check historical strictness */
237
if(Scr->StrictWinNameEncoding) {
240
if((prop == XA_WM_NAME || prop == XA_WM_ICON_NAME)
241
&& text_prop.encoding != XA_STRING
242
&& text_prop.encoding != XA_COMPOUND_TEXT) {
247
if((prop == XA__NET_WM_NAME || prop == XA__NET_WM_ICON_NAME)
248
&& text_prop.encoding != XA_UTF8_STRING) {
254
fprintf(stderr, "%s: Invalid encoding for property %s "
255
"of window 0x%lx\n", ProgramName,
256
XGetAtomName(dpy, prop), w);
257
XFree(text_prop.value);
263
status = XmbTextPropertyToTextList(dpy, &text_prop, &text_list,
265
if(text_list_count == 0
267
|| text_list[0] == NULL) {
269
XFree(text_prop.value);
272
else if(status < 0 || text_list_count < 0) {
273
// Got an error statuf
275
case XConverterNotFound:
277
"%s: Converter not found; unable to convert property %s of window ID %lx.\n",
278
ProgramName, XGetAtomName(dpy, prop), w);
282
"%s: Insufficient memory; unable to convert property %s of window ID %lx.\n",
283
ProgramName, XGetAtomName(dpy, prop), w);
285
case XLocaleNotSupported:
287
"%s: Locale not supported; unable to convert property %s of window ID %lx.\n",
288
ProgramName, XGetAtomName(dpy, prop), w);
293
don't call XFreeStringList - text_list appears to have
294
invalid address if status is bad
295
XFreeStringList(text_list);
267
/* property is encoded in a format we don't understand */
269
"%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n",
270
ProgramName, XGetAtomName(dpy, prop), w);
299
// Actually got the data!
300
stringptr = strdup(text_list[0]);
301
XFreeStringList(text_list);
273
XFree(text_prop.value);
305
/* property is encoded in a format we don't understand */
307
"%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n",
308
ProgramName, XGetAtomName(dpy, prop), w);
276
309
stringptr = NULL;
311
XFree(text_prop.value);
279
313
return stringptr;
942
* [Re]set a window's name. This goes over the available naming sources
943
* for the window and points the TwmWindow::name at the appropriate one.
944
* It may also set a property to signal other EWMH-aware clients when
945
* we're naming it a way they can't see themselves.
947
* \note This should rarely be called directly; apply_window_name()
948
* should be used instead. It's split out because we need to do this
949
* step individually in AddWindow().
951
* \note Note also that we never need to worry about freeing the
952
* TwmWindow::name; it always points to one of the TwmWindow::names
953
* values (which are free'd by the event handler when they change) or to
954
* NoName (which is static). So we can just casually flip it around at
958
set_window_name(TwmWindow *win)
960
char *newname = NULL;
962
if(newname == NULL && win->names.fld != NULL) { \
963
newname = win->names.fld; \
973
if(newname == NULL) {
976
if(win->name == newname) {
977
return false; // Nothing to do
980
// Now we know what to call it
984
// EWMH says we set an additional property on any windows where what
985
// we consider the name isn't what's in _NET_WM_NAME, so pagers etc
986
// can call it the same as we do.
988
// The parts of the text describing it conflict a little; at one
989
// place, it implies this should be set unless we're using
990
// _NET_WM_NAME, in another it seems to suggest WM_NAME should be
991
// considered applicable too. I choose to implement it excluding
992
// both, so this only gets set if we're overriding either standard
993
// naming (probably rare).
994
if(win->name != win->names.net_wm_name && win->name != win->names.wm_name) {
995
// XXX We're not doing any checking of the encoding here... I
996
// don't see that Xlib helps us any, so we probably have to fall
997
// back to iconv? That came into the base in POSIX 2008, but was
998
// in XSI back into the 90's I believe?
999
XChangeProperty(dpy, win->w, XA__NET_WM_VISIBLE_NAME, XA_UTF8_STRING,
1000
8, PropModeReplace, (unsigned char *)win->name,
1004
XDeleteProperty(dpy, win->w, XA__NET_WM_VISIBLE_NAME);
1014
* [Re]set and apply changes to a window's name. This is called after
1015
* we've received a new WM_NAME (or other name-setting) property, to
1016
* update our titlebars, icon managers, etc.
1019
apply_window_name(TwmWindow *win)
1021
/* [Re]set ->name */
1022
if(set_window_name(win) == false) {
1026
win->nameChanged = true;
1029
/* Update the active name */
1031
XRectangle inc_rect;
1032
XRectangle logical_rect;
1034
XmbTextExtents(Scr->TitleBarFont.font_set,
1035
win->name, strlen(win->name),
1036
&inc_rect, &logical_rect);
1037
win->name_width = logical_rect.width;
1040
/* recompute the priority if necessary */
1041
if(Scr->AutoPriority) {
1042
OtpRecomputePrefs(win);
1045
SetupWindow(win, win->frame_x, win->frame_y,
1046
win->frame_width, win->frame_height, -1);
1049
XClearArea(dpy, win->title_w, 0, 0, 0, 0, True);
1051
if(Scr->AutoOccupy) {
1052
WmgrRedoOccupation(win);
1056
/* Experimental, not yet working. */
1061
f = GetColorFromList(Scr->TitleForegroundL, win->name,
1062
&win->class, &cp.fore);
1063
b = GetColorFromList(Scr->TitleBackgroundL, win->name,
1064
&win->class, &cp.back);
1066
if(Scr->use3Dtitles && !Scr->BeNiceToColormap) {
1067
GetShadeColors(&cp);
1071
f = GetColorFromList(Scr->BorderColorL, win->name,
1072
&win->class, &cp.fore);
1073
b = GetColorFromList(Scr->BorderColorL, win->name,
1074
&win->class, &cp.back);
1076
if(Scr->use3Dborders && !Scr->BeNiceToColormap) {
1077
GetShadeColors(&cp);
1082
f = GetColorFromList(Scr->BorderTileForegroundL, win->name,
1083
&win->class, &cp.fore);
1084
b = GetColorFromList(Scr->BorderTileBackgroundL, win->name,
1085
&win->class, &cp.back);
1087
if(Scr->use3Dborders && !Scr->BeNiceToColormap) {
1088
GetShadeColors(&cp);
1090
win->border_tile = cp;
1096
* If we haven't set a separate icon name, we use the window name, so
1097
* we need to update it.
1099
if(win->names.icon_set == false) {
1100
apply_window_icon_name(win);
1102
AutoPopupMaybe(win);
1109
* [Re]set a window's icon name. As with the window name version in
1110
* set_window_name(), this is mostly separate so the AddWindow() process
1113
* \note As with TwmWindow::name, we never want to try free()'ing or the
1114
* like TwmWindow::icon_name.
1116
* \sa set_window_name() for details; this is just the icon name
1120
set_window_icon_name(TwmWindow *win)
1122
char *newname = NULL;
1123
#define TRY(fld) { \
1124
if(newname == NULL && win->names.fld != NULL) { \
1125
newname = win->names.fld; \
1126
win->names.icon_set = true; \
1129
TRY(ctwm_wm_icon_name)
1131
TRY(net_wm_icon_name)
1136
// Our fallback for icon names is the window name. Flag when we're
1137
// doing that, so the window name handler can know when it needs to
1139
if(newname == NULL) {
1140
newname = win->name;
1141
win->names.icon_set = false;
1143
if(win->icon_name == newname) {
1144
return false; // Nothing to do
1148
win->icon_name = newname;
1151
// EWMH asks for _NET_WM_VISIBLE_ICON_NAME in various cases where
1152
// we're not using 'standard' properties' values. x-ref comments above in
1153
// set_window_name() about the parallel property for the window name
1154
// for various caveats.
1155
if(win->icon_name != win->names.net_wm_icon_name
1156
&& win->icon_name != win->names.wm_icon_name) {
1157
// XXX Still encoding questionable; x-ref above.
1158
XChangeProperty(dpy, win->w, XA__NET_WM_VISIBLE_ICON_NAME,
1160
8, PropModeReplace, (unsigned char *)win->icon_name,
1161
strlen(win->icon_name));
1164
XDeleteProperty(dpy, win->w, XA__NET_WM_VISIBLE_ICON_NAME);
1174
* [Re]set and apply changes to a window's icon name. This is called
1175
* after we've received a new WM_ICON_NAME (or other name-setting)
1176
* property, to update our titlebars, icon managers, etc.
1178
* \sa apply_window_name() which does the same for the window title.
1181
apply_window_icon_name(TwmWindow *win)
1183
/* [Re]set ->icon_name */
1184
if(set_window_icon_name(win) == false) {
1190
/* Lot less to do for icons... */
1192
AutoPopupMaybe(Tmp_win);