From 64ad54a0df5e43cf22d2bc002100bbfcc1d8dd2f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 7 Jul 2007 19:20:28 +0000 Subject: [PATCH] Fixed bug #360 Fixed fullscreen video modes and improved the mouse grab code. --- src/video/bwindow/SDL_BView.h | 39 +++++++++++-- src/video/bwindow/SDL_BWin.h | 28 ++++++++++ src/video/bwindow/SDL_sysevents.cc | 89 +++++++++++++++--------------- src/video/bwindow/SDL_sysmouse.cc | 17 +++--- src/video/bwindow/SDL_sysvideo.cc | 11 +++- src/video/bwindow/SDL_sysyuv.cc | 8 ++- 6 files changed, 130 insertions(+), 62 deletions(-) diff --git a/src/video/bwindow/SDL_BView.h b/src/video/bwindow/SDL_BView.h index f78d17216..564d064ff 100644 --- a/src/video/bwindow/SDL_BView.h +++ b/src/video/bwindow/SDL_BView.h @@ -37,12 +37,26 @@ class SDL_BView : public BView 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; + } + virtual void GetXYOffset(float &x, float &y) { + x = (float)xoff; + y = (float)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. */ @@ -52,14 +66,14 @@ class SDL_BView : public BView 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 ) { @@ -69,17 +83,34 @@ class SDL_BView : public BView } virtual void Draw(BRect updateRect) { if ( image ) { - DrawBitmap(image, updateRect, 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; + DrawBitmap(image, updateRect, dest); + } else { + DrawBitmap(image, updateRect, updateRect); + } } } virtual void DrawAsync(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;; + DrawBitmapAsync(image, updateRect, dest); + } else { DrawBitmapAsync(image, updateRect, updateRect); } } private: BBitmap *image; + int xoff, yoff; }; #endif /* _SDL_BView_h */ diff --git a/src/video/bwindow/SDL_BWin.h b/src/video/bwindow/SDL_BWin.h index ea1783690..9bfa9d4df 100644 --- a/src/video/bwindow/SDL_BWin.h +++ b/src/video/bwindow/SDL_BWin.h @@ -149,6 +149,34 @@ class SDL_BWin : public BDirectWindow virtual void SetBitmap(BBitmap *bitmap) { SDL_View->SetBitmap(bitmap); } + virtual void SetXYOffset(int x, int y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + return; + } +#endif + SDL_View->SetXYOffset(x, y); + } + virtual void GetXYOffset(int &x, int &y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + x = 0; + y = 0; + return; + } +#endif + SDL_View->GetXYOffset(x, y); + } + virtual void GetXYOffset(float &x, float &y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + x = 0.0f; + y = 0.0f; + return; + } +#endif + SDL_View->GetXYOffset(x, y); + } virtual bool BeginDraw(void) { return(Lock()); } diff --git a/src/video/bwindow/SDL_sysevents.cc b/src/video/bwindow/SDL_sysevents.cc index 2a084682b..f011c57b2 100644 --- a/src/video/bwindow/SDL_sysevents.cc +++ b/src/video/bwindow/SDL_sysevents.cc @@ -166,62 +166,61 @@ void SDL_BWin::DispatchMessage(BMessage *msg, BHandler *target) 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); - -} + int x, y; + + GetXYOffset(x, y); + x = (int)where.x - x; + y = (int)where.y - y; + + //BeSman: I need another method for cursor catching !!! + if (view->input_grab != SDL_GRAB_OFF) + { + bool clipped = false; + if ( x < 0 ) { + x = 0; + clipped = true; + } else if ( x >= SDL_VideoSurface->w ) { + x = (SDL_VideoSurface->w-1); + clipped = true; + } + if ( y < 0 ) { + y = 0; + clipped = true; + } else if ( y >= SDL_VideoSurface->h ) { + y = (SDL_VideoSurface->h-1); + clipped = true; + } + if ( clipped ) { + BPoint edge; + GetXYOffset(edge.x, edge.y); + edge.x += x; + edge.y += y; + ConvertToScreen(&edge); + set_mouse_position((int)edge.x, (int)edge.y); + } + transit = B_INSIDE_VIEW; + } if (transit == B_EXITED_VIEW) { if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); - // be_app->SetCursor(B_HAND_CURSOR); + be_app->SetCursor(B_HAND_CURSOR); } } else { - - int x, y; - if ( ! (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + 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; + int half_w = (SDL_VideoSurface->w/2); + int half_h = (SDL_VideoSurface->h/2); + x -= half_w; + y -= half_h; if ( x || y ) { + BPoint center; + GetXYOffset(center.x, center.y); + center.x += half_w; + center.y += half_h; ConvertToScreen(¢er); set_mouse_position((int)center.x, (int)center.y); SDL_PrivateMouseMotion(0, 1, x, y); diff --git a/src/video/bwindow/SDL_sysmouse.cc b/src/video/bwindow/SDL_sysmouse.cc index 093814f03..232186d52 100644 --- a/src/video/bwindow/SDL_sysmouse.cc +++ b/src/video/bwindow/SDL_sysmouse.cc @@ -128,15 +128,14 @@ void BE_FreeWMCursor(_THIS, WMcursor *cursor) /* Implementation by Christian Bauer */ 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); - } + BPoint pt; + SDL_Win->GetXYOffset(pt.x, pt.y); + pt.x += x; + pt.y += 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 */ diff --git a/src/video/bwindow/SDL_sysvideo.cc b/src/video/bwindow/SDL_sysvideo.cc index 7ee02c3e0..59edec638 100644 --- a/src/video/bwindow/SDL_sysvideo.cc +++ b/src/video/bwindow/SDL_sysvideo.cc @@ -366,9 +366,8 @@ static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp, --i; /* We went too far */ } -/* BeSman::We dont want to use a Desktop resolution */ -// width = modes[i]->w; -// height = modes[i]->h; + width = modes[i]->w; + height = modes[i]->h; bscreen.GetModeList(&dmodes, &nmodes); for ( i = 0; i < nmodes; ++i ) { @@ -455,6 +454,12 @@ static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) cx = (bounds.IntegerWidth() - width)/2; cy = (bounds.IntegerHeight() - height)/2; + if ( fullscreen ) { + /* Set offset for drawing */ + SDL_Win->SetXYOffset(cx, cy); + } else { + SDL_Win->SetXYOffset(0, 0); + } if ( ! needs_unlock || was_fullscreen ) { /* Center the window the first time */ SDL_Win->MoveTo(cx, cy); diff --git a/src/video/bwindow/SDL_sysyuv.cc b/src/video/bwindow/SDL_sysyuv.cc index 64213af70..557a120ed 100644 --- a/src/video/bwindow/SDL_sysyuv.cc +++ b/src/video/bwindow/SDL_sysyuv.cc @@ -274,7 +274,13 @@ int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect *d return 0; } BView * bview = overlay->hwdata->bview; - bview->MoveTo(dst->x,dst->y); + if (SDL_Win->IsFullScreen()) { + int left,top; + SDL_Win->GetXYOffset(left,top); + bview->MoveTo(left+dst->x,top+dst->y); + } else { + bview->MoveTo(dst->x,dst->y); + } bview->ResizeTo(dst->w,dst->h); bview->Flush(); if (overlay->hwdata->first_display) {