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