/** Toggle the selected client to max * \param cmd uicb_t type unused */ void uicb_togglemax(uicb_t cmd) { (void)cmd; if(!sel || ishide(sel, selscreen) || (sel->flags & HintFlag)|| (sel->flags & FSSFlag)) return; if(!(sel->flags & MaxFlag)) { sel->ogeo = sel->geo; sel->free_geo = sel->geo; sel->flags &= ~(TileFlag | FreeFlag); client_maximize(sel); XRaiseWindow(dpy, sel->frame); sel->flags |= MaxFlag; } else { sel->geo = sel->ogeo; client_moveresize(sel, sel->geo, True); sel->flags &= ~MaxFlag; tags[selscreen][seltag[selscreen]].layout.func(selscreen); } 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; }
/** Manage _NET_WM_STATE_* ewmh */ void ewmh_manage_net_wm_state(long data_l[], Client *c) { /* Manage _NET_WM_STATE_FULLSCREEN */ if(data_l[1] == (long)net_atom[net_wm_state_fullscreen]) { if(data_l[0] == _NET_WM_STATE_ADD && !(c->flags & FSSFlag)) { c->screen = screen_get_with_geo(c->geo.x, c->geo.y); c->flags &= ~UnmapFlag; XMapWindow(dpy, c->win); XReparentWindow(dpy, c->win, ROOT, spgeo[c->screen].x, spgeo[c->screen].y); XResizeWindow(dpy, c->win, spgeo[c->screen].width, spgeo[c->screen].height); XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (uchar *)&net_atom[net_wm_state_fullscreen], 1); c->tmp_geo = c->geo; if(c->flags & FreeFlag) c->ogeo = c->geo; c->flags |= (FSSFlag | MaxFlag); client_raise(c); client_focus(c); XUnmapWindow(dpy, c->frame); } else if(data_l[0] == _NET_WM_STATE_REMOVE && (c->flags & FSSFlag)) { XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (uchar *)0, 0); c->flags &= ~(FSSFlag | MaxFlag); client_map(c); XReparentWindow(dpy, c->win, c->frame, BORDH, TBARH); client_moveresize(c, c->tmp_geo, False); } } /* Manage _NET_WM_STATE_STICKY */ else if(data_l[1] == (long)net_atom[net_wm_state_sticky]) { /* == client_ignore_tag */ c->tag = MAXTAG + 1; arrange(c->screen, True); } /* Manage _NET_WM_STATE_DEMANDS_ATTENTION */ else if(data_l[1] == (long)net_atom[net_wm_state_demands_attention]) { if(data_l[0] == _NET_WM_STATE_ADD) client_urgent(c, True); if(data_l[0] == _NET_WM_STATE_REMOVE) if(c == sel) client_focus(NULL); } return; }
/** ConfigureRequesthandle events * \param ev XConfigureRequestEvent pointer */ static void configureevent(XConfigureRequestEvent *ev) { XWindowChanges wc; Client *c; /* Check part */ if((c = client_gb_win(ev->window)) || (c = client_gb_win(ev->window))) { CHECK(!(c->flags & LMaxFlag)); CHECK(!(c->flags & MaxFlag)); CHECK(!(c->flags & FSSFlag)); } if((c = client_gb_win(ev->window))) { if(ev->value_mask & CWX) c->geo.x = ev->x + BORDH; if(ev->value_mask & CWY) c->geo.y = ev->y + TBARH; if(ev->value_mask & CWWidth) c->geo.width = ev->width; if(ev->value_mask & CWHeight) c->geo.height = ev->height; if(c->flags & FreeFlag || !(c->flags & (TileFlag | LMaxFlag))) client_moveresize(c, c->geo, False); else { client_configure(c); arrange(c->screen, True); } } else { wc.x = ev->x; wc.y = ev->y; wc.width = ev->width; wc.height = ev->height; wc.border_width = ev->border_width; wc.sibling = ev->above; wc.stack_mode = ev->detail; XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); } return; }
static void event_configureevent(XEvent *e) { XConfigureRequestEvent *ev = &e->xconfigurerequest; XWindowChanges wc; struct client *c; if((c = client_gb_win(ev->window))) { if(c->flags & CLIENT_FREE) { if(ev->value_mask & CWX) c->geo.x = ev->x; if(ev->value_mask & CWY) c->geo.y = ev->y - c->tbarw - c->border - c->border; if(ev->value_mask & CWWidth) c->geo.w = ev->width + c->border + c->border; if(ev->value_mask & CWHeight) c->geo.h = ev->height + c->tbarw + c->border; client_moveresize(c, &c->geo); } else { if(ev->value_mask & CWWidth) _fac_resize(c, Right, ev->width - c->wgeo.w); if(ev->value_mask & CWHeight) _fac_resize(c, Bottom, ev->height - c->wgeo.h); client_apply_tgeo(c->tag); } } else { wc.x = ev->x; wc.y = ev->y; wc.width = ev->width; wc.height = ev->height; wc.border_width = ev->border_width; wc.sibling = ev->above; wc.stack_mode = ev->detail; XConfigureWindow(EVDPY(e), ev->window, ev->value_mask, &wc); } }
/** The free layout function */ void freelayout(int screen) { Client *c; (void)screen; for(c = clients; c; c = c->next) if(!ishide(c, selscreen) && c->screen == screen_get_sel() && !(c->flags & MaxFlag)) { client_moveresize(c, c->free_geo, True); c->flags &= ~(TileFlag | LMaxFlag); } ewmh_update_current_tag_prop(); return; }
void ewmh_manage_state(long data[], struct client *c) { /* _NET_WM_STATE_FULLSCREEN */ if(data[1] == (long)W->net_atom[net_wm_state_fullscreen] || data[2] == (long)W->net_atom[net_wm_state_fullscreen]) { if(data[0] == _NET_WM_STATE_ADD || (data[0] == _NET_WM_STATE_TOGGLE && !(c->flags & CLIENT_FULLSCREEN))) { c->flags |= CLIENT_FULLSCREEN; XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (unsigned char*)&W->net_atom[net_wm_state_fullscreen], 1); XReparentWindow(W->dpy, c->win, W->root, c->screen->geo.x, c->screen->geo.y); XResizeWindow(W->dpy, c->win, c->screen->geo.w, c->screen->geo.h); if(c->tag) client_focus(c); XRaiseWindow(W->dpy, c->win); } else { c->flags &= ~CLIENT_FULLSCREEN; XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (unsigned char*)0, 0); XReparentWindow(W->dpy, c->win, c->frame, c->wgeo.x, c->wgeo.y); if(c->flags & CLIENT_FREE) client_moveresize(c, &c->geo); else layout_fix_hole(c); } } }
/** Arrange clients after a client close *\param ghost Ghost client */ void split_arrange_closed(Client *ghost) { Position p; bool b = False; Geo cgeo; Client *c, *cc; int screen = ghost->screen; int tag = (ghost->tag ? ghost->tag : seltag[screen]); /* Use ghost client properties to fix holes in tile * .--. ~ ~ * /xx \ ~ ~ * ~~\O _ (____ ~ * __.| .--'-==~ ~ * '---\ '. ~ , ~ * '. '-.___.-'/ ~ * '-.__ _.' ~ * ````` ~ */ /* Search for single parent for easy resize * Example case: * ___________ ___________ * | | B | -> -> | | | * | A |_____| -> Close -> | A | B | * | | C | -> C -> | |v v v| * |_____|_____| -> -> |_____|_____| */ for(p = Right; p < Center; ++p) if((c = client_get_next_with_direction(ghost, p))) if(CFACTOR_CHECK2(ghost->frame_geo, c->frame_geo, p)) { _split_arrange_size(ghost->wrgeo, &c->wrgeo, p); cfactor_clean(c); client_moveresize(c, (c->pgeo = c->wrgeo), (tags[screen][tag].flags & ResizeHintFlag)); return; } /* Check row parents for full resize * Example case: * ___________ ___________ * | | B | -> -> | << B | * | A |_____| -> Close -> |___________| * | | C | -> A -> | << C | * |_____|_____| -> -> |___________| */ for(p = Right; p < Center && !b; ++p) if((c = client_get_next_with_direction(ghost, p)) && _split_check_row_dir(c, ghost, p)) { for(cgeo = c->frame_geo, cc = tiled_client(c->screen, SLIST_FIRST(&clients)); cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next))) if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p)) && SPLIT_CHECK_ROW(cc->frame_geo, ghost->frame_geo, p)) { _split_arrange_size(ghost->wrgeo, &cc->wrgeo, p); cfactor_clean(cc); client_moveresize(cc, (cc->pgeo = cc->wrgeo), (tags[screen][tag].flags & ResizeHintFlag)); b = True; } } return; }
/** Mirror layout function * \param screen Screen to execute this function * \param horizont To specify the mirror mode (vertical/horizontal) */ static void mirror(int screen, Bool horizontal) { Client *c; XRectangle sg = sgeo[screen]; XRectangle mastergeo = {sg.x, sg.y, sg.width, sg.height}; XRectangle cgeo = {sg.x, sg.y , sg.width, sg.height}; XRectangle nextg[2]; uint i, n, tilesize = 0, mwfact; uint nmaster = tags[screen][seltag[screen]].nmaster; int pa, imp; Bool isp = 0; memset(nextg, 0, sizeof(nextg)); for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); CHECK(n); /* Fix nmaster */ nmaster = (n < nmaster) ? n : nmaster; imp = ((n - (nmaster - 1)) / 2); pa = ((n - (nmaster - 1)) / 2) - (((n - (nmaster - 1)) % 2) ? 0 : 1); /* Set mwfact */ if(tags[screen][seltag[screen]].mwfact < 0.55) tags[screen][seltag[screen]].mwfact = 0.55; mwfact = tags[screen][seltag[screen]].mwfact * ((horizontal) ? sg.height : sg.width); /* Master size */ if(horizontal) { mastergeo.width = (sg.width / nmaster) - (BORDH * 2); mastergeo.height -= BORDH; } else { mastergeo.width -= BORDH * 2; mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH * 2)); } if(n == nmaster + 1) { if(horizontal) { mastergeo.height = mwfact - ((BORDH * 2) + TBARH); tilesize = (sg.height - mastergeo.height) - ((BORDH * 2) + TBARH); } else { mastergeo.width = mwfact - (BORDH * 3); tilesize = (sg.width - mastergeo.width) - (BORDH * 4); } } if(n > nmaster + 1) { if(horizontal) { mastergeo.y = (sg.y + (sg.height - mwfact)) + TBARH + BORDH; mastergeo.height = (2 * mwfact - sg.height) - ((BORDH * 3) + (TBARH * 2)); tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH * 2)); } else { mastergeo.x = (sg.x + (sg.width - mwfact)) + BORDH; mastergeo.width = ((2 * mwfact - sg.width) - (BORDH * 4)); tilesize = (mwfact - mastergeo.width) - (BORDH * 5); } } for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) { /* Set client property */ c->flags &= ~(MaxFlag | LMaxFlag); c->flags |= TileFlag; if(i < nmaster) { cgeo = mastergeo; /* Master remainder */ if(i + 1 == nmaster) { if(horizontal) cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2)); else cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH); } } else { if(horizontal) cgeo.height = tilesize; else cgeo.width = tilesize; if((i + nmaster) % 2) { isp = 1; if(horizontal) { cgeo.y = sg.y; cgeo.width = (sg.width / pa) - (BORDH * 2); } else { cgeo.x = sg.x; cgeo.height = (sg.height / pa) - (TBARH + (BORDH * 2)); } } else { isp = 0; if(horizontal) { cgeo.y = (sg.y + mwfact) - BORDH; cgeo.width = (sg.width / imp) - (BORDH * 2); } else { cgeo.x = (sg.x + mwfact) - BORDH; cgeo.height = (sg.height / imp) - (TBARH + (BORDH * 2)); } } /* Remainder */ if(i + 1 == n || i + 1 == n - 1) { if(horizontal) cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2)); else cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH); } } client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint); if(i >= nmaster) nextg[!isp] = c->geo; /* Next y/x position */ if(i >= nmaster - 1) { if(horizontal) { if(i == nmaster || i == nmaster - 1) cgeo.x = sg.x; else cgeo.x = nextg[isp].x + nextg[isp].width + BORDH * 2; } else { if(i == nmaster || i == nmaster - 1) cgeo.y = sg.y; else cgeo.y = nextg[isp].y + nextg[isp].height + BORDH + TBARH; } } else if (i <= nmaster - 1) { if(horizontal) mastergeo.x = c->geo.x + c->geo.width + BORDH * 2; else mastergeo.y = c->geo.y + c->geo.height + BORDH + TBARH; } } ewmh_update_current_tag_prop(); return; }
/** Multi tile function * \param type Postion type { Top, Bottom, Left, Right } */ static void multi_tile(int screen, Position type) { Client *c; XRectangle sg = sgeo[screen]; XRectangle mastergeo = {sg.x, sg.y, 0, 0}; XRectangle cgeo = {sg.x, sg.y, 0, 0}; uint i, n, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster; for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); CHECK(n); /* FIX NMASTER */ nmaster = (n < nmaster) ? n : nmaster; /* SET MWFACT */ mwfact = (type == Top || type == Bottom) ? tags[screen][seltag[screen]].mwfact * sg.height : tags[screen][seltag[screen]].mwfact * sg.width; /* MASTER SIZE */ if(type == Top || type == Bottom) { if(type == Top) mastergeo.y = (n <= nmaster) ? (uint)sg.y : sg.y + (sg.height - mwfact) - BORDH; mastergeo.width = (sg.width / nmaster) - (BORDH * 4); mastergeo.height = (n <= nmaster) ? (uint)(sg.height - BORDH) : mwfact; } else { if(type == Left) mastergeo.x = (n <= nmaster) ? (uint)sg.x : (sg.x + sg.width) - mwfact - (BORDH * 2); mastergeo.width = (n <= nmaster) ? (uint)(sg.width - (BORDH * 2)) : mwfact; mastergeo.height = (sg.height / nmaster) - BORDH; } /* TILED SIZE */ if(n > nmaster) { if(type == Top || type == Bottom) tilesize = sg.width / (n - nmaster) - (BORDH * 4); else tilesize = sg.height / (n - nmaster) - ((BORDH * 2) + TBARH); } for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) { /* Set client property */ c->flags &= ~(MaxFlag | LMaxFlag); c->flags |= TileFlag; /* MASTER */ if(i < nmaster) { cgeo.width = mastergeo.width; cgeo.height = mastergeo.height; if(type == Top || type == Bottom) cgeo.y = mastergeo.y; else { cgeo.x = mastergeo.x; cgeo.height -= (TBARH + BORDH); } } /* TILED */ else { if(i == nmaster) { switch(type) { case Top: case Left: cgeo.y = sg.y; cgeo.x = sg.x; break; case Bottom: cgeo.y += mastergeo.height + TBARH + BORDH; cgeo.x = sg.x; break; default: case Right: cgeo.x += mastergeo.width + (BORDH * 2); cgeo.y = sg.y; break; } } if(type == Top || type == Bottom) { cgeo.width = tilesize; cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH * 2); } else { cgeo.width = sg.width - mastergeo.width - (BORDH * 4); cgeo.height = tilesize; } } /* REMAINDER */ if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster)) { if(type == Top || type == Bottom) cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2))); else cgeo.height = (sg.y + sg.height) - cgeo.y - BORDH; } /* Magic instant */ client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint); /* Set the position of the next client */ if(type == Top || type == Bottom) cgeo.x = c->geo.x + c->geo.width + (BORDH * 2); else cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH; } ewmh_update_current_tag_prop(); return; }
/** Grid layout function */ static void grid(int screen, Bool horizontal) { Client *c; XRectangle sg = sgeo[screen]; XRectangle cgeo = {sg.x, sg.y, 0, 0}; unsigned int i, n, temp, cols, rows, cpcols = 0; for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); CHECK(n); for(rows = 0; rows <= n / 2; ++rows) if(rows * rows >= n) break; cols = (rows && ((rows - 1) * rows) >= n) ? rows - 1 : rows; if(!horizontal) { temp = cols; cols = rows; rows = temp; } for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) { /* Set client property */ c->flags &= ~(MaxFlag | LMaxFlag); c->flags |= TileFlag; ++cpcols; cgeo.width = (sg.width / cols) - (BORDH * 2); cgeo.height = (sg.height / rows) - BORDH; /* Last row's and last client remainder */ if(cpcols == rows || i + 1 == n) cgeo.height = sg.y + sg.height - cgeo.y - BORDH; /* Last column's client remainder */ if(i >= rows * (cols - 1)) cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2))); /* Resize */ client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint); /* Set all the other size with current client info */ cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH; if(cpcols + 1 > rows) { cpcols = 0; cgeo.x = c->geo.x + c->geo.width + (BORDH * 2); cgeo.y = sg.y; } } ewmh_update_current_tag_prop(); 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; }
/** 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; }
/** Manage the client hints *\param c Client pointer */ void ewmh_manage_window_type(Client *c) { Atom *atom, rf; int f; ulong n, il, i; uchar *data = NULL; long ldata[5] = { 0 }; if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_window_type], 0L, 0x7FFFFFFFL, False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n) { atom = (Atom*)data; for(i = 0; i < n; ++i) { /* Manage _NET_WM_WINDOW_TYPE_DOCK & _NET_WM_WINDOW_TYPE_SPLASH */ if(atom[i] == net_atom[net_wm_window_type_dock] || atom[i] == net_atom[net_wm_window_type_splash]) { /* Unmap frame, decoration.. */ client_unmap(c); /* Map only window */ XMapWindow(dpy, c->win); /* Reparent it to ROOT win */ XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y); XRaiseWindow(dpy, c->win); c->flags |= DockFlag; } /* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */ else if(atom[i] == net_atom[net_wm_window_type_dialog]) { c->flags |= FreeFlag; c->flags &= ~(TileFlag | MaxFlag | LMaxFlag); client_moveresize(c, c->ogeo, True); client_focus(c); tags[selscreen][seltag[selscreen]].layout.func(selscreen); } } XFree(data); } /* Get NET_WM_STATE set without sending client message event */ if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_state], 0L, 0x7FFFFFFFL, False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n) { atom = (Atom*)data; for(i = 0; i < n; ++i) { ldata[0] = _NET_WM_STATE_ADD; ldata[1] = atom[i]; ewmh_manage_net_wm_state(ldata, c); } XFree(data); } return; }