infinitetags.c (5923B)
1 int 2 getcurrenttag(Monitor *m) { 3 unsigned int i; 4 for (i = 0; i < LENGTH(tags) && !(m->tagset[m->seltags] & (1 << i)); i++); 5 return i < LENGTH(tags) ? i : 0; 6 } 7 8 void 9 homecanvas(const Arg *arg) { 10 Client *c; 11 int tagidx = getcurrenttag(selmon); 12 int cx = selmon->canvas[tagidx].cx; 13 int cy = selmon->canvas[tagidx].cy; 14 15 for (c = selmon->clients; c; c = c->next) { 16 if ((c->tags & (1 << tagidx)) && !c->is_pinned) { 17 c->x -= cx; 18 c->y -= cy; 19 XMoveWindow(dpy, c->win, c->x, c->y); 20 } 21 } 22 23 selmon->canvas[tagidx].cx = 0; 24 selmon->canvas[tagidx].cy = 0; 25 drawbar(selmon); 26 XFlush(dpy); 27 } 28 29 void 30 movecanvas(const Arg *arg) 31 { 32 if (selmon->lt[selmon->sellt]->arrange != NULL) 33 return; 34 if (selmon->sel && selmon->sel->isfullscreen) 35 return; 36 37 int tagidx = getcurrenttag(selmon); 38 int dx = 0, dy = 0; 39 40 #ifndef MOVE_CANVAS_STEP 41 #define MOVE_CANVAS_STEP 120 42 #endif 43 44 switch(arg->i) { 45 case 0: dx = -MOVE_CANVAS_STEP; break; 46 case 1: dx = MOVE_CANVAS_STEP; break; 47 case 2: dy = -MOVE_CANVAS_STEP; break; 48 case 3: dy = MOVE_CANVAS_STEP; break; 49 } 50 51 selmon->canvas[tagidx].cx -= dx; 52 selmon->canvas[tagidx].cy -= dy; 53 54 Client *c; 55 for (c = selmon->clients; c; c = c->next) { 56 if (ISVISIBLE(c) && !c->is_pinned) { 57 c->x -= dx; 58 c->y -= dy; 59 XMoveWindow(dpy, c->win, c->x, c->y); 60 } 61 } 62 63 drawbar(selmon); 64 } 65 66 void 67 movecanvasmouse(const Arg *arg) { 68 if (selmon->lt[selmon->sellt]->arrange != NULL) 69 return; 70 if (selmon->sel && selmon->sel->isfullscreen) 71 return; 72 int start_x, start_y; 73 Window dummy; 74 int di; 75 unsigned int dui; 76 int tagidx = getcurrenttag(selmon); 77 float multiplier = arg ? arg->f : 1.0f; 78 float accum_x = 0.0f, accum_y = 0.0f; 79 #if ZOOM 80 float zoom_val = zoom_value(); 81 #endif 82 83 84 #if LOCK_MOVE_RESIZE_REFRESH_RATE 85 Time lasttime = 0; 86 #endif 87 88 if (!XQueryPointer(dpy, root, &dummy, &dummy, &start_x, &start_y, &di, &di, &dui)) 89 return; 90 91 if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, 92 None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) 93 return; 94 95 XEvent ev; 96 do { 97 XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); 98 99 switch (ev.type) { 100 case MotionNotify: 101 { 102 #if LOCK_MOVE_RESIZE_REFRESH_RATE 103 if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate)) 104 continue; 105 lasttime = ev.xmotion.time; 106 #endif 107 int nx = ev.xmotion.x - start_x; 108 int ny = ev.xmotion.y - start_y; 109 110 /* accumulate subpixel remainder to not lose fractional pixels: 111 multiplier=0.5, nx=1: accum=0.5, dx=0 --- skip 112 nx=1: accum=1.0, dx=1 --- move 113 */ 114 #if !ZOOM 115 accum_x += nx * multiplier; 116 accum_y += ny * multiplier; 117 #else 118 accum_x += nx * multiplier / zoom_val; 119 accum_y += ny * multiplier / zoom_val; 120 #endif 121 122 int dx = (int)accum_x; 123 int dy = (int)accum_y; 124 125 accum_x -= dx; 126 accum_y -= dy; 127 128 for (Client *c = selmon->clients; c; c = c->next) { 129 if ((c->tags & (1 << tagidx)) && !c->is_pinned) { 130 c->x += dx; 131 c->y += dy; 132 XMoveWindow(dpy, c->win, c->x, c->y); 133 } 134 } 135 136 selmon->canvas[tagidx].cx += dx; 137 selmon->canvas[tagidx].cy += dy; 138 drawbar(selmon); 139 start_x = ev.xmotion.x; 140 start_y = ev.xmotion.y; 141 } break; 142 } 143 } while (ev.type != ButtonRelease); 144 145 XUngrabPointer(dpy, CurrentTime); 146 } 147 148 void 149 save_canvas_positions(Monitor *m) { 150 Client *c; 151 int tagidx = getcurrenttag(m); 152 153 m->canvas[tagidx].saved_cx = m->canvas[tagidx].cx; 154 m->canvas[tagidx].saved_cy = m->canvas[tagidx].cy; 155 156 for (c = m->clients; c; c = c->next) { 157 if (ISVISIBLE(c)) { 158 c->saved_cx = c->x + m->canvas[tagidx].cx; 159 c->saved_cy = c->y + m->canvas[tagidx].cy; 160 c->saved_cw = c->w; 161 c->saved_ch = c->h; 162 c->was_on_canvas = 1; 163 } 164 } 165 } 166 167 void 168 restore_canvas_positions(Monitor *m) { 169 Client *c; 170 int tagidx = getcurrenttag(m); 171 172 m->canvas[tagidx].cx = m->canvas[tagidx].saved_cx; 173 m->canvas[tagidx].cy = m->canvas[tagidx].saved_cy; 174 175 for (c = m->clients; c; c = c->next) { 176 if (ISVISIBLE(c) && c->was_on_canvas) { 177 if (c->isfullscreen) 178 continue; 179 c->isfloating = 1; 180 181 int target_x = c->saved_cx - m->canvas[tagidx].cx; 182 int target_y = c->saved_cy - m->canvas[tagidx].cy; 183 184 c->x = target_x; 185 c->y = target_y; 186 c->w = c->saved_cw; 187 c->h = c->saved_ch; 188 189 XMoveResizeWindow(dpy, c->win, target_x, target_y, c->w, c->h); 190 191 configure(c); 192 } 193 } 194 XSync(dpy, False); 195 } 196 197 void 198 centerwindow(const Arg *arg) 199 { 200 Client *c = (arg && arg->v) ? (Client *)arg->v : selmon->sel; 201 202 if (!c || !c->mon || c->mon->lt[c->mon->sellt]->arrange != NULL) 203 return; 204 205 if (c->is_pinned) 206 return; 207 208 Monitor *m = c->mon; 209 int tagidx = getcurrenttag(m); 210 211 int dx = m->wx + (m->ww - WIDTH(c)) / 2 - c->x; 212 int dy = m->wy + (m->wh / 2) - (c->y + HEIGHT(c) / 2); 213 214 if (dx == 0 && dy == 0) 215 return; 216 217 Client *tmp; 218 for (tmp = m->clients; tmp; tmp = tmp->next) { 219 if (ISVISIBLE(tmp) && !tmp->is_pinned) { 220 tmp->x += dx; 221 tmp->y += dy; 222 XMoveWindow(dpy, tmp->win, tmp->x, tmp->y); 223 } 224 } 225 226 m->canvas[tagidx].cx += dx; 227 m->canvas[tagidx].cy += dy; 228 229 drawbar(m); 230 } 231 232 void 233 pinwindow(const Arg *arg) { 234 Client *c = selmon->sel; 235 if (!c) 236 return; 237 c->is_pinned = !c->is_pinned; 238 restack(selmon); 239 drawbar(selmon); 240 }