2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Desc: Bitmap class for X11 hidd.
12 #include <proto/utility.h>
14 #include "x11_types.h"
16 #include "x11_hostlib.h"
17 #include "x11gfx_bitmap.h"
19 /****************************************************************************************/
22 #define MASTERWIN(data) (data)->masterxwindow
23 #define ROOTWIN(data) (data)->masterxwindow
25 #define MASTERWIN WINDRAWABLE
26 #define ROOTWIN(data) rootwin
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
)
39 OOP_Object
*sync
, *pixfmt
;
42 XSetWindowAttributes winattr
;
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__
));
51 visualclass
= GetTagData(aHidd_BitMap_X11_VisualClass
, TrueColor
, attrList
);
52 if (visualclass
== PseudoColor
)
57 cm
= XCALL(XCreateColormap
, GetSysDisplay(), RootWindow(GetSysDisplay(), GetSysScreen()),
58 xsd
->vi
->visual
, AllocAll
);
64 data
->flags
|= BMDF_COLORMAP_ALLOCED
;
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
;
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
,
145 DefaultVisual(GetSysDisplay(), GetSysScreen()),
153 WINDRAWABLE(data
) = XCALL(XCreateWindow
, GetSysDisplay(),
162 DefaultVisual(GetSysDisplay(), GetSysScreen()),
168 D(bug("[X11OnBm] X Window @ 0x%p\n", WINDRAWABLE(data
)));
170 if (WINDRAWABLE(data
))
173 #if !ADJUST_XWIN_SIZE
176 XClassHint
*classhint
;
180 classhint
= XCALL(XAllocClassHint
);
181 classhint
->res_name
= "AROS";
182 classhint
->res_class
= "AROS";
183 XCALL(XSetClassHint
, GetSysDisplay(), MASTERWIN(data
), classhint
);
185 XCALL(XStoreName
, GetSysDisplay(), MASTERWIN(data
), "AROS");
186 XCALL(XSetIconName
, GetSysDisplay(), MASTERWIN(data
), "AROS Screen");
188 #if !ADJUST_XWIN_SIZE
189 sizehint
.flags
= PMinSize
| PMaxSize
;
190 sizehint
.min_width
= data
->width
;
191 sizehint
.min_height
= data
->height
;
192 sizehint
.max_width
= data
->width
;
193 sizehint
.max_height
= data
->height
;
195 XCALL(XSetWMNormalHints
, GetSysDisplay(), MASTERWIN(data
), &sizehint
);
198 XCALL(XSetWMProtocols
,
199 GetSysDisplay(), MASTERWIN(data
), &XSD(cl
)->delete_win_atom
, 1);
201 icon
= init_icon(GetSysDisplay(), MASTERWIN(data
),
202 DefaultColormap(GetSysDisplay(), GetSysScreen()), depth
, xsd
);
208 hints
.icon_pixmap
= icon
;
209 hints
.flags
= IconPixmapHint
;
211 XCALL(XSetWMHints
, GetSysDisplay(), MASTERWIN(data
), &hints
);
214 if (XSD(cl
)->options
& OPTION_BACKINGSTORE
)
216 DRAWABLE(data
) = WINDRAWABLE(data
);
217 data
->flags
|= BMDF_BACKINGSTORE
;
221 DRAWABLE(data
) = XCALL(XCreatePixmap
, data
->display
, WINDRAWABLE(data
), data
->width
, data
->height
, depth
);
225 * stegerg: XMapRaised is now called inside the X11 task when getting
226 * the NOTY_MAPWINDOW message, otherwise the X11 task can
227 * get a "dead" MapNotify event:
229 * XCreateWindow is called here on the app task context.
230 * If we also call XMapRaised here then the X11 task might
231 * get the MapNotify event before he got the NOTY_WINCREATE
232 * message sent from here (see below). So the X11 task
233 * would not know about our window and therefore ignore
234 * the MapNotify event from X.
236 * This caused the freezes which sometimes happened during
237 * startup when the Workbench screen was opened.
239 * XCALL(XMapRaised, GetSysDisplay(), DRAWABLE(data));
245 } /* if WINDRAWABLE(data) */
250 /****************************************************************************************/
252 BOOL
X11BM_NotifyFB(OOP_Class
*cl
, OOP_Object
*o
)
254 struct bitmap_data
*data
= OOP_INST_DATA(cl
, o
);
255 struct x11_staticdata
*xsd
= XSD(cl
);
256 struct MsgPort
*port
;
258 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
261 * Now we need to get some message from the X11 task about when
262 * the window has been mapped (i.e. MapWindow event).
263 * This is because we cannot render into the window until
264 * it has been mapped.
267 port
= CreateMsgPort();
271 /* Send a message to the x11 task that the window has been created */
272 struct notify_msg msg
;
274 msg
.notify_type
= NOTY_WINCREATE
;
275 msg
.xdisplay
= GetSysDisplay();
276 msg
.xwindow
= WINDRAWABLE(data
);
277 msg
.masterxwindow
= MASTERWIN(data
);
279 msg
.execmsg
.mn_ReplyPort
= port
;
282 XCALL(XSync
, GetSysDisplay(), FALSE
);
285 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__
,
286 xsd
->x11task_notify_port
));
287 X11DoNotify(xsd
, &msg
);
289 if (!(XSD(cl
)->options
& OPTION_DELAYXWINMAPPING
))
291 D(bug("[X11OnBm] %s: notifying x11 task to map window...\n",
292 __PRETTY_FUNCTION__
));
294 * Send a message to the X11 task to ask when the window has
295 * been mapped. We change only notify_type; other fields are
298 msg
.notify_type
= NOTY_MAPWINDOW
;
301 XCALL(XSync
, GetSysDisplay(), FALSE
);
304 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__
,
305 xsd
->x11task_notify_port
));
306 X11DoNotify(xsd
, &msg
);
317 /****************************************************************************************/
319 VOID
X11BM_DisposeFB(struct bitmap_data
*data
, struct x11_staticdata
*xsd
)
321 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
323 if (WINDRAWABLE(data
))
325 struct MsgPort
*port
;
326 struct notify_msg msg
;
328 port
= CreateMsgPort();
332 D(bug("[X11OnBm] %s: failed to create notification message port!\n", __PRETTY_FUNCTION__
));
337 msg
.notify_type
= NOTY_WINDISPOSE
;
338 msg
.xdisplay
= GetSysDisplay();
339 msg
.xwindow
= WINDRAWABLE(data
);
340 msg
.masterxwindow
= MASTERWIN(data
);
341 msg
.execmsg
.mn_ReplyPort
= port
;
343 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__
, xsd
->x11task_notify_port
));
344 X11DoNotify(xsd
, &msg
);
348 /* Dispose everything */
351 if (WINDRAWABLE(data
))
352 XCALL(XDestroyWindow
, GetSysDisplay(), WINDRAWABLE(data
));
356 XCALL(XDestroyWindow
, GetSysDisplay(), MASTERWIN(data
));
359 if (data
->flags
& BMDF_COLORMAP_ALLOCED
)
360 XCALL(XFreeColormap
, GetSysDisplay(), data
->colmap
);
362 if (!(data
->flags
& BMDF_BACKINGSTORE
))
363 XCALL(XFreePixmap
, GetSysDisplay(), DRAWABLE(data
));
365 XCALL(XFlush
, GetSysDisplay());
370 /****************************************************************************************/
374 BOOL
X11BM_SetMode(struct bitmap_data
*data
, HIDDT_ModeID modeid
,
375 struct x11_staticdata
*xsd
)
377 OOP_Object
*sync
, *pf
;
379 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
381 if (HIDD_Gfx_GetMode(data
->gfxhidd
, (HIDDT_ModeID
) modeid
, &sync
, &pf
))
383 struct MsgPort
*port
;
384 IPTR new_width
, new_height
;
386 D(bug("[X11OnBm] %s: got mode info\n", __PRETTY_FUNCTION__
));
388 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &new_width
);
389 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &new_height
);
392 * Don't do anything if the size actually won't change.
393 * Prevents badly looking flashing, at least on Darwin.
395 if (!(xsd
->options
& OPTION_DELAYXWINMAPPING
) && (new_width
== data
->width
) && (new_height
== data
->height
))
397 D(bug("[X11OnBm] %s: no change ..\n", __PRETTY_FUNCTION__
));
401 port
= CreateMsgPort();
404 struct notify_msg nmsg
;
406 /* Send resize message to the x11 task */
407 nmsg
.notify_type
= NOTY_RESIZEWINDOW
;
408 nmsg
.xdisplay
= data
->display
;
409 nmsg
.xwindow
= WINDRAWABLE(data
);
410 nmsg
.masterxwindow
= data
->masterxwindow
;
411 nmsg
.width
= new_width
;
412 nmsg
.height
= new_height
;
413 nmsg
.execmsg
.mn_ReplyPort
= port
;
415 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__
, xsd
->x11task_notify_port
));
416 X11DoNotify(xsd
, &nmsg
);
419 /* Update cached size */
420 data
->width
= new_width
;
421 data
->height
= new_height
;
431 /****************************************************************************************/
433 VOID
X11BM_ClearFB(struct bitmap_data
*data
, HIDDT_Pixel bg
)
435 XSetWindowAttributes winattr
;
437 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
439 winattr
.background_pixel
= bg
;
441 XCALL(XChangeWindowAttributes
, data
->display
, WINDRAWABLE(data
), CWBackPixel
, &winattr
);
442 XCALL(XClearArea
, data
->display
, DRAWABLE(data
), 0, 0, data
->width
, data
->height
, FALSE
);
443 X11BM_ExposeFB(data
, 0, 0, data
->width
, data
->height
);
446 /****************************************************************************************/
448 VOID
X11BM_ExposeFB(struct bitmap_data
*data
, WORD x
, WORD y
, WORD width
, WORD height
)
450 D(bug("[X11OnBm] %s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__
,
451 x
, y
, width
, height
));
453 if (!(data
->flags
& BMDF_BACKINGSTORE
))
455 XCALL(XSetFunction
, data
->display
, data
->gc
, GXcopy
);
456 XCALL(XCopyArea
, data
->display
, DRAWABLE(data
), WINDRAWABLE(data
), data
->gc
,
457 x
, y
, width
, height
, x
, y
);
461 /****************************************************************************************/
465 //void init_empty_cursor(Window w, GC gc, struct x11_staticdata *xsd)
466 VOID
X11BM_InitEmptyCursor(struct bitmap_data
*data
)
471 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
476 p
= XCALL(XCreatePixmap
, data
->display
, WINDRAWABLE(data
), width
, height
, 1);
482 mask
= XCALL(XCreatePixmap
, data
->display
, WINDRAWABLE(data
), width
, height
, 1);
483 XCALL(XFlush
, data
->display
);
488 /* Define cursor for window */
494 gc
= XCALL(XCreateGC
, data
->display
, WINDRAWABLE(data
), 0, 0);
495 XCALL(XSetForeground
, data
->display
, gc
, 0);
496 XCALL(XSetFunction
, data
->display
, gc
, GXcopy
);
498 XCALL(XFillRectangle
, data
->display
, p
, gc
, 1, 1, 1, 1);
499 for (y
= 0; y
< height
; y
++)
501 for (x
= 0; x
< width
; x
++)
503 XCALL(XDrawPoint
, data
->display
, mask
, gc
, x
, y
);
509 fg
.pixel
= BlackPixel(data
->display
, DefaultScreen(data
->display
));
513 fg
.flags
= DoRed
| DoGreen
| DoBlue
;
515 bg
.pixel
= WhitePixel(data
->display
, DefaultScreen(data
->display
));
519 bg
.flags
= DoRed
| DoGreen
| DoBlue
;
522 c
= XCALL(XCreatePixmapCursor
, data
->display
, p
, mask
, &fg
, &bg
, 0, 0);
528 XCALL(XDefineCursor
, data
->display
, WINDRAWABLE(data
), c
);
533 XCALL(XFreePixmap
, data
->display
, mask
);
534 XCALL(XFreeGC
, data
->display
, gc
);
539 XCALL(XFreePixmap
, data
->display
, p
);
547 /****************************************************************************************/
549 static Pixmap
init_icon(Display
*d
, Window w
, Colormap cm
, LONG depth
,
550 struct x11_staticdata
*xsd
)
554 #define SHIFT_PIX(pix, shift) \
555 (( (shift) < 0) ? (pix) >> (-shift) : (pix) << (shift) )
557 Pixmap icon
= XCALL(XCreatePixmap
, d
, w
, width
, height
, depth
);
558 char *data
= header_data
;
559 LONG red_shift
, green_shift
, blue_shift
;
562 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
564 red_shift
= 24 - xsd
->red_shift
;
565 green_shift
= 24 - xsd
->green_shift
;
566 blue_shift
= 24 - xsd
->blue_shift
;
570 gc
= XCALL(XCreateGC
, d
, icon
, 0, 0);
576 for (y
= 0; y
< height
; y
++)
578 for (x
= 0; x
< width
; x
++)
583 HEADER_PIXEL(data
, rgb
);
585 if (xsd
->vi
->class == TrueColor
)
587 pixel
= (SHIFT_PIX(rgb
[0] & 0xFF, red_shift
)
589 | (SHIFT_PIX(rgb
[1] & 0xFF, green_shift
)
590 & xsd
->vi
->green_mask
)
591 | (SHIFT_PIX(rgb
[2] & 0xFF, blue_shift
)
592 & xsd
->vi
->blue_mask
);
594 else if (xsd
->vi
->class == PseudoColor
)
598 xcol
.red
= (rgb
[0] << 8) + rgb
[0];
599 xcol
.green
= (rgb
[1] << 8) + rgb
[1];
600 xcol
.blue
= (rgb
[2] << 8) + rgb
[2];
601 xcol
.flags
= DoRed
| DoGreen
| DoBlue
;
603 if (XCALL(XAllocColor
, d
, cm
, &xcol
))
609 XCALL(XSetForeground
, d
, gc
, pixel
);
610 XCALL(XDrawPoint
, d
, icon
, gc
, x
, y
);
614 XCALL(XFreeGC
, d
, gc
);