Commit 29285b10 authored by Sam Lantinga's avatar Sam Lantinga

Fixed bug #286

Date: Thu, 9 Feb 2006 17:06:51 +0300
From: "Oleg K  [BeSman]"
Subject: BeOS SDL patches

Hello all. My name is Oleg K. [BeSman], Im a BeOS user from Russia.This mail
contain a BeOs-specific patches to SDL (implementation of InputGrabbing and
mouse_relative mode). See the source in attached file for details.

--HG--
branch : SDL-1.2
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/branches/SDL-1.2%402116
parent fd8b91f9
......@@ -37,22 +37,12 @@ public:
BView(frame, "SDL View", B_FOLLOW_ALL_SIDES,
(B_WILL_DRAW|B_FRAME_EVENTS)) {
image = NULL;
xoff = yoff = 0;
SetViewColor(0,0,0,0);
SetHighColor(0,0,0,0);
}
virtual ~SDL_BView() {
SetBitmap(NULL);
}
/* Set drawing offsets for fullscreen mode */
virtual void SetXYOffset(int x, int y) {
xoff = x;
yoff = y;
}
virtual void GetXYOffset(int &x, int &y) {
x = xoff;
y = yoff;
}
/* The view changed size. If it means we're in fullscreen, we
* draw a nice black box in the entire view to get black borders.
*/
......@@ -62,14 +52,14 @@ public:
bounds.right = width;
bounds.bottom = height;
/* Fill the entire view with black */
FillRect(bounds, B_SOLID_HIGH);
// FillRect(bounds, B_SOLID_HIGH);
/* And if there's an image, redraw it. */
if( image ) {
bounds = image->Bounds();
Draw(bounds);
}
}
/* Drawing portion of this complete breakfast. :) */
virtual void SetBitmap(BBitmap *bitmap) {
if ( image ) {
......@@ -79,34 +69,17 @@ public:
}
virtual void Draw(BRect updateRect) {
if ( image ) {
if(xoff || yoff) {
BRect dest;
dest.top = updateRect.top + yoff;
dest.left = updateRect.left + xoff;
dest.bottom = updateRect.bottom + yoff;
dest.right = updateRect.right + xoff;
DrawBitmap(image, updateRect, dest);
} else {
DrawBitmap(image, updateRect, updateRect);
}
DrawBitmap(image, updateRect, updateRect);
}
}
virtual void DrawAsync(BRect updateRect) {
if(xoff || yoff) {
BRect dest;
dest.top = updateRect.top + yoff;
dest.left = updateRect.left + xoff;
dest.bottom = updateRect.bottom + yoff;
dest.right = updateRect.right + xoff;;
DrawBitmapAsync(image, updateRect, dest);
} else {
if ( image ) {
DrawBitmapAsync(image, updateRect, updateRect);
}
}
private:
BBitmap *image;
int xoff, yoff;
};
#endif /* _SDL_BView_h */
This diff is collapsed.
......@@ -29,6 +29,8 @@
#include "SDL_BWin.h"
#include "SDL_lowvideo.h"
static SDLKey keymap[128];
int mouse_relative = 0;
extern "C" {
#include "../../events/SDL_sysevents.h"
......@@ -41,6 +43,340 @@ void BE_PumpEvents(_THIS)
void BE_InitOSKeymap(_THIS)
{
for ( uint i=0; i<SDL_TABLESIZE(keymap); ++i )
keymap[i] = SDLK_UNKNOWN;
keymap[0x01] = SDLK_ESCAPE;
keymap[B_F1_KEY] = SDLK_F1;
keymap[B_F2_KEY] = SDLK_F2;
keymap[B_F3_KEY] = SDLK_F3;
keymap[B_F4_KEY] = SDLK_F4;
keymap[B_F5_KEY] = SDLK_F5;
keymap[B_F6_KEY] = SDLK_F6;
keymap[B_F7_KEY] = SDLK_F7;
keymap[B_F8_KEY] = SDLK_F8;
keymap[B_F9_KEY] = SDLK_F9;
keymap[B_F10_KEY] = SDLK_F10;
keymap[B_F11_KEY] = SDLK_F11;
keymap[B_F12_KEY] = SDLK_F12;
keymap[B_PRINT_KEY] = SDLK_PRINT;
keymap[B_SCROLL_KEY] = SDLK_SCROLLOCK;
keymap[B_PAUSE_KEY] = SDLK_PAUSE;
keymap[0x11] = SDLK_BACKQUOTE;
keymap[0x12] = SDLK_1;
keymap[0x13] = SDLK_2;
keymap[0x14] = SDLK_3;
keymap[0x15] = SDLK_4;
keymap[0x16] = SDLK_5;
keymap[0x17] = SDLK_6;
keymap[0x18] = SDLK_7;
keymap[0x19] = SDLK_8;
keymap[0x1a] = SDLK_9;
keymap[0x1b] = SDLK_0;
keymap[0x1c] = SDLK_MINUS;
keymap[0x1d] = SDLK_EQUALS;
keymap[0x1e] = SDLK_BACKSPACE;
keymap[0x1f] = SDLK_INSERT;
keymap[0x20] = SDLK_HOME;
keymap[0x21] = SDLK_PAGEUP;
keymap[0x22] = SDLK_NUMLOCK;
keymap[0x23] = SDLK_KP_DIVIDE;
keymap[0x24] = SDLK_KP_MULTIPLY;
keymap[0x25] = SDLK_KP_MINUS;
keymap[0x26] = SDLK_TAB;
keymap[0x27] = SDLK_q;
keymap[0x28] = SDLK_w;
keymap[0x29] = SDLK_e;
keymap[0x2a] = SDLK_r;
keymap[0x2b] = SDLK_t;
keymap[0x2c] = SDLK_y;
keymap[0x2d] = SDLK_u;
keymap[0x2e] = SDLK_i;
keymap[0x2f] = SDLK_o;
keymap[0x30] = SDLK_p;
keymap[0x31] = SDLK_LEFTBRACKET;
keymap[0x32] = SDLK_RIGHTBRACKET;
keymap[0x33] = SDLK_BACKSLASH;
keymap[0x34] = SDLK_DELETE;
keymap[0x35] = SDLK_END;
keymap[0x36] = SDLK_PAGEDOWN;
keymap[0x37] = SDLK_KP7;
keymap[0x38] = SDLK_KP8;
keymap[0x39] = SDLK_KP9;
keymap[0x3a] = SDLK_KP_PLUS;
keymap[0x3b] = SDLK_CAPSLOCK;
keymap[0x3c] = SDLK_a;
keymap[0x3d] = SDLK_s;
keymap[0x3e] = SDLK_d;
keymap[0x3f] = SDLK_f;
keymap[0x40] = SDLK_g;
keymap[0x41] = SDLK_h;
keymap[0x42] = SDLK_j;
keymap[0x43] = SDLK_k;
keymap[0x44] = SDLK_l;
keymap[0x45] = SDLK_SEMICOLON;
keymap[0x46] = SDLK_QUOTE;
keymap[0x47] = SDLK_RETURN;
keymap[0x48] = SDLK_KP4;
keymap[0x49] = SDLK_KP5;
keymap[0x4a] = SDLK_KP6;
keymap[0x4b] = SDLK_LSHIFT;
keymap[0x4c] = SDLK_z;
keymap[0x4d] = SDLK_x;
keymap[0x4e] = SDLK_c;
keymap[0x4f] = SDLK_v;
keymap[0x50] = SDLK_b;
keymap[0x51] = SDLK_n;
keymap[0x52] = SDLK_m;
keymap[0x53] = SDLK_COMMA;
keymap[0x54] = SDLK_PERIOD;
keymap[0x55] = SDLK_SLASH;
keymap[0x56] = SDLK_RSHIFT;
keymap[0x57] = SDLK_UP;
keymap[0x58] = SDLK_KP1;
keymap[0x59] = SDLK_KP2;
keymap[0x5a] = SDLK_KP3;
keymap[0x5b] = SDLK_KP_ENTER;
keymap[0x5c] = SDLK_LCTRL;
keymap[0x5d] = SDLK_LALT;
keymap[0x5e] = SDLK_SPACE;
keymap[0x5f] = SDLK_RALT;
keymap[0x60] = SDLK_RCTRL;
keymap[0x61] = SDLK_LEFT;
keymap[0x62] = SDLK_DOWN;
keymap[0x63] = SDLK_RIGHT;
keymap[0x64] = SDLK_KP0;
keymap[0x65] = SDLK_KP_PERIOD;
keymap[0x66] = SDLK_LMETA;
keymap[0x67] = SDLK_RMETA;
keymap[0x68] = SDLK_MENU;
keymap[0x69] = SDLK_EURO;
keymap[0x6a] = SDLK_KP_EQUALS;
keymap[0x6b] = SDLK_POWER;
}
}; /* Extern C */
void SDL_BWin::DispatchMessage(BMessage *msg, BHandler *target)
{
switch (msg->what) {
case B_MOUSE_MOVED:
{
SDL_VideoDevice *view = current_video;
BPoint where;
int32 transit;
if (msg->FindPoint("where", &where) == B_OK && msg->FindInt32("be:transit", &transit) == B_OK) {
//BeSman: I need another method for cursor catching !!!
if(view->input_grab != SDL_GRAB_OFF)
{
BPoint center;
center.x = (SDL_VideoSurface->w/2);
center.y = (SDL_VideoSurface->h/2);
BPoint delta = where - center;
if(delta.x > center.x)
SDL_WarpMouse((int)center.x*2,(int)where.y);
if(delta.x < -center.x)
SDL_WarpMouse(0,(int)where.y);
if(delta.y > center.y)
SDL_WarpMouse((int)where.x,(int)center.y*2);
if(delta.y < -center.y)
SDL_WarpMouse((int)where.x,0);
if((delta.x-1 < -center.x)&&(delta.y-1 < -center.y))
SDL_WarpMouse(1,1);
if((delta.x-1 < -center.x)&&(delta.y+1 > center.y))
SDL_WarpMouse(1,(int)center.y*2-1);
if((delta.x+1 > center.x)&&(delta.y-1 < -center.y))
SDL_WarpMouse((int)center.x*2-1,1);
if((delta.x+1 > center.x)&&(delta.y+1 > center.y))
SDL_WarpMouse((int)center.x*2-1,(int)center.y*2-1);
}
if (transit == B_EXITED_VIEW) {
if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) {
SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
// be_app->SetCursor(B_HAND_CURSOR);
}
} else {
int x, y;
if ( ! (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
SDL_SetCursor(NULL);
}
x = (int)where.x;
y = (int)where.y;
if ( mouse_relative ) {
BPoint center;
center.x = (SDL_VideoSurface->w/2);
center.y = (SDL_VideoSurface->h/2);
x -= (int)center.x;
y -= (int)center.y;
if ( x || y ) {
ConvertToScreen(&center);
set_mouse_position((int)center.x, (int)center.y);
SDL_PrivateMouseMotion(0, 1, x, y);
}
} else {
SDL_PrivateMouseMotion(0, 0, x, y);
}
}
}
break;
}
case B_MOUSE_DOWN:
{
/* it looks like mouse down is send only for first clicked
button, each next is not send while last one is holded */
int32 buttons;
int sdl_buttons = 0;
if (msg->FindInt32("buttons", &buttons) == B_OK) {
/* Add any mouse button events */
if (buttons & B_PRIMARY_MOUSE_BUTTON) {
sdl_buttons |= SDL_BUTTON_LEFT;
}
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
sdl_buttons |= SDL_BUTTON_RIGHT;
}
if (buttons & B_TERTIARY_MOUSE_BUTTON) {
sdl_buttons |= SDL_BUTTON_MIDDLE;
}
SDL_PrivateMouseButton(SDL_PRESSED, sdl_buttons, 0, 0);
last_buttons = buttons;
}
break;
}
case B_MOUSE_UP:
{
/* mouse up doesn't give which button was released,
only state of buttons (after release, so it's always = 0),
which is not what we need ;]
So we need to store button in mouse down, and restore
in mouse up :(
mouse up is (similarly to mouse down) send only for
first button down (ie. it's no send if we click another button
without releasing previous one first) - but that's probably
because of how drivers are written?, not BeOS itself. */
int32 buttons;
int sdl_buttons = 0;
if (msg->FindInt32("buttons", &buttons) == B_OK) {
/* Add any mouse button events */
if ((buttons ^ B_PRIMARY_MOUSE_BUTTON) & last_buttons) {
sdl_buttons |= SDL_BUTTON_LEFT;
}
if ((buttons ^ B_SECONDARY_MOUSE_BUTTON) & last_buttons) {
sdl_buttons |= SDL_BUTTON_RIGHT;
}
if ((buttons ^ B_TERTIARY_MOUSE_BUTTON) & last_buttons) {
sdl_buttons |= SDL_BUTTON_MIDDLE;
}
SDL_PrivateMouseButton(SDL_RELEASED, sdl_buttons, 0, 0);
last_buttons = buttons;
}
break;
}
case B_MOUSE_WHEEL_CHANGED:
{
float x, y;
x = y = 0;
if (msg->FindFloat("be:wheel_delta_x", &x) == B_OK && msg->FindFloat("be:wheel_delta_y", &y) == B_OK) {
if (x < 0 || y < 0) {
SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0);
SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0);
} else if (x > 0 || y > 0) {
SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0);
SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0);
}
}
break;
}
case B_KEY_DOWN:
case B_UNMAPPED_KEY_DOWN: /* modifier keys are unmapped */
{
int32 key;
int32 modifiers;
int32 key_repeat;
/* Workaround for SDL message queue being filled too fast because of BeOS own key-repeat mechanism */
if (msg->FindInt32("be:key_repeat", &key_repeat) == B_OK && key_repeat > 0)
break;
if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) {
SDL_keysym keysym;
keysym.scancode = key;
if (key < 128) {
keysym.sym = keymap[key];
} else {
keysym.sym = SDLK_UNKNOWN;
}
/* FIX THIS?
it seems SDL_PrivateKeyboard() changes mod value
anyway, and doesn't care about what we setup here */
keysym.mod = KMOD_NONE;
keysym.unicode = 0;
if (SDL_TranslateUNICODE) {
const char *bytes;
if (msg->FindString("bytes", &bytes) == B_OK) {
/* FIX THIS?
this cares only about first "letter",
so if someone maps some key to print
"BeOS rulez!" only "B" will be used. */
keysym.unicode = Translate2Unicode(bytes);
}
}
SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
}
break;
}
case B_KEY_UP:
case B_UNMAPPED_KEY_UP: /* modifier keys are unmapped */
{
int32 key;
int32 modifiers;
if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) {
SDL_keysym keysym;
keysym.scancode = key;
if (key < 128) {
keysym.sym = keymap[key];
} else {
keysym.sym = SDLK_UNKNOWN;
}
keysym.mod = KMOD_NONE; /* FIX THIS? */
keysym.unicode = 0;
if (SDL_TranslateUNICODE) {
const char *bytes;
if (msg->FindString("bytes", &bytes) == B_OK) {
keysym.unicode = Translate2Unicode(bytes);
}
}
SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
}
break;
}
default:
/* move it after switch{} so it's always handled
that way we keep BeOS feautures like:
- CTRL+Q to close window (and other shortcuts)
- PrintScreen to make screenshot into /boot/home
- etc.. */
//BDirectWindow::DispatchMessage(msg, target);
break;
}
BDirectWindow::DispatchMessage(msg, target);
}
......@@ -27,7 +27,7 @@
#include "SDL_BWin.h"
extern "C" {
#include "SDL_cursor_c.h"
#include "SDL_sysmouse_c.h"
/* Convert bits to padded bytes */
......@@ -128,11 +128,26 @@ void BE_FreeWMCursor(_THIS, WMcursor *cursor)
/* Implementation by Christian Bauer <cbauer@student.physik.uni-mainz.de> */
void BE_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
{
if (_this->screen && (_this->screen->flags & SDL_FULLSCREEN) ) {
SDL_PrivateMouseMotion(0, 0, x, y);
} else {
BPoint pt(x, y);
SDL_Win->Lock();
SDL_Win->ConvertToScreen(&pt);
SDL_Win->Unlock();
set_mouse_position((int32)pt.x, (int32)pt.y);
}
}
/* Check to see if we need to enter or leave mouse relative mode */
void BE_CheckMouseMode(_THIS)
{
/* If the mouse is hidden and input is grabbed, we use relative mode */
if ( !(SDL_cursorstate & CURSOR_VISIBLE) &&
(_this->input_grab != SDL_GRAB_OFF) ) {
mouse_relative = 1;
} else {
mouse_relative = 0;
}
}
}; /* Extern C */
......@@ -29,4 +29,5 @@ extern WMcursor *BE_CreateWMCursor(_THIS,
Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);
extern int BE_ShowWMCursor(_THIS, WMcursor *cursor);
extern void BE_WarpWMCursor(_THIS, Uint16 x, Uint16 y);
extern void BE_CheckMouseMode(_THIS);
......@@ -135,7 +135,7 @@ static SDL_VideoDevice *BE_CreateDevice(int devindex)
device->SetCaption = BE_SetWMCaption;
device->SetIcon = NULL;
device->IconifyWindow = BE_IconifyWindow;
device->GrabInput = NULL;
device->GrabInput = BE_GrabInput;
device->GetWMInfo = BE_GetWMInfo;
/* Cursor manager functions */
device->FreeWMCursor = BE_FreeWMCursor;
......@@ -143,7 +143,7 @@ static SDL_VideoDevice *BE_CreateDevice(int devindex)
device->ShowWMCursor = BE_ShowWMCursor;
device->WarpWMCursor = BE_WarpWMCursor;
device->MoveWMCursor = NULL;
device->CheckMouseMode = NULL;
device->CheckMouseMode = BE_CheckMouseMode;
/* Event manager functions */
device->InitOSKeymap = BE_InitOSKeymap;
device->PumpEvents = BE_PumpEvents;
......@@ -365,8 +365,11 @@ static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp,
if ( ! modes[i] || (modes[i]->w < width) || (modes[i]->h < width) ) {
--i; /* We went too far */
}
width = modes[i]->w;
height = modes[i]->h;
/* BeSman::We dont want to use a Desktop resolution */
// width = modes[i]->w;
// height = modes[i]->h;
bscreen.GetModeList(&dmodes, &nmodes);
for ( i = 0; i < nmodes; ++i ) {
if ( (bpp == ColorSpaceToBitsPerPixel(dmodes[i].space)) &&
......@@ -433,7 +436,7 @@ static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen)
}
if ( SDL_Win->Lock() ) {
int xoff, yoff;
int cx, cy;
if ( SDL_Win->Shown() ) {
needs_unlock = 1;
SDL_Win->Hide();
......@@ -449,19 +452,12 @@ static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen)
/* Calculate offsets - used either to center window
* (windowed mode) or to set drawing offsets (fullscreen mode)
*/
xoff = (bounds.IntegerWidth() - width)/2;
yoff = (bounds.IntegerHeight() - height)/2;
if ( fullscreen ) {
/* Set offset for drawing */
SDL_Win->SetXYOffset(xoff, yoff);
} else {
/* Center window and reset the drawing offset */
SDL_Win->SetXYOffset(0, 0);
}
cx = (bounds.IntegerWidth() - width)/2;
cy = (bounds.IntegerHeight() - height)/2;
if ( ! needs_unlock || was_fullscreen ) {
/* Center the window the first time */
SDL_Win->MoveTo(xoff > 0 ? (float)xoff : 0.0f,
yoff > 0 ? (float)yoff : 0.0f);
SDL_Win->MoveTo(cx, cy);
}
SDL_Win->Show();
......
......@@ -24,9 +24,9 @@
#include "SDL_BWin.h"
extern "C" {
#include "SDL_syswm_c.h"
#include "SDL_error.h"
#include "../SDL_cursor_c.h"
void BE_SetWMCaption(_THIS, const char *title, const char *icon)
{
......@@ -38,6 +38,42 @@ int BE_IconifyWindow(_THIS)
SDL_Win->Minimize(true);
}
SDL_GrabMode BE_GrabInput(_THIS, SDL_GrabMode mode)
{
if ( mode == SDL_GRAB_OFF ) {
// be_app->ShowCursor();
if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
/* BeSman: Jan 2, 2006
must be leaving relative mode, move mouse from
center of window to where it belongs ... */
BPoint pt;
int x, y;
SDL_GetMouseState(&x,&y);
pt.x = x;
pt.y = y;
SDL_Win->Lock();
SDL_Win->ConvertToScreen(&pt);
SDL_Win->Unlock();
set_mouse_position((int)pt.x, (int)pt.y);
}
} else {
// be_app->HideCursor();
if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
/* BeSman: Jan 2, 2006
must be entering relative mode, get ready by
moving mouse to center of window ... */
BPoint pt;
pt.x = (SDL_VideoSurface->w/2);
pt.y = (SDL_VideoSurface->h/2);
SDL_Win->Lock();
SDL_Win->ConvertToScreen(&pt);
SDL_Win->Unlock();
set_mouse_position((int)pt.x, (int)pt.y);
}
}
return(mode);
}
int BE_GetWMInfo(_THIS, SDL_SysWMinfo *info)
{
if (info->version.major <= SDL_MAJOR_VERSION)
......
......@@ -29,3 +29,4 @@
extern void BE_SetWMCaption(_THIS, const char *title, const char *icon);
extern int BE_IconifyWindow(_THIS);
extern int BE_GetWMInfo(_THIS, SDL_SysWMinfo *info);
extern SDL_GrabMode BE_GrabInput(_THIS, SDL_GrabMode mode);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment