openbox/openbox/popup.c

235 lines
6.5 KiB
C
Raw Normal View History

#include "popup.h"
2003-05-09 19:58:08 +00:00
#include "openbox.h"
#include "frame.h"
#include "client.h"
#include "window.h"
#include "stacking.h"
2003-05-09 19:58:08 +00:00
#include "render/render.h"
#include "render/theme.h"
struct _ObPopup
{
ObWindow obwin;
2003-05-09 19:58:08 +00:00
Window bg;
2003-05-09 19:58:08 +00:00
Window icon;
Window text;
gboolean hasicon;
RrAppearance *a_bg;
RrAppearance *a_icon;
RrAppearance *a_text;
gint gravity;
gint x;
gint y;
gint w;
gint h;
gboolean mapped;
};
2003-05-09 19:58:08 +00:00
Popup *popup_new(gboolean hasicon)
{
XSetWindowAttributes attrib;
2003-05-09 19:58:08 +00:00
Popup *self = g_new(Popup, 1);
self->obwin.type = Window_Internal;
2003-05-09 19:58:08 +00:00
self->hasicon = hasicon;
self->a_text = NULL;
self->gravity = NorthWestGravity;
self->x = self->y = self->w = self->h = 0;
self->mapped = FALSE;
self->a_bg = self->a_icon = self->a_text = NULL;
attrib.override_redirect = True;
self->bg = XCreateWindow(ob_display, ob_root,
0, 0, 1, 1, 0, RrDepth(ob_rr_inst),
InputOutput, RrVisual(ob_rr_inst),
CWOverrideRedirect, &attrib);
self->text = XCreateWindow(ob_display, self->bg,
0, 0, 1, 1, 0, RrDepth(ob_rr_inst),
InputOutput, RrVisual(ob_rr_inst), 0, NULL);
if (self->hasicon)
self->icon = XCreateWindow(ob_display, self->bg,
0, 0, 1, 1, 0,
RrDepth(ob_rr_inst), InputOutput,
RrVisual(ob_rr_inst), 0, NULL);
XMapWindow(ob_display, self->text);
XMapWindow(ob_display, self->icon);
stacking_add(INTERNAL_AS_WINDOW(self));
2003-05-09 19:58:08 +00:00
return self;
}
void popup_free(Popup *self)
{
if (self) {
2003-05-09 19:58:08 +00:00
XDestroyWindow(ob_display, self->bg);
XDestroyWindow(ob_display, self->text);
XDestroyWindow(ob_display, self->icon);
RrAppearanceFree(self->a_bg);
RrAppearanceFree(self->a_icon);
RrAppearanceFree(self->a_text);
stacking_remove(self);
g_free(self);
}
2003-05-09 19:58:08 +00:00
}
void popup_position(Popup *self, gint gravity, gint x, gint y)
2003-05-09 19:58:08 +00:00
{
self->gravity = gravity;
self->x = x;
self->y = y;
}
void popup_size(Popup *self, gint w, gint h)
2003-05-09 19:58:08 +00:00
{
self->w = w;
self->h = h;
}
void popup_size_to_string(Popup *self, gchar *text)
2003-05-09 19:58:08 +00:00
{
gint textw, texth;
gint iconw;
2003-05-09 19:58:08 +00:00
if (!self->a_text)
2003-06-21 01:53:26 +00:00
self->a_text = RrAppearanceCopy(ob_rr_theme->app_hilite_label);
2003-05-09 19:58:08 +00:00
self->a_text->texture[0].data.text.string = text;
RrMinsize(self->a_text, &textw, &texth);
2003-06-21 01:53:26 +00:00
textw += ob_rr_theme->bevel * 2;
texth += ob_rr_theme->bevel * 2;
2003-05-09 19:58:08 +00:00
2003-06-21 01:53:26 +00:00
self->h = texth + ob_rr_theme->bevel * 2;
2003-05-09 19:58:08 +00:00
iconw = (self->hasicon ? texth : 0);
2003-06-21 01:53:26 +00:00
self->w = textw + iconw + ob_rr_theme->bevel * (self->hasicon ? 3 : 2);
2003-05-09 19:58:08 +00:00
}
void popup_show(Popup *self, gchar *text, ObClientIcon *icon)
2003-05-09 19:58:08 +00:00
{
gint x, y, w, h;
gint textw, texth;
gint iconw;
2003-05-09 19:58:08 +00:00
/* create the shit if needed */
if (!self->a_bg)
2003-06-21 01:53:26 +00:00
self->a_bg = RrAppearanceCopy(ob_rr_theme->app_hilite_bg);
if (self->hasicon && !self->a_icon)
self->a_icon = RrAppearanceCopy(ob_rr_theme->app_icon);
2003-05-09 19:58:08 +00:00
if (!self->a_text)
2003-06-21 01:53:26 +00:00
self->a_text = RrAppearanceCopy(ob_rr_theme->app_hilite_label);
2003-05-09 19:58:08 +00:00
XSetWindowBorderWidth(ob_display, self->bg, ob_rr_theme->bwidth);
XSetWindowBorder(ob_display, self->bg, ob_rr_theme->b_color->pixel);
2003-05-09 19:58:08 +00:00
/* set up the textures */
self->a_text->texture[0].data.text.string = text;
if (self->hasicon) {
if (icon) {
self->a_icon->texture[0].type = RR_TEXTURE_RGBA;
2003-05-09 19:58:08 +00:00
self->a_icon->texture[0].data.rgba.width = icon->width;
self->a_icon->texture[0].data.rgba.height = icon->height;
self->a_icon->texture[0].data.rgba.data = icon->data;
} else
self->a_icon->texture[0].type = RR_TEXTURE_NONE;
2003-05-09 19:58:08 +00:00
}
/* measure the shit out */
RrMinsize(self->a_text, &textw, &texth);
2003-06-21 01:53:26 +00:00
textw += ob_rr_theme->bevel * 2;
texth += ob_rr_theme->bevel * 2;
2003-05-09 19:58:08 +00:00
/* set the sizes up and reget the text sizes from the calculated
outer sizes */
if (self->h) {
h = self->h;
2003-06-21 01:53:26 +00:00
texth = h - (ob_rr_theme->bevel * 2);
2003-05-09 19:58:08 +00:00
} else
2003-06-21 01:53:26 +00:00
h = texth + ob_rr_theme->bevel * 2;
2003-05-09 19:58:08 +00:00
iconw = (self->hasicon ? texth : 0);
if (self->w) {
w = self->w;
2003-06-21 01:53:26 +00:00
textw = w - (iconw + ob_rr_theme->bevel * (self->hasicon ? 3 : 2));
2003-05-09 19:58:08 +00:00
} else
2003-06-21 01:53:26 +00:00
w = textw + iconw + ob_rr_theme->bevel * (self->hasicon ? 3 : 2);
2003-05-09 19:58:08 +00:00
/* sanity checks to avoid crashes! */
if (w < 1) w = 1;
if (h < 1) h = 1;
if (textw < 1) textw = 1;
if (texth < 1) texth = 1;
/* set up the x coord */
x = self->x;
switch (self->gravity) {
case NorthGravity:
case CenterGravity:
case SouthGravity:
x -= w / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
x -= w;
break;
}
/* set up the y coord */
y = self->y;
switch (self->gravity) {
case WestGravity:
case CenterGravity:
case EastGravity:
y -= h / 2;
break;
case SouthWestGravity:
case SouthGravity:
case SouthEastGravity:
y -= h;
break;
}
/* set the windows/appearances up */
XMoveResizeWindow(ob_display, self->bg, x, y, w, h);
2003-06-20 00:05:51 +00:00
self->a_text->surface.parent = self->a_bg;
self->a_text->surface.parentx = iconw +
2003-06-21 01:53:26 +00:00
ob_rr_theme->bevel * (self->hasicon ? 2 : 1);
self->a_text->surface.parenty = ob_rr_theme->bevel;
2003-05-09 19:58:08 +00:00
XMoveResizeWindow(ob_display, self->text,
2003-06-21 01:53:26 +00:00
iconw + ob_rr_theme->bevel * (self->hasicon ? 2 : 1),
ob_rr_theme->bevel, textw, texth);
2003-05-09 19:58:08 +00:00
if (self->hasicon) {
if (iconw < 1) iconw = 1; /* sanity check for crashes */
2003-06-20 00:05:51 +00:00
self->a_icon->surface.parent = self->a_bg;
2003-06-21 01:53:26 +00:00
self->a_icon->surface.parentx = ob_rr_theme->bevel;
self->a_icon->surface.parenty = ob_rr_theme->bevel;
2003-05-09 19:58:08 +00:00
XMoveResizeWindow(ob_display, self->icon,
2003-06-21 01:53:26 +00:00
ob_rr_theme->bevel, ob_rr_theme->bevel,
iconw, texth);
2003-05-09 19:58:08 +00:00
}
RrPaint(self->a_bg, self->bg, w, h);
RrPaint(self->a_text, self->text, textw, texth);
2003-05-09 19:58:08 +00:00
if (self->hasicon)
RrPaint(self->a_icon, self->icon, iconw, texth);
2003-05-09 19:58:08 +00:00
if (!self->mapped) {
XMapWindow(ob_display, self->bg);
stacking_raise(INTERNAL_AS_WINDOW(self));
self->mapped = TRUE;
}
2003-05-09 19:58:08 +00:00
}
void popup_hide(Popup *self)
{
if (self->mapped) {
XUnmapWindow(ob_display, self->bg);
self->mapped = FALSE;
}
2003-05-09 19:58:08 +00:00
}