add shit that i made in the last week!
[mikachu/openbox.git] / openbox / popup.c
1 #include "openbox.h"
2 #include "frame.h"
3 #include "render/render.h"
4 #include "render/theme.h"
5
6 typedef struct Popup {
7     gboolean hasicon;
8     Window bg;
9     Window icon;
10     Window text;
11     Appearance *a_bg;
12     Appearance *a_icon;
13     Appearance *a_text;
14     int gravity;
15     int x;
16     int y;
17     int w;
18     int h;
19 } Popup;
20
21 Popup *popup_new(gboolean hasicon)
22 {
23     Popup *self = g_new(Popup, 1);
24     self->hasicon = hasicon;
25     self->bg = None;
26     self->a_text = NULL;
27     self->gravity = NorthWestGravity;
28     self->x = self->y = self->w = self->h = 0;
29     return self;
30 }
31
32 void popup_free(Popup *self)
33 {
34     if (self->bg) {
35         XDestroyWindow(ob_display, self->bg);
36         XDestroyWindow(ob_display, self->text);
37         XDestroyWindow(ob_display, self->icon);
38         appearance_free(self->a_bg);
39         if (self->hasicon)
40             appearance_free(self->a_icon);
41     }
42     if (self->a_text)
43         appearance_free(self->a_text);
44     g_free(self);
45 }
46
47 void popup_position(Popup *self, int gravity, int x, int y)
48 {
49     self->gravity = gravity;
50     self->x = x;
51     self->y = y;
52 }
53
54 void popup_size(Popup *self, int w, int h)
55 {
56     self->w = w;
57     self->h = h;
58 }
59
60 void popup_size_to_string(Popup *self, char *text)
61 {
62     int textw, texth;
63     int iconw;
64
65     if (!self->a_text)
66         self->a_text = appearance_copy(theme_app_hilite_label);
67
68     self->a_text->texture[0].data.text.string = text;
69     appearance_minsize(self->a_text, &textw, &texth);
70     textw += theme_bevel * 2;
71     texth += theme_bevel * 2;
72
73     self->h = texth + theme_bevel * 2;
74     iconw = (self->hasicon ? texth : 0);
75     self->w = textw + iconw + theme_bevel * 3;
76 }
77
78 void popup_show(Popup *self, char *text, Icon *icon)
79 {
80     XSetWindowAttributes attrib;
81     int x, y, w, h;
82     int textw, texth;
83     int iconw;
84
85     /* create the shit if needed */
86     if (!self->bg) {
87         attrib.override_redirect = True;
88         self->bg = XCreateWindow(ob_display, ob_root,
89                                  0, 0, 1, 1, 0, render_depth, InputOutput,
90                                  render_visual, CWOverrideRedirect, &attrib);
91
92         XSetWindowBorderWidth(ob_display, self->bg, theme_bwidth);
93         XSetWindowBorder(ob_display, self->bg, theme_b_color->pixel);
94
95         self->text = XCreateWindow(ob_display, self->bg,
96                                    0, 0, 1, 1, 0, render_depth, InputOutput,
97                                    render_visual, 0, NULL);
98         if (self->hasicon)
99             self->icon = XCreateWindow(ob_display, self->bg,
100                                        0, 0, 1, 1, 0,
101                                        render_depth, InputOutput,
102                                        render_visual, 0, NULL);
103
104         XMapWindow(ob_display, self->text);
105         XMapWindow(ob_display, self->icon);
106
107         self->a_bg = appearance_copy(theme_app_hilite_bg);
108         if (self->hasicon)
109             self->a_icon = appearance_copy(theme_app_icon);
110     }
111     if (!self->a_text)
112         self->a_text = appearance_copy(theme_app_hilite_label);
113
114     /* set up the textures */
115     self->a_text->texture[0].data.text.string = text;
116     if (self->hasicon) {
117         if (icon) {
118             self->a_icon->texture[0].type = RGBA;
119             self->a_icon->texture[0].data.rgba.width = icon->width;
120             self->a_icon->texture[0].data.rgba.height = icon->height;
121             self->a_icon->texture[0].data.rgba.data = icon->data;
122         } else
123             self->a_icon->texture[0].type = NoTexture;
124     }
125
126     /* measure the shit out */
127     appearance_minsize(self->a_text, &textw, &texth);
128     textw += theme_bevel * 2;
129     texth += theme_bevel * 2;
130
131     /* set the sizes up and reget the text sizes from the calculated
132        outer sizes */
133     if (self->h) {
134         h = self->h;
135         texth = h - (theme_bevel * 2);
136     } else
137         h = texth + theme_bevel * 2;
138     iconw = (self->hasicon ? texth : 0);
139     if (self->w) {
140         w = self->w;
141         textw = w - (iconw + theme_bevel * 3);
142     } else
143         w = textw + iconw + theme_bevel * 3;
144     /* sanity checks to avoid crashes! */
145     if (w < 1) w = 1;
146     if (h < 1) h = 1;
147     if (textw < 1) textw = 1;
148     if (texth < 1) texth = 1;
149
150     /* set up the x coord */
151     x = self->x;
152     switch (self->gravity) {
153     case NorthGravity:
154     case CenterGravity:
155     case SouthGravity:
156         x -= w / 2;
157         break;
158     case NorthEastGravity:
159     case EastGravity:
160     case SouthEastGravity:
161         x -= w;
162         break;
163     }
164
165     /* set up the y coord */
166     y = self->y;
167     switch (self->gravity) {
168     case WestGravity:
169     case CenterGravity:
170     case EastGravity:
171         y -= h / 2;
172         break;
173     case SouthWestGravity:
174     case SouthGravity:
175     case SouthEastGravity:
176         y -= h;
177         break;
178     }
179
180     /* set the windows/appearances up */
181     RECT_SET(self->a_bg->area, 0, 0, w, h);
182     XMoveResizeWindow(ob_display, self->bg, x, y, w, h);
183
184     RECT_SET(self->a_text->area, 0, 0, textw, texth); 
185     RECT_SET(self->a_text->texture[0].position, theme_bevel, theme_bevel,
186              textw - theme_bevel * 2, texth - theme_bevel * 2);
187     self->a_text->surface.data.planar.parent = self->a_bg;
188     self->a_text->surface.data.planar.parentx = iconw + theme_bevel * 2;
189     self->a_text->surface.data.planar.parenty = theme_bevel;
190     XMoveResizeWindow(ob_display, self->text,
191                       iconw + theme_bevel * 2, theme_bevel, textw, texth);
192
193     if (self->hasicon) {
194         if (iconw < 1) iconw = 1; /* sanity check for crashes */
195         RECT_SET(self->a_icon->area, 0, 0, iconw, texth);
196         RECT_SET(self->a_icon->texture[0].position, 0, 0, iconw, texth);
197         self->a_icon->surface.data.planar.parent = self->a_bg;
198         self->a_icon->surface.data.planar.parentx = theme_bevel;
199         self->a_icon->surface.data.planar.parenty = theme_bevel;
200         XMoveResizeWindow(ob_display, self->icon,
201                           theme_bevel, theme_bevel, iconw, texth);
202     }
203
204     paint(self->bg, self->a_bg);
205     paint(self->text, self->a_text);
206     if (self->hasicon)
207         paint(self->icon, self->a_icon);
208
209     XMapWindow(ob_display, self->bg);
210 }
211
212 void popup_hide(Popup *self)
213 {
214     XUnmapWindow(ob_display, self->bg);
215 }