Read decoration layout property from gtk

This commit is contained in:
Ilya Fedin 2020-07-18 09:06:29 +04:00 committed by John Preston
parent 9e0b046213
commit 841908fe31
11 changed files with 218 additions and 4 deletions

View File

@ -1089,6 +1089,7 @@ PRIVATE
window/window_connecting_widget.h
window/window_controller.cpp
window/window_controller.h
window/window_controls_layout.h
window/window_filters_menu.cpp
window/window_filters_menu.h
window/window_history_hider.cpp

View File

@ -205,6 +205,8 @@ void Application::run() {
return;
}
Core::App().settings().setWindowControlsLayout(Platform::WindowControlsLayout());
_translator = std::make_unique<Lang::Translator>();
QCoreApplication::instance()->installTranslator(_translator.get());

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "window/themes/window_themes_embedded.h"
#include "window/window_controls_layout.h"
enum class SendFilesWay;
enum class RectPart;
@ -440,6 +441,18 @@ public:
[[nodiscard]] rpl::producer<bool> systemDarkModeEnabledChanges() const {
return _systemDarkModeEnabled.changes();
}
void setWindowControlsLayout(Window::ControlsLayout value) {
_windowControlsLayout = value;
}
[[nodiscard]] Window::ControlsLayout windowControlsLayout() const {
return _windowControlsLayout.current();
}
[[nodiscard]] rpl::producer<Window::ControlsLayout> windowControlsLayoutValue() const {
return _windowControlsLayout.value();
}
[[nodiscard]] rpl::producer<Window::ControlsLayout> windowControlsLayoutChanges() const {
return _windowControlsLayout.changes();
}
[[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] float64 DefaultDialogsWidthRatio();
@ -510,6 +523,7 @@ private:
rpl::variable<bool> _nativeWindowFrame = false;
rpl::variable<std::optional<bool>> _systemDarkMode = std::nullopt;
rpl::variable<bool> _systemDarkModeEnabled = false;
rpl::variable<Window::ControlsLayout> _windowControlsLayout;
bool _tabbedReplacedWithInfo = false; // per-window
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window

View File

@ -181,6 +181,12 @@ void DarkModeChanged() {
Core::App().settings().setSystemDarkMode(Platform::IsDarkMode());
});
}
void DecorationLayoutChanged() {
Core::Sandbox::Instance().customEnterFromEventLoop([] {
Core::App().settings().setWindowControlsLayout(Platform::WindowControlsLayout());
});
}
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
} // namespace
@ -289,6 +295,10 @@ void start() {
if (!gtk_check_version(3, 0, 0)) {
g_signal_connect(settings, "notify::gtk-application-prefer-dark-theme", G_CALLBACK(DarkModeChanged), nullptr);
}
if (!gtk_check_version(3, 12, 0)) {
g_signal_connect(settings, "notify::gtk-decoration-layout", G_CALLBACK(DecorationLayoutChanged), nullptr);
}
} else {
LOG(("Could not load gtk-3 or gtk-x11-2.0!"));
}

View File

@ -580,6 +580,18 @@ bool StartWaylandResize(QWindow *window, Qt::Edges edges) {
return false;
}
Window::Control GtkKeywordToWindowControl(const QString &keyword) {
if (keyword == qstr("minimize")) {
return Window::Control::Minimize;
} else if (keyword == qstr("maximize")) {
return Window::Control::Maximize;
} else if (keyword == qstr("close")) {
return Window::Control::Close;
}
return Window::Control::Unknown;
}
} // namespace
void SetApplicationIcon(const QIcon &icon) {
@ -939,6 +951,57 @@ bool StartSystemResize(QWindow *window, Qt::Edges edges) {
}
}
Window::ControlsLayout WindowControlsLayout() {
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
if (Libs::GtkSettingSupported()
&& Libs::GtkLoaded()
&& Libs::gtk_check_version != nullptr
&& !Libs::gtk_check_version(3, 12, 0)) {
const auto decorationLayout = Libs::GtkSetting("gtk-decoration-layout").split(':');
std::vector<Window::Control> controlsLeft;
ranges::transform(
decorationLayout[0].split(','),
ranges::back_inserter(controlsLeft),
GtkKeywordToWindowControl
);
std::vector<Window::Control> controlsRight;
if (decorationLayout.size() > 1) {
ranges::transform(
decorationLayout[1].split(','),
ranges::back_inserter(controlsRight),
GtkKeywordToWindowControl
);
}
Window::ControlsLayout controls;
controls.left = controlsLeft;
controls.right = controlsRight;
return controls;
}
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
Window::ControlsLayout controls;
if (DesktopEnvironment::IsUnity()) {
controls.left = {
Window::Control::Close,
Window::Control::Minimize,
Window::Control::Maximize,
};
} else {
controls.right = {
Window::Control::Minimize,
Window::Control::Maximize,
Window::Control::Close,
};
}
return controls;
}
} // namespace Platform
namespace {

View File

@ -283,6 +283,17 @@ void IgnoreApplicationActivationRightNow() {
objc_ignoreApplicationActivationRightNow();
}
Window::ControlsLayout WindowControlsLayout() {
Window::ControlsLayout controls;
controls.left = {
Window::Control::Close,
Window::Control::Minimize,
Window::Control::Maximize,
};
return controls;
}
} // namespace Platform
void psNewVersion() {

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "window/window_controls_layout.h"
namespace Platform {
void start();
@ -52,6 +54,7 @@ bool TrayIconSupported();
QImage GetImageFromClipboard();
bool StartSystemMove(QWindow *window);
bool StartSystemResize(QWindow *window, Qt::Edges edges);
Window::ControlsLayout WindowControlsLayout();
namespace ThirdParty {

View File

@ -418,6 +418,17 @@ bool AutostartSupported() {
return !IsWindowsStoreBuild();
}
Window::ControlsLayout WindowControlsLayout() {
Window::ControlsLayout controls;
controls.right = {
Window::Control::Minimize,
Window::Control::Maximize,
Window::Control::Close,
};
return controls;
}
} // namespace Platform
namespace {

View File

@ -0,0 +1,24 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Window {
enum class Control {
Unknown,
Minimize,
Maximize,
Close,
};
struct ControlsLayout {
std::vector<Control> left;
std::vector<Control> right;
};
} // namespace Window

View File

@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/platform_specific.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
#include "core/core_settings.h"
#include "core/application.h"
#include "styles/style_window.h"
#include "base/call_delayed.h"
@ -54,6 +56,11 @@ TitleWidgetQt::TitleWidgetQt(QWidget *parent)
});
_close->setPointerCursor(false);
Core::App().settings().windowControlsLayoutChanges(
) | rpl::start_with_next([=] {
updateControlsPosition();
}, lifetime());
QCoreApplication::instance()->installEventFilter(this);
_windowWasFrameless = (window()->windowFlags() & Qt::FramelessWindowHint) != 0;
@ -106,10 +113,74 @@ void TitleWidgetQt::paintEvent(QPaintEvent *e) {
}
void TitleWidgetQt::updateControlsPosition() {
auto right = 0;
_close->moveToRight(right, 0); right += _close->width();
_maximizeRestore->moveToRight(right, 0); right += _maximizeRestore->width();
_minimize->moveToRight(right, 0);
const auto controlsLayout = Core::App().settings().windowControlsLayout();
const auto controlsLeft = controlsLayout.left;
const auto controlsRight = controlsLayout.right;
if (ranges::contains(controlsLeft, Control::Minimize)
|| ranges::contains(controlsRight, Control::Minimize)) {
_minimize->show();
} else {
_minimize->hide();
}
if (ranges::contains(controlsLeft, Control::Maximize)
|| ranges::contains(controlsRight, Control::Maximize)) {
_maximizeRestore->show();
} else {
_maximizeRestore->hide();
}
if (ranges::contains(controlsLeft, Control::Close)
|| ranges::contains(controlsRight, Control::Close)) {
_close->show();
} else {
_close->hide();
}
updateControlsPositionBySide(controlsLeft, false);
updateControlsPositionBySide(controlsRight, true);
}
void TitleWidgetQt::updateControlsPositionBySide(
const std::vector<Control> &controls,
bool right) {
const auto preparedControls = right
? (ranges::view::reverse(controls) | ranges::to_vector)
: controls;
auto position = 0;
for (const auto &control : preparedControls) {
switch (control) {
case Control::Minimize:
if (right) {
_minimize->moveToRight(position, 0);
} else {
_minimize->moveToLeft(position, 0);
}
position += _minimize->width();
break;
case Control::Maximize:
if (right) {
_maximizeRestore->moveToRight(position, 0);
} else {
_maximizeRestore->moveToLeft(position, 0);
}
position += _maximizeRestore->width();
break;
case Control::Close:
if (right) {
_close->moveToRight(position, 0);
} else {
_close->moveToLeft(position, 0);
}
position += _close->width();
break;
}
}
}
void TitleWidgetQt::resizeEvent(QResizeEvent *e) {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "window/window_title.h"
#include "window/window_controls_layout.h"
#include "base/object_ptr.h"
namespace style {
@ -40,6 +41,9 @@ private:
void windowStateChanged(Qt::WindowState state = Qt::WindowNoState);
void updateButtonsState();
void updateControlsPosition();
void updateControlsPositionBySide(
const std::vector<Control> &controls,
bool right);
void toggleFramelessWindow(bool enabled);
Qt::Edges edgesFromPos(const QPoint &pos);