美文网首页
WindowManagerService探索——窗口主次序

WindowManagerService探索——窗口主次序

作者: Monster_de47 | 来源:发表于2019-03-26 22:02 被阅读0次

    前言

    上一章中通过添加Window为例,介绍了WMS的第一种职责——窗口管理,今天我们以上一章内容为基础,深入探索一下。众所周知,每个Window被添加或者更新后,WMS是怎样处理它们的显示次序呢?

    窗口的显示次序

    在addWindow()函数的前半部分中,WMS为窗口创建了用于描述窗口状态的WindowState,接下来便会为新建的窗口确定显示次序。为了方便窗口显示次序的管理,手机屏幕用X、Y、Z轴来表示,很奇怪的是,明明手机只有长宽的平面,为什么会有Z轴呢?这里就要简要说明一下WMS的窗口次序管理机制了,Z轴垂直于屏幕,从里指向外,这个次序也称作Z-Oder。前面章节中讲到的Type就是根据Z-Oder为依据定义的,理论上Type的值越大Z-Oder排序越靠前,窗口越靠近用户。

    主序与子序

    又回到上一章中提到的WindowState,这里看一下它的构造方法:

        WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
                WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
                int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
                PowerManagerWrapper powerManagerWrapper) {
            ...
    
            // 为子窗口分配Z-Oder
            if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
                // The multiplier here is to reserve space for multiple
                // windows in the same type layer.
                mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
                mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
                mIsChildWindow = true;
    
                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow);
                parentWindow.addChild(this, sWindowSubLayerComparator);
    
                mLayoutAttached = mAttrs.type !=
                        WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
                mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
                        || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
                mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER;
            } else {
                // 为普通窗口分配Z-Oder
                // The multiplier here is to reserve space for multiple
                // windows in the same type layer.
                mBaseLayer = mPolicy.getWindowLayerLw(this)
                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
                mSubLayer = 0;
                mIsChildWindow = false;
                mLayoutAttached = false;
                mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
                        || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
                mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
            }
            ... 
        }
    

    窗口的显示次序由两个成员变量描述:主序mBaseLayer和子序mSubLayer。主序用于描述窗口及其子窗口在所有窗口中的显示位置。而子序则描述了一个子窗口在其兄弟窗口中的显示位置。

    • 主序越大,则窗口及其子窗口的显示位置相对于其他窗口的位置越靠前。
    • 子序越大,则子窗口相对于其兄弟窗口的位置越靠前。
      对于父窗口而言,其主序取决于其类型,其子序则保持为0。而子窗口的主序与其父窗口一样,子序则取决于其类型。从上述代码可以看到,主序与子序的分配工作是由WindowManagerPolicy的两个成员函数getWindowLayerLw和getSubWindowLayerFromTypeLw完成的。

    窗口的主序:

    窗口类型 主序
    TYPE_UNIVERSE_BACKGROUND 11000
    TYPE_PHONE 31000
    TYPE_RECENTS_OVERLAY 51000
    TYPE_TOAST 61000
    TYPE_DREAM 81000
    TYPE_INPUT_METHOD 101000
    TYPE_KEYGUARD 121000
    TYPE_STATUS_BAR_SUB_PANEL 141000
    TYPE_WALLPAPER 21000
    TYPE_SEARCH_BAR 41000
    TYPE_SYSTEM_DIALOG 51000
    TYPE_PRIORITY_PHONE 71000
    TYPE_SYSTEM_ALERT 91000
    TYPE_INPUT_METHOD_DIALOG 111000
    TYPE_KEYGUARD_DIALOG 131000
    应用窗口与未知类型的窗口 21000

    窗口的子序:

    窗口类型 主序
    TYPE_UNIVERSE_BACKGROUND 11000
    TYPE_PHONE 31000
    TYPE_RECENTS_OVERLAY 51000
    TYPE_TOAST 61000
    TYPE_DREAM 81000
    TYPE_INPUT_METHOD 101000
    TYPE_KEYGUARD 121000
    TYPE_STATUS_BAR_SUB_PANEL 141000
    TYPE_WALLPAPER 21000

    相关文章

      网友评论

          本文标题:WindowManagerService探索——窗口主次序

          本文链接:https://www.haomeiwen.com/subject/vrgnvqtx.html