Lomiri
Window.cpp
1 /*
2  * Copyright (C) 2016-2017 Canonical Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include "Window.h"
18 
19 // lomiri-api
20 #include <lomiri/shell/application/MirSurfaceInterface.h>
21 
22 #include <QQmlEngine>
23 #include <QTextStream>
24 
25 namespace lomiriapi = lomiri::shell::application;
26 
27 Q_LOGGING_CATEGORY(LOMIRI_WINDOW, "lomiri.window", QtWarningMsg)
28 
29 #define DEBUG_MSG qCDebug(LOMIRI_WINDOW).nospace() << qPrintable(toString()) << "::" << __func__
30 #define WARNING_MSG qCWarning(LOMIRI_WINDOW).nospace() << qPrintable(toString()) << "::" << __func__
31 
32 Window::Window(int id, QObject *parent)
33  : QObject(parent)
34  , m_id(id)
35 {
36  DEBUG_MSG << "()";
37  QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
38 }
39 
40 Window::~Window()
41 {
42  DEBUG_MSG << "()";
43 }
44 
45 QPoint Window::position() const
46 {
47  return m_position;
48 }
49 
50 QPoint Window::requestedPosition() const
51 {
52  return m_requestedPosition;
53 }
54 
55 void Window::setRequestedPosition(const QPoint &value)
56 {
57  m_positionRequested = true;
58  if (value != m_requestedPosition) {
59  m_requestedPosition = value;
60  Q_EMIT requestedPositionChanged(m_requestedPosition);
61  if (m_surface) {
62  m_surface->setRequestedPosition(value);
63  } else {
64  // fake-miral: always comply
65  m_position = m_requestedPosition;
66  Q_EMIT positionChanged(m_position);
67  }
68  }
69 }
70 
71 bool Window::allowClientResize() const
72 {
73  return m_allowClientResize;
74 }
75 
76 void Window::setAllowClientResize(bool value)
77 {
78  if (value != m_allowClientResize) {
79  DEBUG_MSG << "("<<value<<")";
80  m_allowClientResize = value;
81  if (m_surface) {
82  m_surface->setAllowClientResize(value);
83  }
84  Q_EMIT allowClientResizeChanged(m_allowClientResize);
85  }
86 }
87 
88 Mir::State Window::state() const
89 {
90  return m_state;
91 }
92 
93 bool Window::focused() const
94 {
95  return m_focused;
96 }
97 
99 {
100  if (m_surface) {
101  return m_surface->confinesMousePointer();
102  } else {
103  return false;
104  }
105 }
106 
107 int Window::id() const
108 {
109  return m_id;
110 }
111 
112 lomiriapi::MirSurfaceInterface* Window::surface() const
113 {
114  return m_surface;
115 }
116 
117 void Window::requestState(Mir::State state)
118 {
119  m_stateRequested = true;
120  if (m_surface) {
121  m_surface->requestState(state);
122  } else if (m_state != state) {
123  m_state = state;
124  Q_EMIT stateChanged(m_state);
125  }
126 }
127 
129 {
130  if (m_surface) {
131  m_surface->close();
132  } else {
133  Q_EMIT closeRequested();
134  }
135 }
136 
138 {
139  DEBUG_MSG << "()";
140  if (m_surface) {
141  m_surface->activate();
142  } else {
143  Q_EMIT emptyWindowActivated();
144  }
145 }
146 
147 void Window::setSurface(lomiriapi::MirSurfaceInterface *surface)
148 {
149  DEBUG_MSG << "(" << surface << ")";
150  if (m_surface) {
151  disconnect(m_surface, 0, this, 0);
152  }
153 
154  m_surface = surface;
155 
156  if (m_surface) {
157  connect(surface, &lomiriapi::MirSurfaceInterface::focusRequested, this, [this]() {
158  Q_EMIT focusRequested();
159  });
160 
161  connect(surface, &lomiriapi::MirSurfaceInterface::closeRequested, this, &Window::closeRequested);
162 
163  connect(surface, &lomiriapi::MirSurfaceInterface::positionChanged, this, [this]() {
164  updatePosition();
165  });
166 
167  connect(surface, &lomiriapi::MirSurfaceInterface::stateChanged, this, [this]() {
168  updateState();
169  });
170 
171  connect(surface, &lomiriapi::MirSurfaceInterface::focusedChanged, this, [this]() {
172  updateFocused();
173  });
174 
175  connect(surface, &lomiriapi::MirSurfaceInterface::allowClientResizeChanged, this, [this]() {
176  if (m_surface->allowClientResize() != m_allowClientResize) {
177  m_allowClientResize = m_surface->allowClientResize();
178  Q_EMIT allowClientResizeChanged(m_allowClientResize);
179  }
180  });
181 
182  connect(surface, &lomiriapi::MirSurfaceInterface::liveChanged, this, &Window::liveChanged);
183 
184  connect(surface, &QObject::destroyed, this, [this]() {
185  setSurface(nullptr);
186  });
187 
188  // Surface should never be focused at this point!
189  if (m_surface->focused()) {
190  WARNING_MSG << "Inital surface is focused!";
191  }
192 
193  // bring it up to speed
194  if (m_focused) {
195  m_surface->activate();
196  }
197  if (m_positionRequested) {
198  m_surface->setRequestedPosition(m_requestedPosition);
199  }
200  if (m_stateRequested && m_surface->state() == Mir::RestoredState) {
201  m_surface->requestState(m_state);
202  }
203  m_surface->setAllowClientResize(m_allowClientResize);
204 
205  // and sync with surface
206  updatePosition();
207  updateState();
208  updateFocused();
209  }
210 
211  Q_EMIT surfaceChanged(surface);
212 }
213 
214 void Window::updatePosition()
215 {
216  if (m_surface->position() != m_position) {
217  m_position = m_surface->position();
218  Q_EMIT positionChanged(m_position);
219  }
220 }
221 
222 void Window::updateState()
223 {
224  if (m_surface->state() != m_state) {
225  m_state = m_surface->state();
226  Q_EMIT stateChanged(m_state);
227  }
228 }
229 
230 void Window::updateFocused()
231 {
232  if (m_surface->focused() != m_focused) {
233  m_focused = m_surface->focused();
234  Q_EMIT focusedChanged(m_focused);
235  }
236 }
237 
238 void Window::setFocused(bool value)
239 {
240  if (value != m_focused) {
241  DEBUG_MSG << "(" << value << ")";
242  m_focused = value;
243  Q_EMIT focusedChanged(m_focused);
244  // when we have a surface we get focus changes from updateFocused() instead
245  Q_ASSERT(!m_surface);
246  }
247 }
248 
249 QString Window::toString() const
250 {
251  QString result;
252  {
253  QTextStream stream(&result);
254  stream << "Window["<<(void*)this<<", id="<<id()<<", ";
255  if (surface()) {
256  stream << "MirSurface["<<(void*)surface()<<",\""<<surface()->name()<<"\"]";
257  } else {
258  stream << "null";
259  }
260  stream << "]";
261  }
262  return result;
263 }
264 
265 QDebug operator<<(QDebug dbg, const Window *window)
266 {
267  QDebugStateSaver saver(dbg);
268  dbg.nospace();
269 
270  if (window) {
271  dbg << qPrintable(window->toString());
272  } else {
273  dbg << (void*)(window);
274  }
275 
276  return dbg;
277 }
A slightly higher concept than MirSurface.
Definition: Window.h:48
bool allowClientResize
Whether to comply to resize requests coming from the client side.
Definition: Window.h:99
void requestState(Mir::State state)
Requests a change to the specified state.
Definition: Window.cpp:117
int id
A unique identifier for this window. Useful for telling windows apart in a list model as they get mov...
Definition: Window.h:84
void focusRequested()
Emitted when focus for this window is requested by an external party.
void close()
Sends a close request.
Definition: Window.cpp:128
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
QPoint requestedPosition
Requested position of the current surface buffer, in pixels.
Definition: Window.h:59
bool confinesMousePointer
Whether the surface wants to confine the mouse pointer within its boundaries.
Definition: Window.h:78
QPoint position
Position of the current surface buffer, in pixels.
Definition: Window.h:54
bool focused
Whether the surface is focused.
Definition: Window.h:71
void activate()
Focuses and raises the window.
Definition: Window.cpp:137
Mir::State state
State of the surface.
Definition: Window.h:64