[Merge] lp:~nick-dedekind/qtubuntu/stagedFullscreen.form-factor into lp:qtubuntu

Michał Sawicz michal.sawicz at canonical.com
Thu Feb 4 16:02:42 UTC 2016


Review: Needs Fixing



Diff comments:

> 
> === modified file 'src/ubuntumirclient/screen.cpp'
> --- src/ubuntumirclient/screen.cpp	2015-12-09 13:01:28 +0000
> +++ src/ubuntumirclient/screen.cpp	2016-02-04 14:19:36 +0000
> @@ -278,3 +230,38 @@
>          QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
>      }
>  }
> +
> +void UbuntuScreen::setMirDisplayOutput(const MirDisplayOutput &output)
> +{
> +    // Physical screen size
> +    mPhysicalSize.setWidth(output.physical_width_mm);
> +    mPhysicalSize.setHeight(output.physical_height_mm);
> +
> +    // Pixel Format
> +//    mFormat = qImageFormatFromMirPixelFormat(output.current_format); // GERRY: TODO

Convert GERRYs to TODOs :)

> +
> +    // Pixel depth
> +    mDepth = 8 * MIR_BYTES_PER_PIXEL(output.current_format);
> +
> +    MirDisplayMode mode = output.modes[output.current_mode];
> +    const int kScreenWidth = mode.horizontal_resolution;
> +    const int kScreenHeight = mode.vertical_resolution;
> +
> +    mGeometry = QRect(0, 0, kScreenWidth, kScreenHeight);
> +
> +    // Misc
> +//    mScale = output.scale; // missing from MirDisplayOutput, wait for later setAdditionalMirDisplayProperties call
> +//    mFormFactor = output.form_factor; // ditto

Is this ever going to show up on MirDisplayOutput? If not, maybe scrap those from here, only leaving a comment that anything else comes in the other calls?

> +    mOutputId = output.output_id;
> +
> +    // Set the default orientation based on the initial screen dimmensions.
> +    mNativeOrientation = (mGeometry.width() >= mGeometry.height()) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
> +
> +    // If it's a landscape device (i.e. some tablets), start in landscape, otherwise portrait
> +    mCurrentOrientation = (mNativeOrientation == Qt::LandscapeOrientation) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
> +}
> +
> +void UbuntuScreen::setAdditionalMirDisplayProperties(MirFormFactor formFactor)
> +{
> +    mFormFactor = formFactor;
> +}
> 
> === added file 'src/ubuntumirclient/screenobserver.cpp'
> --- src/ubuntumirclient/screenobserver.cpp	1970-01-01 00:00:00 +0000
> +++ src/ubuntumirclient/screenobserver.cpp	2016-02-04 14:19:36 +0000
> @@ -0,0 +1,130 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.

2016

> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU Lesser General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "screenobserver.h"
> +#include "screen.h"
> +#include "window.h"
> +#include "logging.h"
> +
> +// Qt
> +#include <QMetaObject>
> +#include <QPointer>
> +#include <private/qwindow_p.h>
> +
> +// Mir
> +#include <mirclient/mir_toolkit/mir_connection.h>
> +
> +#include <memory>
> +
> +namespace {
> +    static void displayConfigurationChangedCallback(MirConnection */*connection*/, void* context)
> +    {
> +        ASSERT(context != NULL);
> +        UbuntuScreenObserver *observer = static_cast<UbuntuScreenObserver *>(context);
> +        QMetaObject::invokeMethod(observer, "update");
> +    }
> +} // anonymous namespace
> +
> +UbuntuScreenObserver::UbuntuScreenObserver(MirConnection *mirConnection)
> +    : mMirConnection(mirConnection)
> +{
> +    mir_connection_set_display_config_change_callback(mirConnection, ::displayConfigurationChangedCallback, this);
> +    update();
> +}
> +
> +void UbuntuScreenObserver::update()
> +{
> +    // Wrap MirDisplayConfiguration to always delete when out of scope
> +    auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); };
> +    using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>;
> +    configUp displayConfig(mir_connection_create_display_config(mMirConnection), configDeleter);
> +
> +    // Mir only tells us something changed, it is up to us to figure out what.
> +    QList<UbuntuScreen*> newScreenList;
> +    QList<UbuntuScreen*> oldScreenList = mScreenList;
> +    mScreenList.clear();
> +
> +    for (uint32_t i=0; i<displayConfig->num_outputs; i++) {
> +        MirDisplayOutput output = displayConfig->outputs[i];
> +        if (output.used && output.connected) {
> +            UbuntuScreen *screen = findScreenWithId(oldScreenList, output.output_id);
> +            if (screen) { // we've already set up this display before, refresh its internals
> +                screen->setMirDisplayOutput(output);
> +                oldScreenList.removeAll(screen);
> +            } else {
> +                // new display, so create UbuntuScreen for it
> +                screen = new UbuntuScreen(output, mMirConnection);
> +                newScreenList.append(screen);
> +                qDebug() << "Added Screen with id" << output.output_id << "and geometry" << screen->geometry();
> +            }
> +            mScreenList.append(screen);
> +        }
> +    }
> +
> +    // Delete any old & unused Screens
> +    Q_FOREACH (const auto screen, oldScreenList) {
> +        qDebug() << "Removed Screen with id" << screen->outputId() << "and geometry" << screen->geometry();
> +        // The screen is automatically removed from Qt's internal list by the QPlatformScreen destructor.
> +        delete screen;
> +    }
> +
> +    /*
> +     * Mir's MirDisplayOutput does not include formFactor or scale for some reason, but Qt
> +     * will want that information on creating the QScreen. Only way we get that info is when
> +     * Mir positions a Window on that Screen. It's ugly, but will have to re-create the window
> +     * again, after that happens. See "handleScreenPropertiesChange" method
> +     */
> +    Q_FOREACH (const auto screen, newScreenList) {
> +        Q_EMIT screenAdded(screen);
> +    }
> +
> +    qDebug() << "=======================================";
> +    for (auto screen: mScreenList) {
> +        qDebug() << screen << "- id:" << screen->outputId()
> +                           << "geometry:" << screen->geometry()
> +                           << "form factor:" << screen->formFactor();
> +    }
> +    qDebug() << "=======================================";
> +}
> +
> +UbuntuScreen *UbuntuScreenObserver::findScreenWithId(uint32_t id)
> +{
> +    return findScreenWithId(mScreenList, id);
> +}
> +
> +UbuntuScreen *UbuntuScreenObserver::findScreenWithId(const QList<UbuntuScreen *> &list, uint32_t id)
> +{
> +    Q_FOREACH (const auto screen, list) {
> +        if (screen->outputId() == id) {
> +            return screen;
> +        }
> +    }
> +    return nullptr;
> +}
> +
> +void UbuntuScreenObserver::handleScreenPropertiesChange(UbuntuScreen *screen, MirFormFactor formFactor)
> +{
> +    screen->setAdditionalMirDisplayProperties(formFactor);
> +
> +    qDebug() << "=======================================";
> +    for (auto screen: mScreenList) {
> +        qDebug() << screen << "- id:" << screen->outputId()
> +                           << "geometry:" << screen->geometry()
> +                           << "form factor:" << screen->formFactor();
> +    }
> +    qDebug() << "=======================================";
> +}
> +
> 
> === added file 'src/ubuntumirclient/screenobserver.h'
> --- src/ubuntumirclient/screenobserver.h	1970-01-01 00:00:00 +0000
> +++ src/ubuntumirclient/screenobserver.h	2016-02-04 14:19:36 +0000
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.

2016

> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU Lesser General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef UBUNTU_SCREEN_OBSERVER_H
> +#define UBUNTU_SCREEN_OBSERVER_H
> +
> +#include <QObject>
> +
> +#include <mir_toolkit/mir_connection.h>
> +
> +struct MirConnection;
> +class UbuntuScreen;
> +class UbuntuWindow;
> +
> +class UbuntuScreenObserver : public QObject
> +{
> +    Q_OBJECT
> +
> +public:
> +    UbuntuScreenObserver(MirConnection *connection);
> +
> +    QList<UbuntuScreen*> screens() const { return mScreenList; }
> +    UbuntuScreen *findScreenWithId(uint32_t id);
> +
> +    void handleScreenPropertiesChange(UbuntuScreen *screen, MirFormFactor formFactor);
> +
> +Q_SIGNALS:
> +    void screenAdded(UbuntuScreen *screen);
> +
> +private Q_SLOTS:
> +    void update();
> +
> +private:
> +    UbuntuScreen *findScreenWithId(const QList<UbuntuScreen *> &list, uint32_t id);
> +
> +    MirConnection *mMirConnection;
> +    QList<UbuntuScreen*> mScreenList;
> +};
> +
> +#endif // UBUNTU_SCREEN_OBSERVER_H
> 
> === modified file 'src/ubuntumirclient/window.cpp'
> --- src/ubuntumirclient/window.cpp	2016-02-02 11:07:38 +0000
> +++ src/ubuntumirclient/window.cpp	2016-02-04 14:19:36 +0000
> @@ -98,6 +84,80 @@
>      }
>  }
>  
> +const char *mirFormFactorToStr(MirFormFactor formFactor)
> +{
> +    switch (formFactor) {
> +    case mir_form_factor_unknown: return "unknown";
> +    case mir_form_factor_phone: return "phone";
> +    case mir_form_factor_tablet: return "tablet";
> +    case mir_form_factor_tv: return "tv";
> +    case mir_form_factor_monitor:return "monitor";
> +    case mir_form_factor_projector:return "projector";
> +    default: return "!?";
> +    }
> +}
> +
> +const char *mirSurfaceStateToStr(MirSurfaceState surfaceState)
> +{
> +    switch (surfaceState) {
> +    case mir_surface_state_unknown: return "unknown";
> +    case mir_surface_state_restored: return "restored";
> +    case mir_surface_state_minimized: return "minimized";
> +    case mir_surface_state_maximized: return "vertmaximized";
> +    case mir_surface_state_vertmaximized: return "vertmaximized";
> +    case mir_surface_state_fullscreen: return "fullscreen";
> +    case mir_surface_state_horizmaximized: return "horizmaximized";
> +    case mir_surface_state_hidden: return "hidden";
> +    default: return "!?";
> +    }
> +}
> +
> +MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
> +{
> +    switch (state) {
> +    case Qt::WindowNoState:
> +        return mir_surface_state_restored;
> +    case Qt::WindowFullScreen:
> +        return mir_surface_state_fullscreen;
> +    case Qt::WindowMaximized:
> +        return mir_surface_state_maximized;
> +    case Qt::WindowMinimized:
> +        return mir_surface_state_minimized;
> +    default:
> +        qCWarning(ubuntumirclient, "Unexpected Qt::WindowState: %d", state);
> +        return mir_surface_state_restored;
> +    }
> +}
> +
> +MirSurfaceState surfaceStateFromWindowProperties(MirFormFactor formFactor, Qt::WindowState state, Qt::WindowFlags flags, bool visible)
> +{
> +    if (!visible) return mir_surface_state_minimized;
> +
> +    bool showDecorationsHint = flags & WindowHidesShellDecorations;
> +    qDebug() << "showDecorationsHint" << showDecorationsHint << qtWindowStateToStr(state) << formFactor;
> +
> +    switch (formFactor) {
> +        case mir_form_factor_phone:
> +        case mir_form_factor_tablet:
> +        case mir_form_factor_tv:
> +            if (state == Qt::WindowFullScreen) {
> +                if (!showDecorationsHint) {
> +                    return mir_surface_state_fullscreen;
> +                }
> +                return mir_surface_state_restored;

Is that correct? Fullscreen should fullscreen, regardless of the flag?

Basically, if (flag && phone/tablet/tv) fullscreen; else return state;

But also, since you're overriding the state, shouldn't you store the previous value to restore to when flag is cleared?

> +            } else if (state == Qt::WindowNoState && showDecorationsHint) {
> +                return mir_surface_state_fullscreen;
> +            }
> +            break;
> +
> +        case mir_form_factor_unknown:
> +        case mir_form_factor_monitor:
> +        case mir_form_factor_projector:
> +            break;
> +    }
> +    return qtWindowStateToMirSurfaceState(state);
> +}
> +
>  WId makeId()
>  {
>      static int id = 1;
> @@ -633,3 +706,33 @@
>      QMutexLocker lock(&mMutex);
>      mSurface->onSwapBuffersDone();
>  }
> +
> +void UbuntuWindow::handleScreenPropertiesChange(MirFormFactor formFactor)
> +{
> +    qCDebug(ubuntumirclient, "handleScreenPropertiesChange (window=%p, formFactor=%s)", window(), mirFormFactorToStr);

ToStr...()?

> +
> +    // Update the form factor native-interface properties for the windows affected
> +    // as there is no convenient way to emit signals for those custom properties on a QScreen
> +    if (formFactor != mFormFactor) {
> +        mFormFactor = formFactor;
> +        updateSurfaceState();
> +
> +        Q_EMIT mNativeInterface->windowPropertyChanged(this, QStringLiteral("formFactor"));
> +    }
> +}
> +
> +void UbuntuWindow::updateSurfaceState()
> +{
> +    QMutexLocker lock(&mMutex);
> +    MirSurfaceState newState = surfaceStateFromWindowProperties(mFormFactor,
> +                                                                mWindowState,
> +                                                                mWindowFlags,
> +                                                                mWindowVisible);
> +    qCDebug(ubuntumirclient, "updateSurfaceState (window=%p, surfaceState=%s)", window(), mirSurfaceStateToStr(newState));
> +    if (newState != mSurface->state()) {
> +        mSurface->setState(newState);
> +
> +        lock.unlock();
> +        enablePanelHeightHack(newState != mir_surface_state_fullscreen);
> +    }
> +}


-- 
https://code.launchpad.net/~nick-dedekind/qtubuntu/stagedFullscreen.form-factor/+merge/284979
Your team Ubuntu Phablet Team is subscribed to branch lp:qtubuntu.



More information about the Ubuntu-reviews mailing list