From 672c42cc4832e9798bd6815fa824dfbf0e798f45 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Dec 2001 04:02:33 +0000 Subject: [PATCH] - removed the collapse appicons thing - added real appicon sharing (apps of the same kind will have a single shared appicon). --- ChangeLog | 3 + WINGs/WINGs/WUtil.h | 2 +- WindowMaker/Defaults/WMWindowAttributes.in | 6 +- configure.ac | 2 +- configure.in | 2 +- src/actions.c | 2 +- src/appicon.c | 174 +++++------------------------ src/appicon.h | 4 - src/application.c | 98 ++-------------- src/application.h | 8 +- src/client.c | 17 ++- src/dock.c | 60 +++++++--- src/screen.c | 2 + src/screen.h | 2 + src/wconfig.h.in | 3 - src/wdefaults.c | 24 ++-- src/window.c | 141 +++++++++++++++++------ src/window.h | 27 +++-- src/winspector.c | 20 ++-- 19 files changed, 251 insertions(+), 346 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5fe50300..3e6a118b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,9 @@ Changes since version 0.70.0: default. - Mapping a new window that belongs to a running application that is hidden, will unhide the application. +- Removed the collapse appicons thing. +- Added real appicon sharing (apps of the same kind will have a single shared + appicon). Changes since version 0.65.1: diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h index c094406c..9b4c50d4 100644 --- a/WINGs/WINGs/WUtil.h +++ b/WINGs/WINGs/WUtil.h @@ -373,7 +373,7 @@ extern const WMHashTableCallbacks WMStringHashCallbacks; * and freed with wfree() */ extern const WMHashTableCallbacks WMStringPointerHashCallbacks; -/* keys are strings, bug they are not copied */ +/* keys are strings, but they are not copied */ /*......................................................................*/ diff --git a/WindowMaker/Defaults/WMWindowAttributes.in b/WindowMaker/Defaults/WMWindowAttributes.in index 9a763523..2711532d 100644 --- a/WindowMaker/Defaults/WMWindowAttributes.in +++ b/WindowMaker/Defaults/WMWindowAttributes.in @@ -7,8 +7,8 @@ WSoundServer = {Icon = sound.#extension#;}; panel.Panel = {NoAppIcon = YES;}; gmc.Gmc = {NoAppIcon = YES;}; - XTerm = {Icon = Terminal.#extension#;}; - NXTerm = {Icon = Terminal.#extension#;}; + XTerm = {SharedAppIcon = Yes;Icon = Terminal.#extension#;}; + NXTerm = {SharedAppIcon = Yes;Icon = Terminal.#extension#;}; ScilabGraphic0.Xscilab = {KeepInsideScreen=YES;}; ScilabGraphic1.Xscilab = {KeepInsideScreen=YES;}; ScilabGraphic2.Xscilab = {KeepInsideScreen=YES;}; @@ -46,7 +46,7 @@ Xmag = {Icon = inspect.xpm;}; Xmessage = {Icon = Reference.xpm;}; XConsole = {Icon = inspect.xpm;Omnipresent = Yes;}; - Fte = {Icon = Clipboard.xpm;}; + Fte = {SharedAppIcon = Yes;Icon = Clipboard.tif;}; xjed = {Icon = Clipboard.xpm;}; xedit = {Icon = notepad.#extension#;}; xmixer = {Icon = mixer.#extension#;}; diff --git a/configure.ac b/configure.ac index 43dabca0..7371645a 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ AC_INIT(src/WindowMaker.h) -AM_INIT_AUTOMAKE(WindowMaker, 0.70.1) +AM_INIT_AUTOMAKE(WindowMaker, 0.80.0) AM_PROG_LIBTOOL diff --git a/configure.in b/configure.in index 43dabca0..7371645a 100644 --- a/configure.in +++ b/configure.in @@ -15,7 +15,7 @@ AC_INIT(src/WindowMaker.h) -AM_INIT_AUTOMAKE(WindowMaker, 0.70.1) +AM_INIT_AUTOMAKE(WindowMaker, 0.80.0) AM_PROG_LIBTOOL diff --git a/src/actions.c b/src/actions.c index 4c7e7e52..31b3c756 100644 --- a/src/actions.c +++ b/src/actions.c @@ -1538,7 +1538,7 @@ wArrangeIcons(WScreen *scr, Bool arrangeAll) pi = 0; si = 0; while (aicon) { - if (!aicon->docked && wAppIconIsFirstInstance(aicon)) { + if (!aicon->docked) { if (aicon->x_pos != X || aicon->y_pos != Y) { #ifdef ANIMATIONS if (!wPreferences.no_animations) { diff --git a/src/appicon.c b/src/appicon.c index a6bcb29e..e723f8fc 100644 --- a/src/appicon.c +++ b/src/appicon.c @@ -278,29 +278,12 @@ void wAppIconMove(WAppIcon *aicon, int x, int y) { WApplication *app; - WAppIcon *tmp; - + app = wApplicationOf(aicon->icon->owner->main_window); - if (!WFLAGP(app->main_window_desc, collapse_appicons)) { - XMoveWindow(dpy, aicon->icon->core->window, x, y); - aicon->x_pos = x; - aicon->y_pos = y; - } else { - tmp = aicon->icon->core->screen_ptr->app_icon_list; - - /* move all icons of the same class/name to the same pos */ - while (tmp) { - if (strcmp(tmp->wm_class, aicon->wm_class) == 0 && - strcmp(tmp->wm_instance, aicon->wm_instance) == 0 && - !tmp->docked) { - XMoveWindow(dpy, tmp->icon->core->window, x, y); - tmp->x_pos = x; - tmp->y_pos = y; - } - tmp = tmp->next; - } - } + XMoveWindow(dpy, aicon->icon->core->window, x, y); + aicon->x_pos = x; + aicon->y_pos = y; } @@ -341,79 +324,11 @@ updateDockNumbers(WScreen *scr) #endif /* WS_INDICATOR */ - -WAppIcon* -wAppIconNextSibling(WAppIcon *icon) -{ - WApplication *app; - WAppIcon *tmp; - - app = wApplicationOf(icon->icon->owner->main_window); - - if (!WFLAGP(app->main_window_desc, collapse_appicons)) { - return NULL; - } - - tmp = icon->next; - while (tmp) { - if (strcmp(tmp->wm_class, icon->wm_class) == 0 - && strcmp(tmp->wm_instance, icon->wm_instance) == 0 - && !tmp->docked) { - return tmp; - } - tmp = tmp->next; - } - - tmp = icon->icon->core->screen_ptr->app_icon_list; - while (tmp && tmp != icon) { - if (strcmp(tmp->wm_class, icon->wm_class) == 0 - && strcmp(tmp->wm_instance, icon->wm_instance) == 0 - && !tmp->docked) { - return tmp; - } - tmp = tmp->next; - } - - return NULL; -} - - -Bool -wAppIconIsFirstInstance(WAppIcon *icon) -{ - WAppIcon *list = icon->icon->core->screen_ptr->app_icon_list; - - if (!WFLAGP(icon->icon->owner, collapse_appicons)) - return True; - - while (list) { - if (icon == list) - return True; - - if (strcmp(icon->wm_instance, - list->wm_instance) == 0 - && - strcmp(icon->wm_class, - list->wm_class) == 0 - && !icon->docked) - return False; - - list = list->next; - } - - puts("OH SHIT!?!?!? HOW THE FUCK DID WE GET HERE!?!?!?!?!"); - - return 0; -} - - - void wAppIconPaint(WAppIcon *aicon) { WApplication *wapp; WScreen *scr = aicon->icon->core->screen_ptr; - int index; if (aicon->icon->owner) wapp = wApplicationOf(aicon->icon->owner->main_window); @@ -448,22 +363,6 @@ wAppIconPaint(WAppIcon *aicon) } #endif /* HIDDENDOT */ - if (wapp) - index = wApplicationIndexOfGroup(wapp); - else - index = 0; - - if (index > 0) { - char buf[16]; - - snprintf(buf, sizeof(buf), "%i", index); - - WMDrawString(scr->wmscreen, aicon->icon->core->window, - scr->clip_title_gc, scr->title_font, - 3, 3, buf, strlen(buf)); - } - - if (aicon->omnipresent) drawCorner(aicon->icon); @@ -504,16 +403,6 @@ unhideHereCallback(WMenu *menu, WMenuEntry *entry) static void -collapseCallback(WMenu *menu, WMenuEntry *entry) -{ - WApplication *wapp = (WApplication*)entry->clientdata; - - wApplicationSetCollapse(wapp, - !WFLAGP(wapp->main_window_desc, collapse_appicons)); -} - - -static void setIconCallback(WMenu *menu, WMenuEntry *entry) { WAppIcon *icon = ((WApplication*)entry->clientdata)->app_icon; @@ -557,6 +446,7 @@ static void killCallback(WMenu *menu, WMenuEntry *entry) { WApplication *wapp = (WApplication*)entry->clientdata; + WFakeGroupLeader *fPtr; char *buffer; if (!WCHECK_STATE(WSTATE_NORMAL)) @@ -571,12 +461,26 @@ killCallback(WMenu *menu, WMenuEntry *entry) "Any unsaved changes will be lost.\n" "Please confirm.")); + fPtr = wapp->main_window_desc->fake_group; + wretain(wapp->main_window_desc); if (wPreferences.dont_confirm_kill || wMessageDialog(menu->frame->screen_ptr, _("Kill Application"), buffer, _("Yes"), _("No"), NULL)==WAPRDefault) { - if (!wapp->main_window_desc->flags.destroyed) - wClientKill(wapp->main_window_desc); + if (fPtr!=NULL) { + WWindow *wwin, *twin; + + wwin = wapp->main_window_desc->screen_ptr->focused_window; + while (wwin) { + twin = wwin->prev; + if (wwin->fake_group == fPtr) { + wClientKill(wwin); + } + wwin = twin; + } + } else if (!wapp->main_window_desc->flags.destroyed) { + wClientKill(wapp->main_window_desc); + } } wrelease(wapp->main_window_desc); @@ -594,7 +498,6 @@ createApplicationMenu(WScreen *scr) menu = wMenuCreate(scr, NULL, False); wMenuAddCallback(menu, _("Unhide Here"), unhideHereCallback, NULL); wMenuAddCallback(menu, _("Hide"), hideCallback, NULL); - wMenuAddCallback(menu, _("Collapse"), collapseCallback, NULL); wMenuAddCallback(menu, _("Set Icon..."), setIconCallback, NULL); wMenuAddCallback(menu, _("Kill"), killCallback, NULL); @@ -622,12 +525,6 @@ openApplicationMenu(WApplication *wapp, int x, int y) menu->entries[1]->text = _("Hide"); } - if (WFLAGP(wapp->main_window_desc, collapse_appicons)) { - menu->entries[2]->text = _("Uncollapse"); - } else { - menu->entries[2]->text = _("Collapse"); - } - menu->flags.realized = 0; wMenuRealize(menu); @@ -712,7 +609,7 @@ appIconMouseDown(WObjDescriptor *desc, XEvent *event) if (aicon->editing || WCHECK_STATE(WSTATE_MODAL)) return; - if (event->xbutton.button == Button1 && IsDoubleClick(scr, event)) { + if (IsDoubleClick(scr, event)) { iconDblClick(desc, event); return; } @@ -750,16 +647,6 @@ appIconMouseDown(WObjDescriptor *desc, XEvent *event) else wRaiseFrame(icon->core); - - if (clickButton == Button2) { - WAppIcon *next = wAppIconNextSibling(aicon); - - if (next) { - wRaiseFrame(next->icon->core); - } - return; - } - if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask |ButtonReleaseMask|ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) { @@ -897,19 +784,10 @@ appIconMouseDown(WObjDescriptor *desc, XEvent *event) wDockLower(workspace->clip); if (!docked) { - /* If icon could not be docked, slide it back to the old - * position */ - SlideWindow(icon->core->window, x, y, oldX, oldY); - } else { - WAppIcon *nextIcon = wAppIconNextSibling(aicon); - - if (nextIcon) { - /* move the next instance back to the old position */ - SlideWindow(nextIcon->icon->core->window, x, y, - oldX, oldY); - wAppIconMove(nextIcon, oldX, oldY); - } - } + /* If icon could not be docked, slide it back to the old + * position */ + SlideWindow(icon->core->window, x, y, oldX, oldY); + } wSoundPlay(WSOUND_DOCK); } else { diff --git a/src/appicon.h b/src/appicon.h index 152a9cc4..c455de4c 100644 --- a/src/appicon.h +++ b/src/appicon.h @@ -97,8 +97,4 @@ Bool wAppIconChangeImage(WAppIcon *icon, char *file); void wAppIconMove(WAppIcon *aicon, int x, int y); -WAppIcon *wAppIconNextSibling(WAppIcon *icon); - -Bool wAppIconIsFirstInstance(WAppIcon *icon); - #endif diff --git a/src/application.c b/src/application.c index 7f949038..1163664f 100644 --- a/src/application.c +++ b/src/application.c @@ -270,8 +270,13 @@ wApplicationCreate(WScreen *scr, Window main_window) wapp = wApplicationOf(main_window); if (wapp) { - wapp->refcount++; - return wapp; + wapp->refcount++; + if (wapp->app_icon && wapp->app_icon->docked && + wapp->app_icon->relaunching && wapp->main_window_desc->fake_group) { + wDockFinishLaunch(wapp->app_icon->dock, wapp->app_icon); + } + + return wapp; } wapp = wmalloc(sizeof(WApplication)); @@ -330,7 +335,7 @@ wApplicationCreate(WScreen *scr, Window main_window) break; } } - + if (wapp->app_icon) { WWindow *mainw = wapp->main_window_desc; @@ -413,56 +418,7 @@ wApplicationCreate(WScreen *scr, Window main_window) if (!tmp) extractClientIcon(wapp->app_icon); } - /* set the application instance index */ - { - WApplication *list = scr->wapp_list; - WApplication *prev = NULL; - int index = 0; - WWindow *wwin = wapp->main_window_desc; -/* - if (!WFLAGP(wwin, collapse_appicons)) - return 0; - */ -#define Xstreql(a, b) ((a) == (b) || (a && b && strcmp(a, b)==0)) - - - /* look for a free index # */ - while (list) { - if (Xstreql(wwin->wm_instance, - list->main_window_desc->wm_instance) - && - Xstreql(wwin->wm_class, - list->main_window_desc->wm_class)) { - - if (list->index == index) { - index++; - - /* restart list traversal */ - list = scr->wapp_list; - prev = NULL; - continue; - } - } - - prev = list; - list = list->next; - } - - wapp->index = index; - wapp->next = NULL; - wapp->prev = NULL; - - /* append to app list */ - if (!prev) { - scr->wapp_list = wapp; - } else { - prev->next = wapp; - wapp->prev = prev; - } - } - - wSoundPlay(WSOUND_APPSTART); #ifdef DEBUG @@ -545,41 +501,3 @@ wApplicationDestroy(WApplication *wapp) -void -wApplicationSetCollapse(WApplication *app, Bool flag) -{ - WApplication *list = app->main_window_desc->screen_ptr->wapp_list; - WWindow *wwin = app->main_window_desc; - - if (WFLAGP(app->main_window_desc, collapse_appicons) == flag) - return; - - - while (list) { - if (strcmp(wwin->wm_instance, - list->main_window_desc->wm_instance) == 0 - && - strcmp(wwin->wm_class, - list->main_window_desc->wm_class) == 0) - WSETUFLAG(list->main_window_desc, collapse_appicons, flag); - - list = list->next; - } - - if (app->app_icon && flag) - wAppIconMove(app->app_icon, app->app_icon->x_pos, app->app_icon->y_pos); -} - - - - -/* - * Returns index number of the app in case there are more than - * one instance of the same class/name. - */ -int -wApplicationIndexOfGroup(WApplication *app) -{ - return app->index; -} - diff --git a/src/application.h b/src/application.h index ecbf10cd..0e7fa9d3 100644 --- a/src/application.h +++ b/src/application.h @@ -36,12 +36,10 @@ typedef struct WApplication { struct WAppIcon *app_icon; - int index; - int refcount; struct WWindow *last_focused; /* focused window before hide */ - + int last_workspace; /* last workspace used to work on the * app */ struct { @@ -60,10 +58,6 @@ WApplication *wApplicationOf(Window window); void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance, char *wm_class); -int wApplicationIndexOfGroup(WApplication *app); - -void wApplicationSetCollapse(WApplication *app, Bool flag); - #ifdef NEWAPPICON # define wApplicationActivate(wapp) {\ diff --git a/src/client.c b/src/client.c index 8020cf54..878e69fa 100644 --- a/src/client.c +++ b/src/client.c @@ -436,7 +436,11 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) i = 0; } } - + + if (wwin->fake_group!=NULL) { + i = 7; + } + if (wwin->wm_hints) XFree(wwin->wm_hints); @@ -475,7 +479,10 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) wwin->group_id = wwin->main_window; wApplicationCreate(wwin->screen_ptr, wwin->main_window); break; - } + /* 7 - we have a fake window group id, so just ignore anything else */ + case 7: + break; + } #ifdef DEBUG if (i) { printf("window leader update caused state transition %i\n",i); @@ -504,8 +511,10 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) wwin->flags.urgent = 1; else wwin->flags.urgent = 0; - } else { - wwin->group_id = None; + } else if (wwin->fake_group!=NULL) { + wwin->group_id = wwin->fake_group->window; + } else { + wwin->group_id = None; } break; diff --git a/src/dock.c b/src/dock.c index f007a09d..ad08dd6b 100644 --- a/src/dock.c +++ b/src/dock.c @@ -234,11 +234,19 @@ toggleLoweredCallback(WMenu *menu, WMenuEntry *entry) } +static int +matchWindow(void *item, void *cdata) +{ + return (((WFakeGroupLeader*)item)->window == (Window)cdata); +} + static void killCallback(WMenu *menu, WMenuEntry *entry) { + WScreen *scr = menu->menu->screen_ptr; WAppIcon *icon; + WFakeGroupLeader *fPtr; char *buffer; if (!WCHECK_STATE(WSTATE_NORMAL)) @@ -257,10 +265,35 @@ killCallback(WMenu *menu, WMenuEntry *entry) "Any unsaved changes will be lost.\n" "Please confirm.")); + if (icon->icon && icon->icon->owner) { + fPtr = icon->icon->owner->fake_group; + } else { + /* is this really necessary? can we kill a dock icon not running? */ + Window win = icon->main_window; + int index; + + index = WMFindInArray(scr->fakeGroupLeaders, matchWindow, (void*)win); + if (index != WANotFound) + fPtr = WMGetFromArray(scr->fakeGroupLeaders, index); + else + fPtr = NULL; + } + if (wPreferences.dont_confirm_kill || wMessageDialog(menu->frame->screen_ptr, _("Kill Application"), buffer, _("Yes"), _("No"), NULL)==WAPRDefault) { - if (icon->icon && icon->icon->owner) { + if (fPtr!=NULL) { + WWindow *wwin, *twin; + + wwin = scr->focused_window; + while (wwin) { + twin = wwin->prev; + if (wwin->fake_group == fPtr) { + wClientKill(wwin); + } + wwin = twin; + } + } else if (icon->icon && icon->icon->owner) { wClientKill(icon->icon->owner); } } @@ -2396,14 +2429,6 @@ wDockDetach(WDock *dock, WAppIcon *icon) wAppIconPaint(icon); if (wPreferences.auto_arrange_icons) { wArrangeIcons(dock->screen_ptr, True); - } else { - WAppIcon *bla = wAppIconNextSibling(icon); - - if (bla) { - SlideWindow(icon->icon->core->window, icon->x_pos, icon->y_pos, - bla->x_pos, bla->y_pos); - wAppIconMove(icon, bla->x_pos, bla->y_pos); - } } } if (dock->auto_collapse || dock->auto_raise_lower) @@ -3123,7 +3148,7 @@ wDockTrackWindowLaunch(WDock *dock, Window window) if (XGetCommand(dpy, window, &argv, &argc)) { if (argc > 0 && argv != NULL) - command = wtokenjoin(argv,argc); + command = wtokenjoin(argv, argc); if (argv) { XFreeStringList(argv); } @@ -3262,16 +3287,17 @@ trackDeadProcess(pid_t pid, unsigned char status, WDock *dock) icon->pid = 0; if (status==111) { char msg[PATH_MAX]; + char *cmd; - if (icon->drop_launch) - snprintf(msg, sizeof(msg), _("Could not execute command \"%s\""), - icon->dnd_command); + if (icon->drop_launch) + cmd = icon->dnd_command; else if (icon->paste_launch) - snprintf(msg, sizeof(msg), _("Could not execute command \"%s\""), - icon->paste_command); + cmd = icon->paste_command; else - snprintf(msg, sizeof(msg), _("Could not execute command \"%s\""), - icon->command); + cmd = icon->command; + + snprintf(msg, sizeof(msg), + _("Could not execute command \"%s\""), cmd); wMessageDialog(dock->screen_ptr, _("Error"), msg, _("OK"), NULL, NULL); diff --git a/src/screen.c b/src/screen.c index f1d55d83..b79aad46 100644 --- a/src/screen.c +++ b/src/screen.c @@ -660,6 +660,8 @@ wScreenInit(int screen_number) scr->totalUsableArea.x2 = scr->scr_width; scr->totalUsableArea.y2 = scr->scr_height; + scr->fakeGroupLeaders = WMCreateArray(16); + #if 0 if (!aquireManagerSelection(scr)) { wfree(scr); diff --git a/src/screen.h b/src/screen.h index b98f7f72..9eb749a4 100644 --- a/src/screen.h +++ b/src/screen.h @@ -110,6 +110,8 @@ typedef struct _WScreen { WMArray *selected_windows; + WMArray *fakeGroupLeaders; /* list of fake window group ids */ + struct WAppIcon *app_icon_list; /* list of all app-icons on screen */ struct WApplication *wapp_list; /* list of all aplications */ diff --git a/src/wconfig.h.in b/src/wconfig.h.in index 9a0f7946..b2dd738a 100644 --- a/src/wconfig.h.in +++ b/src/wconfig.h.in @@ -214,9 +214,6 @@ #undef GRADIENT_CLIP_ARROWS -#undef NO_WINDOW_ENUMERATOR - - /* *-------------------------------------------------------------------- * Default Configuration diff --git a/src/wdefaults.c b/src/wdefaults.c index 322a202f..702e7e1e 100644 --- a/src/wdefaults.c +++ b/src/wdefaults.c @@ -80,11 +80,11 @@ static WMPropList *AUnfocusable; static WMPropList *AAlwaysUserIcon; static WMPropList *AStartMiniaturized; static WMPropList *AStartMaximized; -static WMPropList *AStartHidden; /* app */ -static WMPropList *ADontSaveSession; /* app */ +static WMPropList *AStartHidden; /* app */ +static WMPropList *ADontSaveSession; /* app */ static WMPropList *AEmulateAppIcon; static WMPropList *AFullMaximize; -static WMPropList *ACollapseAppIcons; /* app */ +static WMPropList *ASharedAppIcon; /* app */ #ifdef XKB_BUTTON_HINT static WMPropList *ANoLanguageButton; #endif @@ -125,7 +125,7 @@ init_wdefaults(WScreen *scr) ADontSaveSession = WMCreatePLString("DontSaveSession"); AEmulateAppIcon = WMCreatePLString("EmulateAppIcon"); AFullMaximize = WMCreatePLString("FullMaximize"); - ACollapseAppIcons = WMCreatePLString("CollapseAppIcons"); + ASharedAppIcon = WMCreatePLString("SharedAppIcon"); #ifdef XKB_BUTTON_HINT ANoLanguageButton = WMCreatePLString("NoLanguageButton"); #endif @@ -256,13 +256,13 @@ wDefaultFillAttributes(WScreen *scr, char *instance, char *class, /* get the data */ value = get_value(dw, dc, dn, da, ANoTitlebar, No, useGlobalDefault); APPLY_VAL(value, no_titlebar, ANoTitlebar); - + value = get_value(dw, dc, dn, da, ANoResizebar, No, useGlobalDefault); APPLY_VAL(value, no_resizebar, ANoResizebar); value = get_value(dw, dc, dn, da, ANoMiniaturizeButton, No, useGlobalDefault); APPLY_VAL(value, no_miniaturize_button, ANoMiniaturizeButton); - + value = get_value(dw, dc, dn, da, ANoCloseButton, No, useGlobalDefault); APPLY_VAL(value, no_close_button, ANoCloseButton); @@ -271,19 +271,19 @@ wDefaultFillAttributes(WScreen *scr, char *instance, char *class, value = get_value(dw, dc, dn, da, ANoHideOthers, No, useGlobalDefault); APPLY_VAL(value, no_hide_others, ANoHideOthers); - + value = get_value(dw, dc, dn, da, ANoMouseBindings, No, useGlobalDefault); APPLY_VAL(value, no_bind_mouse, ANoMouseBindings); - + value = get_value(dw, dc, dn, da, ANoKeyBindings, No, useGlobalDefault); APPLY_VAL(value, no_bind_keys, ANoKeyBindings); - + value = get_value(dw, dc, dn, da, ANoAppIcon, No, useGlobalDefault); APPLY_VAL(value, no_appicon, ANoAppIcon); - value = get_value(dw, dc, dn, da, ACollapseAppIcons, No, useGlobalDefault); - APPLY_VAL(value, collapse_appicons, ACollapseAppIcons); - + value = get_value(dw, dc, dn, da, ASharedAppIcon, No, useGlobalDefault); + APPLY_VAL(value, shared_appicon, ASharedAppIcon); + value = get_value(dw, dc, dn, da, AKeepOnTop, No, useGlobalDefault); APPLY_VAL(value, floating, AKeepOnTop); diff --git a/src/window.c b/src/window.c index bc880b3d..72a8fc34 100644 --- a/src/window.c +++ b/src/window.c @@ -238,23 +238,33 @@ wWindowDestroy(WWindow *wwin) } } + if (wwin->fake_group) { + if (wwin->fake_group->retainCount > 0) + wwin->fake_group->retainCount--; + if (wwin->fake_group->retainCount==0 && wwin->fake_group->window!=None) { + XDestroyWindow(dpy, wwin->fake_group->window); + wwin->fake_group->window = None; + XFlush(dpy); + } + } + if (wwin->normal_hints) - XFree(wwin->normal_hints); - + XFree(wwin->normal_hints); + if (wwin->wm_hints) - XFree(wwin->wm_hints); - + XFree(wwin->wm_hints); + if (wwin->wm_instance) - XFree(wwin->wm_instance); + XFree(wwin->wm_instance); if (wwin->wm_class) - XFree(wwin->wm_class); + XFree(wwin->wm_class); if (wwin->wm_gnustep_attr) - wfree(wwin->wm_gnustep_attr); + wfree(wwin->wm_gnustep_attr); if (wwin->cmap_windows) - XFree(wwin->cmap_windows); + XFree(wwin->cmap_windows); XDeleteContext(dpy, wwin->client_win, wWinContext); @@ -524,6 +534,45 @@ wWindowObscuresWindow(WWindow *wwin, WWindow *obscured) } +static Window +createFakeWindowGroupLeader(WScreen *scr, Window win, char *instance, char *class) +{ + XClassHint *classHint; + XWMHints *hints; + Window leader; + int argc; + char **argv; + + leader = XCreateSimpleWindow(dpy, scr->root_win, 10, 10, 10, 10, 0, 0, 0); + /* set class hint */ + classHint = XAllocClassHint(); + classHint->res_name = instance; + classHint->res_class = class; + XSetClassHint(dpy, leader, classHint); + XFree(classHint); + + /* set window group leader to self */ + hints = XAllocWMHints(); + hints->window_group = leader; + hints->flags = WindowGroupHint; + XSetWMHints(dpy, leader, hints); + XFree(hints); + + if (XGetCommand(dpy, win, &argv, &argc)!=0 && argc > 0) { + XSetCommand(dpy, leader, argv, argc); + XFreeStringList(argv); + } + + return leader; +} + + +static int +matchIdentifier(void *item, void *cdata) +{ + return (strcmp(((WFakeGroupLeader*)item)->identifier, (char*)cdata)==0); +} + /* *---------------------------------------------------------------- @@ -690,7 +739,7 @@ wManageWindow(WScreen *scr, Window window) } PropGetProtocols(window, &wwin->protocols); - + if (!XGetTransientForHint(dpy, window, &wwin->transient_for)) { wwin->transient_for = None; } else { @@ -744,13 +793,53 @@ wManageWindow(WScreen *scr, Window window) } #endif /* OLWM_HINTS */ - /* - * Make broken apps behave as a nice app. - */ + /* Make broken apps behave as a nice app. */ if (WFLAGP(wwin, emulate_appicon)) { wwin->main_window = wwin->client_win; } + if (!withdraw && wwin->main_window && WFLAGP(wwin, shared_appicon)) { + char *buffer, *instance, *class; + WFakeGroupLeader *fPtr; + int index; + + PropGetWMClass(wwin->main_window, &class, &instance); + buffer = wmalloc(strlen(instance)+strlen(class)+2); + sprintf(buffer, "%s.%s", instance, class); + + index = WMFindInArray(scr->fakeGroupLeaders, matchIdentifier, (void*)buffer); + if (index != WANotFound) { + fPtr = WMGetFromArray(scr->fakeGroupLeaders, index); + if (fPtr->retainCount == 0) { + fPtr->window = createFakeWindowGroupLeader(scr, wwin->main_window, + instance, class); + } + fPtr->retainCount++; + wwin->fake_group = fPtr; + wwin->group_id = fPtr->window; + wwin->main_window = wwin->group_id; + wfree(buffer); + } else { + fPtr = (WFakeGroupLeader*)wmalloc(sizeof(WFakeGroupLeader)); + + fPtr->identifier = buffer; + fPtr->window = createFakeWindowGroupLeader(scr, wwin->main_window, + instance, class); + fPtr->retainCount = 1; + + WMAddToArray(scr->fakeGroupLeaders, fPtr); + + wwin->fake_group = fPtr; + wwin->group_id = fPtr->window; + wwin->main_window = wwin->group_id; + } + if (instance) + XFree(instance); + if (class) + XFree(class); + + } + /* *------------------------------------------------------------ * @@ -1099,6 +1188,8 @@ wManageWindow(WScreen *scr, Window window) if (app) { app->last_workspace = workspace; + app->main_window_desc->fake_group = wwin->fake_group; + /* * Do application specific stuff, like setting application * wide attributes. @@ -1747,47 +1838,23 @@ wWindowUnfocus(WWindow *wwin) void wWindowUpdateName(WWindow *wwin, char *newTitle) { - WApplication *app = wApplicationOf(wwin->main_window); - int instIndex = 0; - char prefix[32] = ""; char *title; if (!wwin->frame) return; - if (app) - instIndex = wApplicationIndexOfGroup(app); - - wwin->flags.wm_name_changed = 1; if (!newTitle) { /* the hint was removed */ title = DEF_WINDOW_TITLE; - - WMPostNotificationName(WMNChangedName, wwin, NULL); } else { title = newTitle; } - -#ifndef NO_WINDOW_ENUMERATOR - if (instIndex > 0) { - snprintf(prefix, sizeof(prefix), " [%i]", instIndex); - - title = wstrconcat(title, prefix); - } -#endif - - if (wFrameWindowChangeTitle(wwin->frame, title)) { + if (wFrameWindowChangeTitle(wwin->frame, title)) { WMPostNotificationName(WMNChangedName, wwin, NULL); } - -#ifndef NO_WINDOW_ENUMERATOR - if (instIndex > 0) - wfree(title); -#endif - } diff --git a/src/window.h b/src/window.h index 4c86dd6f..16a20c03 100644 --- a/src/window.h +++ b/src/window.h @@ -56,7 +56,7 @@ typedef enum { * window attribute flags. * * Note: attributes that should apply to the application as a - * whole should only access the flags from the app->main_window_desc->window_flags + * whole should only access the flags from app->main_window_desc->window_flags * This is to make sure that the application doesn't have many different * values for the same option. For example, imagine xfoo, which has * foo.bar as leader and it a child window named foo.baz. If you set @@ -119,7 +119,7 @@ typedef struct { unsigned int no_hide_others:1; /* hide window when doing hideothers */ unsigned int no_appicon:1; /* make app icon */ - unsigned int collapse_appicons:1; /* collapse icons of the same name */ + unsigned int shared_appicon:1; unsigned int dont_move_off:1; @@ -167,6 +167,16 @@ typedef struct { /* + * Structure used for storing fake window group information + */ +typedef struct WFakeGroupLeader { + char *identifier; + Window window; + int retainCount; +} WFakeGroupLeader; + + +/* * Stores client window information. Each client window has it's * structure created when it's being first mapped. */ @@ -207,20 +217,23 @@ typedef struct WWindow { GNUstepWMAttributes *wm_gnustep_attr;/* GNUstep window attributes */ int state; /* state as in ICCCM */ - + Window transient_for; /* WM_TRANSIENT_FOR */ + + WFakeGroupLeader *fake_group; /* Fake group leader for grouping into + a single appicon */ Window group_id; /* the leader window of the group */ Window client_leader; /* WM_CLIENT_LEADER if not - internal_window */ + internal_window */ Window main_window; /* main window for the application */ - + int cmap_window_no; Window *cmap_windows; - + /* protocols */ WProtocols protocols; /* accepted WM_PROTOCOLS */ - + FocusMode focus_mode; /* type of keyboard input focus */ #ifdef OLWM_HINTS_unfinished diff --git a/src/winspector.c b/src/winspector.c index 1fbf985d..1b2cd83b 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -154,7 +154,7 @@ static WMPropList *AStartMaximized; static WMPropList *ADontSaveSession; static WMPropList *AEmulateAppIcon; static WMPropList *AFullMaximize; -static WMPropList *ACollapseAppIcons; +static WMPropList *ASharedAppIcon; #ifdef XKB_BUTTON_HINT static WMPropList *ANoLanguageButton; #endif @@ -222,7 +222,7 @@ make_keys() ADontSaveSession = WMCreatePLString("DontSaveSession"); AEmulateAppIcon = WMCreatePLString("EmulateAppIcon"); AFullMaximize = WMCreatePLString("FullMaximize"); - ACollapseAppIcons = WMCreatePLString("CollapseAppIcons"); + ASharedAppIcon = WMCreatePLString("SharedAppIcon"); #ifdef XKB_BUTTON_HINT ANoLanguageButton = WMCreatePLString("NoLanguageButton"); #endif @@ -661,7 +661,7 @@ saveSettings(WMButton *button, InspectorPanel *panel) different |= insertAttribute(dict, winDic, ANoAppIcon, value, flags); value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No; - different |= insertAttribute(dict, winDic, ACollapseAppIcons, value, flags); + different |= insertAttribute(dict, winDic, ASharedAppIcon, value, flags); } WMRemoveFromPLDictionary(dict, key); @@ -715,7 +715,7 @@ saveSettings(WMButton *button, InspectorPanel *panel) flags); value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No; - different |= insertAttribute(dict, appDic, ACollapseAppIcons, value, + different |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags); WMRemoveFromPLDictionary(dict, key); @@ -902,7 +902,7 @@ applySettings(WMButton *button, InspectorPanel *panel) WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1])); - WSETUFLAG(wapp->main_window_desc, collapse_appicons, + WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2])); if (WFLAGP(wapp->main_window_desc, no_appicon)) @@ -1040,7 +1040,7 @@ revertSettings(WMButton *button, InspectorPanel *panel) flag = WFLAGP(wapp->main_window_desc, no_appicon); break; case 2: - flag = WFLAGP(wapp->main_window_desc, collapse_appicons); + flag = WFLAGP(wapp->main_window_desc, shared_appicon); break; } WMSetButtonSelected(panel->appChk[i], flag); @@ -1609,10 +1609,10 @@ createInspectorForWindow(WWindow *wwin, int xpos, int ypos, "working correctly."); break; case 2: - caption = _("Collapse application icons"); - flag = WFLAGP(wapp->main_window_desc, collapse_appicons); - descr = _("Collapse application icons from other instances\n" - "of this application into one.\n"); + caption = _("Shared application icon"); + flag = WFLAGP(wapp->main_window_desc, shared_appicon); + descr = _("Use a single shared application icon for all of\n" + "the instances of this application.\n"); break; } panel->appChk[i] = WMCreateSwitchButton(panel->appFrm); -- 2.11.4.GIT