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 #include "video/imagemanager.h"
00042
00043 #include "animation.h"
00044 #include "image.h"
00045 #include "renderbackend.h"
00046 #include "cursor.h"
00047
00048 #if defined( WIN32 )
00049
00050
00051 struct WMcursor {
00052 HCURSOR curs;
00053 #ifndef _WIN32_WCE
00054 Uint8 *ands;
00055 Uint8 *xors;
00056 #endif
00057 };
00058
00059 #endif
00060
00061 #if defined( __unix__ )
00062
00063
00064 typedef Cursor XCursor;
00065
00066
00067 struct WMcursor {
00068 Cursor x_cursor;
00069 };
00070
00071 #endif
00072
00073 namespace FIFE {
00074 static Logger _log(LM_GUI);
00075
00076 Cursor::Cursor(RenderBackend* renderbackend):
00077 m_cursor_id(NC_ARROW),
00078 m_drag_id(0),
00079 m_cursor_type(CURSOR_NATIVE),
00080 m_drag_type(CURSOR_NONE),
00081 m_native_cursor(NULL),
00082 m_renderbackend(renderbackend),
00083 m_animtime(0),
00084 m_drag_animtime(0),
00085 m_drag_offset_x(0),
00086 m_drag_offset_y(0),
00087 m_mx(0),
00088 m_my(0),
00089 m_timemanager(TimeManager::instance()),
00090 m_invalidated(false) {
00091 assert(m_timemanager);
00092 set(m_cursor_id);
00093 }
00094
00095 void Cursor::set(uint32_t cursor_id) {
00096 m_cursor_type = CURSOR_NATIVE;
00097
00098 if (!SDL_ShowCursor(1)) {
00099 SDL_PumpEvents();
00100 }
00101 setNativeCursor(cursor_id);
00102
00103 m_cursor_image.reset();
00104 m_cursor_animation.reset();
00105 }
00106
00107 void Cursor::set(ImagePtr image) {
00108 assert(image != 0);
00109
00110 m_cursor_image = image;
00111 m_cursor_type = CURSOR_IMAGE;
00112
00113 if (SDL_ShowCursor(0)) {
00114 SDL_PumpEvents();
00115 }
00116
00117 m_cursor_id = NC_ARROW;
00118 m_cursor_animation.reset();
00119 }
00120
00121 void Cursor::set(AnimationPtr anim) {
00122 assert(anim != 0);
00123
00124 m_cursor_animation = anim;
00125 m_cursor_type = CURSOR_ANIMATION;
00126
00127 if (SDL_ShowCursor(0)) {
00128 SDL_PumpEvents();
00129 }
00130 m_animtime = m_timemanager->getTime();
00131
00132 m_cursor_id = NC_ARROW;
00133 m_cursor_image.reset();
00134 }
00135
00136 void Cursor::setDrag(ImagePtr image, int32_t drag_offset_x, int32_t drag_offset_y) {
00137 assert(image != 0);
00138
00139 m_cursor_drag_image = image;
00140 m_drag_type = CURSOR_IMAGE;
00141 m_drag_offset_x = drag_offset_x;
00142 m_drag_offset_y = drag_offset_y;
00143
00144 m_cursor_drag_animation.reset();
00145 }
00146
00147 void Cursor::setDrag(AnimationPtr anim, int32_t drag_offset_x, int32_t drag_offset_y) {
00148 assert(anim != 0);
00149
00150 m_cursor_drag_animation = anim;
00151 m_drag_type = CURSOR_ANIMATION;
00152 m_drag_offset_x = drag_offset_x;
00153 m_drag_offset_y = drag_offset_y;
00154
00155 m_drag_animtime = m_timemanager->getTime();
00156
00157 m_cursor_drag_image.reset();
00158 }
00159
00160 void Cursor::resetDrag() {
00161 m_drag_type = CURSOR_NONE;
00162
00163 m_drag_animtime = 0;
00164 m_drag_offset_x = 0;
00165 m_drag_offset_y = 0;
00166
00167 m_cursor_drag_animation.reset();
00168 m_cursor_drag_image.reset();
00169 }
00170
00171 void Cursor::setPosition(uint32_t x, uint32_t y) {
00172 m_mx = x;
00173 m_my = y;
00174 SDL_WarpMouse(m_mx, m_my);
00175 }
00176
00177 void Cursor::getPosition(int32_t* x, int32_t* y) {
00178 *x = m_mx;
00179 *y = m_my;
00180 }
00181
00182 void Cursor::invalidate() {
00183 if (m_native_cursor != NULL) {
00184 SDL_free(m_native_cursor->wm_cursor);
00185 m_native_cursor->wm_cursor = NULL;
00186 SDL_FreeCursor(m_native_cursor);
00187 m_native_cursor = NULL;
00188
00189 m_invalidated = true;
00190 }
00191 }
00192
00193 void Cursor::draw() {
00194 if (m_invalidated) {
00195 if (m_cursor_type != CURSOR_ANIMATION || m_cursor_type == CURSOR_IMAGE ) {
00196 set(m_cursor_id);
00197 }
00198
00199 m_invalidated = false;
00200 }
00201
00202 SDL_GetMouseState(&m_mx, &m_my);
00203 if ((m_cursor_type == CURSOR_NATIVE) && (m_drag_type == CURSOR_NONE)) {
00204 return;
00205 }
00206
00207
00208 ImagePtr img;
00209 if (m_drag_type == CURSOR_IMAGE) {
00210 img = m_cursor_drag_image;
00211 }
00212 else if (m_drag_type == CURSOR_ANIMATION) {
00213 int32_t animtime = (m_timemanager->getTime() - m_drag_animtime) % m_cursor_drag_animation->getDuration();
00214 img = m_cursor_drag_animation->getFrameByTimestamp(animtime);
00215 }
00216
00217 if (img != 0) {
00218 Rect area(m_mx + m_drag_offset_x + img->getXShift(), m_my + m_drag_offset_y + img->getYShift(), img->getWidth(), img->getHeight());
00219 m_renderbackend->pushClipArea(area, false);
00220 img->render(area);
00221 m_renderbackend->renderVertexArrays();
00222 m_renderbackend->popClipArea();
00223 }
00224
00225 ImagePtr img2;
00226
00227 if (m_cursor_type == CURSOR_IMAGE) {
00228 img2 = m_cursor_image;
00229 }
00230 else if (m_cursor_type == CURSOR_ANIMATION) {
00231 int32_t animtime = (m_timemanager->getTime() - m_animtime) % m_cursor_animation->getDuration();
00232 img2 = m_cursor_animation->getFrameByTimestamp(animtime);
00233 }
00234
00235 if (img2 != 0) {
00236 Rect area(m_mx + img2->getXShift(), m_my + img2->getYShift(), img2->getWidth(), img2->getHeight());
00237 m_renderbackend->pushClipArea(area, false);
00238 img2->render(area);
00239 m_renderbackend->renderVertexArrays();
00240 m_renderbackend->popClipArea();
00241 }
00242 }
00243
00244 uint32_t Cursor::getNativeId(uint32_t cursor_id) {
00245 #if defined( WIN32 )
00246 switch (cursor_id) {
00247 case NC_ARROW:
00248 return 32512;
00249 case NC_IBEAM:
00250 return 32513;
00251 case NC_WAIT:
00252 return 32514;
00253 case NC_CROSS:
00254 return 32515;
00255 case NC_UPARROW:
00256 return 32516;
00257 case NC_RESIZESE:
00258 return 32642;
00259 case NC_RESIZESW:
00260 return 32643;
00261 case NC_RESIZEE:
00262 return 32644;
00263 case NC_RESIZES:
00264 return 32645;
00265 case NC_RESIZENW:
00266 return 32642;
00267 case NC_RESIZENE:
00268 return 32643;
00269 case NC_RESIZEW:
00270 return 32644;
00271 case NC_RESIZEN:
00272 return 32645;
00273 case NC_RESIZEALL:
00274 return 32646;
00275 case NC_NO:
00276 return 32648;
00277 case NC_HAND:
00278 return 32649;
00279 case NC_APPSTARTING:
00280 return 32650;
00281 case NC_HELP:
00282 return 32651;
00283 default:
00284 break;
00285 }
00286
00287 #elif defined( __unix__ )
00288 switch (cursor_id) {
00289 case NC_ARROW:
00290 return 68;
00291 case NC_IBEAM:
00292 return 152;
00293 case NC_WAIT:
00294 return 150;
00295 case NC_CROSS:
00296 return 130;
00297 case NC_UPARROW:
00298 return 22;
00299 case NC_RESIZESE:
00300 return 14;
00301 case NC_RESIZESW:
00302 return 12;
00303 case NC_RESIZEE:
00304 return 96;
00305 case NC_RESIZES:
00306 return 16;
00307 case NC_RESIZENW:
00308 return 134;
00309 case NC_RESIZENE:
00310 return 136;
00311 case NC_RESIZEW:
00312 return 70;
00313 case NC_RESIZEN:
00314 return 138;
00315 case NC_RESIZEALL:
00316 return 52;
00317 case NC_NO:
00318 return 0;
00319 case NC_HAND:
00320 return 60;
00321 case NC_APPSTARTING:
00322 return 150;
00323 case NC_HELP:
00324 return 92;
00325 default:
00326 break;
00327 }
00328 #endif
00329 return cursor_id;
00330 }
00331
00332 void Cursor::setNativeCursor(uint32_t cursor_id) {
00333 #if defined( WIN32 ) || defined(__unix__)
00334
00335 cursor_id = getNativeId(cursor_id);
00336
00337
00338 #if defined( __unix__ )
00339 static Display* dsp = XOpenDisplay(NULL);
00340 XCursor xCursor = XcursorShapeLoadCursor(dsp, cursor_id);
00341 if (xCursor == 0) {
00342 if (m_native_cursor != NULL) {
00343 SDL_FreeCursor(m_native_cursor);
00344 m_native_cursor = NULL;
00345 }
00346 FL_WARN(_log, "Cursor: No cursor matching cursor_id was found.");
00347 return;
00348 }
00349 #elif defined( WIN32 )
00350
00351 HCURSOR hIcon = LoadCursor(NULL, MAKEINTRESOURCE(cursor_id));
00352 if (hIcon == static_cast<HCURSOR>(0)) {
00353 if (m_native_cursor != NULL) {
00354 SDL_FreeCursor(m_native_cursor);
00355 m_native_cursor = NULL;
00356 }
00357 FL_WARN(_log, "Cursor: No cursor matching cursor_id was found.");
00358 return;
00359 }
00360 #endif
00361
00362 WMcursor *cursor;
00363 SDL_Cursor *curs2;
00364
00365
00366 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
00367 curs2 = (SDL_Cursor *)SDL_malloc(sizeof *curs2);
00368
00369
00370 curs2->wm_cursor = cursor;
00371 curs2->data = NULL;
00372 curs2->mask = NULL;
00373 curs2->save[0] = NULL;
00374 curs2->save[1] = NULL;
00375 curs2->area.x = 0;
00376 curs2->area.y = 0;
00377 curs2->area.w = 32;
00378 curs2->area.h = 32;
00379 curs2->hot_x = 0;
00380 curs2->hot_y = 0;
00381
00382 #if defined(WIN32)
00383 cursor->curs = hIcon;
00384 #ifndef _WIN32_WCE
00385 cursor->ands = NULL;
00386 cursor->xors = NULL;
00387 #endif
00388
00389
00390 ICONINFO iconinfo;
00391 if (GetIconInfo(hIcon, &iconinfo)) {
00392 curs2->hot_x = static_cast<Sint16>(iconinfo.xHotspot);
00393 curs2->hot_y = static_cast<Sint16>(iconinfo.yHotspot);
00394 }
00395
00396 #elif defined(__unix__)
00397 cursor->x_cursor = xCursor;
00398 XSync(dsp, false);
00399 #endif
00400
00401 m_native_cursor = curs2;
00402 SDL_SetCursor(curs2);
00403
00404 #endif // WIN32 || __unix__
00405 }
00406 }