00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "Core/precomp.h"
00016
00017 #ifdef USE_X11
00018
00019 #include <API/Application/clanapp.h>
00020 #include <API/Core/System/error.h>
00021 #include <API/Core/System/cl_assert.h>
00022 #include <API/Display/Display/palette.h>
00023 #include <Display/Display/X11/target_ximage.h>
00024 #include <Display/Display/X11/target_ximage_shm.h>
00025 #include <Display/Display/X11/target_ximage_std.h>
00026 #include <API/Display/Display/vidmode.h>
00027 #include <API/Core/Math/rect.h>
00028 #include <Display/Display/X11/display_xwindow.h>
00029 #include <Display/Display/X11/display_xwindow.h>
00030
00031 CL_Signal_v1<XEvent&> CL_XWindow_CompatibleCard::sig_xevent;
00032
00033
00034
00035 CL_XWindow_DisplayCard::CL_XWindow_DisplayCard(
00036 Display *dpy,
00037 Window root,
00038 int card_no)
00039 : CL_XWindow_CompatibleCard(card_no), resolution(dpy, DefaultScreen(dpy))
00040 {
00041 m_initialized = false;
00042 m_dpy = dpy;
00043 m_root = root;
00044 m_win = 0;
00045 m_gc = 0;
00046
00047 m_scr = DefaultScreen(m_dpy);
00048
00049 cl_assert(XMatchVisualInfo(dpy, m_scr, DefaultDepth(dpy,m_scr), TrueColor, &m_visual_info));
00050 m_palette = new CL_Palette();
00051 m_target = NULL;
00052 m_target_front = NULL;
00053
00054 slot_resize = get_sig_resize().connect(CL_CreateSlot(this, &CL_XWindow_DisplayCard::on_resize));
00055 }
00056
00057 CL_XWindow_DisplayCard::~CL_XWindow_DisplayCard()
00058 {
00059 if (m_initialized)
00060 {
00061
00062 delete m_target;
00063 delete m_target_front;
00064 XFreeGC(m_dpy, m_gc);
00065 XDestroyWindow(m_dpy, m_win);
00066 }
00067
00068 delete m_palette;
00069 }
00070
00071 void CL_XWindow_DisplayCard::keep_alive()
00072 {
00073 XEvent event;
00074
00075
00076 bool do_resize = false;
00077 int new_width = 0, new_height = 0;
00078
00079 for (int i=XPending(m_dpy); i>0; i--)
00080 {
00081 XNextEvent(m_dpy, &event);
00082
00083 switch (event.type)
00084 {
00085 case DestroyNotify:
00086 break;
00087
00088 case ConfigureNotify:
00089 do_resize = true;
00090 new_width = event.xconfigure.width;
00091 new_height = event.xconfigure.height;
00092 break;
00093
00094 case Expose:
00095 get_sig_paint()(
00096 CL_Rect(
00097 event.xexpose.x,
00098 event.xexpose.y,
00099 event.xexpose.x + event.xexpose.width,
00100 event.xexpose.y + event.xexpose.height));
00101 break;
00102 }
00103
00104 sig_xevent(event);
00105 }
00106
00107 if (do_resize)
00108 {
00109 set_resize(new_width, new_height);
00110 }
00111 }
00112
00113 void CL_XWindow_DisplayCard::on_resize(int width, int height)
00114 {
00115 delete m_target; m_target = NULL;
00116 delete m_target_front; m_target_front = NULL;
00117
00118 create_target();
00119 }
00120
00121 void CL_XWindow_DisplayCard::flip_display(bool sync)
00122 {
00123 cl_assert(m_initialized);
00124
00125 signal_preflip();
00126
00127
00128 if (sync) XSync(m_dpy, false);
00129
00130 int x = 0;
00131 int y = 0;
00132
00133 if (is_fullscreen())
00134 {
00135 x = win_width/2 - get_width()/2;
00136 y = win_height/2 - get_height()/2;
00137 }
00138
00139 m_target->put_image(x, y, m_win, m_gc);
00140 CL_Target_XImage *t = m_target;
00141 m_target = m_target_front;
00142 m_target_front = t;
00143
00144 XFlush(m_dpy);
00145
00146 signal_postflip();
00147 }
00148
00149 void CL_XWindow_DisplayCard::put_display(const class CL_Rect &rect)
00150 {
00151 cl_assert(m_initialized);
00152
00153 signal_preflip();
00154
00155 int x = 0;
00156 int y = 0;
00157
00158 if (is_fullscreen())
00159 {
00160 x = win_width/2 - get_width()/2;
00161 y = win_height/2 - get_height()/2;
00162 }
00163
00164 m_target->put_image(x, y, rect, m_win, m_gc);
00165
00166 XFlush(m_dpy);
00167
00168 signal_postflip();
00169 }
00170
00171 void CL_XWindow_DisplayCard::set_palette(CL_Palette *pal)
00172 {
00173 m_palette = new CL_Palette(pal->palette);
00174 }
00175
00176 CL_Palette *CL_XWindow_DisplayCard::get_palette()
00177 {
00178 return m_palette;
00179 }
00180
00181 void CL_XWindow_DisplayCard::set_videomode(
00182 int width,
00183 int height,
00184 int bpp,
00185 bool fullscreen,
00186 bool allow_resize,
00187 bool video_memory)
00188 {
00189 this->fullscreen = fullscreen;
00190 if (m_initialized)
00191 {
00192 delete m_target; m_target = NULL;
00193 delete m_target_front; m_target_front = NULL;
00194 XFreeGC(m_dpy, m_gc);
00195 XDestroyWindow(m_dpy, m_win);
00196 m_win = 0;
00197 }
00198 set_gfxmode(width, height, bpp, fullscreen, allow_resize);
00199
00200
00201 XSetWindowAttributes attr;
00202 attr.override_redirect = False;
00203
00204 attr.event_mask =
00205 KeyPressMask|KeyReleaseMask|
00206 ButtonPressMask|ButtonReleaseMask|
00207 EnterWindowMask|LeaveWindowMask|
00208 PointerMotionMask|
00209 StructureNotifyMask|
00210 ExposureMask;
00211
00212
00213 attr.backing_store = Always;
00214 int attr_flags =
00215 CWOverrideRedirect |
00216 CWEventMask;
00217
00218
00219
00220
00221
00222 win_width = width;
00223 win_height = height;
00224 if (fullscreen)
00225 {
00226 resolution.set_mode(width, height);
00227 win_width = resolution.get_width();
00228 win_height = resolution.get_height();
00229 attr.override_redirect = True;
00230 }
00231
00232
00233 m_win = XCreateWindow(
00234 m_dpy,
00235 m_root,
00236 0,
00237 0,
00238 win_width,
00239 win_height,
00240 0,
00241 CopyFromParent,
00242 CopyFromParent,
00243 m_visual_info.visual,
00244 attr_flags,
00245 &attr);
00246
00247 cl_assert(m_win);
00248
00249 char *title = CL_ClanApplication::app->get_title();
00250
00251 XTextProperty text_property;
00252 XStringListToTextProperty(&title, 1, &text_property);
00253 XSizeHints size_hints;
00254 size_hints.x = 0;
00255 size_hints.y = 0;
00256 size_hints.width = win_width;
00257 size_hints.height = win_height;
00258 size_hints.flags = PSize;
00259 if (!allow_resize) size_hints.flags |= PMinSize | PMaxSize;
00260 size_hints.min_width = win_width;
00261 size_hints.min_height = win_height;
00262 size_hints.max_width = win_width;
00263 size_hints.max_height = win_height;
00264
00265 XSetWMProperties(
00266 m_dpy,
00267 m_win,
00268 &text_property,
00269 &text_property,
00270 0,
00271 0,
00272 &size_hints,
00273 0,
00274 0);
00275
00276
00277 XMapRaised(m_dpy, m_win);
00278
00279 if (fullscreen)
00280 {
00281 XSetInputFocus(m_dpy, m_win, RevertToParent, CurrentTime);
00282 XGrabPointer(m_dpy, m_win, true, 0, GrabModeAsync, GrabModeAsync, m_win, None, CurrentTime);
00283 }
00284
00285 m_target = create_target();
00286 m_gc = XCreateGC(m_dpy, m_win, 0, 0);
00287
00288
00289
00290
00291 m_initialized = true;
00292 }
00293
00294 CL_Target_XImage *CL_XWindow_DisplayCard::create_target()
00295 {
00296 try
00297 {
00298 m_target = new CL_Target_XImage_Shm(
00299 m_visual_info,
00300 m_dpy,
00301 get_width(),
00302 get_height());
00303
00304 m_target_front = new CL_Target_XImage_Shm(
00305 m_visual_info,
00306 m_dpy,
00307 get_width(),
00308 get_height());
00309
00310 return m_target;
00311 }
00312 catch (CL_Error err)
00313 {
00314 static bool warning = true;
00315 if (warning)
00316 {
00317 cl_info(info_display, "X11 Implementation: Fallback to normal XImages. This will be horribly slow!");
00318 warning = false;
00319 }
00320
00321 m_target = new CL_Target_XImage_Std(
00322 m_visual_info,
00323 m_dpy,
00324 get_width(),
00325 get_height());
00326
00327 m_target_front = new CL_Target_XImage_Std(
00328 m_visual_info,
00329 m_dpy,
00330 get_width(),
00331 get_height());
00332
00333 return m_target;
00334 }
00335 }
00336
00337 bool CL_XWindow_DisplayCard::is_initialized()
00338 {
00339 return m_initialized;
00340 }
00341
00342 #ifdef USE_VIDMODE
00343
00344 static int cmpmodes(const void *va, const void *vb)
00345 {
00346 XF86VidModeModeInfo *a = *(XF86VidModeModeInfo**)va;
00347 XF86VidModeModeInfo *b = *(XF86VidModeModeInfo**)vb;
00348 if(a->hdisplay > b->hdisplay)
00349 return -1;
00350 return b->vdisplay - a->vdisplay;
00351 }
00352 #endif
00353
00354 void CL_XWindow_CompatibleCard::fill_modelist()
00355 {
00356 if (modelist.empty())
00357 {
00358 #ifdef USE_VIDMODE
00359 int vm_event, vm_error;
00360 int major_version, minor_version;
00361 int nmodes;
00362 XF86VidModeModeInfo **modes;
00363
00364
00365 if (XF86VidModeQueryExtension(get_display(), &vm_event, &vm_error) &&
00366 XF86VidModeQueryVersion(get_display(), &major_version, &minor_version) &&
00367 XF86VidModeGetAllModeLines(get_display(), DefaultScreen(get_display()),&nmodes,&modes) )
00368 {
00369 qsort(modes, nmodes, sizeof *modes, cmpmodes);
00370
00371 for (int i=0; i<nmodes; ++i )
00372 {
00373 CL_VidMode* mode = new CL_VidMode(modes[i]->hdisplay, modes[i]->vdisplay, 0);
00374 modelist.push_back(mode);
00375 }
00376
00377 XFree(modes);
00378 }
00379 #endif
00380 CL_VidMode* mode = new CL_VidMode(
00381 DisplayWidth(get_display(), DefaultScreen(get_display())),
00382 DisplayHeight(get_display(), DefaultScreen(get_display())),
00383 0);
00384 modelist.push_back(mode);
00385 #ifdef DEBUG
00386 #ifdef USE_VIDMODE
00387 cout << "XFree86 VidMode is enabled" << endl;
00388 #endif
00389 for (std::list<CL_VidMode*>::iterator it = modelist.begin(); it != modelist.end(); it++)
00390 cout << (*it)->width << "x" << (*it)->height << endl;
00391 #endif
00392 }
00393 }
00394
00395 void CL_XWindow_CompatibleCard::get_real_resolution(int* w, int* h)
00396 {
00397 #ifdef USE_VIDMODE
00398 XF86VidModeModeLine mode;
00399 int unused;
00400
00401 if ( XF86VidModeGetModeLine(get_display(), DefaultScreen(get_display()), &unused, &mode) )
00402 {
00403 *w = mode.hdisplay;
00404 *h = mode.vdisplay;
00405 return;
00406 }
00407 #endif
00408 *w = DisplayWidth(get_display(), DefaultScreen(get_display()));
00409 *h = DisplayHeight(get_display(), DefaultScreen(get_display()));
00410 }
00411
00412 #endif