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アプリケーションは、3000×2000の高dpi画面では使用できません。 Windowsで虫眼鏡ツールも試してみましたが、ひどかったです。

アプリケーション拡張をサポートするWindows商用xサーバーはありますか?まだ見つかりませんでした。

おすすめ記事