]> icculus.org git repositories - dana/openbox.git/blob - openbox/popup.c
the kernel is using th gl shit to render itself, but with the old style frame shit...
[dana/openbox.git] / openbox / popup.c
1 #include "openbox.h"
2 #include "frame.h"
3 #include "window.h"
4 #include "stacking.h"
5 #include "render2/render.h"
6 #include "render2/theme.h"
7
8 typedef struct Popup {
9     ObWindow obwin;
10     Window bg;
11
12     Window icon;
13     Window text;
14
15     gboolean hasicon;
16     struct RrSurface *s_bg;
17     struct RrSurface *s_icon;
18     struct RrSurface *s_text;
19     int gravity;
20     int x;
21     int y;
22     int w;
23     int h;
24 } Popup;
25
26 Popup *popup_new(gboolean hasicon)
27 {
28     XSetWindowAttributes attrib;
29     Popup *self;
30
31     self = g_new(Popup, 1);
32     self->obwin.type = Window_Internal;
33     self->hasicon = hasicon;
34     self->gravity = NorthWestGravity;
35     self->x = self->y = self->w = self->h = 0;
36     stacking_add(INTERNAL_AS_WINDOW(self));
37     stacking_raise(INTERNAL_AS_WINDOW(self));
38
39     attrib.override_redirect = True;
40     attrib.event_mask = ExposureMask;
41     self->bg = XCreateWindow(ob_display, ob_root,
42                              0, 0, 1, 1, 0, RrInstanceDepth(ob_render_inst),
43                              InputOutput, RrInstanceVisual(ob_render_inst),
44                              CWEventMask|CWOverrideRedirect, &attrib);
45     self->s_bg = RrSurfaceNew(ob_render_inst, 0, self->bg, 0);
46     RrSurfaceCopy(self->s_bg, ob_theme->app_bg_h);
47
48     self->s_text = RrSurfaceNewChild(0, self->s_bg, 1);
49     RrSurfaceCopy(self->s_text, ob_theme->app_label_h);
50
51     self->text = RrSurfaceWindow(self->s_text);
52
53     if (self->hasicon) {
54         self->s_icon = RrSurfaceNewChild(RR_SURFACE_PLANAR, self->s_bg, 1);
55         RrSurfaceCopy(self->s_icon, ob_theme->app_icon);
56
57         self->icon = RrSurfaceWindow(self->s_icon);
58     } else {
59         self->s_icon = NULL;
60         self->icon = None;
61     }
62
63     return self;
64 }
65
66 void popup_free(Popup *self)
67 {
68     RrSurfaceFree(self->s_icon);
69     RrSurfaceFree(self->s_text);
70     RrSurfaceFree(self->s_bg);
71     XDestroyWindow(ob_display, self->bg);
72     stacking_remove(self);
73     g_free(self);
74 }
75
76 void popup_position(Popup *self, int gravity, int x, int y)
77 {
78     self->gravity = gravity;
79     self->x = x;
80     self->y = y;
81 }
82
83 void popup_size(Popup *self, int w, int h)
84 {
85     self->w = w;
86     self->h = h;
87 }
88
89 void popup_size_to_string(Popup *self, char *text)
90 {
91     int textw, texth;
92     int iconw;
93     struct RrColor c;
94
95     RrColorSet(&c, 0, 0, 0, 1.0);
96     RrTextureSetText(self->s_text, 0, NULL, RR_LEFT, &c, text);
97     RrSurfaceMinSize(self->s_text, &textw, &texth);
98     textw += ob_theme->bevel * 2;
99     texth += ob_theme->bevel * 2;
100
101     self->h = texth + ob_theme->bevel * 2 + ob_theme->bwidth * 2;
102     iconw = (self->hasicon ? texth + ob_theme->bevel : 0);
103     self->w = textw + iconw + ob_theme->bevel * 2 + ob_theme->bwidth * 2;
104 }
105
106 void popup_show(Popup *self, char *text, Icon *icon)
107 {
108     int x, y, w, h;
109     int textw, texth;
110     int iconw;
111     struct RrColor c;
112     struct RrFont *font;
113
114     /* set up the textures */
115     RrColorSet(&c, 0, 0, 0, 1.0);
116     font = RrFontOpen(ob_render_inst, "arial-10:bold"); /* XXX mem leak! */
117     RrTextureSetText(self->s_text, 0, font, RR_LEFT, &c, text);
118
119     /* measure the shit out */
120     RrSurfaceMinSize(self->s_text, &textw, &texth);
121     textw += ob_theme->bevel * 2;
122     texth += ob_theme->bevel * 2;
123
124     /* set the sizes up and reget the text sizes from the calculated
125        outer sizes */
126     if (self->h) {
127         h = self->h;
128         texth = h - (ob_theme->bevel * 2) - ob_theme->bwidth * 2;
129     } else
130         h = texth + ob_theme->bevel * 2 + ob_theme->bwidth * 2;
131     iconw = (self->hasicon ? texth : 0);
132     if (self->w) {
133         w = self->w;
134         textw = w - (iconw + ob_theme->bevel * (self->hasicon ? 3 : 2)) -
135             ob_theme->bwidth * 2;
136     } else
137         w = textw + iconw + ob_theme->bevel * (self->hasicon ? 3 : 2) +
138             ob_theme->bwidth * 2;
139     /* sanity checks to avoid crashes! */
140     if (w < 1) w = 1;
141     if (h < 1) h = 1;
142     if (textw < 1) textw = 1;
143     if (texth < 1) texth = 1;
144
145     /* set up the x coord */
146     x = self->x;
147     switch (self->gravity) {
148     case NorthGravity:
149     case CenterGravity:
150     case SouthGravity:
151         x -= w / 2;
152         break;
153     case NorthEastGravity:
154     case EastGravity:
155     case SouthEastGravity:
156         x -= w;
157         break;
158     }
159
160     /* set up the y coord */
161     y = self->y;
162     switch (self->gravity) {
163     case WestGravity:
164     case CenterGravity:
165     case EastGravity:
166         y -= h / 2;
167         break;
168     case SouthWestGravity:
169     case SouthGravity:
170     case SouthEastGravity:
171         y -= h;
172         break;
173     }
174
175     /* set the surfaces up */
176     RrSurfaceSetArea(self->s_bg, x, y, w, h);
177
178     RrSurfaceSetArea(self->s_text,
179                      iconw + ob_theme->bevel * (self->hasicon ? 2 : 1) +
180                      ob_theme->bwidth,
181                      ob_theme->bevel + ob_theme->bwidth,
182                      textw, texth);
183
184     if (self->hasicon) {
185         if (icon)
186             RrTextureSetRGBA(self->s_icon, 0, icon->data, 0, 0, icon->width,
187                              icon->height);
188         else
189             RrTextureSetNone(self->s_icon, 0);
190         if (iconw < 1) iconw = 1; /* sanity check for crashes */
191         RrSurfaceSetArea(self->s_icon,
192                          ob_theme->bwidth + ob_theme->bevel,
193                          ob_theme->bwidth + ob_theme->bevel,
194                          iconw, iconw);
195     }
196
197     if (!RrSurfaceVisible(self->s_bg)) {
198         RrSurfaceShow(self->s_bg);
199         stacking_raise(INTERNAL_AS_WINDOW(self));
200     } else
201         RrPaint(self->s_bg);
202 }
203
204 void popup_hide(Popup *self)
205 {
206     RrSurfaceHide(self->s_bg);
207 }