Xrandr은 Cygwin/X 및 Xming에서 화면 크기를 조정할 수 없습니다.

Xrandr은 Cygwin/X 및 Xming에서 화면 크기를 조정할 수 없습니다.

머리말:

고정 해상도가 필요한 매우 구체적인 원격 X 클라이언트가 있습니다. 말하자면 1280x1024입니다. 내 노트북의 해상도는 1440x900입니다. 창문도 있습니다. 따라서 아이디어는 900px 출력에 맞게 클라이언트 측 출력의 크기를 조정하는 것입니다. 패닝은 옵션이 아닙니다.

첫 번째 방법은 VirtualBox에서 실행되는 Xserver입니다. 하지만 이것은 내가 원하는 대로 작동하지 않습니다. VB 창의 크기를 조정하면 스크롤 막대와 함께 화면이 잘립니다.

그래서 Xming을 사용해봤습니다. 다음 매개변수를 사용하여 화면을 생성합니다.

-screen 0 640x512

성공적으로 시작되었습니다. 내 X 클라이언트를 연결하면 이미지가 잘리지만 이는 예상된 결과입니다. xrandr을 실행하여 디스플레이를 만들고 출력을 얻습니다.

$ xrandr
xrandr: Failed to get size of gamma for output default
Screen 0: minimum 0 x 0, current 640 x 512, maximum 32768 x 32768
default connected primary 640x512+0+0 0mm x 0 mm
   640x512        0.00*

좋습니다. 배율을 변경해 보세요.

$ xrandr --output default --scale 2x2
xrandr: Failed to get size of gamma for output default
X Error of failed request: BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  139 (RANDR)
  Minor opcode of failed request:  26 (RRSetCrtcTransform)
  Value in failed request:  0x3e
  Serial number of failed request:  21
  Current serial number in output stream:  22

그리고 그 규모는 변하지 않았습니다. 그러나 모든 클라이언트 데이터 인바운드를 표시하기 위해 화면 크기가 확장됩니다. 구성을 다시 쿼리하는 경우:

$ xrandr
xrandr: Failed to get size of gamma for output default
Screen 0: minimum 0 x 0, current 1280 x 1024, maximum 32768 x 32768
default connected primary 1280x1024+0+0 0mm x 0 mm
   1280x1024      0.00*

나는 동일한 결과로 Xming과 Cygwin/X를 시도했습니다. "요청 실패 값"은 요청된 배율 값에 의존하지 않으며 항상 0x3e입니다.

요청된 배율이 1보다 큰 경우 화면의 새 크기는 항상 요청된 배율에 초기 크기를 곱한 값입니다. 그렇지 않으면 아무 것도 변경되지 않지만 오류 메시지는 그대로 유지됩니다. 새 크기가 내 클라이언트 크기보다 크면 모든 대체 픽셀이 검은색으로 표시됩니다.

찾았어요여기 이러한 유형의 Xserver 출력은 xf86-video-vesa 및 이전 nvidia 드라이버로 인해 발생합니다. 하지만 이것이 내 경우인지, Xming이나 Cygwin/X 내부 드라이버에서 뭔가를 변경하는 방법은 모르겠습니다. 어쨌든 Windows 호스트 드라이버가 업데이트되었습니다.

또한 Cygwin에서 x11vnc를 시도했으며 x11vnc 및 vnc 클라이언트 모두에서 스케일링이 작동합니다. 그러나 이것은 느리고 너무 까다롭습니다.

그래서 질문은 xrandr에 관한 것입니다. 왜 예상대로 작동하지 않고 매뉴얼 페이지에 명시된 대로 작동하지 않습니까?


고쳐 쓰다:

글쎄, 나는 RANDR 확장이 어디에서 왔는지 좀 더 깊이 파고들었습니다. RRSetCrtcTransform 요청에 대한 응답으로 BadValue를 생성하는 유일한 경우는 부울 변수에 대한 False 값입니다.crtc->변환이는 드라이버가 지원되는 측정항목을 변환함을 의미합니다.

     /*
     * Set the pending CRTC transformation
     */
    
    int
    RRCrtcTransformSet(RRCrtcPtr crtc,
                       PictTransformPtr transform,
                       struct pixman_f_transform *f_transform,
                       struct pixman_f_transform *f_inverse,
                       char *filter_name,
                       int filter_len, xFixed * params, int nparams)
    {
        PictFilterPtr filter = NULL;
        int width = 0, height = 0;
        
        if (!crtc->transforms)
            return BadValue;
        
        if (filter_len) {
            filter = PictureFindFilter(crtc->pScreen, filter_name, filter_len);
            if (!filter)
                return BadName;
            if (filter->ValidateParams) {
                if (!filter->ValidateParams(crtc->pScreen, filter->id,
                                            params, nparams, &width, &height))
                    return BadMatch;
            }
            else {
                width = filter->width;
                height = filter->height;
            }
        }
        else {
            if (nparams)
                return BadMatch;
        }
        if (!RRTransformSetFilter(&crtc->client_pending_transform,
                                  filter, params, nparams, width, height))
            return BadAlloc;
    
        crtc->client_pending_transform.transform = *transform;
        crtc->client_pending_transform.f_transform = *f_transform;
        crtc->client_pending_transform.f_inverse = *f_inverse;
        return Success;
    }

값을 수정하는 유일한 줄은 setter 함수입니다.

    /*
     * Set whether transforms are allowed on a CRTC
     */
    void
    RRCrtcSetTransformSupport(RRCrtcPtr crtc, Bool transforms)
    {
        crtc->transforms = transforms;
    }

하지만 헤더에 내보낸 함수로 선언되어 있으며 누구도 RANDR srcs에서 이를 호출하지 않습니다.

좀 더 자세히 조사해 보면 이 값이 RRGetCrtcTransform 요청에 대한 응답으로 보고된다는 사실이 밝혀졌습니다(라인reply->hasTransforms = crtc->변환;):

    int
    ProcRRGetCrtcTransform(ClientPtr client)
    {
        REQUEST(xRRGetCrtcTransformReq);
        xRRGetCrtcTransformReply *reply;
        RRCrtcPtr crtc;
        int nextra;
        RRTransformPtr current, pending;
        char *extra;
    
        REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq);
        VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
    
        pending = &crtc->client_pending_transform;
        current = &crtc->client_current_transform;
    
        nextra = (transform_filter_length(pending) +
                  transform_filter_length(current));
    
        reply = calloc(1, sizeof(xRRGetCrtcTransformReply) + nextra);
        if (!reply)
            return BadAlloc;
    
        extra = (char *) (reply + 1);
        reply->type = X_Reply;
        reply->sequenceNumber = client->sequence;
        reply->length = bytes_to_int32(CrtcTransformExtra + nextra);
    
        reply->hasTransforms = crtc->transforms;
    
        transform_encode(client, &reply->pendingTransform, &pending->transform);
        extra += transform_filter_encode(client, extra,
                                         &reply->pendingNbytesFilter,
                                         &reply->pendingNparamsFilter, pending);
    
        transform_encode(client, &reply->currentTransform, &current->transform);
        extra += transform_filter_encode(client, extra,
                                         &reply->currentNbytesFilter,
                                         &reply->currentNparamsFilter, current);
    
        if (client->swapped) {
            swaps(&reply->sequenceNumber);
            swapl(&reply->length);
        }
        WriteToClient(client, sizeof(xRRGetCrtcTransformReply) + nextra, reply);
        free(reply);
        return Success;
    }

그러나 요청 자체는 XRRGetCrtcTransform 클라이언트 함수에 의해 생성되며 해당 출력에서 ​​확장 지원에 대한 정보를 얻을 수 있는 방법이 없습니다. 이 함수는 값(나타냅니다.hasTransforms) 답변으로:

    Status
    XRRGetCrtcTransform (Display    *dpy,
                 RRCrtc crtc,
                 XRRCrtcTransformAttributes **attributes)
    {
        XExtDisplayInfo     *info = XRRFindDisplay(dpy);
        xRRGetCrtcTransformReply    rep;
        xRRGetCrtcTransformReq  *req;
        int             major_version, minor_version;
        XRRCrtcTransformAttributes  *attr;
        char            *extra = NULL, *e;
        int             p;
    
        *attributes = NULL;
    
        RRCheckExtension (dpy, info, False);
    
        if (!XRRQueryVersion (dpy, &major_version, &minor_version) ||
        !_XRRHasTransform (major_version, minor_version))
        {
        /* For pre-1.3 servers, just report identity matrices everywhere */
        rep.pendingTransform = identity;
        rep.pendingNbytesFilter = 0;
        rep.pendingNparamsFilter = 0;
        rep.currentTransform = identity;
        rep.currentNbytesFilter = 0;
        rep.currentNparamsFilter = 0;
        }
        else
        {
        LockDisplay (dpy);
        GetReq (RRGetCrtcTransform, req);
        req->reqType = info->codes->major_opcode;
        req->randrReqType = X_RRGetCrtcTransform;
        req->crtc = crtc;
    
        if (!_XReply (dpy, (xReply *) &rep, CrtcTransformExtra >> 2, xFalse))
        {
            rep.pendingTransform = identity;
            rep.pendingNbytesFilter = 0;
            rep.pendingNparamsFilter = 0;
            rep.currentTransform = identity;
            rep.currentNbytesFilter = 0;
            rep.currentNparamsFilter = 0;
        }
        else
        {
            int extraBytes = rep.length * 4 - CrtcTransformExtra;
            extra = Xmalloc (extraBytes);
            if (!extra) {
            _XEatDataWords (dpy, rep.length - (CrtcTransformExtra >> 2));
            UnlockDisplay (dpy);
            SyncHandle ();
            return False;
            }
            _XRead (dpy, extra, extraBytes);
        }
    
        UnlockDisplay (dpy);
        SyncHandle ();
        }
    
        attr = Xmalloc (sizeof (XRRCrtcTransformAttributes) +
                rep.pendingNparamsFilter * sizeof (XFixed) +
                rep.currentNparamsFilter * sizeof (XFixed) +
                rep.pendingNbytesFilter + 1 +
                rep.currentNbytesFilter + 1);
    
        if (!attr) {
        XFree (extra);
        return False;
        }
        XTransform_from_xRenderTransform (&attr->pendingTransform, &rep.pendingTransform);
        XTransform_from_xRenderTransform (&attr->currentTransform, &rep.currentTransform);
    
        attr->pendingParams = (XFixed *) (attr + 1);
        attr->currentParams = attr->pendingParams + rep.pendingNparamsFilter;
        attr->pendingFilter = (char *) (attr->currentParams + rep.currentNparamsFilter);
        attr->currentFilter = attr->pendingFilter + rep.pendingNbytesFilter + 1;
    
        e = extra;
    
        memcpy (attr->pendingFilter, e, rep.pendingNbytesFilter);
        attr->pendingFilter[rep.pendingNbytesFilter] = '\0';
        e += (rep.pendingNbytesFilter + 3) & ~3;
        for (p = 0; p < rep.pendingNparamsFilter; p++) {
        INT32   f;
        memcpy (&f, e, 4);
        e += 4;
        attr->pendingParams[p] = (XFixed) f;
        }
        attr->pendingNparams = rep.pendingNparamsFilter;
    
        memcpy (attr->currentFilter, e, rep.currentNbytesFilter);
        attr->currentFilter[rep.currentNbytesFilter] = '\0';
        e += (rep.currentNbytesFilter + 3) & ~3;
        for (p = 0; p < rep.currentNparamsFilter; p++) {
        INT32   f;
        memcpy (&f, e, 4);
        e += 4;
        attr->currentParams[p] = (XFixed) f;
        }
        attr->currentNparams = rep.currentNparamsFilter;
    
        if (extra)
        XFree (extra);
        *attributes = attr;
    
        return True;
    }

현재 사실은 다음과 같습니다.

  • Cygwin 또는 Xming 내의 X 서버 드라이버는 변환을 지원하지 않습니다.
  • 이러한 정보는 서버 측으로 전송되지만 XRandr 클라이언트 API를 사용하여 얻을 수 없습니다(이것을 결함으로 간주해야 합니까?).

좋아, 이유는 찾았는데, 드라이버가 변경 사항을 지원하도록 하려면 어떻게 해야 할까요?

답변1

댓글을 달 수 없으므로 해결책을 제시해야 합니다.

제안된 해결 방법: VirtualBox로 돌아가겠습니다. 나도 똑같이해야 할 수도 있습니다.

댓글: cygwin에서 xrandr에 대한 솔루션이 있습니까?

이전 UNIX 응용 프로그램은 3000x2000 높은 dpi 화면에서 사용할 수 없습니다. Windows에서 돋보기 도구도 사용해 보았지만 끔찍했습니다.

응용 프로그램 확장을 지원하는 Windows 상용 x 서버가 있습니까? 아직 찾지 못했습니다.

관련 정보