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