i3
|
00001 /* 00002 * vim:ts=4:sw=4:expandtab 00003 * 00004 * i3 - an improved dynamic tiling window manager 00005 * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) 00006 * 00007 */ 00008 #include "all.h" 00009 00010 /* 00011 * Updates the WM_CLASS (consisting of the class and instance) for the 00012 * given window. 00013 * 00014 */ 00015 void window_update_class(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) { 00016 if (prop == NULL || xcb_get_property_value_length(prop) == 0) { 00017 DLOG("empty property, not updating\n"); 00018 FREE(prop); 00019 return; 00020 } 00021 00022 /* We cannot use asprintf here since this property contains two 00023 * null-terminated strings (for compatibility reasons). Instead, we 00024 * use strdup() on both strings */ 00025 char *new_class = xcb_get_property_value(prop); 00026 00027 FREE(win->class_instance); 00028 FREE(win->class_class); 00029 00030 win->class_instance = sstrdup(new_class); 00031 if ((strlen(new_class) + 1) < xcb_get_property_value_length(prop)) 00032 win->class_class = sstrdup(new_class + strlen(new_class) + 1); 00033 else win->class_class = NULL; 00034 LOG("WM_CLASS changed to %s (instance), %s (class)\n", 00035 win->class_instance, win->class_class); 00036 00037 if (before_mgmt) { 00038 free(prop); 00039 return; 00040 } 00041 00042 run_assignments(win); 00043 00044 free(prop); 00045 } 00046 00047 /* 00048 * Updates the name by using _NET_WM_NAME (encoded in UTF-8) for the given 00049 * window. Further updates using window_update_name_legacy will be ignored. 00050 * 00051 */ 00052 void window_update_name(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) { 00053 if (prop == NULL || xcb_get_property_value_length(prop) == 0) { 00054 DLOG("_NET_WM_NAME not specified, not changing\n"); 00055 FREE(prop); 00056 return; 00057 } 00058 00059 /* Save the old pointer to make the update atomic */ 00060 char *new_name; 00061 if (asprintf(&new_name, "%.*s", xcb_get_property_value_length(prop), 00062 (char*)xcb_get_property_value(prop)) == -1) { 00063 perror("asprintf()"); 00064 DLOG("Could not get window name\n"); 00065 free(prop); 00066 return; 00067 } 00068 /* Convert it to UCS-2 here for not having to convert it later every time we want to pass it to X */ 00069 int len; 00070 char *ucs2_name = convert_utf8_to_ucs2(new_name, &len); 00071 if (ucs2_name == NULL) { 00072 LOG("Could not convert _NET_WM_NAME to UCS-2, ignoring new hint\n"); 00073 FREE(new_name); 00074 free(prop); 00075 return; 00076 } 00077 FREE(win->name_x); 00078 FREE(win->name_json); 00079 win->name_json = new_name; 00080 win->name_x = ucs2_name; 00081 win->name_len = len; 00082 win->name_x_changed = true; 00083 LOG("_NET_WM_NAME changed to \"%s\"\n", win->name_json); 00084 00085 win->uses_net_wm_name = true; 00086 00087 if (before_mgmt) { 00088 free(prop); 00089 return; 00090 } 00091 00092 run_assignments(win); 00093 00094 free(prop); 00095 } 00096 00097 /* 00098 * Updates the name by using WM_NAME (encoded in COMPOUND_TEXT). We do not 00099 * touch what the client sends us but pass it to xcb_image_text_8. To get 00100 * proper unicode rendering, the application has to use _NET_WM_NAME (see 00101 * window_update_name()). 00102 * 00103 */ 00104 void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt) { 00105 if (prop == NULL || xcb_get_property_value_length(prop) == 0) { 00106 DLOG("prop == NULL\n"); 00107 FREE(prop); 00108 return; 00109 } 00110 00111 /* ignore update when the window is known to already have a UTF-8 name */ 00112 if (win->uses_net_wm_name) { 00113 free(prop); 00114 return; 00115 } 00116 00117 char *new_name; 00118 if (asprintf(&new_name, "%.*s", xcb_get_property_value_length(prop), 00119 (char*)xcb_get_property_value(prop)) == -1) { 00120 perror("asprintf()"); 00121 DLOG("Could not get legacy window name\n"); 00122 free(prop); 00123 return; 00124 } 00125 00126 LOG("Using legacy window title. Note that in order to get Unicode window " 00127 "titles in i3, the application has to set _NET_WM_NAME (UTF-8)\n"); 00128 00129 FREE(win->name_x); 00130 FREE(win->name_json); 00131 win->name_x = new_name; 00132 win->name_json = sstrdup(new_name); 00133 win->name_len = strlen(new_name); 00134 win->name_x_changed = true; 00135 00136 if (before_mgmt) { 00137 free(prop); 00138 return; 00139 } 00140 00141 run_assignments(win); 00142 00143 free(prop); 00144 } 00145 00146 /* 00147 * Updates the CLIENT_LEADER (logical parent window). 00148 * 00149 */ 00150 void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop) { 00151 if (prop == NULL || xcb_get_property_value_length(prop) == 0) { 00152 DLOG("prop == NULL\n"); 00153 FREE(prop); 00154 return; 00155 } 00156 00157 xcb_window_t *leader = xcb_get_property_value(prop); 00158 if (leader == NULL) { 00159 free(prop); 00160 return; 00161 } 00162 00163 DLOG("Client leader changed to %08x\n", *leader); 00164 00165 win->leader = *leader; 00166 00167 free(prop); 00168 } 00169 00170 /* 00171 * Updates the TRANSIENT_FOR (logical parent window). 00172 * 00173 */ 00174 void window_update_transient_for(i3Window *win, xcb_get_property_reply_t *prop) { 00175 if (prop == NULL || xcb_get_property_value_length(prop) == 0) { 00176 DLOG("prop == NULL\n"); 00177 FREE(prop); 00178 return; 00179 } 00180 00181 xcb_window_t transient_for; 00182 if (!xcb_icccm_get_wm_transient_for_from_reply(&transient_for, prop)) { 00183 free(prop); 00184 return; 00185 } 00186 00187 DLOG("Transient for changed to %08x\n", transient_for); 00188 00189 win->transient_for = transient_for; 00190 00191 free(prop); 00192 } 00193 00194 /* 00195 * Updates the _NET_WM_STRUT_PARTIAL (reserved pixels at the screen edges) 00196 * 00197 */ 00198 void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop) { 00199 if (prop == NULL || xcb_get_property_value_length(prop) == 0) { 00200 DLOG("prop == NULL\n"); 00201 FREE(prop); 00202 return; 00203 } 00204 00205 uint32_t *strut; 00206 if (!(strut = xcb_get_property_value(prop))) { 00207 free(prop); 00208 return; 00209 } 00210 00211 DLOG("Reserved pixels changed to: left = %d, right = %d, top = %d, bottom = %d\n", 00212 strut[0], strut[1], strut[2], strut[3]); 00213 00214 win->reserved = (struct reservedpx){ strut[0], strut[1], strut[2], strut[3] }; 00215 00216 free(prop); 00217 }