版本比较

密钥

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

...

窗口相关操作需要与wayland compositor交互

callback

implement

description

CreateWindow

xwl_glamor_create_window

增加识别合成器隐形重定向的窗口,即视觉配置与祖先不同的窗口

ReparentWindow

xwl_glamor_reparent_window

同上

RealizeWindow

xwl_realize_window

创建damage,wl_surface,并使wl_surface关联X11 window

UnrealizeWindow

xwl_unrealize_window

回收xwl相关显示资源

DestroyWindow

xwl_destroy_window

回收xwl相关资源

ResizeWindow

xwl_resize_window

调整分辨率引起的视口(viewport)坐标调整

MoveWindow

xwl_move_window

同上

XYToWindow

xwl_xy_to_window

处理鼠标移动,跨X11和wayland窗口的场景,若是则返回X11根窗口

CloseScreen

xwl_close_screen

回收资源

ChangeWindowAttributes

xwl_change_window_attributes

跟踪窗口管理器的注册,记录窗口管理器client ID

SetWindowPixmap

xwl_window_set_window_pixmap

画布尺寸变化时,释放wl_surface的xwl_window_buffer资源

CursorWarpedTo

xwl_cursor_warped_to

CursorConfinedTo

xwl_cursor_confined_to

CreateScreenResources

xwl_glamor_create_screen_resources

代码块
languagejava
// 检查光标精灵是否丢失了光标焦点,及精灵跟踪的窗口栈是否失效,window为获取光标焦点的窗口
static Bool sprite_check_lost_focus(SpritePtr sprite, WindowPtr window){
    DeviceIntPtr device, master;
    struct xwl_seat *xwl_seat;
    // 找到sprite对应的wayland输入设备
    for (device = inputInfo.devices; device; device = device->next) {
        if (device->deviceProc == xwl_pointer_proc &&
            device->spriteInfo->sprite == sprite)
            break;
    }
    if (!device)
        return FALSE;
 
    xwl_seat = device->public.devicePrivate;
    if (!xwl_seat)
        return FALSE;
 
    master = GetMaster(device, POINTER_OR_FLOAT);
    if (!master || !master->lastSlave)
        return FALSE;
 
    // xwl_seat需为与主光标设备关联的从属设备
    if (master->lastSlave != get_pointer_device(xwl_seat))
        return FALSE;
 
    // 光标在X11窗口中,但光标锁定窗口与焦点窗口不同,涉及窗口切换
    if (xwl_seat->focus_window != NULL &&
        xwl_seat->cursor_confinement_window != NULL &&
        xwl_seat->focus_window != xwl_seat->cursor_confinement_window)
        return TRUE;
 
    // 光标不在X11窗口系统中,最后一次离开时的光标焦点窗口是当前获取焦点窗口的自身或祖先窗口
    if (xwl_seat->focus_window == NULL &&
        xwl_seat->last_xwindow != NullWindow &&
        (IsParent(xwl_seat->last_xwindow, window) || xwl_seat->last_xwindow == window))
        return TRUE;
 
    return FALSE;
}
 
// 根据(x,y)坐标,找到对应的窗口,光标将聚焦在该窗口上
static WindowPtr xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y){
    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
    // 返回(x,y)坐标所在的窗口
   WindowPtr ret = miXYToWindow(screen, sprite, x, y);
 
    // 场景:光标从Wayland窗口系统进入X11窗口系统,但X11窗口系统跟踪了上次离开X11窗口系统时的光标信息
    // 采用返回X11系统根窗口的方式,使X11系统能发送一个LeaveNotify事件通知client进行光标处理
    if (sprite_check_lost_focus(sprite, ret)) {
        sprite->spriteTraceGood = 1;
        return sprite->spriteTrace[0];
    }
    return ret;
}

...

与CRTC相关操作,非本地硬件,其操作需通过Wayland compositor实现compositor实现。使用drm-lease扩展协议实现对输出设备的租赁功能

callback

implement

description

rrGetInfo

xwl_randr_get_info

获取旋转方向掩码,都支持

rrSetConfig

xwl_randr_set_config

设置配置,不支持

rrScreenSetSize

xwl_randr_screen_set_size

设置屏幕大小,不生效

rrCrtcSet

xwl_randr_crtc_set

设置CRTC模式

rrCrtcGet

xwl_randr_crtc_get

获取CRTC模式

rrCrtcSetGamma

xwl_randr_crtc_set_gamma

设置CRTC灰度映射表,不生效

rrCrtcGetGamma

xwl_randr_crtc_get_gamma

获取CRTC灰度映射表,不生效

rrOutputSetProperty

xwl_randr_output_set_property

设置输出设备属性,不生效

rrOutputValidateMode

xwl_output_validate_mode

检查randr模式是否有效,不生效

rrModeDestroy

xwl_randr_mode_destroy

销毁randr模式

rrRequestLease

xwl_randr_request_lease

请求租赁CRTC等,使用drm-lease扩展协议实现

rrGetLease

xwl_randr_get_lease

获取租赁设备的句柄

rrTerminateLease

xwl_randr_terminate_lease

终止租赁,是否资源

2.1.3 显存相关

callback

implement

description

init_wl_registry

xwl_glamor_gbm_init_wl_registry

has_wl_interfaces

xwl_glamor_gbm_has_wl_interfaces

init_egl

xwl_glamor_gbm_init_egl

init_screen

xwl_glamor_gbm_init_screen

get_wl_buffer_for_pixmap

xwl_glamor_gbm_get_wl_buffer_for_pixmap

check_flip

get_main_device

xwl_gbm_get_main_device

create_pixmap_for_window

xwl_glamor_gbm_create_pixmap_for_window

2.2 创建根窗口

创建X11根窗口,主要是三大步,假设Wayland server已经启动

...

在该环境下,只有fbCreateWindow初始化了窗口的画布,其它函数不做任何处理。

代码块
languagejava
Bool fbCreateWindow(WindowPtr pWin) {
    // 初始化窗口画布PixMapPtr,非根模式下由fbCreatePixmap,而根模式由screen->CreatePixmap链式回调创建
    dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin), fbGetScreenPixmap(pWin->drawable.pScreen));
    return TRUE;
}
 
Bool compCreateWindow(WindowPtr pWin) {
    ScreenPtr pScreen = pWin->drawable.pScreen;
    Bool ret = fbCreateWindow (pWin);
    // 条件不满足,根窗口没有父窗口
    if (pWin->parent && ret) {
        CompSubwindowsPtr csw = GetCompSubwindows(pWin->parent);
        CompClientWindowPtr ccw;
        PixmapPtr parent_pixmap = (*pScreen->GetWindowPixmap)(pWin->parent);
        PixmapPtr window_pixmap = (*pScreen->GetWindowPixmap)(pWin);
 
        if (window_pixmap != parent_pixmap)
            (*pScreen->SetWindowPixmap) (pWin, parent_pixmap);
        if (csw)
            for (ccw = csw->clients; ccw; ccw = ccw->next)
                compRedirectWindow(clients[CLIENT_ID(ccw->id)],
                                   pWin, ccw->update);
        if (compImplicitRedirect(pWin, pWin->parent))
            compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
    }
    return ret;
}
 
static Bool xwl_glamor_create_window(WindowPtr window) {
    // 条件不满足,根窗口没有父窗口
    if (window->parent)
        xwl_avoid_implicit_redirect(window);
    return compCreateWindow (window);
}

注:

  • 在初始化Screen时,xwl_screen_init将非根模式的Screen的clip_root_mode设置为ROOT_CLIP_INPUT_ONLY,所有渲染操作都会重定向。

  • 在创建Screen资源时,xwl_glamor_create_screen_resources在非根模式采用fbCreatePixmap创建画布(且宽高均为0),而根模式由screen->CreatePixmap链式回调创建

...

非根模式的根窗口未使用双缓冲,miDbePositionWindow中双缓冲部分不需处理,其相当于直接调用compPositionWindow,而根窗口的宽高和画布未修改,PositionWindow未做任何事。

代码块
languagejava
// 桩函数,啥都不做
Bool fbPositionWindow(WindowPtr pWin, int x, int y){ return TRUE; }
 
Bool
compPositionWindow(WindowPtr pWin, int x, int y)
{
    ScreenPtr pScreen = pWin->drawable.pScreen;
    Bool ret = TRUE;
    // 根窗口不满足该条件
    if (pWin->redirectDraw != RedirectDrawNone) {
        PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
        int bw = wBorderWidth(pWin);
        int nx = pWin->drawable.x - bw;
        int ny = pWin->drawable.y - bw;
 
        if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) {
            pPixmap->screen_x = nx;
            pPixmap->screen_y = ny;
            pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
        }
    }
 
    if (!fbPositionWindow(pWin, x, y))
        ret = FALSE;
    // 更新重叠窗口,此时根窗口此时无重叠窗口
    if (updateOverlayWindow(pScreen) != Success)
        ret = FALSE;
    return ret;
}

2.2.3 ChangeWindowAttributes

...

xwl_change_window_attributes主要功能是找到窗口管理器的client ID。其它函数因mask等条件不满足,未做任何事情

代码块
languagejava
// mask = (CWBorderPixel | CWCursor || CWBackingStore | CWBackPixel)
// 处理pixmap,而根窗口为pixel。
Bool fbChangeWindowAttributes(WindowPtr pWin, unsigned long mask) {
    if (mask & CWBackPixmap) {
        if (pWin->backgroundState == BackgroundPixmap)
            fbFixupWindowPixmap(&pWin->drawable, &pWin->background.pixmap);
    }
    if (mask & CWBorderPixmap) {
        if (pWin->borderIsPixel == FALSE)
            fbFixupWindowPixmap(&pWin->drawable, &pWin->border.pixmap);
    }
    return TRUE;
}
// 处理后端存储,而根窗口不支持后端存储
static Bool compChangeWindowAttributes(WindowPtr pWin, unsigned long mask){
    ScreenPtr pScreen = pWin->drawable.pScreen;
    Bool ret = fbChangeWindowAttributes(pWin, mask);
    // 根窗口的backingStoreSupport为WhenMapped,条件满足,但backingStore = NotUseful,compCheckBackingStore啥事也不做
    if (ret && (mask & CWBackingStore) && pScreen->backingStoreSupport != NotUseful)
        compCheckBackingStore(pWin);
    return ret;
}
 
Bool xwl_change_window_attributes(WindowPtr window, unsigned long mask)
{
    ScreenPtr screen = window->drawable.pScreen;
    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
    OtherClients *others;
    Bool ret = compChangeWindowAttributes(window, mask);
    if (window != screen->root || !(mask & CWEventMask))
        return ret;
 
    // 查找窗口管理器客户端,窗口管理器将其mask设置为 SubstructureRedirectMask
    for (others = wOtherClients(window); others; others = others->next) {
        if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask))
            xwl_screen->wm_client_id = CLIENT_ID(others->resource);
    }
    return ret;
}

2.2.4 RealizeWindow

xwl_realize_window → compRealizeWindow → fbRealizeWindow

初始化根窗口的可绘制区间。其它因条件不满足,未做任何事情

代码块
Bool fbRealizeWindow(WindowPtr pWindow) { return TRUE; }
 
Bool compRealizeWindow(WindowPtr pWin) {
    compCheckRedirect(pWin);
   fbRealizeWindow(pWin);
    return TRUE;
}
 
Bool xwl_realize_window(WindowPtr window){
    ScreenPtr screen = window->drawable.pScreen;
    CompScreenPtr comp_screen = GetCompScreen(screen);
    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
    ret = compRealizeWindow(window);
    if (xwl_screen->rootless) {
        /* We do not want the COW to be mapped when rootless in Xwayland */
        if (window == comp_screen->pOverlayWin) {
            window->mapped = FALSE;
            return TRUE;
        }
        // 初始化根窗口空间,其它空间清空
        if (!window->parent) {
            BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
            RegionReset(&window->winSize, &box);
            RegionNull(&window->clipList);
            RegionNull(&window->borderClip);
        }
    }
    // 条件不满足,根窗口的父窗口为空,只有顶层窗口满足该条件
    if (xwl_screen->rootless ? (window->drawable.class == InputOutput && window->parent == window->drawable.pScreen->root) : !window->parent) {
        if (!register_damage(window)) return FALSE;
    }
    // 该函数对根窗口不做任何处理,其redirectDraw = RedirectDrawNone
    return ensure_surface_for_window(window);
}

2.2.5 ClipNotify

present_clip_notify → compClipNotify → xf86XVClipNotify

...