Esempio n. 1
0
void
ungrab(XButtonEvent *e)
{
	XEvent ev;

	if(!nobuttons(e))
		for(;;){
			XMaskEvent(dpy, ButtonMask | ButtonMotionMask, &ev);
			if(ev.type == MotionNotify)
				continue;
			e = &ev.xbutton;
			if(nobuttons(e))
				break;
		}
	XUngrabPointer(dpy, e->time);
	curtime = e->time;
}
Esempio n. 2
0
int
menuhit(XButtonEvent *e, Menu *m)
{
	XEvent ev;
	int i, n, cur, old, wide, high, status, drawn, warp;
	int x, y, dx, dy, xmax, ymax;
	ScreenInfo *s;

	if(font == 0)
		return -1;
	s = getscreen(e->root);
	if(s == 0 || e->window == s->menuwin)	   /* ugly event mangling */
		return -1;

	dx = 0;
	for(n = 0; m->item[n]; n++){
		wide = XTextWidth(font, m->item[n], strlen(m->item[n])) + 4;
		if(wide > dx)
			dx = wide;
	}
	wide = dx;
	cur = m->lasthit;
	if(cur >= n)
		cur = n - 1;

	high = font->ascent + font->descent + 1;
	dy = n*high;
	x = e->x - wide/2;
	y = e->y - cur*high - high/2;
	warp = 0;
	xmax = DisplayWidth(dpy, s->num);
	ymax = DisplayHeight(dpy, s->num);
	if(x < 0){
		e->x -= x;
		x = 0;
		warp++;
	}
	if(x+wide >= xmax){
		e->x -= x+wide-xmax;
		x = xmax-wide;
		warp++;
	}
	if(y < 0){
		e->y -= y;
		y = 0;
		warp++;
	}
	if(y+dy >= ymax){
		e->y -= y+dy-ymax;
		y = ymax-dy;
		warp++;
	}
	if(warp)
		setmouse(e->x, e->y, s);
	XMoveResizeWindow(dpy, s->menuwin, x, y, dx, dy);
	XSelectInput(dpy, s->menuwin, MenuMask);
	XMapRaised(dpy, s->menuwin);
	status = grab(s->menuwin, None, MenuGrabMask, None, e->time);
	if(status != GrabSuccess){
		/* graberror("menuhit", status); */
		XUnmapWindow(dpy, s->menuwin);
		return -1;
	}
	drawn = 0;
	for(;;){
		XMaskEvent(dpy, MenuMask, &ev);
		switch (ev.type){
		default:
			fprintf(stderr, "rio: menuhit: unknown ev.type %d\n", ev.type);
			break;
		case ButtonPress:
			break;
		case ButtonRelease:
			if(ev.xbutton.button != e->button)
				break;
			x = ev.xbutton.x;
			y = ev.xbutton.y;
			i = y/high;
			if(cur >= 0 && y >= cur*high-3 && y < (cur+1)*high+3)
				i = cur;
			if(x < 0 || x > wide || y < -3)
				i = -1;
			else if(i < 0 || i >= n)
				i = -1;
			else
				m->lasthit = i;
			if(!nobuttons(&ev.xbutton))
				i = -1;
			ungrab(&ev.xbutton);
			XUnmapWindow(dpy, s->menuwin);
			return i;
		case MotionNotify:
			if(!drawn)
				break;
			x = ev.xbutton.x;
			y = ev.xbutton.y;
			old = cur;
			cur = y/high;
			if(old >= 0 && y >= old*high-3 && y < (old+1)*high+3)
				cur = old;
			if(x < 0 || x > wide || y < -3)
				cur = -1;
			else if(cur < 0 || cur >= n)
				cur = -1;
			if(cur == old)
				break;
			if(old >= 0 && old < n)
				drawstring(dpy, s, m, wide, high, old, 0);
			if(cur >= 0 && cur < n)
				drawstring(dpy, s, m, wide, high, cur, 1);
			break;
		case Expose:
			XClearWindow(dpy, s->menuwin);
			for(i = 0; i < n; i++)
				drawstring(dpy, s, m, wide, high, i, cur==i);
			drawn = 1;
		}
	}
}
Esempio n. 3
0
File: Menu.C Progetto: bbidulock/wmx
int Menu::getSelection()
{
    m_items = getItems(&m_nItems, &m_nHidden);
    XButtonEvent *xbev = (XButtonEvent *)m_event; // KeyEvent is similar enough

    if (xbev->window == m_window[screen()] || m_nItems == 0) return -1;

    int width, maxWidth = 10;
    for (int i = 0; i < m_nItems; i++) {
	width = getTextWidth(m_items[i], STRLEN_MITEMS(i));
	if (width > maxWidth) maxWidth = width;
    }
    maxWidth += 32;

    Boolean isKeyboardMenu = isKeyboardMenuEvent(m_event);
    int selecting = isKeyboardMenu ? 0 : -1, prev = -1;
#ifdef CONFIG_USE_XFT
    int entryHeight = m_font->ascent + m_font->descent + 4;
#else
    int entryHeight = m_font[screen()]->ascent + m_font[screen()]->descent + 4;
#endif
    int totalHeight = entryHeight * m_nItems + 13;

    int mx = DisplayWidth (display(), screen()) - 1;
    int my = DisplayHeight(display(), screen()) - 1;

    int x, y;

    if (isKeyboardMenu) {
	x = mx / 2 - maxWidth / 2;
	y = my / 2 - totalHeight / 2;
    } else {

	x = xbev->x - maxWidth/2;
	y = xbev->y - 2;

	Boolean warp = False;

	if (x < 0) {
	    xbev->x -= x;
	    x = 0;
	    warp = True;
	} else if (x + maxWidth >= mx) {
	    xbev->x -= x + maxWidth - mx;
	    x = mx - maxWidth;
	    warp = True;
	}
    
	if (y < 0) {
	    xbev->y -= y;
	    y = 0;
	    warp = True;
	} else if (y + totalHeight >= my) {
	    xbev->y -= y + totalHeight - my;
	    y = my - totalHeight;
	    warp = True;
	}

	if (warp) XWarpPointer(display(), None, root(), None, None,
			       None, None, xbev->x, xbev->y);
    }

    XMoveResizeWindow(display(), m_window[screen()], x, y, maxWidth, totalHeight);
    XSelectInput(display(), m_window[screen()], MenuMask);
    XMapRaised(display(), m_window[screen()]);

    if (m_windowManager->attemptGrab(m_window[screen()], None,
				     MenuGrabMask, xbev->time)
	!= GrabSuccess) {
	XUnmapWindow(display(), m_window[screen()]);
	return -1;
    }
    
    if (isKeyboardMenu) {
	if (m_windowManager->attemptGrabKey(m_window[screen()], xbev->time)
	    != GrabSuccess) {
	    XUnmapWindow(display(), m_window[screen()]);
	    return -1;
	}
    }	    

    Boolean done = False;
    Boolean drawn = False;
    XEvent event;
    struct timeval sleepval;
    unsigned long tdiff = 0L;
    Boolean speculating = False;
    Boolean foundEvent;

    while (!done)
    {
	int i;
	foundEvent = False;

	if (CONFIG_FEEDBACK_DELAY >= 0 &&
	    tdiff > (unsigned long)CONFIG_FEEDBACK_DELAY &&
	    !isKeyboardMenu && // removeFeedback didn't seem to work for it
	    !speculating) {

	    if (selecting >= 0 && selecting < m_nItems) {
		raiseFeedbackLevel(selecting);
		XRaiseWindow(display(), m_window[screen()]);
	    }

	    speculating = True;
	}

	//!!! MenuMask | ??? suggests MenuMask is wrong
	while (XCheckMaskEvent
	       (display(), MenuMask | StructureNotifyMask |
		KeyPressMask | KeyReleaseMask, &event)) {
	    foundEvent = True;
	    if (event.type != MotionNotify) break;
	}

	if (!foundEvent) {
	    sleepval.tv_sec = 0;
	    sleepval.tv_usec = 10000;
	    select(0, 0, 0, 0, &sleepval);
	    tdiff += 10;
	    continue;
	}
	
	switch (event.type)
	{
	case ButtonPress:
	    break;
	    
	case ButtonRelease:
	    if (isKeyboardMenu) break;

	    if (drawn) {

		if (event.xbutton.button != xbev->button) break;
		x = event.xbutton.x;
		y = event.xbutton.y - 11;
		i = y / entryHeight;
		
		if (selecting >= 0 && y >= selecting * entryHeight - 3 &&
		    y <= (selecting + 1) * entryHeight - 3) i = selecting;

		if (m_hasSubmenus && (i >= 0 && i < m_nHidden)) i = -i;
		
		if (x < 0 || x > maxWidth || y < -3) i = -1;
		else if (i < 0 || i >= m_nItems) i = -1;
		
	    } else {
		i = -1;
	    }
	    
	    if (!nobuttons(&event.xbutton)) i = -1;
	    m_windowManager->releaseGrab(&event.xbutton);
	    XUnmapWindow(display(), m_window[screen()]);
	    selecting = i;
	    done = True;
	    break;

	case MotionNotify:
	    if (!drawn || isKeyboardMenu) break;

	    x = event.xbutton.x;
	    y = event.xbutton.y - 11;
	    prev = selecting;
	    selecting = y / entryHeight;

	    if (prev >= 0 && y >= prev * entryHeight - 3 &&
		y <= (prev+1) * entryHeight - 3) selecting = prev;

	    if (m_hasSubmenus && (selecting >= 0 && selecting < m_nHidden) &&
		x >= maxWidth-32 && x < maxWidth)
	    {
		xbev->x += event.xbutton.x - 32;
		xbev->y += event.xbutton.y;
		
		createSubmenu ((XEvent *)xbev, selecting);
		done = True;
		break;
	    }
	    
	    if (x < 0 || x > maxWidth || y < -3) selecting = -1;
	    else if (selecting < 0 || selecting > m_nItems) selecting = -1;

	    if (selecting == prev) break;
	    tdiff = 0; speculating = False;

	    if (prev >= 0 && prev < m_nItems) {
		removeFeedback(prev, speculating);
		XFillRectangle(display(), m_window[screen()], m_menuGC[screen()],
			       4, prev * entryHeight + 9,
			       maxWidth - 8, entryHeight);
	    }

	    if (selecting >= 0 && selecting < m_nItems) {
		showFeedback(selecting);
		XRaiseWindow(display(), m_window[screen()]);
		XFillRectangle(display(), m_window[screen()], m_menuGC[screen()],
			       4, selecting * entryHeight + 9,
			       maxWidth - 8, entryHeight);
	    }
	    
	    break;
			
	case Expose:

	    if (CONFIG_MAD_FEEDBACK && event.xexpose.window != m_window[screen()]) {
		m_windowManager->dispatchEvent(&event);
		break;
	    }

	    XClearWindow(display(), m_window[screen()]);
			
	    XDrawRectangle(display(), m_window[screen()], m_menuGC[screen()], 2, 7,
			   maxWidth - 5, totalHeight - 10);

	    for (i = 0; i < m_nItems; i++) {

		int dx = getTextWidth(m_items[i], STRLEN_MITEMS(i));
#ifdef CONFIG_USE_XFT
		int dy = i * entryHeight + m_font->ascent + 10;
#else
		int dy = i * entryHeight + m_font[screen()]->ascent + 10;
#endif

		if (i >= m_nHidden) {
#ifdef CONFIG_USE_XFT
		    XftDrawStringUtf8(m_xftDraw[screen()],
				      &m_xftColour[screen()],
				      m_font,
				      maxWidth - 8 - dx, dy,
				      (FcChar8 *)m_items[i], STRLEN_MITEMS(i));
#else
		    XDrawString(display(), m_window[screen()],
				Border::drawGC(m_windowManager,screen()),
				maxWidth - 8 - dx, dy,
				m_items[i], STRLEN_MITEMS(i));
#endif
		} else {
#ifdef CONFIG_USE_XFT
		    XftDrawStringUtf8(m_xftDraw[screen()],
				      &m_xftColour[screen()],
				      m_font,
				      8, dy,
				      (FcChar8 *)m_items[i], STRLEN_MITEMS(i));
#else
		    XDrawString(display(), m_window[screen()],
				Border::drawGC(m_windowManager,screen()),
				8, dy, m_items[i], STRLEN_MITEMS(i));
#endif
		}
	    }

	    if (selecting >= 0 && selecting < m_nItems) {
		XFillRectangle(display(), m_window[screen()], m_menuGC[screen()],
			       4, selecting * entryHeight + 9,
			       maxWidth - 8, entryHeight);
	    }

	    drawn = True;
	    break;

	case KeyPress:
	{
	    if (!isKeyboardMenu) break;

	    KeySym key = XKeycodeToKeysym(display(), event.xkey.keycode, 0);

	    if (key == CONFIG_MENU_SELECT_KEY) {

		if (!drawn) selecting = -1;

		if (m_hasSubmenus && selecting >= 0 && selecting < m_nHidden)
		{
		    createSubmenu((XEvent *)xbev, selecting);
		    selecting = -1;
		}
		m_windowManager->releaseGrabKeyMode(&event.xkey);
		XUnmapWindow(display(), m_window[screen()]);
		done = True;
		break;

	    } else if (key == CONFIG_MENU_CANCEL_KEY) {

		m_windowManager->releaseGrabKeyMode(&event.xkey);
		XUnmapWindow(display(), m_window[screen()]);
		if (selecting >= 0) removeFeedback(selecting, speculating);
		selecting = -1;
		done = True;
		break;

	    } else if (key != CONFIG_MENU_UP_KEY &&
		       key != CONFIG_MENU_DOWN_KEY) {
		break;
	    }

	    if (!drawn) break;
	    prev = selecting;

	    if (key == CONFIG_MENU_UP_KEY) {

		if (prev <= 0) selecting = m_nItems - 1;
		else selecting = prev - 1;

	    } else {

		if (prev == m_nItems - 1 || prev < 0) selecting = 0;
		else selecting = prev + 1;
	    }

	    tdiff = 0; speculating = False;
	    
	    if (prev >= 0 && prev < m_nItems) {
	    	removeFeedback(prev, speculating);
		XFillRectangle(display(), m_window[screen()], m_menuGC[screen()],
			       4, prev * entryHeight + 9,
			       maxWidth - 8, entryHeight);
	    }

	    if (selecting >= 0 && selecting < m_nItems) {
		showFeedback(selecting);
		XRaiseWindow(display(), m_window[screen()]);
		XFillRectangle(display(), m_window[screen()], m_menuGC[screen()],
			       4, selecting * entryHeight + 9,
			       maxWidth - 8, entryHeight);
	    }

	    break;
	}

	case KeyRelease:
	    break;

	default:
	    if (event.xmap.window == m_window[screen()]) break;
	    m_windowManager->dispatchEvent(&event);
	}
    }

    if (selecting >= 0) removeFeedback(selecting, speculating);
    return selecting;
}