Пример #1
0
static dlist *
update_clients(MainWin *mw, dlist *clients, Bool *touched)
{
	dlist *stack, *iter;
	
	stack = dlist_first(wm_get_stack(mw->dpy));
	iter = clients = dlist_first(clients);
	
	if(touched)
		*touched = False;
	
	/* Terminate clients that are no longer managed */
	while(iter)
	{
		ClientWin *cw = (ClientWin *)iter->data;
		if(! dlist_find_data(stack, (void *)cw->client.window))
		{
			dlist *tmp = iter->next;
			clientwin_destroy((ClientWin *)iter->data, True);
			clients = dlist_remove(iter);
			iter = tmp;
			if(touched)
				*touched = True;
			continue;
		}
		clientwin_update(cw);
		iter = iter->next;
	}
	
	/* Add new clients */
	for(iter = dlist_first(stack); iter; iter = iter->next)
	{
		ClientWin *cw = (ClientWin*)dlist_find(clients, clientwin_cmp_func, iter->data);
		if(! cw && (Window)iter->data != mw->window)
		{
			cw = clientwin_create(mw, (Window)iter->data);
			if(! cw)
				continue;
			clients = dlist_add(clients, cw);
			clientwin_update(cw);
			if(touched)
				*touched = True;
		}
	}
	
	dlist_free(stack);
	
	return clients;
}
Пример #2
0
static dlist *
update_clients(MainWin *mw, dlist *clients)
{
	dlist *stack, *iter;
	
	stack = dlist_first(wm_get_stack(mw->dpy));
	iter = clients = dlist_first(clients);

	while(iter)
	{
		ClientWin *cw = (ClientWin *)iter->data;
		if(! dlist_find_data(stack, (void *)cw->client.window))
		{
			dlist *tmp = iter->next;
			clientwin_destroy((ClientWin *)iter->data);
			clients = dlist_remove(iter);
			iter = tmp;
			continue;
		}
		clientwin_update(cw);
		iter = iter->next;
	}
	
	for(iter = dlist_first(stack); iter; iter = iter->next)
	{
		ClientWin *cw = (ClientWin*)dlist_find(clients, clientwin_cmp_func, iter->data);
		if(! cw)
		{
			cw = clientwin_create(mw, (Window)iter->data);
			if(! cw)
				continue;
			clients = dlist_add(clients, cw);
			clientwin_update(cw);
		}
	}
	
	dlist_free(stack);
	
	return clients;
}
Пример #3
0
ClientWin *
clientwin_create(MainWin *mw, Window client) {
	session_t *ps = mw->ps;
	ClientWin *cw = allocchk(malloc(sizeof(ClientWin)));
	{
		static const ClientWin CLIENTWT_DEF = CLIENTWT_INIT;
		memcpy(cw, &CLIENTWT_DEF, sizeof(ClientWin));
	}

	XWindowAttributes attr;
	
	cw->mainwin = mw;
	cw->wid_client = client;
	if (ps->o.includeFrame)
		cw->src.window = wm_find_frame(ps, client);
	if (!cw->src.window)
		cw->src.window = client;
	cw->mini.format = mw->format;
	{
		XSetWindowAttributes sattr = {
			.border_pixel = 0,
			.background_pixel = 0,
			.colormap = mw->colormap,
			.event_mask = ButtonPressMask | ButtonReleaseMask | KeyPressMask
				| KeyReleaseMask | EnterWindowMask | LeaveWindowMask
				| PointerMotionMask | ExposureMask | FocusChangeMask,
			.override_redirect = ps->o.lazyTrans,
		};
		cw->mini.window = XCreateWindow(ps->dpy,
				(ps->o.lazyTrans ? ps->root : mw->window), 0, 0, 1, 1, 0,
				mw->depth, InputOutput, mw->visual,
				CWColormap | CWBackPixel | CWBorderPixel | CWEventMask | CWOverrideRedirect, &sattr);
	}
	if (!cw->mini.window)
		goto clientwin_create_err;
	
	{
		static const char *PREFIX = "mini window of ";
		const int len = strlen(PREFIX) + 20;
		char *str = allocchk(malloc(len));
		snprintf(str, len, "%s%#010lx", PREFIX, cw->src.window);
		wm_wid_set_info(cw->mainwin->ps, cw->mini.window, str, None);
		free(str);
	}

	// Listen to events on the window. We don't want to miss any changes so
	// this is to be done as early as possible
	XSelectInput(cw->mainwin->ps->dpy, cw->src.window, SubstructureNotifyMask | StructureNotifyMask);

	XGetWindowAttributes(ps->dpy, client, &attr);
	if (IsViewable != attr.map_state)
		goto clientwin_create_err;
	clientwin_update(cw);
	
	// Get window pixmap
	if (ps->o.useNameWindowPixmap) {
		XCompositeRedirectWindow(ps->dpy, cw->src.window, CompositeRedirectAutomatic);
		cw->redirected = true;
		cw->cpixmap = XCompositeNameWindowPixmap(ps->dpy, cw->src.window);
	}
	// Create window picture
	{
		Drawable draw = cw->cpixmap;
		if (!draw) draw = cw->src.window;
		XRenderPictureAttributes pa = { .subwindow_mode = IncludeInferiors };
		cw->origin = XRenderCreatePicture(cw->mainwin->ps->dpy,
				draw, cw->src.format, CPSubwindowMode, &pa);
	}
	if (!cw->origin)
		goto clientwin_create_err;

	XRenderSetPictureFilter(cw->mainwin->ps->dpy, cw->origin, FilterBest, 0, 0);


	return cw;

clientwin_create_err:
	if (cw)
		clientwin_destroy(cw, False);

	return NULL;
}

void
clientwin_update(ClientWin *cw) {
	Window tmpwin;
	XWindowAttributes wattr;

	XGetWindowAttributes(cw->mainwin->ps->dpy, cw->src.window, &wattr);
	XTranslateCoordinates(cw->mainwin->ps->dpy, cw->src.window, wattr.root,
			-wattr.border_width, -wattr.border_width,
			&cw->src.x, &cw->src.y, &tmpwin);
	cw->src.width = wattr.width;
	cw->src.height = wattr.height;
	cw->src.format = XRenderFindVisualFormat(cw->mainwin->ps->dpy, wattr.visual);

	cw->mini.x = cw->mini.y = 0;
	cw->mini.width = cw->mini.height = 1;
}
Пример #4
0
static dlist *
skippy_run(MainWin *mw, dlist *clients, int force, Window focus, Window leader, Bool all_xin)
{
	unsigned int width, height, tree_count, u;
	float factor;
	int xoff, yoff;
	XEvent ev;
	int die = 0;
	dlist *iter, *tmp;
	Window dummy_w, *tree_windows;
	CARD32 desktop = wm_get_current_desktop(mw->dpy);
	Bool refocus = False;
	
	/* Update the main window's geometry (and Xinerama info if applicable) */
	mainwin_update(mw);
#ifdef XINERAMA
	if(all_xin)
		mw->xin_active = 0;
#else /* ! XINERAMA */
	if(all_xin);
#endif /* XINERAMA */
	
	/* Update the client table, pick the ones we want and sort them */
	clients = update_clients(mw, clients);
	
	tmp = dlist_first(dlist_find_all(clients, (dlist_match_func)clientwin_validate_func, &desktop));
	if(leader != None)
	{
		mw->cod = dlist_first(dlist_find_all(tmp, clientwin_check_group_leader_func, (void*)&leader));
		dlist_free(tmp);
	} else
		mw->cod = tmp;
	
	if(! mw->cod)
		return clients;
	
	dlist_sort(mw->cod, clientwin_sort_func, 0);
	
	/* Move the mini windows around */
	layout_run(mw, mw->cod, &width, &height);
	factor = (float)(mw->width - 100) / width;
	if(factor * height > mw->height - 100)
		factor = (float)(mw->height - 100) / height;
	
	xoff = (mw->width - (float)width * factor) / 2;
	yoff = (mw->height - (float)height * factor) / 2;
	for(iter = mw->cod; iter; iter = iter->next)
		clientwin_move((ClientWin*)iter->data, factor, xoff, yoff);
	
	/* Get the currently focused window and select which mini-window to focus */
	iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)focus);
	if(! iter)
		iter = mw->cod;
	mw->focus = (ClientWin*)iter->data;
	mw->focus->focused = 1;
	
	/* Save the stacking tree */
	XQueryTree(mw->dpy, mw->root, &dummy_w, &dummy_w, &tree_windows, &tree_count);
	mw->stack_touched = False;
	
	/* Map the client windows */
	for(iter = mw->cod; iter; iter = iter->next)
		clientwin_map((ClientWin*)iter->data, force);
	XWarpPointer(mw->dpy, None, mw->focus->mini.window, 0, 0, 0, 0, mw->focus->mini.width / 2, mw->focus->mini.height / 2);
	
	/* Restore the stacking order (using XRestackWindows seems like a bad idea) */
	if(mw->stack_touched)
		for(u = 0; u < tree_count; ++u)
			XRaiseWindow(mw->dpy, tree_windows[u]);
	XFree(tree_windows);
	
	/* Map the main window and run our event loop */
	mainwin_map(mw);
	
	while(! die) {
 		XNextEvent(mw->dpy, &ev);
		if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_q) {
			DIE_NOW = 1;
			break;
		}
		else if(ev.type == DestroyNotify || ev.type == UnmapNotify) {
			dlist *iter = dlist_find(clients, clientwin_cmp_func, (void *)ev.xany.window);
			if(iter)
			{
				ClientWin *cw = (ClientWin *)iter->data;
				clients = dlist_first(dlist_remove(iter));
				iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)ev.xany.window);
				if(iter)
					mw->cod = dlist_first(dlist_remove(iter));
				clientwin_destroy(cw);
				if(! mw->cod)
				{
					die = 1;
					break;
				}
			}
		}
		else if(ev.xany.window == mw->window)
			die = mainwin_handle(mw, &ev);
		else if(ev.type == PropertyNotify && (ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID))
			mainwin_update_background(mw);
		else if(mw->tooltip && ev.xany.window == mw->tooltip->window)
			tooltip_handle(mw->tooltip, &ev);
		else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_escape)
		{
			refocus = True;
			break;
		}
		else
		{
			dlist *iter;
			for(iter = mw->cod; iter; iter = iter->next)
			{
				ClientWin *cw = (ClientWin *)iter->data;
				if(cw->mini.window == ev.xany.window)
				{
					die = clientwin_handle(cw, &ev);
					break;
				}
			}
		}
	}
	
	/* Unmap the main window and clean up */
	mainwin_unmap(mw);
	XFlush(mw->dpy);
	
	REDUCE(clientwin_unmap((ClientWin*)iter->data), mw->cod);
	dlist_free(mw->cod);
	mw->cod = 0;
	
	if(die == 2)
		DIE_NOW = 1;
	
	if(refocus)
		XSetInputFocus(mw->dpy, focus, RevertToPointerRoot, CurrentTime);
	
	return clients;
}
Пример #5
0
static dlist *
skippy_run(MainWin *mw, dlist *clients, Window focus, Window leader, Bool all_xin)
{
	XEvent ev;
	int die = 0;
	Bool refocus = False;
	int last_rendered;
	
	/* Update the main window's geometry (and Xinerama info if applicable) */
	mainwin_update(mw);
#ifdef XINERAMA
	if(all_xin)
		mw->xin_active = 0;
#else /* ! XINERAMA */
	if(all_xin);
#endif /* XINERAMA */
	
	/* Map the main window and run our event loop */
	if(mw->lazy_trans)
	{
		mainwin_map(mw);
		XFlush(mw->dpy);
	}
	
	clients = do_layout(mw, clients, focus, leader);
	if(! mw->cod)
		return clients;
	
	/* Map the main window and run our event loop */
	if(! mw->lazy_trans)
		mainwin_map(mw);
	
	last_rendered = time_in_millis();
	while(! die) {
	    int i, j, now, timeout;
	    int move_x = -1, move_y = -1;
	    struct pollfd r_fd;
	    
	    XFlush(mw->dpy);
	    
	    r_fd.fd = ConnectionNumber(mw->dpy);
	    r_fd.events = POLLIN;
	    if(mw->poll_time > 0)
	    	timeout = MAX(0, mw->poll_time + last_rendered - time_in_millis());
	    else
	    	timeout = -1;
	    i = poll(&r_fd, 1, timeout);
	    
	    now = time_in_millis();
	    if(now >= last_rendered + mw->poll_time)
	    {
	    	REDUCE(if( ((ClientWin*)iter->data)->damaged ) clientwin_repair(iter->data), mw->cod);
	    	last_rendered = now;
	    }
	    
	    i = XPending(mw->dpy);
	    for(j = 0; j < i; ++j)
	    {
		XNextEvent(mw->dpy, &ev);
		
		if (ev.type == MotionNotify)
		{
			move_x = ev.xmotion.x_root;
			move_y = ev.xmotion.y_root;
		}
		else if(ev.type == DestroyNotify || ev.type == UnmapNotify) {
			dlist *iter = dlist_find(clients, clientwin_cmp_func, (void *)ev.xany.window);
			if(iter)
			{
				ClientWin *cw = (ClientWin *)iter->data;
				clients = dlist_first(dlist_remove(iter));
				iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)ev.xany.window);
				if(iter)
					mw->cod = dlist_first(dlist_remove(iter));
				clientwin_destroy(cw, True);
				if(! mw->cod)
				{
					die = 1;
					break;
				}
			}
		}
		else if (mw->poll_time >= 0 && ev.type == mw->damage_event_base + XDamageNotify)
		{
			XDamageNotifyEvent *d_ev = (XDamageNotifyEvent *)&ev;
			dlist *iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)d_ev->drawable);
			if(iter)
			{
				if(mw->poll_time == 0)
					clientwin_repair((ClientWin *)iter->data);
				else
					((ClientWin *)iter->data)->damaged = True;
			}
				
		}
		else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_q)
		{
			DIE_NOW = 1;
			die = 1;
			break;
		}
		else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_escape)
		{
			refocus = True;
			die = 1;
			break;
		}
		else if(ev.xany.window == mw->window)
			die = mainwin_handle(mw, &ev);
		else if(ev.type == PropertyNotify)
		{
			if(ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID)
			{
				mainwin_update_background(mw);
				REDUCE(clientwin_render((ClientWin *)iter->data), mw->cod);
			}

		}
		else if(mw->tooltip && ev.xany.window == mw->tooltip->window)
			tooltip_handle(mw->tooltip, &ev);
		else
		{
			dlist *iter;
			for(iter = mw->cod; iter; iter = iter->next)
			{
				ClientWin *cw = (ClientWin *)iter->data;
				if(cw->mini.window == ev.xany.window)
				{
					die = clientwin_handle(cw, &ev);
					if(die)
						break;
				}
			}
			if(die)
				break;
		}
	    
	    }
	    	
	    if(mw->tooltip && move_x != -1)
	    	tooltip_move(mw->tooltip, move_x + 20, move_y + 20);
	    
	}