/* appicon.c- icon for applications (not mini-window) * * Window Maker window manager * * Copyright (c) 1997-2003 Alfredo K. Kojima * Copyright (c) 1998-2003 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "wconfig.h" #include #include #include #include #include #include #include #include "WindowMaker.h" #include "window.h" #include "icon.h" #include "application.h" #include "appicon.h" #include "actions.h" #include "stacking.h" #include "dock.h" #include "main.h" #include "defaults.h" #include "workspace.h" #include "superfluous.h" #include "menu.h" #include "framewin.h" #include "dialog.h" #include "xinerama.h" #include "client.h" #ifdef XDND #include "xdnd.h" #endif /* * icon_file for the dock is got from the preferences file by * using the classname/instancename */ /**** Global variables ****/ extern Cursor wCursor[WCUR_LAST]; extern WPreferences wPreferences; extern WDDomain *WDWindowAttributes; #define MOD_MASK wPreferences.modifier_mask void appIconMouseDown(WObjDescriptor * desc, XEvent * event); static void iconDblClick(WObjDescriptor * desc, XEvent * event); static void iconExpose(WObjDescriptor * desc, XEvent * event); static void wApplicationSaveIconPathFor(char *iconPath, char *wm_instance, char *wm_class); static WAppIcon *wAppIconCreate(WWindow * leader_win); static void add_to_appicon_list(WScreen *scr, WAppIcon *appicon); static void remove_from_appicon_list(WScreen *scr, WAppIcon *appicon); /* This function is used if the application is a .app. It checks if it has an icon in it * like for example /usr/local/GNUstep/Applications/WPrefs.app/WPrefs.tiff */ void wApplicationExtractDirPackIcon(WScreen * scr, char *path, char *wm_instance, char *wm_class) { char *iconPath = NULL; char *tmp = NULL; if (strstr(path, ".app")) { tmp = wmalloc(strlen(path) + 16); if (scr->flags.supports_tiff) { strcpy(tmp, path); strcat(tmp, ".tiff"); if (access(tmp, R_OK) == 0) iconPath = tmp; } if (!iconPath) { strcpy(tmp, path); strcat(tmp, ".xpm"); if (access(tmp, R_OK) == 0) iconPath = tmp; } if (!iconPath) wfree(tmp); if (iconPath) { wApplicationSaveIconPathFor(iconPath, wm_instance, wm_class); wfree(iconPath); } } } WAppIcon *wAppIconCreateForDock(WScreen * scr, char *command, char *wm_instance, char *wm_class, int tile) { WAppIcon *dicon; char *path; dicon = wmalloc(sizeof(WAppIcon)); wretain(dicon); dicon->yindex = -1; dicon->xindex = -1; add_to_appicon_list(scr, dicon); if (command) dicon->command = wstrdup(command); if (wm_class) dicon->wm_class = wstrdup(wm_class); if (wm_instance) dicon->wm_instance = wstrdup(wm_instance); /* Search the icon using instance and class, without default icon */ path = wDefaultGetIconFile(wm_instance, wm_class, False); if (!path && command) { wApplicationExtractDirPackIcon(scr, command, wm_instance, wm_class); /* Search again, now with default icon */ path = wDefaultGetIconFile(wm_instance, wm_class, True); } if (path) path = FindImage(wPreferences.icon_path, path); dicon->icon = wIconCreateWithIconFile(scr, path, tile); if (path) wfree(path); #ifdef XDND wXDNDMakeAwareness(dicon->icon->core->window); #endif /* will be overriden by dock */ dicon->icon->core->descriptor.handle_mousedown = appIconMouseDown; dicon->icon->core->descriptor.handle_expose = iconExpose; dicon->icon->core->descriptor.parent_type = WCLASS_APPICON; dicon->icon->core->descriptor.parent = dicon; AddToStackList(dicon->icon->core); return dicon; } void makeAppIconFor(WApplication * wapp) { /* If app_icon, work is done, return */ if (wapp->app_icon) return; /* Create the icon */ wapp->app_icon = wAppIconCreate(wapp->main_window_desc); /* Now, paint the icon */ if (!WFLAGP(wapp->main_window_desc, no_appicon)) paint_app_icon(wapp); } void paint_app_icon(WApplication *wapp) { WIcon *icon; WScreen *scr = wapp->main_window_desc->screen_ptr; WDock *clip = scr->workspaces[scr->current_workspace]->clip; int x = 0, y = 0; if (!wapp || !wapp->app_icon) return; icon = wapp->app_icon->icon; wapp->app_icon->main_window = wapp->main_window; /* If the icon is docked, don't continue */ if (wapp->app_icon->docked) return; if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) { wapp->app_icon->attracted = 1; if (!icon->shadowed) { icon->shadowed = 1; icon->force_paint = 1; } wDockAttachIcon(clip, wapp->app_icon, x, y); } else { PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc)); wAppIconMove(wapp->app_icon, x, y); wLowerFrame(icon->core); } if (!clip || !wapp->app_icon->attracted || !clip->collapsed) XMapWindow(dpy, icon->core->window); if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted) wArrangeIcons(scr, True); } void removeAppIconFor(WApplication * wapp) { if (!wapp->app_icon) return; if (wapp->app_icon->docked && !wapp->app_icon->attracted) { wapp->app_icon->running = 0; /* since we keep it, we don't care if it was attracted or not */ wapp->app_icon->attracted = 0; wapp->app_icon->icon->shadowed = 0; wapp->app_icon->main_window = None; wapp->app_icon->pid = 0; wapp->app_icon->icon->owner = NULL; wapp->app_icon->icon->icon_win = None; wapp->app_icon->icon->force_paint = 1; wAppIconPaint(wapp->app_icon); } else if (wapp->app_icon->docked) { wapp->app_icon->running = 0; wDockDetach(wapp->app_icon->dock, wapp->app_icon); } else { wAppIconDestroy(wapp->app_icon); } wapp->app_icon = NULL; if (wPreferences.auto_arrange_icons) wArrangeIcons(wapp->main_window_desc->screen_ptr, True); } static WAppIcon *wAppIconCreate(WWindow * leader_win) { WAppIcon *aicon; WScreen *scr = leader_win->screen_ptr; aicon = wmalloc(sizeof(WAppIcon)); wretain(aicon); aicon->yindex = -1; aicon->xindex = -1; /* When no_appicon is set we want to avoid having it on the list * because otherwise there will be a hole when the icons are * arranged with wArrangeIcons() */ if (!WFLAGP(leader_win, no_appicon)) add_to_appicon_list(scr, aicon); if (leader_win->wm_class) aicon->wm_class = wstrdup(leader_win->wm_class); if (leader_win->wm_instance) aicon->wm_instance = wstrdup(leader_win->wm_instance); aicon->icon = wIconCreate(leader_win); #ifdef XDND wXDNDMakeAwareness(aicon->icon->core->window); #endif /* will be overriden if docked */ aicon->icon->core->descriptor.handle_mousedown = appIconMouseDown; aicon->icon->core->descriptor.handle_expose = iconExpose; aicon->icon->core->descriptor.parent_type = WCLASS_APPICON; aicon->icon->core->descriptor.parent = aicon; AddToStackList(aicon->icon->core); aicon->icon->show_title = 0; wIconUpdate(aicon->icon); return aicon; } void wAppIconDestroy(WAppIcon * aicon) { WScreen *scr = aicon->icon->core->screen_ptr; RemoveFromStackList(aicon->icon->core); wIconDestroy(aicon->icon); if (aicon->command) wfree(aicon->command); #ifdef XDND if (aicon->dnd_command) wfree(aicon->dnd_command); #endif if (aicon->wm_instance) wfree(aicon->wm_instance); if (aicon->wm_class) wfree(aicon->wm_class); remove_from_appicon_list(scr, aicon); aicon->destroyed = 1; wrelease(aicon); } static void drawCorner(WIcon * icon) { WScreen *scr = icon->core->screen_ptr; XPoint points[3]; points[0].x = 1; points[0].y = 1; points[1].x = 12; points[1].y = 1; points[2].x = 1; points[2].y = 12; XFillPolygon(dpy, icon->core->window, scr->icon_title_texture->normal_gc, points, 3, Convex, CoordModeOrigin); XDrawLine(dpy, icon->core->window, scr->icon_title_texture->light_gc, 0, 0, 0, 12); XDrawLine(dpy, icon->core->window, scr->icon_title_texture->light_gc, 0, 0, 12, 0); } void wAppIconMove(WAppIcon * aicon, int x, int y) { XMoveWindow(dpy, aicon->icon->core->window, x, y); aicon->x_pos = x; aicon->y_pos = y; } #ifdef WS_INDICATOR static void updateDockNumbers(WScreen * scr) { int length; char *ws_numbers; WAppIcon *dicon = scr->dock->icon_array[0]; ws_numbers = wmalloc(20); snprintf(ws_numbers, 20, "%i [ %i ]", scr->current_workspace + 1, ((scr->current_workspace / 10) + 1)); length = strlen(ws_numbers); XClearArea(dpy, dicon->icon->core->window, 2, 2, 50, WMFontHeight(scr->icon_title_font) + 1, False); WMDrawString(scr->wmscreen, dicon->icon->core->window, scr->black, scr->icon_title_font, 4, 3, ws_numbers, length); WMDrawString(scr->wmscreen, dicon->icon->core->window, scr->white, scr->icon_title_font, 3, 2, ws_numbers, length); wfree(ws_numbers); } #endif /* WS_INDICATOR */ void wAppIconPaint(WAppIcon * aicon) { WApplication *wapp; WScreen *scr = aicon->icon->core->screen_ptr; if (aicon->icon->owner) wapp = wApplicationOf(aicon->icon->owner->main_window); else wapp = NULL; wIconPaint(aicon->icon); # ifdef WS_INDICATOR if (aicon->docked && scr->dock && scr->dock == aicon->dock && aicon->yindex == 0) updateDockNumbers(scr); # endif if (scr->dock_dots && aicon->docked && !aicon->running && aicon->command != NULL) { XSetClipMask(dpy, scr->copy_gc, scr->dock_dots->mask); XSetClipOrigin(dpy, scr->copy_gc, 0, 0); XCopyArea(dpy, scr->dock_dots->image, aicon->icon->core->window, scr->copy_gc, 0, 0, scr->dock_dots->width, scr->dock_dots->height, 0, 0); } #ifdef HIDDENDOT if (wapp && wapp->flags.hidden) { XSetClipMask(dpy, scr->copy_gc, scr->dock_dots->mask); XSetClipOrigin(dpy, scr->copy_gc, 0, 0); XCopyArea(dpy, scr->dock_dots->image, aicon->icon->core->window, scr->copy_gc, 0, 0, 7, scr->dock_dots->height, 0, 0); } #endif /* HIDDENDOT */ if (aicon->omnipresent) drawCorner(aicon->icon); XSetClipMask(dpy, scr->copy_gc, None); if (aicon->launching) XFillRectangle(dpy, aicon->icon->core->window, scr->stipple_gc, 0, 0, wPreferences.icon_size, wPreferences.icon_size); } /* Save the application icon, if it's a dockapp then use it with dock = True */ void save_appicon(WAppIcon *aicon, Bool dock) { char *path; if (!aicon) return; if (dock && (!aicon->docked || aicon->attracted)) return; path = wIconStore(aicon->icon); if (!path) return; wApplicationSaveIconPathFor(path, aicon->wm_instance, aicon->wm_class); wfree(path); } #define canBeDocked(wwin) ((wwin) && ((wwin)->wm_class||(wwin)->wm_instance)) /* main_window may not have the full command line; try to find one which does */ static void relaunchApplication(WApplication *wapp) { WScreen *scr; WWindow *wlist, *next; scr = wapp->main_window_desc->screen_ptr; wlist = scr->focused_window; if (! wlist) return; while (wlist->prev) wlist = wlist->prev; while (wlist) { next = wlist->next; if (wlist->main_window == wapp->main_window) { if (RelaunchWindow(wlist)) return; } wlist = next; } } static void relaunchCallback(WMenu * menu, WMenuEntry * entry) { WApplication *wapp = (WApplication *) entry->clientdata; relaunchApplication(wapp); } static void hideCallback(WMenu * menu, WMenuEntry * entry) { WApplication *wapp = (WApplication *) entry->clientdata; if (wapp->flags.hidden) { wWorkspaceChange(menu->menu->screen_ptr, wapp->last_workspace); wUnhideApplication(wapp, False, False); } else { wHideApplication(wapp); } } static void unhideHereCallback(WMenu * menu, WMenuEntry * entry) { WApplication *wapp = (WApplication *) entry->clientdata; wUnhideApplication(wapp, False, True); } static void setIconCallback(WMenu * menu, WMenuEntry * entry) { WAppIcon *icon = ((WApplication *) entry->clientdata)->app_icon; char *file = NULL; WScreen *scr; int result; assert(icon != NULL); if (icon->editing) return; icon->editing = 1; scr = icon->icon->core->screen_ptr; wretain(icon); result = wIconChooserDialog(scr, &file, icon->wm_instance, icon->wm_class); if (result && !icon->destroyed) { if (file && *file == 0) { wfree(file); file = NULL; } if (!wIconChangeImageFile(icon->icon, file)) { wMessageDialog(scr, _("Error"), _("Could not open specified icon file"), _("OK"), NULL, NULL); } else { wDefaultChangeIcon(scr, icon->wm_instance, icon->wm_class, file); wAppIconPaint(icon); } if (file) wfree(file); } icon->editing = 0; wrelease(icon); } static void killCallback(WMenu * menu, WMenuEntry * entry) { WApplication *wapp = (WApplication *) entry->clientdata; WFakeGroupLeader *fPtr; char *buffer; char *shortname; char *basename(const char *shortname); if (!WCHECK_STATE(WSTATE_NORMAL)) return; WCHANGE_STATE(WSTATE_MODAL); assert(entry->clientdata != NULL); shortname = basename(wapp->app_icon->wm_instance); buffer = wstrconcat(wapp->app_icon ? shortname : NULL, _(" will be forcibly closed.\n" "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 (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); wfree(buffer); WCHANGE_STATE(WSTATE_NORMAL); } static WMenu *createApplicationMenu(WScreen * scr) { WMenu *menu; menu = wMenuCreate(scr, NULL, False); wMenuAddCallback(menu, _("Launch"), relaunchCallback, NULL); wMenuAddCallback(menu, _("Unhide Here"), unhideHereCallback, NULL); wMenuAddCallback(menu, _("Hide"), hideCallback, NULL); wMenuAddCallback(menu, _("Set Icon..."), setIconCallback, NULL); wMenuAddCallback(menu, _("Kill"), killCallback, NULL); return menu; } static void openApplicationMenu(WApplication * wapp, int x, int y) { WMenu *menu; WScreen *scr = wapp->main_window_desc->screen_ptr; int i; if (!scr->icon_menu) { scr->icon_menu = createApplicationMenu(scr); wfree(scr->icon_menu->entries[1]->text); } menu = scr->icon_menu; if (wapp->flags.hidden) menu->entries[1]->text = _("Unhide"); else menu->entries[1]->text = _("Hide"); menu->flags.realized = 0; wMenuRealize(menu); x -= menu->frame->core->width / 2; if (x + menu->frame->core->width > scr->scr_width) x = scr->scr_width - menu->frame->core->width; if (x < 0) x = 0; /* set client data */ for (i = 0; i < menu->entry_no; i++) menu->entries[i]->clientdata = wapp; wMenuMapAt(menu, x, y, False); } /******************************************************************/ static void iconExpose(WObjDescriptor * desc, XEvent * event) { wAppIconPaint(desc->parent); } static void iconDblClick(WObjDescriptor * desc, XEvent * event) { WAppIcon *aicon = desc->parent; WApplication *wapp; WScreen *scr = aicon->icon->core->screen_ptr; int unhideHere; assert(aicon->icon->owner != NULL); wapp = wApplicationOf(aicon->icon->owner->main_window); if (event->xbutton.state & ControlMask) { relaunchApplication(wapp); return; } unhideHere = (event->xbutton.state & ShiftMask); /* go to the last workspace that the user worked on the app */ if (!unhideHere && wapp->last_workspace != scr->current_workspace) wWorkspaceChange(scr, wapp->last_workspace); wUnhideApplication(wapp, event->xbutton.button == Button2, unhideHere); if (event->xbutton.state & MOD_MASK) wHideOtherApplications(aicon->icon->owner); } void appIconMouseDown(WObjDescriptor * desc, XEvent * event) { WAppIcon *aicon = desc->parent; WIcon *icon = aicon->icon; XEvent ev; int x = aicon->x_pos, y = aicon->y_pos; int dx = event->xbutton.x, dy = event->xbutton.y; int grabbed = 0; int done = 0; int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ WScreen *scr = icon->core->screen_ptr; WWorkspace *workspace = scr->workspaces[scr->current_workspace]; int shad_x = 0, shad_y = 0, docking = 0, dockable, collapsed = 0; int ix, iy; int clickButton = event->xbutton.button; Pixmap ghost = None; Window wins[2]; Bool movingSingle = False; int oldX = x; int oldY = y; Bool hasMoved = False; if (aicon->editing || WCHECK_STATE(WSTATE_MODAL)) return; if (IsDoubleClick(scr, event)) { /* Middle or right mouse actions were handled on first click */ if (event->xbutton.button == Button1) iconDblClick(desc, event); return; } if (event->xbutton.button == Button2) { WApplication *wapp = wApplicationOf(aicon->icon->owner->main_window); if (wapp) relaunchApplication(wapp); return; } if (event->xbutton.button == Button3) { WObjDescriptor *desc; WApplication *wapp = wApplicationOf(aicon->icon->owner->main_window); if (!wapp) return; if (event->xbutton.send_event && XGrabPointer(dpy, aicon->icon->core->window, True, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) != GrabSuccess) { wwarning("pointer grab failed for appicon menu"); return; } openApplicationMenu(wapp, event->xbutton.x_root, event->xbutton.y_root); /* allow drag select of menu */ desc = &scr->icon_menu->menu->descriptor; event->xbutton.send_event = True; (*desc->handle_mousedown) (desc, event); return; } if (event->xbutton.state & MOD_MASK) wLowerFrame(icon->core); else wRaiseFrame(icon->core); if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) != GrabSuccess) wwarning("pointer grab failed for appicon move"); if (wPreferences.flags.nodock && wPreferences.flags.noclip) dockable = 0; else dockable = canBeDocked(icon->owner); wins[0] = icon->core->window; wins[1] = scr->dock_shadow; XRestackWindows(dpy, wins, 2); if (superfluous) { if (icon->pixmap != None) ghost = MakeGhostIcon(scr, icon->pixmap); else ghost = MakeGhostIcon(scr, icon->core->window); XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); XClearWindow(dpy, scr->dock_shadow); } while (!done) { WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask | ButtonMotionMask | ExposureMask | EnterWindowMask, &ev); switch (ev.type) { case Expose: WMHandleEvent(&ev); break; case EnterNotify: /* It means the cursor moved so fast that it entered * something else (if moving slowly, it would have * stayed in the appIcon that is being moved. Ignore * such "spurious" EnterNotifiy's */ break; case MotionNotify: hasMoved = True; if (!grabbed) { if (abs(dx - ev.xmotion.x) >= MOVE_THRESHOLD || abs(dy - ev.xmotion.y) >= MOVE_THRESHOLD) { XChangeActivePointerGrab(dpy, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, wCursor[WCUR_MOVE], CurrentTime); grabbed = 1; } else { break; } } x = ev.xmotion.x_root - dx; y = ev.xmotion.y_root - dy; if (movingSingle) XMoveWindow(dpy, icon->core->window, x, y); else wAppIconMove(aicon, x, y); if (dockable) { if (scr->dock && wDockSnapIcon(scr->dock, aicon, x, y, &ix, &iy, False)) { shad_x = scr->dock->x_pos + ix * wPreferences.icon_size; shad_y = scr->dock->y_pos + iy * wPreferences.icon_size; if (scr->last_dock != scr->dock && collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (!collapsed && (collapsed = scr->dock->collapsed)) { scr->dock->collapsed = 0; wDockShowIcons(scr->dock); } if (scr->dock->auto_raise_lower) wDockRaise(scr->dock); scr->last_dock = scr->dock; XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); if (!docking) XMapWindow(dpy, scr->dock_shadow); docking = 1; } else if (workspace->clip && wDockSnapIcon(workspace->clip, aicon, x, y, &ix, &iy, False)) { shad_x = workspace->clip->x_pos + ix * wPreferences.icon_size; shad_y = workspace->clip->y_pos + iy * wPreferences.icon_size; if (scr->last_dock != workspace->clip && collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (!collapsed && (collapsed = workspace->clip->collapsed)) { workspace->clip->collapsed = 0; wDockShowIcons(workspace->clip); } if (workspace->clip->auto_raise_lower) wDockRaise(workspace->clip); scr->last_dock = workspace->clip; XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); if (!docking) XMapWindow(dpy, scr->dock_shadow); docking = 1; } else if (docking) { XUnmapWindow(dpy, scr->dock_shadow); docking = 0; } } break; case ButtonPress: break; case ButtonRelease: if (ev.xbutton.button != clickButton) break; XUngrabPointer(dpy, CurrentTime); if (docking) { Bool docked; /* icon is trying to be docked */ SlideWindow(icon->core->window, x, y, shad_x, shad_y); XUnmapWindow(dpy, scr->dock_shadow); docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy); if (scr->last_dock->auto_collapse) collapsed = 0; if (workspace->clip && workspace->clip != scr->last_dock && workspace->clip->auto_raise_lower) 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 { if (movingSingle) { /* move back to its place */ SlideWindow(icon->core->window, x, y, oldX, oldY); wAppIconMove(aicon, oldX, oldY); } else { XMoveWindow(dpy, icon->core->window, x, y); aicon->x_pos = x; aicon->y_pos = y; } if (workspace->clip && workspace->clip->auto_raise_lower) wDockLower(workspace->clip); } if (collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (superfluous) { if (ghost != None) XFreePixmap(dpy, ghost); XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel); } if (wPreferences.auto_arrange_icons) wArrangeIcons(scr, True); if (wPreferences.single_click && !hasMoved) iconDblClick(desc, event); done = 1; break; } } } /* This function save the application icon and store the path in the Dictionary */ static void wApplicationSaveIconPathFor(char *iconPath, char *wm_instance, char *wm_class) { WMPropList *dict = WDWindowAttributes->dictionary; WMPropList *adict, *key, *iconk; WMPropList *val; char *tmp; tmp = get_name_for_instance_class(wm_instance, wm_class); key = WMCreatePLString(tmp); wfree(tmp); adict = WMGetFromPLDictionary(dict, key); iconk = WMCreatePLString("Icon"); if (adict) { val = WMGetFromPLDictionary(adict, iconk); } else { /* no dictionary for app, so create one */ adict = WMCreatePLDictionary(NULL, NULL); WMPutInPLDictionary(dict, key, adict); WMReleasePropList(adict); val = NULL; } if (!val) { val = WMCreatePLString(iconPath); WMPutInPLDictionary(adict, iconk, val); WMReleasePropList(val); } else { val = NULL; } WMReleasePropList(key); WMReleasePropList(iconk); if (val && !wPreferences.flags.noupdates) UpdateDomainFile(WDWindowAttributes); } static WAppIcon *findDockIconFor(WDock *dock, Window main_window) { WAppIcon *aicon = NULL; aicon = wDockFindIconForWindow(dock, main_window); if (!aicon) { wDockTrackWindowLaunch(dock, main_window); aicon = wDockFindIconForWindow(dock, main_window); } return aicon; } void create_appicon_from_dock(WWindow *wwin, WApplication *wapp, Window main_window) { WScreen *scr = wwin->screen_ptr; wapp->app_icon = NULL; if (scr->last_dock) wapp->app_icon = findDockIconFor(scr->last_dock, main_window); /* check main dock if we did not find it in last dock */ if (!wapp->app_icon && scr->dock) wapp->app_icon = findDockIconFor(scr->dock, main_window); /* finally check clips */ if (!wapp->app_icon) { int i; for (i = 0; i < scr->workspace_count; i++) { WDock *dock = scr->workspaces[i]->clip; if (dock) wapp->app_icon = findDockIconFor(dock, main_window); if (wapp->app_icon) break; } } /* If created, then set some flags */ if (wapp->app_icon) { WWindow *mainw = wapp->main_window_desc; wapp->app_icon->running = 1; wapp->app_icon->icon->force_paint = 1; wapp->app_icon->icon->owner = mainw; if (mainw->wm_hints && (mainw->wm_hints->flags & IconWindowHint)) wapp->app_icon->icon->icon_win = mainw->wm_hints->icon_window; wAppIconPaint(wapp->app_icon); save_appicon(wapp->app_icon, True); } } /* Add the appicon to the appiconlist */ static void add_to_appicon_list(WScreen *scr, WAppIcon *appicon) { appicon->prev = NULL; appicon->next = scr->app_icon_list; if (scr->app_icon_list) scr->app_icon_list->prev = appicon; scr->app_icon_list = appicon; } /* Remove the appicon from the appiconlist */ static void remove_from_appicon_list(WScreen *scr, WAppIcon *appicon) { if (appicon == scr->app_icon_list) { if (appicon->next) appicon->next->prev = NULL; scr->app_icon_list = appicon->next; } else { if (appicon->next) appicon->next->prev = appicon->prev; if (appicon->prev) appicon->prev->next = appicon->next; } }