Files
wmaker/src/appicon.c
T
Carlos R. Mafra a1e80f5411 Unify save_appicon() and wAppIconSave()
Having two similarly named functions for doing the same thing is confusing.
In order to account for the extra check done by the late wAppIconSave(),
add an argument "dock".

Now there's only save_appicon().

And as pointed out by Rodolfo kix García, the save_appicon_core() function
can be removed too.

Signed-off-by: Carlos R. Mafra <crmafra@gmail.com>
2012-06-21 20:34:22 +01:00

978 lines
25 KiB
C

/* 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 <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#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 "funcs.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);
/* 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
*/
static 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;
dicon->prev = NULL;
dicon->next = scr->app_icon_list;
if (scr->app_icon_list)
scr->app_icon_list->prev = dicon;
scr->app_icon_list = 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);
path = wDefaultGetIconFile(scr, wm_instance, wm_class, True);
if (!path && command) {
wApplicationExtractDirPackIcon(scr, command, wm_instance, wm_class);
path = wDefaultGetIconFile(scr, wm_instance, wm_class, False);
}
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;
aicon->prev = NULL;
aicon->next = scr->app_icon_list;
if (scr->app_icon_list)
scr->app_icon_list->prev = aicon;
scr->app_icon_list = 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);
if (aicon == scr->app_icon_list) {
if (aicon->next)
aicon->next->prev = NULL;
scr->app_icon_list = aicon->next;
} else {
if (aicon->next)
aicon->next->prev = aicon->prev;
if (aicon->prev)
aicon->prev->next = aicon->next;
}
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);
}
}