source: golgotha/src/i4/video/x11/x11_input.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 14 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 17.2 KB
Line 
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/x11/x11_input.hh"
10#include "main/main.hh"
11#include "video/x11/x11_display.hh"
12#include "video/x11/mitshm.hh"
13#include "video/display.hh"
14#include "device/event.hh"
15#include "device/keys.hh"
16#include "device/kernel.hh"
17#include "image/context.hh"
18
19extern int i4_global_native_argc;
20extern char **i4_global_native_argv;
21
22
23int i4_system_choose_option(char **choices)
24{
25  return 0;
26}
27
28i4_bool x11_input_class::open_display()
29{
30  // get the default display name from the environment variable DISPLAY
31  char ds_name[512];
32
33  strcpy(ds_name,getenv("DISPLAY"));
34  if (ds_name[0]==0)
35    strcpy(ds_name,"unix:0.0");
36
37  if (getenv("X_REPEAT_ON"))
38    repeat_on=i4_T;
39
40  // check the command line args for another display
41  w32 i=1;
42  for (;i<i4_global_argc;i++)
43  {
44    if (i4_global_argv[i] == "-ron")
45      repeat_on=i4_T;
46    else if (i4_global_argv[i] == "-display")
47    {
48      i++;
49      i4_os_string(i4_global_argv[i], ds_name, sizeof(ds_name));
50    }
51  }
52  display=XOpenDisplay(ds_name); 
53  if (!display)
54    return i4_F;
55
56  if (!repeat_on)
57    XAutoRepeatOff(display);
58  return i4_T;
59}
60
61
62void x11_input_class::close_display()
63{
64  if (display)
65  {
66    if (!repeat_on)
67      XAutoRepeatOn(display);
68
69    XCloseDisplay(display);
70    display=NULL;
71  }
72}
73
74x11_input_class::x11_input_class()
75{
76  repeat_on=i4_F;
77  display=0;
78  need_first_time=i4_T;
79}
80
81XVisualInfo *x11_input_class::find_visual_with_depth(int depth)
82{
83  XVisualInfo vis_info, *v;
84  int items;
85
86  if (!display && !open_display())
87    return 0;
88
89  if (depth==8)
90    vis_info.c_class=PseudoColor;
91  else
92    vis_info.c_class=TrueColor;
93
94  vis_info.depth=depth;
95 
96  v=XGetVisualInfo(display,VisualClassMask | VisualDepthMask, &vis_info, &items);
97
98  if (items>0)
99  {
100    XMatchVisualInfo(display, screen_num, vis_info.depth, vis_info.c_class, &vis_info);
101    v->visual = vis_info.visual;
102    return v;
103  }
104  else if (depth==16)
105    return find_visual_with_depth(15);
106  else
107    return 0;
108}
109
110
111// makes a null cursor
112static Cursor x11_CreateNullCursor(Display *display, Window root)
113{
114  Pixmap cursormask;
115  XGCValues xgc;
116  GC gc;
117  XColor dummycolour;
118  Cursor cursor;
119
120  cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
121  xgc.function = GXclear;
122  gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
123  XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
124  dummycolour.pixel = 0;
125  dummycolour.red = 0;
126  dummycolour.flags = 04;
127  cursor = XCreatePixmapCursor(display, cursormask, cursormask,
128                               &dummycolour,&dummycolour, 0,0);
129  XFreePixmap(display,cursormask);
130  XFreeGC(display,gc);
131  return cursor;
132}
133
134i4_bool x11_input_class::create_window(sw32 x, sw32 y, w32 w, w32 h,
135                                       i4_display_class *_i4_display,
136                                       i4_bool takeup_fullscreen,
137                                       XVisualInfo *visual)
138{
139  i4_display=_i4_display;
140
141  if (!open_display())
142    return i4_F;
143
144  XVisualInfo vis_info;
145  int items;
146  XEvent report;
147  XTextProperty winName;
148
149
150
151  // this will be 8, 16, or 32, (most likely 16 for now)
152  my_visual = visual;
153
154
155  if (!my_visual)
156    return i4_F;
157
158  screen_num  = DefaultScreen(display);
159
160
161  Colormap tmpcmap;
162 
163  tmpcmap = XCreateColormap(display,
164                            XRootWindow(display,my_visual->screen),my_visual->visual,
165                            AllocNone);
166
167  int attribmask = CWColormap | CWBorderPixel;
168  XSetWindowAttributes attribs;
169  attribs.border_pixel = 0;
170  attribs.colormap = tmpcmap;
171
172  w=(w+3)&(~3); 
173  mainwin=XCreateWindow(display,
174                        XRootWindow(display,my_visual->screen),
175                        x,y,
176                        w,h,
177                        0,
178                        my_visual->depth,
179                        InputOutput,
180                        my_visual->visual,
181                        attribmask,
182                        &attribs);
183  XFreeColormap(display,tmpcmap);
184
185  XSelectInput(display,mainwin,
186               KeyPressMask     | VisibilityChangeMask | ButtonPressMask | ButtonReleaseMask |
187               ButtonMotionMask | PointerMotionMask    | KeyReleaseMask  | ExposureMask      |
188               StructureNotifyMask | EnterWindowMask | LeaveWindowMask);
189
190  XGCValues values;
191  gc=XCreateGC(display,mainwin,0,&values);
192  XSetBackground(display,gc,BlackPixel(display,screen_num));
193
194  XMapWindow(display,mainwin);
195  do
196  {
197    XNextEvent(display, &report);
198  } while (report.type!= Expose);     // wait for our window to pop up
199
200  i4_kernel.add_device(this);
201
202  XDefineCursor(display, mainwin, x11_CreateNullCursor(display, mainwin));
203
204
205  wm_delete_window = XInternAtom (display, "WM_DELETE_WINDOW", True);
206  wm_protocols = XInternAtom (display, "WM_PROTOCOLS", True);
207
208  Atom prot[2];
209  prot[0]=wm_delete_window;
210  prot[1]=wm_protocols;
211 
212  XSetWMProtocols(display, mainwin, prot, 2);
213 
214
215  return i4_T;
216}
217
218
219void x11_input_class::destroy_window()
220{
221  i4_kernel.remove_device(this);
222
223  XFreeGC(display, gc);
224  XFree((char *)my_visual);
225
226  close_display();
227
228//   if (I4_SCREEN_DEPTH==8)
229//     XFreeColormap(display,xcolor_map);
230}
231
232
233
234void x11_input_class::get_x_time(w32 xtick, i4_time_class &t)
235{
236  i4_time_class now;
237
238  if (need_first_time)
239  {
240    first_time=xtick;
241    i4_start_time=now;
242    need_first_time=i4_F;
243  }
244
245  w32 xtime=xtick-first_time;
246 
247  t = i4_start_time;
248  t.add_milli(xtime);
249             
250  if (now<t)
251  {
252    i4_start_time=now;
253    i4_start_time.add_milli(-xtime);
254    t=now;
255  }
256}
257
258i4_bool x11_input_class::process_events()
259{
260  i4_bool motion_occured=i4_F;
261  sw32 final_x, final_y;
262
263  if (display)
264  {
265    while (XPending(display))
266    {
267      XEvent xev;
268      XNextEvent(display,&xev);
269
270      note_event(xev);
271
272      switch (xev.type)
273      {
274        case Expose :
275        {
276          if (context)
277          {
278            context->add_both_dirty(xev.xexpose.x,
279                                    xev.xexpose.y,
280                                    xev.xexpose.x+xev.xexpose.width,
281                                    xev.xexpose.y+xev.xexpose.height);
282          }
283        } break;
284
285
286        case ClientMessage:
287        {
288          /* Client messages are the means of the window manager
289           *  communicating with a program. We'll first check to
290           *  see if this is really the window manager talking
291           *  to us.
292           */
293          if (xev.xclient.message_type == wm_protocols)
294          {
295            if ((Atom) xev.xclient.data.l[0] == wm_delete_window)
296            {
297              i4_display_close_event_class dc(i4_display);
298              send_event_to_agents(&dc, i4_device_class::FLAG_DISPLAY_CLOSE);
299            }
300          }
301        } break;
302
303        //{{{  not implemented yet
304        case ConfigureNotify :
305        {
306          XFlush(display);
307
308          int new_width=xev.xconfigure.width&~3;  // must be word alligned
309          int new_height=xev.xconfigure.height;
310          if (new_width!=xev.xconfigure.width)
311            XResizeWindow(display,mainwin,new_width,xev.xconfigure.height);
312
313          XFlush(display);
314
315          resize(new_width, new_height);
316   
317          i4_display_change_event_class d_change(i4_display,
318                                                 i4_display_change_event_class::SIZE_CHANGE);
319         
320          send_event_to_agents(&d_change,FLAG_DISPLAY_CHANGE);
321        } break;
322       
323        case MotionNotify :
324        {
325          motion_occured=i4_T;
326          final_x=xev.xmotion.x;
327          final_y=xev.xmotion.y;
328        } break;
329         
330        case ButtonRelease :
331        case ButtonPress :
332        {   
333          i4_mouse_button_event_class::btype but;
334          switch (xev.xbutton.button)
335          {
336            case 1 : but=i4_mouse_button_event_class::LEFT; break;
337            case 3 : but=i4_mouse_button_event_class::RIGHT; break;
338            case 2 : but=i4_mouse_button_event_class::CENTER; break;
339          }
340
341          i4_time_class now;
342          if (xev.type == ButtonRelease)
343          {
344            i4_mouse_button_up_event_class up(but, mouse_x, mouse_y,
345                                              now, last_up[but]);
346            send_event_to_agents(&up,FLAG_MOUSE_BUTTON_UP);
347            last_up[but]=now;
348          }
349          else
350          {
351            i4_mouse_button_down_event_class up(but, mouse_x, mouse_y,
352                                                now, last_down[but]);
353            send_event_to_agents(&up,FLAG_MOUSE_BUTTON_DOWN);
354            last_down[but]=now;
355          }
356        } break;
357
358        case KeyPress :
359        case KeyRelease :
360        {
361          char buf;
362          KeySym ks;
363          XLookupString(&xev.xkey,&buf,1,&ks,NULL);
364          w16 key, key_code;
365
366          switch (ks)
367          {
368            case XK_Down :    key_code=I4_DOWN; break;
369            case XK_Up :      key_code=I4_UP;  break;
370            case XK_Left :    key_code=I4_LEFT;  break;
371            case XK_Right :     key_code=I4_RIGHT; break;
372            case XK_Control_L :   
373            {
374              key_code=I4_CTRL_L;
375              if (xev.type==KeyPress)
376                modifier_state|=I4_MODIFIER_CTRL_L; 
377              else
378                modifier_state&=~I4_MODIFIER_CTRL_L; 
379            } break;
380
381            case XK_Control_R :   
382            {
383              key_code=I4_CTRL_R;
384              if (xev.type==KeyPress)
385                modifier_state|=I4_MODIFIER_CTRL_R; 
386              else
387                modifier_state&=~I4_MODIFIER_CTRL_R;
388            } break;
389
390            case XK_Alt_L :   
391            {
392              key_code=I4_ALT_L;
393              if (xev.type==KeyPress)
394                modifier_state|=I4_MODIFIER_ALT_L; 
395              else
396                modifier_state&=~I4_MODIFIER_ALT_L;
397            } break;
398
399            case XK_Alt_R :   
400            {
401              key_code=I4_ALT_R;
402              if (xev.type==KeyPress)
403                modifier_state|=I4_MODIFIER_ALT_R; 
404              else
405                modifier_state&=~I4_MODIFIER_ALT_R;
406            } break;
407
408
409            case XK_Shift_L :   
410            {
411              key_code=I4_SHIFT_L;
412              if (xev.type==KeyPress)
413                modifier_state|=I4_MODIFIER_SHIFT_L; 
414              else
415                modifier_state&=~I4_MODIFIER_SHIFT_L;
416            } break;
417
418            case XK_Shift_R :
419            {
420              key_code=I4_SHIFT_R;
421              if (xev.type==KeyPress)
422                modifier_state|=I4_MODIFIER_SHIFT_R; 
423              else
424                modifier_state&=~I4_MODIFIER_SHIFT_R;
425            } break;
426
427
428            case XK_Num_Lock :          key_code=I4_NUM_LOCK;  break;
429            case XK_Home :    key_code=I4_HOME;  break;
430            case XK_End :     key_code=I4_END;  break;
431            case XK_BackSpace :         key_code=I4_BACKSPACE;  break;
432            case XK_Tab :   key_code=I4_TAB;  break;
433            case XK_Return :    key_code=I4_ENTER;  break;
434            case XK_Caps_Lock :         key_code=I4_CAPS;  break;
435            case XK_Escape :    key_code=I4_ESC;  break;
436            case XK_F1 :                key_code=I4_F1; break;
437            case XK_F2 :                key_code=I4_F2; break;
438            case XK_F3 :                key_code=I4_F3; break;
439            case XK_F4 :                key_code=I4_F4; break;
440            case XK_F5 :                key_code=I4_F5; break;
441            case XK_F6 :                key_code=I4_F6; break;
442            case XK_F7 :                key_code=I4_F7; break;
443            case XK_F8 :                key_code=I4_F8; break;
444            case XK_F9 :                key_code=I4_F9; break;
445            case XK_F10 :               key_code=I4_F10; break;
446            case XK_Insert :            key_code=I4_INSERT; break;
447            case XK_Page_Up :           key_code=I4_PAGEUP; break;
448            case XK_Page_Down :         key_code=I4_PAGEDOWN; break;
449            case XK_Delete :            key_code=I4_DEL; break;
450
451            case XK_KP_0 :              key_code=I4_KP0; break;
452            case XK_KP_1 :              key_code=I4_KP1; break;
453            case XK_KP_2 :              key_code=I4_KP2; break;
454            case XK_KP_3 :              key_code=I4_KP3; break;
455            case XK_KP_4 :              key_code=I4_KP4; break;
456            case XK_KP_5 :              key_code=I4_KP5; break;
457            case XK_KP_6 :              key_code=I4_KP6; break;
458            case XK_KP_7 :              key_code=I4_KP7; break;
459            case XK_KP_8 :              key_code=I4_KP8; break;
460            case XK_KP_9 :              key_code=I4_KP9; break;
461
462            case XK_KP_Insert :         key_code=I4_KP0; break;
463            case XK_KP_End :            key_code=I4_KP1; break;
464            case XK_KP_Down :           key_code=I4_KP2; break;
465            case XK_KP_Page_Down :      key_code=I4_KP3; break;
466            case XK_KP_Left :           key_code=I4_KP4; break;
467            case XK_KP_Begin :          key_code=I4_KP5; break;
468            case XK_KP_Right :          key_code=I4_KP6; break;
469            case XK_KP_Home :           key_code=I4_KP7; break;
470            case XK_KP_Up :             key_code=I4_KP8; break;
471            case XK_KP_Page_Up :        key_code=I4_KP9; break;
472
473                                                case XK_KP_Delete :
474                                                case XK_KP_Decimal :                            key_code=I4_KPPERIOD; break;
475
476            case ' ':                   key_code=I4_SPACE; break;
477            case '`':
478            case '~':                   key_code='`'; break;
479            case '-':
480            case '_':                   key_code='-'; break;
481            case '=':
482            case '+':                   key_code='='; break;
483            case '[':
484            case '{':                   key_code='['; break;
485            case ']':
486            case '}':                   key_code=']'; break;
487            case '\\':
488            case '|':                   key_code='\\'; break;
489            case ';':
490            case ':':                   key_code=';'; break;
491            case '\'':
492            case '"':                   key_code='\''; break;
493            case ',':
494            case '<':                   key_code=','; break;
495            case '.':
496            case '>':                   key_code='.'; break;
497            case '/':
498            case '?':                   key_code='/'; break;
499
500            case ')':                   key_code='0'; break;
501            case '!':                   key_code='1'; break;
502            case '@':                   key_code='2'; break;
503            case '#':                   key_code='3'; break;
504            case '$':                   key_code='4'; break;
505            case '%':                   key_code='5'; break;
506            case '^':                   key_code='6'; break;
507            case '&':                   key_code='7'; break;
508            case '*':                   key_code='8'; break;
509            case '(':                   key_code='9'; break;
510
511            default :
512              if ((ks>=XK_A && ks<=XK_Z) || (ks>=XK_0 && ks<=XK_9))
513                key_code = ks;
514              else if (ks>=XK_a && ks<=XK_z)
515                key_code = ks + 'A' - 'a';
516              else
517                key_code=0;
518          }
519
520          if (key_code)
521          {
522            if (xev.type==KeyPress)
523            {
524              i4_time_class t;
525              get_x_time(xev.xkey.time, t);
526             
527              key = i4_key_translate(key_code,1,modifier_state);
528              i4_key_press_event_class ev(key, key_code, modifier_state, t);
529
530              send_event_to_agents(&ev,FLAG_KEY_PRESS);   
531            }
532            else
533            {
534              key = i4_key_translate(key_code,0, modifier_state);
535
536              i4_time_class t;
537              get_x_time(xev.xkey.time, t);
538             
539              i4_key_release_event_class ev(key, key_code, modifier_state, t);
540              send_event_to_agents(&ev,FLAG_KEY_RELEASE);   
541            }
542          }
543        } break;
544
545        case EnterNotify:
546          if (!repeat_on)
547            XAutoRepeatOff(display);
548          break;
549
550        case LeaveNotify:
551          if (!repeat_on)
552            XAutoRepeatOn(display);
553          break;
554      }
555    }
556  }
557
558         
559  if (motion_occured && (final_x!=mouse_x || final_y!=mouse_y))
560  {   
561    i4_mouse_move_event_class move(mouse_x, mouse_y, final_x, final_y);
562    send_event_to_agents(&move,FLAG_MOUSE_MOVE);
563
564    if (mouse_locked)
565      XWarpPointer(display, None, mainwin, 0,0, 0,0, mouse_x, mouse_y);
566    else
567    {
568      mouse_x=final_x;
569      mouse_y=final_y;
570    }   
571  }
572
573  return i4_F;
574}
Note: See TracBrowser for help on using the repository browser.