X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fx11.c;h=66f4a3efc69b597beabb09091e23a01a57b02025;hb=a7c06161253796a30a0237a7f5a044f459c8cf35;hp=61d1a1a5d2b06d7759ea32533004215b3ffe6286;hpb=de8b3ae622eae10f1caf96872fb1790f7bd9644b;p=rocksndiamonds.git diff --git a/src/libgame/x11.c b/src/libgame/x11.c index 61d1a1a5..66f4a3ef 100644 --- a/src/libgame/x11.c +++ b/src/libgame/x11.c @@ -1,7 +1,7 @@ /*********************************************************** * Artsoft Retro-Game Library * *----------------------------------------------------------* -* (c) 1994-2002 Artsoft Entertainment * +* (c) 1994-2006 Artsoft Entertainment * * Holger Schemel * * Detmolder Strasse 189 * * 33604 Bielefeld * @@ -22,7 +22,14 @@ static void X11InitDisplay(); static DrawWindow *X11InitWindow(); -inline void X11InitVideoDisplay(void) +static int X11DebugErrorHandler(Display *display, XErrorEvent *event) +{ + int x = 0; + + return 1 / x; /* !!! crash program to give backtrace in gdb !!! */ +} + +void X11InitVideoDisplay(void) { /* initialize X11 video */ X11InitDisplay(); @@ -31,15 +38,23 @@ inline void X11InitVideoDisplay(void) video.default_depth = XDefaultDepth(display, screen); } -inline void X11InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window) +void X11InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window) { + if (*window != NULL) + X11CloseWindow(*window); + *window = X11InitWindow(); XMapWindow(display, (*window)->drawable); + FlushDisplay(); /* create additional (off-screen) buffer for double-buffering */ +#if 1 + ReCreateBitmap(backbuffer, video.width, video.height, video.depth); +#else *backbuffer = CreateBitmap(video.width, video.height, video.depth); +#endif } static void X11InitDisplay() @@ -55,6 +70,14 @@ static void X11InitDisplay() Error(ERR_EXIT, "cannot connect to X server %s", XDisplayName(options.display_name)); + if (options.debug_x11_sync) + { + Error(ERR_WARN, "running in X11 synchronous mode (debug only)"); + + XSynchronize(display, True); + XSetErrorHandler(X11DebugErrorHandler); + } + screen = DefaultScreen(display); visual = DefaultVisual(display, screen); depth = DefaultDepth(display, screen); @@ -87,46 +110,36 @@ static DrawWindow *X11InitWindow() DrawWindow *new_window = CreateBitmapStruct(); unsigned int border_width = 4; XGCValues gc_values; - unsigned long gc_valuemask; + unsigned int gc_valuemask; #if !defined(PLATFORM_MSDOS) XTextProperty windowName, iconName; Pixmap icon_pixmap, iconmask_pixmap; unsigned int icon_width, icon_height; int icon_hot_x, icon_hot_y; -#if 0 - char icon_filename[256]; -#endif XSizeHints size_hints; XWMHints wm_hints; XClassHint class_hints; char *window_name = program.window_title; char *icon_name = program.window_title; - long window_event_mask; + int window_event_mask; Atom proto_atom = None, delete_atom = None; #endif int screen_width, screen_height; int win_xpos, win_ypos; - unsigned long pen_fg = WhitePixel(display,screen); - unsigned long pen_bg = BlackPixel(display,screen); + unsigned int pen_fg = WhitePixel(display, screen); + unsigned int pen_bg = BlackPixel(display, screen); const int width = video.width, height = video.height; int i; -#if 0 -#if !defined(PLATFORM_MSDOS) - static struct IconFileInfo icon_pic = - { - "rocks_icon.xbm", - "rocks_iconmask.xbm" - }; -#endif -#endif - screen_width = XDisplayWidth(display, screen); screen_height = XDisplayHeight(display, screen); win_xpos = (screen_width - width) / 2; win_ypos = (screen_height - height) / 2; + new_window->width = width; + new_window->height = height; + new_window->drawable = XCreateSimpleWindow(display, RootWindow(display, screen), win_xpos, win_ypos, @@ -140,10 +153,6 @@ static DrawWindow *X11InitWindow() XChangeProperty(display, new_window->drawable, proto_atom, XA_ATOM, 32, PropModePrepend, (unsigned char *) &delete_atom, 1); -#if 0 - sprintf(icon_filename, "%s/%s", options.graphics_directory, - icon_pic.picture_filename); -#endif if (XReadBitmapFile(display, new_window->drawable, getCustomImageFilename(program.x11_icon_filename), &icon_width, &icon_height, &icon_pixmap, @@ -151,10 +160,6 @@ static DrawWindow *X11InitWindow() Error(ERR_EXIT, "cannot read icon bitmap file '%s'", program.x11_icon_filename); -#if 0 - sprintf(icon_filename, "%s/%s", options.graphics_directory, - icon_pic.picturemask_filename); -#endif if (XReadBitmapFile(display, new_window->drawable, getCustomImageFilename(program.x11_iconmask_filename), &icon_width, &icon_height, &iconmask_pixmap, @@ -198,12 +203,10 @@ static DrawWindow *X11InitWindow() /* Select event types wanted */ window_event_mask = ExposureMask | StructureNotifyMask | FocusChangeMask | - ButtonPressMask | ButtonReleaseMask | PointerMotionMask | + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | PointerMotionHintMask | KeyPressMask | KeyReleaseMask; - /* unwanted mouse motion events now get filtered out by filter function */ - /* window_event_mask |= PointerMotionHintMask; */ - XSelectInput(display, new_window->drawable, window_event_mask); #endif @@ -216,7 +219,7 @@ static DrawWindow *X11InitWindow() XCreateGC(display, new_window->drawable, gc_valuemask, &gc_values); /* create GCs for line drawing (black and white) */ - for(i=0; i<2; i++) + for (i = 0; i < 2; i++) { gc_values.graphics_exposures = False; gc_values.foreground = (i ? pen_fg : pen_bg); @@ -235,6 +238,20 @@ static DrawWindow *X11InitWindow() return new_window; } +void X11CloseWindow(DrawWindow *window) +{ + if (window->drawable) + { + XUnmapWindow(display, window->drawable); + XDestroyWindow(display, window->drawable); + } + + if (window->gc) + XFreeGC(display, window->gc); + + free(window); +} + void X11ZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap) { #if defined(TARGET_ALLEGRO) @@ -272,7 +289,7 @@ Bitmap *X11LoadImage(char *filename) char *error = "Read_PCX_to_Pixmap(): %s '%s'"; int pcx_err; XGCValues clip_gc_values; - unsigned long clip_gc_valuemask; + unsigned int clip_gc_valuemask; pcx_err = Read_PCX_to_Pixmap(display, window->drawable, window->gc, filename, &new_bitmap->drawable, &new_bitmap->clip_mask); @@ -330,8 +347,8 @@ Bitmap *X11LoadImage(char *filename) return new_bitmap; } -inline void X11CreateBitmapContent(Bitmap *new_bitmap, - int width, int height, int depth) +void X11CreateBitmapContent(Bitmap *new_bitmap, + int width, int height, int depth) { Pixmap pixmap; @@ -350,7 +367,7 @@ inline void X11CreateBitmapContent(Bitmap *new_bitmap, new_bitmap->line_gc[1] = window->line_gc[1]; } -inline void X11FreeBitmapPointers(Bitmap *bitmap) +void X11FreeBitmapPointers(Bitmap *bitmap) { /* The X11 version seems to have a memory leak here -- although "XFreePixmap()" is called, the corresponding memory seems not @@ -369,30 +386,47 @@ inline void X11FreeBitmapPointers(Bitmap *bitmap) bitmap->stored_clip_gc = None; } -inline void X11CopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap, - int src_x, int src_y, int width, int height, - int dst_x, int dst_y, int mask_mode) +void X11CopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap, + int src_x, int src_y, int width, int height, + int dst_x, int dst_y, int mask_mode) { XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable, (mask_mode == BLIT_MASKED ? src_bitmap->clip_gc : dst_bitmap->gc), src_x, src_y, width, height, dst_x, dst_y); } -inline void X11FillRectangle(Bitmap *bitmap, int x, int y, - int width, int height, Pixel color) +void X11FillRectangle(Bitmap *bitmap, int x, int y, + int width, int height, Pixel color) { XSetForeground(display, bitmap->gc, color); XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height); } -inline void X11DrawSimpleLine(Bitmap *bitmap, int from_x, int from_y, - int to_x, int to_y, Pixel color) +void X11FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height, + int fade_mode, int fade_delay, int post_delay, + void (*draw_border_function)(void)) +{ + /* fading currently not supported -- simply copy backbuffer to screen */ + + if (fade_mode == FADE_MODE_FADE_OUT) + X11FillRectangle(backbuffer, x, y, width, height, BLACK_PIXEL); + + if (draw_border_function != NULL) + draw_border_function(); + + X11CopyArea(backbuffer, window, x, y, width, height, x, y, BLIT_OPAQUE); + + /* as we currently cannot use the fade delay, also do not use post delay */ +} + +void X11DrawSimpleLine(Bitmap *bitmap, int from_x, int from_y, + int to_x, int to_y, Pixel color) { XSetForeground(display, bitmap->gc, color); XDrawLine(display, bitmap->drawable, bitmap->gc, from_x, from_y, to_x, to_y); } -inline Pixel X11GetPixel(Bitmap *bitmap, int x, int y) +Pixel X11GetPixel(Bitmap *bitmap, int x, int y) { XImage *pixel_image; Pixel pixel_value; @@ -401,13 +435,14 @@ inline Pixel X11GetPixel(Bitmap *bitmap, int x, int y) AllPlanes, ZPixmap); pixel_value = XGetPixel(pixel_image, 0, 0); - XDestroyImage(pixel_image); + X11DestroyImage(pixel_image); return pixel_value; } -inline Pixel X11GetPixelFromRGB(unsigned int color_r, unsigned int color_g, - unsigned int color_b) +#if defined(TARGET_X11_NATIVE) +Pixel X11GetPixelFromRGB(unsigned int color_r, unsigned int color_g, + unsigned int color_b) { XColor xcolor; Pixel pixel; @@ -422,6 +457,22 @@ inline Pixel X11GetPixelFromRGB(unsigned int color_r, unsigned int color_g, return pixel; } +#endif /* TARGET_X11_NATIVE */ + +void X11DestroyImage(XImage *ximage) +{ +#if defined(TARGET_X11_NATIVE) + /* this seems to be needed for OS/2, but does not hurt on other platforms */ + if (ximage->data != NULL) + { + free(ximage->data); + ximage->data = NULL; + } +#endif /* TARGET_X11_NATIVE */ + + XDestroyImage(ximage); +} + /* ------------------------------------------------------------------------- */ /* mouse pointer functions */ @@ -429,82 +480,46 @@ inline Pixel X11GetPixelFromRGB(unsigned int color_r, unsigned int color_g, #if defined(TARGET_X11_NATIVE) -static Cursor create_cursor(const char **image) +static Cursor create_cursor(struct MouseCursorInfo *cursor_info) { Pixmap pixmap_data, pixmap_mask; XColor color_fg, color_bg; Cursor cursor; - int i, row, col; - char data[4*32]; - char mask[4*32]; - int hot_x, hot_y; - - int data_width = 32, data_height = 32; - int mask_width = 32, mask_height = 32; - - i = -1; - for (row=0; row<32; ++row) - { - for (col=0; col<32; ++col) - { - if (col % 8) - { - data[i] <<= 1; - mask[i] <<= 1; - } - else - { - i++; - data[i] = mask[i] = 0; - } - - switch (image[4+row][col]) - { - case 'X': - data[i] |= 0x01; - mask[i] |= 0x01; - break; - case '.': - mask[i] |= 0x01; - break; - case ' ': - break; - } - } - } - - sscanf(image[4+row], "%d,%d", &hot_x, &hot_y); - /* shape and mask are single plane pixmaps */ - pixmap_data = XCreatePixmapFromBitmapData(display, window->drawable, data, - data_width, data_height, 1, 0, 1); - pixmap_mask = XCreatePixmapFromBitmapData(display, window->drawable, mask, - mask_width, mask_height, 1, 0, 1); + pixmap_data = + XCreatePixmapFromBitmapData(display, window->drawable, cursor_info->data, + cursor_info->width, cursor_info->height, + 1, 0, 1); + pixmap_mask = + XCreatePixmapFromBitmapData(display, window->drawable, cursor_info->mask, + cursor_info->width, cursor_info->height, + 1, 0, 1); XParseColor(display, cmap, "black", &color_fg); XParseColor(display, cmap, "white", &color_bg); cursor = XCreatePixmapCursor(display, pixmap_data, pixmap_mask, - &color_fg, &color_bg, hot_x, hot_y); + &color_fg, &color_bg, + cursor_info->hot_x, cursor_info->hot_y); return cursor; } -void X11SetMouseCursor(const char **cursor_image) +void X11SetMouseCursor(struct MouseCursorInfo *cursor_info) { - static const char **last_cursor_image = NULL; + static struct MouseCursorInfo *last_cursor_info = NULL; static Cursor cursor_default = None; static Cursor cursor_current = None; - if (cursor_image != NULL && cursor_image != last_cursor_image) + if (cursor_info != NULL && cursor_info != last_cursor_info) { - cursor_current = create_cursor(cursor_image); - last_cursor_image = cursor_image; + cursor_current = create_cursor(cursor_info); + last_cursor_info = cursor_info; } XDefineCursor(display, window->drawable, - cursor_image ? cursor_current : cursor_default); + cursor_info ? cursor_current : cursor_default); } #endif /* TARGET_X11_NATIVE */