2015-11-09 04:36:37 -06:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "MessageQueue.hpp"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2016-09-14 16:42:50 -05:00
|
|
|
#include <TileDesc.hpp>
|
2016-09-01 15:45:04 -05:00
|
|
|
#include <Log.hpp>
|
|
|
|
|
2015-11-09 04:36:37 -06:00
|
|
|
MessageQueue::~MessageQueue()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
void MessageQueue::put(const Payload& value)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
|
|
|
put_impl(value);
|
|
|
|
lock.unlock();
|
|
|
|
_cv.notify_one();
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
MessageQueue::Payload MessageQueue::get()
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
|
|
|
_cv.wait(lock, [this] { return wait_impl(); });
|
|
|
|
return get_impl();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MessageQueue::clear()
|
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
2015-12-17 11:47:58 -06:00
|
|
|
clear_impl();
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
|
2016-04-27 07:58:33 -05:00
|
|
|
void MessageQueue::remove_if(const std::function<bool(const Payload&)>& pred)
|
2015-12-13 22:36:46 -06:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
|
|
|
std::remove_if(_queue.begin(), _queue.end(), pred);
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
void MessageQueue::put_impl(const Payload& value)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
|
|
|
_queue.push_back(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MessageQueue::wait_impl() const
|
|
|
|
{
|
|
|
|
return _queue.size() > 0;
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
MessageQueue::Payload MessageQueue::get_impl()
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-03-26 21:32:29 -05:00
|
|
|
auto result = _queue.front();
|
2015-11-09 04:36:37 -06:00
|
|
|
_queue.pop_front();
|
2016-03-29 06:36:30 -05:00
|
|
|
return result;
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void MessageQueue::clear_impl()
|
|
|
|
{
|
|
|
|
_queue.clear();
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
void BasicTileQueue::put_impl(const Payload& value)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-03-26 21:32:29 -05:00
|
|
|
const auto msg = std::string(&value[0], value.size());
|
|
|
|
if (msg == "canceltiles")
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
|
|
|
// remove all the existing tiles from the queue
|
|
|
|
_queue.erase(std::remove_if(_queue.begin(), _queue.end(),
|
2016-03-26 21:32:29 -05:00
|
|
|
[](const Payload& v)
|
2015-11-24 02:41:59 -06:00
|
|
|
{
|
2015-11-09 04:36:37 -06:00
|
|
|
// must not remove the tiles with 'id=', they are special, used
|
|
|
|
// eg. for previews etc.
|
2016-03-29 05:42:45 -05:00
|
|
|
const auto tmp = std::string(&v[0], v.size());
|
|
|
|
return (tmp.compare(0, 5, "tile ") == 0) && (tmp.find("id=") == std::string::npos);
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
),
|
|
|
|
_queue.end());
|
|
|
|
|
|
|
|
// put the "canceltiles" in front of other messages
|
|
|
|
_queue.push_front(value);
|
|
|
|
}
|
|
|
|
else
|
2016-03-26 21:32:29 -05:00
|
|
|
{
|
2015-11-09 04:36:37 -06:00
|
|
|
MessageQueue::put_impl(value);
|
2016-03-26 21:32:29 -05:00
|
|
|
}
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
void TileQueue::put_impl(const Payload& value)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-09-14 16:42:50 -05:00
|
|
|
const auto msg = std::string(value.data(), value.size());
|
|
|
|
Log::trace() << "Putting [" << msg << "]" << Log::end;
|
2016-09-01 15:45:04 -05:00
|
|
|
if (!_queue.empty())
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-09-01 15:45:04 -05:00
|
|
|
if (msg.compare(0, 4, "tile") == 0 || msg.compare(0, 10, "tilecombine") == 0)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-09-01 15:45:04 -05:00
|
|
|
const auto newMsg = msg.substr(0, msg.find(" ver"));
|
|
|
|
|
|
|
|
// TODO: implement a real re-ordering here, so that the tiles closest to
|
|
|
|
// the cursor are returned first.
|
|
|
|
// * we will want to put just a general "tile" message to the queue
|
|
|
|
// * add a std::set that handles the tiles
|
|
|
|
// * change the get_impl() to decide which tile is the correct one to
|
|
|
|
// be returned
|
|
|
|
// * we will also need to be informed about the position of the cursor
|
|
|
|
// so that get_impl() returns optimal results
|
|
|
|
//
|
|
|
|
// For now: just don't put duplicates into the queue
|
|
|
|
for (size_t i = 0; i < _queue.size(); ++i)
|
2016-03-26 21:32:29 -05:00
|
|
|
{
|
2016-09-01 15:45:04 -05:00
|
|
|
auto& it = _queue[i];
|
|
|
|
const std::string old(it.data(), it.size());
|
|
|
|
const auto oldMsg = old.substr(0, old.find(" ver"));
|
2016-09-14 16:42:50 -05:00
|
|
|
Log::trace() << "TileQueue #" << i << ": " << oldMsg << Log::end;
|
2016-09-01 15:45:04 -05:00
|
|
|
if (newMsg == oldMsg)
|
|
|
|
{
|
2016-09-14 16:42:50 -05:00
|
|
|
Log::debug() << "Replacing duplicate tile: " << oldMsg << " -> " << newMsg << Log::end;
|
2016-09-01 15:45:04 -05:00
|
|
|
_queue[i] = value;
|
2016-09-14 16:42:50 -05:00
|
|
|
|
|
|
|
if (priority(msg))
|
|
|
|
{
|
|
|
|
// Bump to top.
|
|
|
|
Log::debug() << "And bumping tile to top: " << msg << Log::end;
|
|
|
|
_queue.erase(_queue.begin() + i);
|
|
|
|
_queue.push_front(value);
|
|
|
|
}
|
|
|
|
|
2016-09-01 15:45:04 -05:00
|
|
|
return;
|
|
|
|
}
|
2016-03-26 21:32:29 -05:00
|
|
|
}
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-14 16:42:50 -05:00
|
|
|
if (priority(msg))
|
|
|
|
{
|
|
|
|
Log::debug() << "Priority tile [" << msg << "]" << Log::end;
|
|
|
|
_queue.push_front(value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BasicTileQueue::put_impl(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Bring the underlying tile (if any) to the top.
|
|
|
|
/// There should be only one overlapping tile at most.
|
|
|
|
void TileQueue::reprioritize(const CursorPosition& cursorPosition)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < _queue.size(); ++i)
|
|
|
|
{
|
|
|
|
auto& it = _queue[i];
|
|
|
|
const std::string msg(it.data(), it.size());
|
2016-09-14 17:18:08 -05:00
|
|
|
if (msg.compare(0, 5, "tile ") != 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-09-14 16:42:50 -05:00
|
|
|
auto tile = TileDesc::parse(msg); //FIXME: Expensive, avoid.
|
|
|
|
|
|
|
|
if (tile.intersectsWithRect(cursorPosition.X, cursorPosition.Y, cursorPosition.Width, cursorPosition.Height))
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
{
|
|
|
|
// Bump to top.
|
|
|
|
Log::trace() << "Bumping tile to top: " << msg << Log::end;
|
|
|
|
const Payload payload = it;
|
|
|
|
_queue.erase(_queue.begin() + i);
|
|
|
|
_queue.push_front(payload);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TileQueue::priority(const std::string& tileMsg)
|
|
|
|
{
|
2016-09-14 17:18:08 -05:00
|
|
|
if (tileMsg.compare(0, 5, "tile ") != 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-14 16:42:50 -05:00
|
|
|
auto tile = TileDesc::parse(tileMsg); //FIXME: Expensive, avoid.
|
|
|
|
|
|
|
|
for (auto& pair : _cursorPositions)
|
|
|
|
{
|
|
|
|
if (tile.intersectsWithRect(pair.second.X, pair.second.Y, pair.second.Width, pair.second.Height))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|