mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
fixed text selection
This commit is contained in:
parent
1133b33318
commit
a190eda075
20 changed files with 278 additions and 1052 deletions
|
@ -258,14 +258,6 @@ win32 {
|
||||||
-ldwmapi \
|
-ldwmapi \
|
||||||
-lgdi32
|
-lgdi32
|
||||||
|
|
||||||
# SOURCES += platform/borderless/qwinwidget.cpp \
|
|
||||||
# platform/borderless/winnativewindow.cpp \
|
|
||||||
# platform/borderless/widget.cpp
|
|
||||||
|
|
||||||
# HEADERS += platform/borderless/qwinwidget.h \
|
|
||||||
# platform/borderless/winnativewindow.h \
|
|
||||||
# platform/borderless/widget.h
|
|
||||||
|
|
||||||
DEFINES += "USEWINSDK"
|
DEFINES += "USEWINSDK"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection
|
||||||
this->bufferValid = false;
|
this->bufferValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->bufferValid) {
|
if (!this->bufferValid || !selection.isEmpty()) {
|
||||||
this->updateBuffer(pixmap, messageIndex, selection);
|
this->updateBuffer(pixmap, messageIndex, selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ int MessageLayoutContainer::getHeight() const
|
||||||
void MessageLayoutContainer::clear()
|
void MessageLayoutContainer::clear()
|
||||||
{
|
{
|
||||||
this->elements.clear();
|
this->elements.clear();
|
||||||
|
this->lines.clear();
|
||||||
|
|
||||||
this->height = 0;
|
this->height = 0;
|
||||||
this->line = 0;
|
this->line = 0;
|
||||||
|
@ -36,6 +37,7 @@ void MessageLayoutContainer::clear()
|
||||||
this->currentY = 0;
|
this->currentY = 0;
|
||||||
this->lineStart = 0;
|
this->lineStart = 0;
|
||||||
this->lineHeight = 0;
|
this->lineHeight = 0;
|
||||||
|
this->charIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageLayoutContainer::addElement(MessageLayoutElement *element)
|
void MessageLayoutContainer::addElement(MessageLayoutElement *element)
|
||||||
|
@ -106,7 +108,16 @@ void MessageLayoutContainer::breakLine()
|
||||||
element->getRect().y() + this->lineHeight + yExtra));
|
element->getRect().y() + this->lineHeight + yExtra));
|
||||||
}
|
}
|
||||||
|
|
||||||
this->lines.push_back({(int)lineStart, QRect(0, this->currentY, this->width, lineHeight)});
|
if (this->lines.size() != 0) {
|
||||||
|
this->lines.back().endIndex = this->lineStart;
|
||||||
|
this->lines.back().endCharIndex = this->charIndex;
|
||||||
|
}
|
||||||
|
this->lines.push_back({(int)lineStart, 0, this->charIndex, 0,
|
||||||
|
QRect(-100000, this->currentY, 200000, lineHeight)});
|
||||||
|
|
||||||
|
for (int i = this->lineStart; i < this->elements.size(); i++) {
|
||||||
|
this->charIndex += this->elements[i]->getSelectionIndexCount();
|
||||||
|
}
|
||||||
|
|
||||||
this->lineStart = this->elements.size();
|
this->lineStart = this->elements.size();
|
||||||
this->currentX = 0;
|
this->currentX = 0;
|
||||||
|
@ -132,8 +143,10 @@ void MessageLayoutContainer::finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->lines.size() != 0) {
|
if (this->lines.size() != 0) {
|
||||||
this->lines[0].rect.setTop(0);
|
this->lines[0].rect.setTop(-100000);
|
||||||
this->lines.back().rect.setBottom(this->height);
|
this->lines.back().rect.setBottom(100000);
|
||||||
|
this->lines.back().endIndex = this->elements.size();
|
||||||
|
this->lines.back().endCharIndex = this->charIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +179,166 @@ void MessageLayoutContainer::paintAnimatedElements(QPainter &painter, int yOffse
|
||||||
void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex,
|
void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex,
|
||||||
Selection &selection)
|
Selection &selection)
|
||||||
{
|
{
|
||||||
|
// don't draw anything
|
||||||
|
if (selection.min.messageIndex > messageIndex || selection.max.messageIndex < messageIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fully selected
|
||||||
|
if (selection.min.messageIndex < messageIndex && selection.max.messageIndex > messageIndex) {
|
||||||
|
for (Line &line : this->lines) {
|
||||||
|
QRect rect = line.rect;
|
||||||
|
|
||||||
|
rect.setTop(std::max(0, rect.top()));
|
||||||
|
rect.setBottom(std::min(this->height, rect.bottom()));
|
||||||
|
rect.setLeft(this->elements[line.startIndex]->getRect().left());
|
||||||
|
rect.setRight(this->elements[line.endIndex - 1]->getRect().right());
|
||||||
|
|
||||||
|
painter.fillRect(rect, QColor(255, 255, 0, 127));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineIndex = 0;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
// start in this message
|
||||||
|
if (selection.min.messageIndex == messageIndex) {
|
||||||
|
for (; lineIndex < this->lines.size(); lineIndex++) {
|
||||||
|
Line &line = this->lines[lineIndex];
|
||||||
|
index = line.startCharIndex;
|
||||||
|
|
||||||
|
bool returnAfter = false;
|
||||||
|
bool breakAfter = false;
|
||||||
|
int x = this->elements[line.startIndex]->getRect().left();
|
||||||
|
int r = this->elements[line.endIndex - 1]->getRect().right();
|
||||||
|
|
||||||
|
if (line.endCharIndex < selection.min.charIndex) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = line.startIndex; i < line.endIndex; i++) {
|
||||||
|
int c = this->elements[i]->getSelectionIndexCount();
|
||||||
|
|
||||||
|
if (index + c > selection.min.charIndex) {
|
||||||
|
x = this->elements[i]->getXFromIndex(selection.min.charIndex - index);
|
||||||
|
|
||||||
|
// ends in same line
|
||||||
|
if (selection.max.messageIndex == messageIndex &&
|
||||||
|
line.endCharIndex > /*=*/selection.max.charIndex) //
|
||||||
|
{
|
||||||
|
returnAfter = true;
|
||||||
|
index = line.startCharIndex;
|
||||||
|
for (int i = line.startIndex; i < line.endIndex; i++) {
|
||||||
|
int c = this->elements[i]->getSelectionIndexCount();
|
||||||
|
|
||||||
|
if (index + c > selection.max.charIndex) {
|
||||||
|
r = this->elements[i]->getXFromIndex(selection.max.charIndex -
|
||||||
|
index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ends in same line end
|
||||||
|
|
||||||
|
if (selection.max.messageIndex != messageIndex) {
|
||||||
|
int lineIndex2 = lineIndex + 1;
|
||||||
|
for (; lineIndex2 < this->lines.size(); lineIndex2++) {
|
||||||
|
Line &line = this->lines[lineIndex2];
|
||||||
|
QRect rect = line.rect;
|
||||||
|
|
||||||
|
rect.setTop(std::max(0, rect.top()));
|
||||||
|
rect.setBottom(std::min(this->height, rect.bottom()));
|
||||||
|
rect.setLeft(this->elements[line.startIndex]->getRect().left());
|
||||||
|
rect.setRight(this->elements[line.endIndex - 1]->getRect().right());
|
||||||
|
|
||||||
|
painter.fillRect(rect, QColor(255, 255, 0, 127));
|
||||||
|
}
|
||||||
|
returnAfter = true;
|
||||||
|
} else {
|
||||||
|
lineIndex++;
|
||||||
|
breakAfter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect rect = line.rect;
|
||||||
|
|
||||||
|
rect.setTop(std::max(0, rect.top()));
|
||||||
|
rect.setBottom(std::min(this->height, rect.bottom()));
|
||||||
|
rect.setLeft(x);
|
||||||
|
rect.setRight(r);
|
||||||
|
|
||||||
|
painter.fillRect(rect, QColor(255, 255, 0, 127));
|
||||||
|
|
||||||
|
if (returnAfter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (breakAfter) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start in this message
|
||||||
|
for (; lineIndex < this->lines.size(); lineIndex++) {
|
||||||
|
Line &line = this->lines[lineIndex];
|
||||||
|
index = line.startCharIndex;
|
||||||
|
bool breakAfter = false;
|
||||||
|
|
||||||
|
// just draw the garbage
|
||||||
|
if (line.endCharIndex < /*=*/selection.max.charIndex) {
|
||||||
|
QRect rect = line.rect;
|
||||||
|
|
||||||
|
rect.setTop(std::max(0, rect.top()));
|
||||||
|
rect.setBottom(std::min(this->height, rect.bottom()));
|
||||||
|
rect.setLeft(this->elements[line.startIndex]->getRect().left());
|
||||||
|
rect.setRight(this->elements[line.endIndex - 1]->getRect().right());
|
||||||
|
|
||||||
|
painter.fillRect(rect, QColor(255, 255, 0, 127));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = this->elements[line.endIndex - 1]->getRect().right();
|
||||||
|
|
||||||
|
for (int i = line.startIndex; i < line.endIndex; i++) {
|
||||||
|
int c = this->elements[i]->getSelectionIndexCount();
|
||||||
|
|
||||||
|
if (index + c > selection.max.charIndex) {
|
||||||
|
r = this->elements[i]->getXFromIndex(selection.max.charIndex - index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect rect = line.rect;
|
||||||
|
|
||||||
|
rect.setTop(std::max(0, rect.top()));
|
||||||
|
rect.setBottom(std::min(this->height, rect.bottom()));
|
||||||
|
rect.setLeft(this->elements[line.startIndex]->getRect().left());
|
||||||
|
rect.setRight(r);
|
||||||
|
|
||||||
|
painter.fillRect(rect, QColor(255, 255, 0, 127));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLayoutContainer::_paintLine(QPainter &painter, Line &line, int x, int y)
|
||||||
|
{
|
||||||
|
QRect rect = line.rect;
|
||||||
|
|
||||||
|
rect.setTop(std::max(0, rect.top()));
|
||||||
|
rect.setBottom(std::min(this->height, rect.bottom()));
|
||||||
|
rect.setLeft(this->elements[line.startIndex]->getRect().left());
|
||||||
|
rect.setRight(this->elements[line.endIndex - 1]->getRect().right());
|
||||||
|
|
||||||
|
painter.fillRect(rect, QColor(255, 255, 0, 127));
|
||||||
}
|
}
|
||||||
|
|
||||||
// selection
|
// selection
|
||||||
|
@ -183,10 +356,10 @@ int MessageLayoutContainer::getSelectionIndex(QPoint point)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(line != this->lines.end());
|
int lineStart = line == this->lines.end() ? this->lines.back().startIndex : line->startIndex;
|
||||||
|
if (line != this->lines.end()) {
|
||||||
int lineStart = line->startIndex;
|
line++;
|
||||||
line++;
|
}
|
||||||
int lineEnd = line == this->lines.end() ? this->elements.size() : line->startIndex;
|
int lineEnd = line == this->lines.end() ? this->elements.size() : line->startIndex;
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
@ -204,10 +377,12 @@ int MessageLayoutContainer::getSelectionIndex(QPoint point)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is the word
|
// this is the word
|
||||||
if (point.x() > this->elements[i]->getRect().left()) {
|
if (point.x() < this->elements[i]->getRect().right()) {
|
||||||
index += this->elements[i]->getMouseOverIndex(point);
|
index += this->elements[i]->getMouseOverIndex(point);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index += this->elements[i]->getSelectionIndexCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << index;
|
qDebug() << index;
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
|
|
||||||
|
#include "messages/selection.hpp"
|
||||||
|
|
||||||
class QPainter;
|
class QPainter;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace messages {
|
namespace messages {
|
||||||
class Selection;
|
|
||||||
|
|
||||||
namespace layouts {
|
namespace layouts {
|
||||||
class MessageLayoutElement;
|
class MessageLayoutElement;
|
||||||
|
@ -72,23 +73,28 @@ public:
|
||||||
int getSelectionIndex(QPoint point);
|
int getSelectionIndex(QPoint point);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Line {
|
||||||
|
int startIndex;
|
||||||
|
int endIndex;
|
||||||
|
int startCharIndex;
|
||||||
|
int endCharIndex;
|
||||||
|
QRect rect;
|
||||||
|
};
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
void _addElement(MessageLayoutElement *element);
|
void _addElement(MessageLayoutElement *element);
|
||||||
|
void _paintLine(QPainter &painter, Line &line, int x, int y);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
int line;
|
int line;
|
||||||
int height;
|
int height;
|
||||||
int currentX, currentY;
|
int currentX, currentY;
|
||||||
|
int charIndex = 0;
|
||||||
size_t lineStart = 0;
|
size_t lineStart = 0;
|
||||||
int lineHeight = 0;
|
int lineHeight = 0;
|
||||||
int spaceWidth = 4;
|
int spaceWidth = 4;
|
||||||
std::vector<std::unique_ptr<MessageLayoutElement>> elements;
|
std::vector<std::unique_ptr<MessageLayoutElement>> elements;
|
||||||
|
|
||||||
struct Line {
|
|
||||||
int startIndex;
|
|
||||||
QRect rect;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Line> lines;
|
std::vector<Line> lines;
|
||||||
};
|
};
|
||||||
} // namespace layouts
|
} // namespace layouts
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "messages/layouts/messagelayoutelement.hpp"
|
#include "messages/layouts/messagelayoutelement.hpp"
|
||||||
#include "messages/messageelement.hpp"
|
#include "messages/messageelement.hpp"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
@ -88,6 +89,18 @@ int ImageLayoutElement::getMouseOverIndex(const QPoint &abs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ImageLayoutElement::getXFromIndex(int index)
|
||||||
|
{
|
||||||
|
if (index <= 0) {
|
||||||
|
return this->getRect().left();
|
||||||
|
} else if (index == 1) {
|
||||||
|
// fourtf: remove space width
|
||||||
|
return this->getRect().right();
|
||||||
|
} else {
|
||||||
|
return this->getRect().right();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// TEXT
|
// TEXT
|
||||||
//
|
//
|
||||||
|
@ -127,7 +140,44 @@ void TextLayoutElement::paintAnimated(QPainter &, int)
|
||||||
|
|
||||||
int TextLayoutElement::getMouseOverIndex(const QPoint &abs)
|
int TextLayoutElement::getMouseOverIndex(const QPoint &abs)
|
||||||
{
|
{
|
||||||
return 0;
|
if (abs.x() < this->getRect().left()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFontMetrics &metrics =
|
||||||
|
singletons::FontManager::getInstance().getFontMetrics(this->style, this->scale);
|
||||||
|
|
||||||
|
int x = this->getRect().left();
|
||||||
|
|
||||||
|
for (int i = 0; i < this->text.size(); i++) {
|
||||||
|
int w = metrics.width(this->text[i]);
|
||||||
|
|
||||||
|
if (x + w > abs.x()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
x += w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->getSelectionIndexCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextLayoutElement::getXFromIndex(int index)
|
||||||
|
{
|
||||||
|
QFontMetrics &metrics =
|
||||||
|
singletons::FontManager::getInstance().getFontMetrics(this->style, this->scale);
|
||||||
|
|
||||||
|
if (index <= 0) {
|
||||||
|
return this->getRect().left();
|
||||||
|
} else if (index < this->text.size()) {
|
||||||
|
int x = 0;
|
||||||
|
for (int i = 0; i < index; i++) {
|
||||||
|
x += metrics.width(this->text[i]);
|
||||||
|
}
|
||||||
|
return x + this->getRect().left();
|
||||||
|
} else {
|
||||||
|
return this->getRect().right();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace layouts
|
} // namespace layouts
|
||||||
} // namespace messages
|
} // namespace messages
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
virtual void paint(QPainter &painter) = 0;
|
virtual void paint(QPainter &painter) = 0;
|
||||||
virtual void paintAnimated(QPainter &painter, int yOffset) = 0;
|
virtual void paintAnimated(QPainter &painter, int yOffset) = 0;
|
||||||
virtual int getMouseOverIndex(const QPoint &abs) = 0;
|
virtual int getMouseOverIndex(const QPoint &abs) = 0;
|
||||||
|
virtual int getXFromIndex(int index) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool trailingSpace = true;
|
bool trailingSpace = true;
|
||||||
|
@ -58,6 +59,7 @@ protected:
|
||||||
virtual void paint(QPainter &painter) override;
|
virtual void paint(QPainter &painter) override;
|
||||||
virtual void paintAnimated(QPainter &painter, int yOffset) override;
|
virtual void paintAnimated(QPainter &painter, int yOffset) override;
|
||||||
virtual int getMouseOverIndex(const QPoint &abs) override;
|
virtual int getMouseOverIndex(const QPoint &abs) override;
|
||||||
|
virtual int getXFromIndex(int index) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Image ℑ
|
Image ℑ
|
||||||
|
@ -76,6 +78,7 @@ protected:
|
||||||
virtual void paint(QPainter &painter) override;
|
virtual void paint(QPainter &painter) override;
|
||||||
virtual void paintAnimated(QPainter &painter, int yOffset) override;
|
virtual void paintAnimated(QPainter &painter, int yOffset) override;
|
||||||
virtual int getMouseOverIndex(const QPoint &abs) override;
|
virtual int getMouseOverIndex(const QPoint &abs) override;
|
||||||
|
virtual int getXFromIndex(int index) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString text;
|
QString text;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <util/emotemap.hpp>
|
#include "util/emotemap.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
class Channel;
|
class Channel;
|
||||||
|
|
|
@ -8,24 +8,36 @@ struct SelectionItem {
|
||||||
|
|
||||||
SelectionItem()
|
SelectionItem()
|
||||||
{
|
{
|
||||||
messageIndex = charIndex = 0;
|
this->messageIndex = 0;
|
||||||
|
this->charIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionItem(int _messageIndex, int _charIndex)
|
SelectionItem(int _messageIndex, int _charIndex)
|
||||||
{
|
{
|
||||||
this->messageIndex = _messageIndex;
|
this->messageIndex = _messageIndex;
|
||||||
|
|
||||||
this->charIndex = _charIndex;
|
this->charIndex = _charIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSmallerThan(const SelectionItem &other) const
|
bool operator<(const SelectionItem &b) const
|
||||||
{
|
{
|
||||||
return this->messageIndex < other.messageIndex ||
|
if (this->messageIndex < b.messageIndex) {
|
||||||
(this->messageIndex == other.messageIndex && this->charIndex < other.charIndex);
|
return true;
|
||||||
|
}
|
||||||
|
if (this->messageIndex == b.messageIndex && this->charIndex < b.charIndex) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool equals(const SelectionItem &other) const
|
bool operator>(const SelectionItem &b) const
|
||||||
{
|
{
|
||||||
return this->messageIndex == other.messageIndex && this->charIndex == other.charIndex;
|
return b.operator<(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const SelectionItem &b) const
|
||||||
|
{
|
||||||
|
return this->messageIndex == b.messageIndex && this->charIndex == b.charIndex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,14 +57,14 @@ struct Selection {
|
||||||
, min(start)
|
, min(start)
|
||||||
, max(end)
|
, max(end)
|
||||||
{
|
{
|
||||||
if (max.isSmallerThan(min)) {
|
if (min > max) {
|
||||||
std::swap(this->min, this->max);
|
std::swap(this->min, this->max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEmpty() const
|
bool isEmpty() const
|
||||||
{
|
{
|
||||||
return this->start.equals(this->end);
|
return this->start == this->end;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSingleMessage() const
|
bool isSingleMessage() const
|
||||||
|
@ -60,5 +72,5 @@ struct Selection {
|
||||||
return this->min.messageIndex == this->max.messageIndex;
|
return this->min.messageIndex == this->max.messageIndex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace messages
|
||||||
}
|
} // namespace chatterino
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2016 Ian Bannerman
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,555 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
|
||||||
** Contact: http://www.qt-project.org/legal
|
|
||||||
**
|
|
||||||
** This file is part of the Qt Solutions component.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:BSD$
|
|
||||||
** You may use this file under the terms of the BSD license as follows:
|
|
||||||
**
|
|
||||||
** "Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are
|
|
||||||
** met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in
|
|
||||||
** the documentation and/or other materials provided with the
|
|
||||||
** distribution.
|
|
||||||
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
|
||||||
** of its contributors may be used to endorse or promote products derived
|
|
||||||
** from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* File is originally from
|
|
||||||
* https://github.com/qtproject/qt-solutions/tree/master/qtwinmigrate/src */
|
|
||||||
/* */
|
|
||||||
/* It has been modified to support borderless window (HTTRANSPARENT) & to remove
|
|
||||||
* pre Qt5 cruft */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
|
|
||||||
#include "QWinWidget.h"
|
|
||||||
|
|
||||||
#include <qt_windows.h>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QFocusEvent>
|
|
||||||
#include <QWindow>
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class QWinWidget qwinwidget.h
|
|
||||||
\brief The QWinWidget class is a Qt widget that can be child of a
|
|
||||||
native Win32 widget.
|
|
||||||
|
|
||||||
The QWinWidget class is the bridge between an existing application
|
|
||||||
user interface developed using native Win32 APIs or toolkits like
|
|
||||||
MFC, and Qt based GUI elements.
|
|
||||||
|
|
||||||
Using QWinWidget as the parent of QDialogs will ensure that
|
|
||||||
modality, placement and stacking works properly throughout the
|
|
||||||
entire application. If the child widget is a top level window that
|
|
||||||
uses the \c WDestructiveClose flag, QWinWidget will destroy itself
|
|
||||||
when the child window closes down.
|
|
||||||
|
|
||||||
Applications moving to Qt can use QWinWidget to add new
|
|
||||||
functionality, and gradually replace the existing interface.
|
|
||||||
*/
|
|
||||||
|
|
||||||
QWinWidget::QWinWidget()
|
|
||||||
: QWidget(nullptr)
|
|
||||||
, m_Layout()
|
|
||||||
, p_Widget(nullptr)
|
|
||||||
, m_ParentNativeWindowHandle(nullptr)
|
|
||||||
, _prevFocus(nullptr)
|
|
||||||
, _reenableParent(false)
|
|
||||||
{
|
|
||||||
// Create a native window and give it geometry values * devicePixelRatio for
|
|
||||||
// HiDPI support
|
|
||||||
p_ParentWinNativeWindow = new WinNativeWindow(
|
|
||||||
1 * window()->devicePixelRatio(), 1 * window()->devicePixelRatio(),
|
|
||||||
1 * window()->devicePixelRatio(), 1 * window()->devicePixelRatio());
|
|
||||||
|
|
||||||
// If you want to set a minimize size for your app, do so here
|
|
||||||
// p_ParentWinNativeWindow->setMinimumSize(1024 *
|
|
||||||
// window()->devicePixelRatio(), 768 * window()->devicePixelRatio());
|
|
||||||
|
|
||||||
// If you want to set a maximum size for your app, do so here
|
|
||||||
// p_ParentWinNativeWindow->setMaximumSize(1024 *
|
|
||||||
// window()->devicePixelRatio(), 768 * window()->devicePixelRatio());
|
|
||||||
|
|
||||||
// Save the native window handle for shorthand use
|
|
||||||
m_ParentNativeWindowHandle = p_ParentWinNativeWindow->hWnd;
|
|
||||||
Q_ASSERT(m_ParentNativeWindowHandle);
|
|
||||||
|
|
||||||
// Create the child window & embed it into the native one
|
|
||||||
if (m_ParentNativeWindowHandle) {
|
|
||||||
SetWindowLong((HWND)winId(), GWL_STYLE,
|
|
||||||
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
|
|
||||||
QWindow *window = windowHandle();
|
|
||||||
window->setProperty("_q_embedded_native_parent_handle",
|
|
||||||
(WId)m_ParentNativeWindowHandle);
|
|
||||||
|
|
||||||
SetParent((HWND)winId(), m_ParentNativeWindowHandle);
|
|
||||||
window->setFlags(Qt::FramelessWindowHint);
|
|
||||||
QEvent e(QEvent::EmbeddingControl);
|
|
||||||
QApplication::sendEvent(this, &e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass along our window handle & widget pointer to WinFramelessWidget so we
|
|
||||||
// can exchange messages
|
|
||||||
p_ParentWinNativeWindow->childWindow = (HWND)winId();
|
|
||||||
p_ParentWinNativeWindow->childWidget = this;
|
|
||||||
|
|
||||||
// Clear margins & spacing & add the layout to prepare for the MainAppWidget
|
|
||||||
setContentsMargins(0, 0, 0, 0);
|
|
||||||
setLayout(&m_Layout);
|
|
||||||
m_Layout.setContentsMargins(0, 0, 0, 0);
|
|
||||||
m_Layout.setSpacing(0);
|
|
||||||
|
|
||||||
// Create the true app widget
|
|
||||||
// p_Widget = new Widget(this);
|
|
||||||
// m_Layout.addWidget(p_Widget);
|
|
||||||
// p_Widget->setParent(this, Qt::Widget);
|
|
||||||
// p_Widget->setVisible(true);
|
|
||||||
|
|
||||||
// Update the BORDERWIDTH value if needed for HiDPI displays
|
|
||||||
BORDERWIDTH = BORDERWIDTH * window()->devicePixelRatio();
|
|
||||||
|
|
||||||
// Update the TOOLBARHEIGHT value to match the height of toolBar * if
|
|
||||||
// needed, the HiDPI display
|
|
||||||
// if (p_Widget->toolBar) {
|
|
||||||
// TOOLBARHEIGHT =
|
|
||||||
// p_Widget->toolBar->height() * window()->devicePixelRatio();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// You need to keep the native window in sync with the Qt window & children,
|
|
||||||
// so wire min/max/close buttons to
|
|
||||||
// slots inside of QWinWidget. QWinWidget can then talk with the native
|
|
||||||
// window as needed
|
|
||||||
// if (p_Widget->minimizeButton) {
|
|
||||||
// connect(p_Widget->minimizeButton, &QPushButton::clicked, this,
|
|
||||||
// &QWinWidget::onMinimizeButtonClicked);
|
|
||||||
// }
|
|
||||||
// if (p_Widget->maximizeButton) {
|
|
||||||
// connect(p_Widget->maximizeButton, &QPushButton::clicked, this,
|
|
||||||
// &QWinWidget::onMaximizeButtonClicked);
|
|
||||||
// }
|
|
||||||
// if (p_Widget->closeButton) {
|
|
||||||
// connect(p_Widget->closeButton, &QPushButton::clicked, this,
|
|
||||||
// &QWinWidget::onCloseButtonClicked);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Send the parent native window a WM_SIZE message to update the widget size
|
|
||||||
SendMessage(m_ParentNativeWindowHandle, WM_SIZE, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Destroys this object, freeing all allocated resources.
|
|
||||||
*/
|
|
||||||
QWinWidget::~QWinWidget()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the handle of the native Win32 parent window.
|
|
||||||
*/
|
|
||||||
HWND
|
|
||||||
QWinWidget::getParentWindow() const
|
|
||||||
{
|
|
||||||
return m_ParentNativeWindowHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\reimp
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
QWinWidget::childEvent(QChildEvent *e)
|
|
||||||
{
|
|
||||||
QObject *obj = e->child();
|
|
||||||
if (obj->isWidgetType()) {
|
|
||||||
if (e->added()) {
|
|
||||||
if (obj->isWidgetType()) {
|
|
||||||
obj->installEventFilter(this);
|
|
||||||
}
|
|
||||||
} else if (e->removed() && _reenableParent) {
|
|
||||||
_reenableParent = false;
|
|
||||||
EnableWindow(m_ParentNativeWindowHandle, true);
|
|
||||||
obj->removeEventFilter(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QWidget::childEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \internal */
|
|
||||||
void
|
|
||||||
QWinWidget::saveFocus()
|
|
||||||
{
|
|
||||||
if (!_prevFocus)
|
|
||||||
_prevFocus = ::GetFocus();
|
|
||||||
if (!_prevFocus)
|
|
||||||
_prevFocus = getParentWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Shows this widget. Overrides QWidget::show().
|
|
||||||
|
|
||||||
\sa showCentered()
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
QWinWidget::show()
|
|
||||||
{
|
|
||||||
ShowWindow(m_ParentNativeWindowHandle, true);
|
|
||||||
saveFocus();
|
|
||||||
QWidget::show();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Centers this widget over the native parent window. Use this
|
|
||||||
function to have Qt toplevel windows (i.e. dialogs) positioned
|
|
||||||
correctly over their native parent windows.
|
|
||||||
|
|
||||||
\code
|
|
||||||
QWinWidget qwin(hParent);
|
|
||||||
qwin.center();
|
|
||||||
|
|
||||||
QMessageBox::information(&qwin, "Caption", "Information Text");
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
This will center the message box over the client area of hParent.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
QWinWidget::center()
|
|
||||||
{
|
|
||||||
const QWidget *child = findChild<QWidget *>();
|
|
||||||
if (child && !child->isWindow()) {
|
|
||||||
qWarning("QWinWidget::center: Call this function only for QWinWidgets "
|
|
||||||
"with toplevel children");
|
|
||||||
}
|
|
||||||
RECT r;
|
|
||||||
GetWindowRect(m_ParentNativeWindowHandle, &r);
|
|
||||||
setGeometry((r.right - r.left) / 2 + r.left, (r.bottom - r.top) / 2 + r.top,
|
|
||||||
0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\obsolete
|
|
||||||
|
|
||||||
Call center() instead.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
QWinWidget::showCentered()
|
|
||||||
{
|
|
||||||
center();
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
QWinWidget::setGeometry(int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
p_ParentWinNativeWindow->setGeometry(
|
|
||||||
x * window()->devicePixelRatio(), y * window()->devicePixelRatio(),
|
|
||||||
w * window()->devicePixelRatio(), h * window()->devicePixelRatio());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sets the focus to the window that had the focus before this widget
|
|
||||||
was shown, or if there was no previous window, sets the focus to
|
|
||||||
the parent window.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
QWinWidget::resetFocus()
|
|
||||||
{
|
|
||||||
if (_prevFocus)
|
|
||||||
::SetFocus(_prevFocus);
|
|
||||||
else
|
|
||||||
::SetFocus(getParentWindow());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the parent native window to minimize
|
|
||||||
void
|
|
||||||
QWinWidget::onMinimizeButtonClicked()
|
|
||||||
{
|
|
||||||
SendMessage(m_ParentNativeWindowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the parent native window to maximize or restore as appropriate
|
|
||||||
void
|
|
||||||
QWinWidget::onMaximizeButtonClicked()
|
|
||||||
{
|
|
||||||
if (p_Widget->maximizeButton->isChecked()) {
|
|
||||||
SendMessage(m_ParentNativeWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
|
|
||||||
} else {
|
|
||||||
SendMessage(m_ParentNativeWindowHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
QWinWidget::onCloseButtonClicked()
|
|
||||||
{
|
|
||||||
if (true /* put your check for it if it safe to close your app here */) // eg, does the user need to save a document
|
|
||||||
{
|
|
||||||
// Safe to close, so hide the parent window
|
|
||||||
ShowWindow(m_ParentNativeWindowHandle, false);
|
|
||||||
|
|
||||||
// And then quit
|
|
||||||
QApplication::quit();
|
|
||||||
} else {
|
|
||||||
// Do nothing, and thus, don't actually close the window
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
QWinWidget::nativeEvent(const QByteArray &, void *message, long *result)
|
|
||||||
{
|
|
||||||
MSG *msg = (MSG *)message;
|
|
||||||
|
|
||||||
if (msg->message == WM_SETFOCUS) {
|
|
||||||
Qt::FocusReason reason;
|
|
||||||
if (::GetKeyState(VK_LBUTTON) < 0 || ::GetKeyState(VK_RBUTTON) < 0)
|
|
||||||
reason = Qt::MouseFocusReason;
|
|
||||||
else if (::GetKeyState(VK_SHIFT) < 0)
|
|
||||||
reason = Qt::BacktabFocusReason;
|
|
||||||
else
|
|
||||||
reason = Qt::TabFocusReason;
|
|
||||||
QFocusEvent e(QEvent::FocusIn, reason);
|
|
||||||
QApplication::sendEvent(this, &e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only close if safeToClose clears()
|
|
||||||
if (msg->message == WM_CLOSE) {
|
|
||||||
if (true /* put your check for it if it safe to close your app here */) // eg, does the user need to save a document
|
|
||||||
{
|
|
||||||
// Safe to close, so hide the parent window
|
|
||||||
ShowWindow(m_ParentNativeWindowHandle, false);
|
|
||||||
|
|
||||||
// And then quit
|
|
||||||
QApplication::quit();
|
|
||||||
} else {
|
|
||||||
*result = 0; // Set the message to 0 to ignore it, and thus, don't
|
|
||||||
// actually close
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Double check WM_SIZE messages to see if the parent native window is
|
|
||||||
// maximized
|
|
||||||
if (msg->message == WM_SIZE) {
|
|
||||||
if (p_Widget && p_Widget->maximizeButton) {
|
|
||||||
// Get the window state
|
|
||||||
WINDOWPLACEMENT wp;
|
|
||||||
GetWindowPlacement(m_ParentNativeWindowHandle, &wp);
|
|
||||||
|
|
||||||
// If we're maximized,
|
|
||||||
if (wp.showCmd == SW_MAXIMIZE) {
|
|
||||||
// Maximize button should show as Restore
|
|
||||||
p_Widget->maximizeButton->setChecked(true);
|
|
||||||
} else {
|
|
||||||
// Maximize button should show as Maximize
|
|
||||||
p_Widget->maximizeButton->setChecked(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass NCHITTESTS on the window edges as determined by BORDERWIDTH &
|
|
||||||
// TOOLBARHEIGHT through to the parent native window
|
|
||||||
if (msg->message == WM_NCHITTEST) {
|
|
||||||
RECT WindowRect;
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
GetWindowRect(msg->hwnd, &WindowRect);
|
|
||||||
x = GET_X_LPARAM(msg->lParam) - WindowRect.left;
|
|
||||||
y = GET_Y_LPARAM(msg->lParam) - WindowRect.top;
|
|
||||||
|
|
||||||
if (x >= BORDERWIDTH &&
|
|
||||||
x <= WindowRect.right - WindowRect.left - BORDERWIDTH &&
|
|
||||||
y >= BORDERWIDTH && y <= TOOLBARHEIGHT) {
|
|
||||||
if (false) { // if (p_Widget->toolBar) {
|
|
||||||
// If the mouse is over top of the toolbar area BUT is actually
|
|
||||||
// positioned over a child widget of the toolbar,
|
|
||||||
// Then we don't want to enable dragging. This allows for
|
|
||||||
// buttons in the toolbar, eg, a Maximize button, to keep the
|
|
||||||
// mouse interaction
|
|
||||||
if (QApplication::widgetAt(QCursor::pos()) != p_Widget->toolBar)
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// The mouse is over the toolbar area & is NOT over a child of
|
|
||||||
// the toolbar, so pass this message
|
|
||||||
// through to the native window for HTCAPTION dragging
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (x < BORDERWIDTH && y < BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
} else if (x > WindowRect.right - WindowRect.left - BORDERWIDTH &&
|
|
||||||
y < BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
} else if (x > WindowRect.right - WindowRect.left - BORDERWIDTH &&
|
|
||||||
y > WindowRect.bottom - WindowRect.top - BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
} else if (x < BORDERWIDTH &&
|
|
||||||
y > WindowRect.bottom - WindowRect.top - BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
} else if (x < BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
} else if (y < BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
} else if (x > WindowRect.right - WindowRect.left - BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
} else if (y > WindowRect.bottom - WindowRect.top - BORDERWIDTH) {
|
|
||||||
*result = HTTRANSPARENT;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\reimp
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
QWinWidget::eventFilter(QObject *o, QEvent *e)
|
|
||||||
{
|
|
||||||
QWidget *w = (QWidget *)o;
|
|
||||||
|
|
||||||
switch (e->type()) {
|
|
||||||
case QEvent::WindowDeactivate:
|
|
||||||
if (w->isModal() && w->isHidden())
|
|
||||||
BringWindowToTop(m_ParentNativeWindowHandle);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::Hide:
|
|
||||||
if (_reenableParent) {
|
|
||||||
EnableWindow(m_ParentNativeWindowHandle, true);
|
|
||||||
_reenableParent = false;
|
|
||||||
}
|
|
||||||
resetFocus();
|
|
||||||
|
|
||||||
if (w->testAttribute(Qt::WA_DeleteOnClose) && w->isWindow())
|
|
||||||
deleteLater();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::Show:
|
|
||||||
if (w->isWindow()) {
|
|
||||||
saveFocus();
|
|
||||||
hide();
|
|
||||||
if (w->isModal() && !_reenableParent) {
|
|
||||||
EnableWindow(m_ParentNativeWindowHandle, false);
|
|
||||||
_reenableParent = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QEvent::Close: {
|
|
||||||
::SetActiveWindow(m_ParentNativeWindowHandle);
|
|
||||||
if (w->testAttribute(Qt::WA_DeleteOnClose))
|
|
||||||
deleteLater();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QWidget::eventFilter(o, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \reimp
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
QWinWidget::focusInEvent(QFocusEvent *e)
|
|
||||||
{
|
|
||||||
QWidget *candidate = this;
|
|
||||||
|
|
||||||
switch (e->reason()) {
|
|
||||||
case Qt::TabFocusReason:
|
|
||||||
case Qt::BacktabFocusReason:
|
|
||||||
while (!(candidate->focusPolicy() & Qt::TabFocus)) {
|
|
||||||
candidate = candidate->nextInFocusChain();
|
|
||||||
if (candidate == this) {
|
|
||||||
candidate = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (candidate) {
|
|
||||||
candidate->setFocus(e->reason());
|
|
||||||
if (e->reason() == Qt::BacktabFocusReason ||
|
|
||||||
e->reason() == Qt::TabFocusReason) {
|
|
||||||
candidate->setAttribute(Qt::WA_KeyboardFocusChange);
|
|
||||||
candidate->window()->setAttribute(
|
|
||||||
Qt::WA_KeyboardFocusChange);
|
|
||||||
}
|
|
||||||
if (e->reason() == Qt::BacktabFocusReason)
|
|
||||||
QWidget::focusNextPrevChild(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \reimp
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
QWinWidget::focusNextPrevChild(bool next)
|
|
||||||
{
|
|
||||||
QWidget *curFocus = focusWidget();
|
|
||||||
if (!next) {
|
|
||||||
if (!curFocus->isWindow()) {
|
|
||||||
QWidget *nextFocus = curFocus->nextInFocusChain();
|
|
||||||
QWidget *prevFocus = 0;
|
|
||||||
QWidget *topLevel = 0;
|
|
||||||
while (nextFocus != curFocus) {
|
|
||||||
if (nextFocus->focusPolicy() & Qt::TabFocus) {
|
|
||||||
prevFocus = nextFocus;
|
|
||||||
topLevel = 0;
|
|
||||||
}
|
|
||||||
nextFocus = nextFocus->nextInFocusChain();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!topLevel) {
|
|
||||||
return QWidget::focusNextPrevChild(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QWidget *nextFocus = curFocus;
|
|
||||||
while (1 && nextFocus != 0) {
|
|
||||||
nextFocus = nextFocus->nextInFocusChain();
|
|
||||||
if (nextFocus->focusPolicy() & Qt::TabFocus) {
|
|
||||||
return QWidget::focusNextPrevChild(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::SetFocus(m_ParentNativeWindowHandle);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
|
||||||
** Contact: http://www.qt-project.org/legal
|
|
||||||
**
|
|
||||||
** This file is part of the Qt Solutions component.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:BSD$
|
|
||||||
** You may use this file under the terms of the BSD license as follows:
|
|
||||||
**
|
|
||||||
** "Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are
|
|
||||||
** met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in
|
|
||||||
** the documentation and/or other materials provided with the
|
|
||||||
** distribution.
|
|
||||||
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
|
||||||
** of its contributors may be used to endorse or promote products derived
|
|
||||||
** from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* */
|
|
||||||
/* File is originally from
|
|
||||||
* https://github.com/qtproject/qt-solutions/tree/master/qtwinmigrate/src */
|
|
||||||
/* */
|
|
||||||
/* It has been modified to support borderless window (HTTTRANSPARENT) & to
|
|
||||||
* remove pre Qt5 cruft */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
|
|
||||||
// Declaration of the QWinWidget classes
|
|
||||||
|
|
||||||
#ifndef QWINWIDGET_H
|
|
||||||
#define QWINWIDGET_H
|
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include "WinNativeWindow.h"
|
|
||||||
#include "widget.h"
|
|
||||||
|
|
||||||
class QWinWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QWinWidget();
|
|
||||||
~QWinWidget();
|
|
||||||
|
|
||||||
void show();
|
|
||||||
void center();
|
|
||||||
void showCentered();
|
|
||||||
void setGeometry(int x, int y, int w, int h);
|
|
||||||
|
|
||||||
HWND getParentWindow() const;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void onMaximizeButtonClicked();
|
|
||||||
void onMinimizeButtonClicked();
|
|
||||||
void onCloseButtonClicked();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void childEvent(QChildEvent *e) override;
|
|
||||||
bool eventFilter(QObject *o, QEvent *e) override;
|
|
||||||
|
|
||||||
bool focusNextPrevChild(bool next) override;
|
|
||||||
void focusInEvent(QFocusEvent *e) override;
|
|
||||||
|
|
||||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QVBoxLayout m_Layout;
|
|
||||||
|
|
||||||
Widget *p_Widget;
|
|
||||||
|
|
||||||
WinNativeWindow *p_ParentWinNativeWindow;
|
|
||||||
HWND m_ParentNativeWindowHandle;
|
|
||||||
|
|
||||||
HWND _prevFocus;
|
|
||||||
bool _reenableParent;
|
|
||||||
|
|
||||||
int BORDERWIDTH = 6; // Adjust this as you wish for # of pixels on the
|
|
||||||
// edges to show resize handles
|
|
||||||
int TOOLBARHEIGHT = 40; // Adjust this as you wish for # of pixels from the
|
|
||||||
// top to allow dragging the window
|
|
||||||
|
|
||||||
void saveFocus();
|
|
||||||
void resetFocus();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QWINWIDGET_H
|
|
|
@ -1,11 +0,0 @@
|
||||||
#include "widget.h"
|
|
||||||
|
|
||||||
Widget::Widget(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
// Set a black background for funsies
|
|
||||||
QPalette Pal(palette());
|
|
||||||
Pal.setColor(QPalette::Background, Qt::blue);
|
|
||||||
setAutoFillBackground(true);
|
|
||||||
setPalette(Pal);
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef WIDGET_H
|
|
||||||
#define WIDGET_H
|
|
||||||
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QToolBar>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class Widget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit Widget(QWidget *parent = 0);
|
|
||||||
|
|
||||||
// If you want to have Max/Min/Close buttons, look at how QWinWidget uses these
|
|
||||||
QPushButton *maximizeButton = nullptr;
|
|
||||||
QPushButton *minimizeButton = nullptr;
|
|
||||||
QPushButton *closeButton = nullptr;
|
|
||||||
|
|
||||||
// If you want to enable dragging the window when the mouse is over top of, say, a QToolBar,
|
|
||||||
// then look at how QWinWidget uses this
|
|
||||||
QToolBar *toolBar = nullptr;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WIDGET_H
|
|
|
@ -1,235 +0,0 @@
|
||||||
#include "WinNativeWindow.h"
|
|
||||||
|
|
||||||
#include <dwmapi.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
HWND WinNativeWindow::childWindow = nullptr;
|
|
||||||
QWidget *WinNativeWindow::childWidget = nullptr;
|
|
||||||
|
|
||||||
WinNativeWindow::WinNativeWindow(const int x, const int y, const int width, const int height)
|
|
||||||
: hWnd(nullptr)
|
|
||||||
{
|
|
||||||
// The native window technically has a background color. You can set it here
|
|
||||||
HBRUSH windowBackground = CreateSolidBrush(RGB(255, 255, 255));
|
|
||||||
|
|
||||||
HINSTANCE hInstance = GetModuleHandle(nullptr);
|
|
||||||
WNDCLASSEX wcx = {0};
|
|
||||||
|
|
||||||
wcx.cbSize = sizeof(WNDCLASSEX);
|
|
||||||
wcx.style = CS_HREDRAW | CS_VREDRAW | CS_DROPSHADOW;
|
|
||||||
wcx.hInstance = hInstance;
|
|
||||||
wcx.lpfnWndProc = WndProc;
|
|
||||||
wcx.cbClsExtra = 0;
|
|
||||||
wcx.cbWndExtra = 0;
|
|
||||||
wcx.lpszClassName = L"WindowClass";
|
|
||||||
wcx.hbrBackground = windowBackground;
|
|
||||||
wcx.hCursor = LoadCursor(hInstance, IDC_ARROW);
|
|
||||||
|
|
||||||
RegisterClassEx(&wcx);
|
|
||||||
if (FAILED(RegisterClassEx(&wcx))) {
|
|
||||||
throw std::runtime_error("Couldn't register window class");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a native window with the appropriate style
|
|
||||||
hWnd = CreateWindow(L"WindowClass", L"WindowTitle", aero_borderless, x, y, width, height, 0, 0,
|
|
||||||
hInstance, nullptr);
|
|
||||||
if (!hWnd) {
|
|
||||||
throw std::runtime_error("couldn't create window because of reasons");
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
|
|
||||||
|
|
||||||
// This code may be required for aero shadows on some versions of Windows
|
|
||||||
// const MARGINS aero_shadow_on = { 1, 1, 1, 1 };
|
|
||||||
// DwmExtendFrameIntoClientArea(hWnd, &aero_shadow_on);
|
|
||||||
|
|
||||||
SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
WinNativeWindow::~WinNativeWindow()
|
|
||||||
{
|
|
||||||
// Hide the window & send the destroy message
|
|
||||||
ShowWindow(hWnd, SW_HIDE);
|
|
||||||
DestroyWindow(hWnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK WinNativeWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
WinNativeWindow *window =
|
|
||||||
reinterpret_cast<WinNativeWindow *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
|
||||||
|
|
||||||
if (!window) {
|
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (message) {
|
|
||||||
// ALT + SPACE or F10 system menu
|
|
||||||
case WM_SYSCOMMAND: {
|
|
||||||
if (wParam == SC_KEYMENU) {
|
|
||||||
RECT winrect;
|
|
||||||
GetWindowRect(hWnd, &winrect);
|
|
||||||
TrackPopupMenu(GetSystemMenu(hWnd, false), TPM_TOPALIGN | TPM_LEFTALIGN,
|
|
||||||
winrect.left + 5, winrect.top + 5, 0, hWnd, NULL);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case WM_NCCALCSIZE: {
|
|
||||||
// this kills the window frame and title bar we added with
|
|
||||||
// WS_THICKFRAME and WS_CAPTION
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the parent window gets any close messages, send them over to
|
|
||||||
// QWinWidget and don't actually close here
|
|
||||||
case WM_CLOSE: {
|
|
||||||
if (childWindow) {
|
|
||||||
SendMessage(childWindow, WM_CLOSE, 0, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WM_DESTROY: {
|
|
||||||
PostQuitMessage(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_NCHITTEST: {
|
|
||||||
const LONG borderWidth =
|
|
||||||
8 * childWidget->window()->devicePixelRatio(); // This value can be arbitrarily
|
|
||||||
// large as only
|
|
||||||
// intentionally-HTTRANSPARENT'd
|
|
||||||
// messages arrive here
|
|
||||||
RECT winrect;
|
|
||||||
GetWindowRect(hWnd, &winrect);
|
|
||||||
long x = GET_X_LPARAM(lParam);
|
|
||||||
long y = GET_Y_LPARAM(lParam);
|
|
||||||
|
|
||||||
// bottom left corner
|
|
||||||
if (x >= winrect.left && x < winrect.left + borderWidth && y < winrect.bottom &&
|
|
||||||
y >= winrect.bottom - borderWidth) {
|
|
||||||
return HTBOTTOMLEFT;
|
|
||||||
}
|
|
||||||
// bottom right corner
|
|
||||||
if (x < winrect.right && x >= winrect.right - borderWidth && y < winrect.bottom &&
|
|
||||||
y >= winrect.bottom - borderWidth) {
|
|
||||||
return HTBOTTOMRIGHT;
|
|
||||||
}
|
|
||||||
// top left corner
|
|
||||||
if (x >= winrect.left && x < winrect.left + borderWidth && y >= winrect.top &&
|
|
||||||
y < winrect.top + borderWidth) {
|
|
||||||
return HTTOPLEFT;
|
|
||||||
}
|
|
||||||
// top right corner
|
|
||||||
if (x < winrect.right && x >= winrect.right - borderWidth && y >= winrect.top &&
|
|
||||||
y < winrect.top + borderWidth) {
|
|
||||||
return HTTOPRIGHT;
|
|
||||||
}
|
|
||||||
// left border
|
|
||||||
if (x >= winrect.left && x < winrect.left + borderWidth) {
|
|
||||||
return HTLEFT;
|
|
||||||
}
|
|
||||||
// right border
|
|
||||||
if (x < winrect.right && x >= winrect.right - borderWidth) {
|
|
||||||
return HTRIGHT;
|
|
||||||
}
|
|
||||||
// bottom border
|
|
||||||
if (y < winrect.bottom && y >= winrect.bottom - borderWidth) {
|
|
||||||
return HTBOTTOM;
|
|
||||||
}
|
|
||||||
// top border
|
|
||||||
if (y >= winrect.top && y < winrect.top + borderWidth) {
|
|
||||||
return HTTOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it wasn't a border but we still got the message, return
|
|
||||||
// HTCAPTION to allow click-dragging the window
|
|
||||||
return HTCAPTION;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When this native window changes size, it needs to manually resize the
|
|
||||||
// QWinWidget child
|
|
||||||
case WM_SIZE: {
|
|
||||||
RECT winrect;
|
|
||||||
GetClientRect(hWnd, &winrect);
|
|
||||||
|
|
||||||
WINDOWPLACEMENT wp;
|
|
||||||
wp.length = sizeof(WINDOWPLACEMENT);
|
|
||||||
GetWindowPlacement(hWnd, &wp);
|
|
||||||
if (childWidget) {
|
|
||||||
if (wp.showCmd == SW_MAXIMIZE) {
|
|
||||||
childWidget->setGeometry(
|
|
||||||
8, 8 // Maximized window draw 8 pixels off screen
|
|
||||||
,
|
|
||||||
winrect.right / childWidget->window()->devicePixelRatio() - 16,
|
|
||||||
winrect.bottom / childWidget->window()->devicePixelRatio() - 16);
|
|
||||||
} else {
|
|
||||||
childWidget->setGeometry(
|
|
||||||
0, 0, winrect.right / childWidget->window()->devicePixelRatio(),
|
|
||||||
winrect.bottom / childWidget->window()->devicePixelRatio());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_GETMINMAXINFO: {
|
|
||||||
MINMAXINFO *minMaxInfo = (MINMAXINFO *)lParam;
|
|
||||||
if (window->minimumSize.required) {
|
|
||||||
minMaxInfo->ptMinTrackSize.x = window->getMinimumWidth();
|
|
||||||
;
|
|
||||||
minMaxInfo->ptMinTrackSize.y = window->getMinimumHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->maximumSize.required) {
|
|
||||||
minMaxInfo->ptMaxTrackSize.x = window->getMaximumWidth();
|
|
||||||
minMaxInfo->ptMaxTrackSize.y = window->getMaximumHeight();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WinNativeWindow::setGeometry(const int x, const int y, const int width, const int height)
|
|
||||||
{
|
|
||||||
MoveWindow(hWnd, x, y, width, height, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WinNativeWindow::setMinimumSize(const int width, const int height)
|
|
||||||
{
|
|
||||||
this->minimumSize.required = true;
|
|
||||||
this->minimumSize.width = width;
|
|
||||||
this->minimumSize.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WinNativeWindow::getMinimumWidth()
|
|
||||||
{
|
|
||||||
return minimumSize.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WinNativeWindow::getMinimumHeight()
|
|
||||||
{
|
|
||||||
return minimumSize.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WinNativeWindow::setMaximumSize(const int width, const int height)
|
|
||||||
{
|
|
||||||
this->maximumSize.required = true;
|
|
||||||
this->maximumSize.width = width;
|
|
||||||
this->maximumSize.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WinNativeWindow::getMaximumWidth()
|
|
||||||
{
|
|
||||||
return maximumSize.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WinNativeWindow::getMaximumHeight()
|
|
||||||
{
|
|
||||||
return maximumSize.height;
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
#ifndef WINNATIVEWINDOW_H
|
|
||||||
#define WINNATIVEWINDOW_H
|
|
||||||
|
|
||||||
#include "Windows.h"
|
|
||||||
#include "Windowsx.h"
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class WinNativeWindow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WinNativeWindow(const int x, const int y, const int width, const int height);
|
|
||||||
~WinNativeWindow();
|
|
||||||
|
|
||||||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
|
||||||
|
|
||||||
// These six functions exist to restrict native window resizing to whatever
|
|
||||||
// you want your app minimum/maximum size to be
|
|
||||||
void setMinimumSize(const int width, const int height);
|
|
||||||
int getMinimumHeight();
|
|
||||||
int getMinimumWidth();
|
|
||||||
|
|
||||||
void setMaximumSize(const int width, const int height);
|
|
||||||
int getMaximumHeight();
|
|
||||||
int getMaximumWidth();
|
|
||||||
void setGeometry(const int x, const int y, const int width, const int height);
|
|
||||||
|
|
||||||
HWND hWnd;
|
|
||||||
|
|
||||||
static HWND childWindow;
|
|
||||||
static QWidget *childWidget;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct sizeType {
|
|
||||||
sizeType()
|
|
||||||
: required(false)
|
|
||||||
, width(0)
|
|
||||||
, height(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
bool required;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
};
|
|
||||||
|
|
||||||
sizeType minimumSize;
|
|
||||||
sizeType maximumSize;
|
|
||||||
|
|
||||||
DWORD aero_borderless = WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
|
|
||||||
WS_THICKFRAME | WS_CLIPCHILDREN;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WINNATIVEWINDOW_H
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <boost/signals2.hpp>
|
#include <boost/signals2.hpp>
|
||||||
#include <pajlada/settings/setting.hpp>
|
#include <pajlada/settings/setting.hpp>
|
||||||
#include <util/serialize-custom.hpp>
|
#include "util/serialize-custom.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "aboutpage.hpp"
|
#include "aboutpage.hpp"
|
||||||
|
|
||||||
#include <util/layoutcreator.hpp>
|
#include "util/layoutcreator.hpp"
|
||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include <util/layoutcreator.hpp>
|
#include "util/layoutcreator.hpp"
|
||||||
|
|
||||||
#define THEME_ITEMS "White", "Light", "Dark", "Black"
|
#define THEME_ITEMS "White", "Light", "Dark", "Black"
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
|
||||||
#include <util/layoutcreator.hpp>
|
|
||||||
#include "singletons/commandmanager.hpp"
|
#include "singletons/commandmanager.hpp"
|
||||||
|
#include "util/layoutcreator.hpp"
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define TEXT "One command per line.\n"\
|
#define TEXT "One command per line.\n"\
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "emotespage.hpp"
|
#include "emotespage.hpp"
|
||||||
|
|
||||||
#include <util/layoutcreator.hpp>
|
#include "util/layoutcreator.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
Loading…
Reference in a new issue