dwm.c
changeset 1494 e00cb20da182
parent 1493 20bd305fa7aa
child 1495 c4c94cff1c3b
equal deleted inserted replaced
1493:20bd305fa7aa 1494:e00cb20da182
   161 static void cleanupmons(void);
   161 static void cleanupmons(void);
   162 static void clearurgent(Client *c);
   162 static void clearurgent(Client *c);
   163 static void configure(Client *c);
   163 static void configure(Client *c);
   164 static void configurenotify(XEvent *e);
   164 static void configurenotify(XEvent *e);
   165 static void configurerequest(XEvent *e);
   165 static void configurerequest(XEvent *e);
       
   166 static Monitor *createmon(void);
   166 static void destroynotify(XEvent *e);
   167 static void destroynotify(XEvent *e);
   167 static void detach(Client *c);
   168 static void detach(Client *c);
   168 static void detachstack(Client *c);
   169 static void detachstack(Client *c);
   169 static void die(const char *errstr, ...);
   170 static void die(const char *errstr, ...);
   170 static Monitor *dirtomon(int dir);
   171 static Monitor *dirtomon(int dir);
   590 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
   591 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
   591 	}
   592 	}
   592 	XSync(dpy, False);
   593 	XSync(dpy, False);
   593 }
   594 }
   594 
   595 
       
   596 Monitor *
       
   597 createmon(void) {
       
   598 	Monitor *m;
       
   599 
       
   600 	if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
       
   601 		die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
       
   602 	m->tagset[0] = m->tagset[1] = 1;
       
   603 	m->mfact = mfact;
       
   604 	m->showbar = showbar;
       
   605 	m->topbar = topbar;
       
   606 	m->lt[0] = &layouts[0];
       
   607 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
       
   608 	m->ltsymbol = layouts[0].symbol;
       
   609 	return m;
       
   610 }
       
   611 
   595 void
   612 void
   596 destroynotify(XEvent *e) {
   613 destroynotify(XEvent *e) {
   597 	Client *c;
   614 	Client *c;
   598 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   615 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   599 
   616 
  1002 				ret = True;
  1019 				ret = True;
  1003 		XFree(protocols);
  1020 		XFree(protocols);
  1004 	}
  1021 	}
  1005 	return ret;
  1022 	return ret;
  1006 }
  1023 }
       
  1024 
       
  1025 #ifdef XINERAMA
       
  1026 static Bool
       
  1027 isuniquegeom(XineramaScreenInfo *unique, size_t len, XineramaScreenInfo *info) {
       
  1028 	unsigned int i;
       
  1029 
       
  1030 	for(i = 0; i < len; i++)
       
  1031 		if(unique[i].x_org == info->x_org && unique[i].y_org == info->y_org
       
  1032 		&& unique[i].width == info->width && unique[i].height == info->height)
       
  1033 			return False;
       
  1034 	return True;
       
  1035 }
       
  1036 #endif /* XINERAMA */
  1007 
  1037 
  1008 void
  1038 void
  1009 keypress(XEvent *e) {
  1039 keypress(XEvent *e) {
  1010 	unsigned int i;
  1040 	unsigned int i;
  1011 	KeySym keysym;
  1041 	KeySym keysym;
  1693 		m->by = -bh;
  1723 		m->by = -bh;
  1694 }
  1724 }
  1695 
  1725 
  1696 Bool
  1726 Bool
  1697 updategeom(void) {
  1727 updategeom(void) {
  1698 	int i, j, nn = 1, n = 1;
  1728 	Bool dirty = False;
  1699 	Client *c;
  1729 
  1700 	Monitor *newmons = NULL, *m = NULL, *tm;
       
  1701 
       
  1702 	/* TODO:
       
  1703 	 * This function needs to be seriously re-designed:
       
  1704 	 *
       
  1705 	 * #ifdef XINERAMA
       
  1706 	 * 1. Determine number of already existing monitors n
       
  1707 	 * 2. Determine number of monitors Xinerama reports nn
       
  1708 	 * 3. if(n <= nn) {
       
  1709 	 *       if(n < nn) {
       
  1710 	 *          append nn-n monitors to current struct
       
  1711 	 *          flag dirty
       
  1712 	 *       }
       
  1713 	 *       for(i = 0; i < nn; i++) {
       
  1714 	 *           if(oldgeom != newgeom) {
       
  1715 	 *               apply newgeom;
       
  1716 	 *               flag dirty;
       
  1717 	 *           }
       
  1718 	 *       }
       
  1719 	 *    }
       
  1720 	 *    else {
       
  1721 	 *       detach all clients
       
  1722 	 *       destroy current monitor struct
       
  1723 	 *       create new monitor struct 
       
  1724 	 *       attach all clients to first monitor
       
  1725 	 *       flag dirty;
       
  1726 	 *    }
       
  1727 	 *    return dirty flag to caller
       
  1728 	 *        if dirty is seen by caller:
       
  1729 	 *           re-arrange bars/pixmaps
       
  1730 	 *           arrange()
       
  1731 	 * #else
       
  1732 	 *    don't share between XINERAMA and non-XINERAMA handling if it gets
       
  1733 	 *    too ugly
       
  1734 	 * #endif
       
  1735 	 */
       
  1736 #ifdef XINERAMA
       
  1737 	XineramaScreenInfo *info = NULL;
       
  1738 	Bool *flags = NULL;
       
  1739 
       
  1740 	if(XineramaIsActive(dpy))
       
  1741 		info = XineramaQueryScreens(dpy, &n);
       
  1742 	flags = (Bool *)malloc(sizeof(Bool) * n);
       
  1743 	for(i = 0; i < n; i++)
       
  1744 		flags[i] = False;
       
  1745 	/* next double-loop seeks any combination of retrieved Xinerama info
       
  1746 	 * with existing monitors, this is used to avoid unnecessary
       
  1747 	 * re-allocations of monitor structs */
       
  1748 	for(i = 0, nn = n; i < n; i++)
       
  1749 		for(j = 0, m = mons; m; m = m->next, j++)
       
  1750 			if(!flags[j]) {
       
  1751 				if((flags[j] = (
       
  1752 					info[i].x_org == m->mx
       
  1753 					&& info[i].y_org == m->my
       
  1754 					&& info[i].width == m->mw
       
  1755 					&& info[i].height == m->mh)
       
  1756 				))
       
  1757 					--nn;
       
  1758 			}
       
  1759 	if(nn == 0) { /* no need to re-allocate monitors */
       
  1760 		j = 0;
       
  1761 		for(i = 0, m = mons; m; m = m->next, i++) {
       
  1762 			m->num = info[i].screen_number;
       
  1763 			if(info[i].x_org != m->mx
       
  1764 			|| info[i].y_org != m->my
       
  1765 			|| info[i].width != m->mw
       
  1766 			|| info[i].height != m->mh)
       
  1767 			{
       
  1768 				m->mx = m->wx = info[i].x_org;
       
  1769 				m->my = m->wy = info[i].y_org;
       
  1770 				m->mw = m->ww = info[i].width;
       
  1771 				m->mh = m->wh = info[i].height;
       
  1772 				updatebarpos(m);
       
  1773 				j++;
       
  1774 			}
       
  1775 		}
       
  1776 		XFree(info);
       
  1777 		free(flags);
       
  1778 		return j > 0;
       
  1779 	}
       
  1780 	/* next algorithm only considers unique geometries as separate screens */
       
  1781 	for(i = 0; i < n; i++)
       
  1782 		flags[i] = False; /* used for ignoring certain monitors */
       
  1783 	for(i = 0, nn = n; i < n; i++)
       
  1784 		for(j = 0; j < n; j++)
       
  1785 			if(i != j && !flags[i]) {
       
  1786 				if((flags[i] = (
       
  1787 					info[i].x_org == info[j].x_org
       
  1788 					&& info[i].y_org == info[j].y_org
       
  1789 					&& info[i].width == info[j].width
       
  1790 					&& info[i].height == info[j].height)
       
  1791 				))
       
  1792 					--nn;
       
  1793 			}
       
  1794 #endif /* XINERAMA */
       
  1795 	/* allocate monitor(s) for the new geometry setup */
       
  1796 	for(i = 0; i < nn; i++) {
       
  1797 		if(!(m = (Monitor *)malloc(sizeof(Monitor))))
       
  1798 			die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
       
  1799 		m->next = newmons;
       
  1800 		newmons = m;
       
  1801 	}
       
  1802 	/* initialise monitor(s) */
       
  1803 #ifdef XINERAMA
  1730 #ifdef XINERAMA
  1804 	if(XineramaIsActive(dpy)) {
  1731 	if(XineramaIsActive(dpy)) {
  1805 		for(i = 0, m = newmons; m && i < n; i++) {
  1732 		int i, j, n, nn;
  1806 			if(!flags[i]) { /* only use screens that aren't dublettes */
  1733 		Monitor *m;
  1807 				m->num = info[i].screen_number;
  1734 		XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
  1808 				m->mx = m->wx = info[i].x_org;
  1735 		XineramaScreenInfo *unique = NULL;
  1809 				m->my = m->wy = info[i].y_org;
  1736 
  1810 				m->mw = m->ww = info[i].width;
  1737 		info = XineramaQueryScreens(dpy, &nn);
  1811 				m->mh = m->wh = info[i].height;
  1738 		for(n = 0, m = mons; m; m = m->next, n++);
  1812 				m = m->next;
  1739 		/* only consider unique geometries as separate screens */
       
  1740 		if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn)))
       
  1741 			die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn);
       
  1742 		for(i = 0, j = 0; i < nn; i++)
       
  1743 			if(isuniquegeom(unique, j, &info[i]))
       
  1744 				memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
       
  1745 		XFree(info);
       
  1746 		nn = j;
       
  1747 		if(n <= nn) {
       
  1748 			for(i = 0; i < (nn - n); i++) { /* new monitors available */
       
  1749 				for(m = mons; m && m->next; m = m->next);
       
  1750 				if(m)
       
  1751 					m->next = createmon();
       
  1752 				else
       
  1753 					mons = createmon();
  1813 			}
  1754 			}
  1814 		}
  1755 			for(i = 0, m = mons; i < nn && m; m = m->next, i++)
  1815 		XFree(info);
  1756 				if(i >= n
  1816 		free(flags);
  1757 				|| (unique[i].x_org != m->mx || unique[i].y_org != m->my
       
  1758 				    || unique[i].width != m->mw || unique[i].height != m->mh))
       
  1759 				{
       
  1760 					dirty = True;
       
  1761 					m->num = unique[i].screen_number;
       
  1762 					m->mx = m->wx = unique[i].x_org;
       
  1763 					m->my = m->wy = unique[i].y_org;
       
  1764 					m->mw = m->ww = unique[i].width;
       
  1765 					m->mh = m->wh = unique[i].height;
       
  1766 					updatebarpos(m);
       
  1767 				}
       
  1768 		}
       
  1769 		else { /* less monitors available */
       
  1770 			cleanup();
       
  1771 			setup();
       
  1772 		}
       
  1773 		free(unique);
  1817 	}
  1774 	}
  1818 	else
  1775 	else
  1819 #endif /* XINERAMA */
  1776 #endif /* XINERAMA */
  1820 	/* default monitor setup */
  1777 	/* default monitor setup */
  1821 	{
  1778 	{
  1822 		m->num = 0;
  1779 		if(!mons)
  1823 		m->mx = m->wx = 0;
  1780 			mons = createmon();
  1824 		m->my = m->wy = 0;
  1781 		if(mons->mw != sw || mons->mh != sh) {
  1825 		m->mw = m->ww = sw;
  1782 			dirty = True;
  1826 		m->mh = m->wh = sh;
  1783 			mons->mw = mons->ww = sw;
  1827 	}
  1784 			mons->mh = mons->wh = sh;
  1828 	/* bar geometry setup */
  1785 			updatebarpos(mons);
  1829 	for(m = newmons; m; m = m->next) {
  1786 		}
  1830 		m->sel = m->stack = m->clients = NULL;
  1787 	}
  1831 		m->seltags = 0;
  1788 	if(dirty) {
  1832 		m->sellt = 0;
  1789 		selmon = mons;
  1833 		m->tagset[0] = m->tagset[1] = 1;
  1790 		selmon = wintomon(root);
  1834 		m->mfact = mfact;
  1791 	}
  1835 		m->showbar = showbar;
  1792 	return dirty;
  1836 		m->topbar = topbar;
       
  1837 		m->lt[0] = &layouts[0];
       
  1838 		m->lt[1] = &layouts[1 % LENGTH(layouts)];
       
  1839 		m->ltsymbol = layouts[0].symbol;
       
  1840 		updatebarpos(m);
       
  1841 	}
       
  1842 	/* reassign left over clients of disappeared monitors */
       
  1843 	for(tm = mons; tm; tm = tm->next)
       
  1844 		while(tm->clients) {
       
  1845 			c = tm->clients;
       
  1846 			tm->clients = c->next;
       
  1847 			detachstack(c);
       
  1848 			c->mon = newmons;
       
  1849 			attach(c);
       
  1850 			attachstack(c);
       
  1851 		}
       
  1852 	/* select focused monitor */
       
  1853 	cleanupmons();
       
  1854 	selmon = mons = newmons;
       
  1855 	selmon = wintomon(root);
       
  1856 	return True;
       
  1857 }
  1793 }
  1858 
  1794 
  1859 void
  1795 void
  1860 updatenumlockmask(void) {
  1796 updatenumlockmask(void) {
  1861 	unsigned int i, j;
  1797 	unsigned int i, j;