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 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
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
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;
00176 case NC_IBEAM:
00177 return 32513;
00178 case NC_WAIT:
00179 return 32514;
00180 case NC_CROSS:
00181 return 32515;
00182 case NC_UPARROW:
00183 return 32516;
00184 case NC_RESIZESE:
00185 return 32642;
00186 case NC_RESIZESW:
00187 return 32643;
00188 case NC_RESIZEE:
00189 return 32644;
00190 case NC_RESIZES:
00191 return 32645;
00192 case NC_RESIZENW:
00193 return 32642;
00194 case NC_RESIZENE:
00195 return 32643;
00196 case NC_RESIZEW:
00197 return 32644;
00198 case NC_RESIZEN:
00199 return 32645;
00200 case NC_RESIZEALL:
00201 return 32646;
00202 case NC_NO:
00203 return 32648;
00204 case NC_HAND:
00205 return 32649;
00206 case NC_APPSTARTING:
00207 return 32650;
00208 case NC_HELP:
00209 return 32651;
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
00262 cursor_id = getNativeId(cursor_id);
00263
00264
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
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
00293 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor));
00294 curs2 = (SDL_Cursor *)SDL_malloc(sizeof *curs2);
00295
00296
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
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 }