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         m_invalidated(false) {
00094         assert(m_timemanager);
00095         set(m_cursor_type, m_cursor_id);
00096     }
00097 
00098     void Cursor::set(MouseCursorType ctype, unsigned int cursor_id) {
00099         m_cursor_id = cursor_id;
00100         m_cursor_type = ctype;
00101         int mx, my;
00102         SDL_GetMouseState(&mx, &my);
00103 
00104         if (ctype == CURSOR_NATIVE) {
00105             if (!SDL_ShowCursor(1)) {
00106                 SDL_PumpEvents();
00107                 SDL_WarpMouse(mx, my);
00108             }
00109             setNativeCursor(cursor_id);
00110         } else {
00111             if (SDL_ShowCursor(0)) {
00112                 SDL_PumpEvents();
00113                 SDL_WarpMouse(mx, my);
00114             }
00115             if (ctype == CURSOR_ANIMATION) {
00116                 m_animtime = m_timemanager->getTime();
00117             }
00118         }
00119         m_invalidated = false;
00120     }
00121 
00122     void Cursor::setDrag(MouseCursorType ctype, unsigned int drag_id, int drag_offset_x, int drag_offset_y) {
00123         m_drag_type = ctype;
00124         m_drag_id = drag_id;
00125         m_drag_offset_x = drag_offset_x;
00126         m_drag_offset_y = drag_offset_y;
00127         if (ctype != CURSOR_NONE) {
00128             if (ctype == CURSOR_ANIMATION) {
00129                 m_drag_animtime = m_timemanager->getTime();
00130             }
00131         }
00132     }
00133 
00134     void Cursor::invalidate() {
00135         if (m_native_cursor != NULL) {
00136             SDL_free(m_native_cursor->wm_cursor);
00137             m_native_cursor->wm_cursor = NULL;
00138             SDL_FreeCursor(m_native_cursor);
00139             m_native_cursor = NULL;
00140 
00141             m_invalidated = true;
00142         }
00143     }
00144 
00145     void Cursor::draw() {
00146         if (m_invalidated) {
00147             set(m_cursor_type, m_cursor_id);
00148         }
00149 
00150         SDL_GetMouseState(&m_mx, &m_my);
00151         if ((m_cursor_type == CURSOR_NATIVE) && (m_drag_type == CURSOR_NONE)) {
00152             return;
00153         }
00154 
00155         // render possible drag image
00156         Image* img = NULL;
00157         if (m_drag_type == CURSOR_IMAGE) {
00158             img = &m_imgpool->getImage(m_drag_id);
00159         } else if (m_drag_type == CURSOR_ANIMATION) {
00160             Animation& anim = m_animpool->getAnimation(m_drag_id);
00161             int animtime = (m_timemanager->getTime() - m_drag_animtime) % anim.getDuration();
00162             img = anim.getFrameByTimestamp(animtime);
00163         }
00164         if (img) {
00165             Rect area(m_mx + m_drag_offset_x + img->getXShift(), m_my + m_drag_offset_y + img->getYShift(), img->getWidth(), img->getHeight());
00166             m_renderbackend->pushClipArea(area, false);
00167             img->render(area);
00168             m_renderbackend->popClipArea();
00169         }
00170 
00171         // render possible cursor image
00172         img = NULL;
00173         if (m_cursor_type == CURSOR_IMAGE) {
00174             img = &m_imgpool->getImage(m_cursor_id);
00175         } else if (m_cursor_type == CURSOR_ANIMATION) {
00176             Animation& anim = m_animpool->getAnimation(m_cursor_id);
00177             int animtime = (m_timemanager->getTime() - m_animtime) % anim.getDuration();
00178             img = anim.getFrameByTimestamp(animtime);
00179         }
00180         if (img) {
00181             Rect area(m_mx + img->getXShift(), m_my + img->getYShift(), img->getWidth(), img->getHeight());
00182             m_renderbackend->pushClipArea(area, false);
00183             img->render(area);
00184             m_renderbackend->popClipArea();
00185         }
00186     }
00187 
00188     unsigned int Cursor::getNativeId(unsigned int cursor_id) {
00189 #if defined( WIN32 )
00190         switch (cursor_id) {
00191             case NC_ARROW:
00192                 return 32512; // IDC_ARROW;
00193             case NC_IBEAM:
00194                 return 32513; // IDC_IBEAM;
00195             case NC_WAIT:
00196                 return 32514; // IDC_WAIT;
00197             case NC_CROSS:
00198                 return 32515; // IDC_CROSS;
00199             case NC_UPARROW:
00200                 return 32516; // IDC_UPARROW;
00201             case NC_RESIZESE:
00202                 return 32642; // IDC_SIZENWSE;
00203             case NC_RESIZESW:
00204                 return 32643; // IDC_SIZENESW;
00205             case NC_RESIZEE:
00206                 return 32644; // IDC_SIZEWE;
00207             case NC_RESIZES:
00208                 return 32645; // IDC_SIZENS;
00209             case NC_RESIZENW:
00210                 return 32642; // IDC_SIZENWSE;
00211             case NC_RESIZENE:
00212                 return 32643; // IDC_SIZENESW;
00213             case NC_RESIZEW:
00214                 return 32644; // IDC_SIZEWE;
00215             case NC_RESIZEN:
00216                 return 32645; // IDC_SIZENS;
00217             case NC_RESIZEALL:
00218                 return 32646; // IDC_SIZEALL;
00219             case NC_NO:
00220                 return 32648; // IDC_NO;
00221             case NC_HAND:
00222                 return 32649; // IDC_HAND;
00223             case NC_APPSTARTING:
00224                 return 32650; // IDC_APPSTARTING;
00225             case NC_HELP:
00226                 return 32651; // IDC_HELP;
00227             default:
00228                 break;
00229         }
00230 
00231 #elif defined( __unix__ )
00232         switch (cursor_id) {
00233             case NC_ARROW:
00234                 return 68;
00235             case NC_IBEAM:
00236                 return 152;
00237             case NC_WAIT:
00238                 return 150;
00239             case NC_CROSS:
00240                 return 130;
00241             case NC_UPARROW:
00242                 return 22;
00243             case NC_RESIZESE:
00244                 return 14;
00245             case NC_RESIZESW:
00246                 return 12;
00247             case NC_RESIZEE:
00248                 return 96;
00249             case NC_RESIZES:
00250                 return 16;
00251             case NC_RESIZENW:
00252                 return 134;
00253             case NC_RESIZENE:
00254                 return 136;
00255             case NC_RESIZEW:
00256                 return 70;
00257             case NC_RESIZEN:
00258                 return 138;
00259             case NC_RESIZEALL:
00260                 return 52;
00261             case NC_NO:
00262                 return 0;
00263             case NC_HAND:
00264                 return 60;
00265             case NC_APPSTARTING:
00266                 return 150;
00267             case NC_HELP:
00268                 return 92;
00269             default:
00270                 break;
00271         }
00272 #endif
00273         return cursor_id;
00274     }
00275 
00276     void Cursor::setNativeCursor(unsigned int cursor_id) {
00277 #if defined( WIN32 ) || defined(__unix__)
00278         // Check if a value in NativeCursors is requested
00279         cursor_id = getNativeId(cursor_id);
00280 
00281         // Load cursor
00282 #if defined( __unix__ )
00283         static Display* dsp = XOpenDisplay(NULL);
00284         XCursor xCursor = XcursorShapeLoadCursor(dsp, cursor_id);
00285         if (xCursor == 0) {
00286             if (m_native_cursor != NULL) {
00287                 SDL_FreeCursor(m_native_cursor);
00288                 m_native_cursor = NULL;
00289             }
00290             FL_WARN(_log, "Cursor: No cursor matching cursor_id was found.");
00291             return;
00292         }
00293 #elif defined( WIN32 )
00294         // Load native cursor
00295         HCURSOR hIcon = LoadCursor(NULL, MAKEINTRESOURCE(cursor_id));
00296         if (hIcon == static_cast<HCURSOR>(0)) {
00297             if (m_native_cursor != NULL) {
00298                 SDL_FreeCursor(m_native_cursor);
00299                 m_native_cursor = NULL;
00300             }
00301             FL_WARN(_log, "Cursor: No cursor matching cursor_id was found.");
00302             return;
00303         }
00304 #endif
00305 
00306         WMcursor *cursor;
00307         SDL_Cursor *curs2;
00308 
00309         // Allocate memory. Use SDL_FreeCursor to free cursor memory
00310         cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
00311         curs2 = (SDL_Cursor *)SDL_malloc(sizeof *curs2);
00312 
00313         //-- Set up some default values --
00314         curs2->wm_cursor = cursor;
00315         curs2->data = NULL;
00316         curs2->mask = NULL;
00317         curs2->save[0] = NULL;
00318         curs2->save[1] = NULL;
00319         curs2->area.x = 0;
00320         curs2->area.y = 0;
00321         curs2->area.w = 32;
00322         curs2->area.h = 32;
00323         curs2->hot_x = 0;
00324         curs2->hot_y = 0;
00325 
00326 #if defined(WIN32)
00327         cursor->curs = hIcon;
00328 #ifndef _WIN32_WCE
00329         cursor->ands = NULL;
00330         cursor->xors = NULL;
00331 #endif
00332 
00333         // Get hot spot
00334         ICONINFO iconinfo;
00335         if (GetIconInfo(hIcon, &iconinfo)) {
00336             curs2->hot_x = static_cast<Sint16>(iconinfo.xHotspot);
00337             curs2->hot_y = static_cast<Sint16>(iconinfo.yHotspot);
00338         }
00339 
00340 #elif defined(__unix__)
00341         cursor->x_cursor = xCursor;
00342         XSync(dsp, false);
00343 #endif
00344 
00345         m_native_cursor = curs2;
00346         SDL_SetCursor(curs2);
00347 
00348 #endif // WIN32 || __unix__
00349     }
00350 }
Generated on Wed Nov 23 13:04:43 2011 for FIFE by  doxygen 1.6.3