/* winnie - an experimental window system Copyright (C) 2013 Eleni Maria Stea This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Author: Eleni Maria Stea */ #ifdef WINNIE_FBDEV #include #include #include #include #include #include #include #include #include #include "geom.h" #include "gfx.h" #include "mouse.h" #include "shalloc.h" #include "window.h" #include "winnie.h" #include "wm.h" #define BN_LEFT 1 #define BN_RIGHT 2 #define BN_MIDDLE 4 static int read_mouse(); struct Mouse { int dev_fd; Rect bounds; int pointer_x; int pointer_y; int bnstate; }; static Mouse *mouse; bool init_mouse() { if(!(mouse = (Mouse*)sh_malloc(sizeof *mouse))) { return false; } get_subsys()->mouse_offset = (int)((char*)mouse - (char*)get_pool()); memset(mouse, 0, sizeof *mouse); mouse->dev_fd = -1; if((mouse->dev_fd = open("/dev/psaux", O_RDONLY | O_NONBLOCK)) == -1) { fprintf(stderr, "Cannot open /dev/psaux : %s\n", strerror(errno)); return false; } set_mouse_bounds(get_screen_size()); return true; } void destroy_mouse() { if(mouse->dev_fd != -1) { close(mouse->dev_fd); mouse->dev_fd = -1; } sh_free(mouse); } bool client_open_mouse(void *smem_start, int offset) { mouse = (Mouse*)((unsigned char*)smem_start + offset); return true; } void client_close_mouse() { } void set_mouse_bounds(const Rect &rect) { mouse->bounds = rect; } int get_mouse_fd() { return mouse->dev_fd; } void process_mouse_event() { /* TODO: * - read all pending events from mouse fd (use O_NONBLOCK so that * read will return -1 when there are no more events instead of blocking). */ int prev_state = mouse->bnstate; int prev_x = mouse->pointer_x; int prev_y = mouse->pointer_y; if(read_mouse() == -1) { return; } Window *top; if(!(top = wm->get_grab_window())) { top = wm->get_window_at_pos(mouse->pointer_x, mouse->pointer_y); if(top) { wm->set_focused_window(top); } else { wm->set_focused_window(0); } } /* - send each pointer move and button press/release to the topmost window * with the pointer on it. */ int dx = mouse->pointer_x - prev_x; int dy = mouse->pointer_y - prev_y; if((dx || dy) && top) { MouseMotionFuncType motion_callback = top->get_mouse_motion_callback(); if(motion_callback) { Rect rect = top->get_absolute_rect(); motion_callback(top, mouse->pointer_x - rect.x, mouse->pointer_y - rect.y); } } MouseButtonFuncType button_callback; if((mouse->bnstate != prev_state) && top && (button_callback = top->get_mouse_button_callback())) { int num_bits = sizeof mouse->bnstate * CHAR_BIT; for(int i=0; ibnstate >> i) & 1; int prev_s = (prev_state >> i) & 1; if(s != prev_s) { Rect rect = top->get_absolute_rect(); button_callback(top, i, s, mouse->pointer_x - rect.x, mouse->pointer_y - rect.y); } } } } void get_pointer_pos(int *x, int *y) { *x = mouse->pointer_x; *y = mouse->pointer_y; } int get_button_state() { return mouse->bnstate; } int get_button(int bn) { if(bn < 0 || bn >= 3) { return 0; } return (mouse->bnstate & (1 << bn)) != 0; } static int read_mouse() { int rd; signed char state[3] = {0, 0, 0}; if((rd = read(mouse->dev_fd, state, 3)) == -1) { fprintf(stderr, "Unable to get mouse state : %s\n", strerror(errno)); return -1; } mouse->bnstate = state[0] & 7; mouse->pointer_x += state[1]; mouse->pointer_y -= state[2]; if(mouse->pointer_x < mouse->bounds.x) { mouse->pointer_x = mouse->bounds.x; } if(mouse->pointer_y < mouse->bounds.y) { mouse->pointer_y = mouse->bounds.y; } if(mouse->pointer_x > mouse->bounds.x + mouse->bounds.width - 1) { mouse->pointer_x = mouse->bounds.x + mouse->bounds.width - 1; } if(mouse->pointer_y > mouse->bounds.y + mouse->bounds.height - 1) { mouse->pointer_y = mouse->bounds.y + mouse->bounds.height - 1; } return 0; } #endif // WINNIE_FBDEV