Beispiel #1
0
void
mousethread(void *v)
{
	Text *t, *argt;
	int but;
	uint q0, q1;
	Window *w;
	Plumbmsg *pm;
	Mouse m;
	char *act;
	enum { MResize, MMouse, MPlumb, MWarnings, NMALT };
	static Alt alts[NMALT+1];

	USED(v);
	threadsetname("mousethread");
	alts[MResize].c = mousectl->resizec;
	alts[MResize].v = nil;
	alts[MResize].op = CHANRCV;
	alts[MMouse].c = mousectl->c;
	alts[MMouse].v = &mousectl->m;
	alts[MMouse].op = CHANRCV;
	alts[MPlumb].c = cplumb;
	alts[MPlumb].v = ±
	alts[MPlumb].op = CHANRCV;
	alts[MWarnings].c = cwarn;
	alts[MWarnings].v = nil;
	alts[MWarnings].op = CHANRCV;
	if(cplumb == nil)
		alts[MPlumb].op = CHANNOP;
	alts[NMALT].op = CHANEND;

	for(;;){
		qlock(&row.lk);
		flushwarnings();
		qunlock(&row.lk);
		flushimage(display, 1);
		switch(alt(alts)){
		case MResize:
			if(getwindow(display, Refnone) < 0)
				error("attach to window");
			draw(screen, screen->r, display->white, nil, ZP);
			iconinit();
			scrlresize();
			rowresize(&row, screen->clipr);
			break;
		case MPlumb:
			if(strcmp(pm->type, "text") == 0){
				act = plumblookup(pm->attr, "action");
				if(act==nil || strcmp(act, "showfile")==0)
					plumblook(pm);
				else if(strcmp(act, "showdata")==0)
					plumbshow(pm);
			}
			plumbfree(pm);
			break;
		case MWarnings:
			break;
		case MMouse:
			/*
			 * Make a copy so decisions are consistent; mousectl changes
			 * underfoot.  Can't just receive into m because this introduces
			 * another race; see /sys/src/libdraw/mouse.c.
			 */
			m = mousectl->m;
			qlock(&row.lk);
			t = rowwhich(&row, m.xy);
			if(t!=mousetext && mousetext!=nil && mousetext->w!=nil){
				winlock(mousetext->w, 'M');
				mousetext->eq0 = ~0;
				wincommit(mousetext->w, mousetext);
				winunlock(mousetext->w);
			}
			mousetext = t;
			if(t == nil)
				goto Continue;
			w = t->w;
			if(t==nil || m.buttons==0)
				goto Continue;
			but = 0;
			if(m.buttons == 1)
				but = 1;
			else if(m.buttons == 2)
				but = 2;
			else if(m.buttons == 4)
				but = 3;
			barttext = t;
			if(t->what==Body && ptinrect(m.xy, t->scrollr)){
				if(but){
					if(swapscrollbuttons){
						if(but == 1)
							but = 3;
						else if(but == 3)
							but = 1;
					}
					winlock(w, 'M');
					t->eq0 = ~0;
					textscroll(t, but);
					winunlock(w);
				}
				goto Continue;
			}
			/* scroll buttons, wheels, etc. */
			if(w != nil && (m.buttons & (8|16))){
				if(m.buttons & 8)
					but = Kscrolloneup;
				else
					but = Kscrollonedown;
				winlock(w, 'M');
				t->eq0 = ~0;
				texttype(t, but);
				winunlock(w);
				goto Continue;
			}
			if(ptinrect(m.xy, t->scrollr)){
				if(but){
					if(t->what == Columntag)
						rowdragcol(&row, t->col, but);
					else if(t->what == Tag){
						coldragwin(t->col, t->w, but);
						if(t->w)
							barttext = &t->w->body;
					}
					if(t->col)
						activecol = t->col;
				}
				goto Continue;
			}
			if(m.buttons){
				if(w)
					winlock(w, 'M');
				t->eq0 = ~0;
				if(w)
					wincommit(w, t);
				else
					textcommit(t, TRUE);
				if(m.buttons & 1){
					textselect(t);
					if(w)
						winsettag(w);
					argtext = t;
					seltext = t;
					if(t->col)
						activecol = t->col;	/* button 1 only */
					if(t->w!=nil && t==&t->w->body)
						activewin = t->w;
				}else if(m.buttons & 2){
					if(textselect2(t, &q0, &q1, &argt))
						execute(t, q0, q1, FALSE, argt);
				}else if(m.buttons & 4){
					if(textselect3(t, &q0, &q1))
						look3(t, q0, q1, FALSE);
				}
				if(w)
					winunlock(w);
				goto Continue;
			}
    Continue:
			qunlock(&row.lk);
			break;
		}
	}
}
Beispiel #2
0
static void
groupctl(Control *c, CParse *cp)
{
	int cmd, i, n;
	
	Rectangle r;
	Group *g;

	g = (Group*)c;
	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
	switch(cmd){
	case EAdd:
		for (i = 1; i < cp->nargs; i++){
			c = controlcalled(cp->args[i]);
			if (c == nil)
				ctlerror("%q: no such control: %s", g->name, cp->args[i]);
			_ctladdgroup(g, c);
		}
		if (g->setsize)
			g->setsize((Control*)g);
		break;
	case EBorder:
		_ctlargcount(g, cp, 2);
		if(cp->iargs[1] < 0)
			ctlerror("%q: bad border: %c", g->name, cp->str);
		g->border = cp->iargs[1];
		break;
	case EBordercolor:
		_ctlargcount(g, cp, 2);
		_setctlimage(g, &g->bordercolor, cp->args[1]);
		break;
	case EFocus:
		/* ignore focus change */
		break;
	case EHide:
		_ctlargcount(g, cp, 1);
		for (i = 0; i < g->nkids; i++)
			if (g->kids[i]->ctl)
				_ctlprint(g->kids[i], "hide");
		g->hidden = 1;
		break;
	case EImage:
		_ctlargcount(g, cp, 2);
		_setctlimage(g, &g->image, cp->args[1]);
		break;
	case ERect:
		_ctlargcount(g, cp, 5);
		r.min.x = cp->iargs[1];
		r.min.y = cp->iargs[2];
		r.max.x = cp->iargs[3];
		r.max.y = cp->iargs[4];
		if(Dx(r)<=0 || Dy(r)<=0)
			ctlerror("%q: bad rectangle: %s", g->name, cp->str);
		g->rect = r;
		r = insetrect(r, g->border);
		if (g->nkids == 0)
			return;
		switch(g->type){
		case Ctlboxbox:
			boxboxresize(g, r);
			break;
		case Ctlcolumn:
			columnresize(g, r);
			break;
		case Ctlrow:
			rowresize(g, r);
			break;
		case Ctlstack:
			stackresize(g, r);
			break;
		}
		break;
	case ERemove:
		_ctlargcount(g, cp, 2);
		for (n = 0; n < g->nkids; n++)
			if (strcmp(cp->args[1], g->kids[n]->name) == 0)
				break;
		if (n == g->nkids)
			ctlerror("%s: remove nonexistent control: %q", g->name, cp->args[1]);
		removegroup(g, n);
		if (g->setsize)
			g->setsize((Control*)g);
		break;
	case EReveal:
		g->hidden = 0;
		if (debugr) fprint(2, "reveal %s\n", g->name);
		if (g->type == Ctlstack){
			if (cp->nargs == 2){
				if (cp->iargs[1] < 0 || cp->iargs[1] >= g->nkids)
					ctlerror("%s: control out of range: %q", g->name, cp->str);
				g->selected = cp->iargs[1];
			}else
				_ctlargcount(g, cp, 1);
			for (i = 0; i < g->nkids; i++)
				if (g->kids[i]->ctl){
					if (g->selected == i){
						if (debugr) fprint(2, "reveal %s: reveal kid %s\n", g->name, g->kids[i]->name);
						_ctlprint(g->kids[i], "reveal");
					}else{
						if (debugr) fprint(2, "reveal %s: hide kid %s\n", g->name, g->kids[i]->name);
						_ctlprint(g->kids[i], "hide");
					}
				}
			break;
		}
		_ctlargcount(g, cp, 1);
		if (debug) fprint(2, "reveal %s: border %R/%d\n", g->name, g->rect, g->border);
		border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min);
		r = insetrect(g->rect, g->border);
		if (debug) fprint(2, "reveal %s: draw %R\n", g->name, r);
		draw(g->screen, r, g->image->image, nil, g->image->image->r.min);
		for (i = 0; i < g->nkids; i++)
			if (g->kids[i]->ctl)
				_ctlprint(g->kids[i], "reveal");
		break;
	case EShow:
		_ctlargcount(g, cp, 1);
		if (g->hidden)
			break;
		// pass it on to the kiddies
		if (debug) fprint(2, "show %s: border %R/%d\n", g->name, g->rect, g->border);
		border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min);
		r = insetrect(g->rect, g->border);
		if (debug) fprint(2, "show %s: draw %R\n", g->name, r);
		draw(g->screen, r, g->image->image, nil, g->image->image->r.min);
		for (i = 0; i < g->nkids; i++)
			if (g->kids[i]->ctl){
				if (debug) fprint(2, "show %s: kid %s: %q\n", g->name, g->kids[i]->name, cp->str);
				_ctlprint(g->kids[i], "show");
			}
		flushimage(display, 1);
		break;
	case ESize:
		r.max = Pt(_Ctlmaxsize, _Ctlmaxsize);
		if (g->type == Ctlboxbox)
			_ctlargcount(g, cp, 5);
		switch(cp->nargs){
		default:
			ctlerror("%s: args of %q", g->name, cp->str);
		case 1:
			/* recursively set size */
			g->mansize = 0;
			if (g->setsize)
				g->setsize((Control*)g);
			break;
		case 5:
			_ctlargcount(g, cp, 5);
			r.max.x = cp->iargs[3];
			r.max.y = cp->iargs[4];
			/* fall through */
		case 3:
			r.min.x = cp->iargs[1];
			r.min.y = cp->iargs[2];
			if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)
			ctlerror("%q: bad sizes: %s", g->name, cp->str);
			g->size = r;
			g->mansize = 1;
			break;
		}
		break;
	case ESeparation:
		if (g->type != Ctlstack){
			_ctlargcount(g, cp, 2);
			if(cp->iargs[1] < 0)
				ctlerror("%q: illegal value: %c", g->name, cp->str);
			g->separation = cp->iargs[1];
			break;
		}
		// fall through for Ctlstack
	default:
		ctlerror("%q: unrecognized message '%s'", g->name, cp->str);
		break;
	}
}
Beispiel #3
0
void
mousethread(void *)
{
	Plumbmsg *pm;
	Mouse m;
	Text *t;
	int but;
	enum { MResize, MMouse, MPlumb, MRefresh, NMALT };
	static Alt alts[NMALT+1];

	threadsetname("mousethread");
	alts[MResize].c = mousectl->resizec;
	alts[MResize].v = nil;
	alts[MResize].op = CHANRCV;
	alts[MMouse].c = mousectl->c;
	alts[MMouse].v = &mousectl->Mouse;
	alts[MMouse].op = CHANRCV;
	alts[MPlumb].c = cplumb;
	alts[MPlumb].v = &pm;
	alts[MPlumb].op = CHANRCV;
	alts[MRefresh].c = crefresh;
	alts[MRefresh].v = nil;
	alts[MRefresh].op = CHANRCV;
	if(cplumb == nil)
		alts[MPlumb].op = CHANNOP;
	alts[NMALT].op = CHANEND;

	for(;;){
		qlock(&row);
		flushrefresh();
		qunlock(&row);
		flushimage(display, 1);
		switch(alt(alts)){
		case MResize:
			if(getwindow(display, Refnone) < 0)
				error("resized");
			scrlresize();
			tmpresize();
			rowresize(&row, screen->clipr);
			break;
		case MPlumb:
			plumblook(pm);
			plumbfree(pm);
			break;
		case MRefresh:
			break;
		case MMouse:
			m = mousectl->Mouse;
			if(m.buttons == 0)
				continue;

			qlock(&row);
			but = 0;
			if(m.buttons == 1)
				but = 1;
			else if(m.buttons == 2)
				but = 2;
			else if(m.buttons == 4)
				but = 3;

			if(m.buttons & (8|16)){
				if(m.buttons & 8)
					but = Kscrolloneup;
				else
					but = Kscrollonedown;
				rowwhich(&row, m.xy, but, TRUE);
			}else	if(but){
				t = rowwhich(&row, m.xy, but, FALSE);
				if(t)
					textmouse(t, m.xy, but);
			}
			qunlock(&row);
			break;
		}
	}
}