/* Loop and handle message box event messages until something kills it. */ static int X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data ) { GC ctx; XGCValues ctx_vals; SDL_bool close_dialog = SDL_FALSE; SDL_bool has_focus = SDL_TRUE; KeySym last_key_pressed = XK_VoidSymbol; unsigned long gcflags = GCForeground | GCBackground; SDL_zero(ctx_vals); ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ]; ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ]; if (!SDL_X11_HAVE_UTF8) { gcflags |= GCFont; ctx_vals.font = data->font_struct->fid; } ctx = X11_XCreateGC( data->display, data->window, gcflags, &ctx_vals ); if ( ctx == None ) { return SDL_SetError("Couldn't create graphics context"); } data->button_press_index = -1; /* Reset what button is currently depressed. */ data->mouse_over_index = -1; /* Reset what button the mouse is over. */ while( !close_dialog ) { XEvent e; SDL_bool draw = SDL_TRUE; /* can't use XWindowEvent() because it can't handle ClientMessage events. */ /* can't use XNextEvent() because we only want events for this window. */ X11_XIfEvent( data->display, &e, X11_MessageBoxEventTest, (XPointer) data ); /* If X11_XFilterEvent returns True, then some input method has filtered the event, and the client should discard the event. */ if ( ( e.type != Expose ) && X11_XFilterEvent( &e, None ) ) continue; switch( e.type ) { case Expose: if ( e.xexpose.count > 0 ) { draw = SDL_FALSE; } break; case FocusIn: /* Got focus. */ has_focus = SDL_TRUE; break; case FocusOut: /* lost focus. Reset button and mouse info. */ has_focus = SDL_FALSE; data->button_press_index = -1; data->mouse_over_index = -1; break; case MotionNotify: if ( has_focus ) { /* Mouse moved... */ const int previndex = data->mouse_over_index; data->mouse_over_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y ); if (data->mouse_over_index == previndex) { draw = SDL_FALSE; } } break; case ClientMessage: if ( e.xclient.message_type == data->wm_protocols && e.xclient.format == 32 && e.xclient.data.l[ 0 ] == data->wm_delete_message ) { close_dialog = SDL_TRUE; } break; case KeyPress: /* Store key press - we make sure in key release that we got both. */ last_key_pressed = X11_XLookupKeysym( &e.xkey, 0 ); break; case KeyRelease: { Uint32 mask = 0; KeySym key = X11_XLookupKeysym( &e.xkey, 0 ); /* If this is a key release for something we didn't get the key down for, then bail. */ if ( key != last_key_pressed ) break; if ( key == XK_Escape ) mask = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; else if ( ( key == XK_Return ) || ( key == XK_KP_Enter ) ) mask = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; if ( mask ) { int i; /* Look for first button with this mask set, and return it if found. */ for ( i = 0; i < data->numbuttons; i++ ) { SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ]; if ( buttondatax11->buttondata->flags & mask ) { *data->pbuttonid = buttondatax11->buttondata->buttonid; close_dialog = SDL_TRUE; break; } } } break; } case ButtonPress: data->button_press_index = -1; if ( e.xbutton.button == Button1 ) { /* Find index of button they clicked on. */ data->button_press_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y ); } break; case ButtonRelease: /* If button is released over the same button that was clicked down on, then return it. */ if ( ( e.xbutton.button == Button1 ) && ( data->button_press_index >= 0 ) ) { int button = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y ); if ( data->button_press_index == button ) { SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ button ]; *data->pbuttonid = buttondatax11->buttondata->buttonid; close_dialog = SDL_TRUE; } } data->button_press_index = -1; break; } if ( draw ) { /* Draw our dialog box. */ X11_MessageBoxDraw( data, ctx ); } } X11_XFreeGC( data->display, ctx ); return 0; }
int X11_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; XGCValues gcv; XVisualInfo vinfo; /* Free the old framebuffer surface */ X11_DestroyWindowFramebuffer(_this, window); /* Create the graphics context for drawing */ gcv.graphics_exposures = False; data->gc = X11_XCreateGC(display, data->xwindow, GCGraphicsExposures, &gcv); if (!data->gc) { return SDL_SetError("Couldn't create graphics context"); } /* Find out the pixel format and depth */ if (X11_GetVisualInfoFromVisual(display, data->visual, &vinfo) < 0) { return SDL_SetError("Couldn't get window visual information"); } *format = X11_GetPixelFormatFromVisualInfo(display, &vinfo); if (*format == SDL_PIXELFORMAT_UNKNOWN) { return SDL_SetError("Unknown window pixel format"); } /* Calculate pitch */ *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3); /* Create the actual image */ #ifndef NO_SHARED_MEMORY if (have_mitshm()) { XShmSegmentInfo *shminfo = &data->shminfo; shminfo->shmid = shmget(IPC_PRIVATE, window->h*(*pitch), IPC_CREAT | 0777); if ( shminfo->shmid >= 0 ) { shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0); shminfo->readOnly = False; if ( shminfo->shmaddr != (char *)-1 ) { shm_error = False; X_handler = X11_XSetErrorHandler(shm_errhandler); X11_XShmAttach(display, shminfo); X11_XSync(display, True); X11_XSetErrorHandler(X_handler); if ( shm_error ) shmdt(shminfo->shmaddr); } else { shm_error = True; } shmctl(shminfo->shmid, IPC_RMID, NULL); } else { shm_error = True; } if (!shm_error) { data->ximage = X11_XShmCreateImage(display, data->visual, vinfo.depth, ZPixmap, shminfo->shmaddr, shminfo, window->w, window->h); if (!data->ximage) { X11_XShmDetach(display, shminfo); X11_XSync(display, False); shmdt(shminfo->shmaddr); } else { /* Done! */ data->use_mitshm = SDL_TRUE; *pixels = shminfo->shmaddr; return 0; } } } #endif /* not NO_SHARED_MEMORY */ *pixels = SDL_malloc(window->h*(*pitch)); if (*pixels == NULL) { return SDL_OutOfMemory(); } data->ximage = X11_XCreateImage(display, data->visual, vinfo.depth, ZPixmap, 0, (char *)(*pixels), window->w, window->h, 32, 0); if (!data->ximage) { SDL_free(*pixels); return SDL_SetError("Couldn't create XImage"); } return 0; }