summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
Diffstat (limited to 'openbox')
-rw-r--r--openbox/openbox.c3
-rw-r--r--openbox/popup.c215
-rw-r--r--openbox/popup.h25
3 files changed, 242 insertions, 1 deletions
diff --git a/openbox/openbox.c b/openbox/openbox.c
index 304d52c6..8c599c4a 100644
--- a/openbox/openbox.c
+++ b/openbox/openbox.c
@@ -271,7 +271,8 @@ void signal_handler(const ObEvent *e, void *data)
case SIGFPE:
case SIGSEGV:
- g_error("Caught signal %d. Aborting and dumping core.", s);
+ g_message("Caught signal %d. Aborting and dumping core.", s);
+ abort();
}
}
diff --git a/openbox/popup.c b/openbox/popup.c
new file mode 100644
index 00000000..f20aa006
--- /dev/null
+++ b/openbox/popup.c
@@ -0,0 +1,215 @@
+#include "openbox.h"
+#include "frame.h"
+#include "render/render.h"
+#include "render/theme.h"
+
+typedef struct Popup {
+ gboolean hasicon;
+ Window bg;
+ Window icon;
+ Window text;
+ Appearance *a_bg;
+ Appearance *a_icon;
+ Appearance *a_text;
+ int gravity;
+ int x;
+ int y;
+ int w;
+ int h;
+} Popup;
+
+Popup *popup_new(gboolean hasicon)
+{
+ Popup *self = g_new(Popup, 1);
+ self->hasicon = hasicon;
+ self->bg = None;
+ self->a_text = NULL;
+ self->gravity = NorthWestGravity;
+ self->x = self->y = self->w = self->h = 0;
+ return self;
+}
+
+void popup_free(Popup *self)
+{
+ if (self->bg) {
+ XDestroyWindow(ob_display, self->bg);
+ XDestroyWindow(ob_display, self->text);
+ XDestroyWindow(ob_display, self->icon);
+ appearance_free(self->a_bg);
+ if (self->hasicon)
+ appearance_free(self->a_icon);
+ }
+ if (self->a_text)
+ appearance_free(self->a_text);
+ g_free(self);
+}
+
+void popup_position(Popup *self, int gravity, int x, int y)
+{
+ self->gravity = gravity;
+ self->x = x;
+ self->y = y;
+}
+
+void popup_size(Popup *self, int w, int h)
+{
+ self->w = w;
+ self->h = h;
+}
+
+void popup_size_to_string(Popup *self, char *text)
+{
+ int textw, texth;
+ int iconw;
+
+ if (!self->a_text)
+ self->a_text = appearance_copy(theme_app_hilite_label);
+
+ self->a_text->texture[0].data.text.string = text;
+ appearance_minsize(self->a_text, &textw, &texth);
+ textw += theme_bevel * 2;
+ texth += theme_bevel * 2;
+
+ self->h = texth + theme_bevel * 2;
+ iconw = (self->hasicon ? texth : 0);
+ self->w = textw + iconw + theme_bevel * 3;
+}
+
+void popup_show(Popup *self, char *text, Icon *icon)
+{
+ XSetWindowAttributes attrib;
+ int x, y, w, h;
+ int textw, texth;
+ int iconw;
+
+ /* create the shit if needed */
+ if (!self->bg) {
+ attrib.override_redirect = True;
+ self->bg = XCreateWindow(ob_display, ob_root,
+ 0, 0, 1, 1, 0, render_depth, InputOutput,
+ render_visual, CWOverrideRedirect, &attrib);
+
+ XSetWindowBorderWidth(ob_display, self->bg, theme_bwidth);
+ XSetWindowBorder(ob_display, self->bg, theme_b_color->pixel);
+
+ self->text = XCreateWindow(ob_display, self->bg,
+ 0, 0, 1, 1, 0, render_depth, InputOutput,
+ render_visual, 0, NULL);
+ if (self->hasicon)
+ self->icon = XCreateWindow(ob_display, self->bg,
+ 0, 0, 1, 1, 0,
+ render_depth, InputOutput,
+ render_visual, 0, NULL);
+
+ XMapWindow(ob_display, self->text);
+ XMapWindow(ob_display, self->icon);
+
+ self->a_bg = appearance_copy(theme_app_hilite_bg);
+ if (self->hasicon)
+ self->a_icon = appearance_copy(theme_app_icon);
+ }
+ if (!self->a_text)
+ self->a_text = appearance_copy(theme_app_hilite_label);
+
+ /* set up the textures */
+ self->a_text->texture[0].data.text.string = text;
+ if (self->hasicon) {
+ if (icon) {
+ self->a_icon->texture[0].type = RGBA;
+ 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 = NoTexture;
+ }
+
+ /* measure the shit out */
+ appearance_minsize(self->a_text, &textw, &texth);
+ textw += theme_bevel * 2;
+ texth += theme_bevel * 2;
+
+ /* set the sizes up and reget the text sizes from the calculated
+ outer sizes */
+ if (self->h) {
+ h = self->h;
+ texth = h - (theme_bevel * 2);
+ } else
+ h = texth + theme_bevel * 2;
+ iconw = (self->hasicon ? texth : 0);
+ if (self->w) {
+ w = self->w;
+ textw = w - (iconw + theme_bevel * 3);
+ } else
+ w = textw + iconw + theme_bevel * 3;
+ /* 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 */
+ RECT_SET(self->a_bg->area, 0, 0, w, h);
+ XMoveResizeWindow(ob_display, self->bg, x, y, w, h);
+
+ RECT_SET(self->a_text->area, 0, 0, textw, texth);
+ RECT_SET(self->a_text->texture[0].position, theme_bevel, theme_bevel,
+ textw - theme_bevel * 2, texth - theme_bevel * 2);
+ self->a_text->surface.data.planar.parent = self->a_bg;
+ self->a_text->surface.data.planar.parentx = iconw + theme_bevel * 2;
+ self->a_text->surface.data.planar.parenty = theme_bevel;
+ XMoveResizeWindow(ob_display, self->text,
+ iconw + theme_bevel * 2, theme_bevel, textw, texth);
+
+ if (self->hasicon) {
+ if (iconw < 1) iconw = 1; /* sanity check for crashes */
+ RECT_SET(self->a_icon->area, 0, 0, iconw, texth);
+ RECT_SET(self->a_icon->texture[0].position, 0, 0, iconw, texth);
+ self->a_icon->surface.data.planar.parent = self->a_bg;
+ self->a_icon->surface.data.planar.parentx = theme_bevel;
+ self->a_icon->surface.data.planar.parenty = theme_bevel;
+ XMoveResizeWindow(ob_display, self->icon,
+ theme_bevel, theme_bevel, iconw, texth);
+ }
+
+ paint(self->bg, self->a_bg);
+ paint(self->text, self->a_text);
+ if (self->hasicon)
+ paint(self->icon, self->a_icon);
+
+ XMapWindow(ob_display, self->bg);
+}
+
+void popup_hide(Popup *self)
+{
+ XUnmapWindow(ob_display, self->bg);
+}
diff --git a/openbox/popup.h b/openbox/popup.h
new file mode 100644
index 00000000..f26bedd9
--- /dev/null
+++ b/openbox/popup.h
@@ -0,0 +1,25 @@
+#ifndef __popup_h
+#define __popup_h
+
+#include "frame.h"
+
+typedef struct Popup Popup;
+
+Popup *popup_new(gboolean hasicon);
+void popup_free(Popup *self);
+
+/*! Position the popup. The gravity rules are not the same X uses for windows,
+ instead of the position being the top-left of the window, the gravity
+ specifies which corner of the popup will be placed at the given coords.
+ Static and Forget gravity are equivilent to NorthWest.
+*/
+void popup_position(Popup *self, int gravity, int x, int y);
+/*! Set the sizes for the popup. When set to 0, the size will be based on
+ the text size. */
+void popup_size(Popup *self, int w, int h);
+void popup_size_to_string(Popup *self, char *text);
+
+void popup_show(Popup *self, char *text, Icon *icon);
+void popup_hide(Popup *self);
+
+#endif