6 #include <X11/extensions/shape.h>
9 typedef struct W_Balloon
{
12 WMHashTable
*table
; /* Table from view ptr to text */
18 WMHandlerID timer
; /* timer for showing balloon */
20 WMHandlerID noDelayTimer
;
24 Window forWindow
; /* window for which the balloon
25 * is being show in the moment */
28 WMAlignment alignment
:2;
35 #define DEFAULT_WIDTH 60
36 #define DEFAULT_HEIGHT 14
37 #define DEFAULT_ALIGNMENT WALeft
38 #define DEFAULT_DELAY 500
40 #define NO_DELAY_DELAY 150
42 static void destroyBalloon(Balloon
* bPtr
);
44 static void handleEvents(XEvent
* event
, void *data
);
46 static void showText(Balloon
* bPtr
, int x
, int y
, int w
, int h
, char *text
);
48 struct W_Balloon
*W_CreateBalloon(WMScreen
* scr
)
52 bPtr
= wmalloc(sizeof(Balloon
));
53 memset(bPtr
, 0, sizeof(Balloon
));
55 bPtr
->view
= W_CreateUnmanagedTopView(scr
);
60 bPtr
->view
->self
= bPtr
;
62 bPtr
->textColor
= WMRetainColor(bPtr
->view
->screen
->black
);
64 WMCreateEventHandler(bPtr
->view
, StructureNotifyMask
, handleEvents
, bPtr
);
66 W_ResizeView(bPtr
->view
, DEFAULT_WIDTH
, DEFAULT_HEIGHT
);
67 bPtr
->flags
.alignment
= DEFAULT_ALIGNMENT
;
69 bPtr
->table
= WMCreateHashTable(WMIntHashCallbacks
);
71 bPtr
->delay
= DEFAULT_DELAY
;
73 bPtr
->flags
.enabled
= 1;
78 void WMSetBalloonTextAlignment(WMScreen
* scr
, WMAlignment alignment
)
80 scr
->balloon
->flags
.alignment
= alignment
;
84 void WMSetBalloonTextForView(char *text
, WMView
* view
)
87 WMScreen
*scr
= view
->screen
;
90 oldText
= WMHashInsert(scr
->balloon
->table
, view
, wstrdup(text
));
92 oldText
= WMHashGet(scr
->balloon
->table
, view
);
94 WMHashRemove(scr
->balloon
->table
, view
);
102 void WMSetBalloonFont(WMScreen
* scr
, WMFont
* font
)
104 Balloon
*bPtr
= scr
->balloon
;
106 if (bPtr
->font
!= NULL
)
107 WMReleaseFont(bPtr
->font
);
110 bPtr
->font
= WMRetainFont(font
);
115 void WMSetBalloonTextColor(WMScreen
* scr
, WMColor
* color
)
117 Balloon
*bPtr
= scr
->balloon
;
120 WMReleaseColor(bPtr
->textColor
);
122 bPtr
->textColor
= WMRetainColor(color
);
125 void WMSetBalloonDelay(WMScreen
* scr
, int delay
)
127 scr
->balloon
->delay
= delay
;
130 void WMSetBalloonEnabled(WMScreen
* scr
, Bool flag
)
132 scr
->balloon
->flags
.enabled
= ((flag
== 0) ? 0 : 1);
134 W_UnmapView(scr
->balloon
->view
);
137 static void clearNoDelay(void *data
)
139 Balloon
*bPtr
= (Balloon
*) data
;
141 bPtr
->flags
.noDelay
= 0;
142 bPtr
->noDelayTimer
= NULL
;
145 void W_BalloonHandleLeaveView(WMView
* view
)
147 Balloon
*bPtr
= view
->screen
->balloon
;
149 if (bPtr
->forWindow
== view
->window
) {
150 if (bPtr
->view
->flags
.mapped
) {
151 W_UnmapView(bPtr
->view
);
152 bPtr
->noDelayTimer
= WMAddTimerHandler(NO_DELAY_DELAY
, clearNoDelay
, bPtr
);
155 WMDeleteTimerHandler(bPtr
->timer
);
159 bPtr
->forWindow
= None
;
164 * botar balao perto do cursor
165 * so mapear balao se o mouse ficar parado pelo delay
169 static void showBalloon(void *data
)
172 WMView
*view
= (WMView
*) data
;
173 Balloon
*bPtr
= view
->screen
->balloon
;
179 text
= WMHashGet(bPtr
->table
, view
);
183 XTranslateCoordinates(view
->screen
->display
, view
->window
, view
->screen
->rootWin
, 0, 0, &x
, &y
, &foo
);
185 if (!bPtr
->view
->flags
.realized
)
186 W_RealizeView(bPtr
->view
);
188 showText(bPtr
, x
, y
, view
->size
.width
, view
->size
.height
, text
);
190 bPtr
->flags
.noDelay
= 1;
193 void W_BalloonHandleEnterView(WMView
* view
)
195 Balloon
*bPtr
= view
->screen
->balloon
;
198 if (!bPtr
->flags
.enabled
)
201 text
= WMHashGet(bPtr
->table
, view
);
203 if (bPtr
->view
->flags
.realized
)
204 W_UnmapView(bPtr
->view
);
210 WMDeleteTimerHandler(bPtr
->timer
);
213 if (bPtr
->noDelayTimer
)
214 WMDeleteTimerHandler(bPtr
->noDelayTimer
);
215 bPtr
->noDelayTimer
= NULL
;
217 bPtr
->forWindow
= view
->window
;
219 if (bPtr
->flags
.noDelay
) {
224 bPtr
->timer
= WMAddTimerHandler(bPtr
->delay
, showBalloon
, view
);
233 #define TLEFT (TOP|LEFT)
234 #define TRIGHT (TOP|RIGHT)
235 #define BLEFT (BOTTOM|LEFT)
236 #define BRIGHT (BOTTOM|RIGHT)
240 static void drawBalloon(WMScreen
* scr
, Pixmap bitmap
, Pixmap pix
, int x
, int y
, int w
, int h
, int side
)
242 Display
*dpy
= scr
->display
;
243 WMColor
*white
= WMWhiteColor(scr
);
244 WMColor
*black
= WMBlackColor(scr
);
245 GC bgc
= scr
->monoGC
;
246 GC gc
= WMColorGC(white
);
247 int rad
= h
* 3 / 10;
248 XPoint pt
[3], ipt
[3];
252 XSetForeground(dpy
, bgc
, 1);
254 XFillArc(dpy
, bitmap
, bgc
, x
, y
, rad
, rad
, 90 * 64, 90 * 64);
255 XFillArc(dpy
, bitmap
, bgc
, x
, y
+ h
- 1 - rad
, rad
, rad
, 180 * 64, 90 * 64);
257 XFillArc(dpy
, bitmap
, bgc
, x
+ w
- 1 - rad
, y
, rad
, rad
, 0 * 64, 90 * 64);
258 XFillArc(dpy
, bitmap
, bgc
, x
+ w
- 1 - rad
, y
+ h
- 1 - rad
, rad
, rad
, 270 * 64, 90 * 64);
260 XFillRectangle(dpy
, bitmap
, bgc
, x
, y
+ rad
/ 2, w
, h
- rad
);
261 XFillRectangle(dpy
, bitmap
, bgc
, x
+ rad
/ 2, y
, w
- rad
, h
);
264 XFillArc(dpy
, pix
, gc
, x
+ 1, y
+ 1, rad
, rad
, 90 * 64, 90 * 64);
265 XFillArc(dpy
, pix
, gc
, x
+ 1, y
+ h
- 2 - rad
, rad
, rad
, 180 * 64, 90 * 64);
267 XFillArc(dpy
, pix
, gc
, x
+ w
- 2 - rad
, y
+ 1, rad
, rad
, 0 * 64, 90 * 64);
268 XFillArc(dpy
, pix
, gc
, x
+ w
- 2 - rad
, y
+ h
- 2 - rad
, rad
, rad
, 270 * 64, 90 * 64);
270 XFillRectangle(dpy
, pix
, gc
, x
+ 1, y
+ 1 + rad
/ 2, w
- 2, h
- 2 - rad
);
271 XFillRectangle(dpy
, pix
, gc
, x
+ 1 + rad
/ 2, y
+ 1, w
- 2 - rad
, h
- 2);
275 pt
[1].y
= y
+ h
- 1 + SPACE
;
277 ipt
[0].y
= pt
[0].y
- 1;
278 ipt
[1].y
= pt
[1].y
- 1;
279 ipt
[2].y
= pt
[2].y
- 1;
284 ipt
[0].y
= pt
[0].y
+ 1;
285 ipt
[1].y
= pt
[1].y
+ 1;
286 ipt
[2].y
= pt
[2].y
+ 1;
289 /*w1 = WMAX(h, 24); */
293 pt
[0].x
= x
+ w
- w1
+ 2 * w1
/ 16;
294 pt
[1].x
= x
+ w
- w1
+ 11 * w1
/ 16;
295 pt
[2].x
= x
+ w
- w1
+ 7 * w1
/ 16;
296 ipt
[0].x
= x
+ 1 + w
- w1
+ 2 * (w1
- 1) / 16;
297 ipt
[1].x
= x
+ 1 + w
- w1
+ 11 * (w1
- 1) / 16;
298 ipt
[2].x
= x
+ 1 + w
- w1
+ 7 * (w1
- 1) / 16;
299 /*ipt[0].x = pt[0].x+1;
301 ipt[2].x = pt[2].x; */
303 pt
[0].x
= x
+ w1
- 2 * w1
/ 16;
304 pt
[1].x
= x
+ w1
- 11 * w1
/ 16;
305 pt
[2].x
= x
+ w1
- 7 * w1
/ 16;
306 ipt
[0].x
= x
- 1 + w1
- 2 * (w1
- 1) / 16;
307 ipt
[1].x
= x
- 1 + w1
- 11 * (w1
- 1) / 16;
308 ipt
[2].x
= x
- 1 + w1
- 7 * (w1
- 1) / 16;
309 /*ipt[0].x = pt[0].x-1;
311 ipt[2].x = pt[2].x; */
314 XFillPolygon(dpy
, bitmap
, bgc
, pt
, 3, Convex
, CoordModeOrigin
);
315 XFillPolygon(dpy
, pix
, gc
, ipt
, 3, Convex
, CoordModeOrigin
);
318 XDrawLines(dpy
, pix
, WMColorGC(black
), pt
, 3, CoordModeOrigin
);
326 XDrawLines(dpy
, pix
, WMColorGC(black
), pt
, 3, CoordModeOrigin
);
328 WMReleaseColor(white
);
329 WMReleaseColor(black
);
332 static Pixmap
makePixmap(WMScreen
* scr
, int width
, int height
, int side
, Pixmap
* mask
)
334 Display
*dpy
= WMScreenDisplay(scr
);
338 WMColor
*black
= WMBlackColor(scr
);
340 bitmap
= XCreatePixmap(dpy
, scr
->rootWin
, width
+ SPACE
, height
+ SPACE
, 1);
342 XSetForeground(dpy
, scr
->monoGC
, 0);
343 XFillRectangle(dpy
, bitmap
, scr
->monoGC
, 0, 0, width
+ SPACE
, height
+ SPACE
);
345 pixmap
= XCreatePixmap(dpy
, scr
->rootWin
, width
+ SPACE
, height
+ SPACE
, scr
->depth
);
347 XFillRectangle(dpy
, pixmap
, WMColorGC(black
), 0, 0, width
+ SPACE
, height
+ SPACE
);
356 drawBalloon(scr
, bitmap
, pixmap
, x
, y
, width
, height
, side
);
360 WMReleaseColor(black
);
365 static void showText(Balloon
* bPtr
, int x
, int y
, int w
, int h
, char *text
)
367 WMScreen
*scr
= bPtr
->view
->screen
;
368 Display
*dpy
= WMScreenDisplay(scr
);
373 WMFont
*font
= bPtr
->font
? bPtr
->font
: scr
->normalFont
;
385 while (ptr
&& ptr2
) {
386 ptr2
= strchr(ptr
, '\n');
388 w
= WMWidthOfString(font
, ptr
, ptr2
- ptr
);
390 w
= WMWidthOfString(font
, ptr
, strlen(ptr
));
400 textHeight
= W_GetTextHeight(font
, text
, width
, False
);
402 height
= textHeight
+ 4;
409 if (x
+ width
> scr
->rootView
->size
.width
) {
411 bx
= x
- width
+ w
/ 2;
418 if (bx
+ width
> scr
->rootView
->size
.width
)
419 bx
= scr
->rootView
->size
.width
- width
;
421 if (y
- (height
+ SPACE
) < 0) {
427 by
= y
- (height
+ SPACE
);
430 pixmap
= makePixmap(scr
, width
, height
, side
, &mask
);
432 W_PaintText(bPtr
->view
, pixmap
, font
, 8, ty
+ (height
- textHeight
) / 2,
433 width
, bPtr
->flags
.alignment
,
434 bPtr
->textColor
? bPtr
->textColor
: scr
->black
, False
, text
, strlen(text
));
436 XSetWindowBackgroundPixmap(dpy
, bPtr
->view
->window
, pixmap
);
438 W_ResizeView(bPtr
->view
, width
, height
+ SPACE
);
440 XFreePixmap(dpy
, pixmap
);
443 XShapeCombineMask(dpy
, bPtr
->view
->window
, ShapeBounding
, 0, 0, mask
, ShapeSet
);
445 XFreePixmap(dpy
, mask
);
447 W_MoveView(bPtr
->view
, bx
, by
);
449 W_MapView(bPtr
->view
);
452 static void handleEvents(XEvent
* event
, void *data
)
454 Balloon
*bPtr
= (Balloon
*) data
;
456 switch (event
->type
) {
458 destroyBalloon(bPtr
);
463 static void destroyBalloon(Balloon
* bPtr
)
468 e
= WMEnumerateHashTable(bPtr
->table
);
470 while ((str
= WMNextHashEnumeratorItem(&e
))) {
473 WMFreeHashTable(bPtr
->table
);
476 WMReleaseColor(bPtr
->textColor
);
479 WMReleaseFont(bPtr
->font
);