1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 popup.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
26 #include "render/render.h"
27 #include "render/theme.h"
29 ObPopup
*popup_new(gboolean hasicon
)
31 XSetWindowAttributes attrib
;
32 ObPopup
*self
= g_new0(ObPopup
, 1);
34 self
->obwin
.type
= Window_Internal
;
35 self
->hasicon
= hasicon
;
36 self
->gravity
= NorthWestGravity
;
37 self
->x
= self
->y
= self
->w
= self
->h
= 0;
38 self
->a_bg
= RrAppearanceCopy(ob_rr_theme
->app_hilite_bg
);
39 self
->a_text
= RrAppearanceCopy(ob_rr_theme
->app_hilite_label
);
41 attrib
.override_redirect
= True
;
42 self
->bg
= XCreateWindow(ob_display
, RootWindow(ob_display
, ob_screen
),
43 0, 0, 1, 1, 0, RrDepth(ob_rr_inst
),
44 InputOutput
, RrVisual(ob_rr_inst
),
45 CWOverrideRedirect
, &attrib
);
47 self
->text
= XCreateWindow(ob_display
, self
->bg
,
48 0, 0, 1, 1, 0, RrDepth(ob_rr_inst
),
49 InputOutput
, RrVisual(ob_rr_inst
), 0, NULL
);
51 XMapWindow(ob_display
, self
->text
);
53 stacking_add(INTERNAL_AS_WINDOW(self
));
57 void popup_free(ObPopup
*self
)
60 XDestroyWindow(ob_display
, self
->bg
);
61 XDestroyWindow(ob_display
, self
->text
);
62 RrAppearanceFree(self
->a_bg
);
63 RrAppearanceFree(self
->a_text
);
64 stacking_remove(self
);
69 void popup_position(ObPopup
*self
, gint gravity
, gint x
, gint y
)
71 self
->gravity
= gravity
;
76 void popup_size(ObPopup
*self
, gint w
, gint h
)
82 void popup_size_to_string(ObPopup
*self
, gchar
*text
)
87 self
->a_text
->texture
[0].data
.text
.string
= text
;
88 RrMinsize(self
->a_text
, &textw
, &texth
);
89 /*XXX textw += ob_rr_theme->bevel * 2;*/
90 texth
+= ob_rr_theme
->padding
* 2;
92 self
->h
= texth
+ ob_rr_theme
->padding
* 2;
93 iconw
= (self
->hasicon
? texth
: 0);
94 self
->w
= textw
+ iconw
+ ob_rr_theme
->padding
* (self
->hasicon
? 3 : 2);
97 void popup_set_text_align(ObPopup
*self
, RrJustify align
)
99 self
->a_text
->texture
[0].data
.text
.justify
= align
;
102 void popup_show(ObPopup
*self
, gchar
*text
)
109 RrMargins(self
->a_bg
, &l
, &t
, &r
, &b
);
111 XSetWindowBorderWidth(ob_display
, self
->bg
, ob_rr_theme
->bwidth
);
112 XSetWindowBorder(ob_display
, self
->bg
, ob_rr_theme
->b_color
->pixel
);
114 /* set up the textures */
115 self
->a_text
->texture
[0].data
.text
.string
= text
;
117 /* measure the shit out */
118 RrMinsize(self
->a_text
, &textw
, &texth
);
119 /*XXX textw += ob_rr_theme->padding * 2;*/
120 texth
+= ob_rr_theme
->padding
* 2;
122 /* set the sizes up and reget the text sizes from the calculated
126 texth
= h
- (t
+b
+ ob_rr_theme
->padding
* 2);
128 h
= t
+b
+ texth
+ ob_rr_theme
->padding
* 2;
129 iconw
= (self
->hasicon
? texth
: 0);
132 textw
= w
- (l
+r
+ iconw
+ ob_rr_theme
->padding
*
133 (self
->hasicon
? 3 : 2));
135 w
= l
+r
+ textw
+ iconw
+ ob_rr_theme
->padding
*
136 (self
->hasicon
? 3 : 2);
137 /* sanity checks to avoid crashes! */
140 if (textw
< 1) textw
= 1;
141 if (texth
< 1) texth
= 1;
143 /* set up the x coord */
145 switch (self
->gravity
) {
151 case NorthEastGravity
:
153 case SouthEastGravity
:
158 /* set up the y coord */
160 switch (self
->gravity
) {
166 case SouthWestGravity
:
168 case SouthEastGravity
:
173 /* set the windows/appearances up */
174 XMoveResizeWindow(ob_display
, self
->bg
, x
, y
, w
, h
);
176 self
->a_text
->surface
.parent
= self
->a_bg
;
177 self
->a_text
->surface
.parentx
= l
+ iconw
+
178 ob_rr_theme
->padding
* (self
->hasicon
? 2 : 1);
179 self
->a_text
->surface
.parenty
= t
+ ob_rr_theme
->padding
;
180 XMoveResizeWindow(ob_display
, self
->text
,
181 l
+ iconw
+ ob_rr_theme
->padding
*
182 (self
->hasicon
? 2 : 1),
183 t
+ ob_rr_theme
->padding
, textw
, texth
);
185 RrPaint(self
->a_bg
, self
->bg
, w
, h
);
186 RrPaint(self
->a_text
, self
->text
, textw
, texth
);
189 if (iconw
< 1) iconw
= 1; /* sanity check for crashes */
191 self
->draw_icon(l
+ ob_rr_theme
->padding
, t
+ ob_rr_theme
->padding
,
192 iconw
, texth
, self
->draw_icon_data
);
196 XMapWindow(ob_display
, self
->bg
);
197 stacking_raise(INTERNAL_AS_WINDOW(self
));
202 void popup_hide(ObPopup
*self
)
205 XUnmapWindow(ob_display
, self
->bg
);
206 self
->mapped
= FALSE
;
210 static void icon_popup_draw_icon(gint x
, gint y
, gint w
, gint h
, gpointer data
)
212 ObIconPopup
*self
= data
;
214 self
->a_icon
->surface
.parent
= self
->popup
->a_bg
;
215 self
->a_icon
->surface
.parentx
= x
;
216 self
->a_icon
->surface
.parenty
= y
;
217 XMoveResizeWindow(ob_display
, self
->icon
, x
, y
, w
, h
);
218 RrPaint(self
->a_icon
, self
->icon
, w
, h
);
221 ObIconPopup
*icon_popup_new()
225 self
= g_new0(ObIconPopup
, 1);
226 self
->popup
= popup_new(TRUE
);
227 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_clear_tex
);
228 self
->icon
= XCreateWindow(ob_display
, self
->popup
->bg
,
230 RrDepth(ob_rr_inst
), InputOutput
,
231 RrVisual(ob_rr_inst
), 0, NULL
);
232 XMapWindow(ob_display
, self
->icon
);
234 self
->popup
->draw_icon
= icon_popup_draw_icon
;
235 self
->popup
->draw_icon_data
= self
;
240 void icon_popup_free(ObIconPopup
*self
)
243 XDestroyWindow(ob_display
, self
->icon
);
244 RrAppearanceFree(self
->a_icon
);
245 popup_free(self
->popup
);
250 void icon_popup_show(ObIconPopup
*self
,
251 gchar
*text
, const ObClientIcon
*icon
)
254 self
->a_icon
->texture
[0].type
= RR_TEXTURE_RGBA
;
255 self
->a_icon
->texture
[0].data
.rgba
.width
= icon
->width
;
256 self
->a_icon
->texture
[0].data
.rgba
.height
= icon
->height
;
257 self
->a_icon
->texture
[0].data
.rgba
.data
= icon
->data
;
259 self
->a_icon
->texture
[0].type
= RR_TEXTURE_NONE
;
261 popup_show(self
->popup
, text
);
264 static void pager_popup_draw_icon(gint px
, gint py
, gint w
, gint h
,
267 ObPagerPopup
*self
= data
;
276 eachw
= (w
- ob_rr_theme
->bwidth
-
277 (screen_desktop_layout
.columns
* ob_rr_theme
->bwidth
))
278 / screen_desktop_layout
.columns
;
279 eachh
= (h
- ob_rr_theme
->bwidth
-
280 (screen_desktop_layout
.rows
* ob_rr_theme
->bwidth
))
281 / screen_desktop_layout
.rows
;
282 /* make them squares */
283 eachw
= eachh
= MIN(eachw
, eachh
);
286 px
+= (w
- (screen_desktop_layout
.columns
* (eachw
+ ob_rr_theme
->bwidth
) +
287 ob_rr_theme
->bwidth
)) / 2;
288 py
+= (h
- (screen_desktop_layout
.rows
* (eachh
+ ob_rr_theme
->bwidth
) +
289 ob_rr_theme
->bwidth
)) / 2;
291 if (eachw
<= 0 || eachh
<= 0)
294 switch (screen_desktop_layout
.start_corner
) {
295 case OB_CORNER_TOPLEFT
:
297 switch (screen_desktop_layout
.orientation
) {
298 case OB_ORIENTATION_HORZ
:
300 vert_inc
= screen_desktop_layout
.columns
;
302 case OB_ORIENTATION_VERT
:
303 horz_inc
= screen_desktop_layout
.rows
;
308 case OB_CORNER_TOPRIGHT
:
309 n
= screen_desktop_layout
.columns
;
310 switch (screen_desktop_layout
.orientation
) {
311 case OB_ORIENTATION_HORZ
:
313 vert_inc
= screen_desktop_layout
.columns
;
315 case OB_ORIENTATION_VERT
:
316 horz_inc
= -screen_desktop_layout
.rows
;
321 case OB_CORNER_BOTTOMLEFT
:
322 n
= screen_desktop_layout
.rows
;
323 switch (screen_desktop_layout
.orientation
) {
324 case OB_ORIENTATION_HORZ
:
326 vert_inc
= -screen_desktop_layout
.columns
;
328 case OB_ORIENTATION_VERT
:
329 horz_inc
= screen_desktop_layout
.rows
;
334 case OB_CORNER_BOTTOMRIGHT
:
336 screen_desktop_layout
.rows
* screen_desktop_layout
.columns
);
337 switch (screen_desktop_layout
.orientation
) {
338 case OB_ORIENTATION_HORZ
:
340 vert_inc
= -screen_desktop_layout
.columns
;
342 case OB_ORIENTATION_VERT
:
343 horz_inc
= -screen_desktop_layout
.rows
;
352 for (r
= 0, y
= 0; r
< screen_desktop_layout
.rows
;
353 ++r
, y
+= eachh
+ ob_rr_theme
->bwidth
)
355 for (c
= 0, x
= 0; c
< screen_desktop_layout
.columns
;
356 ++c
, x
+= eachw
+ ob_rr_theme
->bwidth
)
360 if (i
>= self
->desks
)
363 a
= (n
== self
->curdesk
? self
->hilight
: self
->unhilight
);
365 a
->surface
.parent
= self
->popup
->a_bg
;
366 a
->surface
.parentx
= x
+ px
;
367 a
->surface
.parenty
= y
+ py
;
368 XMoveResizeWindow(ob_display
, self
->wins
[i
],
369 x
+ px
, y
+ py
, eachw
, eachh
);
370 RrPaint(a
, self
->wins
[i
], eachw
, eachh
);
376 n
= rown
+= vert_inc
;
380 ObPagerPopup
*pager_popup_new()
384 self
= g_new(ObPagerPopup
, 1);
385 self
->popup
= popup_new(TRUE
);
388 self
->wins
= g_new(Window
, self
->desks
);
389 self
->hilight
= RrAppearanceCopy(ob_rr_theme
->app_hilite_fg
);
390 self
->unhilight
= RrAppearanceCopy(ob_rr_theme
->app_unhilite_fg
);
392 self
->popup
->draw_icon
= pager_popup_draw_icon
;
393 self
->popup
->draw_icon_data
= self
;
398 void pager_popup_free(ObPagerPopup
*self
)
403 for (i
= 0; i
< self
->desks
; ++i
)
404 XDestroyWindow(ob_display
, self
->wins
[i
]);
406 RrAppearanceFree(self
->hilight
);
407 RrAppearanceFree(self
->unhilight
);
408 popup_free(self
->popup
);
413 void pager_popup_show(ObPagerPopup
*self
, gchar
*text
, guint desk
)
417 if (screen_num_desktops
< self
->desks
)
418 for (i
= screen_num_desktops
; i
< self
->desks
; ++i
)
419 XDestroyWindow(ob_display
, self
->wins
[i
]);
421 if (screen_num_desktops
!= self
->desks
)
422 self
->wins
= g_renew(Window
, self
->wins
, screen_num_desktops
);
424 if (screen_num_desktops
> self
->desks
)
425 for (i
= self
->desks
; i
< screen_num_desktops
; ++i
) {
426 XSetWindowAttributes attr
;
428 attr
.border_pixel
= RrColorPixel(ob_rr_theme
->b_color
);
429 self
->wins
[i
] = XCreateWindow(ob_display
, self
->popup
->bg
,
430 0, 0, 1, 1, ob_rr_theme
->bwidth
,
431 RrDepth(ob_rr_inst
), InputOutput
,
432 RrVisual(ob_rr_inst
), CWBorderPixel
,
434 XMapWindow(ob_display
, self
->wins
[i
]);
437 self
->desks
= screen_num_desktops
;
438 self
->curdesk
= desk
;
440 popup_show(self
->popup
, text
);