Intereting Posts
Ошибка сервера CentOS 6 VPS OpenVPN Почему при загрузке файла SO он добавляет версию до конца? Вкладка для отображения содержимого каталога Как запустить java-службу как пользователя без полномочий root на CentOs 6 Настройка монитора HP DisplayPort с поддержкой Fedora Запись изображения на флешку под OpenBSD Сохранить результат grep для массива Как получить имя Диспетчера отображения в Linux? Можно ли изменить тег сервера в irssi? Как? Назначение постоянных имен интерфейсов, используя udev, с обобщенным методом Разрешение местоположения / регистрации исполняемого файла в системе? Можно ли установить PHP 5.2.17 на новую систему CentOS 6.4? Как сделать вывод этого скрипта: «Ошибка соединения с мамой через SSH», когда соединение не работает? Как искать файл, начинающийся с a или z и заканчивая символом a или z? «Bind: Address уже используется» при создании моста в Linux для Windows

Xrandr не масштабирует экран под Cygwin / X и Xming

Преамбула:

У меня очень специфический удаленный клиент X, который требует фиксированного разрешения. 1280×1024, чтобы сказать. И мой ноутбук имеет 1440×900. И Windows на борту. Итак, идея состоит в том, чтобы масштабировать вывод клиента, чтобы он соответствовал выходу 900px. Панорамирование – это не вариант.

Первым подходом был Xserver, работающий под VirtualBox. Но это не сработало, как мне хотелось, масштабирование окна 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.

Я также попробовал x11vnc внутри Cygwin, и масштабирование работало, как на стороне x11vnc, так и на vnc-клиенте. Но это было медленно, и это слишком сложно.

Итак, вопрос о xrandr, почему это не работает так, как ожидалось и объявлено на страницах руководства?


Обновить:

Ну, я пошел глубже и просмотрел источники расширения RANDR. И единственный случай, который я нашел, который производит BadValue в ответе на запрос RRSetCrtcTransform, – это значение False для логической переменной crtc-> transforms , которое должно быть индикатором поддержки преобразования драйвера:

  /* * 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 (line reply-> hasTransforms = crtc-> transforms; ):

 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, и нет никакого способа получить от его вывода информацию о поддержке масштабирования. Функция просто игнорирует это значение ( rep.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; } 

В этот момент вот факты:

  • Драйвер X-сервера внутри Cygwin или Xming не поддерживает преобразования;
  • Невозможно получить эту информацию с помощью клиентского API-интерфейса XRandr, хотя серверная сторона отправляет такую ​​информацию (следует ли считать ее дефектом?)

Итак, причина найдена, но как сделать преобразования поддержки драйверов?