2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Bitmap class for X11 hidd.
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>
21 #include <hidd/graphics.h>
23 #include <proto/oop.h>
24 #include <proto/utility.h>
28 #include "x11gfx_intern.h"
30 /****************************************************************************************/
33 #define MASTERWIN(data) (data)->masterxwindow
34 #define ROOTWIN(data) (data)->masterxwindow
36 #define MASTERWIN WINDRAWABLE
37 #define ROOTWIN(data) rootwin
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
)
50 OOP_Object
*sync
, *pixfmt
;
53 XSetWindowAttributes winattr
;
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__
));
62 visualclass
= GetTagData(aHidd_X11BitMap_VisualClass
, TrueColor
, attrList
);
63 if (visualclass
== PseudoColor
)
68 cm
= XCALL(XCreateColormap
, GetSysDisplay(), RootWindow(GetSysDisplay(), GetSysScreen()),
69 xsd
->vi
.visual
, AllocAll
);
75 data
->flags
|= BMDF_COLORMAP_ALLOCED
;
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
;
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
,
156 DefaultVisual(GetSysDisplay(), GetSysScreen()),
164 WINDRAWABLE(data
) = XCALL(XCreateWindow
, GetSysDisplay(),
173 DefaultVisual(GetSysDisplay(), GetSysScreen()),
179 D(bug("[X11OnBm] X Window @ 0x%p\n", WINDRAWABLE(data
)));
181 if (WINDRAWABLE(data
))
183 struct MsgPort
*port
;
185 #if !ADJUST_XWIN_SIZE
188 XClassHint
*classhint
;
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
);
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
);
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
;
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));
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();
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
);
275 msg
.execmsg
.mn_ReplyPort
= port
;
278 XCALL(XSync
, GetSysDisplay(), FALSE
);
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
;
294 XCALL(XSync
, GetSysDisplay(), FALSE
);
297 D(bug("[X11] %s: notifying port @ 0x%p\n", __PRETTY_FUNCTION__
, xsd
->x11task_notify_port
));
298 X11DoNotify(xsd
, &msg
);
305 } /* if WINDRAWABLE(data) */
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();
325 D(bug("[X11OnBm] %s: failed to create notification message port!\n", __PRETTY_FUNCTION__
));
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
);
341 /* Dispose everything */
344 if (WINDRAWABLE(data
))
345 XCALL(XDestroyWindow
, GetSysDisplay(), WINDRAWABLE(data
));
349 XCALL(XDestroyWindow
, GetSysDisplay(), MASTERWIN(data
));
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());
363 /****************************************************************************************/
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__
));
394 port
= CreateMsgPort();
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
);
412 /* Update cached size */
413 data
->width
= new_width
;
414 data
->height
= new_height
;
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 /****************************************************************************************/
457 //void init_empty_cursor(Window w, GC gc, struct x11_staticdata *xsd)
458 VOID
X11BM_InitEmptyCursor(struct bitmap_data
*data
)
463 D(bug("[X11OnBm] %s()\n", __PRETTY_FUNCTION__
));
468 p
= XCALL(XCreatePixmap
, data
->display
, WINDRAWABLE(data
), width
, height
, 1);
474 mask
= XCALL(XCreatePixmap
, data
->display
, WINDRAWABLE(data
), width
, height
, 1);
475 XCALL(XFlush
, data
->display
);
480 /* Define cursor for window */
486 gc
= XCALL(XCreateGC
, data
->display
, WINDRAWABLE(data
), 0, 0);
487 XCALL(XSetForeground
, data
->display
, gc
, 0);
488 XCALL(XSetFunction
, data
->display
, gc
, GXcopy
);
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
);
501 fg
.pixel
= BlackPixel(data
->display
, DefaultScreen(data
->display
));
505 fg
.flags
= DoRed
| DoGreen
| DoBlue
;
507 bg
.pixel
= WhitePixel(data
->display
, DefaultScreen(data
->display
));
511 bg
.flags
= DoRed
| DoGreen
| DoBlue
;
514 c
= XCALL(XCreatePixmapCursor
, data
->display
, p
, mask
, &fg
, &bg
, 0, 0);
520 XCALL(XDefineCursor
, data
->display
, WINDRAWABLE(data
), c
);
525 XCALL(XFreePixmap
, data
->display
, mask
);
526 XCALL(XFreeGC
, data
->display
, gc
);
531 XCALL(XFreePixmap
, data
->display
, p
);
539 /****************************************************************************************/
541 static Pixmap
init_icon(Display
*d
, Window w
, Colormap cm
, LONG depth
,
542 struct x11_staticdata
*xsd
)
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
;
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
;
562 gc
= XCALL(XCreateGC
, d
, icon
, 0, 0);
568 for (y
= 0; y
< height
; y
++)
570 for (x
= 0; x
< width
; x
++)
575 HEADER_PIXEL(data
, rgb
);
577 if (xsd
->vi
.class == TrueColor
)
579 pixel
= (SHIFT_PIX(rgb
[0] & 0xFF, red_shift
)
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
)
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
))
601 XCALL(XSetForeground
, d
, gc
, pixel
);
602 XCALL(XDrawPoint
, d
, icon
, gc
, x
, y
);
606 XCALL(XFreeGC
, d
, gc
);