src/video/qtopia/SDL_QWin.cc
author Sam Lantinga <slouken@libsdl.org>
Sun, 19 May 2002 20:06:01 +0000
changeset 371 db0cc6034336
child 379 11c8a7684f74
permissions -rw-r--r--
Added David Hedbor's Qtopia patches
slouken@371
     1
/*
slouken@371
     2
    SDL - Simple DirectMedia Layer
slouken@371
     3
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
slouken@371
     4
slouken@371
     5
    This library is free software; you can redistribute it and/or
slouken@371
     6
    modify it under the terms of the GNU Library General Public
slouken@371
     7
    License as published by the Free Software Foundation; either
slouken@371
     8
    version 2 of the License, or (at your option) any later version.
slouken@371
     9
slouken@371
    10
    This library is distributed in the hope that it will be useful,
slouken@371
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@371
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@371
    13
    Library General Public License for more details.
slouken@371
    14
slouken@371
    15
    You should have received a copy of the GNU Library General Public
slouken@371
    16
    License along with this library; if not, write to the Free
slouken@371
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@371
    18
slouken@371
    19
    Sam Lantinga
slouken@371
    20
    slouken@libsdl.org
slouken@371
    21
*/
slouken@371
    22
slouken@371
    23
#ifdef SAVE_RCSID
slouken@371
    24
static char rcsid =
slouken@371
    25
 "@(#) $Id$";
slouken@371
    26
#endif
slouken@371
    27
slouken@371
    28
#include "SDL_QWin.h"
slouken@371
    29
#include <qapplication.h>
slouken@371
    30
#include <qdirectpainter_qws.h>
slouken@371
    31
SDL_QWin::SDL_QWin(const QSize& size)
slouken@371
    32
  : QWidget(0, "SDL_main"), my_painter(0), my_image(0),
slouken@371
    33
    my_inhibit_resize(false), my_mouse_pos(-1,-1), my_flags(0),
slouken@371
    34
    my_has_fullscreen(false), my_locked(0)
slouken@371
    35
{
slouken@371
    36
  setBackgroundMode(NoBackground);
slouken@371
    37
}
slouken@371
    38
slouken@371
    39
SDL_QWin::~SDL_QWin() {
slouken@371
    40
  // Nothing to do yet.
slouken@371
    41
  if(my_image) {
slouken@371
    42
    delete my_image;
slouken@371
    43
  }
slouken@371
    44
}
slouken@371
    45
slouken@371
    46
void SDL_QWin::setImage(QImage *image) {
slouken@371
    47
  if ( my_image ) {
slouken@371
    48
    delete my_image;
slouken@371
    49
  }
slouken@371
    50
  my_image = image;
slouken@371
    51
  //  setFixedSize(image->size());
slouken@371
    52
}
slouken@371
    53
slouken@371
    54
void SDL_QWin::resizeEvent(QResizeEvent *e) {
slouken@371
    55
  if(size() != qApp->desktop()->size()) {
slouken@371
    56
    // Widget is not the correct size, so do the fullscreen magic
slouken@371
    57
    my_has_fullscreen = false;
slouken@371
    58
    enableFullscreen();
slouken@371
    59
  }
slouken@371
    60
  if(my_inhibit_resize) {
slouken@371
    61
    my_inhibit_resize = false;
slouken@371
    62
  } else {
slouken@371
    63
    SDL_PrivateResize(e->size().width(), e->size().height());
slouken@371
    64
  }
slouken@371
    65
}
slouken@371
    66
slouken@371
    67
void SDL_QWin::focusInEvent(QFocusEvent *) {
slouken@371
    68
  // Always do it here, no matter the size.
slouken@371
    69
  enableFullscreen();
slouken@371
    70
  SDL_PrivateAppActive(true, SDL_APPINPUTFOCUS);
slouken@371
    71
}
slouken@371
    72
slouken@371
    73
void SDL_QWin::focusOutEvent(QFocusEvent *) {
slouken@371
    74
  my_has_fullscreen = false;
slouken@371
    75
  SDL_PrivateAppActive(false, SDL_APPINPUTFOCUS);
slouken@371
    76
}
slouken@371
    77
slouken@371
    78
void SDL_QWin::closeEvent(QCloseEvent *e) {
slouken@371
    79
  SDL_PrivateQuit();
slouken@371
    80
  e->ignore();
slouken@371
    81
}
slouken@371
    82
slouken@371
    83
void SDL_QWin::mouseMoveEvent(QMouseEvent *e) {
slouken@371
    84
  Qt::ButtonState button = e->button();
slouken@371
    85
  int sdlstate = 0;
slouken@371
    86
  if( (button & Qt::LeftButton)) {
slouken@371
    87
    sdlstate |= SDL_BUTTON_LMASK;
slouken@371
    88
  }
slouken@371
    89
  if( (button & Qt::RightButton)) {
slouken@371
    90
    sdlstate |= SDL_BUTTON_RMASK;
slouken@371
    91
  }
slouken@371
    92
  if( (button & Qt::MidButton)) {
slouken@371
    93
    sdlstate |= SDL_BUTTON_MMASK;
slouken@371
    94
  }
slouken@371
    95
  SDL_PrivateMouseMotion(sdlstate, 0, e->pos().x(), e->pos().y());
slouken@371
    96
}
slouken@371
    97
slouken@371
    98
void SDL_QWin::mousePressEvent(QMouseEvent *e) {
slouken@371
    99
  my_mouse_pos = e->pos();
slouken@371
   100
  Qt::ButtonState button = e->button();
slouken@371
   101
  SDL_PrivateMouseButton(SDL_PRESSED,
slouken@371
   102
			 (button & Qt::LeftButton) ? 1 :
slouken@371
   103
			 ((button & Qt::RightButton) ? 2 : 3),
slouken@371
   104
			 e->x(), e->y());
slouken@371
   105
}
slouken@371
   106
slouken@371
   107
void SDL_QWin::mouseReleaseEvent(QMouseEvent *e) {
slouken@371
   108
  my_mouse_pos = QPoint(-1, -1);
slouken@371
   109
  Qt::ButtonState button = e->button();
slouken@371
   110
  SDL_PrivateMouseButton(SDL_RELEASED,
slouken@371
   111
			 (button & Qt::LeftButton) ? 1 :
slouken@371
   112
			 ((button & Qt::RightButton) ? 2 : 3),
slouken@371
   113
			 e->x(), e->y());
slouken@371
   114
}
slouken@371
   115
slouken@371
   116
#define USE_DIRECTPAINTER
slouken@371
   117
slouken@371
   118
slouken@371
   119
#ifndef __i386__
slouken@371
   120
static inline void gs_fastRotateBlit_3 ( unsigned short *fb,
slouken@371
   121
					 unsigned short *bits,
slouken@371
   122
					 const QRect& rect )
slouken@371
   123
{
slouken@371
   124
  int startx, starty;
slouken@371
   125
  int width, height;
slouken@371
   126
  
slouken@371
   127
  startx = rect.left() >> 1;
slouken@371
   128
  starty = rect.top() >> 1;
slouken@371
   129
  width  = ((rect.right() - rect.left()) >> 1) + 2;
slouken@371
   130
  height = ((rect.bottom() - rect.top()) >> 1) + 2;
slouken@371
   131
slouken@371
   132
  if((startx+width) > 120) {
slouken@371
   133
    width = 120 - startx; // avoid horizontal overflow
slouken@371
   134
  }
slouken@371
   135
  if((starty+height) > 160) { 
slouken@371
   136
    height = 160 - starty; // avoid vertical overflow
slouken@371
   137
  }
slouken@371
   138
slouken@371
   139
  ulong *sp1, *sp2, *dp1, *dp2;
slouken@371
   140
  ulong stop, sbot, dtop, dbot;    
slouken@371
   141
  
slouken@371
   142
  sp1 = (ulong*)bits + startx + starty*240;
slouken@371
   143
  sp2 = sp1 + 120;
slouken@371
   144
  dp1 = (ulong *)fb + (159 - starty) + startx*320;
slouken@371
   145
  dp2 = dp1 + 160;
slouken@371
   146
  int rowadd = (-320*width) - 1;
slouken@371
   147
  int rowadd2 = 240 - width;
slouken@371
   148
  // transfer in cells of 2x2 pixels in words
slouken@371
   149
  for (int y=0; y<height; y++) {
slouken@371
   150
    for (int x=0; x<width; x++) {
slouken@371
   151
      // read source pixels
slouken@371
   152
      stop = *sp1;
slouken@371
   153
      sbot = *sp2;
slouken@371
   154
      // rotate pixels
slouken@371
   155
      dtop = (sbot & 0xffff) + ((stop & 0xffff)<<16);
slouken@371
   156
      dbot = ((sbot & 0xffff0000)>>16) + (stop & 0xffff0000);
slouken@371
   157
      // write to framebuffer
slouken@371
   158
      *dp1 = dtop;
slouken@371
   159
      *dp2 = dbot;
slouken@371
   160
      // update source ptrs
slouken@371
   161
      sp1++; sp2++;
slouken@371
   162
      // update dest ptrs - 2 pix at a time
slouken@371
   163
      dp1 += 320;
slouken@371
   164
      dp2 += 320;
slouken@371
   165
    }
slouken@371
   166
    // adjust src ptrs - skip a row as we work in pairs
slouken@371
   167
    sp1 += rowadd2;
slouken@371
   168
    sp2 += rowadd2;
slouken@371
   169
    // adjust dest ptrs for rotation
slouken@371
   170
    dp1 += rowadd;
slouken@371
   171
    dp2 += rowadd;
slouken@371
   172
  }
slouken@371
   173
}
slouken@371
   174
#endif
slouken@371
   175
slouken@371
   176
void SDL_QWin::repaintRect(const QRect& rect) {
slouken@371
   177
  if(!my_painter || !rect.width() || !rect.height()) {
slouken@371
   178
    return;
slouken@371
   179
  }
slouken@371
   180
#ifndef __i386__
slouken@371
   181
slouken@371
   182
  if(QPixmap::defaultDepth() == 16 &&
slouken@371
   183
     my_painter->transformOrientation() == 3 &&
slouken@371
   184
     my_painter->numRects() >= 0) {
slouken@371
   185
    if(my_image->width() == width()) {
slouken@371
   186
      ushort *fb = (ushort*)my_painter->frameBuffer();
slouken@371
   187
      ushort *buf = (ushort*)my_image->bits();
slouken@371
   188
      gs_fastRotateBlit_3(fb, buf, rect);
slouken@371
   189
    } else {
slouken@371
   190
      // landscape mode
slouken@371
   191
      uchar *fb = (uchar*)my_painter->frameBuffer();
slouken@371
   192
      uchar *buf = (uchar*)my_image->bits();
slouken@371
   193
      int h = rect.height();
slouken@371
   194
      int wd = rect.width()<<1;
slouken@371
   195
      int fblineadd = my_painter->lineStep();
slouken@371
   196
      int buflineadd = my_image->bytesPerLine();
slouken@371
   197
      fb  += (rect.left()<<1) + rect.top() * my_painter->lineStep();
slouken@371
   198
      buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine();
slouken@371
   199
      while(h--) {
slouken@371
   200
	memcpy(fb, buf, wd);
slouken@371
   201
	fb += fblineadd;
slouken@371
   202
	buf += buflineadd;
slouken@371
   203
      }
slouken@371
   204
    }
slouken@371
   205
  } else {
slouken@371
   206
#endif
slouken@371
   207
    QPainter pp(this);
slouken@371
   208
    pp.drawImage(rect.topLeft(), *my_image, rect);
slouken@371
   209
    pp.end();
slouken@371
   210
#ifndef __i386__
slouken@371
   211
  }
slouken@371
   212
#endif
slouken@371
   213
}
slouken@371
   214
slouken@371
   215
// This paints the current buffer to the screen, when desired. 
slouken@371
   216
void SDL_QWin::paintEvent(QPaintEvent *ev) {  
slouken@371
   217
  if(my_image && isVisible() && isActiveWindow()) {
slouken@371
   218
    lockScreen();
slouken@371
   219
    repaintRect(ev->rect());
slouken@371
   220
    unlockScreen();
slouken@371
   221
  }
slouken@371
   222
}  
slouken@371
   223
slouken@371
   224
/* Function to translate a keyboard transition and queue the key event */
slouken@371
   225
void SDL_QWin::QueueKey(QKeyEvent *e, int pressed)
slouken@371
   226
{  
slouken@371
   227
  SDL_keysym keysym;
slouken@371
   228
  int scancode = e->key();
slouken@371
   229
  /* Set the keysym information */
slouken@371
   230
  if(scancode >= 'A' && scancode <= 'Z') {
slouken@371
   231
    // Qt sends uppercase, SDL wants lowercase
slouken@371
   232
    keysym.sym = static_cast<SDLKey>(scancode + 32);
slouken@371
   233
  } else if(scancode  >= 0x1000) {
slouken@371
   234
    // Special keys
slouken@371
   235
    switch(scancode) {
slouken@371
   236
    case Qt::Key_Escape: scancode = SDLK_ESCAPE; break;
slouken@371
   237
    case Qt::Key_Tab: scancode = SDLK_TAB; break;
slouken@371
   238
    case Qt::Key_Backspace: scancode = SDLK_BACKSPACE; break;
slouken@371
   239
    case Qt::Key_Return: scancode = SDLK_RETURN; break;
slouken@371
   240
    case Qt::Key_Enter: scancode = SDLK_KP_ENTER; break;
slouken@371
   241
    case Qt::Key_Insert: scancode = SDLK_INSERT; break;
slouken@371
   242
    case Qt::Key_Delete: scancode = SDLK_DELETE; break;
slouken@371
   243
    case Qt::Key_Pause: scancode = SDLK_PAUSE; break;
slouken@371
   244
    case Qt::Key_Print: scancode = SDLK_PRINT; break;
slouken@371
   245
    case Qt::Key_SysReq: scancode = SDLK_SYSREQ; break;
slouken@371
   246
    case Qt::Key_Home: scancode = SDLK_HOME; break;
slouken@371
   247
    case Qt::Key_End: scancode = SDLK_END; break;
slouken@371
   248
    case Qt::Key_Left: scancode = SDLK_LEFT; break;
slouken@371
   249
    case Qt::Key_Up: scancode = SDLK_UP; break;
slouken@371
   250
    case Qt::Key_Right: scancode = SDLK_RIGHT; break;
slouken@371
   251
    case Qt::Key_Down: scancode = SDLK_DOWN; break;
slouken@371
   252
    case Qt::Key_Prior: scancode = SDLK_PAGEUP; break;
slouken@371
   253
    case Qt::Key_Next: scancode = SDLK_PAGEDOWN; break;
slouken@371
   254
    case Qt::Key_Shift: scancode = SDLK_LSHIFT; break;
slouken@371
   255
    case Qt::Key_Control: scancode = SDLK_LCTRL; break;
slouken@371
   256
    case Qt::Key_Meta: scancode = SDLK_LMETA; break;
slouken@371
   257
    case Qt::Key_Alt: scancode = SDLK_LALT; break;
slouken@371
   258
    case Qt::Key_CapsLock: scancode = SDLK_CAPSLOCK; break;
slouken@371
   259
    case Qt::Key_NumLock: scancode = SDLK_NUMLOCK; break;
slouken@371
   260
    case Qt::Key_ScrollLock: scancode = SDLK_SCROLLOCK; break;
slouken@371
   261
    case Qt::Key_F1: scancode = SDLK_F1; break;
slouken@371
   262
    case Qt::Key_F2: scancode = SDLK_F2; break;
slouken@371
   263
    case Qt::Key_F3: scancode = SDLK_F3; break;
slouken@371
   264
    case Qt::Key_F4: scancode = SDLK_F4; break;
slouken@371
   265
    case Qt::Key_F5: scancode = SDLK_F5; break;
slouken@371
   266
    case Qt::Key_F6: scancode = SDLK_F6; break;
slouken@371
   267
    case Qt::Key_F7: scancode = SDLK_F7; break;
slouken@371
   268
    case Qt::Key_F8: scancode = SDLK_F8; break;
slouken@371
   269
    case Qt::Key_F9: scancode = SDLK_F9; break;
slouken@371
   270
    case Qt::Key_F10: scancode = SDLK_F10; break;
slouken@371
   271
    case Qt::Key_F11: scancode = SDLK_F11; break;
slouken@371
   272
    case Qt::Key_F12: scancode = SDLK_F12; break;
slouken@371
   273
    case Qt::Key_F13: scancode = SDLK_F13; break;
slouken@371
   274
    case Qt::Key_F14: scancode = SDLK_F14; break;
slouken@371
   275
    case Qt::Key_F15: scancode = SDLK_F15; break;
slouken@371
   276
    case Qt::Key_Super_L: scancode = SDLK_LSUPER; break;
slouken@371
   277
    case Qt::Key_Super_R: scancode = SDLK_RSUPER; break;
slouken@371
   278
    case Qt::Key_Menu: scancode = SDLK_MENU; break;
slouken@371
   279
    case Qt::Key_Help: scancode = SDLK_HELP; break;
slouken@371
   280
    default:
slouken@371
   281
      scancode = SDLK_UNKNOWN;
slouken@371
   282
      break;
slouken@371
   283
    }
slouken@371
   284
    keysym.sym = static_cast<SDLKey>(scancode);    
slouken@371
   285
  } else {
slouken@371
   286
    keysym.sym = static_cast<SDLKey>(scancode);    
slouken@371
   287
  }
slouken@371
   288
  keysym.scancode = scancode;
slouken@371
   289
  keysym.mod = KMOD_NONE;
slouken@371
   290
  ButtonState st = e->state();
slouken@371
   291
  if( (st & ShiftButton) )   { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LSHIFT);  }
slouken@371
   292
  if( (st & ControlButton) ) { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LCTRL);  }
slouken@371
   293
  if( (st & AltButton) )     { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LALT);  }
slouken@371
   294
  if ( SDL_TranslateUNICODE ) {
slouken@371
   295
    QChar qchar = e->text()[0];
slouken@371
   296
    keysym.unicode = qchar.unicode();
slouken@371
   297
  } else {
slouken@371
   298
    keysym.unicode = 0;
slouken@371
   299
  }
slouken@371
   300
slouken@371
   301
  /* NUMLOCK and CAPSLOCK are implemented as double-presses in reality */
slouken@371
   302
  //	if ( (keysym.sym == SDLK_NUMLOCK) || (keysym.sym == SDLK_CAPSLOCK) ) {
slouken@371
   303
  //		pressed = 1;
slouken@371
   304
  //	}
slouken@371
   305
slouken@371
   306
  /* Queue the key event */
slouken@371
   307
  if ( pressed ) {
slouken@371
   308
    SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
slouken@371
   309
  } else {
slouken@371
   310
    SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
slouken@371
   311
  }
slouken@371
   312
}
slouken@371
   313
slouken@371
   314
void SDL_QWin::setFullscreen(bool fs_on) {
slouken@371
   315
  my_has_fullscreen = false;
slouken@371
   316
  enableFullscreen();
slouken@371
   317
}
slouken@371
   318
slouken@371
   319
void SDL_QWin::enableFullscreen() {
slouken@371
   320
  // Make sure size is correct
slouken@371
   321
  if(!my_has_fullscreen) {
slouken@371
   322
    setFixedSize(qApp->desktop()->size());
slouken@371
   323
    // This call is needed because showFullScreen won't work
slouken@371
   324
    // correctly if the widget already considers itself to be fullscreen.
slouken@371
   325
    showNormal();
slouken@371
   326
    // This is needed because showNormal() forcefully changes the window
slouken@371
   327
    // style to WSTyle_TopLevel.
slouken@371
   328
    setWFlags(WStyle_Customize | WStyle_NoBorder);
slouken@371
   329
    // Enable fullscreen.
slouken@371
   330
    showFullScreen();
slouken@371
   331
    my_has_fullscreen = true;
slouken@371
   332
  }
slouken@371
   333
}