diff --git a/milkwm/config.c b/milkwm/config.c index de5139f..66b81a9 100644 --- a/milkwm/config.c +++ b/milkwm/config.c @@ -11,7 +11,7 @@ static void read_config(const char* path) { xemil_t* tmp; if((tmp = xl_open_file(path)) == NULL || !xl_parse(tmp)) { - fprintf(stderr, "MPanel config error: file %s\n", path); + fprintf(stderr, "MilkWM config error: file %s\n", path); if(tmp != NULL) xl_close(tmp); } else { if(wm_config != NULL) xl_close(wm_config); diff --git a/milkwm/milkwm.h b/milkwm/milkwm.h index 3d56ed7..1010b04 100644 --- a/milkwm/milkwm.h +++ b/milkwm/milkwm.h @@ -32,6 +32,7 @@ int init_x(void); void loop_x(void); void set_focus_x(MwWidget widget); void set_background_x(void); +void delete_x(MwWidget widget); /* wm.c */ extern MwWidget root; diff --git a/milkwm/wm.c b/milkwm/wm.c index 49789d0..c193099 100644 --- a/milkwm/wm.c +++ b/milkwm/wm.c @@ -32,6 +32,8 @@ typedef struct wmframe { MwWidget submenu; MwMenu menu; + + long tick; } wmframe_t; void loop_wm(void) { @@ -153,10 +155,18 @@ static void apply_config(MwWidget wnd) { static void maximize(MwWidget handle, void* user, void* client) { wmframe_t* f = ((MwWidget)user)->opaque; MwRect rc; + int i; set_focus_x(user); if(f->maximized) { + for(i = 0; i < arrlen(f->menu->sub); i++) { + if(strcmp(f->menu->sub[i]->name, "Restore") == 0) { + free(f->menu->sub[i]->name); + f->menu->sub[i]->name = MwStringDuplicate("Maximize"); + } + } + f->maximized = 0; MwVaApply(handle, @@ -170,6 +180,13 @@ static void maximize(MwWidget handle, void* user, void* client) { MwNheight, f->old_size.height, NULL); } else { + for(i = 0; i < arrlen(f->menu->sub); i++) { + if(strcmp(f->menu->sub[i]->name, "Maximize") == 0) { + free(f->menu->sub[i]->name); + f->menu->sub[i]->name = MwStringDuplicate("Restore"); + } + } + f->maximized = 1; f->old_point.x = MwGetInteger(user, MwNx); @@ -196,6 +213,7 @@ static void spawn_menu(MwWidget handle, void* user, void* client) { MwWidget w = handle; wmframe_t* f; MwPoint p; + long t; while(w != NULL && strcmp(MwGetName(w), "frame") != 0) w = MwGetParent(w); @@ -207,21 +225,56 @@ static void spawn_menu(MwWidget handle, void* user, void* client) { p.x = 0; p.y = MwGetInteger(handle, MwNheight); MwSubMenuAppear(f->submenu, f->menu, &p, 0); + + MwVaApply(f->menu_button, + MwNforceInverted, 1, + NULL); } else { MwDestroyWidget(f->submenu); f->submenu = NULL; + + MwVaApply(f->menu_button, + MwNforceInverted, 0, + NULL); } + + if(((t = MwTimeGetTick()) - f->tick) < MwDoubleClickTimeout) { + delete_x(w); + } + + f->tick = t; } static void menu_menu(MwWidget handle, void* user, void* client) { MwWidget w = handle; wmframe_t* f; + int i; + MwMenu m = client; while(w != NULL && strcmp(MwGetName(w), "frame") != 0) w = MwGetParent(w); f = w->opaque; + if(strcmp(m->name, "Maximize") == 0 || strcmp(m->name, "Restore") == 0) { + for(i = 0; i < arrlen(f->left); i++) { + MwLLPixmap px = MwGetVoid(f->left[i], MwNpixmap); + + if(px == f->maximize || px == f->restore) maximize(f->left[i], w, NULL); + } + + for(i = 0; i < arrlen(f->right); i++) { + MwLLPixmap px = MwGetVoid(f->right[i], MwNpixmap); + + if(px == f->maximize || px == f->restore) maximize(f->right[i], w, NULL); + } + } else if(strcmp(m->name, "Close") == 0) { + delete_x(w); + } + f->submenu = NULL; + MwVaApply(f->menu_button, + MwNforceInverted, 0, + NULL); } static void apply_button(MwWidget widget, const char* str) { @@ -269,6 +322,10 @@ static void drag_down(MwWidget handle, void* user, void* client) { if(f->submenu != NULL) { MwDestroyWidget(f->submenu); f->submenu = NULL; + + MwVaApply(f->menu_button, + MwNforceInverted, 0, + NULL); } f->dragging = 1; @@ -423,6 +480,8 @@ MwWidget wm_frame(int w, int h) { f->iconify = MwLoadRaw(wnd, icon, 6, 6); free(icon); + f->tick = 0; + f->left = NULL; f->right = NULL; diff --git a/milkwm/xserver.c b/milkwm/xserver.c index dbdc030..3852a93 100644 --- a/milkwm/xserver.c +++ b/milkwm/xserver.c @@ -50,6 +50,7 @@ typedef struct window { int working; } window_t; static window_t* windows = NULL; +static Window* wnd = NULL; static void* old_handler; static int error_happened = 0; @@ -452,13 +453,23 @@ static int is_no_border(Window window) { return 0; } +static void bring_up(void) { + int i; + for(i = 0; i < arrlen(wnd); i++) { + XWindowAttributes xwa; + + XGetWindowAttributes(xdisplay, wnd[i], &xwa); + + if(xwa.override_redirect) XRaiseWindow(xdisplay, wnd[i]); + } +} + void loop_x(void) { XEvent ev; Window root, parent; Window* children; unsigned int nchildren; int i; - Window* wnd = NULL; begin_error(); @@ -509,6 +520,8 @@ void loop_x(void) { XRaiseWindow(xdisplay, w); } + bring_up(); + XAllowEvents(xdisplay, ReplayPointer, CurrentTime); } else if(ev.type == MotionNotify && ev.xmotion.subwindow != None) { Window w = None, t = ev.xmotion.window; @@ -520,7 +533,10 @@ void loop_x(void) { } } - if(w != None) XRaiseWindow(xdisplay, w); + if(w != None) { + XRaiseWindow(xdisplay, w); + bring_up(); + } XAllowEvents(xdisplay, ReplayPointer, CurrentTime); } else if(ev.type == FocusIn && ev.xfocus.window != focus) { @@ -628,7 +644,11 @@ void loop_x(void) { XMapWindow(xdisplay, ev.xmaprequest.window); - if(xwa.override_redirect) save(ev.xmaprequest.window); + if(xwa.override_redirect) { + arrput(wnd, ev.xmaprequest.window); + + save(ev.xmaprequest.window); + } continue; } @@ -726,7 +746,16 @@ void loop_x(void) { int i; XWindowAttributes xwa; if(!XGetWindowAttributes(xdisplay, ev.xmap.window, &xwa)) continue; - if(xwa.override_redirect) continue; + if(xwa.override_redirect) { + for(i = 0; i < arrlen(wnd); i++) { + if(wnd[i] == ev.xmap.window) { + break; + } + } + + if(i == arrlen(wnd)) arrput(wnd, ev.xmap.window); + continue; + } for(i = 0; i < arrlen(windows); i++) { if(windows[i].client == ev.xmap.window) { @@ -800,7 +829,7 @@ void loop_x(void) { set_focus(w); } } else if(ev.type == ClientMessage) { - if(ev.xclient.message_type == milkwm_set_focus && ev.xclient.data.l[0] == milkwm_set_focus) { + if(ev.xclient.message_type == XInternAtom(xdisplay, "WM_PROTOCOLS", False) && ev.xclient.data.l[0] == milkwm_set_focus) { set_focus(ev.xclient.data.l[1]); } } @@ -819,14 +848,36 @@ void set_focus_x(MwWidget widget) { ev.type = ClientMessage; ev.xclient.window = nofocus; - ev.xclient.message_type = milkwm_set_focus; + ev.xclient.message_type = XInternAtom(xdisplay, "WM_PROTOCOLS", False); ev.xclient.format = 32; - ev.xclient.data.l[0] = ev.xclient.message_type; + ev.xclient.data.l[0] = milkwm_set_focus; ev.xclient.data.l[1] = windows[i].client; XSendEvent(xdisplay, nofocus, False, 0, &ev); XRaiseWindow(xdisplay, windows[i].frame->lowlevel->x11.window); + bring_up(); + + break; + } + } +} + +void delete_x(MwWidget widget) { + int i; + + for(i = 0; i < arrlen(windows); i++) { + if(windows[i].frame == widget) { + XEvent ev; + + ev.type = ClientMessage; + ev.xclient.window = windows[i].client; + ev.xclient.message_type = XInternAtom(xdisplay, "WM_PROTOCOLS", False); + ev.xclient.format = 32; + ev.xclient.data.l[0] = XInternAtom(xdisplay, "WM_DELETE_WINDOW", False); + ev.xclient.data.l[1] = CurrentTime; + + XSendEvent(xdisplay, windows[i].client, False, 0, &ev); break; }