Skip to content
Advertisement

Restarting an endless while loop upon a mouse event?

I am aiming a simple code which looks like this:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <linux/input.h>

int main()
{
    int fd, bytes;
    unsigned char data[3];
    fd = open("/dev/input/mice", O_RDWR);
    int left;

    while(1)
    {    
        bytes = read(fd, data, sizeof(data));

        if(bytes > 0)
        {
            left = data[0] & 0x1;
            right = data[0] & 0x2;

            if(left==1){
            goto reset_EVENT;
            }           
        }

        reset_EVENT:

        printf("hey 1");
        sleep(1);   
        printf("hey 2");
        sleep(1);
        printf("hey 3");
        sleep(1);
    }
    return 0;
}

My goal here is to restart the print sequence from “hey 1” immediately when left mouse is clicked. However, I am not able to achieve this without using “if” conditions before every sleep. a “goto” is not working for me across different functions too. Can anyone suggest an optimal solution for this one please ?

Advertisement

Answer

You could achieve this with some kind of state machine: a function which has an internal static state to know whick was the last hey printed

void print_event(int reset)
{
    /* by default, print nothing */
    static int state = 4;

    /* if reset, restart counting */
    if (reset) 
        state = 1;

    /* if state under 4, display `hey` */
    if (state <= 3)
        printf("hey %dn", state++);
}

int main()
{
    int fd, bytes;
    unsigned char data[3];
    fd = open("/dev/input/mice", O_RDWR);
    int left, right;        

    while(1)    
    {   
        /* by default, event is not reset */
        int reset = 0;
        bytes = read(fd, data, sizeof(data));

        if(bytes > 0)
        {
            left = data[0] & 0x1;
            right = data[0] & 0x2;

            if(left==1){
                /* left click: reset event*/
                reset = 1;
            }           
        }

        /* ask function to print if needed */
        print_event(reset);

        sleep(1);               
    }
    return 0;
}

EDIT

one problem in your loop is that you will wait a long time before reading new value from fd.

You can use signal to achieve this:

  • continously reading input from mice, without sleeping
  • when left click is detected, arm an alarm signal to display event:

Thus, your code could be:

/* print event function: can be called from alarm signal handler
   or directly from main function */
void print_event(int reset)
{
    /* by default, print nothing */
    static int state = 4;

    /* if reset, restart counting */
    if (reset) 
        state = 1;

    /* if state under 4, display `hey` */
    if (state <= 3)
    {
        printf("hey %d", state++);

        /* if all `hey` have not been printed, prepare the next */
        alarm(1);
    }
}

/* alarm signal receiver*/
void handle(int sig) {
    /* print event without reset */
    print_event(0);
}

int main()
{
    int fd, bytes;
    unsigned char data[3];
    fd = open("/dev/input/mice", O_RDWR);
    int left;

    /* tell what function is to be called when alarm signal is raised */
    signal(SIGALRM, handle);

    /* if you want to display one sequence before the first click, uncomment the following line */
    /* print_event(1); */

    while(1)    
    {   
        bytes = read(fd, data, sizeof(data));

        if(bytes > 0)
        {
            left = data[0] & 0x1;                

            if(left==1){
                /* left click: reset event*/
                print_event(1);
            }           
        }
    }
    return 0;
}
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement