00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "Core/precomp.h"
00016
00017 #ifdef BORLAND
00018 #pragma hdrstop
00019 #endif
00020
00021 #include "mousecursor_generic.h"
00022 #include "API/Display/Display/display.h"
00023 #include "API/Core/System/system.h"
00024 #include "API/Display/Input/mouse.h"
00025 #include "surface_generic.h"
00026
00027
00028
00029
00030
00031 void CL_MouseCursor::set_cursor(
00032 CL_MouseCursorProvider *provider,
00033 int frame)
00034 {
00035 CL_MouseCursor_Generic::m_instance.set_cursor(provider, frame);
00036 }
00037
00038 void CL_MouseCursor::show(bool show_async)
00039 {
00040 CL_MouseCursor_Generic::m_instance.show(show_async);
00041 }
00042
00043 void CL_MouseCursor::hide()
00044 {
00045 CL_MouseCursor_Generic::m_instance.hide();
00046 }
00047
00048
00049
00050
00051 CL_MouseCursor_Generic CL_MouseCursor_Generic::m_instance;
00052
00053 CL_MouseCursor_Generic::CL_MouseCursor_Generic() : m_rect(0,0,0,0)
00054 {
00055 m_buffer = NULL;
00056 m_provider = NULL;
00057 m_cursor = NULL;
00058 m_cur_frame = 0;
00059 m_frame_timer = 0;
00060 m_mux = CL_Mutex::create();
00061 m_thread = NULL;
00062 m_callback_added = false;
00063 m_last_x = m_last_y = -1;
00064 }
00065
00066 CL_MouseCursor_Generic::~CL_MouseCursor_Generic()
00067 {
00068 delete[] m_buffer;
00069 delete m_mux;
00070 delete m_thread;
00071 }
00072
00073 void CL_MouseCursor_Generic::run()
00074 {
00075 while (true)
00076 {
00077 m_mux->enter();
00078
00079 if (m_provider != NULL)
00080 {
00081 CL_Target *target = ((CL_DisplayCard_Generic *) CL_Display::get_current_card())->get_frontbuffer();
00082 show_cursor(target, true);
00083 }
00084 m_mux->leave();
00085
00086 CL_System::sleep(20);
00087 }
00088 }
00089
00090 void CL_MouseCursor_Generic::pre_flip()
00091 {
00092 m_mux->enter();
00093
00094 if (m_visible && m_provider != NULL)
00095 {
00096 show_cursor(((CL_DisplayCard_Generic *) CL_Display::get_current_card())->get_target(), false);
00097 }
00098 else
00099 {
00100 invalidate_region();
00101 }
00102
00103
00104 }
00105
00106 void CL_MouseCursor_Generic::post_flip()
00107 {
00108 m_mux->leave();
00109 }
00110
00111 void CL_MouseCursor_Generic::show_cursor(CL_Target *dest, bool load_saved)
00112 {
00113 if (!load_saved)
00114 {
00115 invalidate_region();
00116 }
00117 int mouse_x = CL_Mouse::get_x();
00118 int mouse_y = CL_Mouse::get_y();
00119
00120 int x1 = mouse_x+m_provider->get_surface_provider()->get_translate_x();
00121 int y1 = mouse_y+m_provider->get_surface_provider()->get_translate_y();
00122 if (load_saved && (x1 != m_last_x || y1 != m_last_y))
00123 {
00124 load_region(dest);
00125 }
00126 m_last_x = x1;
00127 m_last_y = y1;
00128
00129 if (m_provider->is_animated() && CL_System::get_time() >= m_frame_timer)
00130 {
00131 m_cur_frame = (m_cur_frame+1) % m_provider->get_surface_provider()->get_num_frames();
00132 int next_frame = m_provider->get_frame_delay(m_cur_frame);
00133 if (next_frame == -1) next_frame = 100;
00134 m_frame_timer = CL_System::get_time() + next_frame;
00135 }
00136
00137 CL_ClipRect r(
00138 x1,
00139 y1,
00140 x1+m_provider->get_surface_provider()->get_width(),
00141 y1+m_provider->get_surface_provider()->get_height());
00142 CL_ClipRect scr_r = r.clip(CL_Display::get_current_card()->get_clip_rect());
00143 if (scr_r.m_x1 < scr_r.m_x2 && scr_r.m_y1 < scr_r.m_y2)
00144 {
00145 save_region(dest, scr_r);
00146 m_cursor->impl->get_cardsurface(
00147 CL_Display::get_current_card())->put_screen(
00148 x1, y1, m_cur_frame, dest);
00149 }
00150 else
00151 {
00152 invalidate_region();
00153 }
00154 }
00155
00156 void CL_MouseCursor_Generic::set_cursor(
00157 CL_MouseCursorProvider *provider,
00158 int frame)
00159 {
00160 m_mux->enter();
00161 if (m_provider != NULL)
00162 {
00163 m_provider->get_surface_provider()->unlock();
00164 delete m_cursor;
00165 }
00166 if (m_cursor != NULL)
00167 {
00168
00169 m_cursor = NULL;
00170 }
00171
00172 m_provider = provider;
00173 if (m_provider != NULL)
00174 {
00175 m_provider->get_surface_provider()->lock();
00176 m_cursor = CL_Surface::create(m_provider->get_surface_provider(), false);
00177 m_cur_frame = frame;
00178
00179 if (m_cur_frame >= provider->get_surface_provider()->get_num_frames())
00180 {
00181 m_cur_frame = provider->get_surface_provider()->get_num_frames()-1;
00182 }
00183 if (!m_callback_added)
00184 {
00185 ((CL_DisplayCard_Generic *) CL_Display::get_current_card())->add_callback(this);
00186 m_callback_added = true;
00187 }
00188 show(true);
00189 }
00190 m_mux->leave();
00191
00192 if (m_provider == NULL && m_visible)
00193 {
00194 CL_DisplayCard_Generic *card = (CL_DisplayCard_Generic *) CL_Display::get_current_card();
00195 card->show_system_cursor();
00196 }
00197 else if (m_provider != NULL && m_visible)
00198 {
00199 CL_DisplayCard_Generic *card = (CL_DisplayCard_Generic *) CL_Display::get_current_card();
00200 card->hide_system_cursor();
00201 }
00202 }
00203
00204 void CL_MouseCursor_Generic::show(bool show_async)
00205 {
00206 m_async = show_async;
00207 m_visible = true;
00208
00209 if (m_cursor == NULL)
00210 {
00211 CL_DisplayCard_Generic *card = (CL_DisplayCard_Generic *) CL_Display::get_current_card();
00212 card->show_system_cursor();
00213 return;
00214 }
00215
00216 if (m_thread == NULL)
00217 {
00218 m_thread = CL_Thread::create(this);
00219 m_thread->start();
00220 }
00221 }
00222
00223 void CL_MouseCursor_Generic::hide()
00224 {
00225 CL_DisplayCard_Generic *card = (CL_DisplayCard_Generic *) CL_Display::get_current_card();
00226 card->hide_system_cursor();
00227
00228 m_mux->enter();
00229 m_visible = false;
00230 delete m_thread;
00231 m_thread = NULL;
00232 invalidate_region();
00233 m_mux->leave();
00234 }
00235
00236 void CL_MouseCursor_Generic::invalidate_region()
00237 {
00238 delete[] m_buffer;
00239 m_buffer = NULL;
00240 m_rect = CL_ClipRect(0,0,0,0);
00241 }
00242
00243 void CL_MouseCursor_Generic::save_region(CL_Target *source, const CL_ClipRect &r)
00244 {
00245 if (source == NULL) return;
00246
00247 source->lock();
00248
00249 if ((m_rect.m_x2-m_rect.m_x1) != (r.m_x2-r.m_x1) ||
00250 (m_rect.m_y2-m_rect.m_y1) != (r.m_y2-r.m_y1))
00251 {
00252 delete[] m_buffer;
00253 m_buffer = new unsigned char[
00254 (r.m_x2-r.m_x1)*
00255 (r.m_y2-r.m_y1)*
00256 source->get_bytes_per_pixel()];
00257 }
00258
00259 int dest_pitch = (r.m_x2-r.m_x1)*source->get_bytes_per_pixel();
00260 unsigned char *dest_ptr = m_buffer;
00261 unsigned char *src_ptr = &((unsigned char *) source->get_data())[
00262 r.m_y1*source->get_pitch()+
00263 r.m_x1*source->get_bytes_per_pixel()];
00264 for (int y=r.m_y1;y<r.m_y2;y++)
00265 {
00266 memcpy(
00267 dest_ptr,
00268 src_ptr,
00269 dest_pitch);
00270 dest_ptr += dest_pitch;
00271 src_ptr += source->get_pitch();
00272 }
00273
00274 m_rect = r;
00275
00276 source->unlock();
00277 }
00278
00279 void CL_MouseCursor_Generic::load_region(CL_Target *dest)
00280 {
00281 if (dest == NULL || m_buffer == NULL) return;
00282
00283 dest->lock();
00284
00285 int src_pitch = (m_rect.m_x2-m_rect.m_x1)*dest->get_bytes_per_pixel();
00286 unsigned char *src_ptr = m_buffer;
00287 unsigned char *dest_ptr = &((unsigned char *) dest->get_data())[
00288 m_rect.m_y1*dest->get_pitch()+
00289 m_rect.m_x1*dest->get_bytes_per_pixel()];
00290 for (int y=m_rect.m_y1;y<m_rect.m_y2;y++)
00291 {
00292 memcpy(
00293 dest_ptr,
00294 src_ptr,
00295 src_pitch);
00296 src_ptr += src_pitch;
00297 dest_ptr += dest->get_pitch();
00298 }
00299
00300 dest->unlock();
00301 }