bool QClipboard::ownsMode(Mode mode) const { if (mode == Clipboard) return clipboardData()->timestamp != CurrentTime; else if(mode == Selection) return selectionData()->timestamp != CurrentTime; else return false; }
bool qt_xfixes_selection_changed(Window selectionOwner, Time timestamp) { QClipboardData *d = selectionData(); #ifdef QCLIPBOARD_DEBUG DEBUG("qt_xfixes_selection_changed: owner = %u; selectionOwner = %u; internal timestamp = %u; external timestamp = %u", (unsigned int)(owner ? (int)owner->internalWinId() : 0), (unsigned int)selectionOwner, (unsigned int)(d ? d->timestamp : 0), (unsigned int)timestamp); #endif if (!owner || (selectionOwner && selectionOwner != owner->internalWinId()) || (!selectionOwner && (d->timestamp == CurrentTime || d->timestamp < timestamp))) return qt_check_selection_sentinel(); return false; }
bool qt_check_selection_sentinel() { bool doIt = true; if (owner && !X11->use_xfixes) { /* Since the X selection mechanism cannot give any signal when the selection has changed, we emulate it (for Qt processes) here. The notification should be ignored in case of either a) This is the process that did setData (because setData() then has already emitted dataChanged()) b) This is the process that owned the selection when dataChanged() was called (because we have then received a SelectionClear event, and have already emitted dataChanged() as a result of that) */ unsigned char *retval; Atom actualType; int actualFormat; ulong nitems; ulong bytesLeft; if (XGetWindowProperty(X11->display, QApplication::desktop()->screen(0)->internalWinId(), ATOM(_QT_SELECTION_SENTINEL), 0, 2, False, XA_WINDOW, &actualType, &actualFormat, &nitems, &bytesLeft, &retval) == Success) { Window *owners = (Window *)retval; if (actualType == XA_WINDOW && actualFormat == 32 && nitems == 2) { Window win = owner->internalWinId(); if (owners[0] == win || owners[1] == win) doIt = false; } XFree(owners); } } if (doIt) { if (waiting_for_data) { pending_selection_changed = true; if (! pending_timer_id) pending_timer_id = QApplication::clipboard()->startTimer(0); doIt = false; } else { selectionData()->clear(); } } return doIt; }
const QMimeData* QClipboard::mimeData(Mode mode) const { QClipboardData *d = 0; switch (mode) { case Selection: d = selectionData(); break; case Clipboard: d = clipboardData(); break; default: qWarning("QClipboard::mimeData: unsupported mode '%d'", mode); return 0; } if (! d->source() && ! timer_event_clear) { if (mode == Selection) { if (! selection_watcher) selection_watcher = new QClipboardWatcher(mode); d->setSource(selection_watcher); } else { if (! clipboard_watcher) clipboard_watcher = new QClipboardWatcher(mode); d->setSource(clipboard_watcher); } if (! timer_id) { // start a zero timer - we will clear cached data when the timer // times out, which will be the next time we hit the event loop... // that way, the data is cached long enough for calls within a single // loop/function, but the data doesn't linger around in case the selection // changes QClipboard *that = ((QClipboard *) this); timer_id = that->startTimer(0); } } return d->source(); }
ResearchTech getResearchTech(const PlayerTactics& playerTactics, TechTypes ignoreTechType) { TechSelectionData selectionData(playerTactics); // pure tech tactics ('first to tech' items, open borders, etc...) for (PlayerTactics::TechTacticsMap::const_iterator ci = playerTactics.techTacticsMap_.begin(), ciEnd = playerTactics.techTacticsMap_.end(); ci != ciEnd; ++ci) { if (ci->second) { ci->second->apply(selectionData.tacticSelectionDataMap[DependencyItem(ResearchTechDependency::ID, ci->first)]); } } // buildings for (PlayerTactics::CityBuildingTacticsMap::const_iterator ci = playerTactics.cityBuildingTacticsMap_.begin(), ciEnd = playerTactics.cityBuildingTacticsMap_.end(); ci != ciEnd; ++ci) { const CvCity* pCity = getCity(ci->first); const City& city = gGlobals.getGame().getAltAI()->getPlayer(pCity->getOwner())->getCity(pCity); for (PlayerTactics::CityBuildingTacticsList::const_iterator li(ci->second.begin()), liEnd(ci->second.end()); li != liEnd; ++li) { li->second->update(playerTactics.player, city.getCityData()); li->second->apply(selectionData.tacticSelectionDataMap, IDependentTactic::Ignore_Techs); } } // units for (PlayerTactics::UnitTacticsMap::const_iterator iter(playerTactics.unitTacticsMap_.begin()), endIter(playerTactics.unitTacticsMap_.end()); iter != endIter; ++iter) { if (iter->second) { iter->second->update(playerTactics.player); iter->second->apply(selectionData.tacticSelectionDataMap, IDependentTactic::Ignore_Techs); } } // city improvements for (PlayerTactics::CityImprovementTacticsMap::const_iterator ci(playerTactics.cityImprovementTacticsMap_.begin()), ciEnd(playerTactics.cityImprovementTacticsMap_.end()); ci != ciEnd; ++ci) { const CvCity* pCity = getCity(ci->first); if (pCity) { const City& city = playerTactics.player.getCity(pCity); TotalOutput base = city.getCurrentOutputProjection().getOutput(); for (PlayerTactics::CityImprovementTacticsList::const_iterator li(ci->second.begin()), liEnd(ci->second.end()); li != liEnd; ++li) { (*li)->update(playerTactics.player, city.getCityData()); const std::vector<ResearchTechDependencyPtr> techs = (*li)->getTechDependencies(); for (size_t i = 0, count = techs.size(); i < count; ++i) { selectionData.tacticSelectionDataMap[techs[i]->getDependencyItem()].cityImprovementsDelta += (*li)->getProjection().getOutput() - base; } } } } // processes for (PlayerTactics::ProcessTacticsMap::const_iterator ci(playerTactics.processTacticsMap_.begin()), ciEnd(playerTactics.processTacticsMap_.end()); ci != ciEnd; ++ci) { if (ci->second->areDependenciesSatisfied(playerTactics.player, IDependentTactic::Ignore_Techs)) { CityIter iter(*playerTactics.player.getCvPlayer()); TotalOutput processOutput; while (CvCity* pCity = iter()) { ProjectionLadder projection = ci->second->getProjection(pCity->getIDInfo()); processOutput += projection.getProcessOutput(); } const std::vector<ResearchTechDependencyPtr>& techs = ci->second->getTechDependencies(); for (size_t i = 0, count = techs.size(); i < count; ++i) { selectionData.tacticSelectionDataMap[techs[i]->getDependencyItem()]. processOutputsMap[ci->second->getProcessType()] += processOutput; } } } selectionData.processTechs(); if (ignoreTechType != NO_TECH) { //selectionData.removeTech(ignoreTechType); } selectionData.scoreTechs(); selectionData.debug(); return selectionData.getSelection(); }
bool QClipboard::event(QEvent *e) { if (e->type() == QEvent::Timer) { QTimerEvent *te = (QTimerEvent *) e; if (waiting_for_data) // should never happen return false; if (te->timerId() == timer_id) { killTimer(timer_id); timer_id = 0; timer_event_clear = true; if (selection_watcher) // clear selection selectionData()->clear(); if (clipboard_watcher) // clear clipboard clipboardData()->clear(); timer_event_clear = false; return true; } else if (te->timerId() == pending_timer_id) { // I hate klipper killTimer(pending_timer_id); pending_timer_id = 0; if (pending_clipboard_changed) { pending_clipboard_changed = false; clipboardData()->clear(); emitChanged(QClipboard::Clipboard); } if (pending_selection_changed) { pending_selection_changed = false; selectionData()->clear(); emitChanged(QClipboard::Selection); } return true; } else if (te->timerId() == incr_timer_id) { killTimer(incr_timer_id); incr_timer_id = 0; qt_xclb_incr_timeout(); return true; } else { return QObject::event(e); } } else if (e->type() != QEvent::Clipboard) { return QObject::event(e); } XEvent *xevent = (XEvent *)(((QClipboardEvent *)e)->data()); Display *dpy = X11->display; if (!xevent) { // That means application exits and we need to give clipboard // content to the clipboard manager. // First we check if there is a clipboard manager. if (XGetSelectionOwner(X11->display, ATOM(CLIPBOARD_MANAGER)) == XNone || !owner) return true; Window ownerId = owner->internalWinId(); Q_ASSERT(ownerId); // we delete the property so the manager saves all TARGETS. XDeleteProperty(X11->display, ownerId, ATOM(_QT_SELECTION)); XConvertSelection(X11->display, ATOM(CLIPBOARD_MANAGER), ATOM(SAVE_TARGETS), ATOM(_QT_SELECTION), ownerId, X11->time); XSync(dpy, false); XEvent event; // waiting until the clipboard manager fetches the content. if (!X11->clipboardWaitForEvent(ownerId, SelectionNotify, &event, 10000)) { qWarning("QClipboard: Unable to receive an event from the " "clipboard manager in a reasonable time"); } return true; } switch (xevent->type) { case SelectionClear: // new selection owner if (xevent->xselectionclear.selection == XA_PRIMARY) { QClipboardData *d = selectionData(); // ignore the event if it was generated before we gained selection ownership if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp) break; DEBUG("QClipboard: new selection owner 0x%lx at time %lx (ours %lx)", XGetSelectionOwner(dpy, XA_PRIMARY), xevent->xselectionclear.time, d->timestamp); if (! waiting_for_data) { d->clear(); emitChanged(QClipboard::Selection); } else { pending_selection_changed = true; if (! pending_timer_id) pending_timer_id = QApplication::clipboard()->startTimer(0); } } else if (xevent->xselectionclear.selection == ATOM(CLIPBOARD)) { QClipboardData *d = clipboardData(); // ignore the event if it was generated before we gained selection ownership if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp) break; DEBUG("QClipboard: new clipboard owner 0x%lx at time %lx (%lx)", XGetSelectionOwner(dpy, ATOM(CLIPBOARD)), xevent->xselectionclear.time, d->timestamp); if (! waiting_for_data) { d->clear(); emitChanged(QClipboard::Clipboard); } else { pending_clipboard_changed = true; if (! pending_timer_id) pending_timer_id = QApplication::clipboard()->startTimer(0); } } else { qWarning("QClipboard: Unknown SelectionClear event received"); return false; } break; case SelectionNotify: /* Something has delivered data to us, but this was not caught by QClipboardWatcher::getDataInFormat() Just skip the event to prevent Bad Things (tm) from happening later on... */ break; case SelectionRequest: { // someone wants our data XSelectionRequestEvent *req = &xevent->xselectionrequest; if (requestor && req->requestor == requestor->internalWinId()) break; XEvent event; event.xselection.type = SelectionNotify; event.xselection.display = req->display; event.xselection.requestor = req->requestor; event.xselection.selection = req->selection; event.xselection.target = req->target; event.xselection.property = XNone; event.xselection.time = req->time; DEBUG("QClipboard: SelectionRequest from %lx\n" " selection 0x%lx (%s) target 0x%lx (%s)", req->requestor, req->selection, X11->xdndAtomToString(req->selection).data(), req->target, X11->xdndAtomToString(req->target).data()); QClipboardData *d; if (req->selection == XA_PRIMARY) { d = selectionData(); } else if (req->selection == ATOM(CLIPBOARD)) { d = clipboardData(); } else { qWarning("QClipboard: Unknown selection '%lx'", req->selection); XSendEvent(dpy, req->requestor, False, NoEventMask, &event); break; } if (! d->source()) { qWarning("QClipboard: Cannot transfer data, no data available"); XSendEvent(dpy, req->requestor, False, NoEventMask, &event); break; } DEBUG("QClipboard: SelectionRequest at time %lx (ours %lx)", req->time, d->timestamp); if (d->timestamp == CurrentTime // we don't own the selection anymore || (req->time != CurrentTime && req->time < d->timestamp)) { DEBUG("QClipboard: SelectionRequest too old"); XSendEvent(dpy, req->requestor, False, NoEventMask, &event); break; } Atom xa_targets = ATOM(TARGETS); Atom xa_multiple = ATOM(MULTIPLE); Atom xa_timestamp = ATOM(TIMESTAMP); struct AtomPair { Atom target; Atom property; } *multi = 0; Atom multi_type = XNone; int multi_format = 0; int nmulti = 0; int imulti = -1; bool multi_writeback = false; if (req->target == xa_multiple) { QByteArray multi_data; if (req->property == XNone || !X11->clipboardReadProperty(req->requestor, req->property, false, &multi_data, 0, &multi_type, &multi_format) || multi_format != 32) { // MULTIPLE property not formatted correctly XSendEvent(dpy, req->requestor, False, NoEventMask, &event); break; } nmulti = multi_data.size()/sizeof(*multi); multi = new AtomPair[nmulti]; memcpy(multi,multi_data.data(),multi_data.size()); imulti = 0; } for (; imulti < nmulti; ++imulti) { Atom target; Atom property; if (multi) { target = multi[imulti].target; property = multi[imulti].property; } else { target = req->target; property = req->property; if (property == XNone) // obsolete client property = target; } Atom ret = XNone; if (target == XNone || property == XNone) { ; } else if (target == xa_timestamp) { if (d->timestamp != CurrentTime) { XChangeProperty(dpy, req->requestor, property, XA_INTEGER, 32, PropModeReplace, (uchar *) &d->timestamp, 1); ret = property; } else { qWarning("QClipboard: Invalid data timestamp"); } } else if (target == xa_targets) { ret = send_targets_selection(d, req->requestor, property); } else { ret = send_selection(d, target, req->requestor, property); } if (nmulti > 0) { if (ret == XNone) { multi[imulti].property = XNone; multi_writeback = true; } } else { event.xselection.property = ret; break; } } if (nmulti > 0) { if (multi_writeback) { // according to ICCCM 2.6.2 says to put None back // into the original property on the requestor window XChangeProperty(dpy, req->requestor, req->property, multi_type, 32, PropModeReplace, (uchar *) multi, nmulti * 2); } delete [] multi; event.xselection.property = req->property; } // send selection notify to requestor XSendEvent(dpy, req->requestor, False, NoEventMask, &event); DEBUG("QClipboard: SelectionNotify to 0x%lx\n" " property 0x%lx (%s)", req->requestor, event.xselection.property, X11->xdndAtomToString(event.xselection.property).data()); } break; } return true; }
void QClipboard::setMimeData(QMimeData* src, Mode mode) { Atom atom, sentinel_atom; QClipboardData *d; switch (mode) { case Selection: atom = XA_PRIMARY; sentinel_atom = ATOM(_QT_SELECTION_SENTINEL); d = selectionData(); break; case Clipboard: atom = ATOM(CLIPBOARD); sentinel_atom = ATOM(_QT_CLIPBOARD_SENTINEL); d = clipboardData(); break; default: qWarning("QClipboard::setMimeData: unsupported mode '%d'", mode); return; } Display *dpy = X11->display; Window newOwner; if (! src) { // no data, clear clipboard contents newOwner = XNone; d->clear(); } else { setupOwner(); newOwner = owner->internalWinId(); d->setSource(src); d->timestamp = X11->time; } Window prevOwner = XGetSelectionOwner(dpy, atom); // use X11->time, since d->timestamp == CurrentTime when clearing XSetSelectionOwner(dpy, atom, newOwner, X11->time); if (mode == Selection) emitChanged(QClipboard::Selection); else emitChanged(QClipboard::Clipboard); if (XGetSelectionOwner(dpy, atom) != newOwner) { qWarning("QClipboard::setData: Cannot set X11 selection owner for %s", X11->xdndAtomToString(atom).data()); d->clear(); return; } // Signal to other Qt processes that the selection has changed Window owners[2]; owners[0] = newOwner; owners[1] = prevOwner; XChangeProperty(dpy, QApplication::desktop()->screen(0)->internalWinId(), sentinel_atom, XA_WINDOW, 32, PropModeReplace, (unsigned char*)&owners, 2); }
void TNMScatterPlot::process() { if (!_inport.hasData()) return; // Activate the outport as the rendering target _outport.activateTarget(); // Clear the buffer _outport.clearTarget(); // Access the provided data. We have already checked before that it exists, so dereferencing it here is safe const Data& data = *(_inport.getData()); // The set contains all indices of voxels that should be ignored const std::set<unsigned int>& brushingIndices = _brushingIndices.get(); // The set contains all indices of voxels that should be visually selected const std::set<unsigned int>& selectionIndices = _linkingIndices.get(); // The number of points is equal to the number in the original dataset minus the number we are ignoring const size_t dataSize = data.size() - brushingIndices.size(); // There are 2 coordinate components for each point const size_t nCoordinateComponents = dataSize * 2; // The vector containing the position data std::vector<float> positionData; // Make room in the vector positionData.resize(nCoordinateComponents); // The vector containing boolean flags saying for each position if it is selected // OpenGL doesn't support boolean values for the vertex buffer, so we take the next best thing instead std::vector<unsigned char> selectionData(dataSize, 0); // In order to map the value ranges to [-1,1] we need to find the mininum and maximum values float minimumFirstCoordinate = std::numeric_limits<float>::max(); float maximumFirstCoordinate = -std::numeric_limits<float>::max(); float minimumSecondCoordinate = std::numeric_limits<float>::max(); float maximumSecondCoordinate = -std::numeric_limits<float>::max(); // i: index into the data // j: index into the coordinates for (size_t i = 0, j = 0; i < data.size(); ++i) { //// See if the index i is in the vector for brushing if (brushingIndices.find(data[i].voxelIndex) != brushingIndices.end()) // If it is, we ignore it continue; else { // otherwise add it to the position data // _firstAxis.getValue() and _secondAxis.getValue() returns the integer value specified above // to determine which selection was chosen in the GUI const float firstCoordinate = data[i].dataValues[_firstAxis.getValue()]; const float secondCoordinate = data[i].dataValues[_secondAxis.getValue()]; positionData[j] = firstCoordinate; positionData[j+1] = secondCoordinate; j += 2; minimumFirstCoordinate = std::min(minimumFirstCoordinate, firstCoordinate); maximumFirstCoordinate = std::max(maximumFirstCoordinate, firstCoordinate); minimumSecondCoordinate = std::min(minimumSecondCoordinate, secondCoordinate); maximumSecondCoordinate = std::max(maximumSecondCoordinate, secondCoordinate); } } // In a second step, we need to normalize the found data. By now we have looked at each value and found the // min/max values // Normalizing the data values to the range [-1,1] for (size_t i = 0; i < nCoordinateComponents; i+=2) { // First normalize to [0,1] positionData[i] = (positionData[i] - minimumFirstCoordinate) / (maximumFirstCoordinate - minimumFirstCoordinate); positionData[i+1] = (positionData[i+1] - minimumSecondCoordinate) / (maximumSecondCoordinate - minimumSecondCoordinate); // Then shift the normalized values to [-1,1] positionData[i] = (positionData[i] - 0.5f) * 2.f; positionData[i+1] = (positionData[i+1] - 0.5f) * 2.f; } // Set the selection array for all selected indices for (std::set<unsigned int>::const_iterator i = selectionIndices.begin(); i != selectionIndices.end(); ++i) { const unsigned int thisIndex = *i; selectionData[thisIndex] = 1; } // We want to be able to set the point size from the vertex shader glEnable(GL_PROGRAM_POINT_SIZE); // Activate, create, and fill the vbo containing the position data GLuint vbo; glEnableVertexAttribArray(0); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(float), &(positionData[0]), GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); // Activate, create, and fill the vbo containing the selection data GLuint selectionVbo; glEnableVertexAttribArray(1); glGenBuffers(1, &selectionVbo); glBindBuffer(GL_ARRAY_BUFFER, selectionVbo); glBufferData(GL_ARRAY_BUFFER, selectionData.size() * sizeof(unsigned char), &(selectionData[0]), GL_STATIC_DRAW); glVertexAttribIPointer(1, 1, GL_UNSIGNED_BYTE, 0, 0); // Activate the shader required for rendering _shader->activate(); // Draw the points glDrawArrays(GL_POINTS, 0, dataSize); // And be a good citizen and clean up _shader->deactivate(); glDeleteBuffers(1, &vbo); glDisable(GL_PROGRAM_POINT_SIZE); _outport.deactivateTarget(); }