Allow fixed windows with custom title bar.
This commit is contained in:
		
							parent
							
								
									bc62f87f0e
								
							
						
					
					
						commit
						c0ce14bb68
					
				
					 11 changed files with 85 additions and 14 deletions
				
			
		| 
						 | 
					@ -20,7 +20,8 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	not_null<RpWidget*> body() override;
 | 
						not_null<RpWidget*> body() override;
 | 
				
			||||||
	void setTitle(const QString &title) override;
 | 
						void setTitle(const QString &title) override;
 | 
				
			||||||
	void setSizeMin(QSize size) override;
 | 
						void setMinimumSize(QSize size) override;
 | 
				
			||||||
 | 
						void setFixedSize(QSize size) override;
 | 
				
			||||||
	void setGeometry(QRect rect) override;
 | 
						void setGeometry(QRect rect) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -204,12 +204,18 @@ void WindowHelper::toggleCustomTitle(bool visible) {
 | 
				
			||||||
	_window->setWindowTitle(visible ? QString() : _title->text());
 | 
						_window->setWindowTitle(visible ? QString() : _title->text());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WindowHelper::setSizeMin(QSize size) {
 | 
					void WindowHelper::setMinimumSize(QSize size) {
 | 
				
			||||||
	_window->setMinimumSize(
 | 
						_window->setMinimumSize(
 | 
				
			||||||
		size.width(),
 | 
							size.width(),
 | 
				
			||||||
		(_title ? _title->height() : 0) + size.height());
 | 
							(_title ? _title->height() : 0) + size.height());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void WindowHelper::setFixedSize(QSize size) {
 | 
				
			||||||
 | 
						_window->setFixedSize(
 | 
				
			||||||
 | 
							size.width(),
 | 
				
			||||||
 | 
							(_title ? _title->height() : 0) + size.height());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WindowHelper::setGeometry(QRect rect) {
 | 
					void WindowHelper::setGeometry(QRect rect) {
 | 
				
			||||||
	_window->setGeometry(
 | 
						_window->setGeometry(
 | 
				
			||||||
		rect.marginsAdded({ 0, (_title ? _title->height() : 0), 0, 0 }));
 | 
							rect.marginsAdded({ 0, (_title ? _title->height() : 0), 0, 0 }));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,8 @@ class BasicWindowHelper {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	[[nodiscard]] virtual not_null<RpWidget*> body() = 0;
 | 
						[[nodiscard]] virtual not_null<RpWidget*> body() = 0;
 | 
				
			||||||
	virtual void setTitle(const QString &title) = 0;
 | 
						virtual void setTitle(const QString &title) = 0;
 | 
				
			||||||
	virtual void setSizeMin(QSize size) = 0;
 | 
						virtual void setMinimumSize(QSize size) = 0;
 | 
				
			||||||
 | 
						virtual void setFixedSize(QSize size) = 0;
 | 
				
			||||||
	virtual void setGeometry(QRect rect) = 0;
 | 
						virtual void setGeometry(QRect rect) = 0;
 | 
				
			||||||
	virtual ~BasicWindowHelper() = default;
 | 
						virtual ~BasicWindowHelper() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -514,6 +514,10 @@ void WindowShadow::updateWindow(int i, POINT *p, SIZE *s) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void WindowShadow::setResizeEnabled(bool enabled) {
 | 
				
			||||||
 | 
						_resizeEnabled = enabled;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LRESULT CALLBACK WindowShadow::WindowCallback(
 | 
					LRESULT CALLBACK WindowShadow::WindowCallback(
 | 
				
			||||||
		HWND hwnd,
 | 
							HWND hwnd,
 | 
				
			||||||
		UINT msg,
 | 
							UINT msg,
 | 
				
			||||||
| 
						 | 
					@ -540,6 +544,9 @@ LRESULT WindowShadow::windowCallback(
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case WM_NCHITTEST: {
 | 
						case WM_NCHITTEST: {
 | 
				
			||||||
 | 
							if (!_resizeEnabled) {
 | 
				
			||||||
 | 
								return HTTRANSPARENT;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		const auto xPos = GET_X_LPARAM(lParam);
 | 
							const auto xPos = GET_X_LPARAM(lParam);
 | 
				
			||||||
		const auto yPos = GET_Y_LPARAM(lParam);
 | 
							const auto yPos = GET_Y_LPARAM(lParam);
 | 
				
			||||||
		if (hwnd == _handles[0]) {
 | 
							if (hwnd == _handles[0]) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,7 @@ public:
 | 
				
			||||||
	void setColor(QColor color);
 | 
						void setColor(QColor color);
 | 
				
			||||||
	void update(Changes changes, WINDOWPOS *pos = nullptr);
 | 
						void update(Changes changes, WINDOWPOS *pos = nullptr);
 | 
				
			||||||
	void updateWindow(int i, POINT *p, SIZE *s = nullptr);
 | 
						void updateWindow(int i, POINT *p, SIZE *s = nullptr);
 | 
				
			||||||
 | 
						void setResizeEnabled(bool enabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	enum class Direction {
 | 
						enum class Direction {
 | 
				
			||||||
| 
						 | 
					@ -90,6 +91,7 @@ private:
 | 
				
			||||||
	std::vector<BYTE> _colors;
 | 
						std::vector<BYTE> _colors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool _hidden = true;
 | 
						bool _hidden = true;
 | 
				
			||||||
 | 
						bool _resizeEnabled = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	HWND _handles[4] = { nullptr };
 | 
						HWND _handles[4] = { nullptr };
 | 
				
			||||||
	HDC _contexts[4] = { nullptr };
 | 
						HDC _contexts[4] = { nullptr };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,11 @@ not_null<RpWidget*> TitleWidget::window() const {
 | 
				
			||||||
	return static_cast<RpWidget*>(parentWidget());
 | 
						return static_cast<RpWidget*>(parentWidget());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TitleWidget::setResizeEnabled(bool enabled) {
 | 
				
			||||||
 | 
						_resizeEnabled = enabled;
 | 
				
			||||||
 | 
						updateControlsVisibility();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidget::init() {
 | 
					void TitleWidget::init() {
 | 
				
			||||||
	_minimize->setClickedCallback([=] {
 | 
						_minimize->setClickedCallback([=] {
 | 
				
			||||||
		window()->setWindowState(Qt::WindowMinimized);
 | 
							window()->setWindowState(Qt::WindowMinimized);
 | 
				
			||||||
| 
						 | 
					@ -85,7 +90,10 @@ void TitleWidget::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
void TitleWidget::updateControlsPosition() {
 | 
					void TitleWidget::updateControlsPosition() {
 | 
				
			||||||
	auto right = 0;
 | 
						auto right = 0;
 | 
				
			||||||
	_close->moveToRight(right, 0); right += _close->width();
 | 
						_close->moveToRight(right, 0); right += _close->width();
 | 
				
			||||||
	_maximizeRestore->moveToRight(right, 0); right += _maximizeRestore->width();
 | 
						_maximizeRestore->moveToRight(right, 0);
 | 
				
			||||||
 | 
						if (_resizeEnabled) {
 | 
				
			||||||
 | 
							right += _maximizeRestore->width();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	_minimize->moveToRight(right, 0);
 | 
						_minimize->moveToRight(right, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,6 +103,7 @@ void TitleWidget::resizeEvent(QResizeEvent *e) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidget::updateControlsVisibility() {
 | 
					void TitleWidget::updateControlsVisibility() {
 | 
				
			||||||
 | 
						_maximizeRestore->setVisible(_resizeEnabled);
 | 
				
			||||||
	updateControlsPosition();
 | 
						updateControlsPosition();
 | 
				
			||||||
	update();
 | 
						update();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,8 @@ public:
 | 
				
			||||||
	explicit TitleWidget(not_null<RpWidget*> parent);
 | 
						explicit TitleWidget(not_null<RpWidget*> parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setText(const QString &text);
 | 
						void setText(const QString &text);
 | 
				
			||||||
	HitTestResult hitTest(QPoint point) const;
 | 
						[[nodiscard]] HitTestResult hitTest(QPoint point) const;
 | 
				
			||||||
 | 
						void setResizeEnabled(bool enabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
	void paintEvent(QPaintEvent *e) override;
 | 
						void paintEvent(QPaintEvent *e) override;
 | 
				
			||||||
| 
						 | 
					@ -61,6 +62,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool _maximizedState = false;
 | 
						bool _maximizedState = false;
 | 
				
			||||||
	bool _activeState = false;
 | 
						bool _activeState = false;
 | 
				
			||||||
 | 
						bool _resizeEnabled = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,10 +99,16 @@ void WindowHelper::setTitle(const QString &title) {
 | 
				
			||||||
	_window->setWindowTitle(title);
 | 
						_window->setWindowTitle(title);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WindowHelper::setSizeMin(QSize size) {
 | 
					void WindowHelper::setMinimumSize(QSize size) {
 | 
				
			||||||
	_window->setMinimumSize(size.width(), _title->height() + size.height());
 | 
						_window->setMinimumSize(size.width(), _title->height() + size.height());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void WindowHelper::setFixedSize(QSize size) {
 | 
				
			||||||
 | 
						_window->setFixedSize(size.width(), _title->height() + size.height());
 | 
				
			||||||
 | 
						_title->setResizeEnabled(false);
 | 
				
			||||||
 | 
						_shadow.setResizeEnabled(false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WindowHelper::setGeometry(QRect rect) {
 | 
					void WindowHelper::setGeometry(QRect rect) {
 | 
				
			||||||
	_window->setGeometry(rect.marginsAdded({ 0, _title->height(), 0, 0 }));
 | 
						_window->setGeometry(rect.marginsAdded({ 0, _title->height(), 0, 0 }));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -133,10 +139,20 @@ void WindowHelper::init() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_menu = GetSystemMenu(_handle, FALSE);
 | 
						_menu = GetSystemMenu(_handle, FALSE);
 | 
				
			||||||
	updateSystemMenu();
 | 
						updateSystemMenu();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto handleStateChanged = [=](Qt::WindowState state) {
 | 
				
			||||||
 | 
							updateSystemMenu(state);
 | 
				
			||||||
 | 
							if (fixedSize() && (state & Qt::WindowMaximized)) {
 | 
				
			||||||
 | 
								crl::on_main(_window.get(), [=] {
 | 
				
			||||||
 | 
									_window->setWindowState(
 | 
				
			||||||
 | 
										_window->windowState() & ~Qt::WindowMaximized);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	Ui::Connect(
 | 
						Ui::Connect(
 | 
				
			||||||
		_window->windowHandle(),
 | 
							_window->windowHandle(),
 | 
				
			||||||
		&QWindow::windowStateChanged,
 | 
							&QWindow::windowStateChanged,
 | 
				
			||||||
		[=](Qt::WindowState state) { updateSystemMenu(state); });
 | 
							handleStateChanged);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool WindowHelper::handleNativeEvent(
 | 
					bool WindowHelper::handleNativeEvent(
 | 
				
			||||||
| 
						 | 
					@ -189,6 +205,16 @@ bool WindowHelper::handleNativeEvent(
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case WM_NCLBUTTONDBLCLK:
 | 
				
			||||||
 | 
						case WM_NCMBUTTONDBLCLK:
 | 
				
			||||||
 | 
						case WM_NCRBUTTONDBLCLK:
 | 
				
			||||||
 | 
						case WM_NCXBUTTONDBLCLK: {
 | 
				
			||||||
 | 
							if (!fixedSize()) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (result) *result = 0;
 | 
				
			||||||
 | 
						} return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case WM_NCACTIVATE: {
 | 
						case WM_NCACTIVATE: {
 | 
				
			||||||
		if (IsCompositionEnabled()) {
 | 
							if (IsCompositionEnabled()) {
 | 
				
			||||||
			const auto res = DefWindowProc(_handle, msg, wParam, -1);
 | 
								const auto res = DefWindowProc(_handle, msg, wParam, -1);
 | 
				
			||||||
| 
						 | 
					@ -288,7 +314,7 @@ bool WindowHelper::handleNativeEvent(
 | 
				
			||||||
	} return true;
 | 
						} return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case WM_SYSCOMMAND: {
 | 
						case WM_SYSCOMMAND: {
 | 
				
			||||||
		if (wParam == SC_MOUSEMENU) {
 | 
							if (wParam == SC_MOUSEMENU && !fixedSize()) {
 | 
				
			||||||
			POINTS p = MAKEPOINTS(lParam);
 | 
								POINTS p = MAKEPOINTS(lParam);
 | 
				
			||||||
			updateSystemMenu(_window->windowHandle()->windowState());
 | 
								updateSystemMenu(_window->windowHandle()->windowState());
 | 
				
			||||||
			TrackPopupMenu(
 | 
								TrackPopupMenu(
 | 
				
			||||||
| 
						 | 
					@ -313,7 +339,9 @@ bool WindowHelper::handleNativeEvent(
 | 
				
			||||||
			_window->setWindowState(Qt::WindowMinimized);
 | 
								_window->setWindowState(Qt::WindowMinimized);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		case SC_MAXIMIZE:
 | 
							case SC_MAXIMIZE:
 | 
				
			||||||
 | 
								if (!fixedSize()) {
 | 
				
			||||||
				_window->setWindowState(Qt::WindowMaximized);
 | 
									_window->setWindowState(Qt::WindowMaximized);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		case SC_RESTORE:
 | 
							case SC_RESTORE:
 | 
				
			||||||
			_window->setWindowState(Qt::WindowNoState);
 | 
								_window->setWindowState(Qt::WindowNoState);
 | 
				
			||||||
| 
						 | 
					@ -325,6 +353,10 @@ bool WindowHelper::handleNativeEvent(
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool WindowHelper::fixedSize() const {
 | 
				
			||||||
 | 
						return _window->minimumSize() == _window->maximumSize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WindowHelper::updateMargins() {
 | 
					void WindowHelper::updateMargins() {
 | 
				
			||||||
	if (_updatingMargins) return;
 | 
						if (_updatingMargins) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,8 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	not_null<RpWidget*> body() override;
 | 
						not_null<RpWidget*> body() override;
 | 
				
			||||||
	void setTitle(const QString &title) override;
 | 
						void setTitle(const QString &title) override;
 | 
				
			||||||
	void setSizeMin(QSize size) override;
 | 
						void setMinimumSize(QSize size) override;
 | 
				
			||||||
 | 
						void setFixedSize(QSize size) override;
 | 
				
			||||||
	void setGeometry(QRect rect) override;
 | 
						void setGeometry(QRect rect) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					@ -39,6 +40,7 @@ private:
 | 
				
			||||||
		WPARAM wParam,
 | 
							WPARAM wParam,
 | 
				
			||||||
		LPARAM lParam,
 | 
							LPARAM lParam,
 | 
				
			||||||
		LRESULT *result);
 | 
							LRESULT *result);
 | 
				
			||||||
 | 
						[[nodiscard]] bool fixedSize() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static not_null<NativeFilter*> GetNativeFilter();
 | 
						static not_null<NativeFilter*> GetNativeFilter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,11 +34,19 @@ void Window::setTitle(const QString &title) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Window::setSizeMin(QSize size) {
 | 
					void Window::setMinimumSize(QSize size) {
 | 
				
			||||||
	if (_helper) {
 | 
						if (_helper) {
 | 
				
			||||||
		_helper->setSizeMin(size);
 | 
							_helper->setMinimumSize(size);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		setMinimumSize(size);
 | 
							RpWidget::setMinimumSize(size);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Window::setFixedSize(QSize size) {
 | 
				
			||||||
 | 
						if (_helper) {
 | 
				
			||||||
 | 
							_helper->setFixedSize(size);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							RpWidget::setFixedSize(size);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,8 @@ public:
 | 
				
			||||||
	[[nodiscard]] not_null<const RpWidget*> body() const;
 | 
						[[nodiscard]] not_null<const RpWidget*> body() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setTitle(const QString &title);
 | 
						void setTitle(const QString &title);
 | 
				
			||||||
	void setSizeMin(QSize size);
 | 
						void setMinimumSize(QSize size);
 | 
				
			||||||
 | 
						void setFixedSize(QSize size);
 | 
				
			||||||
	void setGeometry(QRect rect);
 | 
						void setGeometry(QRect rect);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue