Added a test for MUIA_Listview_SelectChange.
[AROS.git] / arch / all-hosted / hidd / x11 / onbitmap.c
blob85f5ad9a78ee55c7070abf349ce50d8bdc2a075d
1 /*
2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Bitmap class for X11 hidd.
6 Lang: English.
7 */
9 #include "x11_debug.h"
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <X11/cursorfont.h>
14 #include <X11/keysym.h>
16 #include <exec/memory.h>
17 #include <exec/lists.h>
18 #include <graphics/rastport.h>
19 #include <graphics/gfx.h>
20 #include <oop/oop.h>
21 #include <hidd/graphics.h>
23 #include <proto/oop.h>
24 #include <proto/utility.h>
26 #include "x11.h"
27 #include "bitmap.h"
28 #include "x11gfx_intern.h"
30 /****************************************************************************************/
32 #if ADJUST_XWIN_SIZE
33 #define MASTERWIN(data) (data)->masterxwindow
34 #define ROOTWIN(data) (data)->masterxwindow
35 #else
36 #define MASTERWIN WINDRAWABLE
37 #define ROOTWIN(data) rootwin
38 #endif
40 /****************************************************************************************/
42 static Pixmap init_icon(Display *d, Window w, Colormap cm, LONG depth,
43 struct x11_staticdata *xsd);
45 /****************************************************************************************/
47 BOOL X11BM_InitFB(OOP_Class *cl, OOP_Object *o, struct TagItem *attrList)
49 Window rootwin;
50 OOP_Object *sync, *pixfmt;
51 HIDDT_ModeID modeid;
52 IPTR depth;
53 XSetWindowAttributes winattr;
54 int visualclass;
55 unsigned long valuemask;
56 struct bitmap_data *data = OOP_INST_DATA(cl, o);
57 struct x11_staticdata *xsd = XSD(cl);
59 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
61 /* stegerg */
62 visualclass = GetTagData(aHidd_X11BitMap_VisualClass, TrueColor, attrList);
63 if (visualclass == PseudoColor)
65 Colormap cm;
67 HostLib_Lock();
68 cm = XCALL(XCreateColormap, GetSysDisplay(), RootWindow(GetSysDisplay(), GetSysScreen()),
69 xsd->vi.visual, AllocAll);
70 HostLib_Unlock();
72 if (cm)
74 data->colmap = cm;
75 data->flags |= BMDF_COLORMAP_ALLOCED;
78 /* end stegerg */
81 * Get window size from our ModeID.
82 * We can't support scrolling in framebuffer mode.
84 OOP_GetAttr(o, aHidd_BitMap_ModeID, &modeid);
85 OOP_GetAttr(o, aHidd_BitMap_GfxHidd, (IPTR *) &data->gfxhidd);
86 D(bug("[X11OnBm] ModeID 0x%08X, driver @ 0x%p\n", modeid, data->gfxhidd));
88 HIDD_Gfx_GetMode(data->gfxhidd, modeid, &sync, &pixfmt);
90 OOP_GetAttr(sync, aHidd_Sync_HDisp, &data->width);
91 OOP_GetAttr(sync, aHidd_Sync_VDisp, &data->height);
92 depth = DefaultDepth(GetSysDisplay(), GetSysScreen());
94 /* Open an X window to be used for viewing */
95 D(bug("[X11OnBm] Framebuffer window size %ldx%ldx%d\n", data->width, data->height, depth));
97 /* Listen for all sorts of events */
98 winattr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask
99 | KeyPressMask | KeyReleaseMask | StructureNotifyMask
100 | SubstructureNotifyMask | FocusChangeMask | ExposureMask;
102 if (XSD(cl)->options & OPTION_BACKINGSTORE)
104 /* Framebuffer needs backing store. (Uses lots of mem) */
105 winattr.backing_store = Always;
106 winattr.save_under = True;
109 winattr.cursor = GetSysCursor();
110 winattr.background_pixel = BlackPixel(GetSysDisplay(), GetSysScreen());
112 rootwin = DefaultRootWindow(GetSysDisplay());
113 D(bug("Creating XWindow: root win=%p\n", rootwin));
115 valuemask = CWCursor | CWEventMask | CWBackPixel;
117 if (XSD(cl)->options & OPTION_BACKINGSTORE)
118 valuemask |= CWBackingStore | CWSaveUnder;
120 if (data->flags & BMDF_COLORMAP_ALLOCED)
122 winattr.colormap = data->colmap;
123 valuemask |= CWColormap;
126 HostLib_Lock();
128 #if ADJUST_XWIN_SIZE
130 XSetWindowAttributes rootattr;
131 unsigned long rootmask = 0;
133 rootattr.event_mask = FocusChangeMask;
134 rootmask |= CWEventMask;
136 if (XSD(cl)->options & OPTION_FULLSCREEN)
138 rootattr.override_redirect = True;
139 rootmask |= CWOverrideRedirect;
142 if (data->flags & BMDF_COLORMAP_ALLOCED)
144 rootattr.colormap = data->colmap;
145 rootmask |= CWColormap;
148 MASTERWIN(data) = XCALL(XCreateWindow, GetSysDisplay(), rootwin,
149 0, /* leftedge */
150 0, /* topedge */
151 data->width,
152 data->height,
153 0, /* BorderWidth */
154 depth,
155 InputOutput,
156 DefaultVisual(GetSysDisplay(), GetSysScreen()),
157 rootmask,
158 &rootattr);
161 if (MASTERWIN(data))
162 #endif
164 WINDRAWABLE(data) = XCALL(XCreateWindow, GetSysDisplay(),
165 ROOTWIN(data),
166 0, /* leftedge */
167 0, /* topedge */
168 data->width,
169 data->height,
170 0, /* BorderWidth */
171 depth,
172 InputOutput,
173 DefaultVisual(GetSysDisplay(), GetSysScreen()),
174 valuemask,
175 &winattr);
177 HostLib_Unlock();
179 D(bug("[X11OnBm] X Window @ 0x%p\n", WINDRAWABLE(data)));
181 if (WINDRAWABLE(data))
183 struct MsgPort *port;
184 Pixmap icon;
185 #if !ADJUST_XWIN_SIZE
186 XSizeHints sizehint;
187 #endif
188 XClassHint *classhint;
190 HostLib_Lock();
192 classhint = XCALL(XAllocClassHint);
193 classhint->res_name = "AROS";
194 classhint->res_class = "AROS";
195 XCALL(XSetClassHint, GetSysDisplay(), MASTERWIN(data), classhint);
197 XCALL(XStoreName, GetSysDisplay(), MASTERWIN(data), "AROS");
198 XCALL(XSetIconName, GetSysDisplay(), MASTERWIN(data), "AROS Screen");
200 #if !ADJUST_XWIN_SIZE
201 sizehint.flags = PMinSize | PMaxSize;
202 sizehint.min_width = data->width;
203 sizehint.min_height = data->height;
204 sizehint.max_width = data->width;
205 sizehint.max_height = data->height;
207 XCALL(XSetWMNormalHints, GetSysDisplay(), MASTERWIN(data), &sizehint);
208 #endif
210 XCALL(XSetWMProtocols,
211 GetSysDisplay(), MASTERWIN(data), &XSD(cl)->delete_win_atom, 1);
213 icon = init_icon(GetSysDisplay(), MASTERWIN(data),
214 DefaultColormap(GetSysDisplay(), GetSysScreen()), depth, xsd);
216 if (icon)
218 XWMHints hints;
220 hints.icon_pixmap = icon;
221 hints.flags = IconPixmapHint;
223 XCALL(XSetWMHints, GetSysDisplay(), MASTERWIN(data), &hints);
226 if (XSD(cl)->options & OPTION_BACKINGSTORE)
228 DRAWABLE(data) = WINDRAWABLE(data);
229 data->flags |= BMDF_BACKINGSTORE;
231 else
233 DRAWABLE(data) = XCALL(XCreatePixmap, data->display, WINDRAWABLE(data), data->width, data->height, depth);
237 * stegerg: XMapRaised is now called inside the X11 task when getting
238 * the NOTY_MAPWINDOW message, otherwise the X11 task can
239 * get a "dead" MapNotify event:
241 * XCreateWindow is called here on the app task context.
242 * If we also call XMapRaised here then the X11 task might
243 * get the MapNotify event before he got the NOTY_WINCREATE
244 * message sent from here (see below). So the X11 task
245 * would not know about our window and therefore ignore
246 * the MapNotify event from X.
248 * This caused the freezes which sometimes happened during
249 * startup when the Workbench screen was opened.
251 * XCALL(XMapRaised, GetSysDisplay(), DRAWABLE(data));
254 HostLib_Unlock();
257 * Now we need to get some message from the X11 task about when
258 * the window has been mapped (ie. MapWindow event).
259 * This is because we cannot render into the window until
260 * it has been mapped.
263 port = CreateMsgPort();
265 if (NULL != port)
267 /* Send a message to the x11 task that the window has been created */
268 struct notify_msg msg;
270 msg.notify_type = NOTY_WINCREATE;
271 msg.xdisplay = GetSysDisplay();
272 msg.xwindow = WINDRAWABLE(data);
273 msg.masterxwindow = MASTERWIN(data);
274 msg.bmobj = o;
275 msg.execmsg.mn_ReplyPort = port;
277 HostLib_Lock();
278 XCALL(XSync, GetSysDisplay(), FALSE);
279 HostLib_Unlock();
281 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
282 X11DoNotify(xsd, &msg);
284 if (!(XSD(cl)->options & OPTION_DELAYXWINMAPPING))
286 D(bug("[X11OnBm] %s: notifying x11 task to map window..\n", __PRETTY_FUNCTION__));
288 * Send a message to the X11 task to ask when the window has been mapped.
289 * We change only notify_type, other fields are already set.
291 msg.notify_type = NOTY_MAPWINDOW;
293 HostLib_Lock();
294 XCALL(XSync, GetSysDisplay(), FALSE);
295 HostLib_Unlock();
297 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
298 X11DoNotify(xsd, &msg);
301 DeleteMsgPort(port);
303 return TRUE;
304 } /* if (port) */
305 } /* if WINDRAWABLE(data) */
307 return FALSE;
310 /****************************************************************************************/
312 VOID X11BM_DisposeFB(struct bitmap_data *data, struct x11_staticdata *xsd)
314 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
316 if (WINDRAWABLE(data))
318 struct MsgPort *port;
319 struct notify_msg msg;
321 port = CreateMsgPort();
323 if (NULL == port)
325 D(bug("[X11OnBm] %s: failed to create notification message port!\n", __PRETTY_FUNCTION__));
327 return;
330 msg.notify_type = NOTY_WINDISPOSE;
331 msg.xdisplay = GetSysDisplay();
332 msg.xwindow = WINDRAWABLE(data);
333 msg.masterxwindow = MASTERWIN(data);
334 msg.execmsg.mn_ReplyPort = port;
336 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
337 X11DoNotify(xsd, &msg);
338 DeleteMsgPort(port);
341 /* Dispose everything */
342 HostLib_Lock();
344 if (WINDRAWABLE(data))
345 XCALL(XDestroyWindow, GetSysDisplay(), WINDRAWABLE(data));
347 #if ADJUST_XWIN_SIZE
348 if (MASTERWIN(data))
349 XCALL(XDestroyWindow, GetSysDisplay(), MASTERWIN(data));
350 #endif
352 if (data->flags & BMDF_COLORMAP_ALLOCED)
353 XCALL(XFreeColormap, GetSysDisplay(), data->colmap);
355 if (!(data->flags & BMDF_BACKINGSTORE))
356 XCALL(XFreePixmap, GetSysDisplay(), DRAWABLE(data));
358 XCALL(XFlush, GetSysDisplay());
360 HostLib_Unlock();
363 /****************************************************************************************/
365 #if ADJUST_XWIN_SIZE
367 BOOL X11BM_SetMode(struct bitmap_data *data, HIDDT_ModeID modeid,
368 struct x11_staticdata *xsd)
370 OOP_Object *sync, *pf;
372 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
374 if (HIDD_Gfx_GetMode(data->gfxhidd, (HIDDT_ModeID) modeid, &sync, &pf))
376 struct MsgPort *port;
377 IPTR new_width, new_height;
379 D(bug("[X11OnBm] %s: got mode info\n", __PRETTY_FUNCTION__));
381 OOP_GetAttr(sync, aHidd_Sync_HDisp, &new_width);
382 OOP_GetAttr(sync, aHidd_Sync_VDisp, &new_height);
385 * Don't do anything if the size actually won't change.
386 * Prevents badly looking flashing, at least on Darwin.
388 if (!(xsd->options & OPTION_DELAYXWINMAPPING) && (new_width == data->width) && (new_height == data->height))
390 D(bug("[X11OnBm] %s: no change ..\n", __PRETTY_FUNCTION__));
391 return TRUE;
394 port = CreateMsgPort();
395 if (port)
397 struct notify_msg nmsg;
399 /* Send resize message to the x11 task */
400 nmsg.notify_type = NOTY_RESIZEWINDOW;
401 nmsg.xdisplay = data->display;
402 nmsg.xwindow = WINDRAWABLE(data);
403 nmsg.masterxwindow = data->masterxwindow;
404 nmsg.width = new_width;
405 nmsg.height = new_height;
406 nmsg.execmsg.mn_ReplyPort = port;
408 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
409 X11DoNotify(xsd, &nmsg);
410 DeleteMsgPort(port);
412 /* Update cached size */
413 data->width = new_width;
414 data->height = new_height;
416 return TRUE;
419 return FALSE;
422 #endif
424 /****************************************************************************************/
426 VOID X11BM_ClearFB(struct bitmap_data *data, HIDDT_Pixel bg)
428 XSetWindowAttributes winattr;
430 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
432 winattr.background_pixel = bg;
434 XCALL(XChangeWindowAttributes, data->display, WINDRAWABLE(data), CWBackPixel, &winattr);
435 XCALL(XClearArea, data->display, DRAWABLE(data), 0, 0, data->width, data->height, FALSE);
436 X11BM_ExposeFB(data, 0, 0, data->width, data->height);
439 /****************************************************************************************/
441 VOID X11BM_ExposeFB(struct bitmap_data *data, WORD x, WORD y, WORD width, WORD height)
443 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
445 if (!(data->flags & BMDF_BACKINGSTORE))
447 XCALL(XSetFunction, data->display, data->gc, GXcopy);
448 XCALL(XCopyArea, data->display, DRAWABLE(data), WINDRAWABLE(data), data->gc,
449 x, y, width, height, x, y);
453 /****************************************************************************************/
455 #if X11SOFTMOUSE
457 //void init_empty_cursor(Window w, GC gc, struct x11_staticdata *xsd)
458 VOID X11BM_InitEmptyCursor(struct bitmap_data *data)
460 Pixmap p, mask;
461 int width, height;
463 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
465 width = height = 1;
467 LOCK_X11
468 p = XCALL(XCreatePixmap, data->display, WINDRAWABLE(data), width, height, 1);
469 UNLOCK_X11
471 if (0 != p)
473 LOCK_X11
474 mask = XCALL(XCreatePixmap, data->display, WINDRAWABLE(data), width, height, 1);
475 XCALL(XFlush, data->display);
476 UNLOCK_X11
478 if (0 != mask)
480 /* Define cursor for window */
481 XColor fg, bg;
482 Cursor c;
483 GC gc;
485 LOCK_X11
486 gc = XCALL(XCreateGC, data->display, WINDRAWABLE(data), 0, 0);
487 XCALL(XSetForeground, data->display, gc, 0);
488 XCALL(XSetFunction, data->display, gc, GXcopy);
489 #if 0
490 XCALL(XFillRectangle, data->display, p, gc, 1, 1, 1, 1);
491 for (y = 0; y < height; y ++)
493 for (x = 0; x < width; x ++)
495 XCALL(XDrawPoint, data->display, mask, gc, x, y);
498 #endif
499 UNLOCK_X11
501 fg.pixel = BlackPixel(data->display, DefaultScreen(data->display));
502 fg.red = 0x0000;
503 fg.green = 0x0000;
504 fg.blue = 0x0000;
505 fg.flags = DoRed | DoGreen | DoBlue;
507 bg.pixel = WhitePixel(data->display, DefaultScreen(data->display));
508 bg.red = 0xFFFF;
509 bg.green = 0xFFFF;
510 bg.blue = 0xFFFF;
511 bg.flags = DoRed | DoGreen | DoBlue;
513 LOCK_X11
514 c = XCALL(XCreatePixmapCursor, data->display, p, mask, &fg, &bg, 0, 0);
515 UNLOCK_X11
517 if (0 != c)
519 LOCK_X11
520 XCALL(XDefineCursor, data->display, WINDRAWABLE(data), c);
521 UNLOCK_X11
524 LOCK_X11
525 XCALL(XFreePixmap, data->display, mask);
526 XCALL(XFreeGC, data->display, gc);
527 UNLOCK_X11
530 LOCK_X11
531 XCALL(XFreePixmap, data->display, p);
532 UNLOCK_X11
537 #endif
539 /****************************************************************************************/
541 static Pixmap init_icon(Display *d, Window w, Colormap cm, LONG depth,
542 struct x11_staticdata *xsd)
544 #include "icon.h"
546 #define SHIFT_PIX(pix, shift) \
547 (( (shift) < 0) ? (pix) >> (-shift) : (pix) << (shift) )
549 Pixmap icon = XCALL(XCreatePixmap, d, w, width, height, depth);
550 char *data = header_data;
551 LONG red_shift, green_shift, blue_shift;
552 GC gc;
554 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
556 red_shift = 24 - xsd->red_shift;
557 green_shift = 24 - xsd->green_shift;
558 blue_shift = 24 - xsd->blue_shift;
560 if (icon)
562 gc = XCALL(XCreateGC, d, icon, 0, 0);
564 if (gc)
566 WORD x, y;
568 for (y = 0; y < height; y++)
570 for (x = 0; x < width; x++)
572 ULONG rgb[3];
573 ULONG pixel = 0;
575 HEADER_PIXEL(data, rgb);
577 if (xsd->vi.class == TrueColor)
579 pixel = (SHIFT_PIX(rgb[0] & 0xFF, red_shift)
580 & xsd->vi.red_mask)
581 | (SHIFT_PIX(rgb[1] & 0xFF, green_shift)
582 & xsd->vi.green_mask)
583 | (SHIFT_PIX(rgb[2] & 0xFF, blue_shift)
584 & xsd->vi.blue_mask);
586 else if (xsd->vi.class == PseudoColor)
588 XColor xcol;
590 xcol.red = (rgb[0] << 8) + rgb[0];
591 xcol.green = (rgb[1] << 8) + rgb[1];
592 xcol.blue = (rgb[2] << 8) + rgb[2];
593 xcol.flags = DoRed | DoGreen | DoBlue;
595 if (XCALL(XAllocColor, d, cm, &xcol))
597 pixel = xcol.pixel;
601 XCALL(XSetForeground, d, gc, pixel);
602 XCALL(XDrawPoint, d, icon, gc, x, y);
606 XCALL(XFreeGC, d, gc);
608 } /* if (gc) */
610 } /* if (icon) */
612 return icon;