/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Stuff for BeOS. * * By Jason Wilkins. * * Windowed mode modifications by Peter Wang. * * Cursor show/hide in windowed mode added by Angelo Mottola. * * See readme.txt for copyright information. */ #include "bealleg.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintbeos.h" #ifndef ALLEGRO_BEOS #error something is wrong with the makefile #endif #define MOUSE_THREAD_NAME "mouse driver" #define MOUSE_THREAD_PRIORITY 60 #define MOUSE_THREAD_PERIOD 20000 // microseconds, 1/50th of a second #define CLAMP(low, var, high) (((var) < (low))?(low):(((var) > (high))?(high):(var))) #define PREFIX_I "al-bmouse INFO: " #define PREFIX_W "al-bmouse WARNING: " #define PREFIX_E "al-bmouse ERROR: " static thread_id mouse_thread_id = -1; static volatile bool mouse_thread_running = false; sem_id _be_mouse_view_attached = -1; BWindow *_be_mouse_window = NULL; BView *_be_mouse_view = NULL; bool _be_mouse_window_mode = false; static int be_mouse_x = 0; static int be_mouse_y = 0; static int be_mouse_b = 0; static int be_mickey_x = 0; static int be_mickey_y = 0; static int limit_up = 0; static int limit_down = 0; static int limit_left = 0; static int limit_right = 0; static bool be_mouse_warped = false; int32 mouse_thread(void *mouse_started) { BPoint cursor(0, 0); uint32 buttons; if (!_be_mouse_window_mode) { set_mouse_position(320, 240); } release_sem(*(sem_id *)mouse_started); for (;;) { acquire_sem(_be_mouse_view_attached); if (mouse_thread_running == false) { release_sem(_be_mouse_view_attached); TRACE(PREFIX_I "mouse thread exited\n"); return 0; } if ((_be_focus_count > 0) && _be_mouse_window->Lock()) { _be_mouse_view->GetMouse(&cursor, &buttons); if (!_be_mouse_window_mode) { int dx = (int)cursor.x - 320; int dy = (int)cursor.y - 240; if (be_mouse_warped) { dx = 0; dy = 0; be_mouse_warped = false; } be_mickey_x = dx; be_mickey_y = dy; be_mouse_x += dx; be_mouse_y += dy; if (dx != 0 || dy != 0) { set_mouse_position(320, 240); } } else { BRect bounds = _be_mouse_window->Bounds(); if (bounds.Contains(cursor)) { int old_x = be_mouse_x; int old_y = be_mouse_y; _mouse_on = TRUE; if (!be_app->IsCursorHidden()) { be_app->HideCursor(); } be_mouse_x = (int)(cursor.x - bounds.left); be_mouse_y = (int)(cursor.y - bounds.top); if (!be_mouse_warped) { be_mickey_x += (be_mouse_x - old_x); be_mickey_y += (be_mouse_y - old_y); } else { be_mouse_warped = false; be_mickey_x = 0; be_mickey_y = 0; } } else { buttons = 0; _mouse_on = FALSE; if (be_app->IsCursorHidden()) { be_app->ShowCursor(); } } } _be_mouse_window->Unlock(); be_mouse_x = CLAMP(limit_left, be_mouse_x, limit_right); be_mouse_y = CLAMP(limit_up, be_mouse_y, limit_down); be_mouse_b = 0; be_mouse_b |= (buttons & B_PRIMARY_MOUSE_BUTTON) ? 1 : 0; be_mouse_b |= (buttons & B_SECONDARY_MOUSE_BUTTON) ? 2 : 0; be_mouse_b |= (buttons & B_TERTIARY_MOUSE_BUTTON) ? 4 : 0; _mouse_x = be_mouse_x; _mouse_y = be_mouse_y; _mouse_z = _be_mouse_z; _mouse_b = be_mouse_b; _handle_mouse_input(); } release_sem(_be_mouse_view_attached); snooze(MOUSE_THREAD_PERIOD); } } extern "C" int be_mouse_init(void) { sem_id mouse_started; int32 num_buttons; mouse_started = create_sem(0, "starting mouse driver..."); if (mouse_started < 0) { goto cleanup; } mouse_thread_id = spawn_thread(mouse_thread, MOUSE_THREAD_NAME, MOUSE_THREAD_PRIORITY, &mouse_started); if (mouse_thread_id < 0) { goto cleanup; } mouse_thread_running = true; resume_thread(mouse_thread_id); acquire_sem(mouse_started); delete_sem(mouse_started); be_mickey_x = 0; be_mickey_y = 0; be_mouse_x = 0; be_mouse_y = 0; be_mouse_b = 0; limit_up = 0; limit_down = 0; limit_left = 0; limit_right = 0; get_mouse_type(&num_buttons); return num_buttons; cleanup: { if (mouse_started > 0) { delete_sem(mouse_started); } be_mouse_exit(); return 0; } } extern "C" void be_mouse_exit(void) { be_mickey_x = 0; be_mickey_y = 0; be_mouse_x = 0; be_mouse_y = 0; be_mouse_b = 0; limit_up = 0; limit_down = 0; limit_left = 0; limit_right = 0; mouse_thread_running = false; if (mouse_thread_id > 0) { release_sem(_be_mouse_view_attached); wait_for_thread(mouse_thread_id, &ignore_result); acquire_sem(_be_mouse_view_attached); mouse_thread_id = -1; } } extern "C" void be_mouse_position(int x, int y) { acquire_sem(_be_mouse_view_attached); _mouse_x = be_mouse_x = CLAMP(limit_left, x, limit_right); _mouse_y = be_mouse_y = CLAMP(limit_up, y, limit_down); be_mouse_warped = true; if (!_be_mouse_window_mode) set_mouse_position(320, 240); release_sem(_be_mouse_view_attached); } extern "C" void be_mouse_set_range(int x1, int y1, int x2, int y2) { acquire_sem(_be_mouse_view_attached); limit_up = y1; limit_down = y2; limit_left = x1; limit_right = x2; release_sem(_be_mouse_view_attached); } extern "C" void be_mouse_set_speed(int xspeed, int yspeed) { } extern "C" void be_mouse_get_mickeys(int *mickeyx, int *mickeyy) { acquire_sem(_be_mouse_view_attached); if (mickeyx != NULL) { *mickeyx = be_mickey_x; } if (mickeyy != NULL) { *mickeyy = be_mickey_y; } be_mickey_x = 0; be_mickey_y = 0; release_sem(_be_mouse_view_attached); }