2
0

system.linux.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. #include "system.h"
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <signal.h>
  5. #include <pthread.h>
  6. #include <sys/time.h>
  7. #include <sys/sysinfo.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/wait.h>
  10. #include <X11/Xutil.h>
  11. #include <X11/extensions/xf86vmode.h>
  12. #define INTERLACE 0x010
  13. #define DBLSCAN 0x020
  14. typedef struct AsyncOp{
  15. struct AsyncOp *succ;
  16. BBSyncOp syncOp;
  17. BBObject *syncInfo;
  18. int asyncRet;
  19. BBAsyncOp asyncOp;
  20. int asyncInfo;
  21. }AsyncOp;
  22. static AsyncOp *asyncOps;
  23. static pthread_mutex_t asyncMutex=PTHREAD_MUTEX_INITIALIZER;
  24. static int async_pipe[2];
  25. static Display *x_display;
  26. static int x_fd;
  27. static int x_window;
  28. static Cursor x_cursor;
  29. int (*xeventhandler)(XEvent *);
  30. int getxkey(XEvent *event);
  31. int brl_system_XKeyHandler(int type,int key,int mask);
  32. static void postAsyncOp( AsyncOp *p ){
  33. int ch=0;
  34. XEvent event;
  35. AsyncOp **q=&asyncOps,*t;
  36. p->succ=0;
  37. pthread_mutex_lock( &asyncMutex );
  38. while( *q ) q=&(*q)->succ;
  39. *q=p;
  40. write( async_pipe[1],&ch,1 );
  41. pthread_mutex_unlock( &asyncMutex );
  42. }
  43. int bbSystemAsyncFD(){
  44. return async_pipe[0];
  45. }
  46. void bbSystemFlushAsyncOps(){
  47. int rd;
  48. AsyncOp *p;
  49. if( !asyncOps ) return;
  50. pthread_mutex_lock( &asyncMutex );
  51. p=asyncOps;
  52. asyncOps=0;
  53. if( !ioctl( async_pipe[0],FIONREAD,&rd ) ){
  54. static char *buf;
  55. static int buf_sz;
  56. if( rd>buf_sz ){
  57. free( buf );
  58. buf=(char*)malloc( rd );
  59. buf_sz=rd;
  60. }
  61. read( async_pipe[0],buf,rd );
  62. }
  63. pthread_mutex_unlock( &asyncMutex );
  64. while( p ){
  65. AsyncOp *t=p->succ;
  66. p->syncOp( p->syncInfo,p->asyncRet );
  67. if( p->asyncOp ){
  68. BBRELEASE( p->syncInfo );
  69. }
  70. free( p );
  71. p=t;
  72. }
  73. }
  74. void bbSystemShutdown(){
  75. // XCloseDisplay(x_display); causes crash with fltk canvas usage
  76. }
  77. void bbSystemStartup(){
  78. atexit( bbSystemShutdown );
  79. XInitThreads();
  80. x_display=XOpenDisplay(0);
  81. x_fd=ConnectionNumber( x_display );
  82. pipe( async_pipe );
  83. }
  84. Display *bbSystemDisplay(){
  85. return x_display;
  86. }
  87. void bbSetSystemWindow(int window){
  88. x_window=window;
  89. }
  90. void bbMoveMouse(int x,int y){
  91. XWarpPointer(x_display,None,x_window,0,0,0,0,x,y);
  92. }
  93. void bbSetMouseVisible(visible){
  94. if (!x_window) return;
  95. if (visible)
  96. {
  97. XUndefineCursor(x_display,x_window);
  98. }
  99. else
  100. {
  101. if (!x_cursor)
  102. {
  103. XColor black;
  104. char bm[]={0,0,0,0,0,0,0,0};
  105. Pixmap pix=XCreateBitmapFromData(x_display,x_window,bm,8,8);
  106. memset(&black,0,sizeof(XColor));
  107. black.flags=DoRed|DoGreen|DoBlue;
  108. x_cursor=XCreatePixmapCursor(x_display,pix,pix,&black,&black,0,0);
  109. XFreePixmap(x_display,pix);
  110. }
  111. XDefineCursor(x_display,x_window,x_cursor);
  112. }
  113. }
  114. void bbSystemEventHandler( int(*handler)(XEvent*) ){
  115. xeventhandler=handler;
  116. }
  117. void bbSystemEmitOSEvent( XEvent *xevent,BBObject *source ){
  118. XKeyEvent *keyevent;
  119. BBObject *event;
  120. int id,data=0,x=0,y=0,mods=0;
  121. char mybuffer[16];
  122. KeySym mykeysym;
  123. int i,n;
  124. if (xeventhandler){
  125. if (xeventhandler(xevent)) return;
  126. }
  127. x=xevent->xbutton.x;
  128. y=xevent->xbutton.y;
  129. switch( xevent->type ){
  130. case KeyPress:
  131. //
  132. data=getxkey(xevent);
  133. bbSystemEmitEvent( BBEVENT_KEYDOWN,source,data,mods,x,y,&bbNullObject );
  134. //
  135. //Mark swapped above/below - ie: keydown before keychar
  136. //
  137. n=XLookupString( xevent,mybuffer,15,&mykeysym,0 );
  138. for (i=0;i<n;i++){
  139. bbSystemEmitEvent( BBEVENT_KEYCHAR,source,mybuffer[i],0,0,0,&bbNullObject );
  140. }
  141. return;
  142. case KeyRelease:
  143. //
  144. data=getxkey(xevent);
  145. //
  146. //Mark's dodgy fix to generate key repeat events
  147. //Works with "Graphics" style apps - dunno about fltk stuff...
  148. //
  149. if( x_display && XPending( x_display ) ){
  150. XEvent event;
  151. XPeekEvent( x_display,&event );
  152. if( event.type==KeyPress && getxkey( &event )==data ){
  153. XNextEvent( x_display,&event );
  154. //
  155. //generate KEYREPEAT event...
  156. bbSystemEmitEvent( BBEVENT_KEYREPEAT,source,data,mods,x,y,&bbNullObject );
  157. //
  158. //generate KEYCHAR events...
  159. n=XLookupString( xevent,mybuffer,15,&mykeysym,0 );
  160. for (i=0;i<n;i++){
  161. bbSystemEmitEvent( BBEVENT_KEYCHAR,source,mybuffer[i],0,0,0,&bbNullObject );
  162. }
  163. return;
  164. }
  165. }
  166. id=BBEVENT_KEYUP;
  167. break;
  168. case ButtonPress:
  169. data=xevent->xbutton.button;
  170. if (data==4)
  171. {
  172. id=BBEVENT_MOUSEWHEEL;
  173. data=1;
  174. break;
  175. }
  176. if (data==5)
  177. {
  178. id=BBEVENT_MOUSEWHEEL;
  179. data=-1;
  180. break;
  181. }
  182. id=BBEVENT_MOUSEDOWN;
  183. if (data>1) data=5-data;
  184. break;
  185. case ButtonRelease:
  186. id=BBEVENT_MOUSEUP;
  187. data=xevent->xbutton.button;
  188. if (data>1) data=5-data;
  189. break;
  190. case MotionNotify:
  191. id=BBEVENT_MOUSEMOVE;
  192. break;
  193. case ClientMessage:
  194. if( xevent->xclient.data.l[0]==XInternAtom( x_display,"WM_DELETE_WINDOW",True ) ){
  195. id=BBEVENT_APPTERMINATE;
  196. }else{
  197. return;
  198. }
  199. break;
  200. default:
  201. return;
  202. }
  203. bbSystemEmitEvent( id,source,data,mods,x,y,&bbNullObject );
  204. }
  205. void bbSystemPoll(){
  206. if( !x_display ) return;
  207. while( XPending( x_display ) ){
  208. XEvent event;
  209. XNextEvent( x_display,&event );
  210. bbSystemEmitOSEvent(&event,&bbNullObject);
  211. }
  212. bbSystemFlushAsyncOps();
  213. }
  214. void bbSystemWait(){
  215. fd_set in_fds;
  216. struct timeval tv;
  217. if( !x_display ) return;
  218. FD_ZERO( &in_fds );
  219. FD_SET( x_fd,&in_fds );
  220. FD_SET( async_pipe[0],&in_fds );
  221. tv.tv_sec=10;
  222. tv.tv_usec=0;
  223. select( (x_fd>async_pipe[0] ? x_fd : async_pipe[0]) + 1,&in_fds,0,0,&tv );
  224. bbSystemPoll();
  225. }
  226. int getxkey(XEvent *event)
  227. {
  228. int key;
  229. key=XLookupKeysym(&event->xkey,0)&255;
  230. if (key>=97&&key<=126) return key+(65-97); //a..z
  231. if (key>=81&&key<=84) return key+(37-81); //arrow keys
  232. if (key>=190 && key<=201) return key+(112-190); //function keys
  233. if (key==99) return 45; //insert
  234. if (key==227) return 162; //lctrl
  235. if (key==233) return 164; //lalt
  236. if (key==234) return 165; //ralt
  237. if (key==228) return 163; //rctrl
  238. if (key==225) return 160; //lshift
  239. if (key==226) return 161; //rshiftz
  240. if (key==127) return 144; //numlock
  241. if (key==20) return 145; //scroll
  242. if (key==158) return 96; //numkeys 0..9
  243. if (key==156) return 97;
  244. if (key==153) return 98;
  245. if (key==155) return 99;
  246. if (key==150) return 100;
  247. if (key==157) return 101;
  248. if (key==152) return 102;
  249. if (key==149) return 103;
  250. if (key==151) return 104;
  251. if (key==154) return 105;
  252. if (key==235) return 91; //left windows key
  253. if (key==236) return 92; //right windows key
  254. if (key==103) return 93; //startmenu windows key
  255. if (key==80) return 36; //home
  256. if (key==85) return 33; //pageup
  257. if (key==255) return 46; //delete
  258. if (key==87) return 35; //end
  259. if (key==86) return 34; //pagedown
  260. if (key==97) return 42; //print screen
  261. if (key==159) return 110; //keypad .
  262. if (key==141) return 13; //keypad enter
  263. if (key==171) return 107; //keypad add
  264. if (key==173) return 109; //keypad minus
  265. if (key==170) return 106; //keypad mult
  266. if (key==175) return 111; //keypad divide
  267. if (key==96) return 192; //tilde key
  268. if (key=='-') return 189; //minus
  269. if (key=='=') return 187; //equals
  270. if (key==91) return 219; //[
  271. if (key==93) return 221; //]
  272. if (key==92) return 226; //backslash
  273. if (key==59) return 186; //semicolon
  274. if (key==39) return 222; //quotes
  275. if (key==44) return 188; //comma key
  276. if (key==46) return 190; //period key
  277. if (key==47) return 191; //questionmark key
  278. return key;
  279. }
  280. void *asyncOpThread( void *t ){
  281. AsyncOp *p=(AsyncOp*)t;
  282. p->asyncRet=p->asyncOp( p->asyncInfo );
  283. postAsyncOp( p );
  284. return 0;
  285. }
  286. void bbSystemPostSyncOp( BBSyncOp syncOp,BBObject *syncInfo,int asyncRet ){
  287. AsyncOp *p=(AsyncOp*)malloc( sizeof( AsyncOp ) );
  288. p->asyncOp=0;
  289. p->asyncRet=asyncRet;
  290. p->syncOp=syncOp;
  291. p->syncInfo=syncInfo;
  292. postAsyncOp( p );
  293. }
  294. void bbSystemStartAsyncOp( BBAsyncOp asyncOp,int asyncInfo,BBSyncOp syncOp,BBObject *syncInfo ){
  295. pthread_t thread;
  296. AsyncOp *p=(AsyncOp*)malloc( sizeof( AsyncOp ) );
  297. BBRETAIN( syncInfo );
  298. p->asyncOp=asyncOp;
  299. p->asyncInfo=asyncInfo;
  300. p->syncOp=syncOp;
  301. p->syncInfo=syncInfo;
  302. pthread_create( &thread,0,asyncOpThread,p );
  303. pthread_detach( thread );
  304. }
  305. static int _calchertz( XF86VidModeModeInfo *m ){
  306. int freq=( m->dotclock*1000.0 )/( m->htotal*m->vtotal )+.5;
  307. if( m->flags&INTERLACE ) freq<<=1;
  308. if( m->flags&DBLSCAN ) freq>>=1;
  309. return freq;
  310. }
  311. int bbSystemDesktopWidth(){
  312. int count=0,sz=0;
  313. XF86VidModeModeInfo **xmodes=0;
  314. XF86VidModeGetAllModeLines( x_display,DefaultScreen( x_display ),&count,&xmodes );
  315. sz=count>0 ? xmodes[0]->hdisplay : 640;
  316. XFree( xmodes );
  317. return sz;
  318. }
  319. int bbSystemDesktopHeight(){
  320. int count=0,sz=0;
  321. XF86VidModeModeInfo **xmodes=0;
  322. XF86VidModeGetAllModeLines( x_display,DefaultScreen( x_display ),&count,&xmodes );
  323. sz=count>0 ? xmodes[0]->vdisplay : 480;
  324. XFree( xmodes );
  325. return sz;
  326. }
  327. int bbSystemDesktopDepth(){
  328. return 24;
  329. }
  330. int bbSystemDesktopHertz(){
  331. int count=0,sz=0;
  332. XF86VidModeModeInfo **xmodes=0;
  333. XF86VidModeGetAllModeLines( x_display,DefaultScreen( x_display ),&count,&xmodes );
  334. sz=count>0 ? _calchertz( xmodes[0] ) : 60;
  335. XFree( xmodes );
  336. return sz;
  337. }