我正在尝试开发一个简单的应用程序,由一个带有红色方块的窗口组成,用作按钮。应用程序代码如下:
按钮/调试功能:
// Define a structure for the button
typedef struct {
SDL_Rect draw_rect; // dimensions of button
struct {
Uint8 r, g, b, a;
} colour;
bool pressed;
} button_t;
static bool button(SDL_Renderer* r, button_t* btn) {
// draw button
SDL_SetRenderDrawColor(r, btn->colour.r, btn->colour.g, btn->colour.b, btn->colour.a);
SDL_RenderFillRect(r, &btn->draw_rect);
// if button press detected - reset it so it wouldn't trigger twice
if (btn->pressed) {
btn->pressed = false;
return true;
}
return false;
}
// Write a function to process the mouse events for the button
static void button_process_event(button_t* btn, const SDL_Event* ev)
{
// react on mouse click within button rectangle by setting 'pressed'
if (ev->type == SDL_MOUSEBUTTONDOWN) {
if (ev->button.button == SDL_BUTTON_LEFT &&
ev->button.x >= btn->draw_rect.x &&
ev->button.x <= (btn->draw_rect.x + btn->draw_rect.w) &&
ev->button.y >= btn->draw_rect.y &&
ev->button.y <= (btn->draw_rect.y + btn->draw_rect.h)) {
btn->pressed = true;
}
}
}
// Write a function to print the mouse event
static void print_event(const SDL_Event* e) {
// print the event type
if (e->type == SDL_FINGERDOWN) {
printf("touch finger DOWN event\n");
}
else if (e->type == SDL_FINGERUP) {
printf("touch finger UP event\n");
}
else if (e->type == SDL_FINGERMOTION) {
printf("touch finger MOTION event\n");
}
else if (e->type == SDL_MOUSEMOTION) {
printf("Mouse motion event\n");
printf("mouse motion coords: %d,%d\n",e->motion.x,e->motion.y);
}
else if (e->type == SDL_MOUSEBUTTONDOWN) {
printf("Mouse button down event\n");
printf("button coords: %d,%d\n",e->button.x,e->button.y);
}
else if (e->type == SDL_MOUSEBUTTONUP) {
printf("Mouse button up event\n");
printf("button coords: %d,%d\n",e->button.x,e->button.y);
}
else if (e->type == SDL_MOUSEWHEEL) {
printf("Mouse wheel event\n");
}
else{
printf("unknown event %d\n",e->type);
}
}
int main(int argc, char* argv[])
{
// Initialize the SDL2 video subsystem
SDL_Init(SDL_INIT_VIDEO);
// Create a window with a title, position, and size
SDL_Window* window = SDL_CreateWindow("Empty Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 240, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_FULLSCREEN );
// Create a renderer for the window
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
// Set the renderer's draw color
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // black
// Clear the renderer with the draw color
SDL_RenderClear(renderer);
// Create an instance of the button structure
button_t start_button = {
.colour = {.r = 255, .g = 10, .b = 10, .a = 255}, // white
.draw_rect = {.x = 100, .y = 0, .w = 100, .h = 100}, // center of the window
};
然后是主要功能:
// Main loop
SDL_Event event;
bool quit = false;
while (!quit) {
// Poll events
while (SDL_PollEvent(&event)) {
// Quit on close, window close, or 'escape' key hit
if (event.type == SDL_QUIT ||
(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) ||
(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) {
quit = true;
}
// Pass event to button
button_process_event(&start_button, &event);
//debug event
print_event(&event);
}
// Clear the renderer
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // black
SDL_RenderClear(renderer);
// Draw the button
if (button(renderer, &start_button)) {
// Handle the button click event
printf("Start button pressed\n");
}
// Present the renderer
SDL_RenderPresent(renderer);
}
// Destroy the renderer and the window
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
// Quit the SDL2 video subsystem
SDL_Quit();
return 0;
}
正如预期的那样,上面的代码会生成一个带有红色方形按钮的黑色窗口,但是,我观察到一些奇怪的行为:
当我第一次尝试触摸屏幕(屏幕的每个位置)时,以下字符串会打印在标准输出上: “鼠标按钮按下事件 按钮坐标:0,0 鼠标按钮松开事件 按钮坐标:0,0” 似乎屏幕区域保持“聚焦”,直到我将手指拖动到其他屏幕位置(没有运动事件,聚焦区域保持不变);
手指触摸/运动生成的事件只是鼠标事件:鼠标按钮按下+鼠标按钮向上或鼠标运动(我尝试使用鼠标事件相关提示但没有成功);
与1中所述一致,使程序打印“按下开始按钮”(仅当按下红色方形按钮时才打印)我必须先将手指拖动到按钮区域(产生运动事件)在该区域),然后程序开始为每次触摸屏幕打印“按下开始按钮”(独立于触摸的区域)。
有人对让我的应用程序“正常”工作有任何建议吗?
问题在于使用带有 libinput 的 directfb 作为底层“驱动程序”,由于某种原因,它会将触摸屏设备解释为纯鼠标设备。 通过使用选项 --enable-tslib 重新编译 directfb 并导出 env_var TSLIB_TSDEVICE=/dev/input/event0 (在我的例子中这是事件设备),问题已经解决。