diff --git a/chatterino.pro b/chatterino.pro
index 31ed2b8c1..eabd8d396 100644
--- a/chatterino.pro
+++ b/chatterino.pro
@@ -178,21 +178,21 @@ win32 {
}
# Optional dependency on windows sdk 7.1
-#win32:exists(C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\Windows.h) {
-# LIBS += -L"C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib" \
-# -ldwmapi \
-# -lgdi32
-#
+win32:exists(C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\Windows.h) {
+ LIBS += -L"C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib" \
+ -ldwmapi \
+ -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"
+}
macx {
INCLUDEPATH += /usr/local/include
diff --git a/resources/qt.conf b/resources/qt.conf
new file mode 100644
index 000000000..310dd86ab
--- /dev/null
+++ b/resources/qt.conf
@@ -0,0 +1,2 @@
+[Platforms]
+WindowArguments = dpiawareness=2
diff --git a/resources/resources.qrc b/resources/resources.qrc
index e1e4f1a76..e09f97853 100644
--- a/resources/resources.qrc
+++ b/resources/resources.qrc
@@ -33,4 +33,7 @@
images/VSO_Link_blue_16x.png
sounds/ping2.wav
+
+ qt.conf
+
diff --git a/src/main.cpp b/src/main.cpp
index 54f8a118f..d5dd70da4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,12 +1,41 @@
#include "application.hpp"
+#include
#include
#include
+#include
#include
#include
+#ifdef USEWINSDK
+#include "windows.h"
+#endif
+
namespace {
+#ifdef USEWINSDK
+class DpiNativeEventFilter : public QAbstractNativeEventFilter
+{
+public:
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override
+ {
+ MSG *msg = reinterpret_cast(message);
+
+ if (msg->message == WM_NCCREATE) {
+ typedef BOOL(WINAPI * EnableNonClientDpiScaling)(HWND);
+ QLibrary user32("user32.dll", NULL);
+
+ EnableNonClientDpiScaling enableNonClientDpiScaling =
+ (EnableNonClientDpiScaling)user32.resolve("EnableNonClientDpiScaling");
+
+ if (enableNonClientDpiScaling)
+ enableNonClientDpiScaling(msg->hwnd);
+ }
+ return false;
+ }
+};
+#endif
+
inline bool initSettings(bool portable)
{
QString settingsPath;
@@ -38,6 +67,10 @@ int main(int argc, char *argv[])
{
QApplication a(argc, argv);
+#ifdef USEWINSDK
+ a.installNativeEventFilter(new DpiNativeEventFilter);
+#endif
+
a.setAttribute(Qt::AA_EnableHighDpiScaling, true);
// Options
diff --git a/src/widgets/channelview.cpp b/src/widgets/channelview.cpp
index 8e9f4f58c..1594f76c9 100644
--- a/src/widgets/channelview.cpp
+++ b/src/widgets/channelview.cpp
@@ -42,13 +42,24 @@ ChannelView::ChannelView(WindowManager &windowManager, BaseWidget *parent)
this->scrollBar.getCurrentValueChanged().connect([this] {
// Whenever the scrollbar value has been changed, re-render the ChatWidgetView
- this->update();
-
this->layoutMessages();
+
+ this->goToBottom->setVisible(this->scrollBar.isVisible() && !this->scrollBar.isAtBottom());
+
+ this->update();
});
this->repaintGifsConnection =
windowManager.repaintGifs.connect([&] { this->updateGifEmotes(); });
+ this->layoutConnection = windowManager.repaintGifs.connect([&] { this->layout(); });
+
+ this->goToBottom = new RippleEffectLabel(this, 0);
+ this->goToBottom->setStyleSheet("background-color: rgba(0,0,0,0.5); color: #FFF;");
+ this->goToBottom->getLabel().setText("Jump to bottom");
+ this->goToBottom->setVisible(false);
+
+ connect(goToBottom, &RippleEffectLabel::clicked, this,
+ [this] { QTimer::singleShot(180, [this] { this->scrollBar.scrollToBottom(); }); });
}
ChannelView::~ChannelView()
@@ -340,6 +351,10 @@ void ChannelView::resizeEvent(QResizeEvent *)
this->scrollBar.resize(this->scrollBar.width(), height());
this->scrollBar.move(width() - this->scrollBar.width(), 0);
+ this->goToBottom->setGeometry(0, this->height() - 32, this->width(), 32);
+
+ this->scrollBar.raise();
+
layoutMessages();
this->update();
diff --git a/src/widgets/channelview.hpp b/src/widgets/channelview.hpp
index c472dc1bf..d232b5813 100644
--- a/src/widgets/channelview.hpp
+++ b/src/widgets/channelview.hpp
@@ -7,6 +7,7 @@
#include "messages/word.hpp"
#include "widgets/accountpopup.hpp"
#include "widgets/basewidget.hpp"
+#include "widgets/rippleeffectlabel.hpp"
#include "widgets/scrollbar.hpp"
#include
@@ -135,6 +136,7 @@ private:
std::vector gifEmotes;
ScrollBar scrollBar;
+ RippleEffectLabel *goToBottom;
// This variable can be used to decide whether or not we should render the "Show latest
// messages" button
@@ -155,6 +157,7 @@ private:
boost::signals2::connection messageAppendedConnection;
boost::signals2::connection messageRemovedConnection;
boost::signals2::connection repaintGifsConnection;
+ boost::signals2::connection layoutConnection;
private slots:
void wordTypeMaskChanged()
diff --git a/src/widgets/chatwidget.hpp b/src/widgets/chatwidget.hpp
index b468520d5..674478b6f 100644
--- a/src/widgets/chatwidget.hpp
+++ b/src/widgets/chatwidget.hpp
@@ -9,6 +9,7 @@
#include "widgets/channelview.hpp"
#include "widgets/chatwidgetheader.hpp"
#include "widgets/chatwidgetinput.hpp"
+#include "widgets/rippleeffectlabel.hpp"
#include
#include
diff --git a/src/widgets/mainwindow.cpp b/src/widgets/mainwindow.cpp
index 7a3380101..9107b0c44 100644
--- a/src/widgets/mainwindow.cpp
+++ b/src/widgets/mainwindow.cpp
@@ -7,13 +7,14 @@
#include "widgets/settingsdialog.hpp"
#include
+#include
#include
#include
#include
#include
#ifdef USEWINSDK
-#include "Windows.hpp"
+#include "windows.h"
#endif
namespace chatterino {
@@ -70,24 +71,18 @@ MainWindow::~MainWindow()
{
}
-void MainWindow::layoutVisibleChatWidgets(Channel *channel)
+#ifdef USEWINSDK
+bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
- auto *page = this->notebook.getSelectedPage();
+ MSG *msg = reinterpret_cast(message);
- if (page == nullptr) {
- return;
+ if (msg->message == 0x02E0) {
+ qDebug() << "dpi changed";
}
- const std::vector &widgets = page->getChatWidgets();
-
- for (auto it = widgets.begin(); it != widgets.end(); ++it) {
- ChatWidget *widget = *it;
-
- if (channel == nullptr || channel == widget->getChannel().get()) {
- widget->layoutMessages();
- }
- }
+ return QWidget::nativeEvent(eventType, message, result);
}
+#endif
void MainWindow::repaintVisibleChatWidgets(Channel *channel)
{
diff --git a/src/widgets/mainwindow.hpp b/src/widgets/mainwindow.hpp
index 758fc7898..6e96a0ea4 100644
--- a/src/widgets/mainwindow.hpp
+++ b/src/widgets/mainwindow.hpp
@@ -4,9 +4,9 @@
#include "widgets/notebook.hpp"
#include "widgets/titlebar.hpp"
-#ifdef USEWINSDK
-#include
-#endif
+//#ifdef USEWINSDK
+//#include
+//#endif
#include
#include
@@ -30,7 +30,6 @@ public:
CompletionManager &_completionManager);
~MainWindow();
- void layoutVisibleChatWidgets(Channel *channel = nullptr);
void repaintVisibleChatWidgets(Channel *channel = nullptr);
void load(const boost::property_tree::ptree &tree);
@@ -43,6 +42,9 @@ public:
protected:
virtual void closeEvent(QCloseEvent *event) override;
+#ifdef USEWINSDK
+ virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
+#endif
private:
virtual void refreshTheme() override;
diff --git a/src/widgets/notebookbutton.cpp b/src/widgets/notebookbutton.cpp
index 875ba9cfb..3b355e461 100644
--- a/src/widgets/notebookbutton.cpp
+++ b/src/widgets/notebookbutton.cpp
@@ -11,7 +11,7 @@ namespace chatterino {
namespace widgets {
NotebookButton::NotebookButton(BaseWidget *parent)
- : FancyButton(parent)
+ : RippleEffectButton(parent)
{
setMouseEffectColor(QColor(0, 0, 0));
}
@@ -99,7 +99,7 @@ void NotebookButton::mouseReleaseEvent(QMouseEvent *event)
emit clicked();
}
- FancyButton::mouseReleaseEvent(event);
+ RippleEffectButton::mouseReleaseEvent(event);
}
} // namespace widgets
diff --git a/src/widgets/notebookbutton.hpp b/src/widgets/notebookbutton.hpp
index 769dadd8c..811c21667 100644
--- a/src/widgets/notebookbutton.hpp
+++ b/src/widgets/notebookbutton.hpp
@@ -7,7 +7,7 @@
namespace chatterino {
namespace widgets {
-class NotebookButton : public FancyButton
+class NotebookButton : public RippleEffectButton
{
Q_OBJECT
diff --git a/src/widgets/rippleeffectbutton.cpp b/src/widgets/rippleeffectbutton.cpp
index 53d338921..93d84e862 100644
--- a/src/widgets/rippleeffectbutton.cpp
+++ b/src/widgets/rippleeffectbutton.cpp
@@ -6,29 +6,29 @@
namespace chatterino {
namespace widgets {
-FancyButton::FancyButton(BaseWidget *parent)
+RippleEffectButton::RippleEffectButton(BaseWidget *parent)
: BaseWidget(parent)
{
- connect(&effectTimer, &QTimer::timeout, this, &FancyButton::onMouseEffectTimeout);
+ connect(&effectTimer, &QTimer::timeout, this, &RippleEffectButton::onMouseEffectTimeout);
this->effectTimer.setInterval(20);
this->effectTimer.start();
}
-void FancyButton::setMouseEffectColor(QColor color)
+void RippleEffectButton::setMouseEffectColor(QColor color)
{
this->mouseEffectColor = color;
}
-void FancyButton::paintEvent(QPaintEvent *)
+void RippleEffectButton::paintEvent(QPaintEvent *)
{
QPainter painter(this);
this->fancyPaint(painter);
}
-void FancyButton::fancyPaint(QPainter &painter)
+void RippleEffectButton::fancyPaint(QPainter &painter)
{
QColor &c = this->mouseEffectColor;
@@ -58,17 +58,17 @@ void FancyButton::fancyPaint(QPainter &painter)
}
}
-void FancyButton::enterEvent(QEvent *)
+void RippleEffectButton::enterEvent(QEvent *)
{
this->mouseOver = true;
}
-void FancyButton::leaveEvent(QEvent *)
+void RippleEffectButton::leaveEvent(QEvent *)
{
this->mouseOver = false;
}
-void FancyButton::mousePressEvent(QMouseEvent *event)
+void RippleEffectButton::mousePressEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton) {
return;
@@ -79,7 +79,7 @@ void FancyButton::mousePressEvent(QMouseEvent *event)
this->mouseDown = true;
}
-void FancyButton::mouseReleaseEvent(QMouseEvent *event)
+void RippleEffectButton::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton) {
return;
@@ -92,12 +92,12 @@ void FancyButton::mouseReleaseEvent(QMouseEvent *event)
}
}
-void FancyButton::mouseMoveEvent(QMouseEvent *event)
+void RippleEffectButton::mouseMoveEvent(QMouseEvent *event)
{
this->mousePos = event->pos();
}
-void FancyButton::onMouseEffectTimeout()
+void RippleEffectButton::onMouseEffectTimeout()
{
bool performUpdate = false;
diff --git a/src/widgets/rippleeffectbutton.hpp b/src/widgets/rippleeffectbutton.hpp
index c61a9cac7..2ce38f9b0 100644
--- a/src/widgets/rippleeffectbutton.hpp
+++ b/src/widgets/rippleeffectbutton.hpp
@@ -11,7 +11,7 @@
namespace chatterino {
namespace widgets {
-class FancyButton : public BaseWidget
+class RippleEffectButton : public BaseWidget
{
Q_OBJECT
@@ -26,7 +26,7 @@ class FancyButton : public BaseWidget
};
public:
- FancyButton(BaseWidget *parent);
+ RippleEffectButton(BaseWidget *parent);
void setMouseEffectColor(QColor color);
diff --git a/src/widgets/rippleeffectlabel.cpp b/src/widgets/rippleeffectlabel.cpp
index 2addd2973..5e64f03e0 100644
--- a/src/widgets/rippleeffectlabel.cpp
+++ b/src/widgets/rippleeffectlabel.cpp
@@ -9,7 +9,7 @@ namespace chatterino {
namespace widgets {
RippleEffectLabel::RippleEffectLabel(BaseWidget *parent, int spacing)
- : FancyButton(parent)
+ : RippleEffectButton(parent)
{
setLayout(&this->ui.hbox);
diff --git a/src/widgets/rippleeffectlabel.hpp b/src/widgets/rippleeffectlabel.hpp
index 88175f142..bafd21ac1 100644
--- a/src/widgets/rippleeffectlabel.hpp
+++ b/src/widgets/rippleeffectlabel.hpp
@@ -15,7 +15,7 @@ class ColorScheme;
namespace widgets {
-class RippleEffectLabel : public FancyButton
+class RippleEffectLabel : public RippleEffectButton
{
public:
explicit RippleEffectLabel(BaseWidget *parent, int spacing = 6);
diff --git a/src/widgets/settingsdialog.cpp b/src/widgets/settingsdialog.cpp
index 90d861033..d9939622e 100644
--- a/src/widgets/settingsdialog.cpp
+++ b/src/widgets/settingsdialog.cpp
@@ -301,9 +301,11 @@ void SettingsDialog::addTabs()
auto form = new QFormLayout();
form->addRow("Window:", createCheckbox("Window always on top", settings.windowTopMost));
- form->addRow("Messages:", createCheckbox("Mention users with a @ (except in commands)",
- settings.mentionUsersWithAt));
- form->addRow("", createCheckbox("Hide input box if empty", settings.hideEmptyInput));
+ // form->addRow("Messages:", createCheckbox("Mention users with a @ (except in
+ // commands)",
+ // settings.mentionUsersWithAt));
+ form->addRow("Messages:",
+ createCheckbox("Hide input box if empty", settings.hideEmptyInput));
form->addRow("", createCheckbox("Show last read message indicator",
settings.showLastMessageIndicator));
diff --git a/src/windowmanager.cpp b/src/windowmanager.cpp
index f71c5ca7f..3792a42d4 100644
--- a/src/windowmanager.cpp
+++ b/src/windowmanager.cpp
@@ -27,9 +27,7 @@ static const std::string &getSettingsPath()
void WindowManager::layoutVisibleChatWidgets(Channel *channel)
{
- if (this->mainWindow != nullptr) {
- this->mainWindow->layoutVisibleChatWidgets(channel);
- }
+ this->layout();
}
void WindowManager::repaintVisibleChatWidgets(Channel *channel)
diff --git a/src/windowmanager.hpp b/src/windowmanager.hpp
index c5f1231d3..441e7b319 100644
--- a/src/windowmanager.hpp
+++ b/src/windowmanager.hpp
@@ -31,6 +31,7 @@ public:
void save();
boost::signals2::signal repaintGifs;
+ boost::signals2::signal layout;
private:
std::mutex windowMutex;