2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
5 Desc: Bitmap class for X11 hidd.
9 #define __OOP_NOATTRBASES__
14 #include <X11/Xutil.h>
15 #include <X11/cursorfont.h>
16 #include <X11/keysym.h>
22 #include <proto/oop.h>
23 #include <proto/utility.h>
25 #include <exec/memory.h>
26 #include <exec/lists.h>
28 #include <graphics/rastport.h>
29 #include <graphics/gfx.h>
32 #include <hidd/graphics.h>
34 #include <aros/symbolsets.h>
37 #include <aros/debug.h>
39 #include LC_LIBDEFS_FILE
41 #include "x11gfx_intern.h"
46 /****************************************************************************************/
48 static OOP_AttrBase HiddBitMapAttrBase
;
49 OOP_AttrBase HiddPixFmtAttrBase
;
50 static OOP_AttrBase HiddX11GfxAB
;
51 static OOP_AttrBase HiddX11BitMapAB
;
53 /****************************************************************************************/
55 static struct OOP_ABDescr attrbases
[] =
57 { IID_Hidd_BitMap
, &HiddBitMapAttrBase
},
58 { IID_Hidd_PixFmt
, &HiddPixFmtAttrBase
},
60 { IID_Hidd_X11Gfx
, &HiddX11GfxAB
},
61 { IID_Hidd_X11BitMap
, &HiddX11BitMapAB
},
65 /****************************************************************************************/
67 /* Macro trick to reuse code between offscreen and onscreen bitmap hidd
70 #define DRAWABLE(data) (data)->drawable.xwindow
73 #define MASTERWIN(data) (data)->masterxwindow
75 #define MASTERWIN(data) DRAWABLE(data)
78 #define MNAME(x) X11OnBM__ ## x
80 /****************************************************************************************/
82 /* !!! Include methods whose implementation is eqaul for windows and pixmaps
83 (except the DRAWABLE) */
85 #include "bitmap_common.c"
88 static void init_empty_cursor(Window w
, GC c
, struct x11_staticdata
*xsd
);
90 static Pixmap
init_icon(Display
*d
, Window w
, Colormap cm
, LONG depth
,
91 struct x11_staticdata
*xsd
);
93 /****************************************************************************************/
95 OOP_Object
*X11OnBM__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
99 EnterFunc(bug("X11Gfx.OnBitMap::New()\n"));
101 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
104 struct bitmap_data
*data
;
106 IPTR width
, height
, depth
;
107 XSetWindowAttributes winattr
;
109 unsigned long valuemask
;
111 data
= OOP_INST_DATA(cl
, o
);
114 memset(data
, 0, sizeof(struct bitmap_data
));
116 /* Get some info passed to us by the x11gfxhidd class */
117 data
->display
= (Display
*)GetTagData(aHidd_X11Gfx_SysDisplay
, 0, msg
->attrList
);
118 data
->screen
= GetTagData(aHidd_X11Gfx_SysScreen
, 0, msg
->attrList
);
119 data
->cursor
= (Cursor
) GetTagData(aHidd_X11Gfx_SysCursor
, 0, msg
->attrList
);
120 data
->colmap
= (Colormap
) GetTagData(aHidd_X11Gfx_ColorMap
, 0, msg
->attrList
);
124 visualclass
= GetTagData(aHidd_X11Gfx_VisualClass
, TrueColor
, msg
->attrList
);
126 if ( visualclass
== PseudoColor
)
131 cm
= XCALL(XCreateColormap
, GetSysDisplay(),
132 RootWindow(GetSysDisplay(), GetSysScreen()),
140 data
->flags
|= BMDF_COLORMAP_ALLOCED
;
146 /* Get attr values */
147 OOP_GetAttr(o
, aHidd_BitMap_Width
, &width
);
148 OOP_GetAttr(o
, aHidd_BitMap_Height
, &height
);
150 /* Open an X window to be used for viewing */
152 D(bug("Displayable bitmap\n"));
154 /* Listen for all sorts of events */
155 winattr
.event_mask
= 0;
156 /* Mouse buttons .. */
157 winattr
.event_mask
|= ButtonPressMask
| ButtonReleaseMask
;
158 /* Mouse movement .. */
159 winattr
.event_mask
|= PointerMotionMask
;
160 /* Key press & release .. */
161 winattr
.event_mask
|= KeyPressMask
| KeyReleaseMask
;
163 /* We must allways have this one */
164 winattr
.event_mask
|= StructureNotifyMask
;
165 winattr
.event_mask
|= SubstructureNotifyMask
;
167 winattr
.event_mask
|= FocusChangeMask
;
169 /* Use backing store for now. (Uses lots of mem) */
170 winattr
.backing_store
= Always
;
174 winattr
.cursor
= GetSysCursor();
175 winattr
.save_under
= True
;
177 winattr
.background_pixel
= BlackPixel(GetSysDisplay(), GetSysScreen());
178 rootwin
= DefaultRootWindow (GetSysDisplay());
179 D(bug("Creating XWindow: root win=%p\n", rootwin
));
180 depth
= DefaultDepth(GetSysDisplay(), GetSysScreen());
182 valuemask
= CWBackingStore
| CWCursor
| CWSaveUnder
|
183 CWEventMask
| CWBackPixel
;
185 if (data
->flags
& BMDF_COLORMAP_ALLOCED
)
187 winattr
.colormap
= data
->colmap
;
188 valuemask
|= CWColormap
;
193 XSetWindowAttributes winattr
;
194 unsigned long valuemask
= 0;
196 if (XSD(cl
)->fullscreen
)
198 winattr
.override_redirect
= True
;
199 valuemask
|= CWOverrideRedirect
;
202 if (data
->flags
& BMDF_COLORMAP_ALLOCED
)
204 winattr
.colormap
= data
->colmap
;
205 valuemask
|= CWColormap
;
208 MASTERWIN(data
) = XCALL(XCreateWindow
, GetSysDisplay(),
217 DefaultVisual(GetSysDisplay(), GetSysScreen()),
225 DRAWABLE(data
) = XCALL(XCreateWindow
, GetSysDisplay(),
238 DefaultVisual (GetSysDisplay(), GetSysScreen()),
243 D(bug("Xwindow : %p\n", DRAWABLE(data
)));
246 if (DRAWABLE(data
) && MASTERWIN(data
))
253 struct MsgPort
*port
;
254 struct notify_msg
*msg
;
259 XCALL(XStoreName
, GetSysDisplay(), MASTERWIN(data
), "AROS");
260 XCALL(XSetIconName
, GetSysDisplay(), MASTERWIN(data
), "AROS Screen");
262 #if !ADJUST_XWIN_SIZE
263 sizehint
.flags
= PMinSize
| PMaxSize
;
264 sizehint
.min_width
= width
;
265 sizehint
.min_height
= height
;
266 sizehint
.max_width
= width
;
267 sizehint
.max_height
= height
;
269 XCALL(XSetWMNormalHints
, GetSysDisplay(), MASTERWIN(data
), &sizehint
);
272 XCALL(XSetWMProtocols
, GetSysDisplay(), MASTERWIN(data
), &XSD(cl
)->delete_win_atom
, 1);
274 icon
= init_icon(GetSysDisplay(),
276 DefaultColormap(GetSysDisplay(), GetSysScreen()),
283 hints
.icon_pixmap
= icon
;
284 hints
.flags
= IconPixmapHint
;
286 XCALL(XSetWMHints
, GetSysDisplay(), MASTERWIN(data
), &hints
);
290 D(bug("Calling XMapRaised\n"));
293 stegerg: XMapRaised is now called inside the X11 task when getting
294 the NOTY_MAPWINDOW message, otherwise the X11 task can
295 get a "dead" MapNotify event:
297 XCreateWindow is called here on the app task context.
298 If we also call XMapRaised here then the X11 task might
299 get the MapNotify event before he got the NOTY_WINCREATE
300 message sent from here (see below). So the X11 task
301 would not know about our window and therefore ignore
302 the MapNotify event from X.
304 This caused the freezes which sometimes happened during
305 startup when the Workbench screen was opened.
307 //XCALL(XMapRaised, GetSysDisplay(), DRAWABLE(data));
312 /* Now we need to get some message from the X11 task about when
313 the window has been mapped (ie. MapWindow event).
314 This is because we cannot render into the window until the
315 it has been mapped.kfind &
320 port
= CreateMsgPort();
321 msg
= AllocMem(sizeof (*msg
), MEMF_PUBLIC
| MEMF_CLEAR
);
323 if (NULL
!= port
&& NULL
!= msg
)
327 /* Send a message to the x11 task that the window has been created */
329 msg
->notify_type
= NOTY_WINCREATE
;
330 msg
->xdisplay
= GetSysDisplay();
331 msg
->xwindow
= DRAWABLE(data
);
332 msg
->masterxwindow
= MASTERWIN(data
);
334 msg
->execmsg
.mn_ReplyPort
= port
;
337 XCALL(XSync
, GetSysDisplay(), FALSE
);
340 PutMsg(XSD(cl
)->x11task_notify_port
, (struct Message
*)msg
);
342 /* Wait for the reply, so we are sure that the x11 task
348 #if !DELAY_XWIN_MAPPING
349 /* Send a message to the X11 task to ask when the window has been mapped */
351 msg
->xdisplay
= GetSysDisplay();
352 msg
->xwindow
= DRAWABLE(data
);
353 msg
->masterxwindow
= MASTERWIN(data
);
354 msg
->notify_type
= NOTY_MAPWINDOW
;
355 msg
->execmsg
.mn_ReplyPort
= port
;
358 XCALL(XSync
, GetSysDisplay(), FALSE
);
361 PutMsg(XSD(cl
)->x11task_notify_port
, (struct Message
*)msg
);
363 /* Wait for result */
367 kprintf("NOTY_MAPWINDOW request returned\n");
370 gcval
.plane_mask
= AllPlanes
;
371 gcval
.graphics_exposures
= False
;
374 data
->gc
= XCALL(XCreateGC
, data
->display
, DRAWABLE(data
),
375 GCPlaneMask
| GCGraphicsExposures
, &gcval
);
383 init_empty_cursor(DRAWABLE(data
), data
->gc
, XSD(cl
));
395 } /* if (msgport created && msg allocated) */
398 FreeMem(msg
, sizeof (*msg
));
408 } /* if (Xwindow created) */
413 OOP_MethodID disp_mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
415 OOP_CoerceMethod(cl
, o
, (OOP_Msg
) &disp_mid
);
421 } /* if (object allocated by superclass) */
423 ReturnPtr("X11Gfx.OnBitMap::New()", OOP_Object
*, o
);
426 /****************************************************************************************/
428 VOID
X11OnBM__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
430 struct bitmap_data
*data
= OOP_INST_DATA(cl
, o
);
432 EnterFunc(bug("X11Gfx.BitMap::Dispose()\n"));
434 /* Someone is trying to dispose the framefuffer. This should really
435 never happen in AROS. */
442 XCALL(XFreeGC
, data
->display
, data
->gc
);
448 struct MsgPort
*port
;
449 struct notify_msg
*msg
;
451 port
= CreateMsgPort();
452 msg
= AllocMem(sizeof (*msg
), MEMF_PUBLIC
| MEMF_CLEAR
);
454 if (NULL
== port
|| NULL
== msg
)
456 kprintf("COULD NOT CREATE PORT OR ALLOCATE MEM IN onbitmap_dispose()\n");
460 msg
->notify_type
= NOTY_WINDISPOSE
;
461 msg
->xdisplay
= GetSysDisplay();
462 msg
->xwindow
= DRAWABLE(data
);
463 msg
->masterxwindow
= MASTERWIN(data
);
464 msg
->execmsg
.mn_ReplyPort
= port
;
466 PutMsg(XSD(cl
)->x11task_notify_port
, (struct Message
*)msg
);
471 FreeMem(msg
, sizeof (*msg
));
475 XCALL(XDestroyWindow
, GetSysDisplay(), DRAWABLE(data
));
476 XCALL(XFlush
, GetSysDisplay() );
484 XCALL(XDestroyWindow
, GetSysDisplay(), MASTERWIN(data
));
485 XCALL(XFlush
, GetSysDisplay() );
490 if (data
->flags
& BMDF_COLORMAP_ALLOCED
)
493 XCALL(XFreeColormap
, GetSysDisplay(), data
->colmap
);
497 OOP_DoSuperMethod(cl
, o
, msg
);
499 ReturnVoid("X11Gfx.BitMap::Dispose");
502 /****************************************************************************************/
504 VOID
X11OnBM__Hidd_BitMap__Clear(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_Clear
*msg
)
506 struct bitmap_data
*data
= OOP_INST_DATA(cl
, o
);
509 XSetWindowAttributes winattr
;
511 /* Get width & height from bitmap */
513 OOP_GetAttr(o
, aHidd_BitMap_Width
, &width
);
514 OOP_GetAttr(o
, aHidd_BitMap_Height
, &height
);
516 winattr
.background_pixel
= GC_BG(msg
->gc
);
519 XCALL(XChangeWindowAttributes
, data
->display
, DRAWABLE(data
),
520 CWBackPixel
, &winattr
);
522 XCALL(XClearArea
, data
->display
, DRAWABLE(data
),
527 XCALL(XFlush
, data
->display
);
531 /****************************************************************************************/
534 #define XSD(cl) (&LIBBASE->xsd)
536 #define NUM_ROOT_METHODS 4
538 #if USE_X11_DRAWFUNCS
539 # define NUM_BITMAP_METHODS 13
541 # define NUM_BITMAP_METHODS 11
544 /****************************************************************************************/
546 static int X11OnBM_Init(LIBBASETYPEPTR LIBBASE
)
548 return OOP_ObtainAttrBases(attrbases
);
551 /****************************************************************************************/
553 static int X11OnBM_Expunge(LIBBASETYPEPTR LIBBASE
)
555 OOP_ReleaseAttrBases(attrbases
);
559 /****************************************************************************************/
561 ADD2INITLIB(X11OnBM_Init
, 0);
562 ADD2EXPUNGELIB(X11OnBM_Expunge
, 0);
566 /****************************************************************************************/
568 static void init_empty_cursor(Window w
, GC gc
, struct x11_staticdata
*xsd
)
576 p
= XCALL(XCreatePixmap
, xsd
->display
, w
, width
, height
, 1);
583 mask
= XCALL(XCreatePixmap
, xsd
->display
589 XCALL(XFlush
, xsd
->display
);
594 /* Define cursor for window */
600 XCALL(XSetForeground
, xsd
->display
, gc
, 0);
601 XCALL(XSetFunction
, xsd
->display
, gc
, GXcopy
);
603 XCALL(XFillRectangle
, xsd
->display
, p
, gc
, 1, 1, 1, 1);
604 for (y
= 0; y
< height
; y
++)
606 for (x
= 0; x
< width
; x
++)
608 XCALL(XDrawPoint
, xsd
->display
, mask
, gc
, x
, y
);
614 fg
.pixel
= BlackPixel(xsd
->display
, DefaultScreen(xsd
->display
));
618 fg
.flags
= DoRed
| DoGreen
| DoBlue
;
620 bg
.pixel
= WhitePixel(xsd
->display
, DefaultScreen(xsd
->display
));
624 bg
.flags
= DoRed
| DoGreen
| DoBlue
;
627 c
= XCALL(XCreatePixmapCursor
, xsd
->display
, p
, mask
, &fg
, &bg
, 0, 0);
633 XCALL(XDefineCursor
, xsd
->display
, w
, c
);
638 XCALL(XFreePixmap
, xsd
->display
, mask
);
643 XCALL(XFreePixmap
, xsd
->display
, p
);
649 /****************************************************************************************/
653 /****************************************************************************************/
655 static Pixmap
init_icon(Display
*d
, Window w
, Colormap cm
, LONG depth
, struct x11_staticdata
*xsd
)
659 #define SHIFT_PIX(pix, shift) \
660 (( (shift) < 0) ? (pix) >> (-shift) : (pix) << (shift) )
662 Pixmap icon
= XCALL(XCreatePixmap
, d
, w
, width
, height
, depth
);
663 char *data
= header_data
;
664 LONG red_shift
, green_shift
, blue_shift
;
667 red_shift
= 24 - xsd
->red_shift
;
668 green_shift
= 24 - xsd
->green_shift
;
669 blue_shift
= 24 - xsd
->blue_shift
;
673 gc
= XCALL(XCreateGC
, d
, icon
, 0, 0);
679 for(y
= 0; y
< height
; y
++)
681 for(x
= 0; x
< width
; x
++)
686 HEADER_PIXEL(data
,rgb
);
688 if (xsd
->vi
.class == TrueColor
)
690 pixel
= (SHIFT_PIX(rgb
[0] & 0xFF, red_shift
) & xsd
->vi
.red_mask
) |
691 (SHIFT_PIX(rgb
[1] & 0xFF, green_shift
) & xsd
->vi
.green_mask
) |
692 (SHIFT_PIX(rgb
[2] & 0xFF, blue_shift
) & xsd
->vi
.blue_mask
);
694 else if (xsd
->vi
.class == PseudoColor
)
698 xcol
.red
= (rgb
[0] << 8) + rgb
[0];
699 xcol
.green
= (rgb
[1] << 8) + rgb
[1];
700 xcol
.blue
= (rgb
[2] << 8) + rgb
[2];
701 xcol
.flags
= DoRed
| DoGreen
| DoBlue
;
703 if (XCALL(XAllocColor
, d
, cm
, &xcol
))
709 XCALL(XSetForeground
, d
, gc
, pixel
);
710 XCALL(XDrawPoint
, d
, icon
, gc
, x
, y
);
714 XCALL(XFreeGC
, d
, gc
);
723 /****************************************************************************************/