cursor.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 #if defined( WIN32 )
00024 #include <windows.h>
00025 #include <sdl.h>
00026 #endif
00027 
00028 #if defined( __unix__ )
00029 #include <X11/Xcursor/Xcursor.h>
00030 #endif
00031 
00032 // 3rd party library includes
00033 
00034 // FIFE includes
00035 // These includes are split up in two parts, separated by one empty line
00036 // First block: files included from the FIFE root src directory
00037 // Second block: files included from the same folder
00038 #include "util/structures/rect.h"
00039 #include "util/time/timemanager.h"
00040 #include "util/log/logger.h"
00041 
00042 #include "imagepool.h"
00043 #include "animationpool.h"
00044 #include "animation.h"
00045 #include "image.h"
00046 #include "renderbackend.h"
00047 #include "cursor.h"
00048 
00049 #if defined( WIN32 )
00050 
00051 // From SDL_sysmouse.c
00052 struct WMcursor {
00053     HCURSOR curs;
00054 #ifndef _WIN32_WCE
00055     Uint8 *ands;
00056     Uint8 *xors;
00057 #endif
00058 };
00059 
00060 #endif
00061 
00062 #if defined( __unix__ )
00063 
00064 // Stops the compiler from confusing it with FIFE:Cursor
00065 typedef Cursor XCursor;
00066 
00067 // From SDL_x11mouse.c
00068 struct WMcursor {
00069     Cursor x_cursor;
00070 };
00071 
00072 #endif
00073 
00074 namespace FIFE {
00075     static Logger _log(LM_GUI); // We should have a log module for cursor
00076 
00077     Cursor::Cursor(ImagePool* imgpool, AnimationPool* animpool, RenderBackend* renderbackend):
00078         m_cursor_id(NC_ARROW),
00079         m_drag_id(0),
00080         m_cursor_type(CURSOR_NATIVE),
00081         m_drag_type(CURSOR_NONE),
00082         m_native_cursor(NULL),
00083         m_renderbackend(renderbackend),
00084         m_imgpool(imgpool),
00085         m_animpool(animpool),
00086         m_animtime(0),
00087         m_drag_animtime(0),
00088         m_drag_offset_x(0),
00089         m_drag_offset_y(0),
00090         m_mx(0),
00091         m_my(0),
00092         m_timemanager(TimeManager::instance()) {
00093         assert(m_timemanager);
00094         set(m_cursor_type, m_cursor_id);
00095     }
00096     
00097     void Cursor::set(MouseCursorType ctype, unsigned int cursor_id) {
00098         m_cursor_id = cursor_id;
00099         m_cursor_type = ctype;
00100         int mx, my;
00101         SDL_GetMouseState(&mx, &my);
00102 
00103         if (ctype == CURSOR_NATIVE) {
00104             if (!SDL_ShowCursor(1)) {
00105                 SDL_PumpEvents();
00106                 SDL_WarpMouse(mx, my);
00107             }
00108             setNativeCursor(cursor_id);
00109         } else {
00110             if (SDL_ShowCursor(0)) {
00111                 SDL_PumpEvents();
00112                 SDL_WarpMouse(mx, my);
00113             }
00114             if (ctype == CURSOR_ANIMATION) {
00115                 m_animtime = m_timemanager->getTime();
00116             }
00117         }
00118     }
00119     
00120     void Cursor::setDrag(MouseCursorType ctype, unsigned int drag_id, int drag_offset_x, int drag_offset_y) {
00121         m_drag_type = ctype;
00122         m_drag_id = drag_id;
00123         m_drag_offset_x = drag_offset_x;
00124         m_drag_offset_y = drag_offset_y;
00125         if (ctype != CURSOR_NONE) {
00126             if (ctype == CURSOR_ANIMATION) {
00127                 m_drag_animtime = m_timemanager->getTime();
00128             }
00129         }
00130     }
00131     
00132     void Cursor::draw() {
00133         SDL_GetMouseState(&m_mx, &m_my);
00134         if ((m_cursor_type == CURSOR_NATIVE) && (m_drag_type == CURSOR_NONE)) {
00135             return;
00136         }
00137         
00138         // render possible drag image
00139         Image* img = NULL;
00140         if (m_drag_type == CURSOR_IMAGE) {
00141             img = &m_imgpool->getImage(m_drag_id);
00142         } else if (m_drag_type == CURSOR_ANIMATION) {
00143             Animation& anim = m_animpool->getAnimation(m_drag_id);
00144             int animtime = (m_timemanager->getTime() - m_drag_animtime) % anim.getDuration();
00145             img = anim.getFrameByTimestamp(animtime);
00146         }
00147         if (img) {
00148             Rect area(m_mx + m_drag_offset_x + img->getXShift(), m_my + m_drag_offset_y + img->getYShift(), img->getWidth(), img->getHeight());
00149             m_renderbackend->pushClipArea(area, false);
00150             img->render(area);
00151             m_renderbackend->popClipArea();
00152         }
00153         
00154         // render possible cursor image
00155         img = NULL;
00156         if (m_cursor_type == CURSOR_IMAGE) {
00157             img = &m_imgpool->getImage(m_cursor_id);
00158         } else if (m_cursor_type == CURSOR_ANIMATION) {
00159             Animation& anim = m_animpool->getAnimation(m_cursor_id);
00160             int animtime = (m_timemanager->getTime() - m_animtime) % anim.getDuration();
00161             img = anim.getFrameByTimestamp(animtime);
00162         }
00163         if (img) {
00164             Rect area(m_mx + img->getXShift(), m_my + img->getYShift(), img->getWidth(), img->getHeight());
00165             m_renderbackend->pushClipArea(area, false);
00166             img->render(area);
00167             m_renderbackend->popClipArea();
00168         }
00169     }
00170 
00171     unsigned int Cursor::getNativeId(unsigned int cursor_id) {
00172 #if defined( WIN32 )
00173         switch (cursor_id) {
00174             case NC_ARROW:
00175                 return 32512; // IDC_ARROW;
00176             case NC_IBEAM:
00177                 return 32513; // IDC_IBEAM;
00178             case NC_WAIT:
00179                 return 32514; // IDC_WAIT;
00180             case NC_CROSS:
00181                 return 32515; // IDC_CROSS;
00182             case NC_UPARROW:
00183                 return 32516; // IDC_UPARROW;
00184             case NC_RESIZESE:
00185                 return 32642; // IDC_SIZENWSE;
00186             case NC_RESIZESW:
00187                 return 32643; // IDC_SIZENESW;
00188             case NC_RESIZEE:
00189                 return 32644; // IDC_SIZEWE;
00190             case NC_RESIZES:
00191                 return 32645; // IDC_SIZENS;
00192             case NC_RESIZENW:
00193                 return 32642; // IDC_SIZENWSE;
00194             case NC_RESIZENE:
00195                 return 32643; // IDC_SIZENESW;
00196             case NC_RESIZEW:
00197                 return 32644; // IDC_SIZEWE;
00198             case NC_RESIZEN:
00199                 return 32645; // IDC_SIZENS;
00200             case NC_RESIZEALL:
00201                 return 32646; // IDC_SIZEALL;
00202             case NC_NO:
00203                 return 32648; // IDC_NO;
00204             case NC_HAND:
00205                 return 32649; // IDC_HAND;
00206             case NC_APPSTARTING:
00207                 return 32650; // IDC_APPSTARTING;
00208             case NC_HELP:
00209                 return 32651; // IDC_HELP;
00210             default:
00211                 break;
00212         }
00213 
00214 #elif defined( __unix__ )
00215         switch (cursor_id) {
00216             case NC_ARROW:
00217                 return 68;
00218             case NC_IBEAM:
00219                 return 152;
00220             case NC_WAIT:
00221                 return 150;
00222             case NC_CROSS:
00223                 return 130;
00224             case NC_UPARROW:
00225                 return 22;
00226             case NC_RESIZESE:
00227                 return 14;
00228             case NC_RESIZESW:
00229                 return 12;
00230             case NC_RESIZEE:
00231                 return 96;
00232             case NC_RESIZES:
00233                 return 16;
00234             case NC_RESIZENW:
00235                 return 134;
00236             case NC_RESIZENE:
00237                 return 136;
00238             case NC_RESIZEW:
00239                 return 70;
00240             case NC_RESIZEN:
00241                 return 138;
00242             case NC_RESIZEALL:
00243                 return 52;
00244             case NC_NO:
00245                 return 0;
00246             case NC_HAND:
00247                 return 60;
00248             case NC_APPSTARTING:
00249                 return 150;
00250             case NC_HELP:
00251                 return 92;
00252             default:
00253                 break;
00254         }
00255 #endif
00256         return cursor_id;
00257     }
00258 
00259     void Cursor::setNativeCursor(unsigned int cursor_id) {
00260 #if defined( WIN32 ) || defined(__unix__)
00261         // Check if a value in NativeCursors is requested
00262         cursor_id = getNativeId(cursor_id);
00263 
00264         // Load cursor
00265 #if defined( __unix__ )
00266         static Display* dsp = XOpenDisplay(NULL);
00267         XCursor xCursor = XcursorShapeLoadCursor(dsp, cursor_id);
00268         if (xCursor == 0) {
00269             if (m_native_cursor != NULL) {
00270                 SDL_FreeCursor(m_native_cursor);
00271                 m_native_cursor = NULL;
00272             }
00273             FL_WARN(_log, "Cursor: No cursor matching cursor_id was found.");
00274             return;
00275         }
00276 #elif defined( WIN32 )
00277         // Load native cursor
00278         HCURSOR hIcon = LoadCursor(NULL, MAKEINTRESOURCE(cursor_id));
00279         if (hIcon == static_cast<HCURSOR>(0)) {
00280             if (m_native_cursor != NULL) {
00281                 SDL_FreeCursor(m_native_cursor);
00282                 m_native_cursor = NULL;
00283             }
00284             FL_WARN(_log, "Cursor: No cursor matching cursor_id was found.");
00285             return;
00286         }
00287 #endif
00288 
00289         WMcursor *cursor;
00290         SDL_Cursor *curs2;
00291 
00292         // Allocate memory. Use SDL_FreeCursor to free cursor memory
00293         cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
00294         curs2 = (SDL_Cursor *)SDL_malloc(sizeof *curs2);
00295 
00296         //-- Set up some default values --
00297         curs2->wm_cursor = cursor;
00298         curs2->data = NULL;
00299         curs2->mask = NULL;
00300         curs2->save[0] = NULL;
00301         curs2->save[1] = NULL;
00302         curs2->area.x = 0;
00303         curs2->area.y = 0;
00304         curs2->area.w = 32;
00305         curs2->area.h = 32;
00306         curs2->hot_x = 0;
00307         curs2->hot_y = 0;
00308 
00309 #if defined(WIN32)
00310         cursor->curs = hIcon;
00311 #ifndef _WIN32_WCE
00312         cursor->ands = NULL;
00313         cursor->xors = NULL;
00314 #endif
00315 
00316         // Get hot spot
00317         ICONINFO iconinfo;
00318         if (GetIconInfo(hIcon, &iconinfo)) {
00319             curs2->hot_x = static_cast<Sint16>(iconinfo.xHotspot);
00320             curs2->hot_y = static_cast<Sint16>(iconinfo.yHotspot);
00321         }
00322 
00323 #elif defined(__unix__)
00324         cursor->x_cursor = xCursor;
00325         XSync(dsp, false);
00326 #endif
00327         
00328         m_native_cursor = curs2;
00329         SDL_SetCursor(curs2);
00330 
00331 #endif // WIN32 || __unix__
00332     }
00333 }
Generated by  doxygen 1.6.2-20100208