[Development] Window{} API for QML
Alan Alpert
alan.alpert at nokia.com
Fri Nov 11 06:58:56 CET 2011
On Thu, 10 Nov 2011 18:29:58 Knoll Lars (Nokia-MP-Qt/Oslo) wrote:
> On 11/10/11 1:32 AM, "Alan Alpert" <alan.alpert at nokia.com> wrote:
> >On Wed, 9 Nov 2011 06:43:34 Knoll Lars (Nokia-MP-Qt/Oslo) wrote:
> >> I agree with most of the things in this thread, but not everything.
> >>
> >>Here's
> >>
> >> my thoughts:
> >>
> >> We need a Window {} element to create surfaces on a physical screen.
> >>
> >>This
> >>
> >> Window object should IMO be more or less a direct representation of
> >> QQuickView in QML.
> >>
> >> So far we all seem to agree. But I also do not see a need to limit the
> >> Window {} API to the mobile use cases. I'd rather that we expose the
> >>
> >>full
> >>
> >> functionality in one Object, and rather document some of the differences
> >> in behavior between mobile and desktop.
> >
> >I'm wary of trying to expose desktop APIs for desktop use cases,
> >especially
> >before Desktop QML is fully realized. We might end up exposing the wrong
> >then
> >and then we're at the same point as before plus we're maintaining and
> >supporting use-impaired code. I'm also not fond of providing an element
> >for
> >use in mobile contexts with functionality that basically says: "Don't use
> >this". If it's not to be used on those platforms, why even have it
> >available
> >for those platforms?
>
> I think we have quite some stuff to test it. Jens desktop components are
> IMO enough to test all the concepts required in terms of handling top
> level windows for the desktop.
Testing it is not the problem. The problem is understanding the needs and use-
cases of desktop QML, of which one research project is not a full sampling.
The approach of QML development so far has been conservative and use-case
driven development. Not putting in features, which would have to be
maintained, unless there is an important use-case which requires such
features. You can always drop down to C++ to do things that aren't exposed to
QML, and I think that's just fine (and necessary while QML is still
developing).
>
> >As far as I'm aware there is a lot of features in this gap. Window
> >decorations, modality, even geometry could be construed as desktop only.
>
> Depends. And don't forget there are also devices such as tablets that are
> something between desktop and mobile devices.
Previous generation tablets just used desktop APIs, current generation tablets
just use mobile APIs. I'd wait until they figure out their own personality
before we try to cater for them especially.
> >> Using the Window {} object anywhere in QML creates a new top level
> >>
> >>window.
> >>
> >> This implies that a Window{} as the root item of a QQuickView would
> >>
> >>create
> >>
> >> an empty QQuickView and a second top-level created through the WIndow
> >> object. But at least this would mean there's no magic involved.
> >
> >Yep.
> >
> >> Like that we can change the default way of using QML to be symmetric
> >> between Desktop and Mobile. You instantiate a QQuickEngine, and then
> >>
> >>load
> >>
> >> a QML file that contains a WIndow {} as the outermost element. If we
> >> remove the Window {} in QtComponents and use this instead, we can then
> >> make this fully symmetrical on the QML side between desktop and mobile.
> >> The only difference would be in the default behavior of Window (most
> >> likely full screen on mobile, windowed on desktop).
> >
> >One of the changes talked about on the qt-components mailing list is that
> >with
> >this approach you no longer have a Window{} as the outermost element in
> >desktop components.
>
> Why not? If you start a QQuickEngine instead of a View, then the Window{}
> can still be the outermost element. In fact this would IMO give us
> something more consistent. Of course you can still do a QQuickView
> directly, but then you don't have a Window as the outermost element
> anymore.
This should work, but I wouldn't think it would be the common case. The common
case of single window applications shouldn't have to look up this element, or
start with a specific root item (not in generic QML at least). I would still
like the ability for the QML using application to disable creation of sub-
windows, which would prevent you from starting with a Window{} in those cases.
> >I would rather have the C++ controlled windows exposed manually through
> >C++
> >and have the QML Window{}'s separate. This sounds easily exposed through
> >ApplicationWindow{} anyways.
>
> Not sure I understand what you mean here. If you use a QQuickWindow from
> C++, you also control it from C++. If you use a QML Window{} you can
> control it form QML.
>
I just mean that I prefer having the root window controllable only via C++,
like we have now, in the default case.
> >> Differentiation between mobile and desktop can then happen on the
> >> ApplicationWindow level in QtComponents, where the ApplicationWindow for
> >> the desktop would support menu- and toolbars, the mobile version would
> >> support pages and whatever else is needed there.
> >>
> >> In addition, it should be easy to associate a Window {} with a certain
> >> physical screen. For this I'd propose, we somehow expose the list of
> >> screens as objects in Qt.application, and give Window {} a screen
> >>
> >>property
> >>
> >> that can be bound to a screen.
> >>
> >> So
> >>
> >> Window {
> >>
> >> screen: Qt.application.primaryScreen // the default behavior
> >>
> >> }
> >>
> >> would create a Window on the primary screen.
> >>
> >> The main question I'm unsure about is what to do with Windows on screens
> >> that are going away (by unplugging the VGA cable going to the
> >>
> >>projectorÅ ).
> >
> >I've been thinking about the screen issue, and my conclusion was that
> >this
> >approach wouldn't work. Exposing the screens this way through
> >Qt.application
> >wasn't deemed useful in the QScreen API thread, and a lot of the same
> >problems
> >arise here. Aside from the primary screen, it will be very difficult to
> >bind
> >this window to the right other screen, you can't just go off of list
> >index
> >(except perhaps in the common case of external displays) so you need to
> >query
> >the new screens on screenAdded/startup and imperatively assign windows.
> >If
> >you're going to do it the imperative way anyways, you may as well do it
> >in C++
> >and just move Window{} objects out of the main QML file into another
> >canvas
> >(that way they were created in the same engine and have useful bindings).
>
> I tend to disagree. The reason is that you don't want to do many of these
> things from C++. I agree that an imperative API is not ideal, but we're
> having similar things in e.g. the PageStack.
Can you elaborate on "don't want to do many of these things from C++"?
I would agree that the common case should be doable easily from QML. But that
should be a really good, declarative, and simple API that emphasizes the
common case. QML does not have to 'support' the complete set of possible
functionality, because you can do all that from C++ if you need niche or
customized use-cases. The common case should have a streamlined QML API as
much as possible, so that you just place stuff in elements and it works.
Hooking up JS code and signals will raise the bar to only people who feel they
can code, QML is supposed to be easier than that ;) .
> >So here's my suggestion for what would work. Leave the general case for
> >C++ as
> >explained above, and offer a convenience of the common case of an
> >external
> >display. Example:
> >
> >ExternalDisplay{
> >
> > Rectangle{
> >
> > anchors.fill: parent
> >
> > }
> >
> >}
> >
> >Arguably you could require a Window instead and automatically rescreen
> >it, but
> >I prefer relaxing the restriction to any QQuickItem and it's just like
> >the
> >root item in another view.
> >
> >As you can guess, the effect of the ExternalDisplay{} is that it will
> >dynamically load and unload the child component and place it on any
> >secondary
> >display when it's available. The root item for that display will be
> >scaled
> >much like a QQuickView.
>
> Sounds like an interesting idea. But I'm not sure we should or need to
> limit ourselves to this.
>
> >I've been trying to prototype it recently, but my efforts are currently
> >stalled by the XCB plugin crashing when you try to do any GL on a
> >secondary
> >screen :( . So I'm sorry, but I don't have the code for this yet.
> >
> >> So my proposal would be something exposing most of the QWindow API:
> >>
> >> Window {
> >>
> >> property Screen screen
> >> property Orientation orientation // { Portrait, Landscape, Å }
> >
> >Isn't orientation a property of the screen? If we have a good screen API,
> >we
> >don't need to duplicate this in the window.
>
> There's two things that we need: A readonly property from the Screen
> telling us what the current physical orientation of the screen is. In
> addition, the app needs to tell the compositor what the orientation of the
> content of this window is. The two don't need to agree (think about a game
> that wants to enforce Landscape). Telling the compositor about the current
> orientation is important for use cases such as notifications or VKB.
>
> >> property Rect geometry // or x, y, width, height
> >> property WindowFlags windowflags
> >> property Window parent
> >
> >This won't work if the root Window is not a Window{}. I don't think we
> >can
> >just 'expose' QWindow as Window{}, as Window{} needs to create a new
> >QQuickCanvas and reparent the subtree. Nor do I like making QQuickView a
>
> If the root window is created in C++, you have to control it from C++.
>
> My idea was that we'd change the recommended way of creating apps from
> instantiating a QQuickView in C++ to instantiating a QQuickEngine in C++
> and then using Window{} from QML.
>
> Like that we'd get a much more symmetric ways of dealing with surfaces and
> have complete control over them from QML.
>
> >WindowItem, for reasons explained earlier. I'd actually prefer they stick
> >with
> >just the QQuickItem parent hierarchy and not add a third one, but that
> >would
> >require a bit of magic in mapToGlobal functions or such to support the
> >absolute positioning case (unless there's some aspect of the window
> >parenting
> >hierarchy that I'm unaware of).
> >
> >> property real opacity
> >> property string title
> >> ...
> >>
> >> }
> >>
> >> I'd go for a similar approach for Screen, basically exposing QScreen.
> >>
> >> If the API of these classes aren't suitable for direct use in QML (after
> >> adding properties with notifications of course), let's fix them. It's
> >>
> >>new
> >>
> >> API in Qt5 and we can still work on it and make it directly usable from
> >> QML.
> >
> >I'm not convinced it has to be *directly* usable from QML. I liked the
>
> I think this is something we need to aim for more. I don't see why making
> the API suitable for QML would have to compromise the C++ side. It
> probably would improve the C++ API as well.
I'm more referring to how QML wants a declarative API and C++ wants an
imperative API. Take QScreen, the existing imperative API is great for C++
(and usable in QML) but the declarative API suggested involves attached
properties. A lovely declarative syntax which creates a new QObject for every
item that wants to use it, from C++ you would just get the pointer directly
and that way is more convenient. So you wouldn't want to really change
QScreen, it's good for C++, but there are QML alternatives that are better. We
wouldn't want to expose QScreen both ways, because that's just going to
confuse people when they wonder about the difference or the find the wrong
docs first.
--
Alan Alpert
Senior Engineer
Nokia, Qt Development Frameworks
More information about the Development
mailing list