Added missing properties.
[tangerine.git] / arch / all-x11 / hidd / onbitmap.c
blobabd6bbb23a8d25b852792ba44b817340781984a3
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Bitmap class for X11 hidd.
6 Lang: English.
7 */
9 #define __OOP_NOATTRBASES__
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <X11/Xlib.h>
14 #include <X11/Xutil.h>
15 #include <X11/cursorfont.h>
16 #include <X11/keysym.h>
18 #include <string.h>
19 #include <signal.h>
20 #include <unistd.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>
30 #include <oop/oop.h>
32 #include <hidd/graphics.h>
34 #include <aros/symbolsets.h>
36 #define DEBUG 0
37 #include <aros/debug.h>
39 #include LC_LIBDEFS_FILE
41 #include "x11gfx_intern.h"
42 #include "x11.h"
44 #include "bitmap.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 },
59 /* Private bases */
60 { IID_Hidd_X11Gfx , &HiddX11GfxAB },
61 { IID_Hidd_X11BitMap, &HiddX11BitMapAB },
62 { NULL , NULL }
65 /****************************************************************************************/
67 /* Macro trick to reuse code between offscreen and onscreen bitmap hidd
68 (bitmap_common.c) */
70 #define DRAWABLE(data) (data)->drawable.xwindow
72 #if ADJUST_XWIN_SIZE
73 #define MASTERWIN(data) (data)->masterxwindow
74 #else
75 #define MASTERWIN(data) DRAWABLE(data)
76 #endif
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"
87 #if X11SOFTMOUSE
88 static void init_empty_cursor(Window w, GC c, struct x11_staticdata *xsd);
89 #endif
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)
97 BOOL ok = TRUE;
99 EnterFunc(bug("X11Gfx.OnBitMap::New()\n"));
101 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
102 if (o)
104 struct bitmap_data *data;
105 Window rootwin;
106 IPTR width, height, depth;
107 XSetWindowAttributes winattr;
108 int visualclass;
109 unsigned long valuemask;
111 data = OOP_INST_DATA(cl, o);
113 /* clear all data */
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);
122 /* stegerg*/
124 visualclass = GetTagData(aHidd_X11Gfx_VisualClass, TrueColor, msg->attrList);
126 if ( visualclass == PseudoColor)
128 Colormap cm;
130 LOCK_X11
131 cm = XCALL(XCreateColormap, GetSysDisplay(),
132 RootWindow(GetSysDisplay(), GetSysScreen()),
133 XSD(cl)->vi.visual,
134 AllocAll);
135 UNLOCK_X11
137 if (cm)
139 data->colmap = cm;
140 data->flags |= BMDF_COLORMAP_ALLOCED;
144 /* end stegerg */
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;
172 LOCK_X11
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;
191 #if ADJUST_XWIN_SIZE
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(),
209 rootwin,
210 0, /* leftedge */
211 0, /* topedge */
212 width,
213 height,
214 0, /* BorderWidth */
215 depth,
216 InputOutput,
217 DefaultVisual(GetSysDisplay(), GetSysScreen()),
218 valuemask,
219 &winattr);
222 if (MASTERWIN(data))
223 #endif
225 DRAWABLE(data) = XCALL(XCreateWindow, GetSysDisplay(),
226 #if ADJUST_XWIN_SIZE
227 MASTERWIN(data),
228 #else
229 rootwin,
230 #endif
231 0, /* leftedge */
232 0, /* topedge */
233 width,
234 height,
235 0, /* BorderWidth */
236 depth,
237 InputOutput,
238 DefaultVisual (GetSysDisplay(), GetSysScreen()),
239 valuemask,
240 &winattr);
241 UNLOCK_X11
243 D(bug("Xwindow : %p\n", DRAWABLE(data)));
245 #if ADJUST_XWIN_SIZE
246 if (DRAWABLE(data) && MASTERWIN(data))
248 #else
249 if (DRAWABLE(data))
251 XSizeHints sizehint;
252 #endif
253 struct MsgPort *port;
254 struct notify_msg *msg;
255 Pixmap icon;
257 LOCK_X11
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);
270 #endif
272 XCALL(XSetWMProtocols, GetSysDisplay(), MASTERWIN(data), &XSD(cl)->delete_win_atom, 1);
274 icon = init_icon(GetSysDisplay(),
275 MASTERWIN(data),
276 DefaultColormap(GetSysDisplay(), GetSysScreen()),
277 depth,
278 XSD(cl));
279 if (icon)
281 XWMHints hints;
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));
310 UNLOCK_X11
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 &
318 /* Create X11 GC */
320 port = CreateMsgPort();
321 msg = AllocMem(sizeof (*msg), MEMF_PUBLIC | MEMF_CLEAR);
323 if (NULL != port && NULL != msg)
325 XGCValues gcval;
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);
333 msg->bmobj = o;
334 msg->execmsg.mn_ReplyPort = port;
336 LOCK_X11
337 XCALL(XSync, GetSysDisplay(), FALSE);
338 UNLOCK_X11
340 PutMsg(XSD(cl)->x11task_notify_port, (struct Message *)msg);
342 /* Wait for the reply, so we are sure that the x11 task
343 has got it */
345 WaitPort(port);
346 GetMsg(port);
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;
357 LOCK_X11
358 XCALL(XSync, GetSysDisplay(), FALSE);
359 UNLOCK_X11
361 PutMsg(XSD(cl)->x11task_notify_port, (struct Message *)msg);
363 /* Wait for result */
364 WaitPort(port);
365 GetMsg(port);
367 kprintf("NOTY_MAPWINDOW request returned\n");
368 #endif
370 gcval.plane_mask = AllPlanes;
371 gcval.graphics_exposures = False;
373 LOCK_X11
374 data->gc = XCALL(XCreateGC, data->display, DRAWABLE(data),
375 GCPlaneMask | GCGraphicsExposures, &gcval);
376 UNLOCK_X11
378 if (data->gc)
380 ok = TRUE;
382 #if X11SOFTMOUSE
383 init_empty_cursor(DRAWABLE(data), data->gc, XSD(cl));
384 #endif
386 else
388 ok = FALSE;
392 else
394 ok = FALSE;
395 } /* if (msgport created && msg allocated) */
397 if (NULL != msg)
398 FreeMem(msg, sizeof (*msg));
400 if (NULL != port)
401 DeleteMsgPort(port);
405 else
407 ok = FALSE;
408 } /* if (Xwindow created) */
410 if (!ok)
413 OOP_MethodID disp_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
415 OOP_CoerceMethod(cl, o, (OOP_Msg) &disp_mid);
417 o = NULL;
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. */
437 //CCALL(raise, 19);
439 if (data->gc)
441 LOCK_X11
442 XCALL(XFreeGC, data->display, data->gc);
443 UNLOCK_X11
446 if (DRAWABLE(data))
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");
457 //CCALL(raise, 19);
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);
467 WaitPort(port);
469 GetMsg(port);
471 FreeMem(msg, sizeof (*msg));
472 DeleteMsgPort(port);
474 LOCK_X11
475 XCALL(XDestroyWindow, GetSysDisplay(), DRAWABLE(data));
476 XCALL(XFlush, GetSysDisplay() );
477 UNLOCK_X11
480 #if ADJUST_XWIN_SIZE
481 if (MASTERWIN(data))
483 LOCK_X11
484 XCALL(XDestroyWindow, GetSysDisplay(), MASTERWIN(data));
485 XCALL(XFlush, GetSysDisplay() );
486 UNLOCK_X11
488 #endif
490 if (data->flags & BMDF_COLORMAP_ALLOCED)
492 LOCK_X11
493 XCALL(XFreeColormap, GetSysDisplay(), data->colmap);
494 UNLOCK_X11
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);
507 ULONG width, height;
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);
518 LOCK_X11
519 XCALL(XChangeWindowAttributes, data->display, DRAWABLE(data),
520 CWBackPixel, &winattr);
522 XCALL(XClearArea, data->display, DRAWABLE(data),
523 0, 0,
524 width, height,
525 FALSE);
527 XCALL(XFlush, data->display);
528 UNLOCK_X11
531 /****************************************************************************************/
533 #undef XSD
534 #define XSD(cl) (&LIBBASE->xsd)
536 #define NUM_ROOT_METHODS 4
538 #if USE_X11_DRAWFUNCS
539 # define NUM_BITMAP_METHODS 13
540 #else
541 # define NUM_BITMAP_METHODS 11
542 #endif
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);
556 return TRUE;
559 /****************************************************************************************/
561 ADD2INITLIB(X11OnBM_Init, 0);
562 ADD2EXPUNGELIB(X11OnBM_Expunge, 0);
564 #if X11SOFTMOUSE
566 /****************************************************************************************/
568 static void init_empty_cursor(Window w, GC gc, struct x11_staticdata *xsd)
570 Pixmap p, mask;
571 int width, height;
573 width = height = 1;
575 LOCK_X11
576 p = XCALL(XCreatePixmap, xsd->display, w, width, height, 1);
577 UNLOCK_X11
580 if (0 != p)
582 LOCK_X11
583 mask = XCALL(XCreatePixmap, xsd->display
585 , width
586 , height
589 XCALL(XFlush, xsd->display);
590 UNLOCK_X11
592 if (0 != mask)
594 /* Define cursor for window */
595 XColor fg, bg;
596 Cursor c;
597 int x, y;
599 LOCK_X11
600 XCALL(XSetForeground, xsd->display, gc, 0);
601 XCALL(XSetFunction, xsd->display, gc, GXcopy);
602 #if 0
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);
611 #endif
612 UNLOCK_X11
614 fg.pixel = BlackPixel(xsd->display, DefaultScreen(xsd->display));
615 fg.red = 0x0000;
616 fg.green = 0x0000;
617 fg.blue = 0x0000;
618 fg.flags = DoRed | DoGreen | DoBlue;
620 bg.pixel = WhitePixel(xsd->display, DefaultScreen(xsd->display));
621 bg.red = 0xFFFF;
622 bg.green = 0xFFFF;
623 bg.blue = 0xFFFF;
624 bg.flags = DoRed | DoGreen | DoBlue;
626 LOCK_X11
627 c = XCALL(XCreatePixmapCursor, xsd->display, p, mask, &fg, &bg, 0, 0);
628 UNLOCK_X11
630 if (0 != c)
632 LOCK_X11
633 XCALL(XDefineCursor, xsd->display, w, c);
634 UNLOCK_X11
637 LOCK_X11
638 XCALL(XFreePixmap, xsd->display, mask);
639 UNLOCK_X11
642 LOCK_X11
643 XCALL(XFreePixmap, xsd->display, p);
644 UNLOCK_X11
649 /****************************************************************************************/
651 #endif
653 /****************************************************************************************/
655 static Pixmap init_icon(Display *d, Window w, Colormap cm, LONG depth, struct x11_staticdata *xsd)
657 #include "icon.h"
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;
665 GC gc;
667 red_shift = 24 - xsd->red_shift;
668 green_shift = 24 - xsd->green_shift;
669 blue_shift = 24 - xsd->blue_shift;
671 if (icon)
673 gc = XCALL(XCreateGC, d, icon, 0, 0);
675 if (gc)
677 WORD x, y;
679 for(y = 0; y < height; y++)
681 for(x = 0; x < width; x++)
683 ULONG rgb[3];
684 ULONG pixel = 0;
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)
696 XColor xcol;
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))
705 pixel = xcol.pixel;
709 XCALL(XSetForeground, d, gc, pixel);
710 XCALL(XDrawPoint, d, icon, gc, x, y);
714 XCALL(XFreeGC, d, gc);
716 } /* if (gc) */
718 } /* if (icon) */
720 return icon;
723 /****************************************************************************************/