cursor.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00033
00034
00035
00036
00037
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
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
00065 typedef Cursor XCursor;
00066
00067
00068 struct WMcursor {
00069 Cursor x_cursor;
00070 };
00071
00072 #endif
00073
00074 namespace FIFE {
00075 static Logger _log(LM_GUI);
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
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
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;
00193 case NC_IBEAM:
00194 return 32513;
00195 case NC_WAIT:
00196 return 32514;
00197 case NC_CROSS:
00198 return 32515;
00199 case NC_UPARROW:
00200 return 32516;
00201 case NC_RESIZESE:
00202 return 32642;
00203 case NC_RESIZESW:
00204 return 32643;
00205 case NC_RESIZEE:
00206 return 32644;
00207 case NC_RESIZES:
00208 return 32645;
00209 case NC_RESIZENW:
00210 return 32642;
00211 case NC_RESIZENE:
00212 return 32643;
00213 case NC_RESIZEW:
00214 return 32644;
00215 case NC_RESIZEN:
00216 return 32645;
00217 case NC_RESIZEALL:
00218 return 32646;
00219 case NC_NO:
00220 return 32648;
00221 case NC_HAND:
00222 return 32649;
00223 case NC_APPSTARTING:
00224 return 32650;
00225 case NC_HELP:
00226 return 32651;
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
00279 cursor_id = getNativeId(cursor_id);
00280
00281
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
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
00310 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
00311 curs2 = (SDL_Cursor *)SDL_malloc(sizeof *curs2);
00312
00313
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
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 }