wip prep commit in lieu of gfx subsystem update changes.
[AROS.git] / arch / all-hosted / hidd / x11 / x11gfx_onbitmap.c
blobef817d01a0a3d213d0d50dde53ecc885f7374db0
1 /*
2 Copyright © 1995-2017, 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 <hidd/gfx.h>
12 #include <proto/utility.h>
14 #include "x11_types.h"
15 #include "x11.h"
16 #include "x11_hostlib.h"
17 #include "x11gfx_bitmap.h"
19 /****************************************************************************************/
21 #if ADJUST_XWIN_SIZE
22 #define MASTERWIN(data) (data)->masterxwindow
23 #define ROOTWIN(data) (data)->masterxwindow
24 #else
25 #define MASTERWIN WINDRAWABLE
26 #define ROOTWIN(data) rootwin
27 #endif
29 /****************************************************************************************/
31 static Pixmap init_icon(Display *d, Window w, Colormap cm, LONG depth,
32 struct x11_staticdata *xsd);
34 /****************************************************************************************/
36 BOOL X11BM_InitFB(OOP_Class *cl, OOP_Object *o, struct TagItem *attrList)
38 Window rootwin;
39 OOP_Object *sync, *pixfmt;
40 HIDDT_ModeID modeid;
41 IPTR depth;
42 XSetWindowAttributes winattr;
43 int visualclass;
44 unsigned long valuemask;
45 struct bitmap_data *data = OOP_INST_DATA(cl, o);
46 struct x11_staticdata *xsd = XSD(cl);
48 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
50 /* stegerg */
51 visualclass = GetTagData(aHidd_BitMap_X11_VisualClass, TrueColor, attrList);
52 if (visualclass == PseudoColor)
54 Colormap cm;
56 HostLib_Lock();
57 cm = XCALL(XCreateColormap, GetSysDisplay(), RootWindow(GetSysDisplay(), GetSysScreen()),
58 xsd->vi->visual, AllocAll);
59 HostLib_Unlock();
61 if (cm)
63 data->colmap = cm;
64 data->flags |= BMDF_COLORMAP_ALLOCED;
67 /* end stegerg */
70 * Get window size from our ModeID.
71 * We can't support scrolling in framebuffer mode.
73 OOP_GetAttr(o, aHidd_BitMap_ModeID, &modeid);
74 OOP_GetAttr(o, aHidd_BitMap_GfxHidd, (IPTR *) &data->gfxhidd);
75 D(bug("[X11OnBm] ModeID 0x%08X, driver @ 0x%p\n", modeid, data->gfxhidd));
77 HIDD_Gfx_GetMode(data->gfxhidd, modeid, &sync, &pixfmt);
79 OOP_GetAttr(sync, aHidd_Sync_HDisp, &data->width);
80 OOP_GetAttr(sync, aHidd_Sync_VDisp, &data->height);
81 depth = DefaultDepth(GetSysDisplay(), GetSysScreen());
83 /* Open an X window to be used for viewing */
84 D(bug("[X11OnBm] Framebuffer window size %ldx%ldx%d\n", data->width, data->height, depth));
86 /* Listen for all sorts of events */
87 winattr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask
88 | KeyPressMask | KeyReleaseMask | StructureNotifyMask
89 | SubstructureNotifyMask | FocusChangeMask | ExposureMask;
91 if (XSD(cl)->options & OPTION_BACKINGSTORE)
93 /* Framebuffer needs backing store. (Uses lots of mem) */
94 winattr.backing_store = Always;
95 winattr.save_under = True;
98 winattr.cursor = GetSysCursor();
99 winattr.background_pixel = BlackPixel(GetSysDisplay(), GetSysScreen());
101 rootwin = DefaultRootWindow(GetSysDisplay());
102 D(bug("Creating XWindow: root win=%p\n", rootwin));
104 valuemask = CWCursor | CWEventMask | CWBackPixel;
106 if (XSD(cl)->options & OPTION_BACKINGSTORE)
107 valuemask |= CWBackingStore | CWSaveUnder;
109 if (data->flags & BMDF_COLORMAP_ALLOCED)
111 winattr.colormap = data->colmap;
112 valuemask |= CWColormap;
115 HostLib_Lock();
117 #if ADJUST_XWIN_SIZE
119 XSetWindowAttributes rootattr;
120 unsigned long rootmask = 0;
122 rootattr.event_mask = FocusChangeMask;
123 rootmask |= CWEventMask;
125 if (XSD(cl)->options & OPTION_FULLSCREEN)
127 rootattr.override_redirect = True;
128 rootmask |= CWOverrideRedirect;
131 if (data->flags & BMDF_COLORMAP_ALLOCED)
133 rootattr.colormap = data->colmap;
134 rootmask |= CWColormap;
137 MASTERWIN(data) = XCALL(XCreateWindow, GetSysDisplay(), rootwin,
138 0, /* leftedge */
139 0, /* topedge */
140 data->width,
141 data->height,
142 0, /* BorderWidth */
143 depth,
144 InputOutput,
145 DefaultVisual(GetSysDisplay(), GetSysScreen()),
146 rootmask,
147 &rootattr);
150 if (MASTERWIN(data))
151 #endif
153 WINDRAWABLE(data) = XCALL(XCreateWindow, GetSysDisplay(),
154 ROOTWIN(data),
155 0, /* leftedge */
156 0, /* topedge */
157 data->width,
158 data->height,
159 0, /* BorderWidth */
160 depth,
161 InputOutput,
162 DefaultVisual(GetSysDisplay(), GetSysScreen()),
163 valuemask,
164 &winattr);
166 HostLib_Unlock();
168 D(bug("[X11OnBm] X Window @ 0x%p\n", WINDRAWABLE(data)));
170 if (WINDRAWABLE(data))
172 struct MsgPort *port;
173 Pixmap icon;
174 #if !ADJUST_XWIN_SIZE
175 XSizeHints sizehint;
176 #endif
177 XClassHint *classhint;
179 HostLib_Lock();
181 classhint = XCALL(XAllocClassHint);
182 classhint->res_name = "AROS";
183 classhint->res_class = "AROS";
184 XCALL(XSetClassHint, GetSysDisplay(), MASTERWIN(data), classhint);
186 XCALL(XStoreName, GetSysDisplay(), MASTERWIN(data), "AROS");
187 XCALL(XSetIconName, GetSysDisplay(), MASTERWIN(data), "AROS Screen");
189 #if !ADJUST_XWIN_SIZE
190 sizehint.flags = PMinSize | PMaxSize;
191 sizehint.min_width = data->width;
192 sizehint.min_height = data->height;
193 sizehint.max_width = data->width;
194 sizehint.max_height = data->height;
196 XCALL(XSetWMNormalHints, GetSysDisplay(), MASTERWIN(data), &sizehint);
197 #endif
199 XCALL(XSetWMProtocols,
200 GetSysDisplay(), MASTERWIN(data), &XSD(cl)->delete_win_atom, 1);
202 icon = init_icon(GetSysDisplay(), MASTERWIN(data),
203 DefaultColormap(GetSysDisplay(), GetSysScreen()), depth, xsd);
205 if (icon)
207 XWMHints hints;
209 hints.icon_pixmap = icon;
210 hints.flags = IconPixmapHint;
212 XCALL(XSetWMHints, GetSysDisplay(), MASTERWIN(data), &hints);
215 if (XSD(cl)->options & OPTION_BACKINGSTORE)
217 DRAWABLE(data) = WINDRAWABLE(data);
218 data->flags |= BMDF_BACKINGSTORE;
220 else
222 DRAWABLE(data) = XCALL(XCreatePixmap, data->display, WINDRAWABLE(data), data->width, data->height, depth);
226 * stegerg: XMapRaised is now called inside the X11 task when getting
227 * the NOTY_MAPWINDOW message, otherwise the X11 task can
228 * get a "dead" MapNotify event:
230 * XCreateWindow is called here on the app task context.
231 * If we also call XMapRaised here then the X11 task might
232 * get the MapNotify event before he got the NOTY_WINCREATE
233 * message sent from here (see below). So the X11 task
234 * would not know about our window and therefore ignore
235 * the MapNotify event from X.
237 * This caused the freezes which sometimes happened during
238 * startup when the Workbench screen was opened.
240 * XCALL(XMapRaised, GetSysDisplay(), DRAWABLE(data));
243 HostLib_Unlock();
246 * Now we need to get some message from the X11 task about when
247 * the window has been mapped (i.e. MapWindow event).
248 * This is because we cannot render into the window until
249 * it has been mapped.
252 port = CreateMsgPort();
254 if (NULL != port)
256 /* Send a message to the x11 task that the window has been created */
257 struct notify_msg msg;
259 msg.notify_type = NOTY_WINCREATE;
260 msg.xdisplay = GetSysDisplay();
261 msg.xwindow = WINDRAWABLE(data);
262 msg.masterxwindow = MASTERWIN(data);
263 msg.bmobj = o;
264 msg.execmsg.mn_ReplyPort = port;
266 HostLib_Lock();
267 XCALL(XSync, GetSysDisplay(), FALSE);
268 HostLib_Unlock();
270 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
271 X11DoNotify(xsd, &msg);
273 if (!(XSD(cl)->options & OPTION_DELAYXWINMAPPING))
275 D(bug("[X11OnBm] %s: notifying x11 task to map window...\n", __PRETTY_FUNCTION__));
277 * Send a message to the X11 task to ask when the window has been mapped.
278 * We change only notify_type, other fields are already set.
280 msg.notify_type = NOTY_MAPWINDOW;
282 HostLib_Lock();
283 XCALL(XSync, GetSysDisplay(), FALSE);
284 HostLib_Unlock();
286 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
287 X11DoNotify(xsd, &msg);
290 DeleteMsgPort(port);
292 return TRUE;
293 } /* if (port) */
294 } /* if WINDRAWABLE(data) */
296 return FALSE;
299 /****************************************************************************************/
301 VOID X11BM_DisposeFB(struct bitmap_data *data, struct x11_staticdata *xsd)
303 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
305 if (WINDRAWABLE(data))
307 struct MsgPort *port;
308 struct notify_msg msg;
310 port = CreateMsgPort();
312 if (NULL == port)
314 D(bug("[X11OnBm] %s: failed to create notification message port!\n", __PRETTY_FUNCTION__));
316 return;
319 msg.notify_type = NOTY_WINDISPOSE;
320 msg.xdisplay = GetSysDisplay();
321 msg.xwindow = WINDRAWABLE(data);
322 msg.masterxwindow = MASTERWIN(data);
323 msg.execmsg.mn_ReplyPort = port;
325 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
326 X11DoNotify(xsd, &msg);
327 DeleteMsgPort(port);
330 /* Dispose everything */
331 HostLib_Lock();
333 if (WINDRAWABLE(data))
334 XCALL(XDestroyWindow, GetSysDisplay(), WINDRAWABLE(data));
336 #if ADJUST_XWIN_SIZE
337 if (MASTERWIN(data))
338 XCALL(XDestroyWindow, GetSysDisplay(), MASTERWIN(data));
339 #endif
341 if (data->flags & BMDF_COLORMAP_ALLOCED)
342 XCALL(XFreeColormap, GetSysDisplay(), data->colmap);
344 if (!(data->flags & BMDF_BACKINGSTORE))
345 XCALL(XFreePixmap, GetSysDisplay(), DRAWABLE(data));
347 XCALL(XFlush, GetSysDisplay());
349 HostLib_Unlock();
352 /****************************************************************************************/
354 #if ADJUST_XWIN_SIZE
356 BOOL X11BM_SetMode(struct bitmap_data *data, HIDDT_ModeID modeid,
357 struct x11_staticdata *xsd)
359 OOP_Object *sync, *pf;
361 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
363 if (HIDD_Gfx_GetMode(data->gfxhidd, (HIDDT_ModeID) modeid, &sync, &pf))
365 struct MsgPort *port;
366 IPTR new_width, new_height;
368 D(bug("[X11OnBm] %s: got mode info\n", __PRETTY_FUNCTION__));
370 OOP_GetAttr(sync, aHidd_Sync_HDisp, &new_width);
371 OOP_GetAttr(sync, aHidd_Sync_VDisp, &new_height);
374 * Don't do anything if the size actually won't change.
375 * Prevents badly looking flashing, at least on Darwin.
377 if (!(xsd->options & OPTION_DELAYXWINMAPPING) && (new_width == data->width) && (new_height == data->height))
379 D(bug("[X11OnBm] %s: no change ..\n", __PRETTY_FUNCTION__));
380 return TRUE;
383 port = CreateMsgPort();
384 if (port)
386 struct notify_msg nmsg;
388 /* Send resize message to the x11 task */
389 nmsg.notify_type = NOTY_RESIZEWINDOW;
390 nmsg.xdisplay = data->display;
391 nmsg.xwindow = WINDRAWABLE(data);
392 nmsg.masterxwindow = data->masterxwindow;
393 nmsg.width = new_width;
394 nmsg.height = new_height;
395 nmsg.execmsg.mn_ReplyPort = port;
397 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__, xsd->x11task_notify_port));
398 X11DoNotify(xsd, &nmsg);
399 DeleteMsgPort(port);
401 /* Update cached size */
402 data->width = new_width;
403 data->height = new_height;
405 return TRUE;
408 return FALSE;
411 #endif
413 /****************************************************************************************/
415 VOID X11BM_ClearFB(struct bitmap_data *data, HIDDT_Pixel bg)
417 XSetWindowAttributes winattr;
419 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
421 winattr.background_pixel = bg;
423 XCALL(XChangeWindowAttributes, data->display, WINDRAWABLE(data), CWBackPixel, &winattr);
424 XCALL(XClearArea, data->display, DRAWABLE(data), 0, 0, data->width, data->height, FALSE);
425 X11BM_ExposeFB(data, 0, 0, data->width, data->height);
428 /****************************************************************************************/
430 VOID X11BM_ExposeFB(struct bitmap_data *data, WORD x, WORD y, WORD width, WORD height)
432 D(bug("[X11OnBm] %s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
433 x, y, width, height));
435 if (!(data->flags & BMDF_BACKINGSTORE))
437 XCALL(XSetFunction, data->display, data->gc, GXcopy);
438 XCALL(XCopyArea, data->display, DRAWABLE(data), WINDRAWABLE(data), data->gc,
439 x, y, width, height, x, y);
443 /****************************************************************************************/
445 #if X11SOFTMOUSE
447 //void init_empty_cursor(Window w, GC gc, struct x11_staticdata *xsd)
448 VOID X11BM_InitEmptyCursor(struct bitmap_data *data)
450 Pixmap p, mask;
451 int width, height;
453 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
455 width = height = 1;
457 LOCK_X11
458 p = XCALL(XCreatePixmap, data->display, WINDRAWABLE(data), width, height, 1);
459 UNLOCK_X11
461 if (0 != p)
463 LOCK_X11
464 mask = XCALL(XCreatePixmap, data->display, WINDRAWABLE(data), width, height, 1);
465 XCALL(XFlush, data->display);
466 UNLOCK_X11
468 if (0 != mask)
470 /* Define cursor for window */
471 XColor fg, bg;
472 Cursor c;
473 GC gc;
475 LOCK_X11
476 gc = XCALL(XCreateGC, data->display, WINDRAWABLE(data), 0, 0);
477 XCALL(XSetForeground, data->display, gc, 0);
478 XCALL(XSetFunction, data->display, gc, GXcopy);
479 #if 0
480 XCALL(XFillRectangle, data->display, p, gc, 1, 1, 1, 1);
481 for (y = 0; y < height; y ++)
483 for (x = 0; x < width; x ++)
485 XCALL(XDrawPoint, data->display, mask, gc, x, y);
488 #endif
489 UNLOCK_X11
491 fg.pixel = BlackPixel(data->display, DefaultScreen(data->display));
492 fg.red = 0x0000;
493 fg.green = 0x0000;
494 fg.blue = 0x0000;
495 fg.flags = DoRed | DoGreen | DoBlue;
497 bg.pixel = WhitePixel(data->display, DefaultScreen(data->display));
498 bg.red = 0xFFFF;
499 bg.green = 0xFFFF;
500 bg.blue = 0xFFFF;
501 bg.flags = DoRed | DoGreen | DoBlue;
503 LOCK_X11
504 c = XCALL(XCreatePixmapCursor, data->display, p, mask, &fg, &bg, 0, 0);
505 UNLOCK_X11
507 if (0 != c)
509 LOCK_X11
510 XCALL(XDefineCursor, data->display, WINDRAWABLE(data), c);
511 UNLOCK_X11
514 LOCK_X11
515 XCALL(XFreePixmap, data->display, mask);
516 XCALL(XFreeGC, data->display, gc);
517 UNLOCK_X11
520 LOCK_X11
521 XCALL(XFreePixmap, data->display, p);
522 UNLOCK_X11
527 #endif
529 /****************************************************************************************/
531 static Pixmap init_icon(Display *d, Window w, Colormap cm, LONG depth,
532 struct x11_staticdata *xsd)
534 #include "icon.h"
536 #define SHIFT_PIX(pix, shift) \
537 (( (shift) < 0) ? (pix) >> (-shift) : (pix) << (shift) )
539 Pixmap icon = XCALL(XCreatePixmap, d, w, width, height, depth);
540 char *data = header_data;
541 LONG red_shift, green_shift, blue_shift;
542 GC gc;
544 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__));
546 red_shift = 24 - xsd->red_shift;
547 green_shift = 24 - xsd->green_shift;
548 blue_shift = 24 - xsd->blue_shift;
550 if (icon)
552 gc = XCALL(XCreateGC, d, icon, 0, 0);
554 if (gc)
556 WORD x, y;
558 for (y = 0; y < height; y++)
560 for (x = 0; x < width; x++)
562 ULONG rgb[3];
563 ULONG pixel = 0;
565 HEADER_PIXEL(data, rgb);
567 if (xsd->vi->class == TrueColor)
569 pixel = (SHIFT_PIX(rgb[0] & 0xFF, red_shift)
570 & xsd->vi->red_mask)
571 | (SHIFT_PIX(rgb[1] & 0xFF, green_shift)
572 & xsd->vi->green_mask)
573 | (SHIFT_PIX(rgb[2] & 0xFF, blue_shift)
574 & xsd->vi->blue_mask);
576 else if (xsd->vi->class == PseudoColor)
578 XColor xcol;
580 xcol.red = (rgb[0] << 8) + rgb[0];
581 xcol.green = (rgb[1] << 8) + rgb[1];
582 xcol.blue = (rgb[2] << 8) + rgb[2];
583 xcol.flags = DoRed | DoGreen | DoBlue;
585 if (XCALL(XAllocColor, d, cm, &xcol))
587 pixel = xcol.pixel;
591 XCALL(XSetForeground, d, gc, pixel);
592 XCALL(XDrawPoint, d, icon, gc, x, y);
596 XCALL(XFreeGC, d, gc);
598 } /* if (gc) */
600 } /* if (icon) */
602 return icon;