1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include "video/display.hh"
|
---|
10 | #include "video/x11/x11devs.hh"
|
---|
11 | #include "device/kernel.hh"
|
---|
12 | #include "palette/pal.hh"
|
---|
13 | #include "error/error.hh"
|
---|
14 | #include "memory/malloc.hh"
|
---|
15 | #include "device/keys.hh"
|
---|
16 | #include "time/profile.hh"
|
---|
17 | #include <string.h>
|
---|
18 | #include <stdlib.h>
|
---|
19 | #include <stdio.h>
|
---|
20 |
|
---|
21 | x11_display_class x11_display_instance;
|
---|
22 |
|
---|
23 |
|
---|
24 | static Cursor CreateNullCursor(Display *display, Window root)
|
---|
25 | // makes a null cursor
|
---|
26 | {
|
---|
27 | Pixmap cursormask;
|
---|
28 | XGCValues xgc;
|
---|
29 | GC gc;
|
---|
30 | XColor dummycolour;
|
---|
31 | Cursor cursor;
|
---|
32 |
|
---|
33 | cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
|
---|
34 | xgc.function = GXclear;
|
---|
35 | gc = XCreateGC(display, cursormask, GCFunction, &xgc);
|
---|
36 | XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
|
---|
37 | dummycolour.pixel = 0;
|
---|
38 | dummycolour.red = 0;
|
---|
39 | dummycolour.flags = 04;
|
---|
40 | cursor = XCreatePixmapCursor(display, cursormask, cursormask,
|
---|
41 | &dummycolour,&dummycolour, 0,0);
|
---|
42 | XFreePixmap(display,cursormask);
|
---|
43 | XFreeGC(display,gc);
|
---|
44 | return cursor;
|
---|
45 | }
|
---|
46 |
|
---|
47 |
|
---|
48 | i4_bool x11_display_class::set_mouse_shape(i4_cursor_class *cursor)
|
---|
49 | {
|
---|
50 | if (mouse_pict)
|
---|
51 | {
|
---|
52 | delete mouse_pict;
|
---|
53 | delete mouse_save;
|
---|
54 | }
|
---|
55 |
|
---|
56 | mouse_trans=cursor->trans;
|
---|
57 | mouse_pict=cursor->pict->copy();
|
---|
58 |
|
---|
59 | mouse_save=new I4_SCREEN_TYPE(mouse_pict->width(),mouse_pict->height(),screen->get_pal());
|
---|
60 |
|
---|
61 | mouse_hot_x=cursor->hot_x;
|
---|
62 | mouse_hot_y=cursor->hot_y;
|
---|
63 | return i4_T;
|
---|
64 | }
|
---|
65 |
|
---|
66 |
|
---|
67 | enum { devices_handled =
|
---|
68 | i4_device_class::FLAG_MOUSE_BUTTON_UP |
|
---|
69 | i4_device_class::FLAG_MOUSE_BUTTON_DOWN |
|
---|
70 | i4_device_class::FLAG_MOUSE_MOVE |
|
---|
71 | i4_device_class::FLAG_KEY_PRESS |
|
---|
72 | i4_device_class::FLAG_KEY_RELEASE |
|
---|
73 | i4_device_class::FLAG_DISPLAY_CHANGE };
|
---|
74 |
|
---|
75 |
|
---|
76 | void x11_display_class::x11_device_manager::get_x_time(w32 xtick, i4_time_class &t)
|
---|
77 | {
|
---|
78 | if (need_first_time)
|
---|
79 | {
|
---|
80 | first_time=xtick;
|
---|
81 | need_first_time=i4_F;
|
---|
82 | }
|
---|
83 |
|
---|
84 | w32 xtime=xtick-first_time;
|
---|
85 |
|
---|
86 | i4_time_class now;
|
---|
87 | i4_time_class x_now(xtime);
|
---|
88 |
|
---|
89 | sw32 diff=x_now.milli_diff(now);
|
---|
90 |
|
---|
91 | if (diff>x11_start_time_best_diff)
|
---|
92 | {
|
---|
93 | x11_start_time_best_diff=diff;
|
---|
94 | x11_start_time=xtime;
|
---|
95 | i4_start_time=now;
|
---|
96 | }
|
---|
97 |
|
---|
98 | t=i4_start_time;
|
---|
99 | t.add_milli(xtime-x11_start_time);
|
---|
100 | }
|
---|
101 |
|
---|
102 | i4_bool x11_display_class::x11_device_manager::process_events()
|
---|
103 | // returns true if an event was dispatched
|
---|
104 | {
|
---|
105 | i4_bool motion_occured=i4_F;
|
---|
106 | sw32 final_x, final_y;
|
---|
107 |
|
---|
108 | if (parent->display)
|
---|
109 | {
|
---|
110 | while (XPending(parent->display))
|
---|
111 | {
|
---|
112 | XEvent xev;
|
---|
113 | XNextEvent(parent->display,&xev);
|
---|
114 |
|
---|
115 | if (parent->shm_extension)
|
---|
116 | parent->shm_extension->note_event(xev);
|
---|
117 |
|
---|
118 | switch (xev.type)
|
---|
119 | {
|
---|
120 | case Expose :
|
---|
121 | {
|
---|
122 | if (parent->context)
|
---|
123 | {
|
---|
124 | parent->context->add_both_dirty(xev.xexpose.x,
|
---|
125 | xev.xexpose.y,
|
---|
126 | xev.xexpose.x+xev.xexpose.width,
|
---|
127 | xev.xexpose.y+xev.xexpose.height);
|
---|
128 | }
|
---|
129 | } break;
|
---|
130 |
|
---|
131 | //{{{ not implemented yet
|
---|
132 | case ConfigureNotify :
|
---|
133 | {
|
---|
134 | XFlush(parent->display);
|
---|
135 |
|
---|
136 | int new_width=xev.xconfigure.width&~3; // must be word alligned
|
---|
137 | int new_height=xev.xconfigure.height;
|
---|
138 | if (new_width!=xev.xconfigure.width)
|
---|
139 | XResizeWindow(parent->display,parent->mainwin,new_width,xev.xconfigure.height);
|
---|
140 |
|
---|
141 | XFlush(parent->display);
|
---|
142 |
|
---|
143 | parent->destroy_X_image();
|
---|
144 | parent->create_X_image(new_width, new_height);
|
---|
145 |
|
---|
146 | i4_display_change_event_class d_change(parent,
|
---|
147 | i4_display_change_event_class::SIZE_CHANGE);
|
---|
148 |
|
---|
149 | send_event_to_agents(&d_change,FLAG_DISPLAY_CHANGE);
|
---|
150 | } break;
|
---|
151 |
|
---|
152 | case MotionNotify :
|
---|
153 | {
|
---|
154 | motion_occured=i4_T;
|
---|
155 | final_x=xev.xmotion.x;
|
---|
156 | final_y=xev.xmotion.y;
|
---|
157 | } break;
|
---|
158 |
|
---|
159 | case ButtonRelease :
|
---|
160 | {
|
---|
161 | i4_mouse_button_up_event_class::btype but;
|
---|
162 | switch (xev.xbutton.button)
|
---|
163 | {
|
---|
164 | case 1 : but=i4_mouse_button_up_event_class::LEFT; break;
|
---|
165 | case 3 : but=i4_mouse_button_up_event_class::RIGHT; break;
|
---|
166 | case 2 : but=i4_mouse_button_up_event_class::CENTER; break;
|
---|
167 | }
|
---|
168 | i4_mouse_button_up_event_class up(but);
|
---|
169 | send_event_to_agents(&up,FLAG_MOUSE_BUTTON_UP);
|
---|
170 | } break;
|
---|
171 |
|
---|
172 | case ButtonPress :
|
---|
173 | {
|
---|
174 | i4_mouse_button_down_event_class::btype but;
|
---|
175 | switch (xev.xbutton.button)
|
---|
176 | {
|
---|
177 | case 1 : but=i4_mouse_button_down_event_class::LEFT; break;
|
---|
178 | case 3 : but=i4_mouse_button_down_event_class::RIGHT; break;
|
---|
179 | case 2 : but=i4_mouse_button_down_event_class::CENTER; break;
|
---|
180 | }
|
---|
181 | i4_mouse_button_down_event_class down(but);
|
---|
182 | send_event_to_agents(&down,FLAG_MOUSE_BUTTON_DOWN);
|
---|
183 | } break;
|
---|
184 |
|
---|
185 | case KeyPress :
|
---|
186 | case KeyRelease :
|
---|
187 | {
|
---|
188 | char buf;
|
---|
189 | KeySym ks;
|
---|
190 | XLookupString(&xev.xkey,&buf,1,&ks,NULL);
|
---|
191 | w16 key, key_code;
|
---|
192 |
|
---|
193 | switch (ks)
|
---|
194 | {
|
---|
195 | case XK_Down : key_code=I4_DOWN; break;
|
---|
196 | case XK_Up : key_code=I4_UP; break;
|
---|
197 | case XK_Left : key_code=I4_LEFT; break;
|
---|
198 | case XK_Right : key_code=I4_RIGHT; break;
|
---|
199 | case XK_Control_L :
|
---|
200 | {
|
---|
201 | key_code=I4_CTRL_L;
|
---|
202 | if (xev.type==KeyPress)
|
---|
203 | modifier_state|=I4_MODIFIER_CTRL_L;
|
---|
204 | else
|
---|
205 | modifier_state&=~I4_MODIFIER_CTRL_L;
|
---|
206 | } break;
|
---|
207 |
|
---|
208 | case XK_Control_R :
|
---|
209 | {
|
---|
210 | key_code=I4_CTRL_R;
|
---|
211 | if (xev.type==KeyPress)
|
---|
212 | modifier_state|=I4_MODIFIER_CTRL_R;
|
---|
213 | else
|
---|
214 | modifier_state&=~I4_MODIFIER_CTRL_R;
|
---|
215 | } break;
|
---|
216 |
|
---|
217 | case XK_Alt_L :
|
---|
218 | {
|
---|
219 | key_code=I4_ALT_L;
|
---|
220 | if (xev.type==KeyPress)
|
---|
221 | modifier_state|=I4_MODIFIER_ALT_L;
|
---|
222 | else
|
---|
223 | modifier_state&=~I4_MODIFIER_ALT_L;
|
---|
224 | } break;
|
---|
225 |
|
---|
226 | case XK_Alt_R :
|
---|
227 | {
|
---|
228 | key_code=I4_ALT_R;
|
---|
229 | if (xev.type==KeyPress)
|
---|
230 | modifier_state|=I4_MODIFIER_ALT_R;
|
---|
231 | else
|
---|
232 | modifier_state&=~I4_MODIFIER_ALT_R;
|
---|
233 | } break;
|
---|
234 |
|
---|
235 |
|
---|
236 | case XK_Shift_L :
|
---|
237 | {
|
---|
238 | key_code=I4_SHIFT_L;
|
---|
239 | if (xev.type==KeyPress)
|
---|
240 | modifier_state|=I4_MODIFIER_SHIFT_L;
|
---|
241 | else
|
---|
242 | modifier_state&=~I4_MODIFIER_SHIFT_L;
|
---|
243 | } break;
|
---|
244 |
|
---|
245 | case XK_Shift_R :
|
---|
246 | {
|
---|
247 | key_code=I4_SHIFT_R;
|
---|
248 | if (xev.type==KeyPress)
|
---|
249 | modifier_state|=I4_MODIFIER_SHIFT_R;
|
---|
250 | else
|
---|
251 | modifier_state&=~I4_MODIFIER_SHIFT_R;
|
---|
252 | } break;
|
---|
253 |
|
---|
254 |
|
---|
255 | case XK_Num_Lock : key_code=I4_NUM_LOCK; break;
|
---|
256 | case XK_Home : key_code=I4_HOME; break;
|
---|
257 | case XK_End : key_code=I4_END; break;
|
---|
258 | case XK_BackSpace : key_code=I4_BACKSPACE; break;
|
---|
259 | case XK_Tab : key_code=I4_TAB; break;
|
---|
260 | case XK_Return : key_code=I4_ENTER; break;
|
---|
261 | case XK_Caps_Lock : key_code=I4_CAPS; break;
|
---|
262 | case XK_Escape : key_code=I4_ESC; break;
|
---|
263 | case XK_F1 : key_code=I4_F1; break;
|
---|
264 | case XK_F2 : key_code=I4_F2; break;
|
---|
265 | case XK_F3 : key_code=I4_F3; break;
|
---|
266 | case XK_F4 : key_code=I4_F4; break;
|
---|
267 | case XK_F5 : key_code=I4_F5; break;
|
---|
268 | case XK_F6 : key_code=I4_F6; break;
|
---|
269 | case XK_F7 : key_code=I4_F7; break;
|
---|
270 | case XK_F8 : key_code=I4_F8; break;
|
---|
271 | case XK_F9 : key_code=I4_F9; break;
|
---|
272 | case XK_F10 : key_code=I4_F10; break;
|
---|
273 | case XK_Insert : key_code=I4_INSERT; break;
|
---|
274 | case XK_Page_Up : key_code=I4_PAGEUP; break;
|
---|
275 | case XK_Page_Down : key_code=I4_PAGEDOWN; break;
|
---|
276 | case XK_Delete : key_code=I4_DEL; break;
|
---|
277 |
|
---|
278 | case XK_KP_0 : key_code=I4_KP0; break;
|
---|
279 | case XK_KP_1 : key_code=I4_KP1; break;
|
---|
280 | case XK_KP_2 : key_code=I4_KP2; break;
|
---|
281 | case XK_KP_3 : key_code=I4_KP3; break;
|
---|
282 | case XK_KP_4 : key_code=I4_KP4; break;
|
---|
283 | case XK_KP_5 : key_code=I4_KP5; break;
|
---|
284 | case XK_KP_6 : key_code=I4_KP6; break;
|
---|
285 | case XK_KP_7 : key_code=I4_KP7; break;
|
---|
286 | case XK_KP_8 : key_code=I4_KP8; break;
|
---|
287 | case XK_KP_9 : key_code=I4_KP9; break;
|
---|
288 |
|
---|
289 | case ' ': key_code=I4_SPACE; break;
|
---|
290 | case '`':
|
---|
291 | case '~': key_code='`'; break;
|
---|
292 | case '-':
|
---|
293 | case '_': key_code='-'; break;
|
---|
294 | case '=':
|
---|
295 | case '+': key_code='='; break;
|
---|
296 | case '[':
|
---|
297 | case '{': key_code='['; break;
|
---|
298 | case ']':
|
---|
299 | case '}': key_code=']'; break;
|
---|
300 | case '\\':
|
---|
301 | case '|': key_code='\\'; break;
|
---|
302 | case ';':
|
---|
303 | case ':': key_code=';'; break;
|
---|
304 | case '\'':
|
---|
305 | case '"': key_code='\''; break;
|
---|
306 | case ',':
|
---|
307 | case '<': key_code=','; break;
|
---|
308 | case '.':
|
---|
309 | case '>': key_code='.'; break;
|
---|
310 | case '/':
|
---|
311 | case '?': key_code='/'; break;
|
---|
312 |
|
---|
313 | case ')': key_code='0'; break;
|
---|
314 | case '!': key_code='1'; break;
|
---|
315 | case '@': key_code='2'; break;
|
---|
316 | case '#': key_code='3'; break;
|
---|
317 | case '$': key_code='4'; break;
|
---|
318 | case '%': key_code='5'; break;
|
---|
319 | case '^': key_code='6'; break;
|
---|
320 | case '&': key_code='7'; break;
|
---|
321 | case '*': key_code='8'; break;
|
---|
322 | case '(': key_code='9'; break;
|
---|
323 |
|
---|
324 | default :
|
---|
325 | if ((ks>=XK_A && ks<=XK_Z) || (ks>=XK_0 && ks<=XK_9))
|
---|
326 | key_code = ks;
|
---|
327 | else if (ks>=XK_a && ks<=XK_z)
|
---|
328 | key_code = ks + 'A' - 'a';
|
---|
329 | else
|
---|
330 | key_code=0;
|
---|
331 | }
|
---|
332 |
|
---|
333 | if (key_code)
|
---|
334 | {
|
---|
335 | if (xev.type==KeyPress)
|
---|
336 | {
|
---|
337 | i4_time_class t;
|
---|
338 | get_x_time(xev.xkey.time, t);
|
---|
339 |
|
---|
340 | key = i4_key_translate(key_code,1,modifier_state);
|
---|
341 | i4_key_press_event_class ev(key, key_code, modifier_state, t);
|
---|
342 |
|
---|
343 | send_event_to_agents(&ev,FLAG_KEY_PRESS);
|
---|
344 | }
|
---|
345 | else
|
---|
346 | {
|
---|
347 | key = i4_key_translate(key_code,0, modifier_state);
|
---|
348 |
|
---|
349 | i4_time_class t;
|
---|
350 | get_x_time(xev.xkey.time, t);
|
---|
351 |
|
---|
352 | i4_key_release_event_class ev(key, key_code, modifier_state, t);
|
---|
353 | send_event_to_agents(&ev,FLAG_KEY_RELEASE);
|
---|
354 | }
|
---|
355 | }
|
---|
356 | } break;
|
---|
357 | }
|
---|
358 | }
|
---|
359 | }
|
---|
360 |
|
---|
361 |
|
---|
362 | if (motion_occured && (final_x!=parent->mouse_x || final_y!=parent->mouse_y))
|
---|
363 | {
|
---|
364 | i4_mouse_move_event_class move(parent->mouse_x, parent->mouse_y, final_x, final_y);
|
---|
365 | send_event_to_agents(&move,FLAG_MOUSE_MOVE);
|
---|
366 |
|
---|
367 | if (parent->mouse_locked)
|
---|
368 | {
|
---|
369 | XWarpPointer(parent->display, None, parent->mainwin, 0,0, 0,0,
|
---|
370 | parent->mouse_x,
|
---|
371 | parent->mouse_y);
|
---|
372 | }
|
---|
373 | else
|
---|
374 | {
|
---|
375 | parent->mouse_x=final_x;
|
---|
376 | parent->mouse_y=final_y;
|
---|
377 | }
|
---|
378 | }
|
---|
379 |
|
---|
380 | return i4_F;
|
---|
381 | }
|
---|
382 |
|
---|
383 |
|
---|
384 | x11_display_class::x11_device_manager::x11_device_manager()
|
---|
385 | {
|
---|
386 | modifier_state=0;
|
---|
387 | need_first_time=1;
|
---|
388 | x11_start_time_best_diff=0;
|
---|
389 | parent=&x11_display_instance;
|
---|
390 | }
|
---|
391 |
|
---|
392 |
|
---|
393 | x11_display_class::x11_display_class()
|
---|
394 | {
|
---|
395 | mouse_locked=i4_F;
|
---|
396 | screen=0;
|
---|
397 | context=0;
|
---|
398 | shm_extension=0;
|
---|
399 | shm_image=0;
|
---|
400 | ximage=0;
|
---|
401 | display=0;
|
---|
402 | }
|
---|
403 |
|
---|
404 |
|
---|
405 | i4_image_class *x11_display_class::get_screen()
|
---|
406 | {
|
---|
407 | return screen;
|
---|
408 | }
|
---|
409 |
|
---|
410 |
|
---|
411 | void db_show()
|
---|
412 | {
|
---|
413 | x11_display_instance.get_context()->add_both_dirty(0,0,
|
---|
414 | x11_display_instance.get_screen()->width(),
|
---|
415 | x11_display_instance.get_screen()->height());
|
---|
416 | x11_display_instance.flush();
|
---|
417 | x11_display_instance.get_context()->add_both_dirty(0,0,
|
---|
418 | x11_display_instance.get_screen()->width(),
|
---|
419 | x11_display_instance.get_screen()->height());
|
---|
420 | }
|
---|
421 |
|
---|
422 |
|
---|
423 | static i4_profile_class x11_flush_ph("X11 video flush (XPutImage)");
|
---|
424 |
|
---|
425 |
|
---|
426 | void x11_display_class::flush() // the actual work of the function is in copy_part_to_vram
|
---|
427 | {
|
---|
428 | int mw,mh;
|
---|
429 | i4_coord rmx,rmy;
|
---|
430 | x11_flush_ph.start();
|
---|
431 | sw32 mx=mouse_x, my=mouse_y;
|
---|
432 | if (mx<0) mx=0;
|
---|
433 | if (my<0) my=0;
|
---|
434 |
|
---|
435 | rmx=mx-mouse_hot_x;
|
---|
436 | rmy=my-mouse_hot_y;
|
---|
437 |
|
---|
438 | if (mouse_pict)
|
---|
439 | {
|
---|
440 | mw=mouse_pict->width();
|
---|
441 | mh=mouse_pict->height();
|
---|
442 |
|
---|
443 | if (pal.source_type()==I4_8BIT)
|
---|
444 | mouse_save->set_pal(pal);
|
---|
445 |
|
---|
446 |
|
---|
447 | i4_draw_context_class save_context(0,0,mw-1,mh-1);
|
---|
448 | screen->put_part(mouse_save,0,0,rmx,rmy,rmx+mw-1,rmy+mh-1,
|
---|
449 | save_context); // save area behind mouse
|
---|
450 |
|
---|
451 | mouse_pict->put_image_trans(screen,rmx,rmy,mouse_trans,*context);
|
---|
452 | }
|
---|
453 |
|
---|
454 | i4_rect_list_class::area_iter a;
|
---|
455 | for (a=context->single_dirty->list.begin();
|
---|
456 | a!=context->single_dirty->list.end();
|
---|
457 | ++a)
|
---|
458 | context->both_dirty->add_area(a->x1, a->y1, a->x2, a->y2);
|
---|
459 |
|
---|
460 | context->single_dirty->delete_list();
|
---|
461 |
|
---|
462 |
|
---|
463 | context->both_dirty->intersect_area(0,0,width()-1,height()-1);
|
---|
464 |
|
---|
465 | a=context->both_dirty->list.begin();
|
---|
466 | i4_bool error=i4_F;
|
---|
467 | for (;a!=context->both_dirty->list.end();++a)
|
---|
468 | error=(i4_bool)(error & copy_part_to_vram(a->x1,a->y1,a->x1,a->y1,a->x2,a->y2));
|
---|
469 |
|
---|
470 | if (!error)
|
---|
471 | context->both_dirty->delete_list();
|
---|
472 |
|
---|
473 | if (mouse_pict)
|
---|
474 | mouse_save->put_part(screen,rmx,rmy,0,0,mw-1,mh-1,*context); // restore area behind mouse
|
---|
475 |
|
---|
476 | x11_flush_ph.stop();
|
---|
477 | }
|
---|
478 |
|
---|
479 |
|
---|
480 | // Dave : have the name return a string appropriate to the extensions
|
---|
481 | // available on the Xserver, i.e. MITSHM or the page-flip thingy
|
---|
482 | char *x11_display_class::name() const
|
---|
483 | {
|
---|
484 | char buf[200];
|
---|
485 | if (getenv("DISPLAY"))
|
---|
486 | sprintf(buf,"X Server : %s",getenv("DISPLAY"));
|
---|
487 | else strcpy(buf,"X Server : localhost");
|
---|
488 | return buf;
|
---|
489 | }
|
---|
490 |
|
---|
491 |
|
---|
492 | i4_display_class::mode *x11_display_class::get_first_mode()
|
---|
493 | {
|
---|
494 | // Check to see if we need to open the display,
|
---|
495 | // since get_first_mode() is valid while a display is
|
---|
496 | i4_bool need_close=i4_F;
|
---|
497 | if (!display)
|
---|
498 | {
|
---|
499 | need_close=i4_T;
|
---|
500 | if (!open_display())
|
---|
501 | return 0;
|
---|
502 | }
|
---|
503 |
|
---|
504 | // Check to see if they have an 8 bit visual on the display
|
---|
505 | int items;
|
---|
506 | XVisualInfo vis_info;
|
---|
507 |
|
---|
508 | if (I4_SCREEN_DEPTH==8)
|
---|
509 | {
|
---|
510 | vis_info.depth=8;
|
---|
511 | vis_info.c_class=PseudoColor;
|
---|
512 | }
|
---|
513 | else if (I4_SCREEN_DEPTH==15)
|
---|
514 | {
|
---|
515 | vis_info.depth=16;
|
---|
516 | vis_info.c_class=TrueColor;
|
---|
517 | }
|
---|
518 | else if (I4_SCREEN_DEPTH==16)
|
---|
519 | {
|
---|
520 | vis_info.depth=16;
|
---|
521 | vis_info.c_class=TrueColor;
|
---|
522 | }
|
---|
523 | else if (I4_SCREEN_DEPTH==32)
|
---|
524 | {
|
---|
525 | vis_info.depth=24;
|
---|
526 | vis_info.c_class=TrueColor;
|
---|
527 | }
|
---|
528 |
|
---|
529 | XVisualInfo *return_visual=XGetVisualInfo(display,
|
---|
530 | VisualClassMask | VisualDepthMask, &vis_info,&items);
|
---|
531 |
|
---|
532 | amode.red_mask = return_visual->red_mask;
|
---|
533 | amode.green_mask = return_visual->green_mask;
|
---|
534 | amode.blue_mask = return_visual->blue_mask;
|
---|
535 |
|
---|
536 |
|
---|
537 | XFree((char *)return_visual);
|
---|
538 | if (items==0)
|
---|
539 | {
|
---|
540 | if (need_close)
|
---|
541 | close_display();
|
---|
542 | return 0;
|
---|
543 | }
|
---|
544 |
|
---|
545 | strcpy(amode.name,"Standard X11 window");
|
---|
546 | amode.flags=mode::RESOLUTION_DETERMINED_ON_OPEN;
|
---|
547 | amode.bits_per_pixel=I4_SCREEN_DEPTH;
|
---|
548 |
|
---|
549 |
|
---|
550 |
|
---|
551 | Window root;
|
---|
552 | int x,y;
|
---|
553 | unsigned w,h,bord,depth;
|
---|
554 | if (XGetGeometry(display,RootWindow(display,DefaultScreen(display)),&root,
|
---|
555 | &x,&y,&w,&h,&bord,&depth)==0)
|
---|
556 | i4_error("can't get root window attributes");
|
---|
557 |
|
---|
558 | amode.xres=w;
|
---|
559 | amode.yres=h;
|
---|
560 |
|
---|
561 | amode.assoc=this; // so we know in 'initialize_mode' that we created this mode
|
---|
562 |
|
---|
563 | if (need_close)
|
---|
564 | close_display();
|
---|
565 |
|
---|
566 | return &amode;
|
---|
567 | }
|
---|
568 |
|
---|
569 |
|
---|
570 | i4_display_class::mode *x11_display_class::get_next_mode(mode *last_mode)
|
---|
571 | {
|
---|
572 | return NULL; // for now only straight X stuff
|
---|
573 | // this should return modes for direct screen access
|
---|
574 | }
|
---|
575 |
|
---|
576 |
|
---|
577 | void x11_display_class::close_X_window()
|
---|
578 | {
|
---|
579 | destroy_X_image();
|
---|
580 | if (shm_extension)
|
---|
581 | shm_extension->shutdown(display);
|
---|
582 |
|
---|
583 | XFreeGC(display,gc);
|
---|
584 | XFree((char *)my_visual);
|
---|
585 | XCloseDisplay(display);
|
---|
586 | display=0;
|
---|
587 |
|
---|
588 | if (I4_SCREEN_DEPTH==8)
|
---|
589 | XFreeColormap(display,xcolor_map);
|
---|
590 |
|
---|
591 | if (mouse_save)
|
---|
592 | {
|
---|
593 | delete mouse_save;
|
---|
594 | mouse_save=0;
|
---|
595 | }
|
---|
596 |
|
---|
597 | if (mouse_pict)
|
---|
598 | {
|
---|
599 | delete mouse_pict;
|
---|
600 | mouse_pict=0;
|
---|
601 | }
|
---|
602 | }
|
---|
603 |
|
---|
604 |
|
---|
605 | void x11_display_class::destroy_X_image()
|
---|
606 | {
|
---|
607 | if (shm_extension)
|
---|
608 | {
|
---|
609 | if (shm_image)
|
---|
610 | shm_extension->destroy_shm_image(display, shm_image);
|
---|
611 | shm_image=0;
|
---|
612 | }
|
---|
613 | else
|
---|
614 | {
|
---|
615 | if (ximage)
|
---|
616 | XDestroyImage(ximage);
|
---|
617 | ximage=0;
|
---|
618 | }
|
---|
619 | if (screen)
|
---|
620 | {
|
---|
621 | delete screen;
|
---|
622 | screen=0;
|
---|
623 | }
|
---|
624 |
|
---|
625 | if (context)
|
---|
626 | {
|
---|
627 | delete context;
|
---|
628 | context=0;
|
---|
629 | }
|
---|
630 | }
|
---|
631 |
|
---|
632 | void x11_display_class::create_X_image(w32 width, w32 height)
|
---|
633 | {
|
---|
634 | destroy_X_image();
|
---|
635 |
|
---|
636 | if (shm_extension)
|
---|
637 | {
|
---|
638 | w16 w=width,h=height;
|
---|
639 | shm_image=shm_extension->create_shm_image(display,
|
---|
640 | mainwin,
|
---|
641 | gc,
|
---|
642 | my_visual->visual,
|
---|
643 | my_visual->depth,
|
---|
644 | w,h); // actual width and height from X
|
---|
645 | screen=new I4_SCREEN_TYPE(w,h,pal,
|
---|
646 | w*I4_BYTES_PER_PIXEL,
|
---|
647 | (w8 *)shm_image->data);
|
---|
648 | }
|
---|
649 | else
|
---|
650 | {
|
---|
651 |
|
---|
652 | ximage = XCreateImage( display,
|
---|
653 | my_visual->visual,
|
---|
654 | my_visual->depth,
|
---|
655 | ZPixmap,
|
---|
656 | 0,
|
---|
657 | (char *)i4_malloc(width*height*I4_BYTES_PER_PIXEL,"Ximage"),
|
---|
658 | width,
|
---|
659 | height,
|
---|
660 | 32,
|
---|
661 | 0 );
|
---|
662 |
|
---|
663 | screen=new I4_SCREEN_TYPE(width,height,pal,
|
---|
664 | width*I4_BYTES_PER_PIXEL, // bytes per line
|
---|
665 | (w8 *)ximage->data);
|
---|
666 | }
|
---|
667 |
|
---|
668 | if (context)
|
---|
669 | delete context;
|
---|
670 |
|
---|
671 | context=new i4_draw_context_class(0,0,screen->width()-1,screen->height()-1);
|
---|
672 | context->both_dirty=new i4_rect_list_class;
|
---|
673 | context->single_dirty=new i4_rect_list_class;
|
---|
674 | }
|
---|
675 |
|
---|
676 |
|
---|
677 | i4_bool x11_display_class::open_X_window(w32 width, w32 height, i4_display_class::mode *mode)
|
---|
678 | // assumes that the display has already been grabbed
|
---|
679 | {
|
---|
680 | if (!open_display()) return i4_F;
|
---|
681 |
|
---|
682 | width=(width+3)&(~3);
|
---|
683 |
|
---|
684 | XVisualInfo vis_info;
|
---|
685 | int items;
|
---|
686 | XEvent report;
|
---|
687 | XTextProperty winName;
|
---|
688 | char *win_name,*icon_name;
|
---|
689 | if (i4_global_argv)
|
---|
690 | win_name=icon_name=i4_global_argv[0];
|
---|
691 | else
|
---|
692 | win_name=icon_name="...";
|
---|
693 |
|
---|
694 | // locate a visual same depth as i4_SCREEN_DEPTH
|
---|
695 |
|
---|
696 | if (I4_SCREEN_DEPTH==8)
|
---|
697 | {
|
---|
698 | vis_info.depth=8;
|
---|
699 | vis_info.c_class=PseudoColor;
|
---|
700 | }
|
---|
701 | else if (I4_SCREEN_DEPTH==15)
|
---|
702 | {
|
---|
703 | vis_info.depth=16;
|
---|
704 | vis_info.c_class=TrueColor;
|
---|
705 | }
|
---|
706 | else if (I4_SCREEN_DEPTH==16)
|
---|
707 | {
|
---|
708 | vis_info.depth=16;
|
---|
709 | vis_info.c_class=TrueColor;
|
---|
710 | }
|
---|
711 | else if (I4_SCREEN_DEPTH==32)
|
---|
712 | {
|
---|
713 | vis_info.depth=24;
|
---|
714 | vis_info.c_class=TrueColor;
|
---|
715 | }
|
---|
716 |
|
---|
717 |
|
---|
718 | my_visual = XGetVisualInfo(display,VisualClassMask | VisualDepthMask, &vis_info,&items);
|
---|
719 | screen_num = DefaultScreen(display);
|
---|
720 |
|
---|
721 | if (items>0)
|
---|
722 | {
|
---|
723 | XMatchVisualInfo(display, screen_num, vis_info.depth, vis_info.c_class, &vis_info);
|
---|
724 | my_visual->visual = vis_info.visual;
|
---|
725 | } else return i4_F;
|
---|
726 |
|
---|
727 |
|
---|
728 | Colormap tmpcmap;
|
---|
729 |
|
---|
730 | tmpcmap = XCreateColormap(display,
|
---|
731 | XRootWindow(display,my_visual->screen),my_visual->visual,
|
---|
732 | AllocNone);
|
---|
733 |
|
---|
734 | int attribmask = CWColormap | CWBorderPixel;
|
---|
735 | XSetWindowAttributes attribs;
|
---|
736 | attribs.border_pixel = 0;
|
---|
737 | attribs.colormap = tmpcmap;
|
---|
738 |
|
---|
739 | width=(width+3)&(0xffffffff-3);
|
---|
740 | mainwin=XCreateWindow(display,
|
---|
741 | XRootWindow(display,my_visual->screen),
|
---|
742 | 0,0,
|
---|
743 | width,height,
|
---|
744 | 0,
|
---|
745 | my_visual->depth,
|
---|
746 | InputOutput,
|
---|
747 | my_visual->visual,
|
---|
748 | attribmask,
|
---|
749 | &attribs);
|
---|
750 | XFreeColormap(display,tmpcmap);
|
---|
751 |
|
---|
752 | XSelectInput(display,mainwin,
|
---|
753 | KeyPressMask | VisibilityChangeMask | ButtonPressMask | ButtonReleaseMask |
|
---|
754 | ButtonMotionMask | PointerMotionMask | KeyReleaseMask | ExposureMask |
|
---|
755 | StructureNotifyMask);
|
---|
756 |
|
---|
757 | XGCValues values;
|
---|
758 | gc=XCreateGC(display,mainwin,0,&values);
|
---|
759 | XSetBackground(display,gc,BlackPixel(display,screen_num));
|
---|
760 |
|
---|
761 | XMapWindow(display,mainwin);
|
---|
762 | do
|
---|
763 | { XNextEvent(display, &report);
|
---|
764 | } while (report.type!= Expose); // wait for our window to pop up
|
---|
765 |
|
---|
766 | /*
|
---|
767 | if (I4_SCREEN_DEPTH==8)
|
---|
768 | xcolor_map=XCreateColormap(display,mainwin,my_visual->visual,AllocAll);
|
---|
769 | */
|
---|
770 |
|
---|
771 | i4_pixel_format f;
|
---|
772 | f.red_mask = mode->red_mask;
|
---|
773 | f.green_mask = mode->green_mask;
|
---|
774 | f.blue_mask = mode->blue_mask;
|
---|
775 | f.alpha_mask = 0;
|
---|
776 |
|
---|
777 | f.calc_shift();
|
---|
778 |
|
---|
779 | f.lookup = 0;
|
---|
780 | f.pixel_depth = I4_16BIT;
|
---|
781 |
|
---|
782 | pal = i4_pal_man.register_pal(&f);
|
---|
783 |
|
---|
784 |
|
---|
785 | if (shm_extension)
|
---|
786 | {
|
---|
787 | char *ds_name=getenv("DISPLAY");
|
---|
788 | if (!ds_name)
|
---|
789 | ds_name="unix:0.0";
|
---|
790 |
|
---|
791 | if (!shm_extension->available(display,ds_name))
|
---|
792 | shm_extension=0;
|
---|
793 | }
|
---|
794 |
|
---|
795 | create_X_image(width, height);
|
---|
796 |
|
---|
797 | return i4_T;
|
---|
798 | }
|
---|
799 |
|
---|
800 |
|
---|
801 |
|
---|
802 | i4_bool x11_display_class::initialize_mode(mode *which_one)
|
---|
803 | {
|
---|
804 | if ((((x11_mode *)which_one)->assoc)==this)
|
---|
805 | {
|
---|
806 | memcpy(&cur_mode,which_one,sizeof(cur_mode));
|
---|
807 | // this should open an X window
|
---|
808 |
|
---|
809 | open_X_window(cur_mode.xres, cur_mode.yres, which_one);
|
---|
810 |
|
---|
811 | XDefineCursor(display,mainwin, CreateNullCursor(display,mainwin));
|
---|
812 |
|
---|
813 | i4_kernel.add_device(&devs);
|
---|
814 |
|
---|
815 | } else return i4_F;
|
---|
816 | return i4_T;
|
---|
817 | }
|
---|
818 |
|
---|
819 |
|
---|
820 | i4_bool x11_display_class::close()
|
---|
821 | {
|
---|
822 | if (screen)
|
---|
823 | {
|
---|
824 | close_X_window();
|
---|
825 | i4_kernel.remove_device(&devs);
|
---|
826 | }
|
---|
827 | // close the X window, or return to normal mode of operation
|
---|
828 | // prepare for end of program or next mode set
|
---|
829 | }
|
---|
830 |
|
---|
831 |
|
---|
832 | i4_bool x11_display_class::open_display()
|
---|
833 | {
|
---|
834 | // get the default display name from the environment variable DISPLAY
|
---|
835 | char *ds_name=getenv("DISPLAY");
|
---|
836 | if (!ds_name || ds_name[0]==0)
|
---|
837 | ds_name="unix:0.0";
|
---|
838 |
|
---|
839 | // check the command line args for another display
|
---|
840 | w32 i=1;
|
---|
841 | for (;i<i4_global_argc;i++)
|
---|
842 | {
|
---|
843 | if (!strcmp(i4_global_argv[i],"-display"))
|
---|
844 | {
|
---|
845 | i++;
|
---|
846 | ds_name=i4_global_argv[i];
|
---|
847 | }
|
---|
848 | }
|
---|
849 | display=XOpenDisplay(ds_name);
|
---|
850 | if (!display)
|
---|
851 | return i4_F;
|
---|
852 | else return i4_T;
|
---|
853 | }
|
---|
854 |
|
---|
855 |
|
---|
856 | void x11_display_class::close_display()
|
---|
857 | {
|
---|
858 | XCloseDisplay(display);
|
---|
859 | display=NULL;
|
---|
860 | }
|
---|
861 |
|
---|
862 |
|
---|
863 | i4_bool x11_display_class::available()
|
---|
864 | {
|
---|
865 | if (display) // arleady open
|
---|
866 | return i4_T;
|
---|
867 |
|
---|
868 | // determine if the display is available
|
---|
869 | if (open_display())
|
---|
870 | {
|
---|
871 | close_display();
|
---|
872 | return i4_T;
|
---|
873 | } else
|
---|
874 | return i4_F;
|
---|
875 | }
|
---|
876 |
|
---|
877 |
|
---|
878 | i4_bool x11_display_class::realize_palette(i4_pal_handle_class pal_id)
|
---|
879 | // loads the palette into hardware registers,
|
---|
880 | // return i4_F if pal_id is wrong color depth for display
|
---|
881 | // use i4_pal_manager_class::get_pal() to retrieve palette memory
|
---|
882 | {
|
---|
883 | /* if (pal_id.is_8bit())
|
---|
884 | {
|
---|
885 | XColor color;
|
---|
886 | color.flags=DoRed|DoBlue|DoGreen;
|
---|
887 | w32 *p=i4_pal_man.get_pal(pal_id);
|
---|
888 | int i;
|
---|
889 | for (i=0;i<256;i++,p++)
|
---|
890 | {
|
---|
891 | color.pixel=i;
|
---|
892 | color.red= ((((*p)&0x00ff0000)>>16)<<8)|0xff;
|
---|
893 | color.green=((((*p)&0x0000ff00)>>8)<<8)|0xff;
|
---|
894 | color.blue= ((((*p)&0x000000ff))<<8)|0xff;
|
---|
895 | XStoreColor(display,xcolor_map,&color);
|
---|
896 | }
|
---|
897 | XSetWindowColormap(display,mainwin,xcolor_map);
|
---|
898 | pal=pal_id;
|
---|
899 | if (screen)
|
---|
900 | screen->set_pal(pal);
|
---|
901 | } */
|
---|
902 | return i4_T;
|
---|
903 | }
|
---|
904 |
|
---|
905 |
|
---|
906 | i4_bool x11_display_class::copy_part_to_vram(i4_coord x, i4_coord y,
|
---|
907 | i4_coord x1, i4_coord y1,
|
---|
908 | i4_coord x2, i4_coord y2)
|
---|
909 | // this should copy a portion of an image to the actual screen at offset x, y
|
---|
910 | {
|
---|
911 | if (shm_image)
|
---|
912 | return shm_image->copy_part_to_vram(shm_extension,x,y,x1,y1,x2,y2);
|
---|
913 | else
|
---|
914 | {
|
---|
915 | XPutImage(display,mainwin,gc,ximage,x1,y1,x,y,x2-x1+1,y2-y1+1);
|
---|
916 | return i4_T;
|
---|
917 | }
|
---|
918 | }
|
---|
919 |
|
---|