SRC += Sidebar.c
SRC += xdnd.c
SRC += playlist.c
+SRC += nfont.c
OBJ = $(SRC:%.c=$(BUILD_ROOT)/build/application/%.$(OBJ_EXT))
#include <errno.h>
#include "xdnd.h"
+#include "utils.h"
+#include "playlist.h"
static void sidebar_class_init(void);
static void sidebar_init(Widget request, Widget neww, ArgList args, Cardinal *num_args) {
+ Sidebar sb = (Sidebar)neww;
+ XftColor fg, bg;
+ fg.color.red = 0;
+ fg.color.green = 0;
+ fg.color.blue = 0;
+ fg.color.alpha = 0xFFFF;
+
+ bg.color.red = 0xFFFF;
+ bg.color.green = 0xFFFF;
+ bg.color.blue = 0xFFFF;
+ bg.color.alpha = 0xFFFF;
+
+ sb->sidebar.fg = fg;
+ sb->sidebar.bg = bg;
+
+ sb->sidebar.font = FontFromName(XtDisplay(neww), "Sans:size=11");
+ if(!sb->sidebar.font) {
+ fprintf(stderr, "Cannot open font.\nAbort.\n");
+ exit(-1);
+ }
}
XdndInit(XtDisplay(widget), XtWidgetToApplicationContext(widget), sidebar_xdnd_callback, widget);
}
XdndEnable(widget);
+
+ Screen *screen = widget->core.screen;
+ Visual *visual = screen->root_visual;
+ for(int i=0;i<screen->ndepths;i++) {
+ Depth d = screen->depths[i];
+ if(d.depth == widget->core.depth) {
+ visual = d.visuals;
+ break;
+ }
+ }
+
+ Sidebar sb = (Sidebar)widget;
+ sb->sidebar.d = XftDrawCreate(
+ XtDisplay(widget),
+ XtWindow(widget),
+ visual,
+ widget->core.colormap);
}
static void sidebar_expose(Widget widget, XEvent *event, Region region) {
printf("expose\n");
Dimension w, h;
XtMakeResizeRequest(widget, 200, 200, &w, &h);
+
+ Sidebar s = (Sidebar)widget;
+
+ XftDrawRect(s->sidebar.d, &s->sidebar.bg, 0, 0, s->core.width, s->core.height);
+
+ int height = 20;
+
+ printf("current track: %d\n", s->sidebar.window->playlist.current_track);
+
+ int i = 0;
+ UCX_FOREACH(elm, s->sidebar.window->playlist.tracks) {
+ char *name = util_resource_name(elm->data);
+ XftColor *cg = &s->sidebar.fg;
+ if(i == s->sidebar.window->playlist.current_track) {
+ XftDrawRect(s->sidebar.d, &s->sidebar.fg, 0, i*height, s->core.width, height);
+ cg = &s->sidebar.bg;
+ }
+
+ XftDrawString8(s->sidebar.d, cg, s->sidebar.font->fonts->font, 10, i*height + 15, (const FcChar8*)name, strlen(name));
+
+ i++;
+ }
}
static Boolean sidebar_set_values(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args) {
printf("xdnd\n");
fflush(stdout);
+ Sidebar s = (Sidebar)cdata;
+
char *urilist = udata;
size_t len = strlen(urilist);
}
path[k] = '\0';
- // add file
- // TODO
+ PlayListAddFile(s->sidebar.window, path);
free(path);
}
{
return XtCreateWidget(name, xnSidebarWidgetClass, parent, arglist, argcount);
}
+
+void SidebarSetWindow(Widget widget, MainWindow *win) {
+ Sidebar sb = (Sidebar)widget;
+ sb->sidebar.window = win;
+}
#include <Xm/PrimitiveP.h>
#include <Xm/ManagerP.h>
+#include "window.h"
+
#ifdef __cplusplus
extern "C" {
#endif
ArgList arglist,
Cardinal argcount);
+void SidebarSetWindow(Widget widget, MainWindow *win);
+
#ifdef __cplusplus
}
#include <Xm/FormP.h>
#include <X11/Intrinsic.h>
#include <Xm/PrimitiveP.h>
+#include "nfont.h"
+
+#include "window.h"
#ifdef __cplusplus
extern "C" {
#endif
-
-typedef struct SidebarData SidebarData;
-struct SidebarData {
- int a;
-};
-
typedef struct SidebarClassPart {
int unused;
} SidebarClassRec;
typedef struct SidebarPart {
- int a; // placeholder
+ XftDraw *d;
+ NFont *font;
+ XftColor fg;
+ XftColor bg;
+
+ MainWindow *window;
} SidebarPart;
typedef struct SidebarRec {
--- /dev/null
+/*
+ * Copyright 2022 Olaf Wintermann
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "nfont.h"
+
+
+/* font list functions */
+
+NFont *FontCreate(Display *dp, FcPattern *pattern)
+{
+ if(!pattern) {
+ return NULL;
+ }
+ FcResult result;
+ pattern = FcPatternDuplicate(pattern);
+ FcPattern *match = XftFontMatch(dp, DefaultScreen(dp), pattern, &result);
+
+ double sz = 0;
+ result = FcPatternGetDouble (pattern, FC_SIZE, 0, &sz);
+ if(result != FcResultMatch) {
+ FcPatternGetDouble (match, FC_SIZE, 0, &sz);
+ }
+
+ XftFont *defaultFont = XftFontOpenPattern(dp, match);
+ if(!defaultFont) {
+ FcPatternDestroy(match);
+ return NULL;
+ }
+
+ NFont *font = malloc(sizeof(NFont));
+ font->display = dp;
+ font->pattern = pattern;
+ font->fail = NULL;
+ font->size = sz;
+ font->ref = 1;
+
+ NFontList *list = malloc(sizeof(NFontList));
+ list->font = defaultFont;
+ list->next = NULL;
+ font->fonts = list;
+
+ return font;
+}
+
+NFont *FontFromName(Display *dp, const char *name)
+{
+ FcPattern *pattern = FcNameParse((FcChar8*)name);
+ if(!pattern) {
+ return NULL;
+ }
+ NFont *font = FontCreate(dp, pattern);
+ FcPatternDestroy(pattern);
+ return font;
+}
+
+XftFont *FontListAddFontForChar(NFont *f, FcChar32 c)
+{
+ /* charset for char c */
+ FcCharSet *charset = FcCharSetCreate();
+ FcValue value;
+ value.type = FcTypeCharSet;
+ value.u.c = charset;
+ FcCharSetAddChar(charset, c);
+ if(!FcCharSetHasChar(charset, c)) {
+ FcCharSetDestroy(charset);
+ return f->fonts->font;
+ }
+
+ /* font lookup based on the NFont pattern */
+ FcPattern *pattern = FcPatternDuplicate(f->pattern);
+ FcPatternAdd(pattern, FC_CHARSET, value, 0);
+ FcResult result;
+ FcPattern *match = XftFontMatch (
+ f->display, DefaultScreen(f->display), pattern, &result);
+ if(!match) {
+ FcPatternDestroy(pattern);
+ FontAddFail(f, charset);
+ return f->fonts->font;
+ }
+
+ XftFont *newFont = XftFontOpenPattern(f->display, match);
+ if(!newFont || !FcCharSetHasChar(newFont->charset, c)) {
+ FcPatternDestroy(pattern);
+ FcPatternDestroy(match);
+ if(newFont) {
+ XftFontClose(f->display, newFont);
+ }
+ FontAddFail(f, charset);
+ return f->fonts->font;
+ }
+
+ FcCharSetDestroy(charset);
+
+ NFontList *newElm = malloc(sizeof(NFontList));
+ newElm->font = newFont;
+ newElm->next = NULL;
+
+ NFontList *elm = f->fonts;
+ NFontList *last = NULL;
+ while(elm) {
+ last = elm;
+ elm = elm->next;
+ }
+ last->next = newElm;
+
+
+ return newFont;
+}
+
+XftFont *FindFont(NFont *f, FcChar32 c)
+{
+ if(c < 128) {
+ return f->fonts->font;
+ }
+
+ /* make sure the char is not in the fail list, because we don't
+ * want to retry font lookups */
+ NCharSetList *fail = f->fail;
+ while(fail) {
+ if(FcCharSetHasChar(fail->charset, c)) {
+ return f->fonts->font;
+ }
+ fail = fail->next;
+
+ }
+
+ /* find a font that has this char */
+ NFontList *elm = f->fonts;
+ while(elm) {
+ if(FcCharSetHasChar(elm->font->charset, c)) {
+ return elm->font;
+ }
+ elm = elm->next;
+ }
+
+ /* open a new font for this char */
+ return FontListAddFontForChar(f, c);
+}
+
+XftFont *FontDefault(NFont *f) {
+ return f->fonts->font;
+}
+
+void FontAddFail(NFont *f, FcCharSet *c)
+{
+ NCharSetList *elm = f->fail;
+ NCharSetList *last = elm;
+ while(elm) {
+ last = elm;
+ elm = elm->next;
+ }
+
+ NCharSetList *newElm = malloc(sizeof(NCharSetList));
+ newElm->charset = c;
+ newElm->next = NULL;
+ if(last) {
+ last->next = newElm;
+ } else {
+ f->fail = newElm;
+ }
+}
+
+void FontDestroy(NFont *f)
+{
+ NCharSetList *c = f->fail;
+ NCharSetList *nc;
+ while(c) {
+ FcCharSetDestroy(c->charset);
+ nc = c->next;
+ free(c);
+ c = nc;
+ }
+
+ NFontList *l = f->fonts;
+ NFontList *nl;
+ while(l) {
+ XftFontClose(f->display, l->font);
+ nl = l->next;
+ free(nl);
+ l = nl;
+ }
+
+ FcPatternDestroy(f->pattern);
+ free(f);
+}
+
+NFont *FontRef(NFont *font) {
+ font->ref++;
+ return font;
+}
+
+void FontUnref(NFont *font) {
+ if(--font->ref == 0) {
+ FontDestroy(font);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2022 Olaf Wintermann
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef NFONT_H
+#define NFONT_H
+
+#include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct NFont NFont;
+typedef struct NFontList NFontList;
+typedef struct NCharSetList NCharSetList;
+struct NFontList {
+ XftFont *font;
+ NFontList *next;
+};
+
+struct NCharSetList {
+ FcCharSet *charset;
+ NCharSetList *next;
+};
+
+struct NFont {
+ NFontList *fonts;
+ NCharSetList *fail;
+ Display *display;
+ FcPattern *pattern;
+ double size;
+ unsigned int ref;
+};
+
+NFont *FontCreate(Display *dp, FcPattern *pattern);
+NFont *FontFromName(Display *dp, const char *name);
+XftFont *FontListAddFontForChar(NFont *f, FcChar32 c);
+XftFont *FontDefault(NFont *f);
+void FontAddFail(NFont *f, FcCharSet *c);
+XftFont *FindFont(NFont *f, FcChar32 c);
+void FontDestroy(NFont *f);
+NFont *FontRef(NFont *font);
+void FontUnref(NFont *font);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NFONT_H */
+
XtSetArg(args[n], XmNtopWidget, window->menubar); n++;
XtSetArg(args[n], XmNwidth, 300); n++;
window->sidebar = CreateSidebar(container, "sidebar", args, n);
+ SidebarSetWindow(window->sidebar, window);
//XtManageChild(window->sidebar);
n = 0;
# DEPENDENCIES
#
+dependency_xft()
+{
+ printf "checking for xft... "
+ # dependency xft
+ while true
+ do
+ if [ -z "$PKG_CONFIG" ]; then
+ break
+ fi
+ $PKG_CONFIG xft
+ if [ $? -ne 0 ] ; then
+ break
+ fi
+ CFLAGS="$CFLAGS `$PKG_CONFIG --cflags xft`"
+ LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs xft`"
+ $PKG_CONFIG fontconfig
+ if [ $? -ne 0 ] ; then
+ break
+ fi
+ CFLAGS="$CFLAGS `$PKG_CONFIG --cflags fontconfig`"
+ LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs fontconfig`"
+ echo yes
+ return 0
+ done
+
+ echo no
+ return 1
+}
dependency_motif()
{
printf "checking for motif... "
DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED motif "
ERROR=1
fi
+dependency_xft
+if [ $? -ne 0 ]; then
+ DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED xft "
+ ERROR=1
+fi
# Features
<make>PACKAGE_SCRIPT = package_unix.sh</make>
</dependency>
+ <dependency name="xft">
+ <pkgconfig>xft</pkgconfig>
+ <pkgconfig>fontconfig</pkgconfig>
+ </dependency>
+
<dependency>
<ldflags>-lpthread</ldflags>
</dependency>
</dependency>
<target name="app">
- <dependencies>motif</dependencies>
+ <dependencies>motif,xft</dependencies>
</target>
</project>