LINUX.ORG.RU

Как запретить перемещение курсора на другие дисплеи?

 


2

4

$заглав

Неудобно, когда курсор попадет на отдельные дисплеи, хотелось бы по хоткею тоґлить эту возможность, например по-дефолтному в таких случаях Scroll Lock.

Погуглил вики наквадах и арчвики, там такого нет.

Подскажите пожалуйста, кто настраивал себе.


Подпишусь, та же проблема - при задвигании курсора в правый край курсор перескакивает на левый монитор.

DeadEye ★★★★★
()
Ответ на: комментарий от DeadEye

так настрой себе xrandr'ом (--left-of, --primary и т.п.) положение мониторов при запуске осома (в rc.lua) или пропиши в xorg.conf.d/positions.conf;

redhat
() автор топика
Ответ на: комментарий от redhat

Настроил, конечно. Ты правда считаешь, что я идиот?

DeadEye ★★★★★
()

Совсем недавно такую же тему создавал. Как я понял сейчас никаких решений для этого нет, единственный вариант - выстроить дисплеи так, чтоб они касались углами - меньше площадь для перехода получится.

alozovskoy ★★★★★
()

сделал так: расположил по диагонали мониторы в xrandr(arandr для мышковозов) теперь курсор на другой монитор переходит строго через угол и шорткатом.

LiBer ★★★
()
Ответ на: комментарий от alozovskoy

ну не скажи, можно же ещё отдельные иксы запускать на каждый монитор, я так не делал, но вроде можно, мышки отдельные будут вроде как

LiBer ★★★
()
Ответ на: комментарий от LiBer

Ага, а еще WM\DE отдельные будут, и весь профит от нескольких мониторов теряется. Кстати (тут я - диванный) одновременно вроде несколько иксов на обычной одной видюхе работать не будут (если это не так я с радостью увидел бы мануал).

alozovskoy ★★★★★
()
Последнее исправление: alozovskoy (всего исправлений: 1)
Ответ на: комментарий от LiBer

Это неудобно, если всё же плотно работаешь в такой конфигурации (когда нужно, чтобы курсор передвигался как обычно).

У меня 3 дополнительных дисплея: слева, сверху и справа.

redhat
() автор топика
Ответ на: комментарий от redhat

Расположение мониторов можно заскриптовать (хотя может в момент «перемещения» экран будет моргать).

alozovskoy ★★★★★
()
Ответ на: комментарий от redhat

спасибо, осилил прочитать тред до конца, в общем там треш предлагается, не подходит, увы.'

Но я правильно понимаю формулировку задачи? Есть дисплей, сконфигурированный через RandR или Xinerama. Это один большой дисплей (:0), растянутый на два монитора, а не два раздельных экрана (:0.1, :0.0). И только в такой конфигурации тебе надо ограничить мышку. Правильно?

UPD. Перекид мышки все равно можно делать xdotool. Просто координаты во втором экране укажешь, и она туда перескочит. Остается вопрос, как ограничить мышку в таком окружении

А что за оконный менеджер, кстати? Некоторые умеют понимать конфигурации с раздельными экранами.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 2)
Ответ на: комментарий от Zubok

Некоторые умеют понимать конфигурации с раздельными экранами.

Например? Мне кажется это от wm не зависит, это на уровне xrandr/xinerama.

alozovskoy ★★★★★
()
Последнее исправление: alozovskoy (всего исправлений: 1)
Ответ на: комментарий от Zubok

А что за оконный менеджер, кстати?

тег awesome же.

Это один большой дисплей (:0),

да, определяемые xrandr'ом типа:

--output DVI-0 --primary --output HDMI-0 --right-of DVI-0 --output HDMI-1 --left-of DVI-0 --output HDMI-2 --above DVI-0
только на каждом из них панель еще и свои правила.

redhat
() автор топика
Ответ на: комментарий от Zubok

Перекид мышки все равно можно делать xdotool.

перекид мышки я сделал средствами awesome.

redhat
() автор топика
Ответ на: комментарий от alozovskoy

Например? Мне кажется это от wm не зависит, это на уровне xrandr/xinerama.

Например, awesome:

Besides the fact that awesome has: Real multihead support (XRandR, Xinerama or Zaphod mode) with per screen desktops (tags);

Zaphod mode это как раз оно.

Еще вроде openbox: http://openbox.org/wiki/Help:FAQ#How_do_I_run_Openbox_across_multiple_X_scree...

Еще вроде fvwm не пугается таких конфигураций и умеет себя раскидывать по найденным экранам. http://www.fvwm.org/documentation/faq/#toc_3.20

Fvwm spawns itself into all found screens unless -s command line parameter is specified, as explained in the man page.

 -s | --single-screen [screen_num]

    On a multi-screen display, run fvwm only on the screen 
named in the $DISPLAY environment variable or provided through 
the -d option. The optional argument screen_num should be 
positive or null and override the screen number. Normally, fvwm 
attempts to start up on all screens of a multi-screen display.

Disclamer: У меня ни одного из этих WM нет.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Zaphod mode это как раз оно.

Вот почему я и сказал выше, что треш. Мне нужно просто запретить курсору покидать текущий дисплей по хоткею и таким же образом разрешать.

Мне не нужно запускать разные сессии конфигураций монторов/wm'ов/исков и т.п. на разных дисплеях.

Это умеет Synergy, сейчас буду смотреть в её сорс как она это делает.

redhat
() автор топика
Ответ на: комментарий от redhat

Это умеет Synergy, сейчас буду смотреть в её сорс как она это делает.

Дык кроме внешней тулзовины вариантов нет. Вопрос, есть ли такая. Механизм ограничения предельно понятен. Координаты мышки перехватывай и стопори, когда границы достигла. Возможно, с использованием XGrabPointer.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 2)
Ответ на: комментарий от disarmer

Ага, спасибо! Но все равно у тебя иксы в иксах а не «чистый» запуск, да и опять же как мультисит это удобно, а как два монитора - нет.

alozovskoy ★★★★★
()
Ответ на: комментарий от Zubok

читал еще по первой ссылке, это по идее у меня уже установлено вместе с зависимостью иксов: x11-proto/fixesproto;

спс.

redhat
() автор топика
Ответ на: комментарий от redhat

А вот пару слов о способе XGrabPointer (это во всех серверах есть, так как Core Protocol):

http://permalink.gmane.org/gmane.comp.window-managers.awesome/6981

Есть еще, правда, XIGrabPointer. (X Input Extension). То есть идея такая: делается окно без ничего, прозрачное на один монитор и далее XGrabPointer.

UPD: Но мне кажется, чо это будет несколько черезжопно. Вроде как эти барьеры как раз недавно ввели в протокол и в сервер. И они как раз для твоих целей и подходят. И вроде как правильный механизм, но как он работает, ума не приложу.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 2)
Ответ на: комментарий от alozovskoy

Это да, все остальные известные мне схемы только на нескольких видеокартах. Зато такая схема позволяет накладывать поверх xephyr другие окна, например проигрыватель.

как мультисит это удобно, а как два монитора - нет

когда второй монитор не используется, обычно запускаю там проигрыватель (для остального мне хватает первого монитора), но ничего не мешает запускать что угодно. Нет отличий от обычной двухмониторной конфигурации, разве что второй монитор чуть подальше стоит

disarmer ★★★
()
Ответ на: комментарий от alozovskoy

Кстати (тут я - диванный) одновременно вроде несколько иксов на обычной одной видюхе работать не будут (если это не так я с радостью увидел бы мануал).

Если я правильно тебя понял, то

startx -- :2

HerrWeigel ★★★★
()

Средствами awesome: повесить на край экрана прозрачный wibox с сигналом, чтобы курсор при наведении на него отскакивал на пиксель назад.

Worron ★★★
()

Можно попробовать через встроенную функция mousegrabber, примерно так:

awful.key({}, "Scroll_Lock", function () 
    if (io.popen("xset q | grep Num |awk '{print $12}'"):read("*all"))=="on" then
       mousegrabber.run(function(mouse)
         if mouse.x > 3196 then
           mouse.x=3196
         end
         -- Возвращаем true, для продолжения работы
         return true
       end)
    else
      mousegrabber.stop()
    end),
Или если Scroll lock постоянно выдает значение off, завести переменную, и менять ее в условии, при очередном нажатии клавиши

Faiver
()
Ответ на: комментарий от redhat

Решение было чисто теоретическим. Раньше такой надобности не возникало. Сейчас попробовал. Да, не работает, начал разбираться почему, оказалось, что mousegrabber, не предназначен для длительного захвата. Т.е. по большому счету, захватывается одно движение, затем, переход к заданному значению, но после этого происходит прерывание. ((

Вот рабочий вариант, но мне он не нравится постоянно запущенным таймером :

todo_timer = timer({timeout = 0.1})
todo_timer:add_signal("timeout", function()
	mouse_pos=mouse.coords()
    if mouse_pos.x > 1280 then
		mouse.coords({ x=1280, y = mouse_pos.y }, true)
	end
end)
todo_timer:start()
Да и мышка дергается ((

Есть еще вариант от VimCasts

Faiver
()
Ответ на: комментарий от Faiver

Да и мышка дергается ((

Потому что ты не ограничиваешь перемещения, а просто возвращаешь курсор если он покинул экран. Это можно и на xdotool с тем же эффектом запилить.

alozovskoy ★★★★★
()
Ответ на: комментарий от Faiver

Я к тому что все одно - при использовании любого из этих методов курсор будет дергаться, плюс скорее всего конструкция будет сильно жрать ресурсы, потому что нужно как можно чаще проверять позицию курсора и сравнивать с «эталоном».

alozovskoy ★★★★★
()
Ответ на: комментарий от Zubok

Что-то у меня оно не собирается

$ gcc pointer-barriers-interactive.c -lX11
pointer-barriers-interactive.c: In function ‘main’:
pointer-barriers-interactive.c:245:17: warning: ‘XKeycodeToKeysym’ is deprecated (declared at /usr/include/X11/Xlib.h:1699) [-Wdeprecated-declarations]
                 int k = XKeycodeToKeysym (dpy, xev.xkey.keycode, 0);
                 ^
/tmp/ccJnHZm4.o: In function `create_barrier':
pointer-barriers-interactive.c:(.text+0x4dd): undefined reference to `XFixesDestroyPointerBarrier'
pointer-barriers-interactive.c:(.text+0x51c): undefined reference to `XFixesCreatePointerBarrier'
/tmp/ccJnHZm4.o: In function `process_barrier_event':
pointer-barriers-interactive.c:(.text+0x609): undefined reference to `XIBarrierReleasePointer'
/tmp/ccJnHZm4.o: In function `main':
pointer-barriers-interactive.c:(.text+0x740): undefined reference to `XFixesQueryVersion'
pointer-barriers-interactive.c:(.text+0x7f8): undefined reference to `XIQueryVersion'
pointer-barriers-interactive.c:(.text+0x9ac): undefined reference to `XISelectEvents'
collect2: error: ld returned 1 exit status

Причина понятна, но в сях я - ноль, не поправлю.

alozovskoy ★★★★★
()
Ответ на: комментарий от alozovskoy

Поправил.

$ diff oridinal_pointer-barriers-interactive.c new_pointer-barriers-interactive.c 
245c245,247
<                 int k = XKeycodeToKeysym (dpy, xev.xkey.keycode, 0);
---
>                 int k;
> //                int k = XKeycodeToKeysym (dpy, xev.xkey.keycode, 0);
>                 KeySym *keysym = XGetKeyboardMapping(dpy, xev.xkey.keycode, 1, &k);

Только что оно делает пока не понял =)

И, да, компиляция:

$ gcc new_pointer-barriers-interactive.c -lX11 -lXi -lXfixes
alozovskoy ★★★★★
()
Последнее исправление: alozovskoy (всего исправлений: 1)
Ответ на: комментарий от alozovskoy

Только что оно делает пока не понял =)

А, разобрался. При пересечении линии генерируются события, которые пока просто в терминал выводят информацию. На нажатия кнопок оно не реагирует. Короче это просто proof of concept.

alozovskoy ★★★★★
()
Ответ на: комментарий от alozovskoy

Только что оно делает пока не понял =)

А я и не знаю. Я не запускал. Там вроде хелп какой-то выводит. Интерактивная программа. Наверное, в месте, где курсор, она по нажатию кнопок из хелпа ставит барьер. И потом показывает всякие события при его дистижении.

    TEXT ("Press Q/Escape to exit.");
    TEXT ("Velocity threshold: %d", velocity_limit);
    TEXT ("Use up/down arrow keys to adjust.");
    TEXT (" ");
    TEXT ("Press R to put the barrier at a random Y location");
    TEXT ("Press S to %s the barrier", show_barrier ? "hide" : "show");
    TEXT ("Press B to globally %s", block ? "release" : "block");

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

Zubok ★★★★★
()
Ответ на: комментарий от alozovskoy

Ну, да. Это просто пример, который показывает, как использовать. Вообще, это новая фишка и широко мало где используется еще, поэтому примеров очень мало. А тут как раз маленький полезный пример. События тебе вообще не нужны. Тебе нужны функции установки барьера (в примере все есть).

ftp://ftp.x.org/pub/X11R7.7/doc/fixesproto/fixesproto.txt

Тебе только directions в CreatePointerBarrier надо правильно поставить, чтобы запретить физически переход через барьер.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Спасибо огромное!

Вот что у меня получилось:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/XInput2.h>

int dpy_w;
int dpy_h;

int barrier_x;
int barrier_y;
Display *dpy;
PointerBarrier barrier;
Window window;

static void
create_barrier (void)
{

//barrier = XFixesCreatePointerBarrier (dpy, window, 0, barrier_y, dpy_w, barrier_y, 0, 0, NULL); - for horizontal barrier
barrier = XFixesCreatePointerBarrier (dpy, window, barrier_x, 0, barrier_x, dpy_h, 0, 0, NULL); // for vertical barrier
}

int
main (int argc, char **argv)
{
    XEvent xev;
    XIEventMask mask;
    unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };

    dpy = XOpenDisplay(NULL);

    dpy_w = DisplayWidth (dpy, DefaultScreen (dpy));
    dpy_h = DisplayHeight (dpy, DefaultScreen (dpy));

    window = XCreateSimpleWindow (dpy, DefaultRootWindow(dpy),
                                  0, 0, dpy_w, dpy_h,
                                  0, BlackPixel(dpy, 0),
                                  WhitePixel(dpy, 0));

    barrier_y = 100;
    barrier_x = 100;

    create_barrier ();

    XISetMask (mask_bits, XI_BarrierHit);
    XISetMask (mask_bits, XI_BarrierLeave);
    mask.deviceid = XIAllMasterDevices;
    mask.mask = mask_bits;
    mask.mask_len = sizeof (mask_bits);
    XISelectEvents (dpy, window, &mask, 1);
    XSync(dpy, False);
 
    while (1) {}

}

Это работает, но за качество кода не ручаюсь - первый раз сегодня что-то делал с кодом на си, при этом просто повыкидывал все «ненужное» из примера. Ну и, конечно, тут все захардкожено.

alozovskoy ★★★★★
()
Последнее исправление: alozovskoy (всего исправлений: 1)
Ответ на: комментарий от alozovskoy

while (1) {}

Вот это плохо. В цикле вычитывай сообщения, то есть делай XNextEvent (dpy, &xev);, но просто сообщения не обрабатывай. тогда он у тебя в select() повиснет и процессор жрать не будет.

Это вроде тебе не нужно, если ты события никакие не обратываешь.

    XISetMask (mask_bits, XI_BarrierHit);
    XISetMask (mask_bits, XI_BarrierLeave);
    mask.deviceid = XIAllMasterDevices;
    mask.mask = mask_bits;
    mask.mask_len = sizeof (mask_bits);
    XISelectEvents (dpy, window, &mask, 1);
Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от alozovskoy

Вот как раз по ссылке выше самый простой клиент и описан (первый же код):

http://who-t.blogspot.ru/2012/12/whats-new-in-xi-23-pointer-barrier.html

mainloop(); в нем - это как раз твой while с XNextEvent.

вот такой тебе и нужен. Совсем маленький. Окно (XCreateSimpleWindow) тебе тоже не нужно совершенно, можешь убрать. Ты работаешь на окне root, оно уже есть по умолчанию.

barrier = XFixesCreatePointerBarrier(dpy, DefaultRootWindow(dpy),
                                          ^^^^^^^^^^^^^^^^^^^^^^
Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от alozovskoy

Вот рабочий код. Я проверил.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>

int
main (int argc, char **argv)
{
    XEvent xev;
    int fixes_opcode, fixes_event_base, fixes_error_base;
    PointerBarrier barrier;
    int dpy_w;
    int dpy_h;
    Display *dpy;

    dpy = XOpenDisplay(NULL);

    if (!XQueryExtension(dpy, "XFIXES",
			 &fixes_opcode,
			 &fixes_event_base,
			 &fixes_error_base))
	return EXIT_FAILURE;

    dpy_w = DisplayWidth (dpy, DefaultScreen (dpy));
    dpy_h = DisplayHeight (dpy, DefaultScreen (dpy));

    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy), 
					  100, 0, 100, dpy_h, 
					  0, 0, NULL); // for vertical barrier
    while (1) {
	XNextEvent (dpy, &xev);
    }
}

Параметры каждого монитора можно из расширения RandR узнать. Там будет указано, какой монитор где расположен и какие у них разрешения. dpy_w = DisplayWidth (dpy, DefaultScreen (dpy)); выдаст тебе ширину всего виртуального экрана :0, а не помониторно.

UPD. Или сделай так, чтобы координату вертикального барьера можно было передать через командную строчку. Скажем

./vertical-pointer-barrier 1280
Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.