mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Fix possible crash in CalendarBox.
If month change notification was posted async there was a possibility to get a mousePressEvent() with already new Context field values, but with old _selected value. Those two could be inconsistent leading to an assert violation in (_selected + _context->daysShift() >= 0).
This commit is contained in:
parent
80bb6b65a7
commit
de8de84a33
1 changed files with 39 additions and 17 deletions
|
@ -117,11 +117,6 @@ void CalendarBox::Context::showMonth(QDate month) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalendarBox::Context::applyMonth(const QDate &month, bool forced) {
|
void CalendarBox::Context::applyMonth(const QDate &month, bool forced) {
|
||||||
if (forced) {
|
|
||||||
_month.setForced(month);
|
|
||||||
} else {
|
|
||||||
_month.set(month);
|
|
||||||
}
|
|
||||||
_daysCount = month.daysInMonth();
|
_daysCount = month.daysInMonth();
|
||||||
_daysShift = daysShiftForMonth(month);
|
_daysShift = daysShiftForMonth(month);
|
||||||
_rowsCount = rowsCountForMonth(month);
|
_rowsCount = rowsCountForMonth(month);
|
||||||
|
@ -130,6 +125,11 @@ void CalendarBox::Context::applyMonth(const QDate &month, bool forced) {
|
||||||
_highlightedIndex = month.daysTo(_highlighted);
|
_highlightedIndex = month.daysTo(_highlighted);
|
||||||
_minDayIndex = _min.isNull() ? INT_MIN : month.daysTo(_min);
|
_minDayIndex = _min.isNull() ? INT_MIN : month.daysTo(_min);
|
||||||
_maxDayIndex = _max.isNull() ? INT_MAX : month.daysTo(_max);
|
_maxDayIndex = _max.isNull() ? INT_MAX : month.daysTo(_max);
|
||||||
|
if (forced) {
|
||||||
|
_month.setForced(month, true);
|
||||||
|
} else {
|
||||||
|
_month.set(month, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalendarBox::Context::skipMonth(int skip) {
|
void CalendarBox::Context::skipMonth(int skip) {
|
||||||
|
@ -219,6 +219,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void monthChanged(QDate month);
|
void monthChanged(QDate month);
|
||||||
|
void setSelected(int selected);
|
||||||
void setPressed(int pressed);
|
void setPressed(int pressed);
|
||||||
|
|
||||||
int rowsLeft() const;
|
int rowsLeft() const;
|
||||||
|
@ -239,16 +240,21 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CalendarBox::Inner::Inner(QWidget *parent, Context *context) : TWidget(parent)
|
CalendarBox::Inner::Inner(QWidget *parent, Context *context)
|
||||||
|
: TWidget(parent)
|
||||||
, _context(context) {
|
, _context(context) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
subscribe(context->month(), [this](QDate month) { monthChanged(month); });
|
subscribe(context->month(), [this](QDate month) {
|
||||||
|
monthChanged(month);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalendarBox::Inner::monthChanged(QDate month) {
|
void CalendarBox::Inner::monthChanged(QDate month) {
|
||||||
|
setSelected(kEmptySelection);
|
||||||
_ripples.clear();
|
_ripples.clear();
|
||||||
resizeToCurrent();
|
resizeToCurrent();
|
||||||
update();
|
update();
|
||||||
|
sendSynteticMouseEvent(this, QEvent::MouseMove, Qt::NoButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalendarBox::Inner::resizeToCurrent() {
|
void CalendarBox::Inner::resizeToCurrent() {
|
||||||
|
@ -343,19 +349,33 @@ void CalendarBox::Inner::paintRows(Painter &p, QRect clip) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalendarBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
void CalendarBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||||
auto point = e->pos();
|
const auto size = st::calendarCellSize;
|
||||||
auto row = floorclamp(point.y() - rowsTop(), st::calendarCellSize.height(), 0, _context->rowsCount());
|
const auto point = e->pos();
|
||||||
auto col = floorclamp(point.x() - rowsLeft(), st::calendarCellSize.width(), 0, kDaysInWeek);
|
const auto inner = QRect(
|
||||||
auto index = row * kDaysInWeek + col - _context->daysShift();
|
rowsLeft(),
|
||||||
if (_context->isEnabled(index)) {
|
rowsTop(),
|
||||||
_selected = index;
|
kDaysInWeek * size.width(),
|
||||||
setCursor(style::cur_pointer);
|
_context->rowsCount() * size.height());
|
||||||
|
if (inner.contains(point)) {
|
||||||
|
const auto row = (point.y() - rowsTop()) / size.height();
|
||||||
|
const auto col = (point.x() - rowsLeft()) / size.width();
|
||||||
|
const auto index = row * kDaysInWeek + col - _context->daysShift();
|
||||||
|
setSelected(index);
|
||||||
} else {
|
} else {
|
||||||
_selected = kEmptySelection;
|
setSelected(kEmptySelection);
|
||||||
setCursor(style::cur_default);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CalendarBox::Inner::setSelected(int selected) {
|
||||||
|
if (selected != kEmptySelection && !_context->isEnabled(selected)) {
|
||||||
|
selected = kEmptySelection;
|
||||||
|
}
|
||||||
|
_selected = selected;
|
||||||
|
setCursor((_selected == kEmptySelection)
|
||||||
|
? style::cur_default
|
||||||
|
: style::cur_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
void CalendarBox::Inner::mousePressEvent(QMouseEvent *e) {
|
void CalendarBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||||
setPressed(_selected);
|
setPressed(_selected);
|
||||||
if (_selected != kEmptySelection) {
|
if (_selected != kEmptySelection) {
|
||||||
|
@ -400,7 +420,9 @@ CalendarBox::Inner::~Inner() = default;
|
||||||
|
|
||||||
class CalendarBox::Title : public TWidget, private base::Subscriber {
|
class CalendarBox::Title : public TWidget, private base::Subscriber {
|
||||||
public:
|
public:
|
||||||
Title(QWidget *parent, Context *context) : TWidget(parent), _context(context) {
|
Title(QWidget *parent, Context *context)
|
||||||
|
: TWidget(parent)
|
||||||
|
, _context(context) {
|
||||||
subscribe(_context->month(), [this](QDate date) { monthChanged(date); });
|
subscribe(_context->month(), [this](QDate date) { monthChanged(date); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue