Tensor& upsample_nearest3d_out_cpu(
    Tensor& output,
    const Tensor& input,
    IntArrayRef output_size,
    c10::optional<double> scales_d,
    c10::optional<double> scales_h,
    c10::optional<double> scales_w) {
  upsample_nearest3d_out_cpu_template(output, input, output_size, scales_d, scales_h, scales_w);
  return output;
}

#include <ATen/ATen.h>
#include <ATen/NativeFunctions.h>
#include <ATen/native/UpSample.h>

namespace at {
namespace native {
namespace {

static void upsample_nearest3d_out_cpu_template(
    Tensor& output,
    const Tensor& input,
    IntArrayRef output_size,
    c10::optional<double> scales_d,
    c10::optional<double> scales_h,
    c10::optional<double> scales_w) {
  TORCH_CHECK(
      output_size.size() == 3,
      "It is expected output_size equals to 3, but got size ",
      output_size.size());

  int64_t output_depth = output_size[0];
  int64_t output_height = output_size[1];
  int64_t output_width = output_size[2];

  int64_t nbatch = input.size(0);
  int64_t channels = input.size(1);
  int64_t input_depth = input.size(2);
  int64_t input_height = input.size(3);
  int64_t input_width = input.size(4);

  upsample_3d_shape_check(
      input,
      Tensor(),
      nbatch,
      channels,
      input_depth,
      input_height,
      input_width,
      output_depth,
      output_height,
      output_width);

  output.resize_({nbatch, channels, output_depth, output_height, output_width}, input.suggest_memory_format());
  AT_ASSERT(
      input_depth > 0 && input_height > 0 && input_width > 0 &&
      output_depth > 0 && output_height > 0 && output_width > 0);
  upsample_nearest3d_kernel(kCPU, output, input, scales_d, scales_h, scales_w);
}

static void upsample_nearest3d_backward_out_cpu_template(
    Tensor& grad_input,
    const Tensor& grad_output,
    IntArrayRef output_size,
    IntArrayRef input_size,
    c10::optional<double> scales_d,
    c10::optional<double> scales_h,
    c10::optional<double> scales_w) {
  TORCH_CHECK(
      output_size.size() == 3,
      "It is expected output_size equals to 3, but got size ",
      output_size.size());

  TORCH_CHECK(
      input_size.size() == 5,
      "It is expected input_size equals to 5, but got size ",
      input_size.size());

  int64_t output_depth = output_size[0];
  int64_t output_height = output_size[1];
  int64_t output_width = output_size[2];

  int64_t nbatch = input_size[0];
  int64_t channels = input_size[1];
  int64_t input_depth = input_size[2];
  int64_t input_height = input_size[3];
  int64_t input_width = input_size[4];

  upsample_3d_shape_check(
      Tensor(),
      grad_output,
      nbatch,
      channels,
      input_depth,
      input_height,
      input_width,
      output_depth,
      output_height,
      output_width);

  grad_input.resize_(
      {nbatch, channels, input_depth, input_height, input_width});
  grad_input.zero_();

  upsample_nearest3d_backward_kernel(kCPU, grad_input, grad_output, scales_d, scales_h, scales_w);
}
} // namespace

Tensor upsample_nearest3d_cpu(
    const Tensor& input,
    IntArrayRef output_size,
    c10::optional<double> scales_d,
    c10::optional<double> scales_h,
    c10::optional<double> scales_w) {
  auto output = at::empty({0}, input.options());
  upsample_nearest3d_out_cpu_template(output, input, output_size, scales_d, scales_h, scales_w);
  return output;
}

Tensor& upsample_nearest3d_backward_out_cpu(
    Tensor& grad_input,
    const Tensor& grad_output,
    IntArrayRef output_size,
    IntArrayRef input_size,
    c10::optional<double> scales_d,
    c10::optional<double> scales_h,
    c10::optional<double> scales_w) {
  upsample_nearest3d_backward_out_cpu_template(
      grad_input, grad_output, output_size, input_size, scales_d, scales_h, scales_w);
  return grad_input;
}

Tensor upsample_nearest3d_backward_cpu(
    const Tensor& grad_output,
    IntArrayRef output_size,
    IntArrayRef input_size,
    c10::optional<double> scales_d,
    c10::optional<double> scales_h,
    c10::optional<double> scales_w) {
  auto grad_input = at::zeros(input_size, grad_output.options());
  upsample_nearest3d_backward_out_cpu_template(
      grad_input, grad_output, output_size, input_size, scales_d, scales_h, scales_w);
  return grad_input;
}

using at::native::upsample::compute_output_size;
using at::native::upsample::get_scale_value;

Tensor upsample_nearest3d_cpu(
    const Tensor& input,
    c10::optional<IntArrayRef> output_size,
    c10::optional<ArrayRef<double>> scale_factors) {
  auto output = at::empty({0}, input.options());
  auto osize = compute_output_size(input.sizes(), output_size, scale_factors);
  auto scale_d = get_scale_value(scale_factors, 0);
  auto scale_h = get_scale_value(scale_factors, 1);
  auto scale_w = get_scale_value(scale_factors, 2);
  upsample_nearest3d_out_cpu_template(output, input, osize, scale_d, scale_h, scale_w);
  return output;
}

Tensor upsample_nearest3d_backward_cpu(
    const Tensor& grad_output,
    c10::optional<IntArrayRef> output_size,
    IntArrayRef input_size,
    c10::optional<ArrayRef<double>> scale_factors) {
  auto osize = compute_output_size(input_size, output_size, scale_factors);
  auto scale_d = get_scale_value(scale_factors, 0);
  auto scale_h = get_scale_value(scale_factors, 1);
  auto scale_w = get_scale_value(scale_factors, 2);
  auto grad_input = at::zeros(input_size, grad_output.options());
  upsample_nearest3d_backward_out_cpu_template(
      grad_input, grad_output, osize, input_size, scale_d, scale_h, scale_w);
  return grad_input;
}

DEFINE_DISPATCH(upsample_nearest3d_kernel);
DEFINE_DISPATCH(upsample_nearest3d_backward_kernel);

} // namespace native
} // namespace at


Q_FOREACH (screen_window_t overlay, m_overlays) {
        // No error handling, see underlay logic above
        screen_set_window_property_iv(overlay, SCREEN_PROPERTY_ZORDER, &topZorder);
        topZorder++;
    }

/***************************************************************************
**
** Contact: http://example.com
**
** This file is part of the plugins of the Qt Toolkit.
**
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: http://example.com and
** http://example.com.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qqnxglobal.h"

#include "qqnxscreen.h"
#include "qqnxwindow.h"
#include "qqnxcursor.h"

#include <QtCore/QThread>
#include <QtCore/QDebug>
#include <qpa/qwindowsysteminterface.h>

#include <errno.h>

#if defined(QQNXSCREEN_DEBUG)
#define qScreenDebug qDebug
#else
#define qScreenDebug QT_NO_QDEBUG_MACRO
#endif

#if defined(QQNX_PHYSICAL_SCREEN_WIDTH) && QQNX_PHYSICAL_SCREEN_WIDTH > 0 \
    && defined(QQNX_PHYSICAL_SCREEN_HEIGHT) && QQNX_PHYSICAL_SCREEN_HEIGHT > 0
#define QQNX_PHYSICAL_SCREEN_SIZE_DEFINED
#elif defined(QQNX_PHYSICAL_SCREEN_WIDTH) || defined(QQNX_PHYSICAL_SCREEN_HEIGHT)
#error Please define QQNX_PHYSICAL_SCREEN_WIDTH and QQNX_PHYSICAL_SCREEN_HEIGHT to values greater than zero
#endif

// The default z-order of a window (intended to be overlain) created by
static const int MMRENDER_DEFAULT_ZORDER = -1;

// The maximum z-order at which a foreign window will be considered
// an underlay.
static const int MAX_UNDERLAY_ZORDER = MMRENDER_DEFAULT_ZORDER - 1;

QT_BEGIN_NAMESPACE

static QSize determineScreenSize(screen_display_t display, bool primaryScreen) {
    int val[2];

    const int result = screen_get_display_property_iv(display, SCREEN_PROPERTY_PHYSICAL_SIZE, val);
    Q_SCREEN_CHECKERROR(result, "Failed to query display physical size");
    if (result != 0) {
        return QSize(150, 90);
    }

    if (val[0] > 0 && val[1] > 0)
        return QSize(val[0], val[1]);

    qScreenDebug("QQnxScreen: screen_get_display_property_iv() reported an invalid "
                 "physical screen size (%dx%d). Falling back to QQNX_PHYSICAL_SCREEN_SIZE "
                 "environment variable.", val[0], val[1]);

    const QString envPhySizeStr = qgetenv("QQNX_PHYSICAL_SCREEN_SIZE");
    if (!envPhySizeStr.isEmpty()) {
        const auto envPhySizeStrList = QStringView{envPhySizeStr}.split(QLatin1Char(','));
        const int envWidth = envPhySizeStrList.size() == 2 ? envPhySizeStrList[0].toInt() : -1;
        const int envHeight = envPhySizeStrList.size() == 2 ? envPhySizeStrList[1].toInt() : -1;

        if (envWidth <= 0 || envHeight <= 0) {
            qWarning("QQnxScreen: The value of QQNX_PHYSICAL_SCREEN_SIZE must be in the format "
                     "\"width,height\" in mm, with width, height > 0. Defaulting to 150x90. "
                     "Example: QQNX_PHYSICAL_SCREEN_SIZE=150,90");
            return QSize(150, 90);
        }

        return QSize(envWidth, envHeight);
    }

#if defined(QQNX_PHYSICAL_SCREEN_SIZE_DEFINED)
    const QSize defSize(QQNX_PHYSICAL_SCREEN_WIDTH, QQNX_PHYSICAL_SCREEN_HEIGHT);
    qWarning("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. Falling back to defines "
             "QQNX_PHYSICAL_SCREEN_WIDTH/QQNX_PHYSICAL_SCREEN_HEIGHT (%dx%d)",
             defSize.width(), defSize.height());
    return defSize;
#else
    if (primaryScreen)
        qWarning("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. "
                 "Could not determine physical screen size. Defaulting to 150x90.");
    return QSize(150, 90);
#endif
}

static QQnxWindow *findMultimediaWindow(const QList<QQnxWindow*> &windows,
                                                    const QByteArray &mmWindowId)
{
    Q_FOREACH (QQnxWindow *sibling, windows) {
        if (sibling->mmRendererWindowName() == mmWindowId)
            return sibling;

        QQnxWindow *mmWindow = findMultimediaWindow(sibling->children(), mmWindowId);

        if (mmWindow)
            return mmWindow;
    }

    return 0;
}

static QQnxWindow *findMultimediaWindow(const QList<QQnxWindow*> &windows,
                                                    screen_window_t mmWindowId)
{
    Q_FOREACH (QQnxWindow *sibling, windows) {
        if (sibling->mmRendererWindow() == mmWindowId)
            return sibling;

        QQnxWindow *mmWindow = findMultimediaWindow(sibling->children(), mmWindowId);

        if (mmWindow)
            return mmWindow;
    }

    return 0;
}

QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display, bool primaryScreen)
    : m_screenContext(screenContext),
      m_display(display),
      m_rootWindow(0),
      m_primaryScreen(primaryScreen),
      m_keyboardHeight(0),
      m_nativeOrientation(Qt::PrimaryOrientation),
      m_coverWindow(0),
      m_cursor(new QQnxCursor())
{
    qScreenDebug();
    // Cache initial orientation of this display
    int result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ROTATION,
                                                &m_initialRotation);
    Q_SCREEN_CHECKERROR(result, "Failed to query display rotation");

    m_currentRotation = m_initialRotation;

    // Cache size of this display in pixels
    int val[2];
    Q_SCREEN_CRITICALERROR(screen_get_display_property_iv(m_display, SCREEN_PROPERTY_SIZE, val),
                        "Failed to query display size");

    m_currentGeometry = m_initialGeometry = QRect(0, 0, val[0], val[1]);

    char name[100];
    Q_SCREEN_CHECKERROR(screen_get_display_property_cv(m_display, SCREEN_PROPERTY_ID_STRING, 100,
                                                       name), "Failed to query display name");
    m_name = QString::fromUtf8(name);

    // Cache size of this display in millimeters. We have to take care of the orientation.
    // libscreen always reports the physical size dimensions as width and height in the
    // returned dimensions to follow the current orientation.
    const QSize screenSize = determineScreenSize(m_display, primaryScreen);

    m_nativeOrientation = screenSize.width() >= screenSize.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation;

    const int angle = screen()->angleBetween(m_nativeOrientation, orientation());
    if (angle == 0 || angle == 180)
        m_currentPhysicalSize = m_initialPhysicalSize = screenSize;
    else
        m_currentPhysicalSize = m_initialPhysicalSize = screenSize.transposed();
}

QQnxScreen::~QQnxScreen()
{
    qScreenDebug();
    Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
        childWindow->setScreen(0);

    if (m_coverWindow)
        m_coverWindow->setScreen(0);

    delete m_cursor;
}

QPixmap QQnxScreen::grabWindow(WId window, int x, int y, int width, int height) const
{
    QQnxWindow *qnxWin = findWindow(reinterpret_cast<screen_window_t>(window));
    if (!qnxWin) {
        qWarning("grabWindow: unknown window");
        return QPixmap();
    }

    QRect bound = qnxWin->geometry();

    if (width < 0)
        width = bound.width();
    if (height < 0)
        height = bound.height();

    bound &= QRect(x + bound.x(), y + bound.y(), width, height);

    if (bound.width() <= 0 || bound.height() <= 0) {
        qWarning("grabWindow: size is null");
        return QPixmap();
    }

    // Create new context, only SCREEN_DISPLAY_MANAGER_CONTEXT can read from screen
    screen_context_t context;
    if (screen_create_context(&context, SCREEN_DISPLAY_MANAGER_CONTEXT)) {
        if (errno == EPERM)
            qWarning("grabWindow: root privileges required");
        else
            qWarning("grabWindow: cannot create context");
        return QPixmap();
    }

    // Find corresponding display in SCREEN_DISPLAY_MANAGER_CONTEXT
    int count = 0;
    screen_display_t display = 0;
    screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &count);
    if (count > 0) {
        const size_t idLen = 30;
        char matchId[idLen];
        char id[idLen];
        bool found = false;

        screen_display_t *displays = static_cast<screen_display_t*>
                                     (calloc(count, sizeof(screen_display_t)));
        screen_get_context_property_pv(context, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
        screen_get_display_property_cv(m_display,  SCREEN_PROPERTY_ID_STRING, idLen, matchId);

        while (count && !found) {
            --count;
            screen_get_display_property_cv(displays[count], SCREEN_PROPERTY_ID_STRING, idLen, id);
            found = !strncmp(id, matchId, idLen);
        }

        if (found)
            display = displays[count];

        free(displays);
    }

    // Create screen and Qt pixmap
    screen_pixmap_t pixmap;
    QPixmap result;
    if (display && !screen_create_pixmap(&pixmap, context)) {
        screen_buffer_t buffer;
        void *pointer;
        int stride;
        const int rect[4] = { bound.x(), bound.y(), bound.width(), bound.height() };

        int val = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
        screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_USAGE, &val);
        val = SCREEN_FORMAT_RGBA8888;
        screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_FORMAT, &val);

        int err =    screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
        err = err || screen_create_pixmap_buffer(pixmap);
        err = err || screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_RENDER_BUFFERS,
                                                   reinterpret_cast<void**>(&buffer));
        err = err || screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, &pointer);
        err = err || screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride);
        err = err || screen_read_display(display, buffer, 1, rect, 0);

        if (!err) {
            const QImage img(static_cast<unsigned char*>(pointer),
                             bound.width(), bound.height(), stride, QImage::Format_ARGB32);
            result = QPixmap::fromImage(img);
        } else {
            qWarning("grabWindow: capture error");
        }
        screen_destroy_pixmap(pixmap);
    } else {
        qWarning("grabWindow: display/pixmap error ");
    }
    screen_destroy_context(context);

    return result;
}

static int defaultDepth()
{
    qScreenDebug();
    static int defaultDepth = 0;
    if (defaultDepth == 0) {
        // check if display depth was specified in environment variable;
        // use default value if no valid value found
        defaultDepth = qEnvironmentVariableIntValue("QQNX_DISPLAY_DEPTH");
        if (defaultDepth != 16 && defaultDepth != 32)
            defaultDepth = 32;
    }
    return defaultDepth;
}

QRect QQnxScreen::availableGeometry() const
{
    qScreenDebug();
    // available geometry = total geometry - keyboard
    return QRect(m_currentGeometry.x(), m_currentGeometry.y(),
                 m_currentGeometry.width(), m_currentGeometry.height() - m_keyboardHeight);
}

int QQnxScreen::depth() const
{
    return defaultDepth();
}

qreal QQnxScreen::refreshRate() const
{
    screen_display_mode_t displayMode;
    int result = screen_get_display_property_pv(m_display, SCREEN_PROPERTY_MODE, reinterpret_cast<void **>(&displayMode));
    // Screen shouldn't really return 0 but it does so default to 60 or things break.
    if (result != 0 || displayMode.refresh == 0) {
        qWarning("QQnxScreen: Failed to query screen mode. Using default value of 60Hz");
        return 60.0;
    }
    qScreenDebug("screen mode:\n"
                 "      width = %u\n"
                 "     height = %u\n"
                 "    refresh = %u\n"
                 " interlaced = %u",
                 uint(displayMode.width), uint(displayMode.height), uint(displayMode.refresh), uint(displayMode.interlaced));
    return static_cast<qreal>(displayMode.refresh);
}

Qt::ScreenOrientation QQnxScreen::nativeOrientation() const
{
    return m_nativeOrientation;
}

Qt::ScreenOrientation QQnxScreen::orientation() const
{
    Qt::ScreenOrientation orient;
    if (m_nativeOrientation == Qt::LandscapeOrientation) {
        // Landscape devices e.g. PlayBook
        if (m_currentRotation == 0)
            orient = Qt::LandscapeOrientation;
        else if (m_currentRotation == 90)
            orient = Qt::PortraitOrientation;
        else if (m_currentRotation == 180)
            orient = Qt::InvertedLandscapeOrientation;
        else
            orient = Qt::InvertedPortraitOrientation;
    } else {
        // Portrait devices e.g. Phones
        // ###TODO Check these on an actual phone device
        if (m_currentRotation == 0)
            orient = Qt::PortraitOrientation;
        else if (m_currentRotation == 90)
            orient = Qt::LandscapeOrientation;
        else if (m_currentRotation == 180)
            orient = Qt::InvertedPortraitOrientation;
        else
            orient = Qt::InvertedLandscapeOrientation;
    }
    qScreenDebug() << "orientation =" << orient;
    return orient;
}

QWindow *QQnxScreen::topLevelAt(const QPoint &point) const
{
    for (auto it = m_childWindows.rbegin(), end = m_childWindows.rend(); it != end; ++it) {
        QWindow *win = (*it)->window();
        if (win->geometry().contains(point))
            return win;
    }
    return 0;
}

/*!
    Check if the supplied angles are perpendicular to each other.
*/
static bool isOrthogonal(int angle1, int angle2)
{
    return ((angle1 - angle2) % 180) != 0;
}

void QQnxScreen::setRotation(int rotation)
{
    qScreenDebug("orientation = %d", rotation);
    // Check if rotation changed
    // We only want to rotate if we are the primary screen
    if (m_currentRotation != rotation && isPrimaryScreen()) {
        // Update rotation of root window
        if (rootWindow())
            rootWindow()->setRotation(rotation);

        const QRect previousScreenGeometry = geometry();

        // Swap dimensions if we've rotated 90 or 270 from initial orientation
        if (isOrthogonal(m_initialRotation, rotation)) {
            m_currentGeometry = QRect(0, 0, m_initialGeometry.height(), m_initialGeometry.width());
            m_currentPhysicalSize = QSize(m_initialPhysicalSize.height(), m_initialPhysicalSize.width());
        } else {
            m_currentGeometry = QRect(0, 0, m_initialGeometry.width(), m_initialGeometry.height());
            m_currentPhysicalSize = m_initialPhysicalSize;
        }

        // Resize root window if we've rotated 90 or 270 from previous orientation
        if (isOrthogonal(m_currentRotation, rotation)) {
            qScreenDebug() << "resize, size =" << m_currentGeometry.size();
            if (rootWindow())
                rootWindow()->setGeometry(QRect(QPoint(0,0), m_currentGeometry.size()));

            resizeWindows(previousScreenGeometry);
        } else {
            // TODO: Find one global place to flush display updates
            // Force immediate display update if no geometry changes required
            screen_flush_context(nativeContext(), 0);
        }

        // Save new rotation
        m_currentRotation = rotation;

        // TODO: check if other screens are supposed to rotate as well and/or whether this depends
        // on if clone mode is being used.
        // Rotating only the primary screen is what we had in the navigator event handler before refactoring
        if (m_primaryScreen) {
            QWindowSystemInterface::handleScreenOrientationChange(screen(), orientation());
            QWindowSystemInterface::handleScreenGeometryChange(screen(), m_currentGeometry, availableGeometry());
        }

        // Flush everything, so that the windows rotations are applied properly.
        // Needed for non-maximized windows
        screen_flush_context( m_screenContext, 0 );
    }
}

/*!
  Resize the given window proportionally to the screen geometry
*/
void QQnxScreen::resizeNativeWidgetWindow(QQnxWindow *w, const QRect &previousScreenGeometry) const
{
    const qreal relativeX = static_cast<qreal>(w->geometry().topLeft().x()) / previousScreenGeometry.width();
    const qreal relativeY = static_cast<qreal>(w->geometry().topLeft().y()) / previousScreenGeometry.height();
    const qreal relativeWidth = static_cast<qreal>(w->geometry().width()) / previousScreenGeometry.width();
    const qreal relativeHeight = static_cast<qreal>(w->geometry().height()) / previousScreenGeometry.height();

    const QRect windowGeometry(relativeX * geometry().width(), relativeY * geometry().height(),
            relativeWidth * geometry().width(), relativeHeight * geometry().height());

    w->setGeometry(windowGeometry);
}

/*!
  Resize the given window to fit the screen geometry
*/
void QQnxScreen::resizeTopLevelWindow(QQnxWindow *w, const QRect &previousScreenGeometry) const
{
    QRect windowGeometry = w->geometry();

    const qreal relativeCenterX = static_cast<qreal>(w->geometry().center().x()) / previousScreenGeometry.width();
    const qreal relativeCenterY = static_cast<qreal>(w->geometry().center().y()) / previousScreenGeometry.height();
    const QPoint newCenter(relativeCenterX * geometry().width(), relativeCenterY * geometry().height());

    windowGeometry.moveCenter(newCenter);

    // adjust center position in case the window
    // is clipped
    if (!geometry().contains(windowGeometry)) {
        const int x1 = windowGeometry.x();
        const int y1 = windowGeometry.y();
        const int x2 = x1 + windowGeometry.width();
        const int y2 = y1 + windowGeometry.height();

        if (x1 < 0) {
            const int centerX = qMin(qAbs(x1) + windowGeometry.center().x(),
                                        geometry().center().x());

            windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
        }

        if (y1 < 0) {
            const int centerY = qMin(qAbs(y1) + windowGeometry.center().y(),
                                        geometry().center().y());

            windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
        }

        if (x2 > geometry().width()) {
            const int centerX = qMax(windowGeometry.center().x() - (x2 - geometry().width()),
                                        geometry().center().x());

            windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
        }

        if (y2 > geometry().height()) {
            const int centerY = qMax(windowGeometry.center().y() - (y2 - geometry().height()),
                                        geometry().center().y());

            windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
        }
    }

    // at this point, if the window is still clipped,
    // it means that it's too big to fit on the screen,
    // so we need to proportionally shrink it
    if (!geometry().contains(windowGeometry)) {
        QSize newSize = windowGeometry.size();
        newSize.scale(geometry().size(), Qt::KeepAspectRatio);
        windowGeometry.setSize(newSize);

        if (windowGeometry.x() < 0)
            windowGeometry.moveCenter(QPoint(geometry().center().x(), windowGeometry.center().y()));

        if (windowGeometry.y() < 0)
            windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), geometry().center().y()));
    }

    w->setGeometry(windowGeometry);
}

/*!
  Adjust windows to the new screen geometry.
*/
void QQnxScreen::resizeWindows(const QRect &previousScreenGeometry)
{
    resizeMaximizedWindows();

    Q_FOREACH (QQnxWindow *w, m_childWindows) {

        if (w->window()->windowState() & Qt::WindowFullScreen || w->window()->windowState() & Qt::WindowMaximized)
            continue;

        if (w->parent()) {
            // This is a native (non-alien) widget window
            resizeNativeWidgetWindow(w, previousScreenGeometry);
        } else {
            // This is a toplevel window
            resizeTopLevelWindow(w, previousScreenGeometry);
        }
    }
}

QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle) const
{
    Q_FOREACH (QQnxWindow *window, m_childWindows) {
        QQnxWindow * const result = window->findWindow(windowHandle);
        if (result)
            return result;
    }

    return 0;
}

void QQnxScreen::addWindow(QQnxWindow *window)
{
    qScreenDebug() << "window =" << window;

    if (m_childWindows.contains(window))
        return;

    if (window->window()->type() != Qt::CoverWindow) {
        // Ensure that the desktop window is at the bottom of the zorder.
        // If we do not do this then we may end up activating the desktop
        // when the navigator service gets an event that our window group
        // has been activated (see QQnxScreen::activateWindowGroup()).
        // Such a situation would strangely break focus handling due to the
        // invisible desktop widget window being layered on top of normal
        // windows
        if (window->window()->type() == Qt::Desktop)
            m_childWindows.push_front(window);
        else
            m_childWindows.push_back(window);
        updateHierarchy();
    }
}

void QQnxScreen::removeWindow(QQnxWindow *window)
{
    qScreenDebug() << "window =" << window;

    if (window != m_coverWindow) {
        const int numWindowsRemoved = m_childWindows.removeAll(window);
        if (window == m_rootWindow) //We just removed the root window
            m_rootWindow = 0; //TODO we need a new root window ;)
        if (numWindowsRemoved > 0)
            updateHierarchy();
    } else {
        m_coverWindow = 0;
    }
}

void QQnxScreen::raiseWindow(QQnxWindow *window)
{
    qScreenDebug() << "window =" << window;

    if (window != m_coverWindow) {
        removeWindow(window);
        m_childWindows.push_back(window);
    }
}

void QQnxScreen::lowerWindow(QQnxWindow *window)
{
    qScreenDebug() << "window =" << window;

    if (window != m_coverWindow) {
        removeWindow(window);
        m_childWindows.push_front(window);
    }
}

void QQnxScreen::updateHierarchy()
{
    qScreenDebug();

    QList<QQnxWindow*>::const_iterator it;
    int result;
    int topZorder = 0;

    errno = 0;
    if (rootWindow()) {
        result = screen_get_window_property_iv(rootWindow()->nativeHandle(), SCREEN_PROPERTY_ZORDER, &topZorder);
        if (result != 0) { //This can happen if we use winId in QWidgets
            topZorder = 10;
            qWarning("QQnxScreen: failed to query root window z-order, errno=%d", errno);
        }
    } else {
        topZorder = 0;  //We do not need z ordering on the secondary screen, because only one window
                        //is supported there
    }

    topZorder++; // root window has the lowest z-order in the windowgroup

    int underlayZorder = -1;
    // Underlays sit immediately above the root window in the z-ordering
    Q_FOREACH (screen_window_t underlay, m_underlays) {
        // Do nothing when this fails. This can happen if we have stale windows in m_underlays,
        // which in turn can happen because a window was removed but we didn't get a notification
        screen_set_window_property_iv(underlay, SCREEN_PROPERTY_ZORDER, &underlayZorder);
        underlayZorder--;
    }

    // Normal Qt windows come next above the root window z-ordering
    for (it = m_childWindows.constBegin(); it != m_childWindows.constEnd(); ++it)
        (*it)->updateZorder(topZorder);

    // Finally overlays sit above all else in the z-ordering

    // After a hierarchy update, we need to force a flush on all screens.
    // Right now, all screens share a context.
    screen_flush_context(m_screenContext, 0);
}

void QQnxScreen::adjustOrientation()
{
    if (!m_primaryScreen)
        return;

    bool ok = false;
    const int rotation = qEnvironmentVariableIntValue("ORIENTATION", &ok);

    if (ok)
        setRotation(rotation);
}

QPlatformCursor * QQnxScreen::cursor() const
{
    return m_cursor;
}

void QQnxScreen::keyboardHeightChanged(int height)
{
    if (height == m_keyboardHeight)
        return;

    m_keyboardHeight = height;

    QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
}

void QQnxScreen::addOverlayWindow(screen_window_t window)
{
    m_overlays.append(window);
    updateHierarchy();
}

void QQnxScreen::addUnderlayWindow(screen_window_t window)
{
    m_underlays.append(window);
    updateHierarchy();
}

void QQnxScreen::addMultimediaWindow(const QByteArray &id, screen_window_t window)
{
    // find the QnxWindow this mmrenderer window is related to
    QQnxWindow *mmWindow = findMultimediaWindow(m_childWindows, id);

    if (!mmWindow)
        return;

    mmWindow->setMMRendererWindow(window);

    updateHierarchy();
}

void QQnxScreen::removeOverlayOrUnderlayWindow(screen_window_t window)
{
    const int numRemoved = m_overlays.removeAll(window) + m_underlays.removeAll(window);
    if (numRemoved > 0) {
        updateHierarchy();
        Q_EMIT foreignWindowClosed(window);
    }
}

void QQnxScreen::newWindowCreated(void *window)
{
    Q_ASSERT(thread() == QThread::currentThread());
    const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window);
    screen_display_t display = 0;
    if (screen_get_window_property_pv(windowHandle, SCREEN_PROPERTY_DISPLAY, (void**)&display) != 0) {
        qWarning("QQnx: Failed to get screen for window, errno=%d", errno);
        return;
    }

    int zorder;
    if (screen_get_window_property_iv(windowHandle, SCREEN_PROPERTY_ZORDER, &zorder) != 0) {
        qWarning("QQnx: Failed to get z-order for window, errno=%d", errno);
        zorder = 0;
    }

    char windowNameBuffer[256] = { 0 };
    QByteArray windowName;

    if (screen_get_window_property_cv(windowHandle, SCREEN_PROPERTY_ID_STRING,
                sizeof(windowNameBuffer) - 1, windowNameBuffer) != 0) {
        qWarning("QQnx: Failed to get id for window, errno=%d", errno);
    }

    windowName = QByteArray(windowNameBuffer);

    if (display == nativeDisplay()) {
        // A window was created on this screen. If we don't know about this window yet, it means
        // it was not created by Qt, but by some foreign library like the multimedia renderer, which
        // creates an overlay window when playing a video.
        // Treat all foreign windows as overlays, underlays or as windows
        // created by the BlackBerry QtMultimedia plugin.
        // In the case of the BlackBerry QtMultimedia plugin, we need to
        // "attach" the foreign created mmrenderer window to the correct
        // platform window (usually the one belonging to QVideoWidget) to
        // ensure proper z-ordering.
        // Otherwise, assume that if a foreign window already has a Z-Order both negative and
        // less than the default Z-Order installed by mmrender on windows it creates,
        // the windows should be treated as an underlay. Otherwise, we treat it as an overlay.
        if (!windowName.isEmpty() && windowName.startsWith("MmRendererVideoWindowControl")) {
            addMultimediaWindow(windowName, windowHandle);
        } else if (!findWindow(windowHandle)) {
            if (zorder <= MAX_UNDERLAY_ZORDER)
                addUnderlayWindow(windowHandle);
            else
                addOverlayWindow(windowHandle);
            Q_EMIT foreignWindowCreated(windowHandle);
        }
    }
}

void QQnxScreen::windowClosed(void *window)
{
    Q_ASSERT(thread() == QThread::currentThread());
    const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window);

    QQnxWindow *mmWindow = findMultimediaWindow(m_childWindows, windowHandle);

    if (mmWindow)
        mmWindow->clearMMRendererWindow();
    else
        removeOverlayOrUnderlayWindow(windowHandle);
}

void QQnxScreen::windowGroupStateChanged(const QByteArray &id, Qt::WindowState state)
{
    qScreenDebug();

    if (!rootWindow() || id != rootWindow()->groupName())
        return;

    QWindow * const window = rootWindow()->window();

    if (!window)
        return;

    QWindowSystemInterface::handleWindowStateChanged(window, state);
}

void QQnxScreen::activateWindowGroup(const QByteArray &id)
{
    qScreenDebug();

    if (!rootWindow() || id != rootWindow()->groupName())
        return;

    QWindow * const window = rootWindow()->window();

    if (!window)
        return;

    Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
        childWindow->setExposed(true);

    if (m_coverWindow)
        m_coverWindow->setExposed(false);
}

void QQnxScreen::deactivateWindowGroup(const QByteArray &id)
{
    qScreenDebug();

    if (!rootWindow() || id != rootWindow()->groupName())
        return;

    if (m_coverWindow)
        m_coverWindow->setExposed(true);

    Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
        childWindow->setExposed(false);
}

QQnxWindow *QQnxScreen::rootWindow() const
{
    return m_rootWindow;
}

void QQnxScreen::setRootWindow(QQnxWindow *window)
{
    // Optionally disable the screen power save
    bool ok = false;
    const int disablePowerSave = qEnvironmentVariableIntValue("QQNX_DISABLE_POWER_SAVE", &ok);
    if (ok && disablePowerSave) {
        const int mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
        int result = screen_set_window_property_iv(window->nativeHandle(), SCREEN_PROPERTY_IDLE_MODE, &mode);
        if (result != 0)
            qWarning("QQnxRootWindow: failed to disable power saving mode");
    }
    m_rootWindow = window;
}

QT_END_NAMESPACE


try
    {
        _fd = createSocket(false, _addr);
        setBlock(_fd, false);
        setTcpBufSize(_fd, _instance);
        setReuseAddress(_fd, true);
    }
    catch(...)
    {
        _fd = INVALID_SOCKET;
        throw;
    }

#include <Ice/Config.h>

#if TARGET_OS_IPHONE != 0

#include "StreamTransceiver.h"
#include "StreamEndpointI.h"
#include "StreamAcceptor.h"

#include <IceUtil/StringUtil.h>

#include <Ice/Instance.h>
#include <Ice/UniqueRef.h>
#include <Ice/Network.h>
#include <Ice/Exception.h>
#include <Ice/Properties.h>

#include <CoreFoundation/CoreFoundation.h>

using namespace std;
using namespace Ice;
using namespace IceInternal;

NativeInfoPtr
IceObjC::StreamAcceptor::getNativeInfo()
{
    return this;
}

void
IceObjC::StreamAcceptor::close()
{
    if(_fd != INVALID_SOCKET)
    {
        closeSocketNoThrow(_fd);
        _fd = INVALID_SOCKET;
    }
}

EndpointIPtr
IceObjC::StreamAcceptor::listen()
{
    try
    {
        const_cast<Address&>(_addr) = doBind(_fd, _addr);
        doListen(_fd, _backlog);
    }
    catch(...)
    {
        _fd = INVALID_SOCKET;
        throw;
    }

    _endpoint = _endpoint->endpoint(this);
    return _endpoint;
}

TransceiverPtr
IceObjC::StreamAcceptor::accept()
{
    SOCKET fd = doAccept(_fd);
    setBlock(fd, false);
    setTcpBufSize(fd, _instance);

    // Create the read/write streams
    UniqueRef<CFReadStreamRef> readStream;
    UniqueRef<CFWriteStreamRef> writeStream;
    try
    {
        CFStreamCreatePairWithSocket(ICE_NULLPTR, fd, &readStream.get(), &writeStream.get());
        _instance->setupStreams(readStream.get(), writeStream.get(), true, "");
        return new StreamTransceiver(_instance, readStream.release(), writeStream.release(), fd);
    }
    catch(const Ice::LocalException& ex)
    {
        if(fd != INVALID_SOCKET)
        {
            closeSocketNoThrow(fd);
        }
        throw;
    }
}

string
IceObjC::StreamAcceptor::protocol() const
{
    return _instance->protocol();
}

string
IceObjC::StreamAcceptor::toString() const
{
    return addrToString(_addr);
}

string
IceObjC::StreamAcceptor::toDetailedString() const
{
    ostringstream os;
    os << "local address = " << toString();
    vector<string> intfs = getHostsForEndpointExpand(inetAddrToString(_addr), _instance->protocolSupport(), true);
    if(!intfs.empty())
    {
        os << "\nlocal interfaces = ";
        os << IceUtilInternal::joinString(intfs, ", ");
    }
    return os.str();
}

int
IceObjC::StreamAcceptor::effectivePort() const
{
    return getPort(_addr);
}

IceObjC::StreamAcceptor::StreamAcceptor(const StreamEndpointIPtr& endpoint,
                                        const InstancePtr& instance,
                                        const string& host,
                                        int port) :
    _endpoint(endpoint),
    _instance(instance),
    _addr(getAddressForServer(host, port, instance->protocolSupport(), instance->preferIPv6(), true))
{
#ifdef SOMAXCONN
    _backlog = instance->properties()->getPropertyAsIntWithDefault("Ice.TCP.Backlog", SOMAXCONN);
#else
    _backlog = instance->properties()->getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511);
#endif

}

IceObjC::StreamAcceptor::~StreamAcceptor()
{
    assert(_fd == INVALID_SOCKET);
}

#endif