From a86a7e7b3cae90893de1280b3c886c80cb56c116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 11 Sep 2015 13:31:41 +0200 Subject: [PATCH] Add a placement strategy for transient ShellClients A transient ShellClient has an offset position to the parent surface. Use this to position the ShellClient properly. This fixes the random placement of menus. --- abstract_client.cpp | 10 ++++++++++ abstract_client.h | 9 +++++++++ placement.cpp | 8 ++++++++ placement.h | 1 + shell_client.cpp | 10 ++++++++++ shell_client.h | 2 ++ 6 files changed, 40 insertions(+) diff --git a/abstract_client.cpp b/abstract_client.cpp index a1c66a710e..0fde7e0d12 100644 --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -812,4 +812,14 @@ AbstractClient *AbstractClient::transientFor() return m_transientFor; } +bool AbstractClient::hasTransientPlacementHint() const +{ + return false; +} + +QPoint AbstractClient::transientPlacementHint() const +{ + return QPoint(); +} + } diff --git a/abstract_client.h b/abstract_client.h index 3bdee8c170..993e6597fe 100644 --- a/abstract_client.h +++ b/abstract_client.h @@ -247,6 +247,15 @@ public: // TODO: remove boolean trap virtual AbstractClient *findModal(bool allow_itself = false) = 0; virtual bool isTransient() const; + /** + * @returns Whether there is a hint available to place the AbstractClient on it's parent, default @c false. + * @see transientPlacementHint + **/ + virtual bool hasTransientPlacementHint() const; + /** + * @returns The recommended position of the transient in parent coordinates + **/ + virtual QPoint transientPlacementHint() const; const AbstractClient* transientFor() const; AbstractClient* transientFor(); /** diff --git a/placement.cpp b/placement.cpp index ff1a06b095..1b4873fe09 100644 --- a/placement.cpp +++ b/placement.cpp @@ -72,6 +72,8 @@ void Placement::place(AbstractClient* c, QRect& area) placeOnMainWindow(c, area); // on mainwindow, if any, otherwise centered else if (c->isOnScreenDisplay() || c->isNotification()) placeOnScreenDisplay(c, area); + else if (c->isTransient() && c->hasTransientPlacementHint()) + placeTransient(c); else place(c, area, options->placement()); } @@ -492,6 +494,12 @@ void Placement::placeOnScreenDisplay(AbstractClient* c, QRect& area) c->move(QPoint(x, y)); } +void Placement::placeTransient(AbstractClient *c) +{ + // TODO: apply sanity checks? + c->move(c->transientFor()->pos() + c->transientPlacementHint()); +} + void Placement::placeDialog(AbstractClient* c, QRect& area, Policy nextPlacement) { placeOnMainWindow(c, area, nextPlacement); diff --git a/placement.h b/placement.h index 87c1dfa052..f50f35c012 100644 --- a/placement.h +++ b/placement.h @@ -92,6 +92,7 @@ private: void place(AbstractClient* c, QRect& area, Policy policy, Policy nextPlacement = Unknown); void placeUnderMouse(AbstractClient* c, QRect& area, Policy next = Unknown); void placeOnMainWindow(AbstractClient* c, QRect& area, Policy next = Unknown); + void placeTransient(AbstractClient *c); QRect checkArea(const AbstractClient*c, const QRect& area); //CT needed for cascading+ diff --git a/shell_client.cpp b/shell_client.cpp index 975ae473e0..beef5c2ca3 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -726,4 +726,14 @@ void ShellClient::setTransient() setTransientFor(waylandServer()->findClient(s.data())); } +bool ShellClient::hasTransientPlacementHint() const +{ + return isTransient() && transientFor() != nullptr; +} + +QPoint ShellClient::transientPlacementHint() const +{ + return m_shellSurface->transientOffset(); +} + } diff --git a/shell_client.h b/shell_client.h index 32f70a8c28..cf770531ad 100644 --- a/shell_client.h +++ b/shell_client.h @@ -112,6 +112,8 @@ public: bool isInitialPositionSet() const; bool isTransient() const override; + bool hasTransientPlacementHint() const override; + QPoint transientPlacementHint() const override; protected: void addDamage(const QRegion &damage) override;