From baffb475f3abfed993a86182f199b0d167ea7f6d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 20 Jan 2003 01:08:20 +0000 Subject: [PATCH] From: David Hedbor Subject: Qtopia patches (input grabbing and iconify) Ok, here's a patch that adds support for SDL_WM_GrabInput (default state is "ungrabbed") and SDL_WM_IconifyWindow. Also has some other tweaks such as taking additional steps to clean up when exiting (bypassing certain bugs in some versions of Qtopia and/or OPIE) and it also maps Key_F33 to Key_Return (this is the Zaurus 'ok' key). --- configure.in | 5 + src/main/linux/SDL_Qtopia_main.cc | 26 ++- src/video/SDL_video.c | 6 +- src/video/qtopia/SDL_QWin.cc | 277 ++++++++++++++++++++++-------- src/video/qtopia/SDL_QWin.h | 38 +--- src/video/qtopia/SDL_sysvideo.cc | 49 ++++-- 6 files changed, 282 insertions(+), 119 deletions(-) diff --git a/configure.in b/configure.in index 748414259..64007ac9a 100644 --- a/configure.in +++ b/configure.in @@ -1459,8 +1459,13 @@ CheckQtopia() if test x$video_qtopia = xyes; then CFLAGS="$CFLAGS -DENABLE_QTOPIA -DQT_QWS_EBX -DQT_QWS_CUSTOM -DQWS -I${QPEDIR}/include -I${QTDIR}/include/ -DNO_DEBUG -fno-rtti -fno-exceptions" SDL_LIBS="$SDL_LIBS -L${QPEDIR}/lib -L${QTDIR}/lib/ -lqpe -lqte" + SDL_CFLAGS="$SDL_CFLAGS -DQWS" VIDEO_SUBDIRS="$VIDEO_SUBDIRS qtopia" VIDEO_DRIVERS="$VIDEO_DRIVERS qtopia/libvideo_qtopia.la" + else + AC_MSG_ERROR([ +*** Failed to find Qtopia includes. Make sure that the QTDIR and QPEDIR +*** environment variables are set correctly.]) fi AC_LANG_C fi diff --git a/src/main/linux/SDL_Qtopia_main.cc b/src/main/linux/SDL_Qtopia_main.cc index 9263746f9..baea13b1e 100644 --- a/src/main/linux/SDL_Qtopia_main.cc +++ b/src/main/linux/SDL_Qtopia_main.cc @@ -1,11 +1,32 @@ /* Include the SDL main definition header */ #include "SDL_main.h" +#include +#include #ifdef main #undef main #endif #ifdef QWS #include +#include +#include +#include + +// Workaround for OPIE to remove taskbar icon. Also fixes +// some issues in Qtopia where there are left-over qcop files in /tmp/. +// I'm guessing this will also clean up the taskbar in the Sharp version +// of Qtopia. +static inline void cleanupQCop() { + QString appname(qApp->argv()[0]); + int slash = appname.findRev("/"); + if(slash != -1) { appname = appname.mid(slash+1); } + QString cmd = QPEApplication::qpeDir() + "bin/qcop QPE/System 'closing(QString)' '"+appname+"'"; + system(cmd.latin1()); + cmd = "/tmp/qcop-msg-"+appname; + unlink(cmd.latin1()); +} + +static QPEApplication *app; #endif extern int SDL_main(int argc, char *argv[]); @@ -15,9 +36,10 @@ int main(int argc, char *argv[]) #ifdef QWS // This initializes the Qtopia application. It needs to be done here // because it parses command line options. - QPEApplication app(argc, argv); QWidget dummy; - app.showMainWidget(&dummy); + app = new QPEApplication(argc, argv); + app->showMainWidget(&dummy); + atexit(cleanupQCop); #endif // Exit here because if return is used, the application // doesn't seem to quit correctly. diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index c1fa56e15..c9dbdc3c1 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -54,6 +54,9 @@ static VideoBootStrap *bootstrap[] = { #ifdef ENABLE_NANOX &NX_bootstrap, #endif +#ifdef ENABLE_QTOPIA + &Qtopia_bootstrap, +#endif #ifdef ENABLE_FBCON &FBCON_bootstrap, #endif @@ -111,9 +114,6 @@ static VideoBootStrap *bootstrap[] = { #ifdef ENABLE_GEM &GEM_bootstrap, #endif -#ifdef ENABLE_QTOPIA - &Qtopia_bootstrap, -#endif #ifdef ENABLE_PICOGUI &PG_bootstrap, #endif diff --git a/src/video/qtopia/SDL_QWin.cc b/src/video/qtopia/SDL_QWin.cc index a67fb5eee..ea49c3cbe 100644 --- a/src/video/qtopia/SDL_QWin.cc +++ b/src/video/qtopia/SDL_QWin.cc @@ -129,14 +129,12 @@ void SDL_QWin::mouseReleaseEvent(QMouseEvent *e) { my_mouse_pos = QPoint(-1, -1); } -#define USE_DIRECTPAINTER - - -#ifndef __i386__ -static inline void gs_fastRotateBlit_3 ( unsigned short *fb, - unsigned short *bits, - const QRect& rect ) +static inline void +gs_fastRotateBlit_3 ( unsigned short *fb, + unsigned short *bits, + const QRect& rect ) { + // FIXME: this only works correctly for 240x320 displays int startx, starty; int width, height; @@ -187,87 +185,193 @@ static inline void gs_fastRotateBlit_3 ( unsigned short *fb, dp2 += rowadd; } } -#endif -void SDL_QWin::repaintRect(const QRect& rect) { - if(!my_painter || !rect.width() || !rect.height()) { - return; +static inline void +gs_fastRotateBlit_1 ( unsigned short *fb, + unsigned short *bits, + const QRect& rect ) { + // FIXME: this only works correctly for 240x320 displays + int startx, starty; + int width, height; + + startx = rect.left() >> 1; + starty = rect.top() >> 1; + width = ((rect.right() - rect.left()) >> 1) + 2; + height = ((rect.bottom() - rect.top()) >> 1) + 2; + + if((startx+width) > 120) { + width = 120 - startx; // avoid horizontal overflow } -#ifndef __i386__ - - if(QPixmap::defaultDepth() == 16 && - my_painter->transformOrientation() == 3 && - my_painter->numRects() >= 0) { - if(my_image->width() == width()) { - ushort *fb = (ushort*)my_painter->frameBuffer(); - ushort *buf = (ushort*)my_image->bits(); - gs_fastRotateBlit_3(fb, buf, rect); + if((starty+height) > 160) { + height = 160 - starty; // avoid vertical overflow + } + + ulong *sp1, *sp2, *dp1, *dp2; + ulong stop, sbot, dtop, dbot; + fb += 320*239; // Move "fb" to top left corner + sp1 = (ulong*)bits + startx + starty*240; + sp2 = sp1 + 120; + dp1 = (ulong*)fb - startx * 320 - starty; + dp2 = dp1 - 160; + int rowadd = (320*width) + 1; + int rowadd2 = 240 - width; + // transfer in cells of 2x2 pixels in words + for (int y=0; y>16) + (sbot & 0xffff0000); + // write + *dp1 = dtop; + *dp2 = dbot; + // update source ptrs + sp1++; sp2++; + // update dest ptrs - 2 pix at a time + dp1 -= 320; + dp2 -= 320; + } + // adjust src ptrs - skip a row as we work in pairs + sp1 += rowadd2; + sp2 += rowadd2; + // adjust dest ptrs for rotation + dp1 += rowadd; + dp2 += rowadd; + } +} + +// desktop, SL-A300 etc +bool SDL_QWin::repaintRotation0(const QRect& rect) { + if(my_image->width() == width()) { + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + if(rect == my_image->rect()) { + memcpy(fb, buf, width()*height()*2); } else { - // landscape mode - if (screenRotation == SDL_QT_ROTATION_90) { - uchar *fb = (uchar*)my_painter->frameBuffer(); - uchar *buf = (uchar*)my_image->bits(); - if(rect == my_image->rect()) { - memcpy(fb, buf, width()*height()*2); - } else { - int h = rect.height(); - int wd = rect.width()<<1; - int fblineadd = my_painter->lineStep(); - int buflineadd = my_image->bytesPerLine(); - fb += (rect.left()<<1) + rect.top() * my_painter->lineStep(); - buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine(); - while(h--) { - memcpy(fb, buf, wd); - fb += fblineadd; - buf += buflineadd; - } - } + int h = rect.height(); + int wd = rect.width()<<1; + int fblineadd = my_painter->lineStep(); + int buflineadd = my_image->bytesPerLine(); + fb += (rect.left()<<1) + rect.top() * my_painter->lineStep(); + buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine(); + while(h--) { + memcpy(fb, buf, wd); + fb += fblineadd; + buf += buflineadd; } - else if (screenRotation == SDL_QT_ROTATION_270) { - int h = rect.height(); - int wd = rect.width(); - int fblineadd = my_painter->lineStep() - (rect.width() << 1); - int buflineadd = my_image->bytesPerLine() - (rect.width() << 1); - int w; - - uchar *fb = (uchar*)my_painter->frameBuffer(); - uchar *buf = (uchar*)my_image->bits(); - - fb += ((my_painter->width() - (rect.top() + rect.height())) * - my_painter->lineStep()) + ((my_painter->height() - ((rect.left() + - rect.width()))) << 1); - - buf += my_image->bytesPerLine() * (rect.top() + rect.height()) - - (((my_image->width() - (rect.left() + rect.width())) << 1) + 2); - - while(h--) { - w = wd; - while(w--) *((unsigned short*)fb)++ = *((unsigned short*)buf)--; - fb += fblineadd; - buf -= buflineadd; - } - } } } else { -#endif - QPainter pp(this); - pp.drawImage(rect.topLeft(), *my_image, rect); - pp.end(); -#ifndef __i386__ + return false; // FIXME: Landscape } +#ifdef __i386__ + my_painter->fillRect( rect, QBrush( Qt::NoBrush ) ); #endif + return true; +} + + +// Sharp Zaurus SL-5500 etc +bool SDL_QWin::repaintRotation3(const QRect& rect) { + if(my_image->width() == width()) { + ushort *fb = (ushort*)my_painter->frameBuffer(); + ushort *buf = (ushort*)my_image->bits(); + gs_fastRotateBlit_3(fb, buf, rect); + } else { + // landscape mode + if (screenRotation == SDL_QT_ROTATION_90) { + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + if(rect == my_image->rect()) { + memcpy(fb, buf, width()*height()*2); + } else { + int h = rect.height(); + int wd = rect.width()<<1; + int fblineadd = my_painter->lineStep(); + int buflineadd = my_image->bytesPerLine(); + fb += (rect.left()<<1) + rect.top() * my_painter->lineStep(); + buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine(); + while(h--) { + memcpy(fb, buf, wd); + fb += fblineadd; + buf += buflineadd; + } + } + } else if (screenRotation == SDL_QT_ROTATION_270) { + int h = rect.height(); + int wd = rect.width(); + int fblineadd = my_painter->lineStep() - (rect.width() << 1); + int buflineadd = my_image->bytesPerLine() - (rect.width() << 1); + int w; + + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + + fb += ((my_painter->width() - (rect.top() + rect.height())) * + my_painter->lineStep()) + ((my_painter->height() - ((rect.left() + + rect.width()))) << 1); + + buf += my_image->bytesPerLine() * (rect.top() + rect.height()) - + (((my_image->width() - (rect.left() + rect.width())) << 1) + 2); + + while(h--) { + w = wd; + while(w--) *((unsigned short*)fb)++ = *((unsigned short*)buf)--; + fb += fblineadd; + buf -= buflineadd; + } + } + } + return true; +} + +// ipaq 3800... +bool SDL_QWin::repaintRotation1(const QRect& rect) { + if(my_image->width() == width()) { + ushort *fb = (ushort*)my_painter->frameBuffer(); + ushort *buf = (ushort*)my_image->bits(); + gs_fastRotateBlit_1(fb, buf, rect); + } else { + return false; // FIXME: landscape mode + } + return true; +} + +void SDL_QWin::repaintRect(const QRect& rect) { + if(!my_painter || !rect.width() || !rect.height()) { + return; + } + + if(QPixmap::defaultDepth() == 16) { + switch(my_painter->transformOrientation()) { + case 3: + if(repaintRotation3(rect)) { return; } + break; + case 1: + if(repaintRotation1(rect)) { return; } + break; + case 0: + if(repaintRotation0(rect)) { return; } + break; + } + } + my_painter->drawImage(rect.topLeft(), *my_image, rect); } // This paints the current buffer to the screen, when desired. void SDL_QWin::paintEvent(QPaintEvent *ev) { - if(my_image && isVisible() && isActiveWindow()) { - lockScreen(); + if(my_image) { + lockScreen(true); repaintRect(ev->rect()); unlockScreen(); } } -/* Function to translate a keyboard transition and queue the key event */ +/* Function to translate a keyboard transition and queue the key event + * This should probably be a table although this method isn't exactly + * slow. + */ void SDL_QWin::QueueKey(QKeyEvent *e, int pressed) { SDL_keysym keysym; @@ -340,6 +444,14 @@ void SDL_QWin::QueueKey(QKeyEvent *e, int pressed) case Qt::Key_Super_R: scancode = SDLK_RSUPER; break; case Qt::Key_Menu: scancode = SDLK_MENU; break; case Qt::Key_Help: scancode = SDLK_HELP; break; + + case Qt::Key_F33: + // FIXME: This is a hack to enable the OK key on + // Zaurii devices. SDLK_RETURN is a suitable key to use + // since it often is used as such. + // david@hedbor.org + scancode = SDLK_RETURN; + break; default: scancode = SDLK_UNKNOWN; break; @@ -394,3 +506,26 @@ void SDL_QWin::enableFullscreen() { my_has_fullscreen = true; } } + +bool SDL_QWin::lockScreen(bool force) { + if(!my_painter) { + if(force || (isVisible() && isActiveWindow())) { + my_painter = new QDirectPainter(this); + } else { + return false; + } + } + my_locked++; // Increate lock refcount + return true; +} + +void SDL_QWin::unlockScreen() { + if(my_locked > 0) { + my_locked--; // decrease lock refcount; + } + if(!my_locked && my_painter) { + my_painter->end(); + delete my_painter; + my_painter = 0; + } +} diff --git a/src/video/qtopia/SDL_QWin.h b/src/video/qtopia/SDL_QWin.h index d5f3f8ddb..f1177f68d 100644 --- a/src/video/qtopia/SDL_QWin.h +++ b/src/video/qtopia/SDL_QWin.h @@ -70,14 +70,7 @@ class SDL_QWin : public QWidget x = my_offset.x(); y = my_offset.y(); } - bool beginDraw(void) { - return true; - } - void endDraw(void) { - } - QImage *image(void) { - return my_image; - } + QImage *image(void) { return my_image; } void setWFlags(WFlags flags) { QWidget::setWFlags(flags); @@ -87,22 +80,8 @@ class SDL_QWin : public QWidget void setMousePos(const QPoint& newpos); void setFullscreen(bool); - void lockScreen() { - if(!my_painter) { - my_painter = new QDirectPainter(this); - } - my_locked++; // Increate lock refcount - } - void unlockScreen() { - if(my_locked > 0) { - my_locked--; // decrease lock refcount; - } - if(!my_locked && my_painter) { - my_painter->end(); - delete my_painter; - my_painter = 0; - } - } + bool lockScreen(bool force=false); + void unlockScreen(); void repaintRect(const QRect& rect); protected: /* Handle resizing of the window */ @@ -114,13 +93,12 @@ class SDL_QWin : public QWidget void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); void paintEvent(QPaintEvent *ev); - void keyPressEvent(QKeyEvent *e) { - QueueKey(e, 1); - } - void keyReleaseEvent(QKeyEvent *e) { - QueueKey(e, 0); - } + void keyPressEvent(QKeyEvent *e) { QueueKey(e, 1); } + void keyReleaseEvent(QKeyEvent *e) { QueueKey(e, 0); } private: + bool repaintRotation0(const QRect& rect); + bool repaintRotation1(const QRect& rect); + bool repaintRotation3(const QRect& rect); void enableFullscreen(); QDirectPainter *my_painter; QImage *my_image; diff --git a/src/video/qtopia/SDL_sysvideo.cc b/src/video/qtopia/SDL_sysvideo.cc index 85274320a..66f516333 100644 --- a/src/video/qtopia/SDL_sysvideo.cc +++ b/src/video/qtopia/SDL_sysvideo.cc @@ -53,12 +53,12 @@ extern "C" { //#define QTOPIA_DEBUG #define QT_HIDDEN_SIZE 32 /* starting hidden window size */ -/* Name of the environment variable used to invert the screen rotation or not: - Possible values: - !=0 : Screen is 270° rotated - 0: Screen is 90° rotated*/ + /* Name of the environment variable used to invert the screen rotation or not: + Possible values: + !=0 : Screen is 270° rotated + 0: Screen is 90° rotated*/ #define SDL_QT_ROTATION_ENV_NAME "SDL_QT_INVERT_ROTATION" - + /* Initialization/Query functions */ static int QT_VideoInit(_THIS, SDL_PixelFormat *vformat); static SDL_Rect **QT_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); @@ -75,6 +75,8 @@ extern "C" { static int QT_ToggleFullScreen(_THIS, int fullscreen); + static int QT_IconifyWindow(_THIS); + static SDL_GrabMode QT_GrabInput(_THIS, SDL_GrabMode mode); /* FB driver bootstrap functions */ @@ -128,6 +130,8 @@ extern "C" { device->FreeHWSurface = QT_FreeHWSurface; device->SetIcon = NULL; device->SetCaption = QT_SetWMCaption; + device->IconifyWindow = QT_IconifyWindow; + device->GrabInput = QT_GrabInput; device->GetWMInfo = NULL; device->FreeWMCursor = QT_FreeWMCursor; device->CreateWMCursor = QT_CreateWMCursor; @@ -281,7 +285,7 @@ extern "C" { QSize desktop_size = qApp->desktop()->size(); - current->flags = SDL_FULLSCREEN; // We always run fullscreen. + current->flags = 0; //SDL_FULLSCREEN; // We always run fullscreen. if(width <= desktop_size.width() && height <= desktop_size.height()) { @@ -355,14 +359,14 @@ extern "C" { static void QT_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) { - int i; - SDL_Win->lockScreen(); - for ( i=0; irepaintRect(rect); + if(SDL_Win->lockScreen()) { + for(int i=0; irepaintRect(rect); + } + SDL_Win->unlockScreen(); } - SDL_Win->unlockScreen(); } /* Is the system palette settable? */ int QT_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) @@ -380,6 +384,25 @@ extern "C" { // delete SDL_Win; // SDL_Win = 0; _this->screen->pixels = NULL; + QT_GrabInput(_this, SDL_GRAB_OFF); } + static int QT_IconifyWindow(_THIS) { + SDL_Win->hide(); + + return true; + } + + static SDL_GrabMode QT_GrabInput(_THIS, SDL_GrabMode mode) { + if(mode == SDL_GRAB_OFF) { + QPEApplication::grabKeyboard(); + qApp->processEvents(); + QPEApplication::ungrabKeyboard(); + } else { + QPEApplication::grabKeyboard(); + } + qApp->processEvents(); + return mode; + } + }; /* Extern C */