diff --git a/milkwm/CMakeLists.txt b/milkwm/CMakeLists.txt index f92106d..9b7f50f 100644 --- a/milkwm/CMakeLists.txt +++ b/milkwm/CMakeLists.txt @@ -3,14 +3,13 @@ include(MDEPkgConfig) mde_setup_project(milkwm ${CMAKE_INSTALL_BINDIR}) mde_pkg_config_add(milkwm x11) -mde_pkg_config_add(milkwm libconfig) mde_math_add(milkwm) target_link_libraries( milkwm PRIVATE - pthread + xemil pthread ) include(GNUInstallDirs) diff --git a/milkwm/config.c b/milkwm/config.c index 59cbe41..de5139f 100644 --- a/milkwm/config.c +++ b/milkwm/config.c @@ -2,15 +2,21 @@ /* we prefix them for reasons */ -config_t wm_config; +xemil_t* wm_config = NULL; void wm_config_init(void) { - config_init(&wm_config); } static void read_config(const char* path) { - if(!config_read_file(&wm_config, path)) { - fprintf(stderr, "MilkWM config error: file %s at line %d: %s\n", path, config_error_line(&wm_config), config_error_text(&wm_config)); + xemil_t* tmp; + + if((tmp = xl_open_file(path)) == NULL || !xl_parse(tmp)) { + fprintf(stderr, "MPanel config error: file %s\n", path); + if(tmp != NULL) xl_close(tmp); + } else { + if(wm_config != NULL) xl_close(wm_config); + + wm_config = tmp; } } @@ -22,7 +28,6 @@ void wm_config_read(void) { free(dir); free(conf); - config_clear(&wm_config); read_config(SYSCONFDIR "/milkwm/milkwmrc"); read_config(path); diff --git a/milkwm/milkwm.h b/milkwm/milkwm.h index bc9ec5b..d3ffb8d 100644 --- a/milkwm/milkwm.h +++ b/milkwm/milkwm.h @@ -8,7 +8,7 @@ #include /* External */ -#include +#include #include #include #include @@ -51,7 +51,7 @@ int wm_content_x(void); int wm_content_y(void); /* config.c */ -extern config_t wm_config; +extern xemil_t* wm_config; void wm_config_init(void); void wm_config_read(void); diff --git a/milkwm/milkwmrc.in b/milkwm/milkwmrc.in index ae78f83..6c7c713 100644 --- a/milkwm/milkwmrc.in +++ b/milkwm/milkwmrc.in @@ -1,41 +1,38 @@ -# This file should be copied to .config/milkwm/milkwmrc + + + + @CMAKE_INSTALL_FULL_DATAROOTDIR@/wallpapers/mde/blue.png + + + + + + + + + + + + + + + white + -Wallpaper: { - Type = "Fill"; - Path = "@CMAKE_INSTALL_FULL_DATAROOTDIR@/wallpapers/mde/blue.png"; -}; - -Window: { - TitleBar: { - Buttons: { - # Ordered from left to right - Left = [ - "Close" - ]; - - # Ordered from right to left - Right = [ - "Maximize", - "Iconify" - ]; - }; - Active: { - Background: { - From = "#435f7e"; - To = "#0a284b"; - }; - Foreground = "white"; - }; - Inactive: { - # Just don't write anything if you want default background/foreground - Background: { - From = "#a0a0a0"; - To = "#cdcdcd"; - }; - }; - - # Left, Right, or Center - # Default is Center - Align = "Left"; - }; -}; + + Left + + diff --git a/milkwm/wm.c b/milkwm/wm.c index 36ec957..a55523b 100644 --- a/milkwm/wm.c +++ b/milkwm/wm.c @@ -116,10 +116,24 @@ static int alignment(const char* str) { } static void apply_config(MwWidget wnd) { - wmframe_t* f = wnd->opaque; - const char* str; + wmframe_t* f = wnd->opaque; + const char* str = NULL; + xl_node_t* n = wm_config->root->first_child; - if(config_lookup_string(&wm_config, "Window.TitleBar.Align", &str)) { + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, "Window") == 0) { + xl_node_t* n2 = n->first_child; + while(n2 != NULL) { + if(n2->type == XL_NODE_NODE && strcmp(n2->name, "Align") == 0 && n2->text != NULL) { + str = n2->text; + } + n2 = n2->next; + } + } + n = n->next; + } + + if(str != NULL) { MwVaApply(f->title, MwNalignment, alignment(str), NULL); @@ -249,14 +263,49 @@ static void drag(MwWidget handle, void* user, void* client) { } } +static xl_node_t* get_window(void) { + xl_node_t* n; + + if(wm_config == NULL || wm_config->root == NULL) return NULL; + + n = wm_config->root->first_child; + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, "Window") == 0) { + return n; + } + + n = n->next; + } + + return NULL; +} + +static xl_node_t* get_titlebar(void) { + xl_node_t* n; + + if(wm_config == NULL || wm_config->root == NULL) return NULL; + + n = get_window(); + if(n == NULL) return NULL; + + n = n->first_child; + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, "TitleBar") == 0) { + return n; + } + + n = n->next; + } + + return NULL; +} + MwWidget wm_frame(int w, int h) { - MwWidget wnd, titlebar; - int i; - config_setting_t* s; - const char* str; - wmframe_t* f = malloc(sizeof(*f)); - unsigned char* icon; - int y, x; + MwWidget wnd, titlebar; + int i; + wmframe_t* f = malloc(sizeof(*f)); + unsigned char* icon; + int y, x; pthread_mutex_lock(&xmutex); @@ -319,26 +368,44 @@ MwWidget wm_frame(int w, int h) { MwAddUserHandler(f->title, MwNmouseMoveHandler, drag, NULL); MwAddUserHandler(f->title, MwNmouseDownHandler, drag_down, NULL); - s = config_lookup(&wm_config, "Window.TitleBar.Buttons.Left"); - for(i = 0; (str = config_setting_get_string_elem(s, i)) != NULL; i++) { - MwWidget w = MwVaCreateWidget(MwButtonClass, "button", f->titlebar, 0, 0, TitleBarHeight, TitleBarHeight, - MwNborderWidth, 1, - NULL); + for(i = 0; i < 2; i++) { + xl_node_t* node = get_titlebar(); + xl_node_t* n; - apply_button(w, str); + if(node == NULL) continue; - arrput(f->left, w); - } + n = node->first_child; + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, "Button") == 0) { + xl_node_t* n2 = n->first_child; + while(n2 != NULL) { + if(n2->type == XL_NODE_NODE && strcmp(n2->name, i == 0 ? "Left" : "Right") == 0) { + xl_node_t* n3 = n2->first_child; + while(n3 != NULL) { + if(n3->type == XL_NODE_NODE) { + MwWidget w = MwVaCreateWidget(MwButtonClass, "button", f->titlebar, 0, 0, TitleBarHeight, TitleBarHeight, + MwNborderWidth, 1, + NULL); - s = config_lookup(&wm_config, "Window.TitleBar.Buttons.Right"); - for(i = 0; (str = config_setting_get_string_elem(s, i)) != NULL; i++) { - MwWidget w = MwVaCreateWidget(MwButtonClass, "button", f->titlebar, 0, 0, TitleBarHeight, TitleBarHeight, - MwNborderWidth, 1, - NULL); + apply_button(w, n3->name); - apply_button(w, str); + if(i == 0) { + arrput(f->left, w); + } else { + arrput(f->right, w); + } + } - arrput(f->right, w); + n3 = n3->next; + } + } + + n2 = n2->next; + } + } + + n = n->next; + } } apply_config(wnd); @@ -377,51 +444,90 @@ void wm_set_name(MwWidget widget, const char* name) { } static char tmp_bg[64]; -MwLLPixmap lookup_bg(MwWidget widget, const char* path, const char** bg) { - config_setting_t* s = config_lookup(&wm_config, path); - wmframe_t* f = widget->opaque; - MwLLPixmap px = NULL; - *bg = NULL; - if(s == NULL) { - } else if(config_setting_type(s) == CONFIG_TYPE_STRING) { - *bg = config_setting_get_string(s); - } else if(config_setting_type(s) == CONFIG_TYPE_GROUP) { - const char* from; - const char* to; - int i; - unsigned char* d = malloc(1 * TitleBarHeight * 4); - MwLLColor cfrom; - MwLLColor cto; - int fr, fg, fb; - int tr, tg, tb; +MwLLPixmap lookup_col(MwWidget widget, const char* bgfg, const char* type, const char** bg) { + wmframe_t* f = widget->opaque; + MwLLPixmap px = NULL; + xl_node_t* node = get_window(); + xl_node_t* n; - config_setting_lookup_string(s, "From", &from); - config_setting_lookup_string(s, "To", &to); + *bg = NULL; - cfrom = MwParseColor(widget, from == NULL ? MwGetText(widget, MwNbackground) : from); - cto = MwParseColor(widget, to == NULL ? MwGetText(widget, MwNbackground) : to); - MwColorGet(cfrom, &fr, &fg, &fb); - MwColorGet(cto, &tr, &tg, &tb); - MwLLFreeColor(cfrom); - MwLLFreeColor(cto); + if(node == NULL) return NULL; - memset(d, 255, 1 * TitleBarHeight * 4); + n = node->first_child; - for(i = 0; i < TitleBarHeight; i++) { - d[i * 4 + 0] = fr + (tr - fr) * i / TitleBarHeight; - d[i * 4 + 1] = fg + (tg - fg) * i / TitleBarHeight; - d[i * 4 + 2] = fb + (tb - fb) * i / TitleBarHeight; - } - px = MwLoadRaw(widget, d, 1, TitleBarHeight); + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, bgfg) == 0) { + xl_node_t* n2 = n->first_child; + while(n2 != NULL) { + if(n2->type == XL_NODE_NODE && strcmp(n2->name, type) == 0) { + if(n2->text != NULL) { + *bg = n2->text; + } else { + const char* from = NULL; + const char* to; + int i; + unsigned char* d = malloc(1 * TitleBarHeight * 4); + MwLLColor cfrom; + MwLLColor cto; + int fr, fg, fb; + int tr, tg, tb; + xl_node_t* n3 = n2->first_child; - sprintf(tmp_bg, "#%02x%02x%02x", fr + (tr - fr) / 2, fg + (tg - fg) / 2, fb + (tb - fb) / 2); - *bg = &tmp_bg[0]; + while(n3 != NULL) { + if(n3->type == XL_NODE_NODE && strcmp(n3->name, "Gradient") == 0) { + xl_attribute_t* a = n3->first_attribute; - free(d); - } + while(a != NULL) { + if(strcmp(a->key, "From") == 0) { + from = a->value; + } else if(strcmp(a->key, "To") == 0) { + to = a->value; + } + a = a->next; + } + } + n3 = n3->next; + } - return px; + if(from == NULL || to == NULL) { + free(d); + + n2 = n2->next; + continue; + } + + cfrom = MwParseColor(widget, from == NULL ? MwGetText(widget, MwNbackground) : from); + cto = MwParseColor(widget, to == NULL ? MwGetText(widget, MwNbackground) : to); + MwColorGet(cfrom, &fr, &fg, &fb); + MwColorGet(cto, &tr, &tg, &tb); + MwLLFreeColor(cfrom); + MwLLFreeColor(cto); + + memset(d, 255, 1 * TitleBarHeight * 4); + + for(i = 0; i < TitleBarHeight; i++) { + d[i * 4 + 0] = fr + (tr - fr) * i / TitleBarHeight; + d[i * 4 + 1] = fg + (tg - fg) * i / TitleBarHeight; + d[i * 4 + 2] = fb + (tb - fb) * i / TitleBarHeight; + } + px = MwLoadRaw(widget, d, 1, TitleBarHeight); + + sprintf(tmp_bg, "#%02x%02x%02x", fr + (tr - fr) / 2, fg + (tg - fg) / 2, fb + (tb - fb) / 2); + *bg = &tmp_bg[0]; + + free(d); + } + } + n2 = n2->next; + } + } + + n = n->next; + } + + return px; } void wm_focus(MwWidget widget, int focus) { @@ -429,16 +535,19 @@ void wm_focus(MwWidget widget, int focus) { const char* bg = NULL; const char* fg = NULL; MwLLPixmap bgpx = NULL; + MwLLPixmap fgpx = NULL; pthread_mutex_lock(&xmutex); if(focus) { - bgpx = lookup_bg(widget, "Window.TitleBar.Active.Background", &bg); - config_lookup_string(&wm_config, "Window.TitleBar.Active.Foreground", &fg); + bgpx = lookup_col(widget, "Background", "Active", &bg); + fgpx = lookup_col(widget, "Foreground", "Active", &fg); } else { - bgpx = lookup_bg(widget, "Window.TitleBar.Inactive.Background", &bg); - config_lookup_string(&wm_config, "Window.TitleBar.Inactive.Foreground", &fg); + bgpx = lookup_col(widget, "Background", "Inactive", &bg); + fgpx = lookup_col(widget, "Foreground", "Inactive", &fg); } + if(fgpx != NULL) MwLLDestroyPixmap(fgpx); + if(f->background != NULL) MwLLDestroyPixmap(f->background); f->background = bgpx; diff --git a/milkwm/xserver.c b/milkwm/xserver.c index 19cd785..c38bb1d 100644 --- a/milkwm/xserver.c +++ b/milkwm/xserver.c @@ -201,10 +201,29 @@ static Pixmap render_image(Window wnd, const char* path, int tile, int fit) { /* this can be optimized by backends p much, so we do this in backend... */ void set_background_x(void) { - const char* str; - const char* type; + const char* str = NULL; + const char* type = NULL; + xl_node_t* n; - if(config_lookup_string(&wm_config, "Wallpaper.Type", &str) && strcmp(str, "Solid") == 0 && config_lookup_string(&wm_config, "Wallpaper.Color", &str)) { + if(wm_config == NULL || wm_config->root == NULL) { + n = NULL; + } else { + n = wm_config->root->first_child; + } + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, "Wallpaper") == 0) { + xl_attribute_t* a = n->first_attribute; + while(a != NULL) { + if(strcmp(a->key, "Type") == 0) type = a->value; + a = a->next; + } + + str = n->text; + } + n = n->next; + } + + if(type != NULL && strcmp(type, "Solid") == 0 && str != NULL) { MwRGB rgb; XColor xc; @@ -217,7 +236,7 @@ void set_background_x(void) { XAllocColor(xdisplay, DefaultColormap(xdisplay, DefaultScreen(xdisplay)), &xc); XSetWindowBackground(xdisplay, DefaultRootWindow(xdisplay), xc.pixel); - } else if(config_lookup_string(&wm_config, "Wallpaper.Type", &type) && (strcmp(type, "Tile") == 0 || strcmp(type, "Fill") == 0 || strcmp(type, "Fit") == 0) && config_lookup_string(&wm_config, "Wallpaper.Path", &str)) { + } else if(type != NULL && (strcmp(type, "Tile") == 0 || strcmp(type, "Fill") == 0 || strcmp(type, "Fit") == 0) && str != NULL) { XWindowAttributes xwa; Pixmap px; @@ -519,6 +538,7 @@ void loop_x(void) { int ret = 0; XWindowAttributes xwa, xwar; XConfigureEvent ev2; + int mx, my; if(!XGetWindowAttributes(xdisplay, ev.xmaprequest.window, &xwa)) continue; /* ?? ? ? ???? ?? ? ? */ @@ -530,7 +550,7 @@ void loop_x(void) { XMapWindow(xdisplay, ev.xmaprequest.window); - if(!xwa.override_redirect) save(ev.xmaprequest.window); + if(xwa.override_redirect) save(ev.xmaprequest.window); continue; } @@ -551,6 +571,12 @@ void loop_x(void) { continue; } + if(xwa.override_redirect) { + wm_destroy(windows[i].frame); + arrdel(windows, i); + continue; + } + ev2.type = ConfigureNotify; ev2.display = xdisplay; ev2.event = windows[i].client; @@ -596,7 +622,10 @@ void loop_x(void) { XGetWindowAttributes(xdisplay, DefaultRootWindow(xdisplay), &xwar); - XMoveWindow(xdisplay, w.client, rand() % (xwar.width - wm_entire_width(xwa.width)), rand() % (xwar.height - wm_entire_height(xwa.height))); + mx = (xwar.width - wm_entire_width(xwa.width)); + my = (xwar.height - wm_entire_height(xwa.height) - 46); + + XMoveWindow(xdisplay, w.client, mx == 0 ? 0 : (rand() % mx), my == 0 ? 0 : (rand() % my)); } else if(ev.type == PropertyNotify) { int i; for(i = 0; i < arrlen(windows); i++) { @@ -610,8 +639,10 @@ void loop_x(void) { set_name(windows[i].client); } } else if(ev.type == MapNotify) { - int i; - if(ev.xmap.override_redirect) continue; + int i; + XWindowAttributes xwa; + if(!XGetWindowAttributes(xdisplay, ev.xmap.window, &xwa)) continue; + if(xwa.override_redirect) continue; for(i = 0; i < arrlen(windows); i++) { if(windows[i].client == ev.xmap.window) {