LinuxForum.Fans
Тема

KeyRelease и его причуды

Автор: dedm0zaj 7 сообщений 1302 просмотров
#213686

или мои причуды...

перед вами часть кода отлавливания сообщений при создании окошечка на иксах:

text

XNextEvent(dpy, &event); //чтение сообщения из очереди
      switch (event.type)
      {
        case KeyRelease: //если происходит отпуск кнопки, то keyR = true
        {
          keyR = true;
          break;
        }
      }

на сколько я понял, KeyRelease это аналог виндового WM_KEYUP, т.е когда любая кнопка на клавиатуре подымается вверх (отпускается после нажатия), то посылается сообщение, тип которого KeyRelease. и, исходя из вышеуказанного кода, keyR должна стать true.

но на деле keyR становится true почему то после того, как я зажму любую клавишу и подожду некоторое время (всё ещё не отпуская клавишу). время, которое я жду, это время от нажатия на кнопку до того, как символ нажатой кнопки начнёт многократно набираться автоматически.

короткие нажатия и отпуская кнопок не делают из keyR true.

в общем или я наркоман, или KeyRelease такая странная.

зы IDE - Code::Blocks, компилятор - gnu gcc, пробовал компилить как у себя под арчи, так и под свежей убунтой

#213698

странно всё это... из идей только: маска получаемых событий неправильно задана...
хотя всё равно не должно окно себя так вести...
можно минимальный компилируемый нерабочий пример?

#213703

у меня в коде такой срач ибо я просто тестирую :D но вот

main.cpp

Показать
text

#include <stdio.h>
#include <stdlib.h>

#include <iostream>

#include <GL/glx.h> #include <GL/gl.h>

#include <X11/X.h> #include <X11/keysym.h>

#include <time.h>

#include "c_timer.h"

using namespace std;

static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, None}; static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None};

Display *dpy; Window win; GLfloat xAngle = 42.0, yAngle = 82.0, zAngle = 112.0; GLboolean doubleBuffer = GL_TRUE; GLboolean needRedraw = GL_FALSE;

XVisualInfo *vi; Colormap cmap; XSetWindowAttributes swa; GLXContext cx; XEvent event;

bool keyR = false;

int a = 0;

void (* redraw2)();

void timemake();

void timemake2() { cout << a << endl; a = 0; }

void fatalError(char *message) { fprintf(stderr, "main: %s\n", message); exit(1); }

void redraw(timespec*req) { a++;

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glTranslatef(0.0, 0.0, -3.0);

glRotatef(xAngle, 0.1, 0.0, 0.0); glRotatef(yAngle, 0.0, 0.1, 0.0); glRotatef(zAngle, 0.0, 0.0, 1.0);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBegin(GL_QUADS); glColor3f(0.0, 0.7, 0.1); glVertex3f(-1.0, 1.0, 1.0); glVertex3f(1.0, 1.0, 1.0); glVertex3f(1.0, -1.0, 1.0); glVertex3f(-1.0, -1.0, 1.0);

glColor3f(0.9, 1.0, 0.0); glVertex3f(-1.0, 1.0, -1.0); glVertex3f(1.0, 1.0, -1.0); glVertex3f(1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, -1.0);

glColor3f(0.2, 0.2, 1.0); glVertex3f(-1.0, 1.0, 1.0); glVertex3f(1.0, 1.0, 1.0); glVertex3f(1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, -1.0);

glColor3f(0.7, 0.0, 0.1); glVertex3f(-1.0, -1.0, 1.0); glVertex3f(1.0, -1.0, 1.0); glVertex3f(1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, -1.0); glEnd();

if (doubleBuffer) glXSwapBuffers(dpy, win);/* buffer swap does implicit glFlush */ else glFlush(); /* explicit flush for single buffered case */ nanosleep(req, (struct timespec *)NULL); }

int main(int argc, char **argv) {

//redraw2 = &redraw;

struct timespec req = {0}; req.tv_sec = 0; req.tv_nsec =10 * 1000000L;

dpy = XOpenDisplay(NULL);

vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf); if (vi == NULL) { vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf); doubleBuffer = GL_FALSE; }

cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); swa.colormap = cmap; swa.border_pixel = 0; swa.event_mask = KeyPressMask | ExposureMask | ButtonPressMask | StructureNotifyMask; win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 300, 300, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa); XSetStandardProperties(dpy, win, "main", "main", None, argv, argc, NULL);

cx = glXCreateContext(dpy, vi, /* no shared dlists */ None, /* direct rendering if possible */ GL_TRUE);

glXMakeCurrent(dpy, win, cx);

XMapWindow(dpy, win);

glEnable(GL_DEPTH_TEST);

glClearColor(0.0, 0.0, 0.0, 0.0);

glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0); glViewport(0, 0, 300, 300);

printf( "Press left mouse button to rotate around X axis\n" ); printf( "Press middle mouse button to rotate around Y axis\n" ); printf( "Press right mouse button to rotate around Z axis\n" ); printf( "Press ESC to quit the application\n" );

c_timer tim(10,timemake); c_timer tim2(1000, timemake2);

while (1) {

if (XPending(dpy) == 0) {redraw(&req);} else { XNextEvent(dpy, &event); switch (event.type) { case KeyRelease: { keyR = true; break; } case KeyPress: { KeySym keysym; char buffer[1]; XLookupString((XKeyEvent *)&event,buffer,1,&keysym,NULL); cout << buffer[0]; if ( (XLookupString((XKeyEvent *)&event,buffer,1,&keysym,NULL) == 1) && (keysym == (KeySym)XK_Escape) ) exit(0);

if (keysym == (KeySym)'r') keyR = false; break; } case ButtonPress: switch (event.xbutton.button) { case 1: {xAngle += 10.0; } break; case 2: yAngle += 10.0; break; case 3: zAngle += 10.0; break; } break; case ConfigureNotify: glViewport(0, 0, event.xconfigure.width, event.xconfigure.height); break; } }

}

return 0; }

void timemake() { xAngle += 1.0; if (keyR == true) yAngle += 1.0; }

c_timer.h

Показать
text

#ifndef C_TIMER_H_INCLUDED
#define C_TIMER_H_INCLUDED

#include <time.h> #include <pthread.h>

class c_timer { private: int step_t; void (*timer_make)(); void thread_make(); static void* thread_func(void *); public: c_timer(int, void ()); //~c_timer(); //inline int get_sec() {return req.tv_sec;} };

#endif // C_TIMER_H_INCLUDED

c_timer.cpp

Показать
text

#include "c_timer.h"

c_timer::c_timer(int msek, void (*ati)()) { if (msek<1) msek = 1; step_t = msek*10; pthread_t thread1; timer_make = ati; pthread_create(&thread1, NULL, thread_func, this); }

void* c_timer::thread_func(void *arg) { c_timer* p = reinterpret_cast<c_timer*>(arg); p->thread_make(); return NULL; }

void c_timer::thread_make() { timespec req; req.tv_sec = 0; req.tv_nsec = 1000000L;

int t1, tt; timespec req2; clockid_t clid = CLOCK_MONOTONIC;

clock_gettime(clid, &req2); tt = req2.tv_sec*10000 + req2.tv_nsec/100000 + step_t;

while (1>0){ clock_gettime(clid, &req2); t1 = req2.tv_sec*10000 + req2.tv_nsec/100000; if (t1>tt) { tt = tt + step_t; timer_make(); } nanosleep(&req, (struct timespec *)NULL); } }

запускать с либами GL, rt, pthread

если срабатывает KeyRelease, то кубик начинает вращаться ещё и по другой оси

#213711

блин! я два дня искал в инете проблему, а оказывается и правда маску не настроил oO позор мне

это всё из-за того, что копаюсь в готовом примере, не изучив его полностью

зы тему можно удалить, как за ложную тревогу

#213714
dedm0zaj написал:
или мои причуды...

Я таки думаю, что скорее это :lol:

dedm0zaj написал:

на сколько я понял, KeyRelease это аналог виндового WM_KEYUP,

Категорически! - не ищите ни в каком случае и ни в какой ситуации аналогии с Windows. У UNIX и Windows программирования (гораздо больше, чем в использовании или администрировании) настолько различающиеся история, традиции, привычки и стереотипы, что поиск аналогий из Windows всегда только сильно затягивает и усложняет понимание проблемы.

#213716
dedm0zaj написал:
зы IDE - Code::Blocks, компилятор - gnu gcc, пробовал компилить как у себя под арчи, так и под свежей убунтой

А при чём здесь компиляция и вид компилятора вообще?
Это мог бы быть вообще из SolarisStudio компилятор cc вместо gcc - было бы в точности то же.
От библиотек .so могут зависеть эффекты ... а от компилятора?

#213718
Olej написал:
У UNIX и Windows программирования настолько различающиеся история, традиции, привычки и стереотипы

мир познаётся в сравнении smile

Войдите или зарегистрируйтесь, чтобы ответить.