Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqnxwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
5
6#include "qqnxglobal.h"
7
8#include "qqnxwindow.h"
10#include "qqnxscreen.h"
11#include "qqnxlgmon.h"
12
13#include <QUuid>
14
15#include <QtGui/QWindow>
16#include <qpa/qwindowsysteminterface.h>
17
18#include "private/qguiapplication_p.h"
19
20#include <QtCore/QDebug>
21
22#include <errno.h>
23
25
26Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
27
28#define DECLARE_DEBUG_VAR(variable)
29 static bool debug_ ## variable()
30 { static bool value = qgetenv("QNX_SCREEN_DEBUG").contains(QT_STRINGIFY(variable)); return value; }
34DECLARE_DEBUG_VAR(updates)
35DECLARE_DEBUG_VAR(cpu_time)
36DECLARE_DEBUG_VAR(gpu_time)
37DECLARE_DEBUG_VAR(statistics)
38#undef DECLARE_DEBUG_VAR
39
40/*!
41 \class QQnxWindow
42 \brief The QQnxWindow is the base class of the various classes used as instances of
43 QPlatformWindow in the QNX QPA plugin.
44
45 The standard properties and methods available in Qt are not a perfect match for the
46 features provided by the QNX screen service. While for the majority of applications
47 the default behavior suffices, some circumstances require greater control over the
48 interaction with screen.
49
50 \section1 Window Types
51
52 The QNX QPA plugin can operate in two modes, with or without a root window. The
53 selection of mode is made via the \e rootwindow and \e no-rootwindow options to the
54 plugin. The default mode is rootwindow for BlackBerry builds and no-rootwindow for
55 non-BlackBerry builds.
56
57 Windows with parents are always created as child windows, the difference in the modes
58 is in the treatment of parentless windows. In no-rootwindow mode, these windows are
59 created as application windows while in rootwindow mode, the first window on a screen
60 is created as an application window while subsequent windows are created as child
61 windows. The only exception to this is any window of type Qt::CoverWindow;
62 these are created as application windows, but will never become the root window,
63 even if they are the first window created.
64
65 It is also possible to create a parentless child window. These may be useful to
66 create windows that are parented by windows from other processes. To do this, you
67 attach a dynamic property \e qnxInitialWindowGroup to the QWindow though this must be done
68 prior to the platform window class (this class) being created which typically happens
69 when the window is made visible. When the window is created in QML, it is acceptable
70 to have the \e visible property hardcoded to true so long as the qnxInitialWindowGroup
71 is also set.
72
73 \section1 Joining Window Groups
74
75 Window groups may be joined in a number of ways, some are automatic based on
76 predefined rules though an application is also able to provide explicit control.
77
78 A QWindow that has a parent will join its parent's window group. When rootwindow mode
79 is in effect, all but the first parentless window on a screen will be child windows
80 and join the window group of the first parentless window, the root window.
81
82 If a QWindow has a valid dynamic property called \e qnxInitialWindowGroup at the time the
83 QQnxWindow is created, the window will be created as a child window and, if the
84 qnxInitialWindowGroup property is a non-empty string, an attempt will be made to join that
85 window group. This has an effect only when the QQnxWindow is created, subsequent
86 changes to this property are ignored. Setting the property to an empty string
87 provides a means to create 'top level' child windows without automatically joining
88 any group. Typically when this property is used \e qnxWindowId should be used as well
89 so that the process that owns the window group being joined has some means to
90 identify the window.
91
92 At any point following the creation of the QQnxWindow object, an application can
93 change the window group it has joined. This is done by using the \e
94 setWindowProperty function of the native interface to set the \e qnxWindowGroup property
95 to the desired value, for example:
96
97 \snippet code/src_plugins_platforms_qnx_qqnxwindow.cpp 0
98
99 To leave the current window group, one passes a null value for the property value,
100 for example:
101
102 \snippet code/src_plugins_platforms_qnx_qqnxwindow.cpp 1
103
104 \section1 Window Id
105
106 The screen window id string property can be set on a window by assigning the desired
107 value to a dynamic property \e qnxWindowId on the QWindow prior to the QQnxWindow having
108 been created. This is often wanted when one joins a window group belonging to a
109 different process.
110
111*/
112QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow)
115 m_window(0),
116 m_screen(0),
117 m_parentWindow(0),
118 m_visible(false),
119 m_exposed(true),
120 m_foreign(false),
122 m_firstActivateHandled(false),
123 m_desktopNotify(0)
124{
125 qCDebug(lcQpaWindow) << "window =" << window << ", size =" << window->size();
126
127 QQnxScreen *platformScreen = static_cast<QQnxScreen *>(window->screen()->handle());
128
129 // If a qnxInitialWindowGroup property is set on the window we'll take this as an
130 // indication that we want to create a child window and join that window group.
131 QVariant windowGroup = window->property("qnxInitialWindowGroup");
132 if (!windowGroup.isValid())
133 windowGroup = window->property("_q_platform_qnxParentGroup");
134
135 if (window->type() == Qt::CoverWindow) {
136 // Cover windows have to be top level to be accessible to window delegate (i.e. navigator)
137 // Desktop windows also need to be toplevel because they are not
138 // supposed to be part of the window hierarchy tree
139 m_isTopLevel = true;
140 } else if (parent() || windowGroup.isValid()) {
141 // If we have a parent we are a child window. Sometimes we have to be a child even if we
142 // don't have a parent e.g. our parent might be in a different process.
143 m_isTopLevel = false;
144 } else {
145 // We're parentless. If we're not using a root window, we'll always be a top-level window
146 // otherwise only the first window is.
147 m_isTopLevel = !needRootWindow || !platformScreen->rootWindow();
148 }
149
150 QVariant type = window->property("_q_platform_qnxWindowType");
151 if (type.isValid() && type.canConvert<int>()) {
153 screen_create_window_type(&m_window, m_screenContext, type.value<int>()),
154 "Could not create window");
155 } else if (m_isTopLevel) {
156 Q_SCREEN_CRITICALERROR(screen_create_window(&m_window, m_screenContext),
157 "Could not create top level window"); // Creates an application window
158 if (window->type() != Qt::CoverWindow) {
159 if (needRootWindow)
160 platformScreen->setRootWindow(this);
161 }
162 } else {
164 screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW),
165 "Could not create child window");
166 }
167
168 createWindowGroup();
169
170 // If the window has a qnxWindowId property, set this as the string id property. This generally
171 // needs to be done prior to joining any group as it might be used by the owner of the
172 // group to identify the window.
173 QVariant windowId = window->property("qnxWindowId");
174 if (!windowId.isValid())
175 windowId = window->property("_q_platform_qnxWindowId");
176 if (windowId.isValid() && windowId.canConvert<QByteArray>()) {
177 QByteArray id = windowId.toByteArray();
178 Q_SCREEN_CHECKERROR(screen_set_window_property_cv(m_window, SCREEN_PROPERTY_ID_STRING,
179 id.size(), id), "Failed to set id");
180 }
181
182 // If a window group has been provided join it now. If it's an empty string that's OK too,
183 // it'll cause us not to join a group (the app will presumably join at some future time).
184 if (windowGroup.isValid() && windowGroup.canConvert<QByteArray>())
185 joinWindowGroup(windowGroup.toByteArray());
186
187 QVariant pipelineValue = window->property("_q_platform_qnxPipeline");
188 if (pipelineValue.isValid()) {
189 bool ok = false;
190 int pipeline = pipelineValue.toInt(&ok);
191 if (ok) {
192 qCDebug(lcQpaWindow) << "Set pipeline value to" << pipeline;
193
195 screen_set_window_property_iv(m_window, SCREEN_PROPERTY_PIPELINE, &pipeline),
196 "Failed to set window pipeline");
197 } else {
198 qCDebug(lcQpaWindow) << "Invalid pipeline value:" << pipelineValue;
199 }
200 }
201
202 // QNX desktop integration.
204 // Determine if the window needs a frame.
205 switch (window->type()) {
206 case Qt::Popup:
207 case Qt::ToolTip:
208 m_desktopNotify = DesktopNotifyPosition | DesktopNotifyVisible;
209 break;
210
211 default:
212 m_desktopNotify = DesktopNotifyTitle | DesktopNotifyVisible;
213 break;
214 }
215
216 // Wait for the window manager to acknowledge the window's creation.
217 // The call returns immediately if there is no window manager.
218 screen_manage_window(m_window,
219 (m_desktopNotify & DesktopNotifyTitle) ? "Frame=Y" : "Frame=N");
220 }
221
222 int debug = 0;
223 if (Q_UNLIKELY(debug_fps())) {
224 debug |= SCREEN_DEBUG_GRAPH_FPS;
225 }
226 if (Q_UNLIKELY(debug_posts())) {
227 debug |= SCREEN_DEBUG_GRAPH_POSTS;
228 }
229 if (Q_UNLIKELY(debug_blits())) {
230 debug |= SCREEN_DEBUG_GRAPH_BLITS;
231 }
232 if (Q_UNLIKELY(debug_updates())) {
233 debug |= SCREEN_DEBUG_GRAPH_UPDATES;
234 }
235 if (Q_UNLIKELY(debug_cpu_time())) {
236 debug |= SCREEN_DEBUG_GRAPH_CPU_TIME;
237 }
238 if (Q_UNLIKELY(debug_gpu_time())) {
239 debug |= SCREEN_DEBUG_GRAPH_GPU_TIME;
240 }
241 if (Q_UNLIKELY(debug_statistics())) {
242 debug = SCREEN_DEBUG_STATISTICS;
243 }
244
245 if (debug > 0) {
246 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_DEBUG, &debug),
247 "Could not set SCREEN_PROPERTY_DEBUG");
248 qCDebug(lcQpaWindow) << "window SCREEN_PROPERTY_DEBUG= " << debug;
249 }
250}
251
252QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow)
256 , m_screen(0)
257 , m_parentWindow(0)
258 , m_visible(false)
259 , m_exposed(true)
260 , m_foreign(true)
262 , m_parentGroupName(256, 0)
263 , m_isTopLevel(false)
264{
265 qCDebug(lcQpaWindow) << "window =" << window << ", size =" << window->size();
266
267 collectWindowGroup();
268
269 screen_get_window_property_cv(m_window,
270 SCREEN_PROPERTY_PARENT,
271 m_parentGroupName.size(),
272 m_parentGroupName.data());
273 m_parentGroupName.resize(strlen(m_parentGroupName.constData()));
274
275 // If a window group has been provided join it now. If it's an empty string that's OK too,
276 // it'll cause us not to join a group (the app will presumably join at some future time).
277 QVariant parentGroup = window->property("qnxInitialWindowGroup");
278 if (!parentGroup.isValid())
279 parentGroup = window->property("_q_platform_qnxParentGroup");
280 if (parentGroup.isValid() && parentGroup.canConvert<QByteArray>())
281 joinWindowGroup(parentGroup.toByteArray());
282}
283
285{
286 qCDebug(lcQpaWindow) << "window =" << window();
287
288 // Qt should have already deleted the children before deleting the parent.
289 Q_ASSERT(m_childWindows.size() == 0);
290
291 // Remove from plugin's window mapper
292 QQnxIntegration::instance()->removeWindow(m_window);
293
294 // Remove from parent's Hierarchy.
295 removeFromParent();
296 if (m_screen)
297 m_screen->updateHierarchy();
298
299 // Cleanup QNX window and its buffers
300 // Foreign windows are cleaned up externally after the CLOSE event has been handled.
301 if (m_foreign)
302 removeContextPermission();
303 else
304 screen_destroy_window(m_window);
305}
306
307void QQnxWindow::setGeometry(const QRect &rect)
308{
309 QRect newGeometry = rect;
310 if (shouldMakeFullScreen())
311 newGeometry = screen()->geometry();
312
313 setGeometryHelper(newGeometry);
314
315 if (isExposed())
316 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), newGeometry.size()));
317}
318
319void QQnxWindow::setGeometryHelper(const QRect &rect)
320{
321 qCDebug(lcQpaWindow) << "window =" << window()
322 << ", (" << rect.x() << "," << rect.y()
323 << "," << rect.width() << "," << rect.height() << ")";
324
325 // Call base class method
326 QPlatformWindow::setGeometry(rect);
327
328 int val[2];
329
330 // Set window geometry equal to widget geometry
331 if (m_desktopNotify & DesktopNotifyPosition) {
332 notifyManager(QString::asprintf("Pos=%d,%d", rect.x(), rect.y()));
333 } else {
334 val[0] = rect.x();
335 val[1] = rect.y();
336 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val),
337 "Failed to set window position");
338 }
339
340 val[0] = rect.width();
341 val[1] = rect.height();
342 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val),
343 "Failed to set window size");
344
345 // Set viewport size equal to window size
346 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val),
347 "Failed to set window source size");
348
349 screen_flush_context(m_screenContext, 0);
350
351 QWindowSystemInterface::handleGeometryChange(window(), rect);
352}
353
354void QQnxWindow::setVisible(bool visible)
355{
356 qCDebug(lcQpaWindow) << "window =" << window() << "visible =" << visible;
357
358 if (m_visible == visible)
359 return;
360
361 // The first time through we join a window group if appropriate.
362 if (m_parentGroupName.isNull() && !m_isTopLevel) {
363 joinWindowGroup(parent() ? static_cast<QQnxWindow*>(parent())->groupName()
364 : QByteArray(m_screen->windowGroupName()));
365 }
366
367 m_visible = visible;
368
369 QQnxWindow *root = this;
370 while (root->m_parentWindow)
371 root = root->m_parentWindow;
372
373 root->updateVisibility(root->m_visible);
374
375 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), window()->geometry().size()));
376
377 if (visible) {
378 applyWindowState();
379 } else {
380 if (showWithoutActivating() && focusable() && m_firstActivateHandled) {
381 m_firstActivateHandled = false;
382 int val = SCREEN_SENSITIVITY_NO_FOCUS;
384 screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val),
385 "Failed to set window sensitivity");
386 }
387
388 // Flush the context, otherwise it won't disappear immediately
389 screen_flush_context(m_screenContext, 0);
390 }
391}
392
393void QQnxWindow::updateVisibility(bool parentVisible)
394{
395 qCDebug(lcQpaWindow) << "parentVisible =" << parentVisible << "window =" << window();
396 // Set window visibility
397 int val = (m_visible && parentVisible) ? 1 : 0;
398 if (m_desktopNotify & DesktopNotifyVisible) {
399 notifyManager(QString("Visible=") + (val ? "Y" : "N"));
400 } else {
401 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &val),
402 "Failed to set window visibility");
403 }
404
405 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
406 childWindow->updateVisibility(m_visible && parentVisible);
407}
408
409void QQnxWindow::setOpacity(qreal level)
410{
411 qCDebug(lcQpaWindow) << "window =" << window() << "opacity =" << level;
412 // Set window global alpha
413 int val = (int)(level * 255);
414 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_GLOBAL_ALPHA, &val),
415 "Failed to set global alpha");
416
417 screen_flush_context(m_screenContext, 0);
418}
419
420void QQnxWindow::setExposed(bool exposed)
421{
422 qCDebug(lcQpaWindow) << "window =" << window() << "expose =" << exposed;
423
424 if (m_exposed != exposed) {
425 m_exposed = exposed;
426 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), window()->geometry().size()));
427 }
428}
429
431{
432 return m_visible && m_exposed;
433}
434
435void QQnxWindow::setBufferSize(const QSize &size)
436{
437 qCDebug(lcQpaWindow) << "window =" << window() << "size =" << size;
438
439 // libscreen fails when creating empty buffers
440 const QSize nonEmptySize = size.isEmpty() ? QSize(1, 1) : size;
441 int format = pixelFormat();
442
443 if (nonEmptySize == m_bufferSize || format == -1)
444 return;
445
447 screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, &format),
448 "Failed to set window format");
449
450 int val[2] = { nonEmptySize.width(), nonEmptySize.height() };
451 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val),
452 "Failed to set window buffer size");
453
454 if (m_bufferSize.isValid()) {
455 m_bufferSize = nonEmptySize;
457 return;
458 }
459
460 Q_SCREEN_CRITICALERROR(screen_create_window_buffers(m_window, MAX_BUFFER_COUNT),
461 "Failed to create window buffers");
462
463 // check if there are any buffers available
464 int bufferCount = 0;
466 screen_get_window_property_iv(m_window, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &bufferCount),
467 "Failed to query render buffer count");
468
469 if (Q_UNLIKELY(bufferCount != MAX_BUFFER_COUNT)) {
470 qFatal("QQnxWindow: invalid buffer count. Expected = %d, got = %d.",
471 MAX_BUFFER_COUNT, bufferCount);
472 }
473
474 // Set the transparency. According to QNX technical support, setting the window
475 // transparency property should always be done *after* creating the window
476 // buffers in order to guarantee the property is paid attention to.
477 if (size.isEmpty()) {
478 // We can't create 0x0 buffers and instead make them 1x1. But to allow these windows to
479 // still be 'visible' (thus allowing their children to be visible), we need to allow
480 // them to be posted but still not show up.
481 val[0] = SCREEN_TRANSPARENCY_DISCARD;
482 } else if (window()->requestedFormat().alphaBufferSize() == 0) {
483 // To avoid overhead in the composition manager, disable blending
484 // when the underlying window buffer doesn't have an alpha channel.
485 val[0] = SCREEN_TRANSPARENCY_NONE;
486 } else {
487 // Normal alpha blending. This doesn't commit us to translucency; the
488 // normal backfill during the painting will contain a fully opaque
489 // alpha channel unless the user explicitly intervenes to make something
490 // transparent.
491 val[0] = SCREEN_TRANSPARENCY_SOURCE_OVER;
492 }
493
494 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, val),
495 "Failed to set window transparency");
496
497 // Cache new buffer size
498 m_bufferSize = nonEmptySize;
500}
501
502void QQnxWindow::setScreen(QQnxScreen *platformScreen)
503{
504 qCDebug(lcQpaWindow) << "window =" << window() << "platformScreen =" << platformScreen;
505
506 if (platformScreen == 0) { // The screen has been destroyed
507 m_screen = 0;
508 Q_FOREACH (QQnxWindow *childWindow, m_childWindows) {
509 childWindow->setScreen(0);
510 }
511 return;
512 }
513
514 if (m_screen == platformScreen)
515 return;
516
517 if (m_screen) {
518 qCDebug(lcQpaWindow) << "Moving window to different screen";
519 m_screen->removeWindow(this);
520
522 screen_leave_window_group(m_window);
523 }
524 }
525
526 m_screen = platformScreen;
527 if (!m_parentWindow) {
528 platformScreen->addWindow(this);
529 }
530 if (m_isTopLevel) {
531 // Move window to proper screen/display
532 screen_display_t display = platformScreen->nativeDisplay();
534 screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display),
535 "Failed to set window display");
536 } else {
537 Q_FOREACH (QQnxWindow *childWindow, m_childWindows) {
538 // Only subwindows and tooltips need necessarily be moved to another display with the window.
539 if (window()->type() == Qt::SubWindow || window()->type() == Qt::ToolTip)
540 childWindow->setScreen(platformScreen);
541 }
542 }
543
544 m_screen->updateHierarchy();
545}
546
547void QQnxWindow::removeFromParent()
548{
549 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window =" << window();
550 // Remove from old Hierarchy position
551 if (m_parentWindow) {
552 if (Q_UNLIKELY(!m_parentWindow->m_childWindows.removeAll(this)))
553 qFatal("QQnxWindow: Window Hierarchy broken; window has parent, but parent hasn't got child.");
554 else
555 m_parentWindow = nullptr;
556 } else if (m_screen) {
557 m_screen->removeWindow(this);
558 }
559}
560
561void QQnxWindow::setParent(const QPlatformWindow *window)
562{
563 qCDebug(lcQpaWindow) << "window =" << this->window() << "platformWindow =" << window;
564 // Cast away the const, we need to modify the hierarchy.
565 QQnxWindow* const newParent = static_cast<QQnxWindow*>(const_cast<QPlatformWindow*>(window));
566
567 if (newParent == m_parentWindow)
568 return;
569
570 if (static_cast<QQnxScreen *>(screen())->rootWindow() == this) {
571 qWarning("Application window cannot be reparented");
572 return;
573 }
574
575 removeFromParent();
576 m_parentWindow = newParent;
577
578 // Add to new hierarchy position.
579 if (m_parentWindow) {
580 if (m_parentWindow->m_screen != m_screen)
581 setScreen(m_parentWindow->m_screen);
582
583 m_parentWindow->m_childWindows.push_back(this);
584 joinWindowGroup(m_parentWindow->groupName());
585 } else {
586 m_screen->addWindow(this);
587 joinWindowGroup(QByteArray());
588 }
589
590 m_screen->updateHierarchy();
591}
592
594{
595 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window =" << window();
596
597 if (m_parentWindow) {
598 m_parentWindow->m_childWindows.removeAll(this);
599 m_parentWindow->m_childWindows.push_back(this);
600 } else {
601 m_screen->raiseWindow(this);
602 }
603
604 m_screen->updateHierarchy();
605}
606
608{
609 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "window =" << window();
610
611 if (m_parentWindow) {
612 m_parentWindow->m_childWindows.removeAll(this);
613 m_parentWindow->m_childWindows.push_front(this);
614 } else {
615 m_screen->lowerWindow(this);
616 }
617
618 m_screen->updateHierarchy();
619}
620
622{
623 QQnxWindow *focusWindow = nullptr;
624 if (QGuiApplication::focusWindow())
625 focusWindow = static_cast<QQnxWindow*>(QGuiApplication::focusWindow()->handle());
626
627 if (focusWindow == this)
628 return;
629
630 if (static_cast<QQnxScreen *>(screen())->rootWindow() == this ||
631 (focusWindow && findWindow(focusWindow->nativeHandle()))) {
632 // If the focus window is a child, we can just set the focus of our own window
633 // group to our window handle
634 setFocus(nativeHandle());
635 } else {
636 // In order to receive focus the parent's window group has to give focus to the
637 // child. If we have several hierarchy layers, we have to do that several times
638 QQnxWindow *currentWindow = this;
639 QList<QQnxWindow*> windowList;
640 while (currentWindow) {
641 auto platformScreen = static_cast<QQnxScreen *>(screen());
642 windowList.prepend(currentWindow);
643 // If we find the focus window, we don't have to go further
644 if (currentWindow == focusWindow)
645 break;
646
647 if (currentWindow->parent()){
648 currentWindow = static_cast<QQnxWindow*>(currentWindow->parent());
649 } else if (platformScreen->rootWindow() &&
650 platformScreen->rootWindow()->m_windowGroupName == currentWindow->m_parentGroupName) {
651 currentWindow = platformScreen->rootWindow();
652 } else {
653 currentWindow = nullptr;
654 }
655 }
656
657 // We have to apply the focus from parent to child windows
658 for (int i = 1; i < windowList.size(); ++i)
659 windowList.at(i-1)->setFocus(windowList.at(i)->nativeHandle());
660
661 windowList.last()->setFocus(windowList.constLast()->nativeHandle());
662 }
663
664 screen_flush_context(m_screenContext, 0);
665}
666
667void QQnxWindow::setFocus(screen_window_t newFocusWindow)
668{
669 screen_window_t temporaryFocusWindow = nullptr;
670
671 screen_group_t screenGroup = 0;
672 Q_SCREEN_CHECKERROR(screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP,
673 reinterpret_cast<void **>(&screenGroup)),
674 "Failed to retrieve window group");
675
676 if (showWithoutActivating() && focusable() && !m_firstActivateHandled) {
677 m_firstActivateHandled = true;
678 int val = SCREEN_SENSITIVITY_TEST;
680 screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val),
681 "Failed to set window sensitivity");
682
684 // For older versions of screen, the window may still have group
685 // focus even though it was marked NO_FOCUS when it was hidden.
686 // In that situation, focus has to be given to another window
687 // so that this window can take focus back from it.
688 screen_window_t oldFocusWindow = nullptr;
690 screen_get_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS,
691 reinterpret_cast<void **>(&oldFocusWindow)),
692 "Failed to retrieve group focus");
693 if (newFocusWindow == oldFocusWindow) {
694 char groupName[256];
695 memset(groupName, 0, sizeof(groupName));
696 Q_SCREEN_CHECKERROR(screen_get_group_property_cv(screenGroup, SCREEN_PROPERTY_NAME,
697 sizeof(groupName) - 1, groupName),
698 "Failed to retrieve group name");
699
700 Q_SCREEN_CHECKERROR(screen_create_window_type(&temporaryFocusWindow,
701 m_screenContext, SCREEN_CHILD_WINDOW),
702 "Failed to create temporary focus window");
703 Q_SCREEN_CHECKERROR(screen_join_window_group(temporaryFocusWindow, groupName),
704 "Temporary focus window failed to join window group");
706 screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS,
707 reinterpret_cast<void **>(&temporaryFocusWindow)),
708 "Temporary focus window failed to take focus");
709 screen_flush_context(m_screenContext, 0);
710 }
711#endif
712 }
713
714 Q_SCREEN_CHECKERROR(screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS,
715 reinterpret_cast<void **>(&newFocusWindow)),
716 "Failed to set group focus");
717
718 screen_destroy_window(temporaryFocusWindow);
719}
720
721void QQnxWindow::setWindowState(Qt::WindowStates state)
722{
723 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "state =" << state;
724
725 // Prevent two calls with Qt::WindowFullScreen from changing m_unmaximizedGeometry
726 if (m_windowState == state)
727 return;
728
729 m_windowState = state;
730
731 if (m_visible)
732 applyWindowState();
733}
734
736{
737 // nothing to do; silence base class warning
738 // qWindowDebug("ignored");
739}
740
742{
743 return m_screen;
744}
745
746QQnxWindow *QQnxWindow::findWindow(screen_window_t windowHandle)
747{
748 if (m_window == windowHandle)
749 return this;
750
751 Q_FOREACH (QQnxWindow *window, m_childWindows) {
752 QQnxWindow * const result = window->findWindow(windowHandle);
753 if (result)
754 return result;
755 }
756
757 return 0;
758}
759
761{
762 qWarning("Qt::WindowMinimized is not supported by this OS version");
763}
764
765void QQnxWindow::setRotation(int rotation)
766{
767 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "angle =" << rotation;
769 screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ROTATION, &rotation),
770 "Failed to set window rotation");
771}
772
774{
775 // Alpha channel is always pre-multiplied if present
776 int val = SCREEN_PRE_MULTIPLIED_ALPHA;
777 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ALPHA_MODE, &val),
778 "Failed to set alpha mode");
779
780 // Set the window swap interval
781 val = 1;
783 screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val),
784 "Failed to set swap interval");
785
786 if (showWithoutActivating() || !focusable()) {
787 // NO_FOCUS is temporary for showWithoutActivating (and pop-up) windows.
788 // Using NO_FOCUS ensures that screen doesn't activate the window because
789 // it was just created. Sensitivity will be changed to TEST when the
790 // window is clicked or touched.
791 val = SCREEN_SENSITIVITY_NO_FOCUS;
793 screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val),
794 "Failed to set window sensitivity");
795 }
796
797 QQnxScreen *platformScreen = static_cast<QQnxScreen *>(window()->screen()->handle());
798 setScreen(platformScreen);
799
800 if (window()->type() == Qt::CoverWindow)
801 m_exposed = false;
802
803 // Add window to plugin's window mapper
804 QQnxIntegration::instance()->addWindow(m_window, window());
805
806 // Qt never calls these setters after creating the window, so we need to do that ourselves here
807 setWindowState(window()->windowState());
808 setOpacity(window()->opacity());
809
810 if (window()->parent() && window()->parent()->handle())
811 setParent(window()->parent()->handle());
812
813 setGeometryHelper(shouldMakeFullScreen() ? screen()->geometry() : window()->geometry());
814}
815
816void QQnxWindow::collectWindowGroup()
817{
818 QByteArray groupName(256, 0);
819 Q_SCREEN_CHECKERROR(screen_get_window_property_cv(m_window,
820 SCREEN_PROPERTY_GROUP,
821 groupName.size(),
822 groupName.data()),
823 "Failed to retrieve window group");
824 groupName.resize(strlen(groupName.constData()));
825 m_windowGroupName = groupName;
826}
827
828void QQnxWindow::createWindowGroup()
829{
830 Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, nullptr),
831 "Failed to create window group");
832
833 collectWindowGroup();
834}
835
836void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
837{
838 bool changed = false;
839
840 qCDebug(lcQpaWindow) << Q_FUNC_INFO << "group:" << groupName;
841
842 // screen has this annoying habit of generating a CLOSE/CREATE when the owner context of
843 // the parent group moves a foreign window to another group that it also owns. The
844 // CLOSE/CREATE changes the identity of the foreign window. Usually, this is undesirable.
845 // To prevent this CLOSE/CREATE when changing the parent group, we temporarily add a
846 // context permission for the Qt context. screen won't send a CLOSE/CREATE when the
847 // context has some permission other than the PARENT permission. If there isn't a new
848 // group (the window has no parent), this context permission is left in place.
849
850 if (m_foreign && !m_parentGroupName.isEmpty())
851 addContextPermission();
852
853 if (!groupName.isEmpty()) {
854 if (groupName != m_parentGroupName) {
855 screen_join_window_group(m_window, groupName);
856 m_parentGroupName = groupName;
857 changed = true;
858 }
859 } else {
860 if (!m_parentGroupName.isEmpty()) {
861 screen_leave_window_group(m_window);
862 changed = true;
863 }
864 // By setting to an empty string we'll stop setVisible from trying to
865 // change our group, we want that to happen only if joinWindowGroup has
866 // never been called. This allows windows to be created that are not initially
867 // part of any group.
868 m_parentGroupName = "";
869 }
870
871 if (m_foreign && !groupName.isEmpty())
872 removeContextPermission();
873
874 if (changed)
875 screen_flush_context(m_screenContext, 0);
876}
877
878void QQnxWindow::updateZorder(int &topZorder)
879{
880 updateZorder(m_window, topZorder);
881
882 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
883 childWindow->updateZorder(topZorder);
884}
885
886void QQnxWindow::updateZorder(screen_window_t window, int &topZorder)
887{
888 Q_SCREEN_CHECKERROR(screen_set_window_property_iv(window, SCREEN_PROPERTY_ZORDER, &topZorder),
889 "Failed to set window z-order");
890 topZorder++;
891}
892
893void QQnxWindow::applyWindowState()
894{
895 if (m_windowState & Qt::WindowMinimized) {
897
898 if (m_unmaximizedGeometry.isValid())
899 setGeometry(m_unmaximizedGeometry);
900 else
901 setGeometry(m_screen->geometry());
902 } else if (m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen)) {
903 m_unmaximizedGeometry = geometry();
904 setGeometry(m_windowState & Qt::WindowFullScreen ? m_screen->geometry()
905 : m_screen->availableGeometry());
906 } else if (m_unmaximizedGeometry.isValid()) {
907 setGeometry(m_unmaximizedGeometry);
908 }
909}
910
912{
913 if (m_cover) {
914 m_cover->updateCover();
915 qqnxLgmonFramePosted(true); // for performance measurements
916 } else {
917 qqnxLgmonFramePosted(false); // for performance measurements
918 }
919}
920
922{
923 return ((static_cast<QQnxScreen *>(screen())->rootWindow() == this)
924 && (QQnxIntegration::instance()->options() & QQnxIntegration::FullScreenApplication));
925}
926
927
929{
930 if (showWithoutActivating() && focusable() && !m_firstActivateHandled)
932}
933
934bool QQnxWindow::showWithoutActivating() const
935{
936 return (window()->flags() & Qt::Popup) == Qt::Popup
937 || window()->property("_q_showWithoutActivating").toBool();
938}
939
940bool QQnxWindow::focusable() const
941{
942 return (window()->flags() & Qt::WindowDoesNotAcceptFocus) != Qt::WindowDoesNotAcceptFocus;
943}
944
945void QQnxWindow::addContextPermission()
946{
947 QByteArray grantString("context:");
948 grantString.append(QQnxIntegration::instance()->screenContextId());
949 grantString.append(":rw-");
950 screen_set_window_property_cv(m_window,
951 SCREEN_PROPERTY_PERMISSIONS,
952 grantString.length(),
953 grantString.data());
954}
955
956void QQnxWindow::setWindowTitle(const QString &title)
957{
958 if (m_desktopNotify & DesktopNotifyTitle) {
959 QString titleStr = "Title=" + title;
960 notifyManager(titleStr);
961 }
962}
963
964void QQnxWindow::notifyManager(const QString &msg)
965{
966 screen_event_t ev;
967 screen_create_event(&ev);
968
969 std::string str = msg.toStdString();
970 screen_set_event_property_iv(ev, SCREEN_PROPERTY_TYPE,
971 (const int[]){ SCREEN_EVENT_MANAGER });
972 screen_set_event_property_cv(ev, SCREEN_PROPERTY_USER_DATA, str.length(),
973 str.c_str());
974 screen_set_event_property_pv(ev, SCREEN_PROPERTY_WINDOW,
975 reinterpret_cast<void **>(&m_window));
976 screen_set_event_property_pv(ev, SCREEN_PROPERTY_CONTEXT,
977 reinterpret_cast<void **>(&m_screenContext));
978
979 Q_SCREEN_CHECKERROR(screen_inject_event(NULL, ev),
980 "Failed to send a message to the window manager");
981}
982
983void QQnxWindow::removeContextPermission()
984{
985 QByteArray revokeString("context:");
986 revokeString.append(QQnxIntegration::instance()->screenContextId());
987 revokeString.append(":---");
988 screen_set_window_property_cv(m_window,
989 SCREEN_PROPERTY_PERMISSIONS,
990 revokeString.length(),
991 revokeString.data());
992}
993
994QT_END_NAMESPACE
static QQnxIntegration * instance()
void lowerWindow(QQnxWindow *window)
void raiseWindow(QQnxWindow *window)
void removeWindow(QQnxWindow *child)
void addWindow(QQnxWindow *child)
void setRootWindow(QQnxWindow *)
QQnxWindow * rootWindow() const
void updateHierarchy()
The QQnxWindow is the base class of the various classes used as instances of QPlatformWindow in the Q...
Definition qqnxwindow.h:31
void windowPosted()
void setExposed(bool exposed)
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
virtual int pixelFormat() const =0
QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow)
QQnxWindow * findWindow(screen_window_t windowHandle)
void setParent(const QPlatformWindow *window) override
This function is called to enable native child window in QPA.
bool shouldMakeFullScreen() const
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
virtual void resetBuffers()=0
bool isExposed() const override
Returns if this window is exposed in the windowing system.
void initWindow()
void raise() override
Reimplement to be able to let Qt raise windows to the top of the desktop.
QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow)
void joinWindowGroup(const QByteArray &groupName)
void minimize()
void propagateSizeHints() override
Reimplement to propagate the size hints of the QWindow.
void setWindowTitle(const QString &title)
Reimplement to set the window title to title.
void setScreen(QQnxScreen *platformScreen)
void setBufferSize(const QSize &size)
void setWindowState(Qt::WindowStates state) override
Requests setting the window state of this surface to type.
QPlatformScreen * screen() const override
Returns the platform screen handle corresponding to this platform window, or null if the window is no...
void setRotation(int rotation)
void handleActivationEvent()
void lower() override
Reimplement to be able to let Qt lower windows to the bottom of the desktop.
void setGeometry(const QRect &rect) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
void setOpacity(qreal level) override
Reimplement to be able to let Qt set the opacity level of a window.
virtual ~QQnxWindow()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
#define Q_SCREEN_CRITICALERROR(x, message)
Definition qqnxglobal.h:16
#define Q_SCREEN_CHECKERROR(x, message)
Definition qqnxglobal.h:13
void qqnxLgmonFramePosted(bool)
Definition qqnxlgmon.h:35
#define _SCREEN_VERSION
Definition qqnxscreen.h:18
#define _SCREEN_MAKE_VERSION(major, minor, patch)
Definition qqnxscreen.h:17
#define DECLARE_DEBUG_VAR(variable)
#define MAX_BUFFER_COUNT
Definition qqnxwindow.h:24