added gotToBottom and EnableNonClientDpiScaling

This commit is contained in:
fourtf 2017-09-21 17:34:41 +02:00
parent 3e24752477
commit 222eedcd21
18 changed files with 108 additions and 53 deletions

View file

@ -178,21 +178,21 @@ win32 {
} }
# Optional dependency on windows sdk 7.1 # Optional dependency on windows sdk 7.1
#win32:exists(C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\Windows.h) { win32:exists(C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\Windows.h) {
# LIBS += -L"C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib" \ LIBS += -L"C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib" \
# -ldwmapi \ -ldwmapi \
# -lgdi32 -lgdi32
#
# SOURCES += platform/borderless/qwinwidget.cpp \ # SOURCES += platform/borderless/qwinwidget.cpp \
# platform/borderless/winnativewindow.cpp \ # platform/borderless/winnativewindow.cpp \
# platform/borderless/widget.cpp # platform/borderless/widget.cpp
#
# HEADERS += platform/borderless/qwinwidget.h \ # HEADERS += platform/borderless/qwinwidget.h \
# platform/borderless/winnativewindow.h \ # platform/borderless/winnativewindow.h \
# platform/borderless/widget.h # platform/borderless/widget.h
#
# DEFINES += "USEWINSDK" DEFINES += "USEWINSDK"
#} }
macx { macx {
INCLUDEPATH += /usr/local/include INCLUDEPATH += /usr/local/include

2
resources/qt.conf Normal file
View file

@ -0,0 +1,2 @@
[Platforms]
WindowArguments = dpiawareness=2

View file

@ -33,4 +33,7 @@
<file>images/VSO_Link_blue_16x.png</file> <file>images/VSO_Link_blue_16x.png</file>
<file>sounds/ping2.wav</file> <file>sounds/ping2.wav</file>
</qresource> </qresource>
<qresource prefix="/qt/etc">
<file>qt.conf</file>
</qresource>
</RCC> </RCC>

View file

@ -1,12 +1,41 @@
#include "application.hpp" #include "application.hpp"
#include <QAbstractNativeEventFilter>
#include <QApplication> #include <QApplication>
#include <QDir> #include <QDir>
#include <QLibrary>
#include <QStandardPaths> #include <QStandardPaths>
#include <pajlada/settings/settingmanager.hpp> #include <pajlada/settings/settingmanager.hpp>
#ifdef USEWINSDK
#include "windows.h"
#endif
namespace { namespace {
#ifdef USEWINSDK
class DpiNativeEventFilter : public QAbstractNativeEventFilter
{
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override
{
MSG *msg = reinterpret_cast<MSG *>(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) inline bool initSettings(bool portable)
{ {
QString settingsPath; QString settingsPath;
@ -38,6 +67,10 @@ int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
#ifdef USEWINSDK
a.installNativeEventFilter(new DpiNativeEventFilter);
#endif
a.setAttribute(Qt::AA_EnableHighDpiScaling, true); a.setAttribute(Qt::AA_EnableHighDpiScaling, true);
// Options // Options

View file

@ -42,13 +42,24 @@ ChannelView::ChannelView(WindowManager &windowManager, BaseWidget *parent)
this->scrollBar.getCurrentValueChanged().connect([this] { this->scrollBar.getCurrentValueChanged().connect([this] {
// Whenever the scrollbar value has been changed, re-render the ChatWidgetView // Whenever the scrollbar value has been changed, re-render the ChatWidgetView
this->update();
this->layoutMessages(); this->layoutMessages();
this->goToBottom->setVisible(this->scrollBar.isVisible() && !this->scrollBar.isAtBottom());
this->update();
}); });
this->repaintGifsConnection = this->repaintGifsConnection =
windowManager.repaintGifs.connect([&] { this->updateGifEmotes(); }); 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() ChannelView::~ChannelView()
@ -340,6 +351,10 @@ void ChannelView::resizeEvent(QResizeEvent *)
this->scrollBar.resize(this->scrollBar.width(), height()); this->scrollBar.resize(this->scrollBar.width(), height());
this->scrollBar.move(width() - this->scrollBar.width(), 0); this->scrollBar.move(width() - this->scrollBar.width(), 0);
this->goToBottom->setGeometry(0, this->height() - 32, this->width(), 32);
this->scrollBar.raise();
layoutMessages(); layoutMessages();
this->update(); this->update();

View file

@ -7,6 +7,7 @@
#include "messages/word.hpp" #include "messages/word.hpp"
#include "widgets/accountpopup.hpp" #include "widgets/accountpopup.hpp"
#include "widgets/basewidget.hpp" #include "widgets/basewidget.hpp"
#include "widgets/rippleeffectlabel.hpp"
#include "widgets/scrollbar.hpp" #include "widgets/scrollbar.hpp"
#include <QPaintEvent> #include <QPaintEvent>
@ -135,6 +136,7 @@ private:
std::vector<GifEmoteData> gifEmotes; std::vector<GifEmoteData> gifEmotes;
ScrollBar scrollBar; ScrollBar scrollBar;
RippleEffectLabel *goToBottom;
// This variable can be used to decide whether or not we should render the "Show latest // This variable can be used to decide whether or not we should render the "Show latest
// messages" button // messages" button
@ -155,6 +157,7 @@ private:
boost::signals2::connection messageAppendedConnection; boost::signals2::connection messageAppendedConnection;
boost::signals2::connection messageRemovedConnection; boost::signals2::connection messageRemovedConnection;
boost::signals2::connection repaintGifsConnection; boost::signals2::connection repaintGifsConnection;
boost::signals2::connection layoutConnection;
private slots: private slots:
void wordTypeMaskChanged() void wordTypeMaskChanged()

View file

@ -9,6 +9,7 @@
#include "widgets/channelview.hpp" #include "widgets/channelview.hpp"
#include "widgets/chatwidgetheader.hpp" #include "widgets/chatwidgetheader.hpp"
#include "widgets/chatwidgetinput.hpp" #include "widgets/chatwidgetinput.hpp"
#include "widgets/rippleeffectlabel.hpp"
#include <QFont> #include <QFont>
#include <QShortcut> #include <QShortcut>

View file

@ -7,13 +7,14 @@
#include "widgets/settingsdialog.hpp" #include "widgets/settingsdialog.hpp"
#include <QDebug> #include <QDebug>
#include <QLibrary>
#include <QPalette> #include <QPalette>
#include <QShortcut> #include <QShortcut>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#ifdef USEWINSDK #ifdef USEWINSDK
#include "Windows.hpp" #include "windows.h"
#endif #endif
namespace chatterino { 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<MSG *>(message);
if (page == nullptr) { if (msg->message == 0x02E0) {
return; qDebug() << "dpi changed";
} }
const std::vector<ChatWidget *> &widgets = page->getChatWidgets(); return QWidget::nativeEvent(eventType, message, result);
for (auto it = widgets.begin(); it != widgets.end(); ++it) {
ChatWidget *widget = *it;
if (channel == nullptr || channel == widget->getChannel().get()) {
widget->layoutMessages();
}
}
} }
#endif
void MainWindow::repaintVisibleChatWidgets(Channel *channel) void MainWindow::repaintVisibleChatWidgets(Channel *channel)
{ {

View file

@ -4,9 +4,9 @@
#include "widgets/notebook.hpp" #include "widgets/notebook.hpp"
#include "widgets/titlebar.hpp" #include "widgets/titlebar.hpp"
#ifdef USEWINSDK //#ifdef USEWINSDK
#include <platform/borderless/qwinwidget.h> //#include <platform/borderless/qwinwidget.h>
#endif //#endif
#include <QMainWindow> #include <QMainWindow>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
@ -30,7 +30,6 @@ public:
CompletionManager &_completionManager); CompletionManager &_completionManager);
~MainWindow(); ~MainWindow();
void layoutVisibleChatWidgets(Channel *channel = nullptr);
void repaintVisibleChatWidgets(Channel *channel = nullptr); void repaintVisibleChatWidgets(Channel *channel = nullptr);
void load(const boost::property_tree::ptree &tree); void load(const boost::property_tree::ptree &tree);
@ -43,6 +42,9 @@ public:
protected: protected:
virtual void closeEvent(QCloseEvent *event) override; virtual void closeEvent(QCloseEvent *event) override;
#ifdef USEWINSDK
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
#endif
private: private:
virtual void refreshTheme() override; virtual void refreshTheme() override;

View file

@ -11,7 +11,7 @@ namespace chatterino {
namespace widgets { namespace widgets {
NotebookButton::NotebookButton(BaseWidget *parent) NotebookButton::NotebookButton(BaseWidget *parent)
: FancyButton(parent) : RippleEffectButton(parent)
{ {
setMouseEffectColor(QColor(0, 0, 0)); setMouseEffectColor(QColor(0, 0, 0));
} }
@ -99,7 +99,7 @@ void NotebookButton::mouseReleaseEvent(QMouseEvent *event)
emit clicked(); emit clicked();
} }
FancyButton::mouseReleaseEvent(event); RippleEffectButton::mouseReleaseEvent(event);
} }
} // namespace widgets } // namespace widgets

View file

@ -7,7 +7,7 @@
namespace chatterino { namespace chatterino {
namespace widgets { namespace widgets {
class NotebookButton : public FancyButton class NotebookButton : public RippleEffectButton
{ {
Q_OBJECT Q_OBJECT

View file

@ -6,29 +6,29 @@
namespace chatterino { namespace chatterino {
namespace widgets { namespace widgets {
FancyButton::FancyButton(BaseWidget *parent) RippleEffectButton::RippleEffectButton(BaseWidget *parent)
: BaseWidget(parent) : BaseWidget(parent)
{ {
connect(&effectTimer, &QTimer::timeout, this, &FancyButton::onMouseEffectTimeout); connect(&effectTimer, &QTimer::timeout, this, &RippleEffectButton::onMouseEffectTimeout);
this->effectTimer.setInterval(20); this->effectTimer.setInterval(20);
this->effectTimer.start(); this->effectTimer.start();
} }
void FancyButton::setMouseEffectColor(QColor color) void RippleEffectButton::setMouseEffectColor(QColor color)
{ {
this->mouseEffectColor = color; this->mouseEffectColor = color;
} }
void FancyButton::paintEvent(QPaintEvent *) void RippleEffectButton::paintEvent(QPaintEvent *)
{ {
QPainter painter(this); QPainter painter(this);
this->fancyPaint(painter); this->fancyPaint(painter);
} }
void FancyButton::fancyPaint(QPainter &painter) void RippleEffectButton::fancyPaint(QPainter &painter)
{ {
QColor &c = this->mouseEffectColor; QColor &c = this->mouseEffectColor;
@ -58,17 +58,17 @@ void FancyButton::fancyPaint(QPainter &painter)
} }
} }
void FancyButton::enterEvent(QEvent *) void RippleEffectButton::enterEvent(QEvent *)
{ {
this->mouseOver = true; this->mouseOver = true;
} }
void FancyButton::leaveEvent(QEvent *) void RippleEffectButton::leaveEvent(QEvent *)
{ {
this->mouseOver = false; this->mouseOver = false;
} }
void FancyButton::mousePressEvent(QMouseEvent *event) void RippleEffectButton::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() != Qt::LeftButton) { if (event->button() != Qt::LeftButton) {
return; return;
@ -79,7 +79,7 @@ void FancyButton::mousePressEvent(QMouseEvent *event)
this->mouseDown = true; this->mouseDown = true;
} }
void FancyButton::mouseReleaseEvent(QMouseEvent *event) void RippleEffectButton::mouseReleaseEvent(QMouseEvent *event)
{ {
if (event->button() != Qt::LeftButton) { if (event->button() != Qt::LeftButton) {
return; return;
@ -92,12 +92,12 @@ void FancyButton::mouseReleaseEvent(QMouseEvent *event)
} }
} }
void FancyButton::mouseMoveEvent(QMouseEvent *event) void RippleEffectButton::mouseMoveEvent(QMouseEvent *event)
{ {
this->mousePos = event->pos(); this->mousePos = event->pos();
} }
void FancyButton::onMouseEffectTimeout() void RippleEffectButton::onMouseEffectTimeout()
{ {
bool performUpdate = false; bool performUpdate = false;

View file

@ -11,7 +11,7 @@
namespace chatterino { namespace chatterino {
namespace widgets { namespace widgets {
class FancyButton : public BaseWidget class RippleEffectButton : public BaseWidget
{ {
Q_OBJECT Q_OBJECT
@ -26,7 +26,7 @@ class FancyButton : public BaseWidget
}; };
public: public:
FancyButton(BaseWidget *parent); RippleEffectButton(BaseWidget *parent);
void setMouseEffectColor(QColor color); void setMouseEffectColor(QColor color);

View file

@ -9,7 +9,7 @@ namespace chatterino {
namespace widgets { namespace widgets {
RippleEffectLabel::RippleEffectLabel(BaseWidget *parent, int spacing) RippleEffectLabel::RippleEffectLabel(BaseWidget *parent, int spacing)
: FancyButton(parent) : RippleEffectButton(parent)
{ {
setLayout(&this->ui.hbox); setLayout(&this->ui.hbox);

View file

@ -15,7 +15,7 @@ class ColorScheme;
namespace widgets { namespace widgets {
class RippleEffectLabel : public FancyButton class RippleEffectLabel : public RippleEffectButton
{ {
public: public:
explicit RippleEffectLabel(BaseWidget *parent, int spacing = 6); explicit RippleEffectLabel(BaseWidget *parent, int spacing = 6);

View file

@ -301,9 +301,11 @@ void SettingsDialog::addTabs()
auto form = new QFormLayout(); auto form = new QFormLayout();
form->addRow("Window:", createCheckbox("Window always on top", settings.windowTopMost)); form->addRow("Window:", createCheckbox("Window always on top", settings.windowTopMost));
form->addRow("Messages:", createCheckbox("Mention users with a @ (except in commands)", // form->addRow("Messages:", createCheckbox("Mention users with a @ (except in
settings.mentionUsersWithAt)); // commands)",
form->addRow("", createCheckbox("Hide input box if empty", settings.hideEmptyInput)); // settings.mentionUsersWithAt));
form->addRow("Messages:",
createCheckbox("Hide input box if empty", settings.hideEmptyInput));
form->addRow("", createCheckbox("Show last read message indicator", form->addRow("", createCheckbox("Show last read message indicator",
settings.showLastMessageIndicator)); settings.showLastMessageIndicator));

View file

@ -27,9 +27,7 @@ static const std::string &getSettingsPath()
void WindowManager::layoutVisibleChatWidgets(Channel *channel) void WindowManager::layoutVisibleChatWidgets(Channel *channel)
{ {
if (this->mainWindow != nullptr) { this->layout();
this->mainWindow->layoutVisibleChatWidgets(channel);
}
} }
void WindowManager::repaintVisibleChatWidgets(Channel *channel) void WindowManager::repaintVisibleChatWidgets(Channel *channel)

View file

@ -31,6 +31,7 @@ public:
void save(); void save();
boost::signals2::signal<void()> repaintGifs; boost::signals2::signal<void()> repaintGifs;
boost::signals2::signal<void()> layout;
private: private:
std::mutex windowMutex; std::mutex windowMutex;