gi_x11.c (7601B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <ctype.h> 6 #include <locale.h> 7 #include <X11/keysym.h> 8 #include <X11/Xlib.h> 9 #include <X11/Xutil.h> 10 #include <dc.h> 11 #include "swk.h" 12 #define SWK 13 #include "config.h" 14 15 //#define FONTNAME "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*" 16 #define FONTNAME "--10x20" 17 18 static int fs = FONTSIZE; // TODO: we need fsW and fsH 19 static Window window; 20 static XWindowAttributes wa; 21 static DC *dc = NULL; 22 static int col[ColorLast]; 23 static int colors[ColorLast] = { FGCOLOR, BGCOLOR, HICOLOR, TFCOLOR, CCCOLOR }; 24 #define EVENTMASK PointerMotionMask | ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask 25 26 static void dc_window_title(Window w, const char *title) { 27 XSetStandardProperties(dc->dpy, window, title, NULL, None, NULL, 0, NULL); 28 } 29 30 int 31 swk_gi_fontsize(int sz) { 32 fs += sz*2; 33 /* TODO: resize font */ 34 return 1; 35 } 36 37 int 38 swk_gi_init(SwkWindow *w) { 39 char buf[128]; 40 int i; 41 if (dc) return 0; 42 dc = dc_init(); 43 for(i=0;i<ColorLast;i++) { 44 sprintf(buf, "#%06x", colors[i]); 45 col[i] = dc_color(dc, buf); 46 } 47 dc_font(dc, FONTNAME); 48 // TODO: must be dc_window(dc, x, y, w, h, bg, fg) 49 window = dc_window(dc, 10, 10, w->r.w, w->r.h); 50 XSelectInput(dc->dpy, window, EVENTMASK); 51 dc_window_title(window, w->title); 52 return swk_gi_fontsize(0); 53 } 54 55 int 56 swk_gi_update(SwkWindow *w) { 57 XWindowAttributes wa; 58 XGetWindowAttributes(dc->dpy, window, &wa); 59 w->r.w = (wa.width / fs)-1; 60 w->r.h = (wa.height / fs)-1; 61 return 1; 62 } 63 64 void 65 swk_gi_exit() { 66 dc_free(dc); 67 dc = NULL; 68 } 69 70 SwkEvent * 71 swk_gi_event(SwkWindow *w, int dowait) { 72 static int mousedowny, mousedownx, mousedown = 0; 73 KeySym ksym; 74 XEvent event; 75 SwkEvent *ret = &w->_e; 76 77 if(!dowait && !XPending(dc->dpy)) 78 return NULL; 79 XNextEvent(dc->dpy, &event); 80 switch(event.type) { 81 case Expose: 82 ret->type = EExpose; 83 ret->data.expose.x = ret->data.expose.y = \ 84 ret->data.expose.w = ret->data.expose.h = 0; 85 break; 86 case MotionNotify: 87 // TODO: move this stuff into swk.c.. shoudlnt be backend dependent 88 // fprintf(stderr, "event: motion (%d,%d)\n", event.motion.x,event.motion.y); 89 if(mousedown) { 90 if(event.xmotion.y>mousedowny+fs) { 91 mousedowny = event.xmotion.y; 92 swk_scroll_up(w); 93 } else 94 if(event.xmotion.y<mousedowny-fs) { 95 mousedowny = event.xmotion.y; 96 swk_scroll_down(w); 97 } 98 if(event.xmotion.x>mousedownx+fs) { 99 mousedownx = event.xmotion.x; 100 swk_column_move_right(); 101 swk_column_move_right(); 102 } else 103 if(event.xmotion.x<mousedownx-fs) { 104 mousedownx = event.xmotion.x; 105 swk_column_move_left(); 106 swk_column_move_left(); 107 } 108 ret->type = EExpose; 109 ret->data.expose.x = ret->data.expose.y = \ 110 ret->data.expose.w = ret->data.expose.h = 0; 111 } else { 112 ret->type = EMotion; 113 ret->data.motion.x = event.xmotion.x / fs; 114 ret->data.motion.y = event.xmotion.y / fs; 115 } 116 break; 117 case ButtonRelease: 118 //fprintf(stderr, "event: up %d (%d,%d)\n", event.button.button,event.button.x,event.button.y); 119 mousedown = 0; 120 ret->type = EClick; 121 switch(event.xbutton.state) { 122 case 4096: // 0x1000 123 ret->data.click.button = 4; 124 break; 125 case 2048: // 0x800 126 ret->data.click.button = 5; 127 break; 128 case 1024: // 0x400 129 ret->data.click.button = 2; 130 break; 131 case 512: // 0x200 132 ret->data.click.button = 3; 133 break; 134 case 256: // 0x100 135 ret->data.click.button = 1; 136 break; 137 } 138 ret->data.click.point.x = event.xbutton.x / fs; 139 ret->data.click.point.y = event.xbutton.y / fs; 140 break; 141 case ButtonPress: 142 //fprintf(stderr, "event: down %d (%d,%d)\n", event.button.button,event.button.x,event.button.y); 143 mousedown = 1; 144 mousedowny = event.xbutton.y; 145 break; 146 case KeyPress: 147 ret->type = EKey; 148 XLookupString(&event.xkey, NULL, 0, &ksym, NULL); 149 printf("ksym=%d\n", (int)ksym); 150 151 switch(ksym) { 152 case 65535: // supr 153 ret->data.key.keycode = 127; 154 break; 155 case 65511: 156 ret->data.key.keycode = KUp; 157 break; 158 case 65362: 159 ret->data.key.keycode = KUp; 160 break; 161 case 65364: 162 ret->data.key.keycode = KDown; 163 break; 164 case 65361: 165 ret->data.key.keycode = KLeft; 166 break; 167 case 65363: 168 ret->data.key.keycode = KRight; 169 break; 170 case XK_BackSpace: 171 ret->data.key.keycode = 8; 172 break; 173 case XK_Return: 174 ret->data.key.keycode = '\n'; 175 break; 176 default: 177 ret->data.key.keycode = ksym; 178 } 179 ret->data.key.modmask = 0; 180 if(event.xkey.state&ShiftMask) 181 ret->data.key.modmask |= Shift; 182 if(event.xkey.state&Mod1Mask) 183 ret->data.key.modmask |= Alt; 184 if(event.xkey.state&ControlMask) 185 ret->data.key.modmask |= Ctrl; 186 fprintf(stderr, "event: key %d %d (%c)\n", 187 ret->data.key.modmask, ret->data.key.keycode, ret->data.key.keycode); 188 break; 189 case 0: 190 ret->type = EQuit; 191 break; 192 default: 193 ret = NULL; 194 break; 195 } 196 return ret; 197 } 198 199 void 200 swk_gi_clear() { 201 Rect r = {0}; 202 XGetWindowAttributes(dc->dpy, window, &wa); 203 dc_resize(dc, wa.width, wa.height); 204 r.w = wa.width; // TODO: propagate those values into SwkWindow? 205 r.h = wa.height; 206 swk_gi_fill(r, ColorBG, 0); 207 } 208 209 void 210 swk_gi_flip() { 211 dc_map(dc, window, wa.width, wa.height); 212 } 213 214 /* -- drawing primitives -- */ 215 void 216 swk_gi_line(int x1, int y1, int x2, int y2, int color) { 217 XSetForeground(dc->dpy, dc->gc, col[color]); 218 XDrawLine(dc->dpy, dc->canvas, dc->gc, x1*fs, y1*fs, (x1+x2)*fs, (y1+y2)*fs); 219 } 220 221 void 222 swk_gi_fill(Rect r, int color, int lil) { 223 XRectangle area = { r.x*fs, r.y*fs, r.w*fs, r.h*fs }; 224 if(lil==1) { 225 int s = fs/4; 226 area.x += s; 227 area.y += s; 228 area.width -= (s*2); 229 area.height -= (s*2); 230 } else 231 if(lil==2) { 232 area.x/=3; 233 area.x-=2; 234 area.width=2;///=4; 235 area.y+=4; 236 area.height-=4; 237 } else if (lil==3) { 238 const int s = fs/4; 239 area.width -= (s*2); 240 area.height -= (s*4); 241 } 242 if(area.width<1) area.width = 1; 243 if(area.height<1) area.height = 1; 244 XSetForeground(dc->dpy, dc->gc, col[color]); 245 XFillRectangles(dc->dpy, dc->canvas, dc->gc, &area, 1); 246 } 247 248 void 249 swk_gi_rect(Rect r, int color) { 250 swk_gi_line(r.x, r.y, r.w, 0, color); 251 swk_gi_line(r.x, r.y+r.h, r.w, 0, color); 252 swk_gi_line(r.x, r.y, 0, r.h, color); 253 swk_gi_line(r.x+r.w, r.y, 0, r.h, color); 254 } 255 256 void 257 swk_gi_text(Rect r, const char *text) { 258 if(!text||!*text) 259 return; 260 XSetForeground(dc->dpy, dc->gc, col[ColorFG]); 261 // TODO: use libdraw to get length of string and support utf8.. 262 // TODO: retrieve character width before rendering 263 XmbDrawString(dc->dpy, dc->canvas, dc->font.set, dc->gc, 264 5+(r.x*fs), ((r.y+1)*fs-3), text, strlen(text)); 265 } 266 267 void 268 swk_gi_img(Rect r, void *_img) { 269 SwkImage *img = _img; 270 if(img) 271 XPutImage(dc->dpy, dc->canvas, DefaultGC(dc->dpy, 0), img->pub, 272 0, 0, r.x*fs, r.y*fs, img->w, img->h); 273 } 274 275 void* 276 swk_gi_img_new(int w, int h, int color) { 277 SwkImage *img = img_open(NULL); 278 img->w = w*fs; 279 img->h = h*fs; 280 img->bpp = 24; 281 img->priv = NULL; 282 *img->name = 0; 283 img->data = malloc(img->w*img->h*4); 284 memset(img->data, colors[color]&0xff, img->w*img->h*4); 285 img->pub = XCreateImage(dc->dpy, DefaultVisual(dc->dpy, 0), 24, ZPixmap, 286 0, img->data, img->w, img->h, 32, 0); 287 return img; 288 } 289 290 void* 291 swk_gi_img_load(const char *str) { 292 SwkImage *img = img_open(str); 293 if (img == NULL) 294 return NULL; 295 img->pub = XCreateImage(dc->dpy, DefaultVisual(dc->dpy, 0), 24, ZPixmap, 296 0, img->data, img->w, img->h, 32, 0); 297 return img; 298 } 299 300 void 301 swk_gi_img_free(void *s) { 302 img_free(s); 303 } 304 305 void 306 swk_gi_img_set(void *_img, int x, int y, int color) { 307 SwkImage *img = _img; 308 int *ptr = img->data; 309 if(ptr) ptr[(y*img->w)+x] = color; 310 } 311 312 int 313 swk_gi_img_get(void *_img, int x, int y) { 314 SwkImage *img = _img; 315 int *ptr = img->data; 316 return ptr?ptr[(y*img->w)+x]:0; 317 }