externalbars.c (5535B)
1 static ExternalBarStrut *ebarstruts = NULL; 2 static Atom eb_atom_strut = None; 3 static Atom eb_atom_strut_partial = None; 4 static int eb_scanning = 0; 5 6 void 7 externalbars_init_atoms(void) 8 { 9 if (eb_atom_strut == None) 10 eb_atom_strut = XInternAtom(dpy, "_NET_WM_STRUT", False); 11 if (eb_atom_strut_partial == None) 12 eb_atom_strut_partial = XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False); 13 } 14 15 int 16 externalbars_read(Window w, ExternalBarStrut *out) 17 { 18 Atom real; 19 int fmt; 20 unsigned long n, extra; 21 unsigned char *p = NULL; 22 23 externalbars_init_atoms(); 24 memset(out, 0, sizeof *out); 25 out->win = w; 26 27 /* Prefer _NET_WM_STRUT_PARTIAL (12 longs) */ 28 if (XGetWindowProperty(dpy, w, eb_atom_strut_partial, 0L, 12L, False, 29 XA_CARDINAL, &real, &fmt, &n, &extra, &p) == Success && p) { 30 if (n >= 4) { 31 long *s = (long *)p; 32 out->left = (int)s[0]; out->right = (int)s[1]; 33 out->top = (int)s[2]; out->bottom = (int)s[3]; 34 if (n >= 12) { 35 out->left_start_y = (int)s[4]; out->left_end_y = (int)s[5]; 36 out->right_start_y = (int)s[6]; out->right_end_y = (int)s[7]; 37 out->top_start_x = (int)s[8]; out->top_end_x = (int)s[9]; 38 out->bottom_start_x = (int)s[10]; out->bottom_end_x = (int)s[11]; 39 } else { 40 out->left_start_y = 0; out->left_end_y = sh; 41 out->right_start_y = 0; out->right_end_y = sh; 42 out->top_start_x = 0; out->top_end_x = sw; 43 out->bottom_start_x = 0; out->bottom_end_x = sw; 44 } 45 XFree(p); 46 if (out->left == 0 && out->right == 0 && 47 out->top == 0 && out->bottom == 0) 48 return 0; 49 return 1; 50 } 51 XFree(p); 52 p = NULL; 53 } 54 55 /* Fallback: plain _NET_WM_STRUT (4 longs) */ 56 if (XGetWindowProperty(dpy, w, eb_atom_strut, 0L, 4L, False, 57 XA_CARDINAL, &real, &fmt, &n, &extra, &p) == Success && p) { 58 if (n >= 4) { 59 long *s = (long *)p; 60 out->left = (int)s[0]; out->right = (int)s[1]; 61 out->top = (int)s[2]; out->bottom = (int)s[3]; 62 out->left_start_y = 0; out->left_end_y = sh; 63 out->right_start_y = 0; out->right_end_y = sh; 64 out->top_start_x = 0; out->top_end_x = sw; 65 out->bottom_start_x = 0; out->bottom_end_x = sw; 66 XFree(p); 67 if (out->left == 0 && out->right == 0 && 68 out->top == 0 && out->bottom == 0) 69 return 0; 70 return 1; 71 } 72 XFree(p); 73 } 74 return 0; 75 } 76 77 int 78 externalbars_hasstrut(Window w) 79 { 80 ExternalBarStrut tmp; 81 return externalbars_read(w, &tmp); 82 } 83 84 void 85 externalbars_begin_scan(void) 86 { 87 eb_scanning = 1; 88 } 89 90 void 91 externalbars_end_scan(void) 92 { 93 eb_scanning = 0; 94 externalbars_reapply_all(); 95 } 96 97 void 98 externalbars_register(Window w) 99 { 100 ExternalBarStrut tmp, *sw; 101 102 if (!externalbars_read(w, &tmp)) 103 return; 104 105 for (sw = ebarstruts; sw; sw = sw->next) { 106 if (sw->win == w) { 107 ExternalBarStrut *nxt = sw->next; 108 *sw = tmp; 109 sw->next = nxt; 110 if (!eb_scanning) 111 externalbars_reapply_all(); 112 return; 113 } 114 } 115 116 sw = ecalloc(1, sizeof(ExternalBarStrut)); 117 *sw = tmp; 118 sw->next = ebarstruts; 119 ebarstruts = sw; 120 if (!eb_scanning) 121 externalbars_reapply_all(); 122 } 123 124 void 125 externalbars_unregister(Window w) 126 { 127 ExternalBarStrut **prev = &ebarstruts, *sw; 128 129 while ((sw = *prev)) { 130 if (sw->win == w) { 131 *prev = sw->next; 132 free(sw); 133 if (!eb_scanning) 134 externalbars_reapply_all(); 135 return; 136 } 137 prev = &sw->next; 138 } 139 } 140 141 void 142 externalbars_apply(Monitor *m) 143 { 144 ExternalBarStrut *s; 145 int top = 0, bottom = 0, left = 0, right = 0; 146 147 for (s = ebarstruts; s; s = s->next) { 148 if (s->top > 0) { 149 if (s->top_start_x < m->mx + m->mw && s->top_end_x > m->mx) { 150 int local = s->top - m->my; 151 if (local > 0) 152 top = MAX(top, MIN(local, m->mh)); 153 } 154 } 155 if (s->bottom > 0) { 156 if (s->bottom_start_x < m->mx + m->mw && s->bottom_end_x > m->mx) { 157 int local = s->bottom - (sh - (m->my + m->mh)); 158 if (local > 0) 159 bottom = MAX(bottom, MIN(local, m->mh)); 160 } 161 } 162 if (s->left > 0) { 163 if (s->left_start_y < m->my + m->mh && s->left_end_y > m->my) { 164 int local = s->left - m->mx; 165 if (local > 0) 166 left = MAX(left, MIN(local, m->mw)); 167 } 168 } 169 if (s->right > 0) { 170 if (s->right_start_y < m->my + m->mh && s->right_end_y > m->my) { 171 int local = s->right - (sw - (m->mx + m->mw)); 172 if (local > 0) 173 right = MAX(right, MIN(local, m->mw)); 174 } 175 } 176 } 177 178 m->strut_top = top; 179 m->strut_bottom = bottom; 180 m->strut_left = left; 181 m->strut_right = right; 182 } 183 184 void 185 externalbars_reapply_all(void) 186 { 187 Monitor *m; 188 189 for (m = mons; m; m = m->next) { 190 externalbars_apply(m); 191 updatebarpos(m); 192 } 193 if (selmon) 194 arrange(NULL); 195 }