diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index 56002d07d..3acd46b7f 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -485,6 +485,13 @@ void MainWindow::closeEvent(QCloseEvent *e) { g.s.qbaHeaderState = qtvUsers->header()->saveState(); } + if (g.talkingUI && g.talkingUI->isVisible()) { + // Save the TalkingUI's position if it is visible + // Note that we explicitly don't save the whole geometry as the TalkingUI's size + // is a flexible thing that'll adjust automatically anyways. + g.s.qpTalkingUI_Position = g.talkingUI->pos(); + } + if (qwPTTButtonWidget) { qwPTTButtonWidget->close(); qwPTTButtonWidget->deleteLater(); diff --git a/src/mumble/Settings.cpp b/src/mumble/Settings.cpp index 461822373..dd6b767a9 100644 --- a/src/mumble/Settings.cpp +++ b/src/mumble/Settings.cpp @@ -19,9 +19,15 @@ #include +#include + // We define a global macro called 'g'. This can lead to issues when included code uses 'g' as a type or parameter name (like protobuf 3.7 does). As such, for now, we have to make this our last include. #include "Global.h" + + +const QPoint Settings::UNSPECIFIED_POSITION = QPoint(std::numeric_limits::min(), std::numeric_limits::max()); + bool Shortcut::isServerSpecific() const { if (qvData.canConvert()) { const ShortcutTarget &sc = qvariant_cast (qvData); @@ -461,6 +467,7 @@ Settings::Settings() { bLog24HourClock = true; iChatMessageMargins = 3; + qpTalkingUI_Position = UNSPECIFIED_POSITION; bShowTalkingUI = false; bTalkingUI_LocalUserStaysVisible = false; bTalkingUI_AbbreviateChannelNames = true; @@ -835,6 +842,7 @@ void Settings::load(QSettings* settings_ptr) { SAVELOAD(bDisablePublicList, "ui/disablepubliclist"); // TalkingUI + SAVELOAD(qpTalkingUI_Position, "ui/talkingUIPosition"); SAVELOAD(bShowTalkingUI, "ui/showTalkingUI"); SAVELOAD(bTalkingUI_LocalUserStaysVisible, "ui/talkingUI_LocalUserStaysVisible"); SAVELOAD(bTalkingUI_AbbreviateChannelNames, "ui/talkingUI_AbbreviateChannelNames"); @@ -1191,6 +1199,7 @@ void Settings::save() { SAVELOAD(bDisablePublicList, "ui/disablepubliclist"); // TalkingUI + SAVELOAD(qpTalkingUI_Position, "ui/talkingUIPosition"); SAVELOAD(bShowTalkingUI, "ui/showTalkingUI"); SAVELOAD(bTalkingUI_LocalUserStaysVisible, "ui/talkingUI_LocalUserStaysVisible"); SAVELOAD(bTalkingUI_AbbreviateChannelNames, "ui/talkingUI_AbbreviateChannelNames"); diff --git a/src/mumble/Settings.h b/src/mumble/Settings.h index 308c50367..6762a6298 100644 --- a/src/mumble/Settings.h +++ b/src/mumble/Settings.h @@ -278,6 +278,8 @@ struct Settings { bool bLog24HourClock; int iChatMessageMargins; + static const QPoint UNSPECIFIED_POSITION; + QPoint qpTalkingUI_Position; bool bShowTalkingUI; bool bTalkingUI_LocalUserStaysVisible; bool bTalkingUI_AbbreviateChannelNames; diff --git a/src/mumble/main.cpp b/src/mumble/main.cpp index a757e03d8..bf7c11dea 100644 --- a/src/mumble/main.cpp +++ b/src/mumble/main.cpp @@ -509,6 +509,17 @@ int main(int argc, char **argv) { g.mw->show(); g.talkingUI = new TalkingUI(); + if (g.s.qpTalkingUI_Position != Settings::UNSPECIFIED_POSITION) { + // Restore last position + g.talkingUI->move(g.s.qpTalkingUI_Position); + } else { + // Place the TalkingUI next to the MainWindow by default by default + const QPoint mainWindowPos = g.mw->pos(); + const int horizontalBuffer = 10; + g.talkingUI->move(mainWindowPos.x() + g.mw->size().width() + horizontalBuffer, mainWindowPos.y()); + } + // By setting the TalkingUI's position **before** making it visible tends to more reliably include the + // window's frame to be included in the positioning calculation on X11 (at least using KDE Plasma) g.talkingUI->setVisible(g.s.bShowTalkingUI); QObject::connect(g.mw, &MainWindow::serverSynchronized, g.talkingUI, &TalkingUI::on_serverSynchronized);