void ProcessorRouter::disconnect(Processor* destination, const Output* source) { if (isDownstream(destination, source->owner)) { // We're fine unless there is a cycle and need to delete a Feedback node. for (int i = 0; i < destination->numInputs(); ++i) { const Processor* owner = destination->input(i)->source->owner; if (feedback_processors_.find(owner) != feedback_processors_.end()) { Feedback* feedback = feedback_processors_[owner]; if (feedback->input()->source == source) removeFeedback(feedback_processors_[owner]); destination->input(i)->source = &Processor::null_source_; } } } }
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; }