diff --git a/CMakeLists.txt b/CMakeLists.txt index 053f7a9..8ced6a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ set(wmfs_src src/init.c src/layout.c src/mouse.c + src/screen.c src/tag.c src/util.c src/wmfs.c) @@ -78,7 +79,8 @@ set(LIBRARIES_TO_LINK ${FREETYPE_LIBRARIES} ${X11_LIBRARIES} confuse - Xft) + Xft + Xinerama) target_link_libraries(wmfs ${LIBRARIES_TO_LINK}) diff --git a/src/barwin.c b/src/barwin.c index 4c9dbec..069a3d8 100644 --- a/src/barwin.c +++ b/src/barwin.c @@ -249,7 +249,8 @@ barwin_refresh_color(BarWindow *bw) void barwin_refresh(BarWindow *bw) { - CHECK(bw); + if(!bw || !bw->dr || !bw->win) + return; XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0); diff --git a/src/client.c b/src/client.c index 6d6eeaf..1943201 100644 --- a/src/client.c +++ b/src/client.c @@ -107,7 +107,6 @@ uicb_client_prev(uicb_t cmd) client_focus(c); client_raise(c); } - arrange(); return; } @@ -131,7 +130,6 @@ uicb_client_next(uicb_t cmd) client_focus(c); client_raise(c); } - arrange(); return; } @@ -150,7 +148,7 @@ client_focus(Client *c) mouse_grabbuttons(sel, False); } - selbytag[seltag] = sel = c; + sel = c; if(c) { @@ -168,8 +166,8 @@ client_focus(Client *c) return; } -/* The following function are the same point : - * find a client membere with a Window {{{ +/* The following function have the same point : + * find a client member with a Window {{{ */ /* Get Client with a window */ @@ -227,6 +225,7 @@ client_focus(Client *c) return c; } + /* }}} */ /** Get a client name @@ -266,7 +265,7 @@ client_hide(Client *c) Bool ishide(Client *c) { - if(c->tag && c->tag == seltag) + if(c->tag && c->tag == seltag[screen_get_sel()]) return False; return True; } @@ -360,11 +359,12 @@ client_manage(Window w, XWindowAttributes *wa) c = emalloc(1, sizeof(Client)); c->win = w; + c->screen = screen_get_sel(); c->ogeo.x = c->geo.x = wa->x; - c->ogeo.y = c->geo.y = wa->y + sgeo.y; + c->ogeo.y = c->geo.y = wa->y + TBARH + INFOBARH; c->ogeo.width = c->geo.width = wa->width; c->ogeo.height = c->geo.height = wa->height; - c->tag = seltag; + c->tag = seltag[c->screen]; at.event_mask = PropertyChangeMask; frame_create(c); @@ -399,6 +399,8 @@ client_moveresize(Client *c, XRectangle geo, bool r) { CHECK(c); + int i; + /* Resize hints {{{ */ if(r) { @@ -452,6 +454,13 @@ client_moveresize(Client *c, XRectangle geo, bool r) || c->geo.height != geo.height) { c->geo = geo; + + /* Set the client screen */ + for(i = 0; i < screen_count(); ++i) + if(geo.x >= screen_get_geo(i).x + && geo.x < screen_get_geo(i).x + screen_get_geo(i).width) + c->screen = i; + frame_moveresize(c, geo); XMoveResizeWindow(dpy, c->win, BORDH, BORDH + TBARH, geo.width, geo.height); XSync(dpy, False); diff --git a/src/config.c b/src/config.c index 92faeb5..0917474 100644 --- a/src/config.c +++ b/src/config.c @@ -484,10 +484,18 @@ init_conf(void) } } - seltag = 1; - prevtag = 0; - for(i = 0; i < conf.ntag; ++i) - tags[i + 1] = conf.tag[i]; + + seltag = emalloc(screen_count(), sizeof(int)); + + //tags = emalloc(screen_count(), sizeof(Tag*)); + + for(j = 0; j < screen_count(); ++j) + { + //tags[j] = emalloc(conf.ntag, sizeof(Tag)); + seltag[j] = 1; + for(i = 0; i < conf.ntag; ++i) + tags[j][i + 1] = conf.tag[i]; + } /* keybind */ conf.nkeybind = cfg_size(cfg_keys, "key"); diff --git a/src/event.c b/src/event.c index 01dfb14..3a2dcf3 100644 --- a/src/event.c +++ b/src/event.c @@ -42,6 +42,8 @@ buttonpress(XButtonEvent *ev) int i; char s[6]; + screen_get_sel(); + /* Titlebar */ if((c = client_gb_titlebar(ev->window))) for(i = 0; i < conf.titlebar.nmouse; ++i) @@ -63,7 +65,7 @@ buttonpress(XButtonEvent *ev) /* Root */ if(ev->window == root) for(i = 0; i < conf.root.nmouse; ++i) - if(conf.root.mouse[i].tag == seltag + if(conf.root.mouse[i].tag == seltag[selscreen] || conf.root.mouse[i].tag < 0) if(ev->button == conf.root.mouse[i].button) if(conf.root.mouse[i].func) @@ -73,7 +75,7 @@ buttonpress(XButtonEvent *ev) for(i = 1; i < conf.ntag + 1; ++i) { ITOA(s, i); - if(ev->window == infobar->tags[i]->win) + if(ev->window == infobar[screen_get_sel()].tags[i]->win) { if(ev->button == Button1) uicb_tag(s); @@ -87,7 +89,7 @@ buttonpress(XButtonEvent *ev) } /* Layout button */ - if(ev->window == infobar->layout_button->win) + if(ev->window == infobar[screen_get_sel()].layout_button->win) { if(ev->button == Button1 || ev->button == Button4) @@ -202,18 +204,21 @@ void expose(XExposeEvent *ev) { Client *c; - int i; + int i, sc; - if(ev->count == 0 - && (ev->window == infobar->bar->win)) - barwin_refresh(infobar->bar); - for(i = 1; i < conf.ntag + 1; ++i) - if(ev->window == infobar->tags[i]->win) - barwin_refresh(infobar->tags[i]); + for(sc = 0; sc > screen_count(); ++sc) + { + if(ev->window == infobar[sc].bar->win) + barwin_refresh(infobar[sc].bar); - if(ev->window == infobar->layout_button->win) - barwin_refresh(infobar->layout_button); + for(i = 1; i < conf.ntag + 1; ++i) + if(ev->window == infobar[sc].tags[i]->win) + barwin_refresh(infobar[sc].tags[i]); + + if(ev->window == infobar[sc].layout_button->win) + barwin_refresh(infobar[sc].layout_button); + } if((c = client_gb_titlebar(ev->window))) frame_update(c); @@ -239,25 +244,17 @@ focusin(XFocusChangeEvent *ev) void grabkeys(void) { - uint i, j; + uint i; KeyCode code; - uint ml[] = - { - LockMask, - numlockmask, - scrolllockmask, - numlockmask|scrolllockmask, - LockMask|scrolllockmask, - LockMask|numlockmask, - LockMask|numlockmask|scrolllockmask - }; XUngrabKey(dpy, AnyKey, AnyModifier, root); for(i = 0; i < conf.nkeybind; ++i) { code = XKeysymToKeycode(dpy, keys[i].keysym); - for(j = 0; j < (sizeof ml / sizeof ml[0]); ++j) - XGrabKey(dpy, code, keys[i].mod|ml[j], root, True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod, root, True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod|LockMask, root, True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod|numlockmask, root, True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod|LockMask|numlockmask, root, True, GrabModeAsync, GrabModeAsync); } return; @@ -275,8 +272,8 @@ keypress(XKeyPressedEvent *ev) keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < conf.nkeybind; ++i) if(keysym == keys[i].keysym - && (keys[i].mod & ~(numlockmask | LockMask | scrolllockmask)) - == (ev->state & ~(numlockmask | LockMask | scrolllockmask)) + && (keys[i].mod & ~(numlockmask | LockMask)) + == (ev->state & ~(numlockmask | LockMask)) && keys[i].func) keys[i].func(keys[i].cmd); @@ -372,6 +369,7 @@ unmapnotify(XUnmapEvent *ev) void getevent(XEvent ev) { + int st; switch (ev.type) diff --git a/src/frame.c b/src/frame.c index 23b581e..7252060 100644 --- a/src/frame.c +++ b/src/frame.c @@ -87,7 +87,7 @@ frame_create(Client *c) CWIN(c->left, c->frame, 0, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, color_enlight(c->colors.frame), &at); CWIN(c->top, c->frame, 0, 0, c->frame_geo.width, SHADH, 0, CWBackPixel, color_enlight(c->colors.frame), &at); CWIN(c->bottom, c->frame, 0, c->frame_geo.height - SHADH, c->frame_geo.width, SHADH, 0, CWBackPixel, SHADC, &at); - CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, SHADC, &at); + CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, SHADC, &at); /* Reparent window with the frame */ XReparentWindow(dpy, c->win, c->frame, BORDH, BORDH + TBARH); @@ -122,6 +122,8 @@ frame_delete(Client *c) void frame_moveresize(Client *c, XRectangle geo) { + CHECK(c); + c->frame_geo.x = (geo.x) ? geo.x - BORDH : c->frame_geo.x; c->frame_geo.y = (geo.y) ? geo.y - TBARH : c->frame_geo.y; c->frame_geo.width = (geo.width) ? FRAMEW(geo.width) : c->frame_geo.width; @@ -157,6 +159,8 @@ frame_moveresize(Client *c, XRectangle geo) void frame_update(Client *c) { + CHECK(c); + if(TBARH) { c->titlebar->color = c->colors.frame; @@ -179,6 +183,7 @@ frame_update(Client *c) if(TBARH && (TBARH + BORDH + 1) > font->height) { + draw_text(c->titlebar->dr, (c->frame_geo.width / 2) - (textw(c->title) / 2), (font->height - (font->descent)) + (((TBARH + BORDH) - font->height) / 2), diff --git a/src/infobar.c b/src/infobar.c index 90b831f..cec0a1b 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -37,61 +37,68 @@ void infobar_init(void) { - int i, j = 0; + int sc, i, j; if(!infobar) - infobar = emalloc(1, sizeof(InfoBar)); - infobar->geo.height = font->height * 1.5; - infobar->geo.y = (conf.bartop) ? 0 : MAXH - infobar->geo.height; + infobar = emalloc(screen_count(), sizeof(InfoBar)); - /* Create infobar barwindow */ - infobar->bar = barwin_create(root, 0, infobar->geo.y, MAXW, infobar->geo.height, conf.colors.bar, False); - - - /* Create tags window */ - for(i = 1; i < conf.ntag + 1; ++i) + for(sc = 0; sc < screen_count(); ++sc) { - infobar->tags[i] = barwin_create(infobar->bar->win, j, 0, textw(tags[i].name) + PAD, - infobar->geo.height, conf.colors.bar, False); - j += textw(tags[i].name) + PAD; - barwin_map_subwin(infobar->tags[i]); + j = 0; + infobar[sc].geo.height = INFOBARH; + infobar[sc].geo.y = (conf.bartop) + ? screen_get_geo(sc).y - INFOBARH - TBARH + : screen_get_geo(sc).height - infobar[sc].geo.height; + + /* Create infobar barwindow */ + infobar[sc].bar = barwin_create(root, screen_get_geo(sc).x - BORDH, infobar[sc].geo.y, + screen_get_geo(sc).width, infobar[sc].geo.height, conf.colors.bar, False); + + /* Create tags window */ + for(i = 1; i < conf.ntag + 1; ++i) + { + infobar[sc].tags[i] = barwin_create(infobar[sc].bar->win, j, 0, textw(tags[sc][i].name) + PAD, + infobar[sc].geo.height, conf.colors.bar, False); + j += textw(tags[sc][i].name) + PAD; + barwin_map_subwin(infobar[sc].tags[i]); + } + + /* Create layout switch & layout type switch barwindow */ + infobar[sc].layout_button = barwin_create(infobar[sc].bar->win, j + PAD / 2, 0, + textw(tags[sc][seltag[sc]].layout.symbol) + PAD, + infobar[sc].geo.height, conf.colors.layout_bg, False); + + /* Map/Refresh all */ + barwin_map(infobar[sc].bar); + barwin_map_subwin(infobar[sc].bar); + barwin_map_subwin(infobar[sc].layout_button); + barwin_refresh_color(infobar[sc].bar); + barwin_refresh(infobar[sc].bar); + + strcpy(infobar[sc].statustext, "WMFS-" WMFS_VERSION); + infobar_draw(sc); } - /* Create layout switch & layout type switch barwindow */ - infobar->layout_button = barwin_create(infobar->bar->win, j + PAD / 2, 0, - textw(tags[seltag].layout.symbol) + PAD, - infobar->geo.height, conf.colors.layout_bg, False); - - /* Map/Refresh all */ - barwin_map(infobar->bar); - barwin_map_subwin(infobar->bar); - barwin_map_subwin(infobar->layout_button); - barwin_refresh_color(infobar->bar); - barwin_refresh(infobar->bar); - - strcpy(infobar->statustext, "WMFS-" WMFS_VERSION); - infobar_draw(); - return; } /** Draw the Infobar */ void -infobar_draw(void) +infobar_draw(int sc) { - infobar_draw_taglist(); - infobar_draw_layout(); - barwin_refresh_color(infobar->bar); + infobar_draw_taglist(sc); + infobar_draw_layout(sc); + barwin_refresh_color(infobar[sc].bar); /* Draw status text */ - draw_text(infobar->bar->dr, - (MAXW - SHADH) - textw(infobar->statustext), + draw_text(infobar[sc].bar->dr, + (MAXW - SHADH) - textw(infobar[sc].statustext), font->height, conf.colors.text, 0, - infobar->statustext); + infobar[sc].statustext); - barwin_refresh(infobar->bar); + barwin_refresh(infobar[sc].bar); return; } @@ -99,13 +106,13 @@ infobar_draw(void) /** Draw the layout button in the InfoBar */ void -infobar_draw_layout(void) +infobar_draw_layout(int sc) { - barwin_resize(infobar->layout_button, textw(tags[seltag].layout.symbol) + PAD, infobar->geo.height); - barwin_refresh_color(infobar->layout_button); - draw_text(infobar->layout_button->dr, PAD / 2, font->height, - conf.colors.layout_fg, 0, tags[seltag].layout.symbol); - barwin_refresh(infobar->layout_button); + barwin_resize(infobar[sc].layout_button, textw(tags[sc][seltag[sc]].layout.symbol) + PAD, infobar[sc].geo.height); + barwin_refresh_color(infobar[sc].layout_button); + draw_text(infobar[sc].layout_button->dr, PAD / 2, font->height, + conf.colors.layout_fg, 0, tags[sc][seltag[sc]].layout.symbol); + barwin_refresh(infobar[sc].layout_button); return; } @@ -113,18 +120,17 @@ infobar_draw_layout(void) /** Draw the taglist in the InfoBar */ void -infobar_draw_taglist(void) +infobar_draw_taglist(int sc) { int i; for(i = 1; i < conf.ntag + 1; ++i) { - infobar->tags[i]->color = ((i == seltag) ? conf.colors.tagselbg : conf.colors.bar); - barwin_refresh_color(infobar->tags[i]); - draw_text(infobar->tags[i]->dr, PAD / 2, font->height, - ((i == seltag) ? conf.colors.tagselfg : conf.colors.text), - 0, tags[i].name); - barwin_refresh(infobar->tags[i]); + infobar[sc].tags[i]->color = ((i == seltag[sc]) ? conf.colors.tagselbg : conf.colors.bar); + barwin_refresh_color(infobar[sc].tags[i]); + draw_text(infobar[sc].tags[i]->dr, PAD / 2, font->height, + ((i == seltag[sc]) ? conf.colors.tagselfg : conf.colors.text), 0, tags[sc][i].name); + barwin_refresh(infobar[sc].tags[i]); } return; @@ -135,17 +141,20 @@ infobar_draw_taglist(void) void infobar_destroy(void) { - int i; + int sc, i; - barwin_delete(infobar->bar); - barwin_delete(infobar->layout_button); - barwin_delete_subwin(infobar->layout_button); - for(i = 1; i < conf.ntag + 1; ++i) + for(sc = 0; sc < screen_count(); ++sc) { - barwin_delete_subwin(infobar->tags[i]); - barwin_delete(infobar->tags[i]); + barwin_delete(infobar[sc].layout_button); + barwin_delete_subwin(infobar[sc].layout_button); + for(i = 1; i < conf.ntag + 1; ++i) + { + barwin_delete_subwin(infobar[sc].tags[i]); + barwin_delete(infobar[sc].tags[i]); + } + barwin_delete_subwin(infobar[sc].bar); + barwin_delete(infobar[sc].bar); } - barwin_delete_subwin(infobar->bar); return; } @@ -157,16 +166,18 @@ infobar_destroy(void) void uicb_infobar_togglepos(uicb_t cmd) { + XRectangle sg = screen_get_geo(screen_get_sel()); + conf.bartop = !conf.bartop; if(conf.bartop) - sgeo.y = infobar->geo.height + TBARH; + sg.y = infobar[selscreen].geo.height + TBARH; else - sgeo.y = TBARH; + sg.y = TBARH; - infobar->geo.y = (conf.bartop) ? 0 : MAXH - infobar->geo.height; - barwin_move(infobar->bar, 0, infobar->geo.y); - infobar_draw(); + infobar[selscreen].geo.y = (conf.bartop) ? sg.y : MAXH - infobar[selscreen].geo.height; + barwin_move(infobar[selscreen].bar, sg.y, infobar[selscreen].geo.y); + infobar_draw(selscreen); arrange(); return; diff --git a/src/init.c b/src/init.c index 5a58ecc..b852682 100644 --- a/src/init.c +++ b/src/init.c @@ -46,7 +46,7 @@ init(void) init_root(); init_atom(); infobar_init(); - init_geometry(); + screen_init(); grabkeys(); /* Warning about font */ @@ -91,14 +91,10 @@ init_key(void) for(i = 0; i < 8; i++) for(j = 0; j < modmap->max_keypermod; ++j) - { if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) numlockmask = (1 << i); - if(modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Scroll_Lock)) - scrolllockmask = (1 << i); - } + XFreeModifiermap(modmap); return; @@ -113,9 +109,10 @@ init_root(void) root = RootWindow(dpy, screen); - at.event_mask = KeyMask | ButtonPressMask | ButtonReleaseMask | - SubstructureRedirectMask | SubstructureNotifyMask | - EnterWindowMask | LeaveWindowMask | StructureNotifyMask ; + at.event_mask = KeyMask|ButtonMask|MouseMask + |SubstructureRedirectMask|SubstructureNotifyMask + |EnterWindowMask|LeaveWindowMask|StructureNotifyMask; + at.cursor = cursor[CurNormal]; XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &at); if(conf.root.background_command) @@ -142,21 +139,3 @@ init_atom(void) return; } -/** Init screen geometry -*/ -void -init_geometry(void) -{ - sgeo.x = BORDH; - sgeo.y = infobar->geo.height; - - if(conf.bartop) - sgeo.y += TBARH; - else - sgeo.y = TBARH; - - sgeo.width = MAXW; - sgeo.height = MAXH - infobar->geo.height - TBARH; - - return; -} diff --git a/src/layout.c b/src/layout.c index 3bfec67..ed0bc91 100644 --- a/src/layout.c +++ b/src/layout.c @@ -39,20 +39,22 @@ arrange(void) { Client *c; + screen_get_sel(); + for(c = clients; c; c = c->next) - if(!ishide(c)) - client_unhide(c); - else - client_hide(c); + if(c->screen == selscreen) + { + if(!ishide(c)) + client_unhide(c); + else + client_hide(c); + } - tags[seltag].layout.func(); + tags[selscreen][seltag[selscreen]].layout.func(); - if(selbytag[seltag] != NULL) - client_focus(selbytag[seltag]); - else - client_focus(NULL); + client_focus(NULL); - infobar_draw(); + infobar_draw(selscreen); return; } @@ -67,7 +69,7 @@ freelayout(void) for(c = clients; c; c = c->next) { - if(!ishide(c)) + if(!ishide(c) && c->screen == screen_get_sel()) { if(c->tile || c->lmax) { @@ -92,15 +94,17 @@ layoutswitch(Bool b) { int i; + screen_get_sel(); + for(i = 0; i < conf.nlayout; ++i) { - if(tags[seltag].layout.symbol == conf.layout[i].symbol - && tags[seltag].layout.func == conf.layout[i].func) + if(tags[selscreen][seltag[selscreen]].layout.symbol == conf.layout[i].symbol + && tags[selscreen][seltag[selscreen]].layout.func == conf.layout[i].func) { if(b) - tags[seltag].layout = conf.layout[(i + 1) % conf.nlayout]; + tags[selscreen][seltag[selscreen]].layout = conf.layout[(i + 1) % conf.nlayout]; else - tags[seltag].layout = conf.layout[(i + conf.nlayout - 1) % conf.nlayout]; + tags[selscreen][seltag[selscreen]].layout = conf.layout[(i + conf.nlayout - 1) % conf.nlayout]; break; } } @@ -138,6 +142,7 @@ maxlayout(void) { Client *c; XRectangle geo; + XRectangle sg = screen_get_geo(screen_get_sel()); for(c = nexttiled(clients); c; c = nexttiled(c->next)) { @@ -148,9 +153,10 @@ maxlayout(void) c->ogeo.width = c->geo.width; c->ogeo.height = c->geo.height; - geo.x = sgeo.x; geo.y = sgeo.y; - geo.width = sgeo.width - BORDH * 2; - geo.height = sgeo.height - BORDH * 2; + geo.x = sg.x; + geo.y = sg.y; + geo.width = sg.width - BORDH * 2; + geo.height = sg.height - BORDH * 2; client_moveresize(c, geo, False); } @@ -166,7 +172,7 @@ maxlayout(void) Client* nexttiled(Client *c) { - for(; c && (c->max || c->free || ishide(c)); c = c->next); + for(; c && (c->max || c->free || c->screen != screen_get_sel() || ishide(c)); c = c->next); return c; } @@ -179,14 +185,16 @@ uicb_set_mwfact(uicb_t cmd) { double c; + screen_get_sel(); + CHECK((sscanf(cmd, "%lf", &c))); - if(tags[seltag].mwfact + c > 0.95 - || tags[seltag].mwfact + c < 0.05) + if(tags[selscreen][seltag[selscreen]].mwfact + c > 0.95 + || tags[selscreen][seltag[selscreen]].mwfact + c < 0.05) return; - tags[seltag].mwfact += c; - tags[seltag].layout.func(); + tags[selscreen][seltag[selscreen]].mwfact += c; + tags[selscreen][seltag[selscreen]].layout.func(); return; } @@ -200,14 +208,16 @@ uicb_set_nmaster(uicb_t cmd) int nc, n = atoi(cmd); Client *c; + screen_get_sel(); + for(nc = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++nc); - if(!nc || tags[seltag].nmaster + n == 0 - || tags[seltag].nmaster + n > nc) + if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0 + || tags[selscreen][seltag[selscreen]].nmaster + n > nc) return; - tags[seltag].nmaster += n; - tags[seltag].layout.func(); + tags[selscreen][seltag[selscreen]].nmaster += n; + tags[selscreen][seltag[selscreen]].layout.func(); return; } @@ -218,7 +228,8 @@ void grid(void) { Client *c; - XRectangle cgeo = {sgeo.x, sgeo.y, 0, 0}; + XRectangle sg = screen_get_geo(screen_get_sel()); + XRectangle cgeo = {sg.x, sg.y, 0, 0}; unsigned int i, n, cols, rows, cpcols = 0; unsigned int border = BORDH * 2; @@ -242,19 +253,19 @@ grid(void) c->ogeo.width = c->geo.width; c->ogeo.height = c->geo.height; ++cpcols; - cgeo.width = (sgeo.width / cols) - border; - cgeo.height = (sgeo.height / rows) - border; + cgeo.width = (sg.width / cols) - border; + cgeo.height = (sg.height / rows) - border; /* Last row's and last client remainder */ if(cpcols == rows || i + 1 == n) - cgeo.height = (sgeo.y + sgeo.height) - cgeo.y - border; + cgeo.height = sg.y + sg.height - cgeo.y - border; /* Last column's client remainder */ if(i >= rows * (cols - 1)) - cgeo.width = sgeo.width - cgeo.x - BORDH; + cgeo.width = sg.width - (cgeo.x - (sg.x - border)); /* Resize */ - client_moveresize(c, cgeo, tags[seltag].resizehint); + client_moveresize(c, cgeo, tags[selscreen][seltag[selscreen]].resizehint); /* Set all the other size with current client info */ cgeo.y = c->geo.y + c->geo.height + border + TBARH; @@ -262,7 +273,7 @@ grid(void) { cpcols = 0; cgeo.x = c->geo.x + c->geo.width + border; - cgeo.y = sgeo.y; + cgeo.y = sg.y; } } @@ -276,9 +287,10 @@ void multi_tile(Position type) { Client *c; - XRectangle mastergeo = {sgeo.x, sgeo.y, 0, 0}; - XRectangle cgeo = {sgeo.x, sgeo.y, 0, 0}; - uint i , n, tilesize, mwfact, nmaster = tags[seltag].nmaster; + XRectangle sg = screen_get_geo(screen_get_sel()); + XRectangle mastergeo = {sg.x, sg.y, 0, 0}; + XRectangle cgeo = {sg.x, sg.y, 0, 0}; + uint i , n, tilesize, mwfact, nmaster = tags[selscreen][seltag[selscreen]].nmaster; uint border = BORDH * 2; for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++n); @@ -289,32 +301,32 @@ multi_tile(Position type) /* SET MWFACT */ mwfact = (type == Top || type == Bottom) - ? tags[seltag].mwfact * sgeo.height - : tags[seltag].mwfact * sgeo.width; + ? tags[selscreen][seltag[selscreen]].mwfact * sg.height + : tags[selscreen][seltag[selscreen]].mwfact * sg.width; /* MASTER SIZE */ if(type == Top || type == Bottom) { if(type == Top) - mastergeo.y = (n <= nmaster) ? sgeo.y : sgeo.y + (sgeo.height - mwfact) - border; - mastergeo.width = (sgeo.width / nmaster) - (border * 2); - mastergeo.height = (n <= nmaster) ? sgeo.height - border : mwfact; + mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - border; + mastergeo.width = (sg.width / nmaster) - (border * 2); + mastergeo.height = (n <= nmaster) ? sg.height - border : mwfact; } else { if(type == Left) - mastergeo.x = (n <= nmaster) ? sgeo.x : sgeo.width - mwfact - BORDH; - mastergeo.width = (n <= nmaster) ? sgeo.width - border : mwfact; - mastergeo.height = (sgeo.height / nmaster) - border; + mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - border; + mastergeo.width = (n <= nmaster) ? sg.width - border : mwfact; + mastergeo.height = (sg.height / nmaster) - border; } /* TILED SIZE */ if(n > nmaster) { if(type == Top || type == Bottom) - tilesize = sgeo.width / (n - nmaster) - border; + tilesize = sg.width / (n - nmaster) - border; else - tilesize = sgeo.height / (n - nmaster) - border; + tilesize = sg.height / (n - nmaster) - border; } @@ -350,17 +362,17 @@ multi_tile(Position type) { case Top: case Left: - cgeo.y = sgeo.y; - cgeo.x = sgeo.x; + cgeo.y = sg.y; + cgeo.x = sg.x; break; case Bottom: cgeo.y += mastergeo.height + TBARH + border; - cgeo.x = sgeo.x; + cgeo.x = sg.x; break; default: case Right: cgeo.x += mastergeo.width + border; - cgeo.y = sgeo.y; + cgeo.y = sg.y; break; } } @@ -368,11 +380,11 @@ multi_tile(Position type) { cgeo.width = tilesize; cgeo.width -= border; - cgeo.height = sgeo.height - mastergeo.height - TBARH - border*2; + cgeo.height = sg.height - mastergeo.height - TBARH - border*2; } else { - cgeo.width = sgeo.width - mastergeo.width - border*2; + cgeo.width = sg.width - mastergeo.width - border*2; cgeo.height = tilesize; cgeo.height -= border + TBARH; } @@ -382,13 +394,13 @@ multi_tile(Position type) if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster)) { if(type == Top || type == Bottom) - cgeo.width = sgeo.width - cgeo.x - BORDH; + cgeo.width = sg.width - (cgeo.x - (sg.x - border)); else - cgeo.height = (sgeo.y + sgeo.height) - cgeo.y - border; + cgeo.height = (sg.y + sg.height) - cgeo.y - border; } /* Magic instant */ - client_moveresize(c, cgeo, tags[seltag].resizehint); + client_moveresize(c, cgeo, tags[selscreen][seltag[selscreen]].resizehint); /* Set the position of the next client */ if(type == Top || type == Bottom) @@ -449,6 +461,8 @@ uicb_tile_switch(uicb_t cmd) { Client *c; + screen_get_sel(); + if(!sel || sel->hint || !sel->tile) return; if((c = sel) == nexttiled(clients)) @@ -456,7 +470,7 @@ uicb_tile_switch(uicb_t cmd) client_detach(c); client_attach(c); client_focus(c); - tags[seltag].layout.func(); + tags[selscreen][seltag[selscreen]].layout.func(); return; } @@ -469,12 +483,14 @@ uicb_togglefree(uicb_t cmd) { CHECK(sel); + screen_get_sel(); + sel->free = !sel->free; sel->tile = False; sel->max = False; sel->lmax = False; client_moveresize(sel, sel->ogeo, True); - tags[seltag].layout.func(); + tags[selscreen][seltag[selscreen]].layout.func(); return; } @@ -486,6 +502,7 @@ void uicb_togglemax(uicb_t cmd) { XRectangle geo; + XRectangle sg = screen_get_geo(screen_get_sel()); if(!sel || ishide(sel) || sel->hint) return; @@ -496,9 +513,10 @@ uicb_togglemax(uicb_t cmd) sel->ogeo.width = sel->geo.width; sel->ogeo.height = sel->geo.height; - geo.x = sgeo.x; geo.y = sgeo.y; - geo.width = sgeo.width - BORDH * 2; - geo.height = sgeo.height - BORDH * 2; + geo.x = sg.x; + geo.y = sg.y; + geo.width = sg.width - BORDH * 2; + geo.height = sg.height - BORDH * 2; client_moveresize(sel, geo, False); client_raise(sel); diff --git a/src/mouse.c b/src/mouse.c index 5144b4a..a88c917 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -40,7 +40,7 @@ mouse_move(Client *c) { int ocx = c->geo.x; int ocy = c->geo.y; - int mx, my, dint; + int mx = 0, my = 0, dint; uint duint; Window dw; XRectangle geo; @@ -57,7 +57,7 @@ mouse_move(Client *c) for(;;) { - XMaskEvent(dpy, MouseMask | ExposureMask | SubstructureRedirectMask, &ev); + XMaskEvent(dpy, ButtonMask | MouseMask | ExposureMask | SubstructureRedirectMask, &ev); if(ev.type == ButtonRelease) { @@ -89,9 +89,10 @@ mouse_resize(Client *c) { int ocx = c->geo.x; int ocy = c->geo.y; - int my = sgeo.y, mx = 0; double fy, fx, mwf; XRectangle geo; + XRectangle sg = screen_get_geo(screen_get_sel()); + int my = sg.y, mx = 0; XEvent ev; if(c->max || c->lmax) @@ -107,21 +108,21 @@ mouse_resize(Client *c) /* Warp pointer for mwfact resize {{{ */ if(c->tile) { - if(tags[seltag].layout.func == tile) - mx = tags[seltag].mwfact * sgeo.width; - else if(tags[seltag].layout.func == tile_left) - mx = sgeo.width - (tags[seltag].mwfact * sgeo.width); - else if(tags[seltag].layout.func == tile_top) + if(tags[selscreen][seltag[selscreen]].layout.func == tile) + mx = tags[selscreen][seltag[selscreen]].mwfact * sg.width; + else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left) + mx = sg.width - (tags[selscreen][seltag[selscreen]].mwfact * sg.width); + else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top) { - mx = ev.xmotion.x_root; - my = sgeo.height - (tags[seltag].mwfact * sgeo.height); + mx = sg.width / 2; + my = sg.height - (tags[selscreen][seltag[selscreen]].mwfact * sg.height); } - else if(tags[seltag].layout.func == tile_bottom) + else if(tags[selscreen][seltag[selscreen]].layout.func == tile_bottom) { - mx = ev.xmotion.x_root; - my = tags[seltag].mwfact * sgeo.height; + mx = sg.width / 2; + my = tags[selscreen][seltag[selscreen]].mwfact * sg.height; } - XWarpPointer(dpy, None, root, 0, 0, 0, 0, mx, my); + XWarpPointer(dpy, None, root, 0, 0, 0, 0, sg.x + mx, sg.y + my); } /* }}} */ @@ -148,22 +149,22 @@ mouse_resize(Client *c) } else { - fy = (round(((ev.xmotion.y * 50) / sgeo.height))) / 50; - fx = (round(((ev.xmotion.x * 50) / sgeo.width))) / 50; + fy = (round(((ev.xmotion.y * 50) / sg.height))) / 50; + fx = (round(((ev.xmotion.x * 50) / sg.width))) / 50; - if(tags[seltag].layout.func == tile) - mwf = fx; - else if(tags[seltag].layout.func == tile_left) - mwf = 1 - fx; - else if(tags[seltag].layout.func == tile_top) + if(tags[selscreen][seltag[selscreen]].layout.func == tile) + mwf = sg.x + fx; + else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left) + mwf = 1 - (sg.x + fx); + else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top) mwf = 1 - fy; - else if(tags[seltag].layout.func == tile_bottom) + else if(tags[selscreen][seltag[selscreen]].layout.func == tile_bottom) mwf = fy; else - mwf = tags[seltag].mwfact; + mwf = tags[selscreen][seltag[selscreen]].mwfact; - tags[seltag].mwfact = (mwf < 0.05) ? 0.05 : ((mwf > 0.95) ? 0.95 : mwf); - tags[seltag].layout.func(); + tags[selscreen][seltag[selscreen]].mwfact = (mwf < 0.05) ? 0.05 : ((mwf > 0.95) ? 0.95 : mwf); + tags[selscreen][seltag[selscreen]].layout.func(); } if(!c->tile) @@ -184,27 +185,22 @@ mouse_resize(Client *c) void mouse_grabbuttons(Client *c, Bool focused) { - int i, j; - uint mod = conf.client.mod; - uint bl[] = {Button1, Button2, Button3, Button4, Button5}; - uint ml[] = - { - mod, mod|LockMask, - mod|numlockmask, - mod|scrolllockmask, - mod|numlockmask|scrolllockmask, - mod|LockMask|scrolllockmask, - mod|LockMask|numlockmask, - mod|LockMask|numlockmask|scrolllockmask - }; + int i; + uint but[] = {Button1, Button2, Button3, Button4, Button5}; XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if(focused) - for(i = 0; i < (sizeof bl / sizeof bl[0]); ++i) - for(j = 0; j < (sizeof ml / sizeof ml[0]); ++j) - XGrabButton(dpy, bl[i], ml[j], c->win, False, - ButtonMask, GrabModeAsync,GrabModeSync, None, None); + for(i = 0; i < (sizeof but / sizeof but[0]); ++i) + { + XGrabButton(dpy, but[i], conf.client.mod, c->win, False, + ButtonMask, GrabModeAsync,GrabModeSync, None, None); + XGrabButton(dpy, but[i], conf.client.mod|LockMask, c->win, False, + ButtonMask, GrabModeAsync,GrabModeSync, None, None); + XGrabButton(dpy, but[i], conf.client.mod|numlockmask, c->win, False, + ButtonMask, GrabModeAsync,GrabModeSync, None, None); + XGrabButton(dpy, but[i], conf.client.mod|LockMask|numlockmask, c->win, False, + ButtonMask, GrabModeAsync,GrabModeSync, None, None); + } else XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, ButtonMask, GrabModeAsync, GrabModeSync, None, None); diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..8be192f --- /dev/null +++ b/src/screen.c @@ -0,0 +1,118 @@ +/* +* screen.c +* Copyright © 2008 Martin Duquesnoy +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of the nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "wmfs.h" + +/** Count the screens + *\return the number of screen +*/ +int +screen_count(void) +{ + int n = 0; + + if(XineramaIsActive(dpy)) + XineramaQueryScreens(dpy, &n); + else + n = ScreenCount(dpy); + + return n; +} + +/** Get screen geometry by number + *\param s Screen number + *\return XRectangle struct +*/ +XRectangle +screen_get_geo(int s) +{ + int n = 0; + XineramaScreenInfo *xsi; + XRectangle geo; + + if(XineramaIsActive(dpy)) + { + xsi = XineramaQueryScreens(dpy, &n); + geo.x = xsi[s].x_org + BORDH; + geo.y = (conf.bartop) + ? xsi[s].y_org + INFOBARH + TBARH + : xsi[s].y_org + TBARH; + geo.height = xsi[s].height - INFOBARH - TBARH; + geo.width = xsi[s].width; + + efree(xsi); + } + else + { + geo.x = BORDH; + geo.y = (conf.bartop) ? INFOBARH + TBARH : TBARH; ; + geo.height = MAXH - INFOBARH - TBARH; + geo.width = MAXW; + } + + return geo; +} + +/** Get and set the selected screen + *\return The number of the selected screen +*/ +int +screen_get_sel(void) +{ + if(XineramaIsActive(dpy)) + { + Window w; + uint du; + int x, y, d, i = 0; + + XQueryPointer(dpy, root, &w, &w, &x, &y, &d, &d, &du); + + for(i = 0; i < screen_count(); ++i) + if(x >= screen_get_geo(i).x + && x < screen_get_geo(i).x + screen_get_geo(i).width) + selscreen = i; + + return selscreen; + } + else + return 0; +} + +/** Init screen geometry +*/ +void +screen_init(void) +{ + screen_get_sel(); + + return; +} diff --git a/src/structs.h b/src/structs.h index a270186..e425ff7 100644 --- a/src/structs.h +++ b/src/structs.h @@ -80,6 +80,8 @@ struct Client char *title; /* Tag num */ int tag; + /* Screen */ + int screen; /* Window attribute */ XRectangle geo; XRectangle frame_geo; diff --git a/src/tag.c b/src/tag.c index 149c3e6..0918d66 100644 --- a/src/tag.c +++ b/src/tag.c @@ -40,24 +40,24 @@ uicb_tag(uicb_t cmd) { int tmp = atoi(cmd); + screen_get_sel(); + if(!tmp) tmp = 1; if(cmd[0] == '+' || cmd[0] == '-') { - if(tmp + seltag < 1 - || tmp + seltag > conf.ntag) + if(tmp + seltag[selscreen] < 1 + || tmp + seltag[selscreen] > conf.ntag) return; - prevtag = seltag; - seltag += tmp; + seltag[selscreen] += tmp; } else { - if(tmp == seltag + if(tmp == seltag[selscreen] || tmp > conf.ntag) return; - prevtag = seltag; - seltag = tmp; + seltag[selscreen] = tmp; } arrange(); @@ -95,15 +95,15 @@ uicb_tagtransfert(uicb_t cmd) { int n = atoi(cmd); - if(!sel || n == seltag) + screen_get_sel(); + + if(!sel || n == seltag[selscreen]) return; if(!n) n = 1; sel->tag = n; - selbytag[n] = sel; - selbytag[seltag] = NULL; arrange(); diff --git a/src/util.c b/src/util.c index 7632710..7302199 100644 --- a/src/util.c +++ b/src/util.c @@ -69,7 +69,7 @@ getcolor(char *color) { XColor xcolor; - if(!XAllocNamedColor(dpy,DefaultColormap(dpy, screen), color, &xcolor, &xcolor)) + if(!XAllocNamedColor(dpy, DefaultColormap(dpy, screen), color, &xcolor, &xcolor)) fprintf(stderr,"WMFS Error: cannot allocate color \"%s\"\n", color); return xcolor.pixel; } @@ -81,14 +81,13 @@ getcolor(char *color) ulong color_enlight(ulong col) { - ulong ret = col; - if((col + 0x330000) < 0xffffff && (col + 0x003300) < 0xffffff && (col + 0x000033) < 0xffffff) - ret += 0x333333; + return col + 0x333333; + else + return col; - return ret; } /** Get a Window WM State diff --git a/src/wmfs.c b/src/wmfs.c index 952346d..b3fc357 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -47,9 +47,15 @@ errorhandler(Display *d, XErrorEvent *event) } /* Ignore focus change error for unmapped client */ - if((c = client_gb_win(event->resourceid)) - && c->unmapped - && event->request_code == 42) /* 42: X_SetInputFocus (Xproto.h) */ + /* Too lemmy to add Xproto.h so: + * 42 = X_SetInputFocus + * 28 = X_GrabButton + */ + + if((c = client_gb_win(event->resourceid))) + if(event->error_code == BadWindow + || (event->error_code == BadMatch && event->request_code == 42) + || event->request_code == 28) return 0; @@ -96,6 +102,8 @@ quit(void) XFreeCursor(dpy, cursor[CurResize]); infobar_destroy(); efree(infobar); + efree(seltag); + efree(tags); efree(keys); efree(conf.titlebar.mouse); efree(conf.client.mouse); @@ -112,13 +120,15 @@ void mainloop(void) { fd_set fd; - char sbuf[sizeof infobar->statustext], *p; - int len, r, offset = 0; + int len, r, offset = 0, sc = screen_count() - 1; + char sbuf[sizeof infobar[sc].statustext], *p; Bool readstdin = True; XEvent ev; - len = sizeof infobar->statustext - 1; - sbuf[len] = infobar->statustext[len] = '\0'; + + + len = sizeof infobar[sc].statustext - 1; + sbuf[len] = infobar[sc].statustext[len] = '\0'; while(!exiting) { @@ -137,7 +147,7 @@ mainloop(void) if(*p == '\n') { *p = '\0'; - strncpy(infobar->statustext, sbuf, len); + strncpy(infobar[sc].statustext, sbuf, len); p += r - 1; for(r = 0; *(p - r) && *(p - r) != '\n'; ++r); offset = r; @@ -149,10 +159,10 @@ mainloop(void) } else { - strncpy(infobar->statustext, sbuf, strlen(sbuf)); + strncpy(infobar[sc].statustext, sbuf, strlen(sbuf)); readstdin = False; } - infobar_draw(); + infobar_draw(screen_get_sel()); } while(XPending(dpy)) { diff --git a/src/wmfs.h b/src/wmfs.h index a04754c..ab1ca1d 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -50,6 +50,7 @@ #include #include #include +#include /* Local headers */ #include "config.h" @@ -67,7 +68,7 @@ #define MAXH DisplayHeight(dpy, screen) #define MAXW DisplayWidth(dpy, screen) - +#define INFOBARH font->height * 1.5 #define SHADH 1 #define SHADC 0x000000 /* 'Cause i don't know how darken a color yet */ #define BORDH conf.client.borderheight @@ -100,9 +101,9 @@ ushort textw(const char *text); /* infobar.c */ void infobar_init(void); -void infobar_draw(void); -void infobar_draw_layout(void); -void infobar_draw_taglist(void); +void infobar_draw(int sc); +void infobar_draw_layout(int sc); +void infobar_draw_taglist(int sc); void infobar_destroy(void); void uicb_infobar_togglepos(uicb_t cmd); @@ -180,6 +181,12 @@ void uicb_tag_next(uicb_t); void uicb_tag_prev(uicb_t); void uicb_tagtransfert(uicb_t); +/* screen */ +int screen_count(void); +XRectangle screen_get_geo(int s); +int screen_get_sel(void); +void screen_init(void); + /* layout.c */ void arrange(void); void freelayout(void); @@ -226,8 +233,8 @@ void uicb_reload(uicb_t cmd); Display *dpy; GC gc; Window root; -XRectangle sgeo; int screen; +int selscreen; Conf conf; Key *keys; Bool exiting; @@ -242,19 +249,15 @@ XftFont *font; /* InfoBar */ InfoBar *infobar; -Tag tags[MAXTAG]; -int taglen[MAXTAG]; -int seltag; -int prevtag; +Tag tags[32][MAXTAG]; +int *seltag; /* Important Client */ Client *clients; Client *sel; -Client *selbytag[MAXTAG]; /* Other */ uint numlockmask; -uint scrolllockmask; Variable confvar[256]; #endif /* WMFS_H */