/* Transfert a client to a tag * \param c Client pointer * \param tag Tag */ void tag_transfert(Client *c, int tag) { screen_get_sel(); CHECK(c); if(tag <= 0) tag = 1; if(tag > conf.ntag[selscreen]) return; c->tag = tag; c->screen = selscreen; arrange(c->screen, True); client_focus_next(c); client_update_attributes(c); tags[c->screen][tag].request_update = True; return; }
/** Toggle the selected client to free * \param cmd uicb_t type unused */ void uicb_togglefree(uicb_t cmd) { (void)cmd; if(!sel || sel->screen != screen_get_sel() || (sel->flags & FSSFlag)) return; sel->flags ^= FreeFlag; if((sel->flags & FreeFlag)) { sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag); client_moveresize(sel, sel->free_geo, True); client_raise(sel); } else { sel->free_geo = sel->geo; sel->ogeo = sel->geo; } client_update_attributes(sel); tags[selscreen][seltag[selscreen]].layout.func(selscreen); return; }
/** Move the client with the mouse * \param c Client pointer */ static void mouse_move(Client *c) { int ocx, ocy, mx, my; int dint; uint duint; Window dw; XRectangle geo = c->geo; XGCValues xgc; GC gci; XEvent ev; if((c->flags & MaxFlag) || (c->flags & FSSFlag)) return; ocx = c->geo.x; ocy = c->geo.y; if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync, None, cursor[CurMove], CurrentTime) != GrabSuccess) return; if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag)) XGrabServer(dpy); /* Set the GC for the rectangle */ xgc.function = GXinvert; xgc.subwindow_mode = IncludeInferiors; xgc.line_width = BORDH; gci = XCreateGC(dpy, ROOT, GCFunction | GCSubwindowMode | GCLineWidth, &xgc); if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag)) mouse_dragborder(c->geo, gci); XQueryPointer(dpy, ROOT, &dw, &dw, &mx, &my, &dint, &dint, &duint); do { XMaskEvent(dpy, MouseMask | SubstructureRedirectMask, &ev); screen_get_sel(); if(ev.type == MotionNotify) { mouse_move_tile_client(&c); mouse_move_tag_client(c); /* To move a client normally, in freelayout */ if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag)) { mouse_dragborder(geo, gci); geo.x = (ocx + (ev.xmotion.x - mx)); geo.y = (ocy + (ev.xmotion.y - my)); /* * Need to draw 2 times the same rectangle because * it is draw with the revert color; revert + revert = normal */ mouse_dragborder(geo, gci); } } else if(ev.type == MapRequest || ev.type == ConfigureRequest) getevent(ev); } while(ev.type != ButtonRelease); /* One time again to delete all the trace on the window */ if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag)) { mouse_dragborder(geo, gci); client_moveresize(c, geo, False); frame_update(c); XUngrabServer(dpy); } client_update_attributes(c); XUngrabPointer(dpy, CurrentTime); XFreeGC(dpy, gci); return; }
void mouse_resize(Client *c) { XRectangle geo = c->geo, ogeo = c->geo; Position pos = Right; XEvent ev; Window w; int d, u, omx, omy; XGCValues xgc; GC gci; float mwf = tags[selscreen][seltag[selscreen]].mwfact; if((c->flags & MaxFlag) || (c->flags & LMaxFlag) || (c->flags & FSSFlag)) return; XQueryPointer(dpy, ROOT, &w, &w, &omx, &omy, &d, &d, (uint *)&u); if((omx - c->geo.x) < (c->geo.width / 2)) pos = Left; if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync, None, cursor[((c->flags & TileFlag) ? CurResize : ((pos == Right) ? CurRightResize : CurLeftResize))], CurrentTime) != GrabSuccess) return; if(!(c->flags & TileFlag)) XGrabServer(dpy); /* Set the GC for the rectangle */ xgc.function = GXinvert; xgc.subwindow_mode = IncludeInferiors; xgc.line_width = BORDH; gci = XCreateGC(dpy, ROOT, GCFunction | GCSubwindowMode | GCLineWidth, &xgc); if(!(c->flags & TileFlag)) { if(pos == Right) XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geo.width + conf.client.borderheight, c->geo.height); else XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 0, c->geo.height); mouse_dragborder(c->geo, gci); } do { XMaskEvent(dpy, MouseMask | SubstructureRedirectMask, &ev); if(ev.type == MotionNotify) { /* To resize MWFACT in tile mode */ if((c->flags & TileFlag) && tags[selscreen][seltag[selscreen]].layout.func != grid_vertical && tags[selscreen][seltag[selscreen]].layout.func != grid_horizontal) { if(tags[selscreen][seltag[selscreen]].layout.func == tile) mwf += (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width); else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left) mwf -= (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width); else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top) mwf -= (ROUND(ev.xmotion.y_root) - omy) / (sgeo[c->screen].height); else mwf += (ROUND(ev.xmotion.y_root) - omy) / (sgeo[c->screen].height); omx = ROUND(ev.xmotion.x_root); omy = ROUND(ev.xmotion.y_root); tags[selscreen][seltag[selscreen]].mwfact = (mwf < 0.05) ? 0.05 : ((mwf > 0.95) ? 0.95 : mwf); } /* Free mode */ else if(!(c->flags & TileFlag)) { mouse_dragborder(geo, gci); if(pos == Right) { geo.width = ((ev.xmotion.x - c->geo.x < c->minw) ? c->minw : ev.xmotion.x - c->geo.x); geo.height = ((ev.xmotion.y - c->geo.y < c->minh) ? c->minh : ev.xmotion.y - c->geo.y); } else { geo.x = (geo.width != c->maxw) ? c->geo.x - (c->geo.x - ev.xmotion.x) : geo.x; geo.width = ((c->geo.width + (c->geo.x - geo.x) < c->minw) ? c->minw && (geo.x = (c->geo.x + c->geo.width) - c->minw) : c->geo.width + (c->geo.x - geo.x)); geo.height = ((ev.xmotion.y - c->geo.y <= c->minh) ? c->minh : ev.xmotion.y - c->geo.y); } client_geo_hints(&geo, c); mouse_dragborder((ogeo = geo), gci); XSync(dpy, False); } } } while(ev.type != ButtonRelease); if(!(c->flags & TileFlag)) { mouse_dragborder(ogeo, gci); client_moveresize(c, geo, True); frame_update(c); XUngrabServer(dpy); } else tags[selscreen][seltag[selscreen]].layout.func(c->screen); client_update_attributes(c); XUngrabPointer(dpy, CurrentTime); XFreeGC(dpy, gci); return; }
/** Scan if there are windows on X * for manage it */ static void scan(void) { uint n; XWindowAttributes wa; Window usl, usl2, *w = NULL; Atom rt; int s, rf, tag = -1, screen = -1, free = -1, i; ulong ir, il; uchar *ret; Client *c; s = screen_count(); if(XQueryTree(dpy, ROOT, &usl, &usl2, &w, &n)) for(i = n - 1; i != -1; --i) { XGetWindowAttributes(dpy, w[i], &wa); if(!wa.override_redirect && wa.map_state == IsViewable) { if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_TAG"), 0, 32, False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret) { tag = *ret; XFree(ret); } if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_SCREEN"), 0, 32, False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret) { screen = *ret; XFree(ret); } if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_ISFREE"), 0, 32, False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret) { free = *ret; XFree(ret); } c = client_manage(w[i], &wa, False); if(tag != -1 && tag != MAXTAG + 1) c->tag = tag; if(screen != -1 && screen <= s - 1) c->screen = screen; if(free != -1) c->flags |= (free) ? FreeFlag : 0; client_update_attributes(c); } } /* Set update layout request */ for(c = clients; c; c = c->next) { if(c->tag > (uint)conf.ntag[c->screen]) c->tag = conf.ntag[c->screen]; tags[c->screen][c->tag].request_update = True; } for(i = 0; i < s; ++i) arrange(i, True); XFree(w); return; }