]> Dogcows Code - chaz/openbox/blob - openbox/slit.c
add a slit to the kernel
[chaz/openbox] / openbox / slit.c
1 #include "slit.h"
2 #include "screen.h"
3 #include "openbox.h"
4 #include "render/theme.h"
5 #include "render/render.h"
6
7 #ifdef HAVE_LIMITS_H
8 # include <limits.h>
9 #endif
10
11 #define SLITAPP_EVENT_MASK (StructureNotifyMask)
12
13 struct Slit {
14 Window frame;
15
16 /* user-requested position stuff */
17 SlitPosition pos;
18 int gravity;
19 int user_x, user_y;
20
21 /* actual position (when not auto-hidden) */
22 int x, y;
23 int w, h;
24
25 gboolean horz;
26
27 Appearance *a_frame;
28
29 GList *slit_apps;
30 };
31
32 GHashTable *slit_map = NULL;
33
34 static Slit *slit;
35 static int nslits;
36
37 static void slit_configure(Slit *self);
38
39 void slit_startup()
40 {
41 XSetWindowAttributes attrib;
42 int i;
43
44 slit_map = g_hash_table_new(g_int_hash, g_int_equal);
45
46 nslits = 1;
47 slit = g_new0(struct Slit, nslits);
48
49 for (i = 0; i < nslits; ++i) {
50 slit[i].horz = TRUE;
51
52 attrib.override_redirect = True;
53 slit[i].frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
54 render_depth, InputOutput, render_visual,
55 CWOverrideRedirect, &attrib);
56 slit[i].a_frame = appearance_copy(theme_a_unfocused_title);
57 XSetWindowBorder(ob_display, slit[i].frame, theme_b_color->pixel);
58 XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
59 }
60 }
61
62 void slit_shutdown()
63 {
64 int i;
65
66 for (i = 0; i < nslits; ++i) {
67 XDestroyWindow(ob_display, slit[i].frame);
68 appearance_free(slit[i].a_frame);
69 }
70 }
71
72 void slit_add(Window win, XWMHints *wmhints, XWindowAttributes *attrib)
73 {
74 Slit *s;
75 SlitApp *app;
76
77 /* XXX pick a slit */
78 s = &slit[0];
79
80 app = g_new0(SlitApp, 1);
81 app->slit = s;
82 app->win = win;
83 app->icon_win = (wmhints->flags & IconWindowHint) ?
84 wmhints->icon_window : win;
85
86 app->w = attrib->width;
87 app->h = attrib->height;
88
89 s->slit_apps = g_list_append(s->slit_apps, app);
90 slit_configure(s);
91 XReparentWindow(ob_display, app->icon_win, s->frame, app->x, app->y);
92
93 /*
94 This is the same case as in frame.c for client windows. When Openbox is
95 starting, the window is already mapped so we see unmap events occur for
96 it. There are 2 unmap events generated that we see, one with the 'event'
97 member set the root window, and one set to the client, but both get
98 handled and need to be ignored.
99 */
100 if (ob_state == State_Starting)
101 app->ignore_unmaps += 2;
102
103 if (app->win != app->icon_win)
104 XMoveWindow(ob_display, app->win, 100, 100);
105 XMapWindow(ob_display, app->icon_win);
106 XSync(ob_display, False);
107
108 /* specify that if we exit, the window should not be destroyed and should
109 be reparented back to root automatically */
110 XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
111 XSelectInput(ob_display, app->icon_win, SLITAPP_EVENT_MASK);
112
113 g_hash_table_insert(slit_map, &app->icon_win, app);
114
115 g_message("Managed Slit App: 0x%lx", app->icon_win);
116 }
117
118 void slit_remove_all()
119 {
120 int i;
121
122 for (i = 0; i < nslits; ++i)
123 while (slit[i].slit_apps)
124 slit_remove(slit[i].slit_apps->data, TRUE);
125 }
126
127 void slit_remove(SlitApp *app, gboolean reparent)
128 {
129 XSelectInput(ob_display, app->icon_win, NoEventMask);
130 /* remove the window from our save set */
131 XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
132 XSync(ob_display, False);
133
134 g_hash_table_remove(slit_map, &app->icon_win);
135
136 if (reparent)
137 XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
138
139 app->slit->slit_apps = g_list_remove(app->slit->slit_apps, app);
140 slit_configure(app->slit);
141
142 g_message("Unmanaged Slit App: 0x%lx", app->icon_win);
143
144 g_free(app);
145 }
146
147 void slit_configure_all()
148 {
149 int i; for (i = 0; i < nslits; ++i) slit_configure(&slit[i]);
150 }
151
152 static void slit_configure(Slit *self)
153 {
154 GList *it;
155 int spot;
156
157 self->w = self->h = spot = 0;
158
159 for (it = self->slit_apps; it; it = it->next) {
160 struct SlitApp *app = it->data;
161 if (self->horz) {
162 app->x = spot;
163 app->y = 0;
164 self->w += app->w;
165 self->h = MAX(self->h, app->h);
166 spot += app->w;
167 } else {
168 app->x = 0;
169 app->y = spot;
170 self->w = MAX(self->h, app->w);
171 self->h += app->h;
172 spot += app->h;
173 }
174
175 XMoveWindow(ob_display, app->icon_win, app->x, app->y);
176 }
177
178 /* used for calculating offsets */
179 self->w += theme_bwidth * 2;
180 self->h += theme_bwidth * 2;
181
182 switch (self->pos) {
183 case SlitPos_Floating:
184 /* calculate position */
185 self->x = self->user_x;
186 self->y = self->user_y;
187
188 switch(self->gravity) {
189 case NorthGravity:
190 case CenterGravity:
191 case SouthGravity:
192 self->x -= self->w / 2;
193 break;
194 case NorthEastGravity:
195 case EastGravity:
196 case SouthEastGravity:
197 self->x -= self->w;
198 break;
199 }
200 switch(self->gravity) {
201 case WestGravity:
202 case CenterGravity:
203 case EastGravity:
204 self->y -= self->h / 2;
205 break;
206 case SouthWestGravity:
207 case SouthGravity:
208 case SouthEastGravity:
209 self->y -= self->h;
210 break;
211 }
212 break;
213 case SlitPos_TopLeft:
214 self->x = 0;
215 self->y = 0;
216 break;
217 case SlitPos_Top:
218 self->x = (screen_physical_size.width - self->w) / 2;
219 self->y = 0;
220 break;
221 case SlitPos_TopRight:
222 self->x = screen_physical_size.width - self->w;
223 self->y = 0;
224 break;
225 case SlitPos_Left:
226 self->x = 0;
227 self->y = (screen_physical_size.height - self->h) / 2;
228 break;
229 case SlitPos_Right:
230 self->x = screen_physical_size.width - self->w;
231 self->y = (screen_physical_size.height - self->h) / 2;
232 break;
233 case SlitPos_BottomLeft:
234 self->x = 0;
235 self->y = screen_physical_size.height - self->h;
236 break;
237 case SlitPos_Bottom:
238 self->x = (screen_physical_size.width - self->w) / 2;
239 self->y = screen_physical_size.height - self->h;
240 break;
241 case SlitPos_BottomRight:
242 self->x = screen_physical_size.width - self->w;
243 self->y = screen_physical_size.height - self->h;
244 break;
245 }
246
247 /* not used for actually sizing shit */
248 self->w -= theme_bwidth * 2;
249 self->h -= theme_bwidth * 2;
250
251 if (self->w > 0 && self->h > 0) {
252 RECT_SET(self->a_frame->area, 0, 0, self->w, self->h);
253 XMoveResizeWindow(ob_display, self->frame,
254 self->x, self->y, self->w, self->h);
255
256 paint(self->frame, self->a_frame);
257 XMapWindow(ob_display, self->frame);
258 } else
259 XUnmapWindow(ob_display, self->frame);
260 }
This page took 0.043986 seconds and 4 git commands to generate.