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).
--- a/configure.in Mon Jan 20 00:25:28 2003 +0000
+++ b/configure.in Mon Jan 20 01:08:20 2003 +0000
@@ -1459,8 +1459,13 @@
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
--- a/src/main/linux/SDL_Qtopia_main.cc Mon Jan 20 00:25:28 2003 +0000
+++ b/src/main/linux/SDL_Qtopia_main.cc Mon Jan 20 01:08:20 2003 +0000
@@ -1,11 +1,32 @@
/* Include the SDL main definition header */
#include "SDL_main.h"
+#include <stdlib.h>
+#include <unistd.h>
#ifdef main
#undef main
#endif
#ifdef QWS
#include <qpe/qpeapplication.h>
+#include <qapplication.h>
+#include <qpe/qpeapplication.h>
+#include <stdlib.h>
+
+// 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 @@
#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.
--- a/src/video/SDL_video.c Mon Jan 20 00:25:28 2003 +0000
+++ b/src/video/SDL_video.c Mon Jan 20 01:08:20 2003 +0000
@@ -54,6 +54,9 @@
#ifdef ENABLE_NANOX
&NX_bootstrap,
#endif
+#ifdef ENABLE_QTOPIA
+ &Qtopia_bootstrap,
+#endif
#ifdef ENABLE_FBCON
&FBCON_bootstrap,
#endif
@@ -111,9 +114,6 @@
#ifdef ENABLE_GEM
&GEM_bootstrap,
#endif
-#ifdef ENABLE_QTOPIA
- &Qtopia_bootstrap,
-#endif
#ifdef ENABLE_PICOGUI
&PG_bootstrap,
#endif
--- a/src/video/qtopia/SDL_QWin.cc Mon Jan 20 00:25:28 2003 +0000
+++ b/src/video/qtopia/SDL_QWin.cc Mon Jan 20 01:08:20 2003 +0000
@@ -129,14 +129,12 @@
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 @@
dp2 += rowadd;
}
}
+
+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
+ }
+ 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<height; y++) {
+ for (int x=0; x<width; x++) {
+ // read
+ stop = *sp1;
+ sbot = *sp2;
+ // rotate
+ dtop = (stop & 0xffff) + ((sbot & 0xffff)<<16);
+ dbot = ((stop & 0xffff0000)>>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 {
+ 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 {
+ 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;
}
-#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);
- } 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;
- }
- }
+
+ 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;
}
- } else {
-#endif
- QPainter pp(this);
- pp.drawImage(rect.topLeft(), *my_image, rect);
- pp.end();
-#ifndef __i386__
- }
-#endif
+ }
+ 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 @@
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 @@
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;
+ }
+}
--- a/src/video/qtopia/SDL_QWin.h Mon Jan 20 00:25:28 2003 +0000
+++ b/src/video/qtopia/SDL_QWin.h Mon Jan 20 01:08:20 2003 +0000
@@ -70,14 +70,7 @@
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 @@
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 @@
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;
--- a/src/video/qtopia/SDL_sysvideo.cc Mon Jan 20 00:25:28 2003 +0000
+++ b/src/video/qtopia/SDL_sysvideo.cc Mon Jan 20 01:08:20 2003 +0000
@@ -53,12 +53,12 @@
//#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 @@
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 @@
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 @@
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 @@
static void QT_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
{
- int i;
- SDL_Win->lockScreen();
- for ( i=0; i<numrects; ++i ) {
- QRect rect(rects[i].x, rects[i].y,
- rects[i].w, rects[i].h);
- SDL_Win->repaintRect(rect);
+ if(SDL_Win->lockScreen()) {
+ for(int i=0; i<numrects; ++i ) {
+ QRect rect(rects[i].x, rects[i].y,
+ rects[i].w, rects[i].h);
+ SDL_Win->repaintRect(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 @@
// 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 */