53
53
#include < NETWM>
54
54
#include < KWindowInfo>
55
55
56
+ #include < LayerShellQt/Window>
57
+
56
58
// Turn on this to show the time required to load each plugin during startup
57
59
// #define DEBUG_PLUGIN_LOADTIME
58
60
#ifdef DEBUG_PLUGIN_LOADTIME
@@ -141,6 +143,7 @@ LXQtPanel::LXQtPanel(const QString &configGroup, LXQt::Settings *settings, QWidg
141
143
mAnimationTime(0 ),
142
144
mReserveSpace(true ),
143
145
mAnimation(nullptr ),
146
+ mLayerWindow(nullptr ),
144
147
mLockPanel(false )
145
148
{
146
149
// You can find information about the flags and widget attributes in your
@@ -230,6 +233,37 @@ LXQtPanel::LXQtPanel(const QString &configGroup, LXQt::Settings *settings, QWidg
230
233
231
234
loadPlugins ();
232
235
236
+ if (qGuiApp->nativeInterface <QNativeInterface::QWaylandApplication>())
237
+ {
238
+ // Create backing QWindow for LayerShellQt integration
239
+ create ();
240
+
241
+ if (!windowHandle ())
242
+ {
243
+ qWarning () << " LXQtPanel: could not create QWindow for LayerShellQt integration." ;
244
+ }
245
+ else
246
+ {
247
+ // Init Layer Shell (Must be done before showing widget)
248
+ mLayerWindow = LayerShellQt::Window::get (windowHandle ());
249
+ mLayerWindow ->setLayer (LayerShellQt::Window::LayerTop);
250
+
251
+ mLayerWindow ->setScope (QStringLiteral (" dock" ));
252
+
253
+ LayerShellQt::Window::Anchors anchors;
254
+ anchors.setFlag (LayerShellQt::Window::AnchorLeft);
255
+ anchors.setFlag (LayerShellQt::Window::AnchorBottom);
256
+ anchors.setFlag (LayerShellQt::Window::AnchorRight);
257
+ mLayerWindow ->setAnchors (anchors);
258
+
259
+ mLayerWindow ->setKeyboardInteractivity (LayerShellQt::Window::KeyboardInteractivityOnDemand);
260
+ mLayerWindow ->setCloseOnDismissed (false );
261
+
262
+ mLayerWindow ->setExclusiveEdge (LayerShellQt::Window::AnchorBottom);
263
+ mLayerWindow ->setExclusiveZone (height ());
264
+ }
265
+ }
266
+
233
267
// NOTE: Some (X11) WMs may need the geometry to be set before QWidget::show().
234
268
setPanelGeometry ();
235
269
@@ -479,6 +513,8 @@ void LXQtPanel::setPanelGeometry(bool animate)
479
513
const QRect currentScreen = screens.at (mActualScreenNum )->geometry ();
480
514
481
515
QRect rect;
516
+ LayerShellQt::Window::Anchors anchors;
517
+ LayerShellQt::Window::Anchor edge = LayerShellQt::Window::AnchorBottom;
482
518
483
519
if (isHorizontal ())
484
520
{
@@ -500,6 +536,7 @@ void LXQtPanel::setPanelGeometry(bool animate)
500
536
switch (mAlignment )
501
537
{
502
538
case LXQtPanel::AlignmentLeft:
539
+ anchors.setFlag (LayerShellQt::Window::AnchorLeft);
503
540
rect.moveLeft (currentScreen.left ());
504
541
break ;
505
542
@@ -508,20 +545,34 @@ void LXQtPanel::setPanelGeometry(bool animate)
508
545
break ;
509
546
510
547
case LXQtPanel::AlignmentRight:
548
+ anchors.setFlag (LayerShellQt::Window::AnchorRight);
511
549
rect.moveRight (currentScreen.right ());
512
550
break ;
513
551
}
514
552
553
+ if (lengthInPercents () && mLength == 100 )
554
+ {
555
+ // Fill all available width
556
+ anchors.setFlag (LayerShellQt::Window::AnchorLeft);
557
+ anchors.setFlag (LayerShellQt::Window::AnchorRight);
558
+ }
559
+
515
560
// Vert .......................
516
561
if (mPosition == ILXQtPanel::PositionTop)
517
562
{
563
+ anchors.setFlag (LayerShellQt::Window::AnchorTop);
564
+ edge = LayerShellQt::Window::AnchorTop;
565
+
518
566
if (mHidden )
519
567
rect.moveBottom (currentScreen.top () + PANEL_HIDE_SIZE - 1 );
520
568
else
521
569
rect.moveTop (currentScreen.top ());
522
570
}
523
571
else
524
572
{
573
+ anchors.setFlag (LayerShellQt::Window::AnchorBottom);
574
+ edge = LayerShellQt::Window::AnchorBottom;
575
+
525
576
if (mHidden )
526
577
rect.moveTop (currentScreen.bottom () - PANEL_HIDE_SIZE + 1 );
527
578
else
@@ -548,6 +599,7 @@ void LXQtPanel::setPanelGeometry(bool animate)
548
599
switch (mAlignment )
549
600
{
550
601
case LXQtPanel::AlignmentLeft:
602
+ anchors.setFlag (LayerShellQt::Window::AnchorTop);
551
603
rect.moveTop (currentScreen.top ());
552
604
break ;
553
605
@@ -556,26 +608,50 @@ void LXQtPanel::setPanelGeometry(bool animate)
556
608
break ;
557
609
558
610
case LXQtPanel::AlignmentRight:
611
+ anchors.setFlag (LayerShellQt::Window::AnchorBottom);
559
612
rect.moveBottom (currentScreen.bottom ());
560
613
break ;
561
614
}
562
615
616
+ if (lengthInPercents () && mLength == 100 )
617
+ {
618
+ // Fill all available width
619
+ anchors.setFlag (LayerShellQt::Window::AnchorTop);
620
+ anchors.setFlag (LayerShellQt::Window::AnchorBottom);
621
+ }
622
+
563
623
// Horiz ......................
564
624
if (mPosition == ILXQtPanel::PositionLeft)
565
625
{
626
+ anchors.setFlag (LayerShellQt::Window::AnchorLeft);
627
+ edge = LayerShellQt::Window::AnchorLeft;
628
+
566
629
if (mHidden )
567
630
rect.moveRight (currentScreen.left () + PANEL_HIDE_SIZE - 1 );
568
631
else
569
632
rect.moveLeft (currentScreen.left ());
570
633
}
571
634
else
572
635
{
636
+ anchors.setFlag (LayerShellQt::Window::AnchorRight);
637
+ edge = LayerShellQt::Window::AnchorRight;
638
+
573
639
if (mHidden )
574
640
rect.moveLeft (currentScreen.right () - PANEL_HIDE_SIZE + 1 );
575
641
else
576
642
rect.moveRight (currentScreen.right ());
577
643
}
578
644
}
645
+
646
+ if (mLayerWindow )
647
+ {
648
+ mLayerWindow ->setAnchors (anchors);
649
+ mLayerWindow ->setExclusiveEdge (edge);
650
+
651
+ // Make LayerShell apply changes immediatly
652
+ windowHandle ()->requestUpdate ();
653
+ }
654
+
579
655
if (!mHidden || !mGeometry .isValid ()) mGeometry = rect;
580
656
if (rect != geometry ())
581
657
{
@@ -603,6 +679,37 @@ void LXQtPanel::setPanelGeometry(bool animate)
603
679
setGeometry (rect);
604
680
}
605
681
}
682
+
683
+ if (mLayerWindow )
684
+ {
685
+ // Emulate auto-hide on Wayland
686
+ // NOTE: we cannot move window out of screen so we make it smaller
687
+
688
+ // NOTE: a cleaner approach would be to use screen edge protocol
689
+ // but it's specific to KWin
690
+
691
+ if (mHidden && LXQtPanelWidget->isVisible ())
692
+ {
693
+ // Make it blank
694
+ LXQtPanelWidget->hide ();
695
+
696
+ // And make it small
697
+ if (isHorizontal ())
698
+ resize (rect.width (), PANEL_HIDE_SIZE);
699
+ else
700
+ resize (PANEL_HIDE_SIZE, rect.height ());
701
+ }
702
+ else if (!mHidden && !LXQtPanelWidget->isVisible ())
703
+ {
704
+ // Restore contents
705
+ LXQtPanelWidget->show ();
706
+
707
+ // And make it big again
708
+ resize (rect.size ());
709
+ }
710
+
711
+ updateWmStrut ();
712
+ }
606
713
}
607
714
608
715
void LXQtPanel::setMargins ()
@@ -664,62 +771,104 @@ void LXQtPanel::updateWmStrut()
664
771
if (wid == 0 || !isVisible ())
665
772
return ;
666
773
667
- if ( mReserveSpace && QApplication::primaryScreen ())
774
+ if (qGuiApp-> nativeInterface <QNativeInterface::QX11Application> ())
668
775
{
669
- const QRect wholeScreen = QApplication::primaryScreen ()->virtualGeometry ();
670
- const QRect rect = geometry ();
671
- // NOTE: https://standards.freedesktop.org/wm-spec/wm-spec-latest.html
672
- // Quote from the EWMH spec: " Note that the strut is relative to the screen edge, and not the edge of the xinerama monitor."
673
- // So, we use the geometry of the whole screen to calculate the strut rather than using the geometry of individual monitors.
674
- // Though the spec only mention Xinerama and did not mention XRandR, the rule should still be applied.
675
- // At least openbox is implemented like this.
676
- switch (mPosition )
776
+ if (mReserveSpace && QApplication::primaryScreen ())
677
777
{
678
- case LXQtPanel::PositionTop:
679
- KX11Extras::setExtendedStrut (wid,
680
- /* Left */ 0 , 0 , 0 ,
681
- /* Right */ 0 , 0 , 0 ,
682
- /* Top */ rect.top () + getReserveDimension (), rect.left (), rect.right (),
683
- /* Bottom */ 0 , 0 , 0
684
- );
685
- break ;
778
+ const QRect wholeScreen = QApplication::primaryScreen ()->virtualGeometry ();
779
+ const QRect rect = geometry ();
780
+ // NOTE: https://standards.freedesktop.org/wm-spec/wm-spec-latest.html
781
+ // Quote from the EWMH spec: " Note that the strut is relative to the screen edge, and not the edge of the xinerama monitor."
782
+ // So, we use the geometry of the whole screen to calculate the strut rather than using the geometry of individual monitors.
783
+ // Though the spec only mention Xinerama and did not mention XRandR, the rule should still be applied.
784
+ // At least openbox is implemented like this.
785
+ switch (mPosition )
786
+ {
787
+ case LXQtPanel::PositionTop:
788
+ KX11Extras::setExtendedStrut (wid,
789
+ /* Left */ 0 , 0 , 0 ,
790
+ /* Right */ 0 , 0 , 0 ,
791
+ /* Top */ rect.top () + getReserveDimension (), rect.left (), rect.right (),
792
+ /* Bottom */ 0 , 0 , 0
793
+ );
794
+ break ;
686
795
687
- case LXQtPanel::PositionBottom:
688
- KX11Extras::setExtendedStrut (wid,
689
- /* Left */ 0 , 0 , 0 ,
690
- /* Right */ 0 , 0 , 0 ,
691
- /* Top */ 0 , 0 , 0 ,
692
- /* Bottom */ wholeScreen.bottom () - rect.bottom () + getReserveDimension (), rect.left (), rect.right ()
693
- );
694
- break ;
796
+ case LXQtPanel::PositionBottom:
797
+ KX11Extras::setExtendedStrut (wid,
798
+ /* Left */ 0 , 0 , 0 ,
799
+ /* Right */ 0 , 0 , 0 ,
800
+ /* Top */ 0 , 0 , 0 ,
801
+ /* Bottom */ wholeScreen.bottom () - rect.bottom () + getReserveDimension (), rect.left (), rect.right ()
802
+ );
803
+ break ;
695
804
696
- case LXQtPanel::PositionLeft:
697
- KX11Extras::setExtendedStrut (wid,
698
- /* Left */ rect.left () + getReserveDimension (), rect.top (), rect.bottom (),
699
- /* Right */ 0 , 0 , 0 ,
700
- /* Top */ 0 , 0 , 0 ,
701
- /* Bottom */ 0 , 0 , 0
702
- );
805
+ case LXQtPanel::PositionLeft:
806
+ KX11Extras::setExtendedStrut (wid,
807
+ /* Left */ rect.left () + getReserveDimension (), rect.top (), rect.bottom (),
808
+ /* Right */ 0 , 0 , 0 ,
809
+ /* Top */ 0 , 0 , 0 ,
810
+ /* Bottom */ 0 , 0 , 0
811
+ );
703
812
704
- break ;
813
+ break ;
705
814
706
- case LXQtPanel::PositionRight:
815
+ case LXQtPanel::PositionRight:
816
+ KX11Extras::setExtendedStrut (wid,
817
+ /* Left */ 0 , 0 , 0 ,
818
+ /* Right */ wholeScreen.right () - rect.right () + getReserveDimension (), rect.top (), rect.bottom (),
819
+ /* Top */ 0 , 0 , 0 ,
820
+ /* Bottom */ 0 , 0 , 0
821
+ );
822
+ break ;
823
+ }
824
+ } else
825
+ {
707
826
KX11Extras::setExtendedStrut (wid,
708
- /* Left */ 0 , 0 , 0 ,
709
- /* Right */ wholeScreen. right () - rect. right () + getReserveDimension (), rect. top (), rect. bottom () ,
710
- /* Top */ 0 , 0 , 0 ,
711
- /* Bottom */ 0 , 0 , 0
712
- );
713
- break ;
827
+ /* Left */ 0 , 0 , 0 ,
828
+ /* Right */ 0 , 0 , 0 ,
829
+ /* Top */ 0 , 0 , 0 ,
830
+ /* Bottom */ 0 , 0 , 0
831
+ );
832
+ }
714
833
}
715
- } else
834
+ else if ( mLayerWindow && qGuiApp-> nativeInterface <QNativeInterface::QWaylandApplication>())
716
835
{
717
- KX11Extras::setExtendedStrut (wid,
718
- /* Left */ 0 , 0 , 0 ,
719
- /* Right */ 0 , 0 , 0 ,
720
- /* Top */ 0 , 0 , 0 ,
721
- /* Bottom */ 0 , 0 , 0
722
- );
836
+ // TODO: duplicated code, also set in setPanelGeometry()
837
+
838
+ if (mReserveSpace )
839
+ {
840
+ LayerShellQt::Window::Anchor edge = LayerShellQt::Window::AnchorBottom;
841
+
842
+ switch (mPosition )
843
+ {
844
+ case LXQtPanel::PositionTop:
845
+ edge = LayerShellQt::Window::AnchorTop;
846
+ break ;
847
+
848
+ case LXQtPanel::PositionBottom:
849
+ edge = LayerShellQt::Window::AnchorBottom;
850
+ break ;
851
+
852
+ case LXQtPanel::PositionLeft:
853
+ edge = LayerShellQt::Window::AnchorLeft;
854
+ break ;
855
+
856
+ case LXQtPanel::PositionRight:
857
+ edge = LayerShellQt::Window::AnchorRight;
858
+ break ;
859
+ }
860
+
861
+ mLayerWindow ->setExclusiveEdge (edge);
862
+ mLayerWindow ->setExclusiveZone (getReserveDimension ());
863
+ }
864
+ else
865
+ {
866
+ mLayerWindow ->setExclusiveEdge (LayerShellQt::Window::AnchorNone);
867
+ mLayerWindow ->setExclusiveZone (0 );
868
+ }
869
+
870
+ // Make LayerShellQt apply changes immediatly
871
+ windowHandle ()->requestUpdate ();
723
872
}
724
873
}
725
874
0 commit comments