Сказка
Я сделал простую программу для рисования, отображающую графику, используя X11/Xlib для системы Linux.
В нем есть меню и редактор для создания рисунков.
Ему нужно знать размер окна, поэтому сначала я использовал XGetWindowAttributes()
, но на мой вкус он оказался слишком медленным.
Поскольку я выполнял функцию каждый кадр, моя программа работала медленно.
Затем я пытался запускать функцию реже, примерно каждые 4 кадра, но это вызывало мерцание .
Я хотел, чтобы событие могло генерироваться каждый раз при изменении размера окна, чтобы запускать функцию только при изменении размера.
Исходное исправление:
Я нашел ResizeRequest
, который делает то, что я хочу и выводит размер окна в качестве бонуса.
Так что XGetWindowAttributes()
мне больше не понадобилось. Это значительно ускорило работу программы.
Хорошо работает при уменьшении размера окна.
Новый выпуск:
Я обнаружил, что когда размер окна больше больше исходного размера, каждый объект, нарисованный за пределами исходного диапазона, обрезается< /strong> как показано на изображении.
Мы видим серые рамки, которые должны быть вокруг окна, но обрезаны все черные. Это особенно заметно для цветовой палитры вверху справа, которая состоит из 16 цветов, но 4 цвета обрезаны наполовину, а 8 не видны здесь вообще. .
Что я хотел бы сделать:
Я хотел бы знать, как решить проблему обрезки, возможно, решив один из следующих вопросов:
- Если я должен одобрить изменение размера при отправке события, как мне это сделать?
- Если я должен возиться с буферами, как я могу это сделать?
Треки:
В моей программе есть меню, в котором по-прежнему используется XGetWindowAttributes()
, а редактор (показан на изображении) использует событие ResizeRequest
, которое работает быстрее, чем XGetWindowAttributes()
.
Как и ожидалось , обрезка происходит в редакторе, а не в меню.
Но я заметил, что я могу изменить размер окна без обрезки, если я изменю его в меню, а затем в редакторе, и < strong>это работает!
Затем я обнаружил, что обрезка происходит всякий раз, когда в функции XSelectInput()
установлено значение ResizeRedirectMask
.
Как указано в Руководстве по программированию Xlib в версии 10.11. 4 Страница событий ResizeRequest.
Любые попытки изменить размер другими клиентами затем перенаправляются.
Я думаю, это означает, что это не повлияет на размер окна (что верно, поскольку я тестировал XGetWindowAttributes()
параллельно). Итак, я должен одобрить изменение размера, но как?
Как указано в ответе размер окна X11 заикается.
Я бы очистил передний буфер и дождался завершения изменения размера.
Как это сделать?
Образец кода:
Я сделал короткую программу, которая отображает случайные цветные квадраты везде, даже за пределами окна. Программа запускается, если ее скопировать.
Существует утверждение #if
, которое вы можете изменить, чтобы увидеть разницу между ожидаемым (false
) и реальным (true
)
#include <X11/Xlib.h>
#include <cstdint>
#include <unistd.h>
#if true //Make it true to set ResizeRedirectMask and false to disable.
#define Masks KeyPressMask|ResizeRedirectMask
#else
#define Masks KeyPressMask
#endif
int main(){
uint32_t RDM=0;
uint16_t i=0;
bool RunLoop=true;
Display* XDisplay=XOpenDisplay(0);//Create a display
Window XWindow=XCreateSimpleWindow(XDisplay,DefaultRootWindow(XDisplay),0,0,480,360,0,0,0);//Create a Window
XMapWindow(XDisplay,XWindow);//Make the Window visible
GC XGraphicCTX=XCreateGC(XDisplay,XWindow,0,0);//Create a Graphics Context
//v Wait for a MapNotify XEvent for next commands
XSelectInput(XDisplay,XWindow,StructureNotifyMask);
while(1){
XEvent e;
XNextEvent(XDisplay,&e);
if(e.type==MapNotify)break;
}
XSelectInput(XDisplay,XWindow,Masks); //Here is part of the magic error
while(RunLoop){
while(XPending(XDisplay)){//Get key changes
XEvent Event;
XNextEvent(XDisplay,&Event);
if(Event.type==KeyPress){
RunLoop=false;
}
}
for(i=0;i<4096;i++){
RDM=(RDM+1841)*9245; //Not perfect but good enough
XSetForeground(XDisplay,XGraphicCTX,RDM&0xFFFFFF);
RDM=(RDM+1841)*9245; //Not perfect but good enough
XFillRectangle(XDisplay,XWindow,XGraphicCTX,RDM&0xFFFF,(RDM>>16),64,64);
}
XFlush(XDisplay);
usleep(16667); //AHHH there is 666!
}
return 0;
}
Результат при изменении размера выглядит следующим образом:
Как мы видим, обрезка происходит всякий раз, когда установлено ResizeRedirectMask
, вам даже не нужно реагировать на событие, чтобы это произошло!
Переключение оператора #if
на false
дает желаемое поведение, так как это отключит ResizeRedirectMask
.
Эта конкретная программа не заботится о размере окна, большинству моих программ нужно знать размер, иначе они не работают.
Некоторые детали:
Я раньше получал размер окна с помощью XGetWindowAttributes()
что немного медленно, я до сих пор использую его в меню поскольку он работает достаточно хорошо.
Вот почему в редакторе я использую событие ResizeRequest
.
Событие ConfigureNotify
кажется отлично работает, но оно мигает гораздо чаще, чем при использовании XGetWindowAttributes()
.
Почему оно мерцает?
Оно мерцает, потому что ConfigureNotify
отправлено после завершения изменения размера, это означает, что оно обычно отправляет один кадр после изменения размера.
Это связано с Изменение размера окна X11 тормозит.
По крайней мере, это не тратит впустую много выступлений.
Я ищу способ исправить мерцание, как это может быть проще.
Обратите внимание, что вопрос полностью изменился, потому что проблема отличается от первоначальной. Но все еще в связи с исходной проблемой.