4 #include "render/theme.h"
5 #include "render/render.h"
7 #define SLIT_EVENT_MASK (EnterNotifyMask | LeaveNotifyMask)
8 #define SLITAPP_EVENT_MASK (StructureNotifyMask)
13 /* user-requested position stuff */
18 /* actual position (when not auto-hidden) */
31 GHashTable
*slit_map
= NULL
;
32 GHashTable
*slit_app_map
= NULL
;
37 static void slit_configure(Slit
*self
);
41 XSetWindowAttributes attrib
;
44 slit_map
= g_hash_table_new(g_int_hash
, g_int_equal
);
45 slit_app_map
= g_hash_table_new(g_int_hash
, g_int_equal
);
48 slit
= g_new0(struct Slit
, nslits
);
50 for (i
= 0; i
< nslits
; ++i
) {
53 slit
[i
].hidden
= FALSE
;
54 slit
[i
].pos
= SlitPos_TopRight
;
56 attrib
.override_redirect
= True
;
57 slit
[i
].frame
= XCreateWindow(ob_display
, ob_root
, 0, 0, 1, 1, 0,
58 render_depth
, InputOutput
, render_visual
,
59 CWOverrideRedirect
, &attrib
);
60 slit
[i
].a_frame
= appearance_copy(theme_a_unfocused_title
);
61 XSetWindowBorder(ob_display
, slit
[i
].frame
, theme_b_color
->pixel
);
62 XSetWindowBorderWidth(ob_display
, slit
[i
].frame
, theme_bwidth
);
64 g_hash_table_insert(slit_map
, &slit
[i
].frame
, &slit
[i
]);
72 for (i
= 0; i
< nslits
; ++i
) {
73 XDestroyWindow(ob_display
, slit
[i
].frame
);
74 appearance_free(slit
[i
].a_frame
);
75 g_hash_table_remove(slit_map
, &slit
[i
].frame
);
77 g_hash_table_destroy(slit_app_map
);
78 g_hash_table_destroy(slit_map
);
81 void slit_add(Window win
, XWMHints
*wmhints
, XWindowAttributes
*attrib
)
89 app
= g_new0(SlitApp
, 1);
92 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
93 wmhints
->icon_window
: win
;
95 app
->w
= attrib
->width
;
96 app
->h
= attrib
->height
;
98 s
->slit_apps
= g_list_append(s
->slit_apps
, app
);
101 XReparentWindow(ob_display
, app
->icon_win
, s
->frame
, app
->x
, app
->y
);
103 This is the same case as in frame.c for client windows. When Openbox is
104 starting, the window is already mapped so we see unmap events occur for
105 it. There are 2 unmap events generated that we see, one with the 'event'
106 member set the root window, and one set to the client, but both get
107 handled and need to be ignored.
109 if (ob_state
== State_Starting
)
110 app
->ignore_unmaps
+= 2;
112 if (app
->win
!= app
->icon_win
) {
113 /* have to map it so that it can be re-managed on a restart */
114 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
115 XMapWindow(ob_display
, app
->win
);
117 g_message(" Slitting 0x%lx 0x%lx", app
->icon_win
, app
->win
);
118 XMapWindow(ob_display
, app
->icon_win
);
119 XSync(ob_display
, False
);
121 /* specify that if we exit, the window should not be destroyed and should
122 be reparented back to root automatically */
123 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
124 XSelectInput(ob_display
, app
->icon_win
, SLITAPP_EVENT_MASK
);
126 g_hash_table_insert(slit_app_map
, &app
->icon_win
, app
);
128 g_message("Managed Slit App: 0x%lx", app
->icon_win
);
131 void slit_remove_all()
135 for (i
= 0; i
< nslits
; ++i
)
136 while (slit
[i
].slit_apps
)
137 slit_remove(slit
[i
].slit_apps
->data
, TRUE
);
140 void slit_remove(SlitApp
*app
, gboolean reparent
)
142 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
143 /* remove the window from our save set */
144 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
145 XSync(ob_display
, False
);
147 g_hash_table_remove(slit_app_map
, &app
->icon_win
);
150 XReparentWindow(ob_display
, app
->icon_win
, ob_root
, app
->x
, app
->y
);
152 app
->slit
->slit_apps
= g_list_remove(app
->slit
->slit_apps
, app
);
153 slit_configure(app
->slit
);
155 g_message("Unmanaged Slit App: 0x%lx", app
->icon_win
);
160 void slit_configure_all()
162 int i
; for (i
= 0; i
< nslits
; ++i
) slit_configure(&slit
[i
]);
165 static void slit_configure(Slit
*self
)
170 self
->w
= self
->h
= spot
= 0;
172 for (it
= self
->slit_apps
; it
; it
= it
->next
) {
173 struct SlitApp
*app
= it
->data
;
178 self
->h
= MAX(self
->h
, app
->h
);
183 self
->w
= MAX(self
->h
, app
->w
);
188 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
191 /* used for calculating offsets */
192 self
->w
+= theme_bwidth
* 2;
193 self
->h
+= theme_bwidth
* 2;
195 /* calculate position */
197 case SlitPos_Floating
:
198 self
->x
= self
->user_x
;
199 self
->y
= self
->user_y
;
201 case SlitPos_TopLeft
:
204 self
->gravity
= NorthWestGravity
;
207 self
->x
= screen_physical_size
.width
/ 2;
209 self
->gravity
= NorthGravity
;
211 case SlitPos_TopRight
:
212 self
->x
= screen_physical_size
.width
;
214 self
->gravity
= NorthEastGravity
;
218 self
->y
= screen_physical_size
.height
/ 2;
219 self
->gravity
= WestGravity
;
222 self
->x
= screen_physical_size
.width
;
223 self
->y
= screen_physical_size
.height
/ 2;
224 self
->gravity
= EastGravity
;
226 case SlitPos_BottomLeft
:
228 self
->y
= screen_physical_size
.height
;
229 self
->gravity
= SouthWestGravity
;
232 self
->x
= screen_physical_size
.width
/ 2;
233 self
->y
= screen_physical_size
.height
;
234 self
->gravity
= SouthGravity
;
236 case SlitPos_BottomRight
:
237 self
->x
= screen_physical_size
.width
;
238 self
->y
= screen_physical_size
.height
;
239 self
->gravity
= SouthEastGravity
;
243 switch(self
->gravity
) {
247 self
->x
-= self
->w
/ 2;
249 case NorthEastGravity
:
251 case SouthEastGravity
:
255 switch(self
->gravity
) {
259 self
->y
-= self
->h
/ 2;
261 case SouthWestGravity
:
263 case SouthEastGravity
:
268 if (self
->hide
&& self
->hidden
) {
271 case SlitPos_Floating
:
273 case SlitPos_TopLeft
:
275 self
->y
-= self
->h
- theme_bwidth
;
277 self
->x
-= self
->w
- theme_bwidth
;
280 self
->y
-= self
->h
- theme_bwidth
;
282 case SlitPos_TopRight
:
284 self
->y
-= self
->h
- theme_bwidth
;
286 self
->x
+= self
->w
- theme_bwidth
;
289 self
->x
-= self
->w
- theme_bwidth
;
292 self
->x
+= self
->w
- theme_bwidth
;
294 case SlitPos_BottomLeft
:
296 self
->y
+= self
->h
- theme_bwidth
;
298 self
->x
-= self
->w
- theme_bwidth
;
301 self
->y
+= self
->h
- theme_bwidth
;
303 case SlitPos_BottomRight
:
305 self
->y
+= self
->h
- theme_bwidth
;
307 self
->x
+= self
->w
- theme_bwidth
;
312 /* not used for actually sizing shit */
313 self
->w
-= theme_bwidth
* 2;
314 self
->h
-= theme_bwidth
* 2;
316 if (self
->w
> 0 && self
->h
> 0) {
317 RECT_SET(self
->a_frame
->area
, 0, 0, self
->w
, self
->h
);
318 XMoveResizeWindow(ob_display
, self
->frame
,
319 self
->x
, self
->y
, self
->w
, self
->h
);
321 paint(self
->frame
, self
->a_frame
);
322 XMapWindow(ob_display
, self
->frame
);
324 XUnmapWindow(ob_display
, self
->frame
);
327 void slit_app_configure(SlitApp
*app
, int w
, int h
)
331 slit_configure(app
->slit
);