Using Multiple Screens/ru

Люди часто спрашивают, как настроить X для использования на нескольких мониторах на IRC канале. Поэтому здесь приведено краткое руководство охватывающее несколько различных драверов и методов доступных в GNU/Linux.

Если вас интересует как управлять несколькими монитормаи, после того как вы их настроите смотрите awesome 3 key bindings (смотрите те, которые управляют экранами, также вы можете открыть man страницу в терминале) и если вы хотите управлять виджетами(например системным треем) на каждом экране, то вам необходимо изучить страницу Виджеты в Awesome, конкретно Управление виджетами секцию.

Основы
Самым простым способом является использование XRandR (X Resize и Rotate) расширения, которое позволяет динамически контролировать ваши выходы, разрешения, ориентацию... и добавлять новые дисплеи на лету, без перезапуска X-сервера. Но пока еще не все драйверы поддерживаются в нем. Вот список поддерживаемых драйверов: intel, ati (OpenSource driver), radeonhd (OpenSource driver), nv (nvidia 2D driver) и nouveau (OpenSource nvidia driver). Я также захвачу драйвер nvidia, как наиболее часто используемый людьми, использующий TwinView и Xinerama (которые могут быть использованы также и с другими драйверами, например с fglrx).

Помиом этого, Awesome имеет: Реальную поддержку нескольких экранов (XRandR, Xinerama и Zaphod режимы) на десктопных экранах (tags); Awesome поставляется с примером конфигурационного файла (/etc/xdg/awesome/rc.lua начиная с v3.0 и старше) которая уже настроена на несколько дисплеев; касающаяся wiboxes, taskbars и widgets, но также имеет и клавиатурные сочетания, которые позволяют вам перемещать клиенты между несколькими экранами и переключать фокус между ними.

XRandR
Для начала я покажу вам несколько примеров использования xrandr для динамической настройки на лету (и перенастройки).

Итак первой командой мы запросим список нашего оборудования: $ xrandr -q

После получения вывода, давайте предположим, что у вас есть ноутбук с панелью LVDS и внешним портом VGA, который мы будем рассматривать как VGA, мы выполним: $ xrandr --output VGA --mode 1280x1024 --right-of LVDS

Команда приведенная выше проста, ваш VGA монитор инициализируется с разрешением 1280х1024 и размещается и размещается с права от вашего экрана LVDS screen (допустим что разрешение LVDS равно 1280x800). Важно помнить, что у вас теперь одни большой экран, размер которого будет 2560x1024. Если команда выше завершится с ошибкой, то вы вероятно не примете это в расчет когда будете настраивать ваш xorg.conf (вам необходимо настроить ваш Virtual размер), подробнее об этом чуть ниже.

Довольно часто случается, что Xrandr не может найти 'наилучшее' разрешение для вашего внешнего монитора. Не говоря уже о правильно частоте его обновления. Когда это происходит, вам необходимо создать modeline (gtf), затем добавить его к выводу. Вот несколько простых команд, которые создадут новую конфигурацию 1280x800 с частотой обновления 68Hz и прикрепят его к выводу VGA: $ xrandr --newmode $(gtf 1280 800 68 | grep Modeline | sed s/Modeline\ // | tr -d '"')   $ xrandr --addmode VGA 1280x800_68.00

Для других способов использования Xrandr прочитайте man. Здесь я покажу только один пример, отключения внешнего монитора: $ xrandr --output VGA --off

Здесь вы можете найти простой скрипт который несколько упрощает задачу правильного выбора частоты обновления, а затем настраивает ваши экраны stupid.sh

Циклическое переключение возможных конфигураций
Есть возможность циклически переключаться между различными конфигурациями с помощью клавиатуры (например XF86Display). Вот фрагмент кода, который использует уведомления для отображения предложенной конфигурации. Каждый раз при нажатии клавиш, предлагается другая конфигурация в зависимости от активных выходов. После обхода всех возможных конфигурация, мы предполагаем что менять нечего. Чтобы принять конфигурацию, пользователь просто не должен переключаться на другие конфигурации:


 * Only LVDS1
 * Only VGA1
 * LVDS1 + VGA1
 * VGA1 + LVDS1
 * No change
 * Only LVDS1

-- Get active outputs local function outputs local outputs = {} local xrandr = io.popen("xrandr -q") if xrandr then for line in xrandr:lines do	 output = line:match("^([%w-]+) connected ") if output then outputs[#outputs + 1] = output end end xrandr:close end

return outputs end

local function arrange(out) -- We need to enumerate all the way to combinate output. We assume -- we want only an horizontal layout. local choices = {} local previous = { {} } for i = 1, #out do     -- Find all permutation of length `i`: we take the permutation -- of length `i-1` and for each of them, we create new -- permutations by adding each output at the end of it if it is     -- not already present. local new = {} for _, p in pairs(previous) do	 for _, o in pairs(out) do	   if not awful.util.table.hasitem(p, o) then new[#new + 1] = awful.util.table.join(p, {o}) end end end choices = awful.util.table.join(choices, new) previous = new end

return choices end

-- Build available choices local function menu local menu = {} local out = outputs local choices = arrange(out)

for _, choice in pairs(choices) do     local cmd = "xrandr" -- Enabled outputs for i, o in pairs(choice) do cmd = cmd .. " --output " .. o .. " --auto" if i > 1 then cmd = cmd .. " --right-of " .. choice[i-1] end end -- Disabled outputs for _, o in pairs(out) do	 if not awful.util.table.hasitem(choice, o) then cmd = cmd .. " --output " .. o .. " --off" end end

local label = "" if #choice == 1 then label = 'Only ' .. choice[1] .. ' '     else for i, o in pairs(choice) do if i > 1 then label = label .. " + " end label = label .. ' ' .. o .. ' '	 end end

menu[#menu + 1] = { label, cmd, "/usr/share/icons/Tango/32x32/devices/display.png"} end

return menu end

-- Display xrandr notifications from choices local state = { iterator = nil, timer = nil, cid = nil } local function xrandr -- Stop any previous timer if state.timer then state.timer:stop state.timer = nil end

-- Build the list of choices if not state.iterator then state.iterator = awful.util.table.iterate(menu,					function return true end) end

-- Select one and display the appropriate notification local next = state.iterator local label, action, icon if not next then label, icon = "Keep the current configuration", "/usr/share/icons/Tango/32x32/devices/display.png" state.iterator = nil else label, action, icon = unpack(next) end state.cid = naughty.notify({ text = label,				icon = icon,				timeout = 4,				screen = mouse.screen, -- Important, not all screens may be visible				font = "Free Sans 18",				replaces_id = state.cid }).id

-- Setup the timer state.timer = timer { timeout = 4 } state.timer:connect_signal("timeout",			 function			     state.timer:stop			     state.timer = nil			     state.iterator = nil			     if action then				awful.util.spawn(action, false)			     end			  end) state.timer:start end

config.keys.global = awful.util.table.join(  config.keys.global,   awful.key({}, "XF86Display", xrandr))

Постоянная конфигурация
Если вы хотите использовать постоянные настройки для ваших дисплеев, то вы можете сделать по следующему примеру. У вас уже есть одна Section "Monitor" для вашего первого дисплей (и в этом примере, предполагается, что его идентификатор LCD-Monitor и наш VGA будет CRT-Monitor). И первым шагом нам необходимо добавить еще одну, с настройками для второго дисплея (мы продолжим пример с VGA): # This is for a static setup of the external display #   Section "Monitor" Identifier  "CRT-Monitor" VendorName  "FUS" ModelName   "19P4" HorizSync   30-96 VertRefresh 50-160 Option      "DPMS" Option      "PreferredMode" "1280x1024" Option      "RightOf"       "LVDS" ##Option    "Position"      "1280 0" EndSection

Затем в вашей Section "Device" вы делаете актуальные настройки: # Graphics configuration #    Section "Device" Identifier  "intel" Driver      "intel" VendorName  "Intel Corporation" BoardName   "Mobile GM965/GL960 Integrated Graphics Controller" # VGA display options Option      "monitor-VGA"     "CRT-Monitor" ##Option    "MonitorLayout"   "CRT,LFP" ##Option    "MonitorLayout"   "NONE,CRT+LFP" EndSection

Это самые основные настройки, некоторые другие, которые заслуживают упоминания это: CheckLid, DevicePresence и Clone. Вы можете найти все опции с объяснениями на странице руководства драйвера intel (для ознакомления с ней вы можете набрать в терминале: man intel или заменить intel на название драйвера, которым пользуетесь вы).

Последний шаг включает настройку вашего Virtual размера, как я упоминал ранее. В вашей Section "Screen" подразделе "Display" вам необходимо настроить виртуальный размер вашего desktop (обычно его размещают после строк Modes). Итак, после наших действий, раздел "Screen" будет выглядеть следующим образом:

# Screen configuration #   Section "Screen" Identifier "LCD Screen" Device     "intel" Monitor    "LCD-Monitor" DefaultDepth 24 Subsection "Display" Depth      24 Modes      "1280x800" "1280x768" "1280x720" "1024x768" "800x600" "640x480" ViewPort   0 0 Virtual    2560 1024 EndSubsection EndSection

nvidia
Итак, nvidia все еще не поддерживается XRandR. Все что они сделали, это разработали собственную технологию называемую TwinView которая в его простейшей конфигурации, не так уж хороша для нас в стандартном виде, так как Awesome видит экран как один большой desktop (таким образом вы не сможете перемещать приложения между экранами, поскольку нет другого экрана, куда можно было бы переместить их). Но я полагаю, здесь могут быть некоторые случаи использования, где это будет востребовано, поэтому я также опишу это. Тогда, немного настроив, мы получим то поведение, которое ожидаем. Наш последний пример будет использовать Xinerama который будет иметь тот же результат, как и в наших предыдущих примерах.

TwinView
Используя TwinView у вас будет только один Section "Monitor", для первого дисплея. Полная настройка второго дисплея осуществляется в Section "Device". Простейший способ сделать это, это nvidia-settings, и если это не будет работать, вы можете отредактировать ваш Xorg.conf вручную. Давайте посмотрим, как она может выглядеть (в этом случае я использую два одинаковых CRT монитора): Section "Device" Identifier "Card0" Driver     "nvidia" VendorName "nVidia Corporation" BoardName  "NV34 [GeForce FX 5500]" #       Option      "ConnectedMonitor"     "CRT-0, CRT-1" ##Option   "IgnoreDisplayDevices" "TV-0" #       # This is the important part Option     "TwinView"            "true" # Possible options are: Right-Of, Left-Of, Above, Below, Clone Option     "TwinViewOrientation" "Right-Of" #       Option      "SecondMonitorHorizSync"   "30-96" Option     "SecondMonitorVertRefresh" "50-160" #       # Metamodes tell us when: # monitor A is using resolution X then monitor B will use resolution Y; second lower A reolution, second lower B resolution... Option     "MetaModes" "1280x1024, 1280x1024; 1024x768, 1024x768; 800x600, 800x600; 640x480, 640x480" # Example when monitor B is using a lower resolution #Option    "MetaModes" "1280x1024, 1024x768@1280x1024; 1024x768, 1024x768; 800x600, 800x600" EndSection

Теперь давайте рассмотрим другой пример предоставленый другим пользователем, где он использует два дисплея ведущих себя независимо под Awesome с использованием TwinView. Здесь мы перемещаем несколько опций, делегируя их другим секциям, но не позволяйте этому сбить себя с толку. В данном примере, мы будет использовать два одинаковых LCD монитора (назовем их DFP-0 и DFP-1): Section "Monitor" Identifier   "Monitor0" HorizSync    30-100 VertRefresh  60 ModeLine     "1680x1050" 147.1 1680 1784 1968 2256 1050 1051 1054 1087 +Hsync -Vsync EndSection Section "Monitor" Identifier   "Monitor1" HorizSync    30-100 VertRefresh  60 ModeLine     "1680x1050" 147.1 1680 1784 1968 2256 1050 1051 1054 1087 +Hsync -Vsync EndSection Section "Device" Identifier     "Card0" Driver         "nvidia" VendorName     "nVidia" BoardName      "NVIDIA GeForce 7800GS" Option         "AllowDDCCI"            "true" Option         "FlatPanelProperties"   "Scaling = aspect-scaled" Option         "RandRRotation"         "true" Option         "TripleBuffer"          "true" # Multiple display configuration ##Option       "ConnectedMonitor"          "DFP-0, DFP-1" Option         "PrimaryMonitor"            "DFP-0" Option         "UseDisplayDevice"          "DFP-0, DFP-1" # According to their docs, this is what makes the difference #  http://us.download.nvidia.com/XFree86/Linux-x86/180.29/README/chapter-13.html Option         "TwinViewOrientation"       "DFP-0  LeftOf DFP-1" Option         "TwinViewXineramaInfoOrder" "DFP-0, DFP-1" EndSection Section "Screen" Identifier   "Screen0" Device       "Card0" Monitor      "Monitor0" DefaultDepth 24 Subsection   "Display" Modes           "1680x1050" EndSubsection Option "MetaModes"  "DFP-0: 1680x1050 +0+0, DFP-1: 1680x1050 +1680+0;" Option "HorizSync"  "DFP-0: 30-100; DFP-1: 30-100" Option "VertRefresh" "DFP-0: 60; DFP-1: 60" Option "TwinView"   "true" EndSection Section "ServerLayout" Identifier   "TwinView Screen" Screen       0 "Screen0" 0 0 Option       "Xinerama"  "false" EndSection

Чтобы получить больше информации о TwinView (называя устройства (CRT, DFP, TV...), которые объединены, могут быть использованы в то же время и для чего то еще) ссылки на последний nvidia README файл, который который распространяется со всеми драйверами, но с ним также можно ознакомиться и онлайн: http://www.nvidia.com/object/unix.html

Xinerama
Xinerama это расширения для X, которое позволяет multi-headed X приложениям и оконным менеджерам использовать два или больше физических дисплея как один большой виртуальный дисплей. Обратите внимание, что вы можете использовать Xinerama таким же способом также и с другими драйверам (например с fglrx). Когда используется Xinerama нам необходимо иметь секцию для каждого Monitor, две секции Device, две секции Screen (каждая из которых использует свой собственный Device и Monitor) и поэтому мы настраиваем ориентацию наших экранов в главной секции ServerLayout (где мы также разрешаем использовать Xinerama). Это наиболее простой пример, показывающий о чем я говорю (используются два однинаковых LCD дисплея): # Out Monitor sections #    Section "Monitor" Identifier  "Monitor0" VendorName  "Monitor Vendor" ModelName   "Monitor Model" EndSection Section "Monitor" Identifier  "Monitor1" VendorName  "Monitor Vendor" ModelName   "Monitor Model" EndSection # Our Device sections #     Section "Device" Identifier "Card0" Driver     "nvidia" VendorName "nVidia Corporation" BoardName  "G70 [GeForce 7800 GS]" Screen     0 EndSection Section "Device" Identifier "Card1" Driver     "nvidia" VendorName "nVidia Corporation" BoardName  "G70 [GeForce 7800 GS]" Screen     1 EndSection # Our Screen sections #    Section "Screen" Identifier   "Screen0" Device       "Card0" Monitor      "Monitor0" DefaultDepth 24 SubSection   "Display" Viewport 0 0 Depth    24 Modes    "1680x1050" EndSubSection EndSection Section "Screen" Identifier   "Screen1" Device       "Card1" Monitor      "Monitor1" DefaultDepth 24 SubSection   "Display" Viewport 0 0 Depth    24 Modes    "1680x1050" EndSubSection EndSection # Finally our ServerLayout that does the work #     Section "ServerLayout" Identifier    "Xinerama Screen" Screen        0  "Screen0" 0 0 Screen        1  "Screen1" RightOf "Screen0" Option        "Xinerama"   "true" EndSection

У вас также будут собственные настройки Keyboard и Mouse в этом файле, и ссылаться на них в вашем server layout и т.д.. (если вы все еще не испльзуете HAL разрещите X.org). Вы уже должны знать все это. Я пишу только о дисплеях. Говоря об этом, существует еще несколько способов использования нескольких дисплеев, такие как запуск двух независимых X сессий, каждой на своем мониторе, также можно упомянуть о, Zaphod и MergedFB, последний используется для ATi, а у nVidia, есть свой собственный, называемый BigDesktop (драйвер fglrx). Researching into those is up to you, reader. Этим я завершаю эту статью, я надеюсь вы немного просветились и теперь у вас есть огромный рабочий стол (и Awesome контролирует его :).

Disper
Простейшая утилита: позволяющая переключать конфигурации мониторов через командную строку http://willem.engen.nl/projects/disper/

Это также позволяет работать в обход запроса диалога перезагрузки nvidia-settings, которое будет скрыто awesome's, когда nvidia-settings изменяет режим монитора.