LINUX.ORG.RU

Перемещение собственного окна программно в X11

 , ,


0

3

Здравствуйте

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

// Изменение положения окна на рабочем столе
void GPlatformUnixOGL::SetWindowRect(CMagicRect* rect)
{
    int wi=rect->Width();
    int he=rect->Height();

   XMoveResizeWindow(display, window, rect->left, rect->top, wi, he);

    XFlush(display);
}

Попытки делать что-то типа override_redirect=True; приводят к тому, что окно нельзя свернуть, хотя дребезга и становится меньше.

Что я делаю не так ? Мне всего-то и надо, чтобы окно заняло то положение, которое я ему отправляю.

Само окно создается так:

int glxAttribs[]={
GLX_RGBA,               // Используем режим RGBA
GLX_DOUBLEBUFFER,       // Двойная буферизация
None                    // Завершаем список атрибутов
};

// Выбираем визуальный формат
XVisualInfo* visualInfo=glXChooseVisual(display, screen, glxAttribs);

Window rootWindow=RootWindow(display, screen);
XSetWindowAttributes windowAttributes;
windowAttributes.colormap=XCreateColormap(display, rootWindow, visualInfo->visual, AllocNone);
windowAttributes.background_pixmap=None;  // ОТКЛЮЧАЕМ очистку фона!
windowAttributes.backing_store=Always;    // Просим X11 сохранять буфер окна

window=XCreateWindow(
display,
rootWindow,
wx, wy, view_width, view_height, // Позиция и размер окна
0,                               // Без границы
visualInfo->depth,               // Глубина цвета
InputOutput,                     // Тип окна
visualInfo->visual,              // Визуальный формат
CWColormap | CWEventMask,        // Устанавливаем атрибуты окна
&windowAttributes
);


// Указываем тип окна NORMAL
Atom wmWindowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
Atom wmWindowNormal = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
XChangeProperty(display, window, wmWindowType, XA_ATOM, 32, PropModeReplace, (unsigned char *)&wmWindowNormal, 1);

// Отключаем рамки и заголовок
Atom motifHints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
struct {
long flags;
long functions;
long decorations;
long input_mode;
long status;
} hints = { 2, 0, 0, 0, 0 };
XChangeProperty(display, window, motifHints, motifHints, 32, PropModeReplace, (unsigned char *)&hints, 5);

XSizeHints *h = XAllocSizeHints();
h->flags = PPosition | PSize | PResizeInc | PBaseSize;
h->x = 100;          // Координаты X
h->y = 100;          // Координаты Y
h->width = 640;      // Ширина окна
h->height = 480;     // Высота окна
h->base_width = 640; // Базовая ширина
h->base_height = 480; // Базовая высота

XSetWMNormalHints(display, window, h);
XFree(h);

Всё изображение внутри окна рисуется через OpenGL, включая собственный заголовок и кнопки типа развернуть/свернуть.

Тебя вяленый покусал, что-ли?

anonymous
()

Окно при перетаскивании дребезжит по всему экрану, хотя и перемещается в нужную сторону.

Подозреваю что у тебя проблема с расчётом координат.

rect->left, rect->top

Вот эти значения откуда там берутся? Надо в начале перемещения запомнать все нужные числа и потом смотреть только на положение мышки и пересчитывать по ней. Я когда делал перемещение/ресайз в своём WM, сначала пересчитывал всё при каждом движении мышки и тоже дребезжание получалось из-за разных факторов.

И уточни, что именно ты под «дребезжит» имеешь ввиду - меняются координаты начала окна или его размер?

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

Почему антипаттерн, может он хочет индивидуальный дизайн.

Но, автор, если ты хочешь эмулировать таким способом стандартный заголовок в обычном его оформлении - то, да, так делать не надо. Заголовки в разных WM разные, а в каких-то их вообще нет.

firkax ★★★★★
()

Что за wm? И как он обрабатывает configurenotify?. Думаю они друг другу мешают при перетаскивании окна мышью, поэтому у тебя окно туда-сюда елозит. Это асинхронно происходит. Выставь для окна wm hints, wm window type(dock или dialog). А wm дальше сам справится.

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

И уточни, что именно ты под «дребезжит» имеешь ввиду - меняются координаты начала окна или его размер?

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

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

Что за wm?

echo $DESKTOP_SESSION
/usr/share/xsessions/plasma

echo $XDG_CURRENT_DESKTOP
KDE

У меня достаточно неновая Fedora

Выставь для окна wm hints, wm window type(dock или dialog).

Dock вообще лучше не ставить, потому что мой Linux такое окно всегда отображает поверх других окон, а кроме того оно не сворачивается.

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

Антипаттерн и юзай тогда SDL.

Хотелось бы обойтись без SDL, тем более, что там нет Drag & Drop.

Вообще сейчас ситуация такова, что по крайней мере на моем компьютере всё более-менее заработало. Единственное что всё портит - если приложение стартует с развернутым окном (точнее я его не разворачиваю, а просто указываю положение во весь экран), то потом приложение уже размер окна менять отказывается (просто игнорирует новые размер и положение). Тут надо ещё подумать…

Odin_KG
() автор топика