Unity 8
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 // unity-api
20 #include <unity/shell/application/MirSurfaceInterface.h>
21 
22 #include <QQmlEngine>
23 #include <QTextStream>
24 
26 
27 Q_LOGGING_CATEGORY(UNITY_WINDOW, "unity.window", QtWarningMsg)
28 
29 #define DEBUG_MSG qCDebug(UNITY_WINDOW).nospace() << qPrintable(toString()) << "::" << __func__
30 
31 Window::Window(int id, QObject *parent)
32  : QObject(parent)
33  , m_id(id)
34 {
35  DEBUG_MSG << "()";
36  QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
37 }
38 
39 Window::~Window()
40 {
41  DEBUG_MSG << "()";
42 }
43 
44 QPoint Window::position() const
45 {
46  return m_position;
47 }
48 
49 QPoint Window::requestedPosition() const
50 {
51  return m_requestedPosition;
52 }
53 
54 void Window::setRequestedPosition(const QPoint &value)
55 {
56  m_positionRequested = true;
57  if (value != m_requestedPosition) {
58  m_requestedPosition = value;
59  Q_EMIT requestedPositionChanged(m_requestedPosition);
60  if (m_surface) {
61  m_surface->setRequestedPosition(value);
62  } else {
63  // fake-miral: always comply
64  m_position = m_requestedPosition;
65  Q_EMIT positionChanged(m_position);
66  }
67  }
68 }
69 
70 bool Window::allowClientResize() const
71 {
72  return m_allowClientResize;
73 }
74 
75 void Window::setAllowClientResize(bool value)
76 {
77  if (value != m_allowClientResize) {
78  DEBUG_MSG << "("<<value<<")";
79  m_allowClientResize = value;
80  if (m_surface) {
81  m_surface->setAllowClientResize(value);
82  }
83  Q_EMIT allowClientResizeChanged(m_allowClientResize);
84  }
85 }
86 
87 Mir::State Window::state() const
88 {
89  return m_state;
90 }
91 
92 bool Window::focused() const
93 {
94  return m_focused;
95 }
96 
98 {
99  if (m_surface) {
100  return m_surface->confinesMousePointer();
101  } else {
102  return false;
103  }
104 }
105 
106 int Window::id() const
107 {
108  return m_id;
109 }
110 
111 unityapi::MirSurfaceInterface* Window::surface() const
112 {
113  return m_surface;
114 }
115 
116 void Window::requestState(Mir::State state)
117 {
118  m_stateRequested = true;
119  if (m_surface) {
120  m_surface->requestState(state);
121  } else if (m_state != state) {
122  m_state = state;
123  Q_EMIT stateChanged(m_state);
124  }
125 }
126 
128 {
129  if (m_surface) {
130  m_surface->close();
131  } else {
132  Q_EMIT closeRequested();
133  }
134 }
135 
137 {
138  DEBUG_MSG << "()";
139  if (m_surface) {
140  m_surface->activate();
141  } else {
142  Q_EMIT emptyWindowActivated();
143  }
144 }
145 
146 void Window::setSurface(unityapi::MirSurfaceInterface *surface)
147 {
148  DEBUG_MSG << "(" << surface << ")";
149  if (m_surface) {
150  disconnect(m_surface, 0, this, 0);
151  }
152 
153  m_surface = surface;
154 
155  if (m_surface) {
156  connect(surface, &unityapi::MirSurfaceInterface::focusRequested, this, [this]() {
157  Q_EMIT focusRequested();
158  });
159 
160  connect(surface, &unityapi::MirSurfaceInterface::closeRequested, this, &Window::closeRequested);
161 
162  connect(surface, &unityapi::MirSurfaceInterface::positionChanged, this, [this]() {
163  updatePosition();
164  });
165 
166  connect(surface, &unityapi::MirSurfaceInterface::stateChanged, this, [this]() {
167  updateState();
168  });
169 
170  connect(surface, &unityapi::MirSurfaceInterface::focusedChanged, this, [this]() {
171  updateFocused();
172  });
173 
174  connect(surface, &unityapi::MirSurfaceInterface::allowClientResizeChanged, this, [this]() {
175  if (m_surface->allowClientResize() != m_allowClientResize) {
176  m_allowClientResize = m_surface->allowClientResize();
177  Q_EMIT allowClientResizeChanged(m_allowClientResize);
178  }
179  });
180 
181  connect(surface, &unityapi::MirSurfaceInterface::liveChanged, this, &Window::liveChanged);
182 
183  connect(surface, &QObject::destroyed, this, [this]() {
184  setSurface(nullptr);
185  });
186 
187  // bring it up to speed
188  if (m_positionRequested) {
189  m_surface->setRequestedPosition(m_requestedPosition);
190  }
191  if (m_stateRequested && m_surface->state() == Mir::RestoredState) {
192  m_surface->requestState(m_state);
193  }
194  m_surface->setAllowClientResize(m_allowClientResize);
195 
196  // and sync with surface
197  updatePosition();
198  updateState();
199  updateFocused();
200  }
201 
202  Q_EMIT surfaceChanged(surface);
203 }
204 
205 void Window::updatePosition()
206 {
207  if (m_surface->position() != m_position) {
208  m_position = m_surface->position();
209  Q_EMIT positionChanged(m_position);
210  }
211 }
212 
213 void Window::updateState()
214 {
215  if (m_surface->state() != m_state) {
216  m_state = m_surface->state();
217  Q_EMIT stateChanged(m_state);
218  }
219 }
220 
221 void Window::updateFocused()
222 {
223  if (m_surface->focused() != m_focused) {
224  m_focused = m_surface->focused();
225  Q_EMIT focusedChanged(m_focused);
226  }
227 }
228 
229 void Window::setFocused(bool value)
230 {
231  if (value != m_focused) {
232  DEBUG_MSG << "(" << value << ")";
233  m_focused = value;
234  Q_EMIT focusedChanged(m_focused);
235  // when we have a surface we get focus changes from updateFocused() instead
236  Q_ASSERT(!m_surface);
237  }
238 }
239 
240 QString Window::toString() const
241 {
242  QString result;
243  {
244  QTextStream stream(&result);
245  stream << "Window["<<(void*)this<<", id="<<id()<<", ";
246  if (surface()) {
247  stream << "MirSurface["<<(void*)surface()<<",\""<<surface()->name()<<"\"]";
248  } else {
249  stream << "null";
250  }
251  stream << "]";
252  }
253  return result;
254 }
255 
256 QDebug operator<<(QDebug dbg, const Window *window)
257 {
258  QDebugStateSaver saver(dbg);
259  dbg.nospace();
260 
261  if (window) {
262  dbg << qPrintable(window->toString());
263  } else {
264  dbg << (void*)(window);
265  }
266 
267  return dbg;
268 }
A slightly higher concept than MirSurface.
Definition: Window.h:47
Mir::State state
State of the surface.
Definition: Window.h:64
void activate()
Focuses and raises the window.
Definition: Window.cpp:136
unity::shell::application::MirSurfaceInterface surface
Surface backing up this window It might be null if a surface hasn&#39;t been created yet (application is ...
Definition: Window.h:92
bool focused
Whether the surface is focused.
Definition: Window.h:71
void requestState(Mir::State state)
Requests a change to the specified state.
Definition: Window.cpp:116
QPoint position
Position of the current surface buffer, in pixels.
Definition: Window.h:54
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
QPoint requestedPosition
Requested position of the current surface buffer, in pixels.
Definition: Window.h:59
bool allowClientResize
Whether to comply to resize requests coming from the client side.
Definition: Window.h:99
void close()
Sends a close request.
Definition: Window.cpp:127
bool confinesMousePointer
Whether the surface wants to confine the mouse pointer within its boundaries.
Definition: Window.h:78