Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phX11Util.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #include <phStandard.h>
00031 
00032 #include <phImage.h>
00033 #include <phX11Util.h>
00034 
00035 /* ------------------------------------------------------------------------- */
00036 /* GUI TK header files here */
00037 /* ------------------------------------------------------------------------- */
00038 #include <X11/Xlib.h>
00039 #include <X11/Xutil.h>
00040 #include <X11/keysym.h>
00041 #include <X11/Xatom.h>
00042 
00043 /* ------------------------------------------------------------------------- */
00044 /* 2.) Optional GUI TK features here */
00045 /* ------------------------------------------------------------------------- */
00046 #ifdef HAVE_X11_EXTENSIONS_XSHM
00047     #define USE_SHARED_MEM() 1
00048 #else
00049     #define USE_SHARED_MEM() 0
00050 #endif
00051 
00052 /* ------------------------------------------------------------------------- */
00053 #ifdef HAVE_X11_EXTENSIONS_XDBE
00054     #define USE_DOUBLEBUFFER_EXT() 1
00055 #else
00056     #define USE_DOUBLEBUFFER_EXT() 0
00057 #endif
00058 
00059 /* ------------------------------------------------------------------------- */
00060 /* leave as zero, support unfinished */
00061 #ifdef HAVE_X11_EXTENSIONS_XF86DGA
00062 #define USE_DGA() 0
00063 #else
00064 #define USE_DGA() 0
00065 #endif
00066 
00067 #ifdef HAVE_X11_EXTENSIONS_XVLIB
00068 #define USE_XV() 0
00069 #else
00070 #define USE_XV() 0
00071 #endif
00072 
00073 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE
00074 #define USE_XF86SYNC() 0
00075 #else
00076 #define USE_XF86SYNC() 0
00077 #endif
00078 
00079 /* ------------------------------------------------------------------------- */
00080 #if USE_SHARED_MEM()
00081 #include <sys/ipc.h>
00082 #include <sys/shm.h>
00083 #include <X11/extensions/XShm.h>
00084 #endif
00085 
00086 #if USE_DOUBLEBUFFER_EXT()
00087 #include <X11/extensions/Xdbe.h>
00088 #endif
00089 
00090 #if USE_DGA()
00091 #include <X11/extensions/xf86dga.h>
00092 #endif
00093 
00094 #if USE_XV()
00095 #include <X11/extensions/Xvlib.h>
00096 #endif
00097 
00098 #if USE_XF86SYNC()
00099 #include <X11/extensions/xf86vmode.h>
00100 #endif
00101 
00102 #include <phError.h>
00103 #include <phMemory.h>
00104 #include <phPrint.h>
00105 
00106 /* ------------------------------------------------------------------------- */
00107 #ifdef __cplusplus
00108 extern "C" 
00109 {
00110 #endif
00111 
00112 /* ------------------------------------------------------------------------- */
00113 typedef struct phX11DisplayInfo_t   *phX11DisplayInfo;
00114 struct phX11DisplayInfo_t
00115 {
00116     char        *name;
00117    
00118     Display     *display;
00119     
00120     int         screen_number;
00121     int         screen_height;
00122     int         screen_width;
00123     long        black_pixel;
00124     long        white_pixel;
00125     Window      root_window;
00126     Visual      *visual;
00127     int         depth;
00128 
00129 };
00130 
00131 /* ------------------------------------------------------------------------- */
00132 struct phX11EventAtom_t
00133 {
00134     /* All the necesary details to identify this atom and compare it */
00135     Atom                atom;
00136     char               *name;
00137     uint32_t            name_length;
00138     uint32_t            name_mem_length;
00139 
00140     /* a send/post-able event structure which identifies this atom */
00141     XEvent              event;
00142     
00143     /* The display the atom was created on */
00144     Display            *display;
00145 
00146     /* Windows for which this event will accept events.
00147      * The event atom is bound to these windows */
00148     uint32_t           num_windows;
00149     Window             *windows;
00150 };
00151 
00152 /* ------------------------------------------------------------------------- */
00153 struct phX11EventInfo_t
00154 {
00155     XEvent event;
00156 };
00157 
00158 /* ------------------------------------------------------------------------- */
00159 struct phX11WindowInfo_t
00160 {
00161     struct phX11DisplayInfo_t  display_info;
00162 
00163     Display            *display;
00164     int                 screen_number;
00165     int                 depth;
00166     
00167     int32_t             red_mask;
00168     int32_t             red_shift;
00169     int32_t             green_mask;
00170     int32_t             green_shift;
00171     int32_t             blue_mask;
00172     int32_t             blue_shift;
00173 
00174     Window              base_window;
00175     Window              image_window;
00176 
00177     int32_t             x;
00178     int32_t             y;
00179     
00180     uint32_t            width;
00181     uint32_t            height;
00182     
00183     int                 is_visible;
00184     int                 is_open;
00185     
00186     GC                  gc;
00187     XGCValues           gc_vals;
00188     Drawable            drawable;
00189     XSizeHints         *hints;
00190 
00191     int                 use_xdbe;
00192 #if USE_DOUBLEBUFFER_EXT()
00193     XdbeBackBuffer      back_buffer;
00194     XdbeSwapInfo        swap_info;
00195 #endif
00196  
00197     /* Event Stuff */
00198     long                image_event_mask;
00199     long                base_event_mask;
00200     
00201     Atom                WM_DELETE_WINDOW;
00202 
00203     uint32_t                num_event_atoms;
00204     struct phX11EventAtom_t **event_atoms;
00205 };
00206 
00207 /* ------------------------------------------------------------------------- */
00208 struct phX11ImageInfo_t
00209 {
00210     Display     *display;
00211     
00212     int         nBuffers;
00213     int         bufIndex;
00214 
00215     uint32_t    width;
00216     uint32_t    height;
00217     uint32_t    in_dbytes;     /* in bytes */
00218     uint32_t    in_dbits;      /* in bits */
00219     uint32_t    out_dbytes;    /* in bytes */
00220     uint32_t    out_dbits;     /* in bits */
00221     uint32_t    window_dbits;     /* in bits */
00222     
00223     int32_t     in_ri;
00224     int32_t     in_gi;
00225     int32_t     in_bi;
00226     
00227     int32_t     red_mask;
00228     int32_t     red_shift;
00229     int32_t     green_mask;
00230     int32_t     green_shift;
00231     int32_t     blue_mask;
00232     int32_t     blue_shift;
00233     
00234     /* Data is copied here first then passed to XPutImage */
00235     char        **repack_buffer;
00236     uint32_t    repack_buffer_size;
00237     
00238     /* The _size array and vars are used for phDALLOC */
00239     uint32_t    *repack_buffer_sizes;
00240     uint32_t    repack_buffer_sizes_memsize;
00241     
00242     XImage      **image_array;
00243     uint32_t    image_array_memsize;
00244     
00245     int             use_shared_mem;
00246 #if USE_SHARED_MEM()   
00247     XShmSegmentInfo shm_info;
00248     int             refresh_wait;
00249 #endif
00250 
00251 };
00252 
00253 
00254 /* ------------------------------------------------------------------------- */
00255 /* Prototypes that aren't exported in the header file */
00256 /* ------------------------------------------------------------------------- */
00257 inline static void phX11_Align_8bitmask( int32_t *mask, int32_t *shift );
00258 
00259 /* This prints the information contained within a Visual structure */
00260 #if 0
00261 static void phX11Visual_Print   ( Visual *visual );
00262 #endif
00263 /* These are used to assign error handlers for the X11 System */
00264 static int phX11_ErrorHandler   ( Display *display, 
00265                                   XErrorEvent *e );
00266 static int phX11_IOHandler      ( Display *display );
00267     
00268 /* These are used to check for the availability of certain X11 extensions */
00269 static int phX11Check_XSHM      ( Display *display );
00270 #if USE_XF86SYNC()
00271 static int phX11Check_VM        ( Display *display );
00272 #endif
00273 static int phX11Check_XDBE      ( Display *display );
00274 static int phX11Check_XV        ( Display *display );
00275 #if 0
00276 static int phX11_XvPrintAdapters( Display *display,
00277                                   Window window    );
00278 #endif
00279 #if USE_DGA()
00280 static int phX11Check_XDGA      ( Display *display );
00281 #endif
00282     
00283 /* Display Utility functions */    
00284 static int phX11Display_Initialize  ( phX11DisplayInfo display_info );
00285 static int phX11Display_Deinitialize( phX11DisplayInfo display_info );
00286 
00287 /* ----------------------------------------------------------------------------
00288  * ------------------------------------------------------------------------- */
00289 #include <math.h>
00290 
00291 /* ------------------------------------------------------------------------- */
00292 inline static void phX11_Align_8bitmask( int32_t *mask, int32_t *shift )
00293 {
00294     /* prevent an infinite loop when mask has no bits */
00295     if (!*mask) return;
00296     
00297     /* Figure out how many bits it has to be shifted left to
00298      * realign it with the total bits available for the color depth */
00299     while (!((*mask) & 0x01)) {
00300         (*mask) >>= 1;
00301         (*shift)++;
00302     }
00303     /* Assume that the mask is used on the high order bits
00304      * of the color value and shift it back */
00305     while (!((*mask) & 0x80)) {
00306         (*mask) <<= 1;
00307         (*shift)--;
00308     }
00309 }
00310 
00311 /* ------------------------------------------------------------------------- */
00312 #if 0
00313 void phX11Visual_Print( Visual *visual )
00314 {
00315     if (visual != NULL)
00316     {
00317 #if 0
00318         printf("\nVisual {\n\tid:%u\n\tclass: %d\n",
00319                (uint8_t)visual->visualid,
00320                visual->c_class );
00321 #endif
00322         printf( "\trm: 0x%08lx gm: 0x%08lx: bm: 0x%08lx\n",
00323                visual->red_mask,
00324                visual->green_mask,
00325                visual->blue_mask );
00326         printf(" bprgb: %d\n\tmaps: %d\n\n",
00327                visual->bits_per_rgb,
00328                visual->map_entries );
00329         fflush(stdout);
00330     }
00331 }
00332 #endif
00333 
00334 /* ------------------------------------------------------------------------- */
00335 static int phX11_ErrorHandler( Display *display, XErrorEvent *e )
00336 {
00337     phFUNCTION("phX11_ErrorHandler")
00338 
00339     char errorText[1024];
00340     XGetErrorText( display, e->error_code, errorText, sizeof(errorText) );
00341 
00342     phERR_PRINT("X11 Error: %s\n", errorText );
00343 
00344     return -1;
00345 }
00346 
00347 /* ------------------------------------------------------------------------- */
00348 static int phX11_IOHandler( Display *d)
00349 {
00350     phFUNCTION("phX11_IOHandler")
00351 
00352     phERR_PRINT("X11 IO Error\n" );
00353     
00354     return 0;
00355 }
00356 
00357 /* ------------------------------------------------------------------------- */
00358 #define WARN_UNSUPPORTED() 0
00359 
00360 /* ------------------------------------------------------------------------- */
00361 static int phX11Check_XSHM( Display *display )
00362 {
00363     phFUNCTION("phX11Check_XSHM")
00364 
00365 #if USE_SHARED_MEM()
00366     int major = 0;
00367     int minor = 0;
00368     Bool sharedPixmaps;
00369     
00370     DEBUG_PRINT("Querying XSHM\n");
00371     /* Check to see if Double Buffer Extensionn is supported */
00372     if (XShmQueryExtension(display) == False) 
00373     {
00374         #if WARN_UNSUPPORTED()
00375         phCHECK_RC(-1,NULL,"XSHM not supported.\n");
00376         #else
00377         goto error;
00378         #endif
00379     }
00380     else
00381     {
00382         if (XShmQueryVersion(display,&major,&minor,&sharedPixmaps) != False)
00383         {
00384             DEBUG_PRINT("XSHM v%d.%d Shared Pixmaps: %s\n",
00385                         major,minor,(sharedPixmaps ? "yes" : "no"));
00386         }
00387         else
00388         {
00389             goto error;
00390         }
00391     }
00392 
00393     return 1;
00394 #endif
00395     
00396 error:
00397     return 0;
00398 }
00399 
00400 /* ------------------------------------------------------------------------- */
00401 static int phX11Check_XDBE( Display *display )
00402 {
00403     phFUNCTION("phX11Check_XDBE")
00404 
00405 #if USE_DOUBLEBUFFER_EXT()
00406     int dbe_version[2] = {0,0};
00407     
00408     DEBUG_PRINT("Querying XDBE\n");
00409     /* Check to see if Double Buffer Extensionn is supported */
00410     if (XdbeQueryExtension(display,
00411                            &(dbe_version[0]),&(dbe_version[1])) == False) 
00412     {
00413         #if WARN_UNSUPPORTED()
00414         phCHECK_RC(-1,NULL,"XDBE not supported.\n");
00415         #else
00416         goto error;
00417         #endif
00418     }
00419     else
00420     {
00421         DEBUG_PRINT("XDBE v%d.%d\n",
00422                     dbe_version[0],
00423                     dbe_version[1]);
00424     }
00425 
00426     return 1;
00427 #endif
00428     
00429 error:
00430     return 0;
00431 }
00432 
00433 /* ------------------------------------------------------------------------- */
00434 #if USE_XF86SYNC()
00435 static int phX11Check_VM( Display *display )
00436 {
00437     phFUNCTION("phX11Check_VM")
00438     
00439     int xf86vm_version[2] = {0,0};
00440  
00441     DEBUG_PRINT("Querying XF86VidMode\n");
00442     if (XF86VidModeQueryVersion(display, 
00443                                 &(xf86vm_version[0]), 
00444                                 &(xf86vm_version[1])) == False)
00445     {
00446         #if WARN_UNSUPPORTED()
00447         phCHECK_RC(-1,NULL,"XF86VidMode not supported.\n");
00448         #else
00449         goto error;
00450         #endif
00451     }
00452     else
00453     {
00454         DEBUG_PRINT("XF86VidMode v%d.%d\n",
00455                     xf86vm_version[0],
00456                     xf86vm_version[1]);
00457     }
00458 
00459     return 1;
00460     
00461 error:
00462     return 0;
00463 }
00464 #endif
00465 
00466 /* ------------------------------------------------------------------------- */
00467 static int phX11Check_XV( Display *display )
00468 {
00469 #if USE_XV()
00470     unsigned int xv_version[5] = {0,0,0,0,0};
00471 
00472     /*----------------------------------------------------------------------*
00473      XvQueryExtension(dpy, p_version, p_release,
00474            p_request_base, p_event_base, p_error_base)
00475 
00476         Display *dpy;
00477         unsigned int *p_version, *p_release;
00478         unsigned int *p_request_base, *p_event_base, *p_error_base;
00479     *-----------------------------------------------------------------------*/
00480     DEBUG_PRINT("Querying Xv\n");
00481     if (XvQueryExtension(display,
00482                          &(xv_version[0]),
00483                          &(xv_version[1]),
00484                          &(xv_version[2]),
00485                          &(xv_version[3]),
00486                          &(xv_version[4])) != Success)
00487     {
00488         #if WARN_UNSUPPORTED()
00489         phCHECK_RC(-1,NULL,"Xv not supported.\n");
00490         #else
00491         goto error;
00492         #endif
00493     }
00494     else
00495     {
00496         DEBUG_PRINT("Xv v%u.%u\n",
00497                     xv_version[0],
00498                     xv_version[1]);
00499     }
00500 
00501     return 1;
00502 
00503 error:
00504 #endif
00505     return 0;
00506 }
00507 
00508 /* ------------------------------------------------------------------------- */
00509 #if 0
00510 static int phX11_XvPrintAdapters( Display *display, Window window )
00511 {
00512 #if USE_XV()
00513     unsigned int num_adaptors   = 0;
00514     XvAdaptorInfo *adaptor_info = NULL;
00515     /*----------------------------------------------------------------------*/
00516     if ((rc = XvQueryAdaptors(display,window,
00517                     &num_adaptors,&adaptor_info)) != Success)
00518     {
00519         if (rc == XvBadExtension)
00520         {
00521             phCHECK_RC(-1,NULL,"XvQueryAdaptors returned XvBadExtension");
00522         }
00523         else if (rc == XvBadAlloc)
00524         {
00525             phCHECK_RC(-1,NULL,"XvQueryAdaptors returned XvBadAlloc");
00526         }
00527     }
00528 
00529     for (unsigned int i = 0; i < num_adaptors; i++)
00530     {
00531         DEBUG_PRINT("\nAdaptor %d {\n"
00532                     "\tbase_id      : 0x%08x\n"
00533                     "\tnum_ports    : %lu\n"
00534                     "\ttype         : %c\n"
00535                     "\tname         : %s\n"
00536                     "\tnum_adaptors : %lu\n"
00537                     "\tnum_formats  : %lu\n"
00538                     ,
00539                     i,
00540                     (unsigned int)adaptor_info[i].base_id,
00541                     adaptor_info[i].num_ports,
00542                     adaptor_info[i].type,
00543                     adaptor_info[i].name,
00544                     adaptor_info[i].num_formats,
00545                     adaptor_info[i].num_adaptors
00546                 );
00547         
00548         for (unsigned int j = 0; j < adaptor_info[i].num_formats; j++)
00549         {
00550             DEBUG_PRINT("\tFormat %d {\n"
00551                         "\t\tdepth      : %d\n"
00552                         "\t\tvisual_id  : %lu\n\t};\n",
00553                         j,
00554                         adaptor_info[i].formats[j].depth,
00555                         adaptor_info[i].formats[j].visual_id );
00556         }
00557         DEBUG_PRINT("};\n\n");
00558     }
00559 
00560     return phSUCCESS;
00561     
00562 error:
00563 #endif
00564     return phFAIL;
00565 }
00566 #endif
00567 
00568 /* ------------------------------------------------------------------------- */
00569 #if USE_DGA()
00570 static int phX11Check_XDGA( Display *display )
00571 {
00572     int xdga_errorBase  = 0;
00573     int xdga_eventBase  = 0;
00574     int xdga_version[2] = {0,0};
00575     
00576     DEBUG_PRINT("Querying XDGA\n");
00577     
00578     if (XDGAQueryExtension( display,
00579                             &xdga_eventBase,
00580                             &xdga_errorBase) == False)
00581     {
00582         #if WARN_UNSUPPORTED()
00583         phCHECK_RC(-1,NULL,"XDGA extension not supported.\n");
00584         #else
00585         goto error;
00586         #endif
00587     }
00588     else
00589     {
00590         DEBUG_PRINT("XDGA - eventBase:%d errorBase:%d\n",
00591                     xdga_eventBase,
00592                     xdga_errorBase  );
00593     }
00594     if (XDGAQueryVersion(display,
00595                          &(xdga_version[0]),
00596                          &(xdga_version[1])) == False)
00597     {
00598         #if WARN_UNSUPPORTED()
00599         phCHECK_RC(-1,NULL,"XDGA not supported.\n");
00600         #else
00601         goto error;
00602         #endif
00603     }
00604     else
00605     {
00606         DEBUG_PRINT("XDGA v%d.%d\n",
00607                     xdga_version[0],
00608                     xdga_version[1]);
00609     }
00610 
00611     return 1;
00612         
00613 error:
00614     return 0;
00615 }
00616 #endif
00617 
00618 /* ------------------------------------------------------------------------- */
00619 static int phX11Display_Initialize( struct phX11DisplayInfo_t *display_info )
00620 {
00621     phFUNCTION("phX11Display_Initialize")
00622 
00623     char    *display_name   = NULL;
00624     Display *display        = NULL;
00625     /* Visual  *visual         = NULL; */
00626     /* Status  initStat        = 0; */
00627     
00628     phCHECK_NULLPTR(display_info,NULL,"dispInfo pointer == NULL");
00629     
00630     memset(display_info,0,sizeof(struct phX11DisplayInfo_t));
00631    
00632     /* initStat = XInitThreads(); */
00633 
00634     /*  Get environmental variables */
00635     /* DISPLAY */
00636 
00637     DEBUG_PRINT("XDisplayName\n");
00638     display_name = XDisplayName(NULL);
00639     if (display_name == NULL)
00640     {
00641         display_name = "120.0.0.1:0.0";
00642     }
00643     
00644     display_info->name = (char *)phCalloc(strlen(display_name) + 2,
00645                                        sizeof(char));
00646     phCHECK_NULLPTR(display_info->name,"phCalloc","phCalloc failed.");
00647 
00648     sprintf(display_info->name,"%s",display_name);
00649     
00650     /* Open a connection to the X Server */
00651     /*------------------------------------------------------------------------
00652      * http://www.the-labs.com/X11/XLib-Manual/display/opening.html
00653      *------------------------------------------------------------------------
00654      Display *XOpenDisplay(display_name)
00655         char *display_name;
00656      *-----------------------------------------------------------------------*/
00657     DEBUG_PRINT("XOpenDisplay\n");
00658     display = display_info->display = XOpenDisplay(display_info->name);
00659     phCHECK_NULLPTR(display_info->display,NULL,"XOpenDisplay failed");
00660     
00661     /* XLockDisplay(display); */
00662     
00663     /* Set Synchronous mode */
00664     /*------------------------------------------------------------------------
00665      * http://x.holovko.ru/Xlib/chap11.html#11.8.1 
00666      *----------------------------------------------------------------------*/
00667     /* XSynchronize((*display),True); */
00668     
00669     /* Get the screen settings  */
00670     /*------------------------------------------------------------------------
00671      * http://www.the-labs.com/X11/XLib-Manual/display/display-macros.html 
00672      *----------------------------------------------------------------------*/
00673     display_info->screen_number = DefaultScreen(display);
00674     
00675     display_info->screen_width = 
00676         DisplayWidth( display, display_info->screen_number );
00677     
00678     display_info->screen_height = 
00679         DisplayHeight( display, display_info->screen_number );
00680     
00681     display_info->black_pixel = 
00682         BlackPixel( display, display_info->screen_number );
00683     
00684     display_info->white_pixel = 
00685         WhitePixel( display, display_info->screen_number );
00686     
00687     display_info->root_window = 
00688         RootWindow( display, display_info->screen_number );
00689     
00690     display_info->visual = 
00691         XDefaultVisual( display, display_info->screen_number );
00692 
00693     display_info->depth = 
00694         DefaultDepth( display, display_info->screen_number );
00695     
00696     /* Set the error handler [2] */
00697     DEBUG_PRINT("XSetErrorHandler\n");
00698     XSetErrorHandler    ( phX11_ErrorHandler    );
00699     DEBUG_PRINT("XSetIOErrorHandler\n");
00700     XSetIOErrorHandler  ( phX11_IOHandler       );
00701 
00702     /* XUnlockDisplay(display); */
00703     
00704     return phSUCCESS;
00705     
00706 error:
00707     return phFAIL;
00708 }
00709     
00710 /* ------------------------------------------------------------------------- */
00711 static int phX11Display_Deinitialize( struct phX11DisplayInfo_t *display_info )
00712 {
00713     phFUNCTION("phX11Display_Deinitialize")
00714 
00715     Display *display = display_info->display;
00716     /*XEvent event;*/
00717     Status xrc  = 0;
00718     
00719     phCHECK_NULLPTR(display_info,NULL,"dispInfo pointer == NULL");  
00720 
00721     phFree(display_info->name);
00722     
00723     /* XLockDisplay(display); */
00724     
00725     /* Close the connection to the X Server [2] */
00726     if (display != NULL)
00727     {
00728         xrc = XFlush(display);
00729         if (!xrc)
00730         {
00731             phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
00732         }
00733 
00734         DEBUG_PRINT("XCloseDisplay\n");
00735         xrc = XCloseDisplay(display);
00736         if (xrc)
00737         {
00738             phPRINT_RC(-1,NULL,"XCloseDisplay failed with status = %d.",xrc);
00739         }
00740     }
00741 
00742     return phSUCCESS;
00743     
00744 error:
00745 
00746     return phFAIL;
00747 }
00748 
00749 /* ------------------------------------------------------------------------- */
00750 int phX11EventAtom_Create( const char               *name,
00751                            struct phX11EventAtom_t  *event_atom_class,
00752                            struct phX11WindowInfo_t *window,
00753                            struct phX11EventAtom_t  **pevent_atom )
00754 {
00755     phFUNCTION("phX11EventAtom_Create")
00756     
00757     struct phX11EventAtom_t *event_atom = NULL;
00758 
00759     /* Check the parameters */
00760     phCHECK_NULLPTR(name,NULL,"Invalid argument: name == NULL");
00761     phCHECK_NULLPTR(window,NULL,"Invalid argument: window == NULL");
00762     phCHECK_NULLPTR(pevent_atom,NULL,"Invalid argument: pevent_atom == NULL");
00763 
00764     /* Allocate the event atom */
00765     event_atom = (*pevent_atom) = (struct phX11EventAtom_t *)phCalloc(1,
00766                                     sizeof(struct phX11EventAtom_t));
00767     phCHECK_NULLPTR(event_atom,"phCalloc",
00768                   "phCalloc failed to allocate event atom");
00769 
00770     /* Keep a list of windows which the event atom will accept messages
00771      * from */
00772     event_atom->num_windows = 2;
00773     event_atom->windows = (Window *)phCalloc(event_atom->num_windows,
00774                                         sizeof(Window));
00775     phCHECK_NULLPTR(event_atom->windows,"phCalloc",
00776             "phCalloc failed to allocate memory for window id array");
00777     
00778     event_atom->windows[0] = window->base_window;
00779     event_atom->windows[1] = window->image_window;
00780     
00781 
00782     /* name != NULL since we passed the phCHECK_NULLPTR macro above */
00783     /* Set the mem_length to the name size + more mem; so we can 
00784      * sprintf a prefix/suffix with the name */
00785     event_atom->name_mem_length = strlen(name) + 256;
00786     
00787     /* allocate the space for the event atom name */
00788     event_atom->name = (char *)phCalloc(event_atom->name_mem_length,
00789                                         sizeof(char));
00790     phCHECK_NULLPTR(event_atom->name,"phCalloc","phCalloc failed.");
00791     
00792     /* Set the name into the event atom name buffer */
00793     sprintf(event_atom->name,
00794             "_X11Display_%lld_%s_atom",
00795             (long long)window->base_window,
00796             name);
00797     
00798     /* Set the name length */
00799     event_atom->name_length = strlen(event_atom->name);
00800     
00801     DEBUG_PRINT("XInternAtom\n");
00802     event_atom->atom = XInternAtom(window->display,
00803                                    event_atom->name,
00804                                    False);
00805     if (event_atom->atom == None)
00806     {
00807         phCHECK_RC(-1,NULL,"XInternAtom failed to create atom.");
00808     }
00809 
00810     event_atom->event.type                   = ClientMessage;
00811     event_atom->event.xclient.format         = 32;
00812     event_atom->event.xclient.window         = window->base_window;
00813     event_atom->event.xclient.data.l[0]      = event_atom->atom;
00814     event_atom->event.xclient.data.l[1] = 
00815         event_atom->event.xclient.data.l[2] = 
00816         event_atom->event.xclient.data.l[3] = 
00817         event_atom->event.xclient.data.l[4] = 0L;
00818     
00819     if (event_atom_class == NULL)
00820     {
00821         event_atom->event.xclient.message_type = (Atom)0;
00822     }
00823     else
00824     {
00825         event_atom->event.xclient.message_type = 
00826                         event_atom_class->atom;
00827     }
00828 
00829     event_atom->display = window->display;
00830 
00831     return phSUCCESS;
00832 error:
00833     if (event_atom)
00834     {
00835         phFree(event_atom->name);
00836         phFree(event_atom->windows);
00837         memset(event_atom,0,sizeof(struct phX11EventAtom_t));
00838 
00839         event_atom = NULL;
00840         phFree(*pevent_atom);
00841     }
00842     
00843     return phFAIL;
00844 }
00845 
00846 /* ------------------------------------------------------------------------- */
00847 int phX11EventAtom_Delete( struct phX11EventAtom_t  **pevent_atom )
00848 {
00849     phFUNCTION("phX11EventAtom_Delete")
00850     
00851     /* Check the parameters */
00852     phCHECK_NULLPTR(pevent_atom,NULL,"Invalid argument: pevent_atom == NULL");
00853 
00854     if (*pevent_atom == NULL) return phSUCCESS;
00855    
00856     /* Free the name */
00857     phFree((*pevent_atom)->name);
00858     /* Free the bound window array */
00859     phFree((*pevent_atom)->windows);
00860     /* reset the values in the atom */
00861     memset((*pevent_atom),0,sizeof(struct phX11EventAtom_t));
00862     /* free the event atom memory */
00863     phFree(*pevent_atom);
00864     
00865     return phSUCCESS;
00866 error:
00867     return phFAIL;
00868 }
00869 
00870 /* ------------------------------------------------------------------------- */
00871 int phX11EventAtom_Equal( struct phX11EventAtom_t *event_atom,
00872                           phX11EventInfo           e )
00873 {
00874     phFUNCTION("phX11EventAtom_Equal")
00875    
00876     int         retrc           = 0;
00877     int         valid_window_id = 0;
00878     uint32_t    i               = 0;
00879     
00880     Atom        a_class         = (Atom)0;
00881     char        *class_name     = NULL;
00882 
00883     Atom        a               = (Atom)0;
00884     char        *name           = NULL;
00885     
00886     phCHECK_NULLPTR(event_atom,NULL,"Invalid parameter: event_atom == NULL");
00887    
00888     /* Make sure this is a valid event to begin with */
00889     if (phX11Event_GetType(e) != ClientMessage) goto error;
00890         
00891     /* make sure the event passed in comes from one of the windows 
00892      * to which the event_atom is bound */
00893     for (i = 0; i < event_atom->num_windows; i++ )
00894     {
00895         if (e->event.xclient.window == event_atom->windows[i])
00896         {
00897             valid_window_id = 1;
00898         }
00899     }
00900    
00901     /* if it isn't bound to one of the event_atom's windows, then
00902      * return false by not setting the retrc to true and returning 
00903      * striaght away */
00904     if (valid_window_id == 0) goto error;
00905     
00906     /* Make sure the event belongs to the event_atoms class */
00907     if (phX11EventAtom_BelongsToClass(event_atom, e))
00908     {
00909         a_class       = e->event.xclient.message_type;
00910         a             = (Atom)e->event.xclient.data.l[0];
00911         
00912         DEBUG_PRINT("XGetAtomName\n");
00913         class_name    = XGetAtomName(event_atom->display,a_class);
00914         phPRINT_NULLPTR(class_name,"XGetAtomName","XGetAtomName failed to get atom name.");
00915         
00916         DEBUG_PRINT("XGetAtomName\n");
00917         name          = XGetAtomName(event_atom->display,a);
00918         phPRINT_NULLPTR(name,"XGetAtomName","XGetAtomName failed to get atom name.");
00919 
00920         DEBUG_PRINT("class_name:%s name:%s\n",class_name,name);
00921         
00922         /* Check if the name isn't NULL and if the atoms are the same */
00923         if (e->event.xclient.data.l[0] == (int)event_atom->atom)
00924         {
00925             if (strcmp(event_atom->name, name) == 0)
00926             {
00927                 retrc = 1;
00928             }
00929         }
00930     }
00931     
00932 error:
00933     if (name != NULL)
00934     {
00935         DEBUG_PRINT("XFree\n");
00936         XFree(name);
00937         name = NULL;
00938     }
00939     
00940     if (class_name != NULL)
00941     {
00942         DEBUG_PRINT("XFree\n");
00943         XFree(class_name);
00944         class_name = NULL;
00945     }
00946     
00947     return retrc;
00948 }
00949 
00950 /* ------------------------------------------------------------------------- */
00951 int phX11EventAtom_BelongsToClass( struct phX11EventAtom_t *event_atom,
00952                                    phX11EventInfo           e )
00953 {
00954     phFUNCTION("phX11EventAtom_BelongsToClass")
00955    
00956     phCHECK_NULLPTR(event_atom,NULL,"Invalid parameter: event_atom == NULL");
00957     
00958     if (e->event.xclient.message_type == 
00959             event_atom->event.xclient.message_type)
00960     {
00961         return 1;
00962     }
00963     else
00964     {
00965         return 0;
00966     }
00967           
00968 error:
00969     return 0;
00970 }
00971 
00972 /* ------------------------------------------------------------------------- */
00973 int phX11EventAtom_IsNamed( struct phX11EventAtom_t *event_atom,
00974                             const char *name )
00975 {
00976     phFUNCTION("phX11EventAtom_IsNamed")
00977     uint32_t    name_length = 0;
00978     int         retrc       = 0;
00979    
00980     /* Don't complain if name == NULL, only if the event_atom is NULL */
00981     if (name == NULL) goto error;
00982     phCHECK_NULLPTR(event_atom,NULL,"Invalid parameter: event_atom == NULL");
00983     
00984     /* Compare the passed name and the event_atom name */
00985     name_length = strlen(name);
00986     if (name_length == event_atom->name_length)
00987     {
00988         if (strcmp(name,event_atom->name) == 0)
00989         {
00990             retrc = 1;
00991         }
00992     }
00993     
00994 error:
00995     return retrc;
00996 }
00997 
00998 /* ------------------------------------------------------------------------- */
00999 int phX11Window_Create( phX11SizeInfo               size,
01000                         phX11LocationInfo           location,
01001                         unsigned long               border,
01002                         char                        *title,
01003                         struct phX11WindowInfo_t    **pwindow )
01004 {
01005     phFUNCTION("phX11Window_Create")
01006 
01007     XSetWindowAttributes    base_window_attr;
01008     XSetWindowAttributes    image_window_attr;
01009     
01010     /* XWindowAttributes       win_attr; */
01011 
01012     /* These 2 variables are for the HINTS allocation and setting */
01013     Status                  xrc             = 0;
01014     /*long                    xSuppliedReturn = 0;*/
01015 
01016     struct phX11WindowInfo_t    *window       = NULL;
01017     struct phX11DisplayInfo_t   *display_info = NULL;
01018     
01019 #if 0
01020     uint32_t allMask;
01021 
01022     allMask = NoEventMask               |
01023                 KeyPressMask            |
01024                 KeyReleaseMask          |
01025                 ButtonPressMask         |
01026                 ButtonReleaseMask       |
01027                 EnterWindowMask         |
01028                 LeaveWindowMask         |
01029                 PointerMotionMask       |
01030                 PointerMotionHintMask   |
01031                 Button1MotionMask       |
01032                 Button2MotionMask       |
01033                 Button3MotionMask       |
01034                 Button4MotionMask       |
01035                 Button5MotionMask       |
01036                 ButtonMotionMask        |
01037                 KeymapStateMask         |
01038                 ExposureMask            |
01039                 VisibilityChangeMask    |
01040                 StructureNotifyMask     |
01041                 ResizeRedirectMask      |
01042                 SubstructureNotifyMask  |
01043                 SubstructureRedirectMask|
01044                 FocusChangeMask         |
01045                 PropertyChangeMask      |
01046                 ColormapChangeMask      |
01047                 OwnerGrabButtonMask;
01048 #endif
01049 
01050     
01051     phCHECK_NULLPTR(pwindow,NULL,"Invalid argument: pwindow == NULL");
01052 
01053     window = (*pwindow) = (struct phX11WindowInfo_t *)phCalloc(1,
01054                                     sizeof(struct phX11WindowInfo_t));
01055     phCHECK_NULLPTR(window,"phCalloc","phCalloc failed to allocate window");
01056 
01057     display_info = &window->display_info;
01058     
01059     /* Open and Initialize the display */
01060     rc = phX11Display_Initialize(display_info);
01061     phCHECK_RC(rc,NULL,"InitializeDisplay failed");
01062 
01063     /* XLockDisplay(display_info->display); */
01064     
01065     window->display         = display_info->display;
01066     window->screen_number   = display_info->screen_number;
01067     window->depth           = display_info->depth;
01068     
01069     /* Figure out the 8 bit aligned mask for an 8 bit color values */
01070     window->red_mask    = display_info->visual->red_mask;
01071     window->red_shift   = 0;
01072     window->green_mask  = display_info->visual->green_mask;
01073     window->green_shift = 0;
01074     window->blue_mask   = display_info->visual->blue_mask;
01075     window->blue_shift  = 0;
01076     
01077     phX11_Align_8bitmask( &window->red_mask,  &window->red_shift);
01078     phX11_Align_8bitmask( &window->green_mask,&window->green_shift);
01079     phX11_Align_8bitmask( &window->blue_mask, &window->blue_shift);
01080     
01081     /* Create the window */
01082     /* base_window_attr.override_redirect = False;  */
01083     base_window_attr.background_pixel = display_info->black_pixel;
01084     base_window_attr.border_pixel = 0;
01085     base_window_attr.colormap = DefaultColormap(display_info->display,
01086                                      display_info->screen_number);
01087 
01088     DEBUG_PRINT("XCreateWindow\n");
01089     window->base_window = 
01090         XCreateWindow(display_info->display,
01091                       display_info->root_window,
01092                       location.x, location.y, size.w, size.h, 0,
01093                       display_info->depth,
01094                       InputOutput, 
01095                       display_info->visual,
01096                       CWBackPixel |
01097                       /* CWOverrideRedirect |  */
01098                       CWBorderPixel | 
01099                       CWColormap, 
01100                       &base_window_attr);
01101     if (window->base_window == (Window)0)
01102     {
01103         phCHECK_RC(-1,NULL,"XCreateWindow failed: base_window");
01104     }
01105  
01106     /* This creates a way of signalling that the window should be deleted
01107      * through an event posting */
01108     DEBUG_PRINT("XInternAtom\n");
01109     window->WM_DELETE_WINDOW = XInternAtom(display_info->display,
01110                                            "WM_DELETE_WINDOW", 
01111                                            False);
01112                             /* TODO : phCHECK_RC */
01113     DEBUG_PRINT("XSetWMProtocols\n");
01114     XSetWMProtocols(display_info->display,
01115                     window->base_window,
01116                     &(window->WM_DELETE_WINDOW), 
01117                     1);
01118                             /* TODO : phCHECK_RC */
01119 
01120     /* Allocate the event atom array */
01121     window->num_event_atoms = phX11Window_EVENT_COUNT;
01122     window->event_atoms = (struct phX11EventAtom_t **)phCalloc(
01123                                     window->num_event_atoms,
01124                                     sizeof(struct phX11EventAtom_t *));
01125     phCHECK_NULLPTR(window->event_atoms,
01126                   "phCalloc",
01127                   "phCalloc failed to allocate event_atoms array.");
01128     
01129     /* --------------------------------------------------------------------- */
01130     /* Passed with other atoms to ident the set of atoms as a class of events*/
01131     /* Particularly the StructureAtom class of events... I made it up, yea   */
01132     /* --------------------------------------------------------------------- */
01133     rc = phX11EventAtom_Create(phSTRUCTURE_NAME,
01134                                NULL,
01135                                window,
01136                                &(window->event_atoms[phSTRUCTURE_INDEX]) );
01137     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: structure class event atom.");
01138     
01139     /* --------------------------------------------------------------------- */
01140     /* Create an atom that can be sent to wakeup a blocked event loop */
01141     /* --------------------------------------------------------------------- */
01142     rc = phX11EventAtom_Create(phWAKEUP_NAME,
01143                                window->event_atoms[phSTRUCTURE_INDEX],
01144                                window,
01145                                &(window->event_atoms[phWAKEUP_INDEX]) );
01146     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: wakeup event atom.");
01147 
01148     /* --------------------------------------------------------------------- */
01149     /* Create an atom that can be sent to tell the input/event thread to 
01150      * update the image */
01151     /* --------------------------------------------------------------------- */
01152     rc = phX11EventAtom_Create(phUPDATE_NAME,
01153                                window->event_atoms[phSTRUCTURE_INDEX],
01154                                window,
01155                                &(window->event_atoms[phUPDATE_INDEX]) );
01156     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: update event atom.");
01157     
01158     /* --------------------------------------------------------------------- */
01159     rc = phX11EventAtom_Create(phREDRAW_NAME,
01160                                window->event_atoms[phSTRUCTURE_INDEX],
01161                                window,
01162                                &(window->event_atoms[phREDRAW_INDEX]) );
01163     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: minsize event atom.");
01164 
01165     rc = phX11EventAtom_Create(phRESIZE_NAME,
01166                                window->event_atoms[phSTRUCTURE_INDEX],
01167                                window,
01168                                &(window->event_atoms[phRESIZE_INDEX]) );
01169     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: resize event atom.");
01170     
01171     rc = phX11EventAtom_Create(phMOVE_NAME,
01172                                window->event_atoms[phSTRUCTURE_INDEX],
01173                                window,
01174                                &(window->event_atoms[phMOVE_INDEX]) );
01175     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: move event atom.");
01176     
01177     rc = phX11EventAtom_Create(phMINSIZE_NAME,
01178                                window->event_atoms[phSTRUCTURE_INDEX],
01179                                window,
01180                                &(window->event_atoms[phMINSIZE_INDEX]) );
01181     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: minsize event atom.");
01182 
01183     rc = phX11EventAtom_Create(phVISIBLE_NAME,
01184                                window->event_atoms[phSTRUCTURE_INDEX],
01185                                window,
01186                                &(window->event_atoms[phVISIBLE_INDEX]) );
01187     phPRINT_RC(rc,NULL,"phX11EventAtom_Create failed: resize event atom.");
01188     
01189     /* --------------------------------------------------------------------- */
01190     /* Create the window that the image will be drawn into. This exists
01191      * within the base window */
01192     image_window_attr.background_pixel = 0;
01193     image_window_attr.border_pixel = 0;
01194     image_window_attr.colormap = base_window_attr.colormap;
01195 
01196     DEBUG_PRINT("XCreateWindow\n");
01197     window->image_window = 
01198                 XCreateWindow(  display_info->display, 
01199                                 window->base_window,
01200                                 0, 0, size.w, size.h, 0, 
01201                                 display_info->depth,
01202                                 InputOutput, 
01203                                 display_info->visual,
01204                                 CWBackPixel | CWBorderPixel | CWColormap, 
01205                                 &image_window_attr);
01206     if (window->image_window == (Window)0)
01207     {
01208         phCHECK_RC(-1,NULL,"XCreateWindow failed: image_window");
01209     }
01210 
01211 #if USE_DGA()
01212     DEBUG_PRINT("XDGAOpenFramebuffer\n");
01213     if (XDGAOpenFramebuffer(display_info->display,
01214                             display_info->screen_number) == False)
01215     {
01216         phCHECK_RC(-1,NULL,"XDGAOpenFramebuffer failed.");
01217     }
01218 #endif
01219     
01220     window->base_event_mask =   FocusChangeMask             |
01221                                 KeyPressMask                |
01222                                 KeyReleaseMask              |
01223                                 PropertyChangeMask          |
01224                                 KeymapStateMask             |
01225                                 StructureNotifyMask         |
01226                                 /* SubstructureRedirectMask | */
01227                                 SubstructureNotifyMask
01228                                 ;
01229     
01230     window->image_event_mask =  KeyPressMask            |
01231                                 KeyReleaseMask          |
01232                                 ButtonPressMask         |
01233                                 ButtonReleaseMask       |
01234                                 ExposureMask            |
01235                                 VisibilityChangeMask    |
01236                                 StructureNotifyMask     |
01237                                 SubstructureNotifyMask
01238                                 ;
01239 
01240     /* Set up the event handling */
01241     DEBUG_PRINT("XSelectInput\n");
01242     xrc = XSelectInput(display_info->display, 
01243                        window->base_window,
01244                        window->base_event_mask );
01245     if (!xrc)
01246     {
01247         phPRINT_RC(-1,NULL,"XSelectInput failed with status = %d.",xrc);
01248     }
01249         
01250     DEBUG_PRINT("XSelectInput\n");
01251     xrc = XSelectInput(display_info->display, 
01252                        window->image_window,
01253                        window->image_event_mask  );
01254     if (!xrc)
01255     {
01256         phPRINT_RC(-1,NULL,"XSelectInput failed with status = %d.",xrc);
01257     }
01258 
01259     /* Set the default value in the case XDBE fails, is unsupported or
01260      * isn't compiled in */
01261     window->use_xdbe = 0;
01262     
01263 #if USE_DOUBLEBUFFER_EXT()
01264     if (phX11Check_XDBE(window->display))
01265     {
01266         /* Create a back buffer for the Double Buffer Extension support.
01267          *    this removes the flickering */
01268         /*--------------------------------------------------------*
01269             XdbeSwapInfo structure has the following fields:
01270                 Window            swap_window
01271                 XdbeSwapAction    swap_action
01272                     XdbeUndefined
01273                     XdbeBackground
01274                     XdbeUntouched
01275                     XdbeCopied
01276          *----------------------------------------------------------*/
01277         window->swap_info.swap_window = window->image_window;
01278             
01279         window->swap_info.swap_action = XdbeUndefined;
01280     
01281         DEBUG_PRINT("XdbeAllocateBackBufferName\n");
01282         window->back_buffer = 
01283             XdbeAllocateBackBufferName( display_info->display,
01284                                         window->image_window,
01285                                         window->swap_info.swap_action );
01286         if (window->back_buffer)
01287         {
01288             window->use_xdbe = 1;
01289             window->drawable = window->back_buffer;
01290         }
01291         else
01292         {
01293             window->use_xdbe = 0;
01294             window->drawable = 0;
01295         }
01296     }
01297 #endif
01298      
01299     if (!(window->use_xdbe))
01300     {   
01301         window->drawable = window->image_window;
01302     }
01303 
01304     /* Create the GraphicContext for displaying */
01305     DEBUG_PRINT("XCreateGC\n");
01306     window->gc_vals.graphics_exposures = False;
01307     window->gc = XCreateGC( display_info->display,
01308                             window->drawable,
01309                             GCGraphicsExposures,
01310                             &(window->gc_vals));                   
01311                             /* TODO : phCHECK_RC */
01312     if (window->gc == (GC)0)
01313     {
01314         phPRINT_RC(-1,NULL,"XCreateGC failed.");
01315     }
01316  
01317     /* Setup the X11 hints structure */
01318     /* Set the NORMAL hints for the minimum size of the window */
01319     DEBUG_PRINT("XAllocSizeHints\n");
01320     window->hints = XAllocSizeHints();
01321     /* Make sure the hints was allocated */
01322     phPRINT_NULLPTR(window->hints,"XAllocSizeHints",
01323                   "XAllocSizeHints failed.");
01324 
01325     /* Set the size limits in the window */
01326     rc = phX11Window_SetSizeLimits(window,size.w,size.h,4096,4096);
01327     phPRINT_RC(rc,NULL,"phX11Window_SetSizeLimits failed.");
01328     window->width   = size.w;
01329     window->height  = size.h;
01330     
01331     /* Set the title in the window */
01332     rc = phX11Window_SetTitle(window,title);
01333     phPRINT_RC(rc,NULL,"phX11Window_SetTitle");
01334 
01335     rc = phX11Window_SetLocation(window,location.x,location.y);
01336     phPRINT_RC(rc,NULL,"phX11Window_SetLocation");
01337     
01338     window->is_open = 1;
01339     window->is_visible = 0;
01340 
01341     /* XUnlockDisplay(display_info->display); */
01342     
01343     return phSUCCESS;
01344 error:
01345     if (pwindow != NULL)
01346     {
01347         rc = phX11Window_Delete(pwindow);
01348         phPRINT_RC(rc,NULL,"phX11Window_Delete");
01349     }
01350 
01351     /* XUnlockDisplay(display_info->display); */
01352 
01353     return phFAIL;
01354 }
01355 
01356 /* ------------------------------------------------------------------------- */
01357 int phX11Window_Delete( struct phX11WindowInfo_t **pwindow )
01358 {
01359     phFUNCTION("phX11Window_Delete")
01360 
01361     Status                      xrc         = 0;
01362     struct phX11WindowInfo_t    *window     = NULL;
01363     uint32_t                    i           = 0;
01364     
01365     if (pwindow == NULL) return phFAIL;
01366     if (*pwindow == NULL) return phSUCCESS;
01367 
01368     window = *pwindow;
01369     
01370     /* XLockDisplay(window->display); */
01371     
01372     if ((window->is_open) && (window->display != NULL))
01373     {
01374         rc = phX11Window_Hide(window);
01375         
01376 #if USE_DOUBLEBUFFER_EXT()
01377         if (window->use_xdbe)
01378         {
01379             if (window->back_buffer)
01380             {
01381                 DEBUG_PRINT("XdbeDeallocateBackBufferName\n");
01382                 xrc = XdbeDeallocateBackBufferName(window->display,
01383                                                    window->back_buffer);
01384                 if (!xrc)
01385                 {
01386                     phPRINT_RC(-1,NULL,
01387                     "XdbeDeallocateBackBufferName failed with status = %d.",
01388                     xrc);
01389                 }
01390             }
01391         }
01392 #endif
01393  
01394         DEBUG_PRINT("XDestroyWindow\n");
01395         xrc = XDestroyWindow( window->display, 
01396                               window->image_window);
01397         if (!xrc)
01398         {
01399             phPRINT_RC(-1,NULL,"XDestroyWindow failed with status = %d.",xrc);
01400         }
01401     }
01402 
01403     if (window->gc)
01404     {
01405         DEBUG_PRINT("XFree\n");
01406         XFree(window->gc);
01407         window->gc = NULL;
01408     }
01409     
01410     if (window->hints) 
01411     {
01412         DEBUG_PRINT("XFree\n");
01413         XFree(window->hints);
01414         window->hints = NULL;
01415     }
01416  
01417     for (i = 0; i < window->num_event_atoms; i++)
01418     {
01419         rc = phX11EventAtom_Delete(&(window->event_atoms[i]));
01420         phPRINT_RC(rc,NULL,"phX11EventAtom_Delete failed [i:%lu]",
01421                  (long unsigned)i);
01422     }
01423 
01424     phFree(window->event_atoms);
01425     
01426     /* Make sure the display was opened correctly first */
01427     if (window->display != NULL)
01428     {
01429         rc = phX11Display_Deinitialize(&window->display_info);
01430         phPRINT_RC(rc,NULL,"phX11Display_Deinitialize");
01431     }
01432     
01433     memset(window,0,sizeof(struct phX11WindowInfo_t));
01434     
01435     phFree(*pwindow);
01436     
01437     /* XUnlockDisplay(display); */
01438     
01439     return phSUCCESS;
01440 }
01441 
01442 /* ------------------------------------------------------------------------- */
01443 static int phX11Window_SendEvent( struct phX11WindowInfo_t *window,
01444                                   XEvent *event )
01445 {
01446     phFUNCTION("phX11Window_SendEvent")
01447     
01448     Status          xrc         = 0;
01449     uint32_t        retry       = 0;
01450     const uint32_t  max_retry   = 10000;
01451     
01452     if (window == NULL) return phFAIL;
01453     
01454     do
01455     {
01456         retry++;
01457         DEBUG_PRINT("XSendEvent\n");
01458         xrc = XSendEvent(window->display,
01459                          window->base_window,
01460                          False,
01461                          NoEventMask,
01462                          event );
01463         if (xrc == 0)
01464         {
01465             phPRINT_RC(-1,NULL,"XSendEvent failed with status = %d.",xrc);
01466         }
01467 
01468         DEBUG_PRINT("XFlush\n");
01469         xrc = XFlush(window->display);
01470         if (!xrc)
01471         {
01472             phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
01473         }
01474     }
01475     while ((xrc==0) && (retry <= max_retry));
01476    
01477     if (xrc==0) return phFAIL;
01478     
01479     return phSUCCESS;
01480 }
01481 
01482 /* ------------------------------------------------------------------------- */
01483 int phX11Window_SendRedraw( struct phX11WindowInfo_t *window )
01484 {
01485     phFUNCTION("phX11Window_SendRedraw")
01486     
01487     XEvent event;
01488     
01489     if (window == NULL) return phFAIL;
01490     if (window->event_atoms[phREDRAW_INDEX] == NULL) return phFAIL;
01491     
01492     event = window->event_atoms[phREDRAW_INDEX]->event;
01493 
01494     return phX11Window_SendEvent(window,&event);
01495 }
01496 
01497 /* ------------------------------------------------------------------------- */
01498 int phX11Window_SendUpdate( struct phX11WindowInfo_t *window )
01499 {
01500     phFUNCTION("phX11Window_SendUpdate")
01501     
01502     XEvent event;
01503     
01504     if (window == NULL) return phFAIL;
01505     if (window->event_atoms[phUPDATE_INDEX] == NULL) return phFAIL;
01506 
01507     event = window->event_atoms[phUPDATE_INDEX]->event;
01508     
01509     return phX11Window_SendEvent(window,&event);
01510 }
01511 
01512 /* ------------------------------------------------------------------------- */
01513 int phX11Window_SendVisible ( struct phX11WindowInfo_t  *window,
01514                               int32_t                   show        )
01515 {
01516     phFUNCTION("phX11Window_SendVisible")
01517 
01518     XEvent event;
01519     
01520     if (window == NULL) return phFAIL;
01521     if (window->event_atoms[phVISIBLE_INDEX] == NULL) return phFAIL;
01522     
01523     /* We need to copy the information from the event_atoms in case
01524      * another thread is sending a resize at the same time; unlikely,
01525      * but should still protect against it */
01526     event = window->event_atoms[phVISIBLE_INDEX]->event;
01527     event.xclient.data.l[1] = (long)show;
01528 
01529     return phX11Window_SendEvent(window,&event);
01530 }
01531 
01532 /* ------------------------------------------------------------------------- */
01533 int phX11Window_SendResize( struct phX11WindowInfo_t *window,
01534                             uint32_t width,
01535                             uint32_t height )
01536 {
01537     phFUNCTION("phX11Window_SendResize")
01538     
01539     XEvent event;
01540     
01541     if (window == NULL) return phFAIL;
01542     if (window->event_atoms[phRESIZE_INDEX] == NULL) return phFAIL;
01543     
01544     event = window->event_atoms[phRESIZE_INDEX]->event;
01545     event.xclient.data.l[1] = (long)width;
01546     event.xclient.data.l[2] = (long)height;
01547 
01548     return phX11Window_SendEvent(window,&event);
01549 }
01550 
01551 /* ------------------------------------------------------------------------- */
01552 int phX11Window_SendMove( struct phX11WindowInfo_t *window,
01553                           int32_t x,
01554                           int32_t y )
01555 {
01556     phFUNCTION("phX11Window_SendMove")
01557     
01558     XEvent          event;
01559     
01560     if (window == NULL) return phFAIL;
01561     if (window->event_atoms[phMOVE_INDEX] == NULL) return phFAIL;
01562     
01563     event = window->event_atoms[phMOVE_INDEX]->event;
01564     event.xclient.data.l[1] = (long)x;
01565     event.xclient.data.l[2] = (long)y;
01566     
01567     return phX11Window_SendEvent(window,&event);
01568 }
01569 
01570 /* ------------------------------------------------------------------------- */
01571 int phX11Window_SendMinSize( struct phX11WindowInfo_t *window,
01572                              uint32_t min_width,
01573                              uint32_t min_height )
01574 {
01575     phFUNCTION("phX11Window_SendUpdate")
01576     
01577     XEvent event;
01578     
01579     if (window == NULL) return phFAIL;
01580     if (window->event_atoms[phMINSIZE_INDEX] == NULL) return phFAIL;
01581     
01582     event = window->event_atoms[phMINSIZE_INDEX]->event;
01583     event.xclient.data.l[1] = (long)min_width;
01584     event.xclient.data.l[2] = (long)min_height;
01585     
01586     return phX11Window_SendEvent(window,&event);
01587 }
01588 
01589 /* ------------------------------------------------------------------------- */
01590 int phX11Window_SendWakeup( struct phX11WindowInfo_t *window )
01591 {
01592     phFUNCTION("phX11Window_SendWakeup")
01593    
01594     XEvent event;
01595     
01596     if (window == NULL) return phFAIL;
01597     if (window->event_atoms[phWAKEUP_INDEX] == NULL) return phFAIL;
01598 
01599     event = window->event_atoms[phWAKEUP_INDEX]->event;
01600     
01601     return phX11Window_SendEvent(window,&event);
01602 }
01603 
01604 /* ------------------------------------------------------------------------- */
01605 int phX11Window_IsOpen( struct phX11WindowInfo_t *window)
01606 {
01607     /* Window not open */
01608     if (window == NULL) return 0;
01609     
01610     return window->is_open;
01611 }
01612 
01613 /* ------------------------------------------------------------------------- */
01614 int phX11Window_IsVisible( struct phX11WindowInfo_t *window)
01615 {
01616     /* Window not open */
01617     if (window == NULL) return 0;
01618     
01619     return window->is_visible;
01620 }
01621 
01622 /* ------------------------------------------------------------------------- */
01623 int phX11Window_Show( struct phX11WindowInfo_t *window )
01624 {
01625     phFUNCTION("phX11Window_Show")
01626     /* XEvent event; */
01627     Status xrc = 0;
01628     
01629     if (window == NULL) return phFAIL;
01630     if (window->display == NULL) return phFAIL;
01631     
01632     /* XLockDisplay(window->display); */
01633     
01634     if (window->is_visible == 0)
01635     {
01636         /* Display the window */
01637         DEBUG_PRINT("XMapWindow\n");
01638         xrc = XMapWindow( window->display, 
01639                           window->base_window );
01640         if (!xrc)
01641         {
01642             phPRINT_RC(-1,NULL,"XMapWindow failed with status = %d.",xrc);
01643         }
01644 
01645         /* Map the image window (which lives in the base window) */
01646         DEBUG_PRINT("XMapWindow\n");
01647         xrc = XMapWindow( window->display, 
01648                           window->image_window );
01649         if (!xrc)
01650         {
01651             phPRINT_RC(-1,NULL,"XMapWindow failed with status = %d.",xrc);
01652         }
01653 
01654 
01655         /* Flush all events in the display */
01656         DEBUG_PRINT("XFlush\n");
01657         xrc = XFlush(window->display);
01658         if (!xrc)
01659         {
01660             phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
01661         }
01662 #if 0        
01663         /* From SDL library */
01664         do 
01665         {
01666             XMaskEvent(window->display, 
01667                        StructureNotifyMask, 
01668                        &event );
01669         }
01670         while ( (event.type != MapNotify) || 
01671                 (event.xmap.event != window->image_window) );
01672         do 
01673         {
01674             XMaskEvent(window->display, 
01675                        StructureNotifyMask, 
01676                        &event );
01677         }
01678         while ( (event.type != MapNotify) || 
01679                 (event.xmap.event != window->base_window) );
01680 #endif
01681         /* The window should now be visible */
01682         window->is_visible = 1;
01683     }
01684 
01685     /* XUnlockDisplay(window->display); */
01686     
01687     return phSUCCESS;
01688 }
01689 
01690 /* ------------------------------------------------------------------------- */
01691 int phX11Window_Hide( struct phX11WindowInfo_t *window )
01692 {
01693     phFUNCTION("phX11Window_Hide")
01694     Status xrc = 0;
01695 
01696     if (window == NULL) return phFAIL;
01697     if (window->display == NULL) return phFAIL;
01698     
01699     /* XLockDisplay(window->display); */
01700     
01701     if (window->is_visible == 1)
01702     {
01703         /* XEvent event; */
01704         
01705         /* Unmap the image window (which lives in the base window) */
01706         DEBUG_PRINT("XUnmapWindow\n");
01707         xrc = XUnmapWindow( window->display, 
01708                             window->image_window );
01709         if (!xrc)
01710         {
01711             phPRINT_RC(-1,NULL,"XUnmapWindow failed with status = %d.",xrc);
01712         }
01713 
01714         /* Unmap the base window */
01715         DEBUG_PRINT("XUnmapWindow\n");
01716         xrc = XUnmapWindow( window->display, 
01717                             window->base_window );
01718         if (!xrc)
01719         {
01720             phPRINT_RC(-1,NULL,"XUnmapWindow failed with status = %d.",xrc);
01721         }
01722 
01723         /* Flush all events in the display */
01724         DEBUG_PRINT("XFlush\n");
01725         xrc = XFlush(window->display);
01726         if (!xrc)
01727         {
01728             phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
01729         }
01730 #if 0        
01731         /* These must be in order of the unmap calls above */
01732         /* From SDL library */
01733         do 
01734         {
01735             XMaskEvent( window->display, 
01736                         StructureNotifyMask, 
01737                         &event);
01738         } 
01739         while ( (event.type != UnmapNotify) || 
01740                 (event.xunmap.event != window->image_window) );
01741         do 
01742         {
01743             XMaskEvent( window->display, 
01744                         StructureNotifyMask, 
01745                         &event);
01746         } 
01747         while ( (event.type != UnmapNotify) || 
01748                 (event.xunmap.event != window->base_window) );
01749 #endif  
01750         /* The window isn't visible anymore */
01751         window->is_visible = 0;
01752     }
01753 
01754     /* XUnlockDisplay(window->display); */
01755     
01756     return phSUCCESS;
01757 }
01758 
01759 
01760 /* ------------------------------------------------------------------------- */
01761 int phX11Window_SetTitle( struct phX11WindowInfo_t *window,
01762                           const char *title )
01763 {
01764     phFUNCTION("phX11Window_SetTitle")
01765     XTextProperty   titleprop;
01766     Status          xrc = 0;
01767     const char      *use_title = (title == NULL) ? "" : title;
01768 
01769     if (window == NULL) return phFAIL;
01770     
01771     DEBUG_PRINT("%s\n",use_title);
01772     
01773     /* from the SDL library */
01774     /* This sets the title of the base window in which all other components
01775      * live */
01776     DEBUG_PRINT("XStringListToTextProperty\n");
01777     xrc = XStringListToTextProperty((char **)&use_title, 1, &titleprop);
01778     if (!xrc)
01779     {
01780         phPRINT_RC(-1,NULL,"XStringListToTextProperty failed with status = %d.",xrc);
01781     }
01782     
01783     DEBUG_PRINT("XSetWMName\n");
01784     XSetWMName(window->display,
01785                window->base_window, 
01786                &titleprop);
01787     
01788     DEBUG_PRINT("XSetWMIconName\n");
01789     XSetWMIconName(window->display,
01790                    window->base_window,
01791                    &titleprop);
01792     
01793     DEBUG_PRINT("XFree\n");
01794     XFree(titleprop.value);
01795         
01796     titleprop.value = NULL;
01797 
01798     return phSUCCESS;
01799 }
01800 
01801 /* ------------------------------------------------------------------------- */
01802 int phX11Window_Resize( struct phX11WindowInfo_t   *window,
01803                         uint32_t                    width,
01804                         uint32_t                    height )
01805 {
01806     phFUNCTION("phX11Window_Resize")
01807     /* XEvent  event; */
01808     Status  xrc     = 0;
01809     Window  wb      = 0;
01810     Window  wv      = 0;
01811     Display *display= NULL;
01812     int     retrc   = phSUCCESS;
01813     
01814     /* Tells Resize to adjust the outer base frame as 
01815      * well as the child window(the one the image is displayed on) */
01816     uint32_t force_frame_resize = 0;
01817         
01818     phCHECK_NULLPTR(window,NULL,"window == NULL");
01819     phCHECK_NULLPTR(window->hints,NULL,"window->hints == NULL");
01820     phCHECK_NULLPTR(window->display,NULL,"window->display == NULL");
01821 
01822     /* XLockDisplay(window->display); */
01823     
01824     /* Set the w/h to the size of the input if either w/h are 
01825      * smaller than the current window size */
01826     /* This ALSO should really never happen if the hints are working */
01827     if ((uint32_t)window->hints->min_width > width) 
01828     {
01829         width = window->hints->min_width;
01830         force_frame_resize = 1;
01831     }
01832     if ((uint32_t)window->hints->min_height > height)
01833     {
01834         height = window->hints->min_height;
01835         force_frame_resize = 1;
01836     }
01837     
01838     if ((height != (uint32_t)window->height) || 
01839         (width != (uint32_t)window->width) || (force_frame_resize))
01840     {
01841         wb = window->base_window;
01842         wv = window->image_window;
01843         display = window->display;
01844 
01845         window->width = width;
01846         window->height = height;
01847 
01848         if (force_frame_resize)
01849         {
01850             DEBUG_PRINT("XResizeWindow\n");
01851             xrc = XResizeWindow(display, wb, width, height);
01852             if (!xrc)
01853             {
01854                 phPRINT_RC(-1,NULL,"XResizeWindow failed with status = %d.",xrc);
01855             }
01856         }
01857     
01858         DEBUG_PRINT("XResizeWindow\n");
01859         xrc = XResizeWindow(display, wv, width, height);
01860         if (!xrc)
01861         {
01862             phPRINT_RC(-1,NULL,"XResizeWindow failed with status = %d.",xrc);
01863         }
01864     
01865         DEBUG_PRINT("XFlush\n");
01866         xrc = XFlush(display);
01867         if (!xrc)
01868         {
01869             phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
01870         }
01871     }
01872     else
01873     {
01874         retrc = phX11Window_NORESIZE;
01875     }
01876     
01877     /* XUnlockDisplay(window->display); */
01878     
01879     return retrc;
01880 error:
01881     /* XUnlockDisplay(window->display); */
01882     
01883     return phFAIL;
01884 }
01885 
01886 /* ------------------------------------------------------------------------- */
01887 int phX11Window_GetSize     ( struct phX11WindowInfo_t  *window,
01888                               uint32_t                  *width,
01889                               uint32_t                  *height  )
01890 {
01891     phFUNCTION("phX11Window_GetSize")
01892 
01893     XWindowAttributes   win_attr;
01894     Status              xrc = 0;
01895 
01896     if (window == NULL) return phFAIL;
01897 
01898     if (width != NULL)
01899     {
01900         (*width) = (uint32_t)window->width;
01901     }
01902 
01903     if (height != NULL)
01904     {
01905         (*height) = (uint32_t)window->height;
01906     }
01907     
01908     /* query the window's attributes. */
01909     DEBUG_PRINT("XGetWindowAttributes\n");
01910     xrc = XGetWindowAttributes(window->display, window->base_window, &win_attr);
01911     if (!xrc)
01912     {
01913         phPRINT_RC(-1,NULL,"XGetWindowAttributes failed with status = %d.",xrc);
01914     }
01915 
01916     if ((uint32_t)win_attr.width != window->width) 
01917     {
01918         DEBUG_PRINT("width out of sync\n");
01919     }
01920     if ((uint32_t)win_attr.height != window->height)
01921     {
01922         DEBUG_PRINT("height out of sync\n");
01923     }
01924 
01925     return phSUCCESS;
01926 }
01927 
01928 /* ------------------------------------------------------------------------- */
01929 int phX11Window_SetMinSize  ( struct phX11WindowInfo_t  *window,
01930                               uint32_t                  min_width,
01931                               uint32_t                  min_height  )
01932 {
01933     phFUNCTION("phX11Window_SetMinSize")
01934     Status  xrc             = 0;
01935     long    xSuppliedReturn = 0;
01936 
01937     if (window == NULL) return phFAIL;
01938     
01939     if ((window->hints != NULL) && (window->display != NULL))
01940     {
01941         DEBUG_PRINT("XGetWMNormalHints\n");
01942         xrc = XGetWMNormalHints(window->display,
01943                                     window->base_window,
01944                                     window->hints,
01945                                     &xSuppliedReturn);
01946         /* if xrc == 1 and xSuppliedReturn has a value == 0, then
01947          * a real error happened, otherwise the function is acknowledging
01948          * the values passed in the hints structure */
01949         if ((xrc) && (!xSuppliedReturn))
01950         {
01951             /*
01952             if (xrc == BadWindow)
01953             {
01954                 DEBUG_PRINT("BadWindow: d:%p bw:%d h:%p\n",
01955                           window->display, window->base_window, window->hints)
01956             }
01957             */
01958             phPRINT_RC(-1,NULL,"XGetWMNormalHints failed. [status:%d supplied_return:%ld]",
01959                      xrc,xSuppliedReturn);
01960         }
01961 
01962         window->hints->flags = 0;
01963         
01964         if (window->hints->min_width < 0)
01965             window->hints->min_width = window->width;
01966         if (window->hints->min_height < 0)
01967             window->hints->min_height = window->height;
01968         if (window->hints->max_width < 0)
01969             window->hints->max_width = window->width;
01970         if (window->hints->max_height < 0)
01971             window->hints->max_height = window->height;
01972             
01973         /* Check to make sure the size settings are within bounds */
01974         if (min_width == 0)     min_width = window->width;
01975         if (min_height == 0)    min_height = window->height;
01976         if (min_width > 4096)   min_width = 4096;
01977         if (min_height > 4096)  min_height = 4096;
01978         if (min_width > (uint32_t)window->hints->max_width)
01979             min_width = window->hints->max_width;
01980         if (min_height > (uint32_t)window->hints->max_height)
01981             min_height = window->hints->max_height;
01982             
01983         /* w & h are the default minimum size settings */
01984         if (min_width != (uint32_t)window->hints->min_width)
01985         {
01986             window->hints->min_width = min_width;
01987             /* Set the flag to apply the MIN setting */
01988             window->hints->flags = PMinSize;
01989         }
01990         if (min_height != (uint32_t)window->hints->min_height)
01991         {
01992             window->hints->min_height = min_height;
01993             /* Set the flag to apply the MIN setting */
01994             window->hints->flags = PMinSize;
01995         }
01996         
01997         /* Apply the hints/settings */
01998         if (window->hints->flags != 0)
01999         {
02000             DEBUG_PRINT("XSetWMNormalHints\n");
02001             XSetWMNormalHints(window->display,
02002                               window->base_window, 
02003                               window->hints );
02004             window->hints->flags = 0;
02005         }        
02006     }
02007     else
02008     {
02009         return phFAIL;
02010     }
02011 
02012     return phSUCCESS;
02013 }
02014 
02015 /* ------------------------------------------------------------------------- */
02016 int phX11Window_GetMinSize  ( struct phX11WindowInfo_t  *window,
02017                               uint32_t                  *min_width,
02018                               uint32_t                  *min_height  )
02019 {
02020     if (window == NULL) return phFAIL;
02021 
02022     if ((min_width != NULL) && (window->hints != NULL))
02023     {
02024         (*min_width) = (uint32_t)window->hints->min_width;
02025     }
02026 
02027     if ((min_height != NULL) && (window->hints != NULL))
02028     {
02029         (*min_height) = (uint32_t)window->hints->min_height;
02030     }
02031     
02032     return phSUCCESS;
02033 }
02034 
02035 /* ------------------------------------------------------------------------- */
02036 int phX11Window_SetMaxSize  ( struct phX11WindowInfo_t  *window,
02037                               uint32_t                  max_width,
02038                               uint32_t                  max_height  )
02039 {
02040     phFUNCTION("phX11Window_SetMaxSize")
02041     Status  xrc             = 0;
02042     long    xSuppliedReturn = 0;
02043 
02044     if (window == NULL) return phFAIL;
02045     
02046     if ((window->hints != NULL) && (window->display != NULL))
02047     {
02048         DEBUG_PRINT("XGetWMNormalHints\n");
02049         xrc = XGetWMNormalHints(window->display,
02050                                     window->base_window,
02051                                     window->hints,
02052                                     &xSuppliedReturn);
02053         /* if xrc == 1 and xSuppliedReturn has a value == 0, then
02054          * a real error happened, otherwise the function is acknowledging
02055          * the values passed in the hints structure */
02056         if ((xrc) && (!xSuppliedReturn))
02057         {
02058             /*
02059             if (xrc == BadWindow)
02060             {
02061                 DEBUG_PRINT("BadWindow: d:%p bw:%d h:%p\n",
02062                           window->display, window->base_window, window->hints)
02063             }
02064             */
02065             phPRINT_RC(-1,NULL,"XGetWMNormalHints failed. [status:%d supplied_return:%ld]",
02066                      xrc,xSuppliedReturn);
02067         }
02068 
02069         window->hints->flags = 0;
02070         
02071         if (window->hints->min_width < 0)
02072             window->hints->min_width = window->width;
02073         if (window->hints->min_height < 0)
02074             window->hints->min_height = window->height;
02075         if (window->hints->max_width < 0)
02076             window->hints->max_width = window->width;
02077         if (window->hints->max_height < 0)
02078             window->hints->max_height = window->height;
02079             
02080         /* SDL uses 4096 because of the size var bit size, I think */
02081         /* it's also resonable to assume that 4096 will never be reached
02082          * unless it's some crazy image capture card or bank of image 
02083          * capture cards being used */
02084         if (max_width > 4096)   max_width = 4096;
02085         if (max_height > 4096)  max_height = 4096;
02086         if (max_width < (uint32_t)window->hints->min_width)
02087             max_width = window->hints->min_width;
02088         if (max_height < (uint32_t)window->hints->min_height)
02089             max_height = window->hints->min_height;
02090         
02091         if (max_width != (uint32_t)window->hints->max_width)
02092         {
02093             window->hints->max_width = max_width;
02094             /* Set the flag to apply the MAX setting */
02095             window->hints->flags = PMaxSize;
02096         }
02097         if (max_height != (uint32_t)window->hints->max_height)
02098         {
02099             window->hints->max_height = max_height;
02100             /* Set the flag to apply the MAX setting */
02101             window->hints->flags = PMaxSize;
02102         }
02103        
02104         /* Going to apply the MAX size settings */
02105         window->hints->flags = PMaxSize;
02106         
02107         /* Apply the hints/settings */
02108         if (window->hints->flags != 0)
02109         {
02110             DEBUG_PRINT("XSetWMNormalHints\n");
02111             XSetWMNormalHints(window->display,
02112                               window->base_window, 
02113                               window->hints );
02114             window->hints->flags = 0;
02115         }
02116     }
02117     else
02118     {
02119         return phFAIL;
02120     }
02121 
02122     return phSUCCESS;
02123 }
02124 
02125 /* ------------------------------------------------------------------------- */
02126 int phX11Window_GetMaxSize  ( struct phX11WindowInfo_t  *window,
02127                               uint32_t                  *max_width,
02128                               uint32_t                  *max_height  )
02129 {
02130     if (window == NULL) return phFAIL;
02131 
02132     if ((max_width != NULL) && (window->hints != NULL))
02133     {
02134         (*max_width) = (uint32_t)window->hints->max_width;
02135     }
02136 
02137     if ((max_height != NULL) && (window->hints != NULL))
02138     {
02139         (*max_height) = (uint32_t)window->hints->max_height;
02140     }
02141     
02142     return phSUCCESS;
02143 }
02144 
02145 /* ------------------------------------------------------------------------- */
02146 int phX11Window_SetSizeLimits( struct phX11WindowInfo_t *window,
02147                                uint32_t                 min_width,
02148                                uint32_t                 min_height,
02149                                uint32_t                 max_width,
02150                                uint32_t                 max_height  )
02151 {
02152     phFUNCTION("phX11Window_SetSizeLimits")
02153     Status  xrc             = 0;
02154     long    xSuppliedReturn = 0;
02155 
02156     if (window == NULL) return phFAIL;
02157     
02158     if ((window->hints != NULL) && (window->display != NULL))
02159     {
02160         DEBUG_PRINT("XGetWMNormalHints\n");
02161         xrc = XGetWMNormalHints(window->display,
02162                                     window->base_window,
02163                                     window->hints,
02164                                     &xSuppliedReturn);
02165         /* if xrc == 1 and xSuppliedReturn has a value == 0, then
02166          * a real error happened, otherwise the function is acknowledging
02167          * the values passed in the hints structure */
02168         if ((xrc) && (!xSuppliedReturn))
02169         {
02170             /*
02171             if (xrc == BadWindow)
02172             {
02173                 DEBUG_PRINT("BadWindow: d:%p bw:%d h:%p\n",
02174                           window->display, window->base_window, window->hints)
02175             }
02176             */
02177             phPRINT_RC(-1,NULL,"XGetWMNormalHints failed. [status:%d supplied_return:%ld]",
02178                      xrc,xSuppliedReturn);
02179         }
02180 
02181         window->hints->flags = 0;
02182        
02183         if (window->hints->min_width < 0)
02184             window->hints->min_width = window->width;
02185         if (window->hints->min_height < 0)
02186             window->hints->min_height = window->height;
02187         if (window->hints->max_width < 0)
02188             window->hints->max_width = window->width;
02189         if (window->hints->max_height < 0)
02190             window->hints->max_height = window->height;
02191             
02192         /* Check to make sure the size settings are within bounds */
02193         if (min_width == 0)     min_width = window->width;
02194         if (min_height == 0)    min_height = window->height;
02195         if (min_width > 4096)   min_width = 4096;
02196         if (min_height > 4096)  min_height = 4096;
02197         if (min_width > (uint32_t)window->hints->max_width)
02198             min_width = window->hints->max_width;
02199         if (min_height > (uint32_t)window->hints->max_height)
02200             min_height = window->hints->max_height;
02201             
02202         /* w & h are the default minimum size settings */
02203         if (min_width != (uint32_t)window->hints->min_width)
02204         {
02205             window->hints->min_width = min_width;
02206             /* Set the flag to apply the MIN setting */
02207             window->hints->flags = PMinSize;
02208         }
02209         if (min_height != (uint32_t)window->hints->min_height)
02210         {
02211             window->hints->min_height = min_height;
02212             /* Set the flag to apply the MIN setting */
02213             window->hints->flags = PMinSize;
02214         }
02215         
02216         /* SDL uses 4096 because of the size var bit size, I think */
02217         /* it's also resonable to assume that 4096 will never be reached
02218          * unless it's some crazy image capture card or bank of image 
02219          * capture cards being used */
02220         if (max_width > 4096)   max_width = 4096;
02221         if (max_height > 4096)  max_height = 4096;
02222         if (max_width < (uint32_t)window->hints->min_width)
02223             max_width = window->hints->min_width;
02224         if (max_height < (uint32_t)window->hints->min_height)
02225             max_height = window->hints->min_height;
02226 
02227         if (max_width != (uint32_t)window->hints->max_width)
02228         {
02229             window->hints->max_width = max_width;
02230             /* Set the flag to apply the MAX setting */
02231             window->hints->flags |= PMaxSize;
02232         }
02233         if (max_height != (uint32_t)window->hints->max_height)
02234         {
02235             window->hints->max_height = max_height;
02236             /* Set the flag to apply the MAX setting */
02237             window->hints->flags |= PMaxSize;
02238         }
02239        
02240         
02241         /* Apply the hints/settings */
02242         if (window->hints->flags != 0)
02243         {
02244             DEBUG_PRINT("XSetWMNormalHints\n");
02245             XSetWMNormalHints(window->display,
02246                               window->base_window, 
02247                               window->hints );
02248             window->hints->flags = 0;
02249         }
02250     }
02251     else
02252     {
02253         return phFAIL;
02254     }
02255 
02256     return phSUCCESS;
02257 }
02258 
02259 /* ------------------------------------------------------------------------- */
02260 int phX11Window_GetSizeLimits( struct phX11WindowInfo_t *window,
02261                                uint32_t                 *min_width,
02262                                uint32_t                 *min_height,
02263                                uint32_t                 *max_width,
02264                                uint32_t                 *max_height  )
02265 {
02266     if (window == NULL) return phFAIL;
02267 
02268     if (window->hints != NULL)
02269     {
02270         if (min_width != NULL)
02271         {
02272             (*min_width) = (uint32_t)window->hints->min_width;
02273         }
02274         
02275         if (min_height != NULL)
02276         {
02277             (*min_height) = (uint32_t)window->hints->min_height;
02278         }
02279         
02280         if (max_width != NULL)
02281         {
02282             (*max_width) = (uint32_t)window->hints->max_width;
02283         }
02284         
02285         if (max_height != NULL)
02286         {
02287             (*max_height) = (uint32_t)window->hints->max_height;
02288         }
02289     }
02290     else
02291     {
02292         return phFAIL;
02293     }
02294     
02295     return phSUCCESS;
02296 }
02297 
02298 /* ------------------------------------------------------------------------- */
02299 int phX11Window_Move  ( struct phX11WindowInfo_t  *window,
02300                         int32_t                   x,
02301                         int32_t                   y )
02302 {
02303     phFUNCTION("phX11Window_SetMinSize")
02304     Status  xrc             = 0;
02305     /* long    xSuppliedReturn = 0; */
02306 
02307     if (window == NULL) return phFAIL;
02308     
02309     if (window->display != NULL)
02310     {
02311         DEBUG_PRINT("XMoveWindow(%d,%d)->(%d,%d)\n",window->x,window->y,x,y);
02312         xrc = XMoveWindow(window->display, window->base_window, 
02313                           x, y);
02314         window->x = x;
02315         window->y = y;
02316         if (!xrc)
02317         {
02318             phPRINT_RC(-1,NULL,"XMoveWindow failed with status = %d.",xrc);
02319         }
02320         
02321         rc = phX11Window_SetLocation(window,x,y);
02322         phPRINT_RC(rc,NULL,"phX11Window_SetLocation");
02323     }
02324     else
02325     {
02326         return phFAIL;
02327     }
02328 
02329     return phSUCCESS;
02330 }
02331 
02332 /* ------------------------------------------------------------------------- */
02333 int phX11Window_TranslateRootCoords ( struct phX11WindowInfo_t  *window,
02334                                       int32_t                   x,
02335                                       int32_t                   y,
02336                                       int32_t                   *tx,
02337                                       int32_t                   *ty  )
02338 {
02339     phFUNCTION("phX11Window_TranslateRootCoords")
02340 
02341     Status              xrc                 = 0;
02342     Bool                xbool               = 0;
02343     /*long                xSuppliedReturn     = 0;*/
02344     Window              child;
02345     XWindowAttributes   attr;
02346     
02347     xrc = XGetWindowAttributes(window->display,
02348                                window->base_window, 
02349                                &attr);
02350     if (!xrc)
02351     {
02352         phPRINT_RC(-1,NULL,"XGetWindowAttributes failed.");
02353     }
02354 
02355     xbool = XTranslateCoordinates(window->display, window->base_window,
02356                                   attr.root, 0, 0, 
02357                                   (int *)tx, (int *)ty, &child);
02358     if (xbool)
02359     {
02360         /* Success */
02361     }
02362     else
02363     {
02364         /* Coordinates on different screens: child=None; tx,ty=0 */
02365     }
02366 
02367     return phSUCCESS;
02368 }
02369 /* ------------------------------------------------------------------------- */
02370 int phX11Window_SetLocation ( struct phX11WindowInfo_t  *window,
02371                               int32_t                   x,
02372                               int32_t                   y  )
02373 {
02374     phFUNCTION("phX11Window_SetLocation")
02375 
02376     Status  xrc                 = 0;
02377     long    xSuppliedReturn     = 0;
02378     int     apply               = 0;
02379     int     retrc               = phSUCCESS;
02380     
02381 #if 0
02382     XWindowAttributes   win_attr;
02383     Window              root_return;
02384     int                 x_return;
02385     int                 y_return;
02386     unsigned int        width_return;
02387     unsigned int        height_return;
02388     unsigned int        border_width_return;
02389     unsigned int        depth_return;
02390 #endif
02391     
02392     if (window == NULL) return phFAIL;
02393 
02394     window->x = (int32_t)x;
02395     window->y = (int32_t)y;
02396 
02397     if ((window->hints != NULL) && (window->display != NULL))
02398     {
02399         DEBUG_PRINT("XGetWMNormalHints\n");
02400         xrc = XGetWMNormalHints(window->display,
02401                                 window->base_window,
02402                                 window->hints,
02403                                 &xSuppliedReturn);
02404         /* if xrc == 1 and xSuppliedReturn has a value == 0, then
02405          * a real error happened, otherwise the function is acknowledging
02406          * the values passed in the hints structure */
02407         if ((xrc) && (!xSuppliedReturn))
02408         {
02409             /*
02410              * if (xrc == BadWindow)
02411              * {
02412              * DEBUG_PRINT("BadWindow: d:%p bw:%d h:%p\n",
02413              * window->display, window->base_window, window->hints)
02414              * }
02415              * */
02416             phPRINT_RC(-1,NULL,"XGetWMNormalHints failed. [status:%d supplied_return:%ld]",
02417                     xrc,xSuppliedReturn);
02418         }
02419         
02420         if (window->hints->x != x)
02421         {
02422             window->hints->x = x;
02423             apply = 1;
02424         }
02425         if (window->hints->y != y)
02426         {
02427             window->hints->y = y;
02428             apply = 1;
02429         }
02430 
02431         if (apply)
02432         {
02433             window->hints->flags = USPosition;
02434         }
02435         else
02436         {
02437             retrc = 1;
02438         }
02439 
02440         /* Apply the hints/settings */
02441         if (apply)
02442         {
02443             DEBUG_PRINT("XSetWMNormalHints\n");
02444             XSetWMNormalHints(window->display,
02445                               window->base_window, 
02446                               window->hints );
02447             window->hints->flags = 0;
02448         }
02449     }
02450 #if 0
02451     xrc = XGetGeometry(window->display, 
02452                            window->base_window,
02453                            &root_return, 
02454                            &x_return, 
02455                            &y_return, 
02456                            &width_return, 
02457                            &height_return, 
02458                            &border_width_return, 
02459                            &depth_return);
02460     if (x_return != window->x) 
02461     {
02462         DEBUG_PRINT("x out of sync: b:%d %d != %d\n",border_width_return,x_return,window->x);
02463     }
02464     if (y_return != window->y)
02465     {
02466         DEBUG_PRINT("y out of sync: b:%d %d != %d\n",border_width_return,y_return,window->y);
02467     }
02468 #elif 0
02469     
02470     /* query the window's attributes. */
02471     DEBUG_PRINT("XGetWindowAttributes\n");
02472     xrc = XGetWindowAttributes(window->display, window->base_window, &win_attr);
02473     if (!xrc)
02474     {
02475         phPRINT_RC(-1,NULL,"XGetWindowAttributes failed.");
02476     }
02477 
02478     if ((uint32_t)win_attr.x != window->x) 
02479     {
02480         DEBUG_PRINT("x out of sync: %u != %u\n",(uint32_t)win_attr.x,window->x);
02481     }
02482     if ((uint32_t)win_attr.y != window->y)
02483     {
02484         DEBUG_PRINT("y out of sync: %u != %u\n",(uint32_t)win_attr.y,window->y);
02485     }
02486 #endif
02487    
02488     return retrc;
02489 }
02490 
02491 /* ------------------------------------------------------------------------- */
02492 int phX11Window_GetLocation ( struct phX11WindowInfo_t  *window,
02493                               int32_t                   *x,
02494                               int32_t                   *y  )
02495 {
02496     phFUNCTION("phX11Window_GetLocation")
02497 
02498 #if 0
02499     XWindowAttributes   win_attr;
02500     Status              xrc = 0;
02501 
02502     Window              root_return             = 0;
02503     int                 x_return                = 0;
02504     int                 y_return                = 0;
02505     unsigned int        width_return            = 0;
02506     unsigned int        height_return           = 0;
02507     unsigned int        border_width_return     = 0;
02508     unsigned int        depth_return            = 0;
02509 #endif
02510     
02511     if (window == NULL) return phFAIL;
02512 
02513     if (x != NULL)
02514     {
02515         (*x) = (uint32_t)window->x;
02516     }
02517 
02518     if (y != NULL)
02519     {
02520         (*y) = (uint32_t)window->y;
02521     }
02522 #if 0
02523     xrc = XGetGeometry(window->display, 
02524                            window->base_window,
02525                            &root_return, 
02526                            &x_return, 
02527                            &y_return, 
02528                            &width_return, 
02529                            &height_return, 
02530                            &border_width_return, 
02531                            &depth_return);
02532     if (x_return != window->x) 
02533     {
02534         DEBUG_PRINT("x out of sync: %d != %d\n",x_return,window->x);
02535     }
02536     if (y_return != window->y)
02537     {
02538         DEBUG_PRINT("y out of sync: %d != %d\n",y_return,window->y);
02539     }
02540 #elif 0
02541     /* query the window's attributes. */
02542     DEBUG_PRINT("XGetWindowAttributes\n");
02543     xrc = XGetWindowAttributes(window->display, window->base_window, &win_attr);
02544     if (!xrc)
02545     {
02546         phPRINT_RC(-1,NUL,"XGetWindowAttributes failed with status = %d.",xrc);
02547     }
02548 
02549     if ((uint32_t)win_attr.x != window->x) 
02550     {
02551         DEBUG_PRINT("x out of sync: %u != %u\n",(uint32_t)win_attr.x,window->x);
02552     }
02553     if ((uint32_t)win_attr.y != window->y)
02554     {
02555         DEBUG_PRINT("y out of sync: %u != %u\n",(uint32_t)win_attr.y,window->y);
02556     }
02557 #endif
02558     return phSUCCESS;
02559 }
02560 
02561 /* ------------------------------------------------------------------------- */
02562 struct phX11EventAtom_t *phX11Window_GetEventAtom( 
02563                                     struct phX11WindowInfo_t *window,
02564                                     const char *name )
02565 {
02566     phFUNCTION("phX11Window_GetEventAtom")
02567     
02568     struct phX11EventAtom_t *event_atom = NULL;
02569     uint32_t                i           = 0;
02570     char *system_name = NULL;
02571     /* int  system_name_length = 0; */
02572     int  system_name_mem_length = 0;
02573     
02574 
02575     if (window != NULL)
02576     {
02577         if ((window->event_atoms != NULL) && (name != NULL))
02578         {
02579             system_name_mem_length = strlen(name) + 256;
02580             
02581             /* allocate the space for the system event atom name */
02582             system_name = (char *)phCalloc(system_name_mem_length,
02583                                             sizeof(char));
02584             phCHECK_NULLPTR(system_name,"phCalloc","phCalloc failed.");
02585             
02586             /* Set the name into the event atom name buffer */
02587             sprintf(system_name,
02588                     "_X11Display_%lld_%s_atom",
02589                     (long long)window->base_window,
02590                     name);
02591             
02592             for (i = 0; i < window->num_event_atoms; i++)
02593             {
02594                 if (strcmp(window->event_atoms[i]->name, system_name) == 0)
02595                 {
02596                     event_atom = window->event_atoms[i];
02597                 }
02598             }
02599 
02600             phFree(system_name);
02601         }
02602     }
02603 error:
02604     return event_atom;
02605 }
02606 
02607 
02608 /* ------------------------------------------------------------------------- */
02609 Display     *phX11Window_GetDisplay( struct phX11WindowInfo_t *window)
02610 {
02611     if (window == NULL) return NULL;
02612     return window->display;
02613 }
02614 /* ------------------------------------------------------------------------- */
02615 static Window phX11Window_GetBaseWindow( struct phX11WindowInfo_t *window)
02616 {
02617     if (window == NULL) return (Window)0;
02618     return window->base_window;
02619 }
02620 /* ------------------------------------------------------------------------- */
02621 uint32_t    phX11Window_GetBaseEventMask( struct phX11WindowInfo_t *window)
02622 {
02623     if (window == NULL) return 0;
02624     return window->base_event_mask;
02625 }
02626 /* ------------------------------------------------------------------------- */
02627 static Window phX11Window_GetImageWindow( struct phX11WindowInfo_t *window)
02628 {
02629     if (window == NULL) return (Window)0;
02630     return window->image_window;
02631 }
02632 /* ------------------------------------------------------------------------- */
02633 uint32_t    phX11Window_GetImageEventMask( struct phX11WindowInfo_t *window)
02634 {
02635     if (window == NULL) return 0;
02636     return window->image_event_mask;
02637 }
02638 /* ------------------------------------------------------------------------- */
02639 int         phX11Window_GetDeleteCmdID( struct phX11WindowInfo_t *window)
02640 {
02641     if (window == NULL) return 0;
02642     return (int)window->WM_DELETE_WINDOW;
02643 }
02644     
02645 /* ------------------------------------------------------------------------- */
02646 /* http://www.the-labs.com/X11/XLib-Manual/graphics/images.html 
02647  * http://www.the-labs.com/X11/XLib-Manual/utilities/manipulating-images.html */
02648 /* ------------------------------------------------------------------------- */
02649 int phX11Image_Create( struct phX11WindowInfo_t   *window,
02650                        struct phX11ImageInfo_t    **pimage )
02651 {
02652     phFUNCTION("phX11Image_Create")
02653    
02654     Status  xrc         = 0;
02655     int     totalBuffers= 2;
02656     int     width       = 0;
02657     int     height      = 0;
02658     int     d           = 0;
02659     int     i           = 0;
02660     /* int xLocked      = 0; */
02661         
02662     struct phX11ImageInfo_t *image = NULL;
02663    
02664     phCHECK_NULLPTR(window,NULL,"Invalid argument: window == NULL");
02665     phCHECK_NULLPTR(pimage,NULL,"Invalid argument: image == NULL");
02666     
02667     image = *pimage = (struct phX11ImageInfo_t *)phCalloc(1,
02668                                         sizeof(struct phX11ImageInfo_t));
02669     phCHECK_NULLPTR(image,"phCalloc","phCalloc failed to allocate image");
02670     
02671     /* allocate memory for the image buffer(s) and actual XImage(s) */
02672     phDALLOC(image->repack_buffer,
02673              image->repack_buffer_size,
02674              totalBuffers,
02675              char * );
02676     phDALLOC(image->image_array,
02677              image->image_array_memsize,
02678              totalBuffers,
02679              XImage * );
02680     phDALLOC(image->repack_buffer_sizes,
02681              image->repack_buffer_sizes_memsize,
02682              totalBuffers,
02683              uint32_t );
02684 
02685     /* initialize the X11 image */
02686     width   = window->width;
02687     height  = window->height;
02688     d       = (window->depth % 8) ? 0 : window->depth / 8;
02689             
02690     if (d == 0)
02691     {
02692         phCHECK_RC(-1,NULL,
02693             "depth isn't a multiple of 8. What am I supposed to do? ");
02694     }
02695     
02696     if (d >= 3) 
02697     {
02698         d = 4;
02699     }
02700 
02701     /* XLockDisplay(window->display); 
02702     xLocked = 1; */
02703 
02704     /* Set the default in the case SHM allocation fails, it's unsupported
02705      * or it's not compiled in */
02706     image->use_shared_mem = 0;
02707 
02708 #if USE_SHARED_MEM()
02709     if (phX11Check_XSHM(window->display))
02710     {
02711         image->shm_info.shmid = shmget(IPC_PRIVATE, 
02712                                        width*height*d*totalBuffers,
02713                                        IPC_CREAT | 0777);
02714         phPRINT_RC(image->shm_info.shmid,"shmget","shmget failed");
02715         
02716         if (image->shm_info.shmid != -1)
02717         {
02718             image->shm_info.readOnly = False;
02719         
02720             image->shm_info.shmaddr = (char *)shmat(image->shm_info.shmid, 0, 0);
02721             if (((intmax_t)image->shm_info.shmaddr) == (intmax_t)-1)
02722             {
02723                 image->shm_info.shmaddr = NULL;
02724                 phPRINT_PTR(((void *)NULL),"shmat",
02725                             "shmat failed to attach to shmid:%d",
02726                             image->shm_info.shmid);
02727             }
02728             else
02729             {
02730                 DEBUG_PRINT("XShmAttach\n");
02731                 xrc = XShmAttach(window->display,
02732                                  &(image->shm_info));
02733                 if (!xrc)
02734                 {
02735                     phPRINT_RC(-1,NULL,
02736                         "XShmAttach failed to attach with status = %d.",xrc);
02737                 }
02738                 else 
02739                 {
02740                     image->use_shared_mem = 1;
02741                 }
02742                 
02743                 DEBUG_PRINT("XFlush\n");
02744                 xrc = XFlush(window->display);
02745                 if (!xrc)
02746                 {
02747                     phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
02748                 }
02749                 /* XSync(window->display, True); */
02750             }
02751         }
02752     }
02753 #endif
02754 
02755     for (i = 0; i < totalBuffers; i++)
02756     {
02757 #if USE_SHARED_MEM()
02758         if (image->use_shared_mem)
02759         {
02760             /* void *shmat(int shmid, const void *shmaddr, int shmflg); */
02761             if (image->shm_info.shmaddr != NULL)
02762             {
02763                 image->repack_buffer[i] = (char *)(image->shm_info.shmaddr +
02764                                                    (width*height*d*sizeof(uint8_t)*i));
02765                 DEBUG_PRINT("XShmCreateImage\n");
02766                 image->image_array[i] = XShmCreateImage(window->display, 
02767                                                         CopyFromParent,
02768                                                         window->depth, 
02769                                                         ZPixmap,
02770                                                         image->repack_buffer[i], 
02771                                                         &(image->shm_info),
02772                                                         width, 
02773                                                         height);
02774                 phCHECK_NULLPTR(image->image_array[i],NULL,"XShmCreateImage failed");
02775 
02776         
02777                 if ((LSBFirst == ImageByteOrder(window->display))) 
02778                 {
02779                     image->image_array[i]->byte_order = MSBFirst;
02780                 } 
02781                 else 
02782                 {
02783                     image->image_array[i]->byte_order = LSBFirst;
02784                 }
02785             }
02786         }
02787 #endif /* USE_SHARED_MEM() */
02788         if (!(image->use_shared_mem))
02789         {
02790             phDALLOC( image->repack_buffer[i],
02791                       image->repack_buffer_sizes[i],
02792                       width * height * d,
02793                       char);
02794         
02795             DEBUG_PRINT("XCreateImage\n");
02796             image->image_array[i] = XCreateImage(window->display,
02797                                                  CopyFromParent,
02798                                                  window->depth,
02799                                                  ZPixmap,
02800                                                  0,
02801                                                  image->repack_buffer[i],
02802                                                  width,
02803                                                  height,
02804                                                  d*8,
02805                                                  0x0
02806                                                 );
02807             phCHECK_NULLPTR(image->image_array[i],NULL,"XCreateImage failed");
02808         
02809             if ((LSBFirst == ImageByteOrder(window->display)))
02810             {
02811                 image->image_array[i]->byte_order = LSBFirst;
02812             } 
02813             else 
02814             {
02815                 image->image_array[i]->byte_order = MSBFirst;
02816             }
02817         }
02818     }
02819     
02820     image->nBuffers     = totalBuffers;
02821     image->width        = width;
02822     image->height       = height;
02823     
02824     image->in_dbytes    = 3; /* image depth, not window depth */
02825     image->in_dbits     = image->in_dbits * 8; /* image depth in bits */
02826     image->in_ri = 0;
02827     image->in_gi = 1;
02828     image->in_bi = 2;
02829     
02830     image->out_dbytes   = d;
02831     image->window_dbits = window->depth;
02832     image->out_dbits    = image->out_dbytes * 8;
02833     
02834     image->red_mask     = window->red_mask;
02835     image->red_shift    = window->red_shift;
02836     image->green_mask   = window->green_mask;
02837     image->green_shift  = window->green_shift;
02838     image->blue_mask    = window->blue_mask;
02839     image->blue_shift   = window->blue_shift;
02840     image->display      = window->display;
02841 
02842     /* XUnlockDisplay(window->display); */
02843     
02844     return phSUCCESS;
02845     
02846 error:
02847     /* if (xLocked == 1)
02848         XUnlockDisplay(window->display); */
02849     
02850     return phFAIL;
02851 }
02852 
02853 /* ------------------------------------------------------------------------- */
02854 #if USE_SHARED_MEM()
02855 int phX11Image_Resize_shm( struct phX11ImageInfo_t *image_buffer,
02856                            uint32_t                 width,
02857                            uint32_t                 height )
02858 {
02859     phFUNCTION("phX11Image_Resize_shm")
02860     Status xrc = 0;
02861     int shmid = 0;
02862     int i = 0;
02863     
02864     /* Make sure we're not wasting our time by checking the current
02865      * size settings of the image buffer */
02866     if ((height == image_buffer->height) && (width == image_buffer->width))
02867     {
02868         goto success;
02869     }
02870  
02871     image_buffer->width = width;
02872     image_buffer->height = height;
02873     
02874     /* XLockDisplay(image_buffer->display); */
02875     
02876     /* 1.) Detach and remove the current shared memory */
02877     DEBUG_PRINT("XShmDetach\n");
02878     xrc = XShmDetach(image_buffer->display, &(image_buffer->shm_info));
02879     if (!xrc)
02880     {
02881         phPRINT_RC(-1,NULL,"XShmDetach failed with status = %d.",xrc);
02882     }
02883     
02884     rc = shmdt(image_buffer->shm_info.shmaddr);
02885     phPRINT_RC(rc,"shmdt","shmdt");
02886     
02887     /* Mark the identifier for removal; No need to worry about
02888      * other processes doing this simultaneously */
02889     rc = shmctl(image_buffer->shm_info.shmid, IPC_RMID, NULL);
02890     phPRINT_RC(rc,"shmctl","shmctl failed IPC_RMID");
02891     
02892     for (i = 0; i < image_buffer->nBuffers; i++ )
02893     {
02894         image_buffer->repack_buffer[i] = 0;
02895     }
02896     
02897     /* 2.) Create a new shared memory segment */
02898     image_buffer->shm_info.shmid = shmid = shmget(IPC_PRIVATE, 
02899                                   (image_buffer->width * 
02900                                    image_buffer->height * 
02901                                    image_buffer->out_dbytes * 
02902                                    image_buffer->nBuffers),
02903                                   IPC_CREAT | 0777);
02904     phCHECK_RC(image_buffer->shm_info.shmid,"shmget","shmget failed");
02905         
02906     image_buffer->shm_info.readOnly = False;
02907     
02908     image_buffer->shm_info.shmaddr = (char *)shmat(shmid,((void*)0x0),0);
02909     if (((intmax_t)image_buffer->shm_info.shmaddr) == (intmax_t)-1)
02910     {
02911         image_buffer->shm_info.shmaddr = NULL;
02912         phPRINT_PTR(((void *)NULL),"shmat",
02913                     "shmat failed to attach to shmid:%d",
02914                     image_buffer->shm_info.shmid);
02915     }
02916     
02917     DEBUG_PRINT("XShmAttach\n");
02918     xrc = XShmAttach(image_buffer->display, &(image_buffer->shm_info));
02919     if (!xrc)
02920     {
02921         phPRINT_RC(-1,NULL,"XShmAttach failed with status = %d.",xrc);
02922     }
02923 
02924     DEBUG_PRINT("XFlush\n");
02925     xrc = XFlush(image_buffer->display);
02926     if (!xrc)
02927     {
02928         phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
02929     }
02930     /* XSync(image_buffer->display, True); */
02931 
02932     /* 3.) Recreate the XImages */
02933     for (i = 0; i < image_buffer->nBuffers; i++)
02934     {
02935         /* 3a.) Destroy the old XImages */
02936         if (image_buffer->image_array[i])
02937         {
02938             image_buffer->image_array[i]->data = NULL;
02939             DEBUG_PRINT("XDestroyImage\n");
02940             xrc = XDestroyImage(image_buffer->image_array[i]);
02941             if (!xrc)
02942             {
02943                 phPRINT_RC(-1,NULL,"XDestroyImage failed.");
02944             }
02945         }
02946 
02947         /* 3b.) Change the values of the previous buffer pointers */
02948         if (image_buffer->shm_info.shmaddr == NULL)
02949         {
02950             image_buffer->repack_buffer[i] = NULL;
02951         }
02952         else
02953         {
02954             image_buffer->repack_buffer[i] = 
02955                                 (char *)(image_buffer->shm_info.shmaddr+
02956                                          (image_buffer->width * 
02957                                           image_buffer->height * 
02958                                           image_buffer->out_dbytes * i)  );
02959         }
02960         /*
02961         phPRINT("%p[%d] = %p + (%d * %d * %d * %d)\n",
02962                 image_buffer->repack_buffer[i],i,
02963                 image_buffer->shm_info.shmaddr,
02964                 image_buffer->width,
02965                 image_buffer->height,
02966                 image_buffer->out_dbytes,
02967                 i);
02968         */
02969                                      
02970         /* 3c.) Create the new XImage(s) */
02971         DEBUG_PRINT("XShmCreateImage\n");
02972         image_buffer->image_array[i] = 
02973                 XShmCreateImage(image_buffer->display, 
02974                                 CopyFromParent,
02975                                 image_buffer->window_dbits, 
02976                                 ZPixmap,
02977                                 image_buffer->repack_buffer[i], 
02978                                 &(image_buffer->shm_info),
02979                                 image_buffer->width, 
02980                                 image_buffer->height );
02981         phCHECK_NULLPTR(image_buffer->image_array[i],NULL,"XShmCreateImage failed");
02982         
02983         if ((LSBFirst == ImageByteOrder(image_buffer->display))) 
02984         {
02985             image_buffer->image_array[i]->byte_order = MSBFirst;
02986         } 
02987         else 
02988         {
02989             image_buffer->image_array[i]->byte_order = LSBFirst;
02990         }
02991     }
02992 
02993 success: 
02994     /* XUnlockDisplay(image_buffer->display); */
02995     
02996     return phSUCCESS;
02997 error:
02998     /* XUnlockDisplay(image_buffer->display); */
02999     
03000     return phFAIL;
03001 }
03002 #endif
03003 
03004 /* ------------------------------------------------------------------------- */
03005 int phX11Image_Resize_std( struct phX11ImageInfo_t *image_buffer,
03006                            uint32_t                 width,
03007                            uint32_t                 height )
03008 {
03009     phFUNCTION("phX11Image_Resize_std")
03010     int     i   = 0;
03011     Status  xrc = 0;
03012     
03013     /* XLockDisplay(image_buffer->display); */
03014     
03015     /* Make sure we're not wasting our time by checking the current
03016      * size settings of the image buffer */
03017     if ((height == image_buffer->height) && (width == image_buffer->width))
03018     {
03019         goto success;
03020     }
03021  
03022     image_buffer->width = width;
03023     image_buffer->height = height;
03024     
03025     for (i = 0; i < image_buffer->nBuffers; i++)
03026     {
03027         /* 1.) Destroy the old XImage structure */
03028         if (image_buffer->image_array[i])
03029         {
03030             image_buffer->image_array[i]->data = NULL;
03031             DEBUG_PRINT("XDestroyImage\n");
03032             xrc = XDestroyImage(image_buffer->image_array[i]);
03033             if (!xrc)
03034             {
03035                 phPRINT_RC(-1,NULL,"XDestroyImage failed with status = %d.",xrc);
03036             }
03037         }
03038 
03039         /* 2.) Resize the memory that was previously allocated */
03040         phDALLOC_RESIZE(image_buffer->repack_buffer[i],
03041                         image_buffer->repack_buffer_sizes[i],
03042                         image_buffer->width * 
03043                         image_buffer->height * 
03044                         image_buffer->out_dbytes,
03045                         char );
03046 
03047         /* 3.) Create the new XImage(s) */
03048         DEBUG_PRINT("XCreateImage\n");
03049         image_buffer->image_array[i] = 
03050                         XCreateImage(
03051                               image_buffer->display,
03052                               CopyFromParent,
03053                               image_buffer->window_dbits,
03054                               ZPixmap,
03055                               0,
03056                               image_buffer->repack_buffer[i],
03057                               image_buffer->width,
03058                               image_buffer->height,
03059                               image_buffer->out_dbits,
03060                               0x0
03061                           );
03062         phCHECK_NULLPTR(image_buffer->image_array[i],NULL,"XCreateImage failed");
03063         
03064         if ((LSBFirst == ImageByteOrder(image_buffer->display)))
03065         {
03066             image_buffer->image_array[i]->byte_order = LSBFirst;
03067         } 
03068         else 
03069         {
03070             image_buffer->image_array[i]->byte_order = MSBFirst;
03071         }
03072     }
03073 
03074 success: 
03075     /* XUnlockDisplay(image_buffer->display); */
03076     
03077     return phSUCCESS;
03078 error:
03079     /* XUnlockDisplay(image_buffer->display); */
03080     
03081     return phFAIL;
03082 }
03083 
03084 /* ------------------------------------------------------------------------- */
03085 int phX11Image_Resize( struct phX11ImageInfo_t *image_buffer,
03086                        uint32_t                 width,
03087                        uint32_t                 height )
03088 {
03089     phFUNCTION("phX11Image_Resize")
03090     
03091     phCHECK_NULLPTR(image_buffer,NULL,"image_buffer == NULL");
03092     
03093     if (image_buffer->use_shared_mem == 1)
03094     {
03095 #if USE_SHARED_MEM()
03096         return phX11Image_Resize_shm( image_buffer, width, height );
03097 #endif
03098     }
03099     else
03100     {
03101         return phX11Image_Resize_std( image_buffer, width, height );
03102     }
03103 error:
03104     return phFAIL;
03105 }
03106 
03107 /* ------------------------------------------------------------------------- */
03108 int phX11Image_GetSize( struct phX11ImageInfo_t *image_buffer,
03109                         uint32_t                *width,
03110                         uint32_t                *height  )
03111 {
03112     if (image_buffer == NULL) return phFAIL;
03113 
03114     if (width != NULL)
03115     {
03116         (*width) = (uint32_t)image_buffer->width;
03117     }
03118 
03119     if (height != NULL)
03120     {
03121         (*height) = (uint32_t)image_buffer->height;
03122     }
03123     
03124     return phSUCCESS;
03125 }
03126 
03127 
03128 /* ------------------------------------------------------------------------- */
03129 int phX11Image_Delete( struct phX11WindowInfo_t *window,
03130                        struct phX11ImageInfo_t  **pimage_buffer)
03131 {
03132     phFUNCTION("phX11Image_Delete")
03133     
03134     struct phX11ImageInfo_t *image_buffer   = NULL;
03135     int                     i               = 0;
03136     Status                  xrc             = 0;
03137 
03138     /* XLockDisplay(window->display); */
03139    
03140     if (pimage_buffer == NULL) return phFAIL;
03141     if ((*pimage_buffer == NULL)) return phSUCCESS;
03142     
03143     image_buffer = *pimage_buffer;
03144     
03145 #if USE_SHARED_MEM()
03146     if (image_buffer->use_shared_mem)
03147     {
03148         if ((image_buffer != NULL) && (window != NULL))
03149         {
03150             DEBUG_PRINT("XShmDetach\n");
03151             xrc = XShmDetach(window->display,
03152                              &(image_buffer->shm_info));
03153             if (!xrc)
03154             {
03155                 phPRINT_RC(-1,NULL,"XShmDetach failed with status = %d.",xrc);
03156             }
03157         }
03158         
03159         rc = shmdt(image_buffer->shm_info.shmaddr);
03160         phPRINT_RC(rc,"shmdt","shmdt failed.");
03161         
03162         /* Mark the identifier for removal; No need to worry about
03163          * other processes doing this simultaneously */
03164         rc = shmctl(image_buffer->shm_info.shmid, IPC_RMID, NULL);
03165         phPRINT_RC(rc,"shmctl","shmctl failed IPC_RMID");
03166     }
03167 #endif
03168    
03169     if (image_buffer != NULL)
03170     {
03171         for (i = 0; i < image_buffer->nBuffers; i++)
03172         {
03173             if (image_buffer->repack_buffer != NULL)
03174             {
03175 //#if (USE_SHARED_MEM() == 0)
03176                 if (image_buffer->use_shared_mem == 0)
03177                 {
03178                         phFree(image_buffer->repack_buffer[i]);
03179                 }
03180                 else
03181 //#endif
03182                 {
03183                     image_buffer->repack_buffer[i] = NULL;
03184                 }
03185             }
03186             if (image_buffer->image_array != NULL)
03187             {
03188                 if (image_buffer->image_array[i])
03189                 {
03190                     image_buffer->image_array[i]->data = NULL;
03191                     DEBUG_PRINT("XDestroyImage\n");
03192                     xrc = XDestroyImage(image_buffer->image_array[i]);
03193                     if (!xrc)
03194                     {
03195                         phPRINT_RC(-1,NULL,"XDestroyImage failed with status = %d.",xrc);
03196                     }
03197                 }
03198             }
03199         }
03200         
03201         phFree(image_buffer->repack_buffer);
03202         phFree(image_buffer->image_array);
03203         phFree(image_buffer->repack_buffer_sizes);
03204     
03205         memset(image_buffer,0,sizeof(struct phX11ImageInfo_t));
03206 
03207         phFree(*pimage_buffer);
03208     }
03209  
03210     /* XUnlockDisplay(window->display); */
03211     
03212     return phSUCCESS;
03213 }
03214 
03215 /* ------------------------------------------------------------------------- */
03216 #define ph_X11_REPACK_RGB_IMAGE(image_buffer,cast_t)        \
03217     {                                                       \
03218         /* assume RGB always */                             \
03219         const int32_t ri = image_buffer->in_ri;             \
03220         const int32_t gi = image_buffer->in_gi;             \
03221         const int32_t bi = image_buffer->in_bi;             \
03222                                                             \
03223         int32_t i = 0;                                      \
03224         const int32_t width     = image_buffer->width;      \
03225         const int32_t height    = image_buffer->height;     \
03226         const int32_t limit     = width * height;           \
03227                                                             \
03228         const int32_t index     = image_buffer->bufIndex;   \
03229         uint8_t       *buf =                                \
03230             (uint8_t *)image_buffer->repack_buffer[index];  \
03231         cast_t        *bufptr = (cast_t *)buf;              \
03232         const int32_t od = (sizeof(cast_t));                \
03233                                                             \
03234         uint8_t       *imgptr = imageData;                  \
03235         const int32_t id = image_buffer->in_dbytes;         \
03236         const int32_t rm = image_buffer->red_mask;          \
03237         const int32_t rs = image_buffer->red_shift;         \
03238         const int32_t gm = image_buffer->green_mask;        \
03239         const int32_t gs = image_buffer->green_shift;       \
03240         const int32_t bm = image_buffer->blue_mask;         \
03241         const int32_t bs = image_buffer->blue_shift;        \
03242                                                             \
03243         const int32_t osize = od * width * height;          \
03244         const int32_t isize = id * width * height;          \
03245                                                             \
03246         const int32_t ori = (int32_t)(rs / 8);              \
03247         const int32_t ogi = (int32_t)(gs / 8);              \
03248         const int32_t obi = (int32_t)(bs / 8);              \
03249                                                             \
03250         /* Don't use memset, it's more inefficient than     \
03251          * settings the pixels individually to 0 before we  \
03252          * copy the values into them */                     \
03253                                                             \
03254         /* Don't memst, this takes way to long to do when   \
03255          * it could be done one byte/word at a time.        \
03256          * below (*bufptr = 0;) is faster because the data  \
03257          * is likely in the cache whereas memset will       \
03258          * write all the data back to mem when it's done. */\
03259         /*memset(bufptr,0,limit*sizeof(cast_t));*/          \
03260         /*                                                  \
03261         phPROGRESS("image_buffer:%p\n",image_buffer);       \
03262         phPROGRESS("index:%d buf:%p bufptr:%p imgptr:%p\n", \
03263                     index, buf, bufptr, imgptr );           \
03264         phPROGRESS("width:%d height:%d limit:%d\n",         \
03265                    width,height,limit);                     \
03266         phPROGRESS("rs:%d gs:%d bs:%d\n",                   \
03267                     rs,gs,bs);                              \
03268         phPROGRESS("ri:%d gi:%d bi:%d\n",                   \
03269                     ri,gi,bi);                              \
03270         phPROGRESS("ori:%d ogi:%d obi:%d\n",                \
03271                     ori,ogi,obi);                           \
03272         */                                                  \
03273         if ((imgptr == NULL) ||                             \
03274             (buf == NULL) || (bufptr == NULL) ||            \
03275             /* if buf[0] == NULL, then the rest are         \
03276              * wrong too */                                 \
03277             (image_buffer->repack_buffer[0] == NULL))       \
03278         {                                                   \
03279             imgptr = NULL;                                  \
03280         }                                                   \
03281         /* The shifting lies on byte boundaries so we can   \
03282          * index into the byte array and set the values     \
03283          * that way */                                      \
03284         else if (((rs % 8) == 0) &&                         \
03285             ((gs % 8) == 0) &&                              \
03286             ((bs % 8) == 0))                                \
03287         {                                                   \
03288             /*phPROGRESS("foo:r%d=%d g%d=%d b%d=%d\n",      \
03289                          ori, ri, ogi, gi, obi, bi ); */    \
03290             if ((ori == ri) && (ogi == gi) && (obi == bi))  \
03291             {                                               \
03292                 /* phPROGRESS("foo:d%d=%d s:%d=%d\n",       \
03293                          id,od,isize,osize); */             \
03294                 if ((id == od) && (isize == osize))         \
03295                 {                                           \
03296                     /* phPROGRESS("memcpy\n"); */           \
03297                     memcpy(buf,imgptr,isize);               \
03298                 }                                           \
03299                 else                                        \
03300                 {                                           \
03301                     /* phPROGRESS("word copy\n"); */        \
03302                     for (i = 0; i < limit; i++)             \
03303                     {                                       \
03304                         memcpy(buf,imgptr,id);              \
03305                         imgptr += id;                       \
03306                         buf += od;                          \
03307                     }                                       \
03308                 }                                           \
03309             }                                               \
03310             else                                            \
03311             {                                               \
03312                 for (i = 0; i < limit; i++)                 \
03313                 {                                           \
03314                     buf[ori] = imgptr[ri];                  \
03315                     buf[ogi] = imgptr[gi];                  \
03316                     buf[obi] = imgptr[bi];                  \
03317                     imgptr += id;                           \
03318                     buf += od;                              \
03319                 }                                           \
03320             }                                               \
03321         }                                                   \
03322         else                                                \
03323         {                                                   \
03324             for (i = 0; i < limit; i++)                     \
03325             {                                               \
03326                 /* Set this to 0 otherwise we'll end up     \
03327                  * with weird results from the |=           \
03328                  * operation */                             \
03329                     *bufptr = 0;                            \
03330                     *bufptr |= (rs > 0) ?                   \
03331                         ((imgptr[ri] & rm) << rs) :         \
03332                         ((imgptr[ri] & rm) >> (rs*-1));     \
03333                     *bufptr |= (gs > 0) ?                   \
03334                         ((imgptr[gi] & gm) << gs) :         \
03335                         ((imgptr[gi] & gm) >> (gs*-1));     \
03336                     *bufptr |= (bs > 0) ?                   \
03337                         ((imgptr[bi] & bm) << bs) :         \
03338                         ((imgptr[bi] & bm) >> (bs*-1));     \
03339                                                             \
03340                     imgptr += id;                           \
03341                     bufptr++;                               \
03342             }                                               \
03343         }                                                   \
03344     }
03345 
03346 /* ------------------------------------------------------------------------- */
03347 /* Old code that converted from 24 to 32 for SHM and regular Image_Put;
03348  * I'm keeping this around just in case. */
03349 /* ------------------------------------------------------------------------- */
03350 #if 0
03351 #if USE_SHARED_MEM()
03352             for (int i = 0; i < elemCount; i++)
03353             {
03354                 memcpy((void *)&(buf[(i*4)]),
03355                         &imageData[(i*3)],
03356                         sizeof(uint8_t) * 3);
03357             }
03358 #else
03359             for (int i = 0; i < elemCount; i++)
03360             {
03361                 memcpy((void *)&(buf[(i*4)+1]),
03362                         &imageData[(i*3)],
03363                         sizeof(uint8_t) * 3);
03364             }
03365 #endif  
03366 #endif
03367 
03368 /* -------------------------------------------------------------------------- */
03369 inline void ph_x11_repack_image_To16Bits( 
03370                                 struct phX11ImageInfo_t   *image_buffer, 
03371                                 uint8_t         *imageData )
03372 {
03373     phFUNCTION("ph_x11_repack_image_To16Bits")
03374     ph_X11_REPACK_RGB_IMAGE(image_buffer,uint16_t);
03375 }
03376 
03377 /* ------------------------------------------------------------------------- */
03378 inline void ph_x11_repack_image_To32Bits( 
03379                                 struct phX11ImageInfo_t   *image_buffer, 
03380                                 uint8_t         *imageData )
03381 {
03382     phFUNCTION("ph_x11_repack_image_To32Bits")
03383 #if 1
03384     ph_X11_REPACK_RGB_IMAGE(image_buffer,uint32_t);
03385 #else
03386     /* This is useful for debugging the code;
03387      * it's easier to manage the code in the macro however */
03388 
03389     /* :.s/\\$// :.s/cast_t/uint32_t/g */
03390     {                                                       
03391         /* assume RGB always */                             
03392         const int32_t ri = image_buffer->in_ri;             
03393         const int32_t gi = image_buffer->in_gi;             
03394         const int32_t bi = image_buffer->in_bi;             
03395                                                             
03396         int32_t i = 0;                                      
03397         const int32_t width     = image_buffer->width;      
03398         const int32_t height    = image_buffer->height;     
03399         const int32_t limit     = width * height;           
03400                                                             
03401         const int32_t index     = image_buffer->bufIndex;   
03402         uint8_t       *buf =                                
03403             (uint8_t *)image_buffer->repack_buffer[index];  
03404         uint32_t      *bufptr = (uint32_t *)buf;              
03405         const int32_t od = (sizeof(uint32_t));                
03406                                                             
03407         uint8_t       *imgptr = imageData;                  
03408         const int32_t id = image_buffer->in_dbytes;         
03409         const int32_t rm = image_buffer->red_mask;          
03410         const int32_t rs = image_buffer->red_shift;         
03411         const int32_t gm = image_buffer->green_mask;        
03412         const int32_t gs = image_buffer->green_shift;       
03413         const int32_t bm = image_buffer->blue_mask;         
03414         const int32_t bs = image_buffer->blue_shift;        
03415                                                             
03416         const int32_t osize = od * width * height;          
03417         const int32_t isize = id * width * height;          
03418                                                             
03419         const int32_t ori = (int32_t)(rs / 8);              
03420         const int32_t ogi = (int32_t)(gs / 8);              
03421         const int32_t obi = (int32_t)(bs / 8);              
03422                                                             
03423         /* Don't use memset, it's more inefficient than     
03424          * settings the pixels individually to 0 before we  
03425          * copy the values into them */                     
03426                                                             
03427         /* Don't memst, this takes way to long to do when   
03428          * it could be done one byte/word at a time.        
03429          * below (*bufptr = 0;) is faster because the data  
03430          * is likely in the cache whereas memset will       
03431          * write all the data back to mem when it's done. */
03432         /*memset(bufptr,0,limit*sizeof(cast_t));*/          
03433         /*
03434         phPROGRESS("image_buffer:%p\n",image_buffer);
03435         phPROGRESS("index:%d buf:%p bufptr:%p imgptr:%p\n",
03436                     index, buf, bufptr, imgptr );
03437         phPROGRESS("width:%d height:%d limit:%d\n",
03438                    width,height,limit);
03439         phPROGRESS("rs:%d gs:%d bs:%d\n",                    
03440                     rs,gs,bs);                             
03441         phPROGRESS("ri:%d gi:%d bi:%d\n",                    
03442                     ri,gi,bi);                             
03443         phPROGRESS("ori:%d ogi:%d obi:%d\n",                 
03444                     ori,ogi,obi);                          
03445         */
03446         if ((imgptr == NULL) || 
03447             (buf == NULL) || 
03448             (bufptr == NULL) ||
03449             /* if buf[0] == NULL, then the rest are wrong too */
03450             (image_buffer->repack_buffer[0] == NULL))
03451         {
03452             imgptr = NULL;
03453         }
03454         /* The shifting lies on byte boundaries so we can   
03455          * index into the byte array and set the values     
03456          * that way */                                      
03457         else if (((rs % 8) == 0) &&                              
03458                  ((gs % 8) == 0) &&                              
03459                  ((bs % 8) == 0))                                
03460         {                                                   
03461             /*phPROGRESS("foo:r%d=%d g%d=%d b%d=%d\n",        
03462                          ori, ri, ogi, gi, obi, bi ); */    
03463             if ((ori == ri) && (ogi == gi) && (obi == bi))  
03464             {                                               
03465                 /* phPROGRESS("foo:d%d=%d s:%d=%d\n",         
03466                          id,od,isize,osize); */             
03467                 if ((id == od) && (isize == osize))         
03468                 {                                           
03469                     /* phPROGRESS("memcpy\n"); */             
03470                     memcpy(buf,imgptr,isize);               
03471                 }                                           
03472                 else                                        
03473                 {                                           
03474                     /* phPROGRESS("word copy\n"); */          
03475                     for (i = 0; i < limit; i++)             
03476                     {                                       
03477                         memcpy(buf,imgptr,id);              
03478                         imgptr += id;                       
03479                         buf += od;                          
03480                     }                                       
03481                 }                                           
03482             }                                               
03483             else                                            
03484             {                                               
03485                 for (i = 0; i < limit; i++)                 
03486                 {                                           
03487                     buf[ori] = imgptr[ri];                  
03488                     buf[ogi] = imgptr[gi];                  
03489                     buf[obi] = imgptr[bi];                  
03490                     imgptr += id;                           
03491                     buf += od;                              
03492                 }                                           
03493             }                                               
03494         }                                                   
03495         else                                                
03496         {                                                   
03497             for (i = 0; i < limit; i++)                     
03498             {                                               
03499                 /* Set this to 0 otherwise we'll end up     
03500                  * with weird results from the |=           
03501                  * operation */                             
03502                     *bufptr = 0;                            
03503                     *bufptr |= (rs > 0) ?                   
03504                         ((imgptr[ri] & rm) << rs) :         
03505                         ((imgptr[ri] & rm) >> (rs*-1));     
03506                     *bufptr |= (gs > 0) ?                   
03507                         ((imgptr[gi] & gm) << gs) :         
03508                         ((imgptr[gi] & gm) >> (gs*-1));     
03509                     *bufptr |= (bs > 0) ?                   
03510                         ((imgptr[bi] & bm) << bs) :         
03511                         ((imgptr[bi] & bm) >> (bs*-1));     
03512                                                             
03513                     imgptr += id;                           
03514                     bufptr++;                               
03515             }                                               
03516         }                                                   
03517     }
03518 
03519 #endif
03520 }
03521 
03522 /* ------------------------------------------------------------------------- */
03523 phX11EventInfo phX11EventInfo_Create()
03524 {
03525     return (phX11EventInfo)phCalloc(1,sizeof(phX11EventInfo_t));
03526 }
03527 
03528 /* ------------------------------------------------------------------------- */
03529 void phX11EventInfo_Destroy(phX11EventInfo event)
03530 {
03531     if (event != NULL) phFree(event);
03532 }
03533 
03534 /* ------------------------------------------------------------------------- */
03535 void phX11Flush( phX11WindowInfo window )
03536 {
03537     XPending(phX11Window_GetDisplay(window));
03538 }
03539 
03540 /* ------------------------------------------------------------------------- */
03541 int phX11Pending( phX11WindowInfo window )
03542 {
03543     return XPending(phX11Window_GetDisplay(window));
03544 }
03545 
03546 /* ------------------------------------------------------------------------- */
03547 void phX11NextEvent( phX11WindowInfo window,
03548                      phX11EventInfo  event )
03549 {
03550     if (event == NULL) return;
03551     XNextEvent(phX11Window_GetDisplay(window),&(event->event));
03552 }
03553 
03554 /* ------------------------------------------------------------------------- */
03555 /* The most recent event is returned in the 'event' parameter */
03556 int phX11FlushToRecent_BaseWindow( phX11WindowInfo window,
03557                                    int             event_id,
03558                                    phX11EventInfo  event    )
03559 {
03560     XEvent e;
03561     XEvent e1;
03562     int retrc = 0;
03563     while (XCheckTypedWindowEvent(phX11Window_GetDisplay(window),
03564                                   phX11Window_GetBaseWindow(window),
03565                                   event_id,
03566                                   &e) == True)
03567     {
03568         e1 = e;
03569         retrc = 1;
03570     }
03571 
03572     if ((retrc == 1) && (event != NULL))
03573     {
03574         event->event = e1;
03575     }
03576 
03577     return retrc;
03578 }
03579 
03580 /* ------------------------------------------------------------------------- */
03581 /* The most recent event is returned in the 'event' parameter */
03582 int phX11FlushToRecent_ImageWindow( phX11WindowInfo window,
03583                                     int             event_id,
03584                                     phX11EventInfo  event    )
03585 {
03586     XEvent e;
03587     XEvent e1;
03588     int retrc = 0;
03589     while (XCheckTypedWindowEvent(phX11Window_GetDisplay(window),
03590                                   phX11Window_GetImageWindow(window),
03591                                   event_id,
03592                                   &e) == True)
03593     {
03594         e1 = e;
03595         retrc = 1;
03596     }
03597 
03598     if ((retrc == 1) && (event != NULL))
03599     {
03600         event->event = e1;
03601     }
03602 
03603     return retrc;
03604 }
03605 
03606 /* ------------------------------------------------------------------------- */
03607 int phX11Event_FromBaseWindow( phX11WindowInfo window,
03608                                phX11EventInfo  event )
03609 {
03610     if (event == NULL) return 0;
03611     return (event->event.xany.window == 
03612             phX11Window_GetBaseWindow(window) ? 1 : 0); 
03613 }
03614 
03615 /* ------------------------------------------------------------------------- */
03616 int phX11Event_FromImageWindow( phX11WindowInfo window,
03617                                 phX11EventInfo  event )
03618 {
03619     if (event == NULL) return 0;
03620     return (event->event.xany.window == 
03621             phX11Window_GetImageWindow(window) ? 1 : 0); 
03622 }
03623 
03624 /* ------------------------------------------------------------------------- */
03625 int  phX11Event_GetType( phX11EventInfo  event )
03626 {
03627     if (event == NULL) return 0;
03628     return event->event.type;
03629 }
03630 
03631 /* ------------------------------------------------------------------------- */
03632 void phX11Event_GetXConfigureInfo( phX11EventInfo  e,
03633                                    uint32_t        *w,
03634                                    uint32_t        *h,
03635                                    int32_t         *x,
03636                                    int32_t         *y,
03637                                    int32_t         *send_event )
03638 {
03639     if (e != NULL)
03640     {
03641         if (w != NULL) 
03642             *w          = e->event.xconfigure.width;
03643         if (h != NULL)
03644             *h          = e->event.xconfigure.height;
03645         if (x != NULL)
03646             *x          = e->event.xconfigure.x;
03647         if (y != NULL)
03648             *y          = e->event.xconfigure.y;
03649         if (send_event != NULL)
03650             *send_event = e->event.xconfigure.send_event;
03651     }
03652 }
03653 
03654 /* ------------------------------------------------------------------------- */
03655 void phX11Event_GetXClientInfo( phX11EventInfo  e,
03656                                 int             *format,
03657                                 long            *l_0,
03658                                 long            *l_1,
03659                                 long            *l_2 )
03660 {
03661     if (e != NULL)
03662     {
03663         if (format)            *format = e->event.xclient.format;
03664         if (l_0 != NULL)       *l_0    = e->event.xclient.data.l[0];
03665         if (l_1 != NULL)       *l_1    = e->event.xclient.data.l[1];
03666         if (l_2 != NULL)       *l_2    = e->event.xclient.data.l[2];
03667     }
03668 }
03669 
03670 /* ------------------------------------------------------------------------- */
03671 int64_t phX11KeycodeToKeysym( phX11WindowInfo window,
03672                               phX11EventInfo  event   )
03673 {
03674     Display *display = phX11Window_GetDisplay(window);
03675     int64_t val = (KeySym)XKeycodeToKeysym(display,
03676                                            event->event.xkey.keycode, 
03677                                            0);
03678     return val;
03679 }
03680 
03681 /* ------------------------------------------------------------------------- */
03682 #ifdef __cplusplus
03683 } /* extern "C" { */
03684 #endif
03685 
03686 /* ------------------------------------------------------------------------- */
03687 int phX11Image_Put( struct phX11WindowInfo_t    *window,
03688                     struct phX11ImageInfo_t     *image_buffer,
03689                     phImage                     *image )
03690 {
03691     phFUNCTION("phX11Image_Put")
03692     int xLocked = 0;
03693     /* if we need to redraw, then redraw */
03694 
03695     /* TODO: Check window, image_buffer and image substructures */
03696 
03697     if ((image != NULL) && (image_buffer != NULL) && 
03698         (window != NULL) && (window->display != NULL))
03699     {
03700         Status  xrc         = 0;
03701         int     index       = image_buffer->bufIndex;
03702         XImage  *ximage     = image_buffer->image_array[index];
03703         uint8_t *imageData  = NULL;
03704         
03705 #if USE_XF86SYNC()
03706         int viewPort_x = 0;
03707         int viewPort_y = 0;
03708 #endif
03709    
03710         /* XLockDisplay(window->display); */
03711         xLocked = 1;
03712     
03713         if (image_buffer->use_shared_mem == 1)
03714         {
03715 #if USE_SHARED_MEM()
03716             XEvent event;
03717             /* Get the completion event or drop out */
03718             DEBUG_PRINT("XShmGetEventBase\n");
03719             int CompletionType = XShmGetEventBase (window->display) + 
03720                                  ShmCompletion;
03721             
03722             if ((image_buffer->refresh_wait == 1) && (0))
03723             {
03724                 DEBUG_PRINT("XCheckTypedEvent\n");
03725                 if (XCheckTypedEvent(window->display,
03726                             CompletionType,
03727                             &event) == False)
03728                 {
03729                     /* Didn't fail, didn't succeed */
03730                     return 1;
03731                 }
03732                 image_buffer->refresh_wait = 0;
03733             }
03734 #endif
03735         }
03736      
03737 #if USE_XF86SYNC()
03738         DEBUG_PRINT("XF86VidModeGetViewPort\n");
03739         XF86VidModeGetViewPort( window->display, 
03740                                 window->screen_number, 
03741                                 &viewPort_x, &viewPort_y );
03742         DEBUG_PRINT("XF86VidModeSetViewPort\n");
03743         XF86VidModeSetViewPort( window->display, 
03744                                 window->screen_number, 
03745                                 viewPort_x,  viewPort_y  );
03746 #endif
03747         /* reformat if needed */
03748         if ((!(image->getFormat() & (phX11UtilValidFormats))) ||
03749             (image->getFormat() & phImageSpecialMask))
03750         {
03751             rc = image->convert(phX11UtilValidFormats);
03752             phCHECK_RC(rc,NULL,"this->m_image.convert() failed.");
03753         }
03754         
03755         rc = image->resize(  image_buffer->width, image_buffer->height );
03756         if (rc) goto error;
03757 
03758         imageData = (uint8_t *)image->getData();
03759         if (imageData == NULL) goto error;
03760 
03761         /* make sure the in byte/bit sizes are correct */
03762         if (image->getFormat() & phImageRGB24)
03763         {
03764             image_buffer->in_dbytes = 3;
03765             image_buffer->in_dbits = 3*8;
03766             image_buffer->in_ri = 0;
03767             image_buffer->in_gi = 1;
03768             image_buffer->in_bi = 2;
03769         }
03770         else if (image->getFormat() & phImageRGBA32)
03771         {
03772             image_buffer->in_dbytes = 4;
03773             image_buffer->in_dbits = 4*8;
03774             image_buffer->in_ri = 0;
03775             image_buffer->in_gi = 1;
03776             image_buffer->in_bi = 2;
03777         }
03778         else if (image->getFormat() & phImageBGRA32)
03779         {
03780             image_buffer->in_dbytes = 4;
03781             image_buffer->in_dbits = 4*8;
03782             image_buffer->in_ri = 2;
03783             image_buffer->in_gi = 1;
03784             image_buffer->in_bi = 0;
03785         }
03786 
03787         /* Copy the image data into the correct alignment */
03788         /* repack the data if necessary */
03789         if (window->depth >= 24)
03790         {
03791             ph_x11_repack_image_To32Bits( image_buffer, imageData );
03792         }   
03793         else if (window->depth == 16)
03794         {
03795             ph_x11_repack_image_To16Bits( image_buffer, imageData );
03796         }
03797 
03798         if (image_buffer->use_shared_mem == 1)
03799         {
03800 #if USE_SHARED_MEM()       
03801             if (image_buffer->shm_info.shmid > 0)
03802             {
03803                 DEBUG_PRINT("XShmPutImage\n");
03804                 xrc = XShmPutImage( window->display,/* Display *display */ 
03805                                     window->drawable,/* Drawable drawable*/
03806                                     window->gc,     /* GC gc */
03807                                     ximage,         /* XImage *image */
03808                                     0,              /* int src_x  */
03809                                     0,              /* int src_y  */
03810                                     0,              /* int dest_x */
03811                                     0,              /* int dest_y */
03812                                     window->width,  /* unsigned int width  */
03813                                     window->height, /* unsigned int height */
03814                                     True            /* Boolean send_event  */
03815                                     );
03816                 if (!xrc)
03817                 {
03818                     phPRINT_RC(-1,NULL,"XShmPutImage failed with status = %d.",xrc);
03819                 }
03820                 else
03821                 {
03822                     image_buffer->refresh_wait = 1;
03823                 }
03824             }
03825             else
03826             {
03827                 /* phPRINT ERROR ?? */
03828             }
03829 #endif
03830         }
03831         else
03832         {
03833             DEBUG_PRINT("XPutImage\n");
03834             xrc = XPutImage(window->display,    /* Display *display     */
03835                             window->drawable,   /* Drawable drawable    */
03836                             window->gc,         /* GC gc                */
03837                             ximage,             /* XImage *image        */
03838                             0,                  /* int src_x            */
03839                             0,                  /* int src_y            */
03840                             0,                  /* int dest_x           */
03841                             0,                  /* int dest_y           */
03842                             window->width,      /* unsigned int width   */
03843                             window->height      /* unsigned int height  */
03844                             );
03845             if (xrc)
03846             {
03847                 phPRINT_RC(-1,NULL,"XPutImage failed with status = %d.",xrc);
03848             }
03849         }    
03850         
03851 #if USE_DOUBLEBUFFER_EXT()
03852         if (window->use_xdbe)
03853         {
03854             /* Swap the DBE back buffer with the front */
03855             /*----------------------------------------------------------*
03856              * Status XdbeSwapBuffers(  Display      *dpy,
03857              *                          XdbeSwapInfo *swap_info,
03858              *                          int          num_windows)
03859              *                          
03860              * XdbeSwapInfo structure has the following fields:
03861              *  Window            swap_window
03862              *  XdbeSwapAction    swap_action
03863              *----------------------------------------------------------*/
03864             DEBUG_PRINT("XdbeSwapBuffers\n");
03865             xrc = XdbeSwapBuffers(window->display,
03866                                   &(window->swap_info),
03867                                   1 /* num_windows */);
03868             if (!xrc)
03869             {
03870                 phPRINT_RC(-1,NULL,"XdbeSwapBuffers failed with status = %d.",xrc);
03871             }
03872         }
03873 #endif
03874         
03875         /* Make sure all the pending X server commands are finished
03876          * before continuing [3] */
03877         /* Flush out whatever operation was performed above */
03878         DEBUG_PRINT("XFlush\n");
03879         xrc = XFlush(window->display);
03880         if (!xrc)
03881         {
03882             phPRINT_RC(-1,NULL,"XFlush failed with status = %d.",xrc);
03883         }
03884 
03885 #if USE_XF86SYNC()
03886         DEBUG_PRINT("XF86VidModeGetViewPort\n");
03887         XF86VidModeGetViewPort( window->display, 
03888                                 window->screen_number, 
03889                                 &viewPort_x, &viewPort_y  );
03890         DEBUG_PRINT("XF86VidModeSetViewPort\n");
03891         XF86VidModeSetViewPort( window->display, 
03892                                 window->screen_number, 
03893                                 viewPort_x, viewPort_y  );
03894 #endif
03895 
03896     }
03897     else
03898     {
03899         return phFAIL;
03900     }
03901 
03902     image_buffer->bufIndex = (++(image_buffer->bufIndex)) % 
03903                                             image_buffer->nBuffers;
03904 
03905     /* if (xLocked == 1)
03906         XUnlockDisplay(window->display); */
03907     
03908     return phSUCCESS;
03909 error:
03910     /* if (xLocked == 1)
03911         XUnlockDisplay(window->display); */
03912     
03913     return phFAIL;
03914 }
03915 
03916 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:03 2007 for phission by  doxygen 1.4.4