Skip to content

Commit ccbfcab

Browse files
committed
feat: add border and shadow support for TreeLand windows
Implement border width/color and shadow radius/offset/color for TreeLand platform windows. Refactor the personalization window protocol to use a unified dirty-flag schedule/apply pattern instead of immediate per- feature calls. This ensures all window decorations are applied together after surface creation or property changes. Log: Added window border and shadow customization for TreeLand Influence: 1. Test setting border width and color, verify visual appearance 2. Test setting shadow radius, offset, and color, verify correct rendering 3. Test enabling/disabling no-titlebar mode with borders and shadows 4. Verify that changing multiple properties at once triggers correct apply 5. Test window resize and surface recreation scenarios for persistence 6. Verify API backward compatibility: existing radius and blur functions still work feat: 为 Treeland 窗口添加边框和阴影支持 实现边框宽度/颜色和阴影半径/偏移/颜色。重构个性化窗口协议,使用统一的脏 标志调度/应用模式替代旧的即时逐特性调用。确保所有窗口装饰在表面创建或属 性更改后一起应用。 Log: 新增窗口边框和阴影定制功能 Influence: 1. 测试设置边框宽度和颜色,验证视觉效果 2. 测试设置阴影半径、偏移和颜色,验证正确渲染 3. 测试在启用/禁用无标题栏模式下边框和阴影的表现 4. 验证同时更改多个属性会触发正确的应用 5. 测试窗口大小变化和表面重建场景的持久性 6. 验证 API 向后兼容性:原有的圆角和模糊功能仍然正常工作
1 parent ceaea6a commit ccbfcab

2 files changed

Lines changed: 226 additions & 61 deletions

File tree

src/plugins/platform/treeland/dtreelandplatformwindowinterface.cpp

Lines changed: 165 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,8 @@ void DTreeLandPlatformWindowHelper::onActiveChanged()
264264

265265
void DTreeLandPlatformWindowHelper::onSurfaceCreated()
266266
{
267-
if (m_isNoTitlebar) {
268-
doSetEnabledNoTitlebar();
269-
}
270-
if (m_radius > 0) {
271-
doSetWindowRadius();
272-
}
273-
if (m_isWindowBlur) {
274-
doSetEnabledBlurWindow();
275-
}
267+
m_dirty = m_initialized;
268+
scheduleApply();
276269
}
277270

278271
void DTreeLandPlatformWindowHelper::onSurfaceDestroyed()
@@ -313,38 +306,87 @@ PersonalizationWindowContext *DTreeLandPlatformWindowHelper::windowContext() con
313306

314307
void DTreeLandPlatformWindowHelper::setEnabledNoTitlebar(bool enable)
315308
{
316-
m_isNoTitlebar = enable;
317-
doSetEnabledNoTitlebar();
309+
updateFeature(m_noTitlebar, enable, NoTitlebar);
318310
}
311+
319312
void DTreeLandPlatformWindowHelper::setWindowRadius(int windowRadius)
320313
{
321-
m_radius = windowRadius;
322-
doSetWindowRadius();
314+
updateFeature(m_radius, windowRadius, Radius);
315+
}
316+
317+
void DTreeLandPlatformWindowHelper::setBorderWidth(int borderWidth)
318+
{
319+
updateFeature(m_borderWidth, borderWidth, Border);
320+
}
321+
322+
void DTreeLandPlatformWindowHelper::setBorderColor(const QColor &borderColor)
323+
{
324+
updateFeature(m_borderColor, borderColor, Border);
323325
}
326+
327+
void DTreeLandPlatformWindowHelper::setShadowRadius(int shadowRadius)
328+
{
329+
updateFeature(m_shadowRadius, shadowRadius, Shadow);
330+
}
331+
332+
void DTreeLandPlatformWindowHelper::setShadowOffset(const QPoint &shadowOffset)
333+
{
334+
updateFeature(m_shadowOffset, shadowOffset, Shadow);
335+
}
336+
337+
void DTreeLandPlatformWindowHelper::setShadowColor(const QColor &shadowColor)
338+
{
339+
updateFeature(m_shadowColor, shadowColor, Shadow);
340+
}
341+
324342
void DTreeLandPlatformWindowHelper::setEnableBlurWindow(bool enableBlurWindow)
325343
{
326-
m_isWindowBlur = enableBlurWindow;
327-
doSetEnabledBlurWindow();
344+
updateFeature(m_blur, enableBlurWindow, Blur);
328345
}
329346

330-
void DTreeLandPlatformWindowHelper::doSetEnabledNoTitlebar()
347+
void DTreeLandPlatformWindowHelper::setPlatformHandle(DPlatformHandle *handle)
331348
{
332-
if (auto context = windowContext()) {
333-
context->set_titlebar(m_isNoTitlebar ? PersonalizationWindowContext::enable_mode_disable : PersonalizationWindowContext::enable_mode_enable);
334-
}
349+
m_platformHandle = handle;
335350
}
336351

337-
void DTreeLandPlatformWindowHelper::doSetWindowRadius()
352+
void DTreeLandPlatformWindowHelper::scheduleApply()
338353
{
339-
if (auto context = windowContext()) {
340-
context->set_round_corner_radius(m_radius);
341-
}
354+
if (m_applyScheduled)
355+
return;
356+
m_applyScheduled = true;
357+
QMetaObject::invokeMethod(this, &DTreeLandPlatformWindowHelper::applyPending, Qt::QueuedConnection);
342358
}
343359

344-
void DTreeLandPlatformWindowHelper::doSetEnabledBlurWindow()
360+
void DTreeLandPlatformWindowHelper::applyPending()
345361
{
362+
m_applyScheduled = false;
363+
346364
if (auto context = windowContext()) {
347-
context->set_blend_mode(m_isWindowBlur ? PersonalizationWindowContext::blend_mode_blur : PersonalizationWindowContext::blend_mode_transparent);
365+
if (m_dirty & NoTitlebar) {
366+
m_dirty &= ~NoTitlebar;
367+
context->set_titlebar(m_noTitlebar ? PersonalizationWindowContext::enable_mode_disable : PersonalizationWindowContext::enable_mode_enable);
368+
}
369+
if (m_dirty & Radius) {
370+
m_dirty &= ~Radius;
371+
context->set_round_corner_radius(m_radius);
372+
}
373+
if (m_dirty & Blur) {
374+
m_dirty &= ~Blur;
375+
context->set_blend_mode(m_blur ? PersonalizationWindowContext::blend_mode_blur : PersonalizationWindowContext::blend_mode_transparent);
376+
}
377+
if (m_dirty & Border) {
378+
m_dirty &= ~Border;
379+
context->set_border(m_borderWidth,
380+
m_borderColor.red(), m_borderColor.green(),
381+
m_borderColor.blue(), m_borderColor.alpha());
382+
}
383+
if (m_dirty & Shadow) {
384+
m_dirty &= ~Shadow;
385+
context->set_shadow(m_shadowRadius,
386+
m_shadowOffset.x(), m_shadowOffset.y(),
387+
m_shadowColor.red(), m_shadowColor.green(),
388+
m_shadowColor.blue(), m_shadowColor.alpha());
389+
}
348390
}
349391
}
350392

@@ -355,6 +397,9 @@ DTreeLandPlatformWindowInterface::DTreeLandPlatformWindowInterface(QWindow *wind
355397
if (!MoveWindowHelper::mapped.value(window)) {
356398
Q_UNUSED(new MoveWindowHelper(window))
357399
}
400+
if (auto helper = DTreeLandPlatformWindowHelper::get(window)) {
401+
helper->setPlatformHandle(platformHandle);
402+
}
358403
}
359404

360405
DTreeLandPlatformWindowInterface::~DTreeLandPlatformWindowInterface()
@@ -363,9 +408,7 @@ DTreeLandPlatformWindowInterface::~DTreeLandPlatformWindowInterface()
363408

364409
void DTreeLandPlatformWindowInterface::setEnabled(bool enabled)
365410
{
366-
if (setEnabledNoTitlebar(enabled)) {
367-
return;
368-
}
411+
setEnabledNoTitlebar(enabled);
369412
}
370413

371414
bool DTreeLandPlatformWindowInterface::isEnabled() const
@@ -375,56 +418,129 @@ bool DTreeLandPlatformWindowInterface::isEnabled() const
375418

376419
bool DTreeLandPlatformWindowInterface::isEnabledNoTitlebar() const
377420
{
378-
return m_isNoTitlebar;
421+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
422+
return helper->isEnabledNoTitlebar();
423+
return false;
379424
}
380425

381426
bool DTreeLandPlatformWindowInterface::setEnabledNoTitlebar(bool enable)
382427
{
383-
if (m_isNoTitlebar == enable) {
384-
return true;
385-
}
386-
m_isNoTitlebar = enable;
387428
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
388429
helper->setEnabledNoTitlebar(enable);
430+
return true;
389431
}
390-
return true;
432+
return false;
391433
}
392434

393435
int DTreeLandPlatformWindowInterface::windowRadius() const
394436
{
395-
return m_radius;
437+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
438+
return helper->windowRadius();
439+
return 0;
396440
}
397441

398442
void DTreeLandPlatformWindowInterface::setWindowRadius(int windowRadius)
399443
{
400-
if (m_radius == windowRadius) {
401-
return;
444+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
445+
helper->setWindowRadius(windowRadius);
446+
if (m_platformHandle)
447+
Q_EMIT m_platformHandle->windowRadiusChanged();
402448
}
403-
m_radius = windowRadius;
449+
}
450+
451+
int DTreeLandPlatformWindowInterface::borderWidth() const
452+
{
453+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
454+
return helper->borderWidth();
455+
return 0;
456+
}
457+
458+
void DTreeLandPlatformWindowInterface::setBorderWidth(int borderWidth)
459+
{
460+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
461+
helper->setBorderWidth(borderWidth);
462+
if (m_platformHandle)
463+
Q_EMIT m_platformHandle->borderWidthChanged();
464+
}
465+
}
466+
467+
QColor DTreeLandPlatformWindowInterface::borderColor() const
468+
{
469+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
470+
return helper->borderColor();
471+
return {};
472+
}
473+
474+
void DTreeLandPlatformWindowInterface::setBorderColor(const QColor &borderColor)
475+
{
404476
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
405-
helper->setWindowRadius(m_radius);
477+
helper->setBorderColor(borderColor);
478+
if (m_platformHandle)
479+
Q_EMIT m_platformHandle->borderColorChanged();
406480
}
407-
if (m_platformHandle) {
408-
Q_EMIT m_platformHandle->windowRadiusChanged();
481+
}
482+
483+
int DTreeLandPlatformWindowInterface::shadowRadius() const
484+
{
485+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
486+
return helper->shadowRadius();
487+
return 0;
488+
}
489+
490+
void DTreeLandPlatformWindowInterface::setShadowRadius(int shadowRadius)
491+
{
492+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
493+
helper->setShadowRadius(shadowRadius);
494+
if (m_platformHandle)
495+
Q_EMIT m_platformHandle->shadowRadiusChanged();
496+
}
497+
}
498+
499+
QPoint DTreeLandPlatformWindowInterface::shadowOffset() const
500+
{
501+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
502+
return helper->shadowOffset();
503+
return {};
504+
}
505+
506+
void DTreeLandPlatformWindowInterface::setShadowOffset(const QPoint &shadowOffset)
507+
{
508+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
509+
helper->setShadowOffset(shadowOffset);
510+
if (m_platformHandle)
511+
Q_EMIT m_platformHandle->shadowOffsetChanged();
512+
}
513+
}
514+
515+
QColor DTreeLandPlatformWindowInterface::shadowColor() const
516+
{
517+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
518+
return helper->shadowColor();
519+
return {};
520+
}
521+
522+
void DTreeLandPlatformWindowInterface::setShadowColor(const QColor &shadowColor)
523+
{
524+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
525+
helper->setShadowColor(shadowColor);
526+
if (m_platformHandle)
527+
Q_EMIT m_platformHandle->shadowColorChanged();
409528
}
410529
}
411530

412531
bool DTreeLandPlatformWindowInterface::enableBlurWindow() const
413532
{
414-
return m_isWindowBlur;
533+
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window))
534+
return helper->enableBlurWindow();
535+
return false;
415536
}
416537

417538
void DTreeLandPlatformWindowInterface::setEnableBlurWindow(bool enable)
418539
{
419-
if (m_isWindowBlur == enable) {
420-
return;
421-
}
422-
m_isWindowBlur = enable;
423540
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
424541
helper->setEnableBlurWindow(enable);
425-
}
426-
if (m_platformHandle) {
427-
Q_EMIT m_platformHandle->enableBlurWindowChanged();
542+
if (m_platformHandle)
543+
Q_EMIT m_platformHandle->enableBlurWindowChanged();
428544
}
429545
}
430546
DGUI_END_NAMESPACE

0 commit comments

Comments
 (0)