Lomiri
TopLevelWindowModel Class Reference

A model of top-level surfaces. More...

#include <plugins/WindowManager/TopLevelWindowModel.h>

Inherits QAbstractListModel.

Public Types

enum  Roles { WindowRole = Qt::UserRole , ApplicationRole = Qt::UserRole + 1 }
 The Roles supported by the model. More...
 

Signals

void countChanged ()
 
void inputMethodSurfaceChanged (lomiri::shell::application::MirSurfaceInterface *inputMethodSurface)
 
void focusedWindowChanged (Window *focusedWindow)
 
void listChanged ()
 Emitted when the list changes. More...
 
void closedAllWindows ()
 
void rootFocusChanged ()
 

Public Member Functions

 TopLevelWindowModel (Workspace *workspace)
 
int rowCount (const QModelIndex &parent=QModelIndex()) const override
 
QVariant data (const QModelIndex &index, int role) const override
 
QHash< int, QByteArray > roleNames () const override
 
lomiri::shell::application::MirSurfaceInterface * inputMethodSurface () const
 
WindowfocusedWindow () const
 
int nextId () const
 
Q_INVOKABLE lomiri::shell::application::MirSurfaceInterface * surfaceAt (int index) const
 Returns the surface at the given index. More...
 
Q_INVOKABLE WindowwindowAt (int index) const
 Returns the window at the given index. More...
 
Q_INVOKABLE lomiri::shell::application::ApplicationInfoInterface * applicationAt (int index) const
 Returns the application at the given index. More...
 
Q_INVOKABLE int idAt (int index) const
 Returns the unique id of the element at the given index. More...
 
Q_INVOKABLE int indexForId (int id) const
 Returns the index where the row with the given id is located. More...
 
Q_INVOKABLE void raiseId (int id)
 Raises the row with the given id to the top of the window stack (index == count-1) More...
 
Q_INVOKABLE void closeAllWindows ()
 Closes all windows, emits closedAllWindows when done. More...
 
Q_INVOKABLE void pendingActivation ()
 Sets pending activation flag. More...
 
void setApplicationManager (lomiri::shell::application::ApplicationManagerInterface *)
 
void setSurfaceManager (lomiri::shell::application::SurfaceManagerInterface *)
 
void setRootFocus (bool focus)
 
bool rootFocus ()
 

Properties

int count
 Number of top-level surfaces in this model. More...
 
lomiri::shell::application::MirSurfaceInterface * inputMethodSurface
 The input method surface, if any. More...
 
WindowfocusedWindow
 The currently focused window, if any. More...
 
int nextId
 
bool rootFocus
 Sets whether a user Window or "nothing" should be focused. More...
 

Detailed Description

A model of top-level surfaces.

It's an abstraction of top-level application windows.

When an entry first appears, it normaly doesn't have a surface yet, meaning that the application is still starting up. A shell should then display a splash screen or saved screenshot of the application until its surface comes up.

As applications can have multiple surfaces and you can also have entries without surfaces at all, the only way to unambiguously refer to an entry in this model is through its id.

Definition at line 59 of file TopLevelWindowModel.h.

Member Enumeration Documentation

◆ Roles

The Roles supported by the model.

WindowRole - A Window. ApplicationRole - An ApplicationInfoInterface

Definition at line 116 of file TopLevelWindowModel.h.

116 {
117 WindowRole = Qt::UserRole,
118 ApplicationRole = Qt::UserRole + 1,
119 };

Constructor & Destructor Documentation

◆ TopLevelWindowModel()

TopLevelWindowModel::TopLevelWindowModel ( Workspace *  workspace)

Definition at line 43 of file TopLevelWindowModel.cpp.

44 : m_nullWindow(createWindow(nullptr)),
45 m_workspace(workspace),
46 m_surfaceManagerBusy(false)
47{
48 connect(WindowManagerObjects::instance(), &WindowManagerObjects::applicationManagerChanged,
49 this, &TopLevelWindowModel::setApplicationManager);
50 connect(WindowManagerObjects::instance(), &WindowManagerObjects::surfaceManagerChanged,
51 this, &TopLevelWindowModel::setSurfaceManager);
52
53 setApplicationManager(WindowManagerObjects::instance()->applicationManager());
54 setSurfaceManager(WindowManagerObjects::instance()->surfaceManager());
55
56 connect(m_nullWindow, &Window::focusedChanged, this, [this] {
57 Q_EMIT rootFocusChanged();
58 });
59}

◆ ~TopLevelWindowModel()

TopLevelWindowModel::~TopLevelWindowModel ( )

Definition at line 61 of file TopLevelWindowModel.cpp.

62{
63}

Member Function Documentation

◆ applicationAt()

lomiriapi::ApplicationInfoInterface * TopLevelWindowModel::applicationAt ( int  index) const

Returns the application at the given index.

Definition at line 678 of file TopLevelWindowModel.cpp.

679{
680 if (index >=0 && index < m_windowModel.count()) {
681 return m_windowModel[index].application;
682 } else {
683 return nullptr;
684 }
685}

◆ closeAllWindows()

void TopLevelWindowModel::closeAllWindows ( )

Closes all windows, emits closedAllWindows when done.

Definition at line 867 of file TopLevelWindowModel.cpp.

868{
869 m_closingAllApps = true;
870 for (auto win : m_windowModel) {
871 win.window->close();
872 }
873
874 // This is done after the for loop in the unlikely event that
875 // an app starts in between this
876 if (m_windowModel.isEmpty()) {
877 Q_EMIT closedAllWindows();
878 }
879}

◆ data()

QVariant TopLevelWindowModel::data ( const QModelIndex &  index,
int  role 
) const
override

Definition at line 605 of file TopLevelWindowModel.cpp.

606{
607 if (index.row() < 0 || index.row() >= m_windowModel.size())
608 return QVariant();
609
610 if (role == WindowRole) {
611 Window *window = m_windowModel.at(index.row()).window;
612 return QVariant::fromValue(window);
613 } else if (role == ApplicationRole) {
614 return QVariant::fromValue(m_windowModel.at(index.row()).application);
615 } else {
616 return QVariant();
617 }
618}
A slightly higher concept than MirSurface.
Definition: Window.h:48

◆ focusedWindow()

Window * TopLevelWindowModel::focusedWindow ( ) const

Definition at line 753 of file TopLevelWindowModel.cpp.

754{
755 return m_focusedWindow;
756}

◆ idAt()

int TopLevelWindowModel::idAt ( int  index) const

Returns the unique id of the element at the given index.

Definition at line 687 of file TopLevelWindowModel.cpp.

688{
689 if (index >=0 && index < m_windowModel.count()) {
690 return m_windowModel[index].window->id();
691 } else {
692 return 0;
693 }
694}

◆ indexForId()

int TopLevelWindowModel::indexForId ( int  id) const

Returns the index where the row with the given id is located.

Returns -1 if there's no row with the given id.

Definition at line 650 of file TopLevelWindowModel.cpp.

651{
652 for (int i = 0; i < m_windowModel.count(); ++i) {
653 if (m_windowModel[i].window->id() == id) {
654 return i;
655 }
656 }
657 return -1;
658}

◆ inputMethodSurface()

lomiriapi::MirSurfaceInterface * TopLevelWindowModel::inputMethodSurface ( ) const

Definition at line 748 of file TopLevelWindowModel.cpp.

749{
750 return m_inputMethodWindow ? m_inputMethodWindow->surface() : nullptr;
751}
lomiri::shell::application::MirSurfaceInterface * surface
Surface backing up this window It might be null if a surface hasn't been created yet (application is ...
Definition: Window.h:92

◆ listChanged

void TopLevelWindowModel::listChanged ( )
signal

Emitted when the list changes.

Emitted when model gains an element, loses an element or when elements exchange positions.

◆ nextId()

int TopLevelWindowModel::nextId ( ) const
inline

Definition at line 139 of file TopLevelWindowModel.h.

139{ return m_nextId.loadRelaxed(); }

◆ pendingActivation()

void TopLevelWindowModel::pendingActivation ( )

Sets pending activation flag.

Definition at line 919 of file TopLevelWindowModel.cpp.

920{
921 m_pendingActivation = true;
922}

◆ raiseId()

void TopLevelWindowModel::raiseId ( int  id)

Raises the row with the given id to the top of the window stack (index == count-1)

Definition at line 696 of file TopLevelWindowModel.cpp.

697{
698 if (m_modelState == IdleState) {
699 DEBUG_MSG << "(id=" << id << ") - do it now.";
700 doRaiseId(id);
701 } else {
702 DEBUG_MSG << "(id=" << id << ") - Model busy (modelState=" << m_modelState << "). Try again in the next event loop.";
703 // The model has just signalled some change. If we have a Repeater responding to this update, it will get nuts
704 // if we perform yet another model change straight away.
705 //
706 // A bad sympton of this problem is a Repeater.itemAt(index) call returning null event though Repeater.count says
707 // the index is definitely within bounds.
708 QMetaObject::invokeMethod(this, "raiseId", Qt::QueuedConnection, Q_ARG(int, id));
709 }
710}

◆ roleNames()

QHash< int, QByteArray > TopLevelWindowModel::roleNames ( ) const
inlineoverride

Definition at line 127 of file TopLevelWindowModel.h.

127 {
128 QHash<int, QByteArray> roleNames { {WindowRole, "window"},
129 {ApplicationRole, "application"} };
130 return roleNames;
131 }

◆ rowCount()

int TopLevelWindowModel::rowCount ( const QModelIndex &  parent = QModelIndex()) const
override

Definition at line 600 of file TopLevelWindowModel.cpp.

601{
602 return m_windowModel.count();
603}

◆ setApplicationManager()

void TopLevelWindowModel::setApplicationManager ( lomiri::shell::application::ApplicationManagerInterface *  )

Definition at line 65 of file TopLevelWindowModel.cpp.

66{
67 if (m_applicationManager == value) {
68 return;
69 }
70
71 DEBUG_MSG << "(" << value << ")";
72
73 Q_ASSERT(m_modelState == IdleState);
74 m_modelState = ResettingState;
75
76 beginResetModel();
77
78 if (m_applicationManager) {
79 disconnect(m_applicationManager, 0, this, 0);
80 }
81
82 m_applicationManager = value;
83
84 if (m_applicationManager) {
85 connect(m_applicationManager, &QAbstractItemModel::rowsInserted,
86 this, [this](const QModelIndex &/*parent*/, int first, int last) {
87 if (!m_workspace || !m_workspace->isActive())
88 return;
89
90 for (int i = first; i <= last; ++i) {
91 auto application = m_applicationManager->get(i);
92 addApplication(application);
93 }
94 });
95
96 connect(m_applicationManager, &QAbstractItemModel::rowsAboutToBeRemoved,
97 this, [this](const QModelIndex &/*parent*/, int first, int last) {
98 for (int i = first; i <= last; ++i) {
99 auto application = m_applicationManager->get(i);
100 removeApplication(application);
101 }
102 });
103 }
104
105 refreshWindows();
106
107 endResetModel();
108 m_modelState = IdleState;
109}

◆ setRootFocus()

void TopLevelWindowModel::setRootFocus ( bool  focus)

Definition at line 886 of file TopLevelWindowModel.cpp.

887{
888 INFO_MSG << "(" << focus << "), surfaceManagerBusy is " << m_surfaceManagerBusy;
889
890 if (m_surfaceManagerBusy) {
891 // Something else is probably being focused already, let's not add to
892 // the noise.
893 return;
894 }
895
896 if (focus) {
897 // Give focus back to previous focused window, only if null window is focused.
898 // If null window is not focused, a different app had taken the focus and we
899 // should repect that, or if a pendingActivation is going on.
900 if (m_previousWindow && !m_previousWindow->focused() && !m_pendingActivation &&
901 m_nullWindow == m_focusedWindow && m_previousWindow != m_nullWindow) {
902 m_previousWindow->activate();
903 } else if (!m_pendingActivation) {
904 // The previous window does not exist any more, focus top window.
905 activateTopMostWindowWithoutId(-1);
906 }
907 } else {
908 if (!m_nullWindow->focused()) {
909 m_nullWindow->activate();
910 }
911 }
912}
bool focused
Whether the surface is focused.
Definition: Window.h:71
void activate()
Focuses and raises the window.
Definition: Window.cpp:137

◆ setSurfaceManager()

void TopLevelWindowModel::setSurfaceManager ( lomiri::shell::application::SurfaceManagerInterface *  )

Definition at line 111 of file TopLevelWindowModel.cpp.

112{
113 if (surfaceManager == m_surfaceManager) {
114 return;
115 }
116
117 DEBUG_MSG << "(" << surfaceManager << ")";
118
119 Q_ASSERT(m_modelState == IdleState);
120 m_modelState = ResettingState;
121
122 beginResetModel();
123
124 if (m_surfaceManager) {
125 disconnect(m_surfaceManager, 0, this, 0);
126 }
127
128 m_surfaceManager = surfaceManager;
129
130 if (m_surfaceManager) {
131 connect(m_surfaceManager, &lomiriapi::SurfaceManagerInterface::surfacesAddedToWorkspace, this, &TopLevelWindowModel::onSurfacesAddedToWorkspace);
132 connect(m_surfaceManager, &lomiriapi::SurfaceManagerInterface::surfacesRaised, this, &TopLevelWindowModel::onSurfacesRaised);
133 connect(m_surfaceManager, &lomiriapi::SurfaceManagerInterface::surfaceRemoved, this, &TopLevelWindowModel::onSurfaceDestroyed);
134 connect(m_surfaceManager, &lomiriapi::SurfaceManagerInterface::modificationsStarted, this, &TopLevelWindowModel::onModificationsStarted);
135 connect(m_surfaceManager, &lomiriapi::SurfaceManagerInterface::modificationsEnded, this, &TopLevelWindowModel::onModificationsEnded);
136 }
137
138 refreshWindows();
139
140 endResetModel();
141 m_modelState = IdleState;
142}

◆ surfaceAt()

lomiriapi::MirSurfaceInterface * TopLevelWindowModel::surfaceAt ( int  index) const

Returns the surface at the given index.

It will be a nullptr if the application is still starting up and thus hasn't yet created and drawn into a surface.

Same as windowAt(index).surface()

Definition at line 669 of file TopLevelWindowModel.cpp.

670{
671 if (index >=0 && index < m_windowModel.count()) {
672 return m_windowModel[index].window->surface();
673 } else {
674 return nullptr;
675 }
676}

◆ windowAt()

Window * TopLevelWindowModel::windowAt ( int  index) const

Returns the window at the given index.

Will always be valid

Definition at line 660 of file TopLevelWindowModel.cpp.

661{
662 if (index >=0 && index < m_windowModel.count()) {
663 return m_windowModel[index].window;
664 } else {
665 return nullptr;
666 }
667}

Property Documentation

◆ count

int TopLevelWindowModel::count
read

Number of top-level surfaces in this model.

This is the same as rowCount, added in order to keep compatibility with QML ListModels.

Definition at line 59 of file TopLevelWindowModel.h.

◆ focusedWindow

Window* TopLevelWindowModel::focusedWindow
read

The currently focused window, if any.

Definition at line 59 of file TopLevelWindowModel.h.

◆ inputMethodSurface

lomiri::shell::application::MirSurfaceInterface* TopLevelWindowModel::inputMethodSurface
read

The input method surface, if any.

The surface of a onscreen keyboard (akak "virtual keyboard") would be kept here and not in the model itself.

Definition at line 59 of file TopLevelWindowModel.h.

◆ nextId

int TopLevelWindowModel::nextId
read

The id to be used on the next entry created Useful for tests

Definition at line 59 of file TopLevelWindowModel.h.

◆ rootFocus

bool TopLevelWindowModel::rootFocus
readwrite

Sets whether a user Window or "nothing" should be focused.

This implementation of TLWM must have something focused. However, the user may wish to have nothing in some cases - for example, when they minimize all their windows on the desktop or unfocus the app they're using by clicking the background or indicators.

Unsetting rootFocus effectively focuses "nothing" by setting up a Window that has no displayable Surfaces and bringing it into focus.

Setting rootFocus attempts to focus the Window which was focused last - unless another app is attempting to gain focus (as determined by pendingActivation) and that's why we got rootFocus.

If the previously-focused Window was closed before rootFocus was set, the next available window will be focused.

Definition at line 59 of file TopLevelWindowModel.h.


The documentation for this class was generated from the following files: