Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

display_xwindow.cpp

Go to the documentation of this file.
00001 /*
00002         $Id: display_xwindow.cpp,v 1.2 2001/03/15 12:14:46 mbn Exp $
00003 
00004         ------------------------------------------------------------------------
00005         ClanLib, the platform independent game SDK.
00006 
00007         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00008         version 2. See COPYING for details.
00009 
00010         For a total list of contributers see CREDITS.
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 // CL_XWindow_DisplayCard
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 //      m_visual_info = DefaultVisual(dpy, m_scr);
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                 // BUGBUG: What about the visual, context and buffer - should they be deleted?
00062                 delete m_target;
00063                 delete m_target_front;
00064                 XFreeGC(m_dpy, m_gc);
00065                 XDestroyWindow(m_dpy, m_win);
00066         }
00067 //      XFreeColormap(m_dpy, m_color_map);
00068         delete m_palette;
00069 }
00070 
00071 void CL_XWindow_DisplayCard::keep_alive()
00072 {
00073         XEvent event;
00074         
00075         // we try to minize the amounts of exposures to speed up repainting of the window.
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); // card not initialized!
00124         
00125         signal_preflip();
00126 
00127         // New tactic - sync before putscreen
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) // clean up
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         /* set window attributes */
00201         XSetWindowAttributes attr;
00202         attr.override_redirect = False;
00203 //      attr.colormap = m_color_map;
00204         attr.event_mask =
00205                 KeyPressMask|KeyReleaseMask|
00206                 ButtonPressMask|ButtonReleaseMask|
00207                 EnterWindowMask|LeaveWindowMask|
00208                 PointerMotionMask|
00209                 StructureNotifyMask|
00210                 ExposureMask;
00211 //      attr.border_pixel = BlackPixel(m_dpy, m_scr);
00212 //      attr.background_pixel = BlackPixel(m_dpy, m_scr);
00213         attr.backing_store = Always;
00214         int attr_flags =
00215                 CWOverrideRedirect |
00216                 CWEventMask;
00217 //              CWColormap |
00218 //              CWBorderPixel |
00219 //              CWBackPixel |
00220 //              CWBackingStore;
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         /* Create the window */
00233         m_win = XCreateWindow(
00234                 m_dpy,
00235                 m_root,
00236                 0,
00237                 0,
00238                 win_width,
00239                 win_height,
00240                 0,
00241                 CopyFromParent, // m_visual_info.depth,
00242                 CopyFromParent, // m_visual_info.c_class
00243                 m_visual_info.visual,
00244                 attr_flags,
00245                 &attr);
00246 
00247         cl_assert(m_win); // failed to create window!
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 //      size_hints.flags |= USPosition | USSize;
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 //      XMapWindow(m_dpy, m_win);
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         // Listen for keystrokes...
00289 //      XSelectInput(m_dpy, m_win, KeyPressMask|KeyReleaseMask);
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 // needed by qsort
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                 /* Enumerate the available fullscreen modes */
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 /* USE_VIDMODE */
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 /* DEBUG */
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

Generated at Wed Apr 4 19:54:00 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001