xlib_playground

Xlib playground for experiments.
Log | Files | Refs

commit 2e345056ce414a0b80e7e7f26210b106a6c27112
parent 3f9b4e6f1a3cb716f36c7770eadb9294567a000f
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 27 Dec 2022 14:53:40 +0900

split Xlib related operation into separate files.

Diffstat:
Mex7/ex7.c | 186+++++++++++++++++++++++++------------------------------------------------------
Aex7/x.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aex7/x.h | 17+++++++++++++++++
3 files changed, 207 insertions(+), 127 deletions(-)

diff --git a/ex7/ex7.c b/ex7/ex7.c @@ -5,7 +5,7 @@ #include <string.h> #include <math.h> -#include <X11/Xlib.h> +#include "x.h" /* macros */ #define INIT_WIDTH (800) @@ -123,19 +123,14 @@ char world_map[WORLD_WIDTH * WORLD_HEIGHT + 1] = "........................b.......b......................b...b...................."; /* variables */ -Display *display; -Window window; -unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT; -GC gc, sgc[NUM_RECT]; -Atom wm_delete_window; struct rect block[NUM_RECT]; struct rect player; int player_is_falling; int next_menu = START_MENU; +extern int win_width, win_height; /* function prototypes */ -void setup(void); void cleanup(void); void start_menu(void); void game_play(void); @@ -151,73 +146,43 @@ int circle_test_collision(struct circle *, struct circle *); void update_falling_status(struct rect *, long); void game_over(void); - -void -setup(void) -{ - if ((display = XOpenDisplay(NULL)) == NULL){ - fprintf(stderr, "ERROR: could not open display\n"); - exit(1); - } - window = XCreateSimpleWindow( - display, - XDefaultRootWindow(display), - 0, 0, - win_width, win_height, - 0, 0, - 0); - XStoreName(display, window, "UNKO"); - gc = XCreateGC(display, window, 0, NULL); - XSetForeground(display, gc, 0x00FFFF); - for (int i = 0; i < NUM_RECT; i++){ - sgc[i] = XCreateGC(display, window, 0, NULL); - XSetForeground(display, sgc[i], 0x00FF00); - } - - wm_delete_window = XInternAtom(display, - "WM_DELETE_WINDOW", False); - XSetWMProtocols(display, window, &wm_delete_window, 1); - - XSelectInput(display, window, - ExposureMask | KeyPressMask | KeyReleaseMask); - - XMapWindow(display, window); -} - void start_menu(void) { - XEvent event; char *menu_char_q = "press q to quit."; char *menu_char_s = "press <space> to start."; - XClearArea(display, window, - 0, 0, // position - win_width, win_height, // width and height - False); - XDrawString(display, window, gc, - win_width/2 - strlen(menu_char_q)/2, win_height/2, - menu_char_q, strlen(menu_char_q)); - XDrawString(display, window, gc, - win_width/2 - strlen(menu_char_s)/2, win_height/2 + 20, - menu_char_s, strlen(menu_char_s)); + x_clear_area(); + x_draw_string(0x00FFFF, + win_width/2 - 10 * strlen(menu_char_q)/2, + win_height/2, + menu_char_q, strlen(menu_char_q)); + x_draw_string(0x00FFFF, + win_width/2 - 10 * strlen(menu_char_s)/2, + win_height/2 + 20, + menu_char_s, strlen(menu_char_s)); while (next_menu == START_MENU) { - XNextEvent(display, &event); - switch (event.type) { - case Expose: { - XDrawString(display, window, gc, - win_width/2 - strlen(menu_char_q)/2, - win_height/2, - menu_char_q, strlen(menu_char_q)); - XDrawString(display, window, gc, - win_width/2 - strlen(menu_char_s)/2, - win_height/2 + 20, - menu_char_s, strlen(menu_char_s)); - - } break; - case KeyPress: { - switch (XLookupKeysym(&event.xkey, 0)) { + char c; + int event = x_next_event(&c); + + switch (event) { + case XEXPOSE: + x_draw_string(0x00FFFF, + win_width/2 - 10 * strlen(menu_char_q)/2, + win_height/2, + menu_char_q, strlen(menu_char_q)); + x_draw_string(0x00FFFF, + win_width/2 - 10 * strlen(menu_char_s)/2, + win_height/2 + 20, + menu_char_s, strlen(menu_char_s)); + + break; + case XWINDEL: + next_menu = QUIT; + break; + case XKEYPRESS: + switch (c) { case 'q': next_menu = QUIT; break; @@ -227,12 +192,7 @@ start_menu(void) default: break; } - } break; - case ClientMessage: { - if ((Atom) event.xclient.data.l[0] == wm_delete_window) { - next_menu = QUIT; - } - } break; + break; default: break; } @@ -242,21 +202,17 @@ start_menu(void) void receive_events(int key_state[]) { - XEvent event; - XWindowAttributes wattr; - - while (XPending(display) > 0) { - XNextEvent(display, &event); - switch (event.type) { - case Expose: { - XGetWindowAttributes(display, window, &wattr); - win_width = wattr.width; - win_height = wattr.height; - } break; - case KeyPress: { - switch (XLookupKeysym(&event.xkey, 0)) { + while (x_pending() > 0) { + char c; + int event = x_next_event(&c); + + switch (event) { + case XWINDEL: + next_menu = QUIT; + break; + case XKEYPRESS: + switch (c) { case 'q': - //next_menu = GAME_OVER; key_state[KEY_Q] = KEY_DOWN; break; case 'd': @@ -277,9 +233,9 @@ receive_events(int key_state[]) default: break; } - } break; - case KeyRelease: { - switch (XLookupKeysym(&event.xkey, 0)) { + break; + case XKEYRELEASE: + switch (c) { case 'q': key_state[KEY_Q] = KEY_UP; break; @@ -301,13 +257,6 @@ receive_events(int key_state[]) default: break; } - } break; - case ClientMessage: { - if ((Atom) event.xclient.data.l[0] == wm_delete_window) { - next_menu = QUIT; - } - } break; - default: break; } } @@ -665,11 +614,6 @@ game_play(void) collision[i] = 1; } } - for (int i = 0; i < NUM_RECT; i++) - if (collision[i] == 1) - XSetForeground(display, sgc[i], 0xFFFF00); - else - XSetForeground(display, sgc[i], 0x90FF90); // fix fps // TODO: This method create some strange stripe when @@ -689,23 +633,18 @@ game_play(void) } #endif - XClearArea(display, window, - 0, 0, // position - win_width, win_height, // width and height - False); + x_clear_area(); for (int i = 0; i < NUM_RECT; i++) { - XDrawRectangle(display, window, sgc[i], - block[i].px, - block[i].py, // position + x_draw_rectangle(0x00FF00, + block[i].px, block[i].py, // position block[i].w, block[i].h); } - XDrawRectangle(display, window, gc, - player.px, - player.py, // position + x_draw_rectangle(0x009FFF, + player.px, player.py, // position player.w, player.h); char status_string[128]; snprintf(status_string, 128, "falling: %d", player_is_falling); - XDrawString(display, window, gc, + x_draw_string(0x00FFFF, 0, 20, status_string, strlen(status_string)); @@ -717,29 +656,22 @@ game_over(void) { char *menu_char = "GAME OVER"; - XClearArea(display, window, - 0, 0, // position - win_width, win_height, // width and height - False); - XDrawString(display, window, gc, - win_width/2 - strlen(menu_char)/2, win_height/2, + x_clear_area(); + x_draw_string(0x00FFFF, + win_width/2 - 10 * strlen(menu_char)/2, win_height/2, menu_char, strlen(menu_char)); - XFlush(display); + x_flush(); sleep(1); next_menu = START_MENU; } -void -cleanup(void) -{ - XCloseDisplay(display); -} - int main(void) { - setup(); + win_width = 800; + win_height = 600; + x_setup_window(0, 0, win_width, win_height, 0x002240, "UNKO"); while (next_menu != QUIT){ switch (next_menu){ case START_MENU: @@ -756,6 +688,6 @@ main(void) } } - cleanup(); + x_clean_up(); return 0; } diff --git a/ex7/x.c b/ex7/x.c @@ -0,0 +1,131 @@ +#include <stdio.h> + +#include <X11/Xlib.h> + +#include "x.h" + +Display *display; +Atom wm_delete_window; +GC gc; +Window window; +unsigned int win_width, win_height; + +/* + * Creates a window + * If succeeded, returns 0 + * If error occured, returns -1 + */ +int +x_setup_window(int x, int y, + unsigned int w, unsigned int h, + unsigned long bc, char *win_name) +{ + if ((display = XOpenDisplay(NULL)) == NULL){ + fprintf(stderr, "ERROR: could not open display\n"); + return -1; + } + window = XCreateSimpleWindow( + display, + XDefaultRootWindow(display), + x, y, + w, h, + 0, 0, // I don't need border? + bc); + win_width = w; + win_height = h; + + XStoreName(display, window, win_name); + gc = XCreateGC(display, window, 0, NULL); + printf("hello\n"); + + wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(display, window, &wm_delete_window, 1); + + XSelectInput(display, window, + ExposureMask | KeyPressMask | KeyReleaseMask); + + XMapWindow(display, window); + return 0; +} + +/* + * Clears the window with the background color. + * I don't know what the return value of XClearArea means... + */ +void +x_clear_area(void) +{ + XClearArea(display, window, + 0, 0, + win_width, win_height, + False); +} + +/* + * Draws a string with specified color. + */ +void +x_draw_string(unsigned long color, int x, int y, const char *str, int length) +{ + XSetForeground(display, gc, color); + XDrawString(display, window, gc, x, y, str, length); +} + +void +x_draw_rectangle(unsigned long color, int x, int y, + unsigned int w, unsigned int h) +{ + XSetForeground(display, gc, color); + XDrawRectangle(display, window, gc, x, y, w, h); +} + +void +x_flush(void) +{ + XFlush(display); +} + +void +x_clean_up(void) +{ + XCloseDisplay(display); +} + +int +x_next_event(char *c) +{ + XEvent event; + XWindowAttributes wattr; + + XNextEvent(display, &event); + switch (event.type) { + case Expose: + XGetWindowAttributes(display, window, &wattr); + win_width = wattr.width; + win_height = wattr.height; + return XEXPOSE; + break; + case ClientMessage: + if ((Atom) event.xclient.data.l[0] == wm_delete_window) { + return XWINDEL; + } + break; + case KeyPress: + *c = XLookupKeysym(&event.xkey, 0); + return XKEYPRESS; + break; + case KeyRelease: + *c = XLookupKeysym(&event.xkey, 0); + return XKEYRELEASE; + break; + default: + break; + } + return NOEVENT; +} + +int +x_pending(void) +{ + return XPending(display); +} diff --git a/ex7/x.h b/ex7/x.h @@ -0,0 +1,17 @@ +enum event_type { + XKEYPRESS, + XKEYRELEASE, + XEXPOSE, + XWINDEL, + NOEVENT, +}; + +int x_setup_window(int, int, unsigned int, unsigned int, unsigned long, char *); +void x_clear_area(void); +void x_draw_string(unsigned long color, int x, int y, const char *str, int length); +void x_draw_rectangle(unsigned long color, int x, int y, + unsigned int w, unsigned int h); +void x_flush(void); +void x_clean_up(void); +int x_next_event(char *c); +int x_pending(void);