x11.hidd: clean up includes to fix build under linux-armhf
[AROS.git] / arch / all-hosted / hidd / x11 / x11.c
blobca8b2a857dd115c94187353e42edffd4e41f1c53
1 /*
2 Copyright © 1995-2016, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: X11 hidd. Connects to the X server and receives events.
6 Lang: English.
7 */
9 #include "x11_debug.h"
11 #include <hardware/intbits.h>
13 #include <X11/keysym.h>
14 #include <signal.h>
16 #include "x11_types.h"
17 #include "x11.h"
18 #include "x11_hostlib.h"
19 #include "fullscreen.h"
21 VOID X11BM_ExposeFB(APTR data, WORD x, WORD y, WORD width, WORD height);
23 /****************************************************************************************/
25 #define BETTER_REPEAT_HANDLING 1
27 #define XTASK_NAME "x11hidd task"
29 /* We need to have highest priority for this task, because we
30 are simulating an interrupt. I.e. an "interrupt handler" called
31 by this task should NEVER be interrupted by a task (for example input.device),
32 otherwise it will give strange effects, especially in the circular-buffer
33 handling in gameport/keyboard. (Writing to the buffer is not atomic even
34 from within the IRQ handler!)
36 Instead of calling
37 the irq handler directly from the task, we should instead
38 Cause() a software irq, but Cause() does not work at the moment..
41 #define XTASK_PRIORITY 50
43 #define XTASK_STACKSIZE (AROS_STACKSIZE)
45 #undef XSD
46 #define XSD(cl) xsd
48 /****************************************************************************************/
50 AROS_INTH1(x11VBlank, struct Task *, task)
52 AROS_INTFUNC_INIT
54 DB2(bug("[X11] %s()\n", __PRETTY_FUNCTION__));
56 Signal(task, SIGBREAKF_CTRL_D);
58 return FALSE;
60 AROS_INTFUNC_EXIT
63 /****************************************************************************************/
65 VOID x11task_entry(struct x11task_params *xtpparam)
67 ULONG notifysig;
68 struct MinList nmsg_list;
69 struct MinList xwindowlist;
70 ULONG hostclipboardmask;
71 BOOL f12_down = FALSE;
72 KeySym ks;
74 /* copy needed parameter's because they are allocated on the parent's stack */
76 struct Task *task_Parent = xtpparam->parent;
77 ULONG task_SigKill = xtpparam->kill_signal;
78 struct x11_staticdata *xsd = xtpparam->xsd;
80 struct Interrupt myint;
82 D(bug("[X11] %s()\n", __PRETTY_FUNCTION__));
84 xsd->x11task_notify_port = CreateMsgPort();
85 if (NULL == xsd->x11task_notify_port)
87 D(bug("[X11] %s: failed to create notification port!\n", __PRETTY_FUNCTION__));
88 Signal(task_Parent, xtpparam->fail_signal);
89 return;
92 D(bug("[X11] %s: notification port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
94 notifysig = 1L << xsd->x11task_notify_port->mp_SigBit;
96 D(bug("[X11] %s: notification signal = %08x (bit %d)\n", __PRETTY_FUNCTION__, notifysig, xsd->x11task_notify_port->mp_SigBit));
98 NEWLIST(&nmsg_list);
99 NEWLIST(&xwindowlist);
101 myint.is_Code = (VOID_FUNC) x11VBlank;
102 myint.is_Data = FindTask(NULL);
103 myint.is_Node.ln_Name = "X11 VBlank server";
104 myint.is_Node.ln_Pri = 0;
105 myint.is_Node.ln_Type = NT_INTERRUPT;
107 AddIntServer(INTB_VERTB, &myint);
109 Signal(task_Parent, xtpparam->ok_signal);
111 /* N.B : do not attempt to use xtpparam after this point! */
113 hostclipboardmask = x11clipboard_init(xsd);
115 for (;;)
117 XEvent event;
118 #if BETTER_REPEAT_HANDLING
119 XEvent keyrelease_event;
120 BOOL keyrelease_pending = FALSE;
121 #endif
122 struct notify_msg *nmsg;
123 ULONG sigs;
125 DB2(bug("[X11] %s: waiting for signals...\n", __PRETTY_FUNCTION__));
127 sigs = Wait(SIGBREAKF_CTRL_D | notifysig | task_SigKill| hostclipboardmask);
129 DB2(bug("[X11] %s: signal %08x received\n", __PRETTY_FUNCTION__, sigs));
131 if (sigs & task_SigKill)
133 D(bug("[X11] %s: kill signal received - exiting\n", __PRETTY_FUNCTION__));
134 break;
137 if (sigs & notifysig)
139 D(bug("[X11] %s: notification signal received\n", __PRETTY_FUNCTION__));
141 while ((nmsg = (struct notify_msg *) GetMsg(xsd->x11task_notify_port)))
143 /* Add the messages to an internal list */
145 switch (nmsg->notify_type)
147 case NOTY_WINCREATE:
149 struct xwinnode * node;
150 /* Maintain a list of open windows for the X11 event handler in x11.c */
152 D(bug("[X11] %s: NOTY_WINCREATE\n", __PRETTY_FUNCTION__));
154 node = AllocMem(sizeof(struct xwinnode), MEMF_CLEAR);
156 if (NULL != node)
158 node->xwindow = nmsg->xwindow;
159 node->masterxwindow = nmsg->masterxwindow;
160 node->bmobj = nmsg->bmobj;
161 AddTail((struct List *) &xwindowlist, (struct Node *) node);
163 else
165 bug("!!!! CANNOT GET MEMORY FOR X11 WIN NODE\n");
166 CCALL(raise, 19);
169 ReplyMsg((struct Message *) nmsg);
170 break;
172 case NOTY_MAPWINDOW:
174 D(bug("[X11] %s: NOTY_MAPWINDOW Window @ 0x%p (Display = 0x%p)\n", __PRETTY_FUNCTION__, nmsg->xwindow, nmsg->xdisplay));
176 LOCK_X11
177 XCALL(XMapWindow, nmsg->xdisplay, nmsg->xwindow);
178 #if ADJUST_XWIN_SIZE
179 XCALL(XMapRaised, nmsg->xdisplay, nmsg->masterxwindow);
180 #endif
181 UNLOCK_X11
183 AddTail((struct List *) &nmsg_list, (struct Node *) nmsg);
185 /* Do not reply message yet */
186 break;
188 case NOTY_RESIZEWINDOW:
190 XWindowChanges xwc;
191 XSizeHints sizehint;
192 BOOL replymsg = TRUE;
194 D(bug("[X11] %s: NOTY_RESIZEWINDOW\n", __PRETTY_FUNCTION__));
196 xwc.width = nmsg->width;
197 xwc.height = nmsg->height;
199 sizehint.flags = PMinSize | PMaxSize;
200 sizehint.min_width = nmsg->width;
201 sizehint.min_height = nmsg->height;
202 sizehint.max_width = nmsg->width;
203 sizehint.max_height = nmsg->height;
205 LOCK_X11
206 if (xsd->options & OPTION_FULLSCREEN)
208 x11_fullscreen_switchmode(nmsg->xdisplay, &xwc.width, &xwc.height);
211 XCALL(XSetWMNormalHints, nmsg->xdisplay, nmsg->masterxwindow, &sizehint);
212 XCALL(XConfigureWindow, nmsg->xdisplay, nmsg->masterxwindow, CWWidth | CWHeight, &xwc);
213 XCALL(XFlush, nmsg->xdisplay);
214 UNLOCK_X11
216 if (xsd->options & OPTION_DELAYXWINMAPPING)
218 struct xwinnode *node;
219 ForeachNode(&xwindowlist, node)
221 if (node->xwindow == nmsg->xwindow)
223 if (!node->window_mapped)
225 LOCK_X11
226 XCALL(XMapWindow, nmsg->xdisplay, nmsg->xwindow);
227 #if ADJUST_XWIN_SIZE
228 XCALL(XMapRaised, nmsg->xdisplay, nmsg->masterxwindow);
229 #endif
230 if (xsd->options & OPTION_FULLSCREEN)
232 XCALL(XGrabKeyboard, nmsg->xdisplay, nmsg->xwindow, False, GrabModeAsync, GrabModeAsync, CurrentTime);
233 XCALL(XGrabPointer, nmsg->xdisplay, nmsg->xwindow, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, nmsg->xwindow, None, CurrentTime);
236 XCALL(XFlush, nmsg->xdisplay);
237 UNLOCK_X11
239 nmsg->notify_type = NOTY_MAPWINDOW;
240 AddTail((struct List *) &nmsg_list, (struct Node *) nmsg);
242 /* Do not reply message yet */
243 replymsg = FALSE;
245 break;
251 if (replymsg)
252 ReplyMsg((struct Message *) nmsg);
254 break;
256 case NOTY_WINDISPOSE:
258 struct xwinnode *node, *safe;
260 D(bug("[X11] %s: NOTY_WINDISPOSE\n", __PRETTY_FUNCTION__));
262 ForeachNodeSafe(&xwindowlist, node, safe)
264 if (node->xwindow == nmsg->xwindow)
266 Remove((struct Node *) node);
267 FreeMem(node, sizeof(struct xwinnode));
270 ReplyMsg((struct Message *) nmsg);
271 break;
273 } /* switch() */
274 } /* while () */
275 //continue;
276 } /* if (message from notify port) */
278 if (sigs & hostclipboardmask)
280 x11clipboard_handle_commands(xsd);
283 for (;;)
285 struct xwinnode *node;
286 int pending;
287 BOOL window_found = FALSE;
289 LOCK_X11
290 XCALL(XFlush, xsd->display);
291 XCALL(XSync, xsd->display, FALSE);
292 pending = XCALL(XEventsQueued, xsd->display, QueuedAlready);
293 UNLOCK_X11
295 if (pending == 0)
297 #if BETTER_REPEAT_HANDLING
298 if (keyrelease_pending)
300 LOCK_X11
301 if (XCALL(XLookupKeysym, (XKeyEvent *)&keyrelease_event, 0)
302 == XK_F12)
304 f12_down = FALSE;
306 UNLOCK_X11
308 ObtainSemaphoreShared(&xsd->sema);
309 if (xsd->kbdhidd)
311 Hidd_X11Kbd_HandleEvent(xsd->kbdhidd, &keyrelease_event);
313 ReleaseSemaphore(&xsd->sema);
314 keyrelease_pending = FALSE;
316 #endif
318 /* Get out of for(;;) loop */
319 break;
322 LOCK_X11
323 XCALL(XNextEvent, xsd->display, &event);
324 UNLOCK_X11
326 D(bug("Got Event for X=%d\n", event.xany.window));
328 #if BETTER_REPEAT_HANDLING
329 if (keyrelease_pending)
331 BOOL repeated_key = FALSE;
333 /* Saw this in SDL/X11 code, where a comment says that
334 the idea for this was coming from GII, whatever that
335 is. */
337 if ((event.xany.window == keyrelease_event.xany.window)
338 && (event.type == KeyPress)
339 && (event.xkey.keycode == keyrelease_event.xkey.keycode)
340 && ((event.xkey.time - keyrelease_event.xkey.time) < 2))
342 repeated_key = TRUE;
345 keyrelease_pending = FALSE;
347 if (repeated_key)
349 /* Drop both previous keyrelease and this keypress event. */
350 continue;
353 LOCK_X11
354 if (XCALL(XLookupKeysym, (XKeyEvent *)&keyrelease_event, 0)
355 == XK_F12)
357 f12_down = FALSE;
359 UNLOCK_X11
361 ObtainSemaphoreShared(&xsd->sema);
362 if (xsd->kbdhidd)
364 Hidd_X11Kbd_HandleEvent(xsd->kbdhidd, &keyrelease_event);
366 ReleaseSemaphore(&xsd->sema);
368 #endif
370 if (event.type == MappingNotify)
372 LOCK_X11
373 XCALL(XRefreshKeyboardMapping, (XMappingEvent*)&event);
374 UNLOCK_X11
376 continue;
379 #if ADJUST_XWIN_SIZE
380 /* Must check this here, because below only the inner
381 window events are recognized */
383 if ((event.type == ClientMessage) && (event.xclient.data.l[0] == xsd->delete_win_atom))
385 D(bug("Shutting down AROS\n"));
386 CCALL(raise, SIGINT);
389 /* Redirect focus from outer window to inner window. This allows
390 keys to be seen without the mouse hovering over the window */
391 if (event.type == FocusIn)
393 ForeachNode(&xwindowlist, node)
395 if (node->masterxwindow == event.xfocus.window)
397 LOCK_X11
398 XCALL(XSetInputFocus, xsd->display, node->xwindow,
399 RevertToParent, CurrentTime);
400 UNLOCK_X11
401 break;
405 #endif
407 ForeachNode(&xwindowlist, node)
409 if (node->xwindow == event.xany.window)
411 window_found = TRUE;
412 break;
416 if (x11clipboard_want_event(&event))
418 x11clipboard_handle_event(xsd, &event);
421 if (window_found)
423 D(bug("Got event for window %x\n", event.xany.window));
424 switch (event.type)
426 case GraphicsExpose:
427 break;
429 case Expose:
430 LOCK_X11
431 X11BM_ExposeFB(OOP_INST_DATA(OOP_OCLASS(node->bmobj), node->bmobj), event.xexpose.x,
432 event.xexpose.y, event.xexpose.width, event.xexpose.height);
433 UNLOCK_X11
434 break;
436 case ConfigureRequest:
437 bug("!!! CONFIGURE REQUEST !!\n");
438 break;
440 #if 0
441 /* stegerg: not needed */
442 case ConfigureNotify:
444 /* The window has been resized */
446 XConfigureEvent *me;
447 struct notify_msg *nmsg, *safe;
449 me = (XConfigureEvent *)&event;
450 ForeachNodeSafe(&nmsg_list, nmsg, safe)
452 if ( me->window == nmsg->xwindow
453 && nmsg->notify_type == NOTY_RESIZEWINDOW)
455 /* The window has now been mapped.
456 Send reply to app */
458 Remove((struct Node *)nmsg);
459 ReplyMsg((struct Message *)nmsg);
463 break;
465 #endif
467 case ButtonPress:
468 xsd->x_time = event.xbutton.time;
469 D(bug("ButtonPress event\n"));
471 ObtainSemaphoreShared(&xsd->sema);
472 if (xsd->mousehidd)
473 Hidd_X11Mouse_HandleEvent(xsd->mousehidd, &event);
474 ReleaseSemaphore(&xsd->sema);
475 break;
477 case ButtonRelease:
478 xsd->x_time = event.xbutton.time;
479 D(bug("ButtonRelease event\n"));
481 ObtainSemaphoreShared(&xsd->sema);
482 if (xsd->mousehidd)
483 Hidd_X11Mouse_HandleEvent(xsd->mousehidd, &event);
484 ReleaseSemaphore(&xsd->sema);
485 break;
487 case MotionNotify:
488 xsd->x_time = event.xmotion.time;
489 D(bug("Motionnotify event\n"));
491 ObtainSemaphoreShared(&xsd->sema);
492 if (xsd->mousehidd)
493 Hidd_X11Mouse_HandleEvent(xsd->mousehidd, &event);
494 ReleaseSemaphore(&xsd->sema);
495 break;
497 case FocusOut:
498 #if !BETTER_REPEAT_HANDLING
499 LOCK_X11
500 XCALL(XAutoRepeatOn, xsd->display);
501 UNLOCK_X11
502 #endif
503 break;
505 case FocusIn:
506 /* Call the user supplied callback func, if supplied */
507 if (NULL != xsd->activecallback)
509 xsd->activecallback(xsd->callbackdata, NULL);
511 break;
513 case KeyPress:
514 xsd->x_time = event.xkey.time;
516 LOCK_X11
517 #if !BETTER_REPEAT_HANDLING
518 XCALL(XAutoRepeatOff, XSD(cl)->display);
519 #endif
520 ks = XCALL(XLookupKeysym, (XKeyEvent *)&event, 0);
521 if (ks == XK_F12)
523 f12_down = TRUE;
525 else if (f12_down && ((ks == XK_Q) || (ks == XK_q)))
527 CCALL(raise, SIGINT);
529 UNLOCK_X11
531 ObtainSemaphoreShared(&xsd->sema);
532 if (xsd->kbdhidd)
534 Hidd_X11Kbd_HandleEvent(xsd->kbdhidd, &event);
536 ReleaseSemaphore(&xsd->sema);
537 break;
539 case KeyRelease:
540 xsd->x_time = event.xkey.time;
542 #if BETTER_REPEAT_HANDLING
543 keyrelease_pending = TRUE;
544 keyrelease_event = event;
545 #else
546 LOCK_X11
547 if (XCALL(XLookupKeysym, &event, 0) == XK_F12)
549 f12_down = FALSE;
551 XCALL(XAutoRepeatOn, XSD(cl)->display);
552 UNLOCK_X11
554 ObtainSemaphoreShared( &xsd->sema );
555 if (xsd->kbdhidd)
557 Hidd_X11Kbd_HandleEvent(xsd->kbdhidd, &event);
559 ReleaseSemaphore( &xsd->sema );
560 #endif
561 break;
563 case EnterNotify:
564 break;
566 case LeaveNotify:
567 break;
569 case MapNotify:
572 XMapEvent *me;
573 struct notify_msg *nmsg, *safe;
574 struct xwinnode *node;
576 me = (XMapEvent *) &event;
578 ForeachNodeSafe(&nmsg_list, nmsg, safe)
580 if (me->window == nmsg->xwindow && nmsg->notify_type == NOTY_MAPWINDOW)
582 /* The window has now been mapped.
583 Send reply to app */
585 Remove((struct Node *) nmsg);
586 ReplyMsg((struct Message *) nmsg);
590 /* Find it in the window list and mark it as mapped */
592 ForeachNode(&xwindowlist, node)
594 if (node->xwindow == me->window)
596 node->window_mapped = TRUE;
600 break;
603 #if !ADJUST_XWIN_SIZE
604 case ClientMessage:
605 if (event.xclient.data.l[0] == xsd->delete_win_atom)
607 CCALL(raise, SIGINT);
609 break;
610 #endif
612 } /* switch (X11 event type) */
614 } /* if (is event for HIDD window) */
616 } /* while (events from X) */
618 } /* Forever */
620 /* Also try to free window node list ? */
621 if (xsd->x11task_notify_port)
623 DeleteMsgPort(xsd->x11task_notify_port);
627 /****************************************************************************************/
629 struct Task *create_x11task(struct x11task_params *params)
631 struct Task *task;
633 D(bug("[X11] %s()\n", __PRETTY_FUNCTION__));
635 task = NewCreateTask(TASKTAG_PC, x11task_entry, TASKTAG_STACKSIZE,
636 XTASK_STACKSIZE, TASKTAG_NAME, XTASK_NAME, TASKTAG_PRI,
637 XTASK_PRIORITY, TASKTAG_ARG1, params, TAG_DONE);
638 if (task)
640 D(bug("[X11] %s: task @ 0x%p\n", __PRETTY_FUNCTION__, task));
642 /* Everything went OK. Wait for task to initialize */
643 ULONG sigset;
645 sigset = Wait(params->ok_signal | params->fail_signal);
646 if (sigset & params->ok_signal)
648 D(bug("[X11] %s: got ok signal\n", __PRETTY_FUNCTION__));
650 return task;
653 return NULL;
656 /****************************************************************************************/