/* * Copyright: Robert Carr < racarr@beryl-project.org > GPLv2 and all that other stuff will add a real license in a bit * Authors: Robert Carr * Guillaume Seguin * Quinn Storm */ #include #include #include #include #include #include #include #include #include #include #include #include #include "bdm.h" #include #include static void renderImage(cairo_t * cr, BDMImage * image, ScreenArea * area) { cairo_set_source_rgba(cr,0,0,0,0); cairo_paint(cr); cairo_save(cr); gdk_cairo_set_source_pixbuf(cr,image->pixbuf,0,0); int widx = image->widget->attrib->x; int widy = image->widget->attrib->y; int x = image->attrib->x; int y = image->attrib->y; int width = image->pixW; int height = image->pixH; cairo_set_operator(cr,image->attrib->cairoOperator); cairo_scale(cr,(float)image->attrib->width/image->pixW,image->attrib->height/(float)image->pixH); cairo_rotate(cr,image->attrib->xrot); cairo_rectangle(cr,widx+x,widy+y,widx+x+width,widy+y+height); cairo_fill(cr); cairo_stroke(cr); cairo_paint_with_alpha(cr,image->attrib->alpha); cairo_restore(cr); } static void updateFont (BDMText * text) { if (text->font != NULL) pango_font_description_free (text->font); text->font = pango_font_description_new (); pango_font_description_set_family (text->font, text->family); pango_font_description_set_absolute_size (text->font, text->size * PANGO_SCALE); pango_font_description_set_style (text->font, PANGO_STYLE_NORMAL); if (text->style & TEXT_STYLE_BOLD) pango_font_description_set_weight (text->font, PANGO_WEIGHT_BOLD); if (text->style & TEXT_STYLE_ITALIC) pango_font_description_set_style (text->font, PANGO_STYLE_ITALIC); } static void renderText (cairo_t * cr, BDMText * text, ScreenArea * area) { PangoLayout *layout; int w, h; if (text->attrib->updateFont) updateFont (text); layout = pango_cairo_create_layout (cr); if (!layout) { fprintf (stderr, "Error: Couldn't create pango layout\n"); return; } pango_layout_set_font_description (layout, text->font); if (text->ellipsize) pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); pango_layout_set_text (layout, text->text, -1); pango_cairo_update_layout (cr, layout); cairo_set_source_rgba(cr,0,0,0,0); cairo_paint(cr); cairo_save(cr); cairo_set_operator (cr, text->attrib->cairoOperator); pango_layout_get_pixel_size (layout, &w, &h); cairo_scale (cr, (float)text->attrib->width/(float)w, (float)text->attrib->height/(float)h); cairo_rotate(cr,text->attrib->xrot); cairo_set_source_rgba (cr, text->color[0] / 65535.0, text->color[1] / 65535.0, text->color[2] / 65535.0, text->color[3] / 65535.0); cairo_move_to (cr, text->widget->attrib->x + text->attrib->x, text->widget->attrib->y + text->attrib->y); pango_cairo_show_layout (cr, layout); cairo_paint_with_alpha(cr, text->attrib->alpha); g_object_unref (layout); cairo_restore (cr); } static void updateWidgets(cairo_t * cr,ScreenArea * area) { GSList * widgets; BDMWidget * widget; BDMImage * image; BDMText * text; for (widgets=Widgets;widgets;widgets=widgets->next) { widget = widgets->data; widget->updateWidget(); if (widget->attrib->needsPainting) { for (image = widget->images; image; image = image->next) { if (image) if (image->attrib->needsPainting) renderImage(cr,image,area); } for (text = widget->texts; text; text=text->next) { if (text) if (text->attrib->needsPainting) renderText(cr,text,area); } } } } static void render_pixbuf (cairo_t * cr, ScreenArea * area) { cairo_set_source_rgba(cr,0,0,0,0); cairo_paint(cr); cairo_save(cr); cairo_scale(cr,((double)area->width/(double)area->wallpaper->data.pixbuf.width), ((double)area->height/(double)area->wallpaper->data.pixbuf.height)); gdk_cairo_set_source_pixbuf(cr,area->wallpaper->data.pixbuf.source,0,0); cairo_rectangle(cr, 0, 0, area->width,area->height); cairo_fill(cr); cairo_stroke(cr); cairo_paint_with_alpha(cr,area->alpha); cairo_restore(cr); } static void render (ScreenArea * area) { cairo_t * cr; cr = gdk_cairo_create(GTK_WIDGET(area->window)->window); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); switch(area->wallpaper->type) { case WALLPAPER_TYPE_PIXBUF: render_pixbuf(cr,area); break; default: break; } updateWidgets(cr, area); cairo_destroy (cr); } static gboolean on_alpha_window_expose(GtkWidget * widget, GdkEventExpose * expose, ScreenArea * area) { render(area); } static void on_alpha_screen_changed(GtkWidget * widget, GdkScreen * pOldScreen, GtkWidget * label) { GdkScreen * pScreen = gtk_window_get_screen(GTK_WINDOW(widget)); GdkColormap * pColormap = gdk_screen_get_rgba_colormap (pScreen); gtk_widget_set_colormap(widget,pColormap); } static void initPaintAttribs (BDMPaintAttribs * attribs) { attribs->width = attribs->height = attribs->x = attribs->y = attribs->xrot = 100; attribs->needsPainting = attribs->updateFont = 0; attribs->alpha = 1.0f; attribs->cairoOperator = CAIRO_OPERATOR_OVER; } static int loadWidget (char * path) { void * widgetDL; widgetDL = dlopen (path, RTLD_NOW); if (!widgetDL) return 0; BDMWidget * widget = malloc (sizeof (BDMWidget)); if (!widget) { dlclose (widgetDL); return 0; } widget->attrib = malloc (sizeof (BDMPaintAttribs)); if (!widget->attrib) { free (widget); dlclose (widgetDL); return 0; } initPaintAttribs (widget->attrib); widget->initWidget = dlsym (widgetDL, "init"); widget->finiWidget = dlsym (widgetDL, "fini"); widget->updateWidget = dlsym (widgetDL, "update"); widget->getImages = dlsym (widgetDL, "getImages"); widget->getTexts = dlsym (widgetDL, "getTexts"); widget->handleEvent = dlsym (widgetDL, "handleEvent"); widget->prev = (BDMWidget *) g_slist_last (Widgets); if (widget->prev) widget->prev->next = widget; widget->next = NULL; widget->initWidget (widget); widget->images = widget->getImages (); widget->texts = widget->getTexts (); /* TODO: Find how we want widget->screenArea set */ Widgets = g_slist_append (Widgets, widget); return 1; } int main(int argc, char * argv[]) { GtkWidget * window; GtkWidget * hbox; Display * display; Window root; Atom desktopGeometryAtom; Atom actual; Atom bigViewportAtom; int result, format; unsigned long n, left; unsigned char *propData; unsigned long data[2]; int viewx, viewy; int onex, oney; int numx, numy; int i; int j; int k; display = XOpenDisplay(getenv("DISPLAY")); root = XDefaultRootWindow(display); desktopGeometryAtom = XInternAtom(display, "_NET_DESKTOP_GEOMETRY", 0); bigViewportAtom = XInternAtom(display, "_BERYL_DESKTOP_MANAGED", 0); unsigned long datas = 1; int retVal = XChangeProperty(display, XRootWindow(display,0), bigViewportAtom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&datas, 1); printf(" \n retVal: %d \n \n",retVal); result = XGetWindowProperty(display,root,desktopGeometryAtom,0L,2L,FALSE,XA_CARDINAL,&actual, &format, &n, &left, &propData); if (result == Success && n && propData) { memcpy(data, propData, sizeof(unsigned long)*2); XFree(propData); if (data[0] > 0 && data[0] < 0xffffffff) { viewx = data[0]; viewy = data[1]; } } gtk_init(&argc,&argv); printf("Resolution: %d x %d \n \n",data[0],data[1]); onex = gdk_screen_get_width(gdk_screen_get_default()); oney = gdk_screen_get_height(gdk_screen_get_default()); printf("One res: %d x %d \n \n",onex,oney); numx = viewx/onex; numy = viewy/oney; GKeyFile *kf; GError *error = NULL; gchar **keys; gsize n_keys; gchar * path = g_strconcat(g_get_home_dir (), "/.bdm/wallpaper.list", NULL); kf = g_key_file_new (); if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, &error)) { fprintf (stderr, "Where are your settings?\n"); return 1; } g_free (path); keys = g_key_file_get_keys (kf, "wallpapers", &n_keys, &error); if (error != NULL || n_keys == 0) { fprintf (stderr, "Something broke (that means I hate you) or you don't have any wallpapers in your file (but it was found and has the proper format).\n"); return 1; } for(i = 0; i < n_keys; i++) { //for now just assume all are pixbuf gchar * s = g_key_file_get_string(kf,"wallpapers",keys[i],NULL); NEW(Wallpaper,w); w->type=WALLPAPER_TYPE_PIXBUF; w->data.pixbuf.source=gdk_pixbuf_new_from_file(s,NULL); if (w->data.pixbuf.source) { w->data.pixbuf.width=gdk_pixbuf_get_width(w->data.pixbuf.source); w->data.pixbuf.height=gdk_pixbuf_get_height(w->data.pixbuf.source); Wallpapers=g_slist_append(Wallpapers,w); } else { free(w); } g_free (s); } if (!Wallpapers) { fprintf (stderr, "All your wallpapers are belong to NULL.\n"); return 1; } keys = g_key_file_get_keys (kf, "widgets", &n_keys, &error); if (error != NULL || n_keys == 0) { fprintf (stderr, "All your widgets are belong to me.\n"); } else { for(i = 0; i < n_keys; i++) { gchar * s = g_key_file_get_string (kf, "widgets", keys[i], NULL); loadWidget (s); g_free (s); } } g_key_file_free (kf); GSList * wp = Wallpapers; for (j = 0; j < numy; j++) { for (i = 0; i < numx; i++) { for (k = 0; k < gdk_screen_get_n_monitors(gdk_screen_get_default()); k++) { GdkRectangle R; NEW(ScreenArea,sa); gdk_screen_get_monitor_geometry(gdk_screen_get_default(),k,&R); sa->width=R.width; sa->height=R.height; GtkWidget * dwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); sa->window=dwindow; sa->wallpaper=wp->data; sa->alpha=1.0f; wp=wp->next; if (!wp) wp=Wallpapers; gtk_window_set_default_size(GTK_WINDOW(dwindow),onex,oney); gtk_window_set_screen(GTK_WINDOW(dwindow),gdk_screen_get_default()); gtk_window_set_decorated(GTK_WINDOW(dwindow),FALSE); gtk_window_set_type_hint(GTK_WINDOW(dwindow),GDK_WINDOW_TYPE_HINT_DESKTOP); gtk_window_move(GTK_WINDOW(dwindow),i*onex+R.x,j*oney+R.y); on_alpha_screen_changed(dwindow,NULL,NULL); gtk_window_resize(GTK_WINDOW(dwindow),R.width,R.height); gtk_widget_set_app_paintable(dwindow, TRUE); gtk_window_set_keep_below(GTK_WINDOW(dwindow),TRUE); g_signal_connect( G_OBJECT(dwindow),"expose-event",G_CALLBACK(on_alpha_window_expose),sa); gtk_widget_show(dwindow); on_alpha_window_expose(dwindow,0,sa); } } } gtk_main(); //yes I know there is unfreed stuff, its intentional, the system can take care of it }