// // SearchDialog.cc for pekwm // Copyright © 2009 Claes Nästén // // This program is licensed under the GNU GPL. // See the LICENSE file for more information. // #ifdef HAVE_CONFIG_H #include "config.h" #endif // HAVE_CONFIG_H #include "SearchDialog.hh" #include "Client.hh" #include "RegexString.hh" #include #include using std::cerr; using std::endl; using std::list; using std::wcerr; /** * SearchDialog constructor. */ SearchDialog::SearchDialog(Theme *theme) : InputDialog(theme, L"Search"), _result_menu(0) { _type = PWinObj::WO_SEARCH_DIALOG; // Set up ActionEvent _ae.action_list.back().setAction(ACTION_GOTO_CLIENT); // Set up menu for displaying results _result_menu = new PMenu(_theme, L"", ""); _result_menu->reparent(this, borderLeft(), borderTop() + getTitleHeight() + _text_wo->getHeight()); _result_menu->setLayer(LAYER_DESKTOP); // Ignore when placing _result_menu->setSticky(STATE_SET); _result_menu->setBorder(STATE_UNSET); _result_menu->setTitlebar(STATE_UNSET); _result_menu->setFocusable(false); _result_menu->mapWindow(); } /** * SearchDialog destructor. */ SearchDialog::~SearchDialog(void) { delete _result_menu; } /** * Run when INPUT_EXEC is entered in the dialog giving the selected * Client focus if any. */ ActionEvent* SearchDialog::exec(void) { // InputDialog::close() may have overwritten our action. _ae.action_list.back().setAction(ACTION_GOTO_CLIENT); PWinObj *wo_ref = 0; if (_result_menu->getItemCurr()) { wo_ref = _result_menu->getItemCurr()->getWORef(); } setWORef(wo_ref); return &_ae; } /** * Called whenever the buffer has changed. Updates the displayed clients. */ void SearchDialog::bufChanged(void) { InputDialog::bufChanged(); findClients(_buf); } /** * Focus next item in result menu. */ void SearchDialog::histNext(void) { _result_menu->selectItemRel(1); } /** * Focus previous item in result menu. */ void SearchDialog::histPrev(void) { _result_menu->selectItemRel(-1); } /** * Update size making sure result menu fits. */ void SearchDialog::updateSize(void) { InputDialog::updateSize(); _result_menu->setMenuWidth(_text_wo->getWidth()); } /** * Search list of clients for matching titles. * * @param search Regexp to search, case insensitive * @return Number of matches */ uint SearchDialog::findClients(const std::wstring &search) { // Do nothing if search has not changed. if (_previous_search == search) { return _result_menu->size(); } _previous_search = search; _result_menu->removeAll(); if (search.size() > 0) { RegexString search_re(L"/" + search + L"/i"); if (! search_re.is_match_ok()) { return 0; } list matches; list::iterator it(Client::client_begin()); for (; it != Client::client_end(); ++it) { if ((*it)->isFocusable() && ! (*it)->isSkip(SKIP_FOCUS_TOGGLE) && search_re == (*it)->getTitle()->getReal()) { matches.push_back(*it); } } for (it = matches.begin(); it != matches.end(); ++it) { _result_menu->insert((*it)->getTitle()->getVisible(), *it, (*it)->getIcon()); } } // Rebuild menu and make room for it _result_menu->buildMenu(); unsigned int width, height; getInputSize(width, height); if (_result_menu->size()) { resizeChild(_text_wo->getWidth(), height + _result_menu->getHeight()); XRaiseWindow(_dpy, _result_menu->getWindow()); // Render first item as selected, needs to be done after map/raise. _result_menu->selectItemNum(0); } else { resizeChild(_text_wo->getWidth(), height); XLowerWindow(_dpy, _result_menu->getWindow()); } return 0; } /** * Unmap window and clear buffer, result menu and window reference. */ void SearchDialog::unmapWindow(void) { if (_mapped) { InputDialog::unmapWindow(); setWORef(0); bufClear(); // Clear the menu and hide it. _result_menu->clear(); _previous_search.clear(); XLowerWindow(_dpy, _result_menu->getWindow()); } }