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
))
172 struct MsgPort
*port
;
174 #if !ADJUST_XWIN_SIZE
177 XClassHint
*classhint
;
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
);
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
);
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
;
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));
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();
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
);
264 msg
.execmsg
.mn_ReplyPort
= port
;
267 XCALL(XSync
, GetSysDisplay(), FALSE
);
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
;
283 XCALL(XSync
, GetSysDisplay(), FALSE
);
286 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__
, xsd
->x11task_notify_port
));
287 X11DoNotify(xsd
, &msg
);
294 } /* if WINDRAWABLE(data) */
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();
314 D(bug("[X11OnBm] %s: failed to create notification message port!\n", __PRETTY_FUNCTION__
));
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
);
330 /* Dispose everything */
333 if (WINDRAWABLE(data
))
334 XCALL(XDestroyWindow
, GetSysDisplay(), WINDRAWABLE(data
));
338 XCALL(XDestroyWindow
, GetSysDisplay(), MASTERWIN(data
));
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());
352 /****************************************************************************************/
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__
));
383 port
= CreateMsgPort();
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
);
401 /* Update cached size */
402 data
->width
= new_width
;
403 data
->height
= new_height
;
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 /****************************************************************************************/
447 //void init_empty_cursor(Window w, GC gc, struct x11_staticdata *xsd)
448 VOID
X11BM_InitEmptyCursor(struct bitmap_data
*data
)
453 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
458 p
= XCALL(XCreatePixmap
, data
->display
, WINDRAWABLE(data
), width
, height
, 1);
464 mask
= XCALL(XCreatePixmap
, data
->display
, WINDRAWABLE(data
), width
, height
, 1);
465 XCALL(XFlush
, data
->display
);
470 /* Define cursor for window */
476 gc
= XCALL(XCreateGC
, data
->display
, WINDRAWABLE(data
), 0, 0);
477 XCALL(XSetForeground
, data
->display
, gc
, 0);
478 XCALL(XSetFunction
, data
->display
, gc
, GXcopy
);
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
);
491 fg
.pixel
= BlackPixel(data
->display
, DefaultScreen(data
->display
));
495 fg
.flags
= DoRed
| DoGreen
| DoBlue
;
497 bg
.pixel
= WhitePixel(data
->display
, DefaultScreen(data
->display
));
501 bg
.flags
= DoRed
| DoGreen
| DoBlue
;
504 c
= XCALL(XCreatePixmapCursor
, data
->display
, p
, mask
, &fg
, &bg
, 0, 0);
510 XCALL(XDefineCursor
, data
->display
, WINDRAWABLE(data
), c
);
515 XCALL(XFreePixmap
, data
->display
, mask
);
516 XCALL(XFreeGC
, data
->display
, gc
);
521 XCALL(XFreePixmap
, data
->display
, p
);
529 /****************************************************************************************/
531 static Pixmap
init_icon(Display
*d
, Window w
, Colormap cm
, LONG depth
,
532 struct x11_staticdata
*xsd
)
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
;
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
;
552 gc
= XCALL(XCreateGC
, d
, icon
, 0, 0);
558 for (y
= 0; y
< height
; y
++)
560 for (x
= 0; x
< width
; x
++)
565 HEADER_PIXEL(data
, rgb
);
567 if (xsd
->vi
->class == TrueColor
)
569 pixel
= (SHIFT_PIX(rgb
[0] & 0xFF, red_shift
)
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
)
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
))
591 XCALL(XSetForeground
, d
, gc
, pixel
);
592 XCALL(XDrawPoint
, d
, icon
, gc
, x
, y
);
596 XCALL(XFreeGC
, d
, gc
);