No need to call memset after wmalloc
[wmaker-crm.git] / src / appicon.c
blob198fe53b8316698f1831b01ae636609a47366fa8
1 /* appicon.c- icon for applications (not mini-window)
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "wconfig.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "WindowMaker.h"
31 #include "window.h"
32 #include "icon.h"
33 #include "application.h"
34 #include "appicon.h"
35 #include "actions.h"
36 #include "stacking.h"
37 #include "dock.h"
38 #include "funcs.h"
39 #include "defaults.h"
40 #include "workspace.h"
41 #include "superfluous.h"
42 #include "menu.h"
43 #include "framewin.h"
44 #include "dialog.h"
45 #include "client.h"
46 #ifdef XDND
47 #include "xdnd.h"
48 #endif
51 * icon_file for the dock is got from the preferences file by
52 * using the classname/instancename
55 /**** Global variables ****/
56 extern Cursor wCursor[WCUR_LAST];
57 extern WPreferences wPreferences;
59 #define MOD_MASK wPreferences.modifier_mask
61 void appIconMouseDown(WObjDescriptor * desc, XEvent * event);
62 static void iconDblClick(WObjDescriptor * desc, XEvent * event);
63 static void iconExpose(WObjDescriptor * desc, XEvent * event);
65 WAppIcon *wAppIconCreateForDock(WScreen * scr, char *command, char *wm_instance, char *wm_class, int tile)
67 WAppIcon *dicon;
68 char *path;
70 dicon = wmalloc(sizeof(WAppIcon));
71 wretain(dicon);
72 dicon->yindex = -1;
73 dicon->xindex = -1;
75 dicon->prev = NULL;
76 dicon->next = scr->app_icon_list;
77 if (scr->app_icon_list)
78 scr->app_icon_list->prev = dicon;
80 scr->app_icon_list = dicon;
82 if (command)
83 dicon->command = wstrdup(command);
85 if (wm_class)
86 dicon->wm_class = wstrdup(wm_class);
88 if (wm_instance)
89 dicon->wm_instance = wstrdup(wm_instance);
91 path = wDefaultGetIconFile(scr, wm_instance, wm_class, True);
92 if (!path && command) {
93 wApplicationExtractDirPackIcon(scr, command, wm_instance, wm_class);
94 path = wDefaultGetIconFile(scr, wm_instance, wm_class, False);
97 if (path)
98 path = FindImage(wPreferences.icon_path, path);
100 dicon->icon = wIconCreateWithIconFile(scr, path, tile);
101 if (path)
102 wfree(path);
103 #ifdef XDND
104 wXDNDMakeAwareness(dicon->icon->core->window);
105 #endif
107 /* will be overriden by dock */
108 dicon->icon->core->descriptor.handle_mousedown = appIconMouseDown;
109 dicon->icon->core->descriptor.handle_expose = iconExpose;
110 dicon->icon->core->descriptor.parent_type = WCLASS_APPICON;
111 dicon->icon->core->descriptor.parent = dicon;
112 AddToStackList(dicon->icon->core);
114 return dicon;
117 WAppIcon *wAppIconCreate(WWindow * leader_win)
119 WAppIcon *aicon;
120 WScreen *scr = leader_win->screen_ptr;
122 aicon = wmalloc(sizeof(WAppIcon));
123 wretain(aicon);
125 aicon->yindex = -1;
126 aicon->xindex = -1;
128 aicon->prev = NULL;
129 aicon->next = scr->app_icon_list;
130 if (scr->app_icon_list)
131 scr->app_icon_list->prev = aicon;
133 scr->app_icon_list = aicon;
135 if (leader_win->wm_class)
136 aicon->wm_class = wstrdup(leader_win->wm_class);
138 if (leader_win->wm_instance)
139 aicon->wm_instance = wstrdup(leader_win->wm_instance);
141 aicon->icon = wIconCreate(leader_win);
142 #ifdef XDND
143 wXDNDMakeAwareness(aicon->icon->core->window);
144 #endif
146 /* will be overriden if docked */
147 aicon->icon->core->descriptor.handle_mousedown = appIconMouseDown;
148 aicon->icon->core->descriptor.handle_expose = iconExpose;
149 aicon->icon->core->descriptor.parent_type = WCLASS_APPICON;
150 aicon->icon->core->descriptor.parent = aicon;
151 AddToStackList(aicon->icon->core);
152 aicon->icon->show_title = 0;
153 wIconUpdate(aicon->icon);
155 return aicon;
158 void wAppIconDestroy(WAppIcon * aicon)
160 WScreen *scr = aicon->icon->core->screen_ptr;
162 RemoveFromStackList(aicon->icon->core);
163 wIconDestroy(aicon->icon);
164 if (aicon->command)
165 wfree(aicon->command);
166 #ifdef XDND
167 if (aicon->dnd_command)
168 wfree(aicon->dnd_command);
169 #endif
170 if (aicon->wm_instance)
171 wfree(aicon->wm_instance);
173 if (aicon->wm_class)
174 wfree(aicon->wm_class);
176 if (aicon == scr->app_icon_list) {
177 if (aicon->next)
178 aicon->next->prev = NULL;
179 scr->app_icon_list = aicon->next;
180 } else {
181 if (aicon->next)
182 aicon->next->prev = aicon->prev;
183 if (aicon->prev)
184 aicon->prev->next = aicon->next;
187 aicon->destroyed = 1;
188 wrelease(aicon);
191 static void drawCorner(WIcon * icon)
193 WScreen *scr = icon->core->screen_ptr;
194 XPoint points[3];
196 points[0].x = 1;
197 points[0].y = 1;
198 points[1].x = 12;
199 points[1].y = 1;
200 points[2].x = 1;
201 points[2].y = 12;
202 XFillPolygon(dpy, icon->core->window, scr->icon_title_texture->normal_gc,
203 points, 3, Convex, CoordModeOrigin);
204 XDrawLine(dpy, icon->core->window, scr->icon_title_texture->light_gc, 0, 0, 0, 12);
205 XDrawLine(dpy, icon->core->window, scr->icon_title_texture->light_gc, 0, 0, 12, 0);
208 void wAppIconMove(WAppIcon * aicon, int x, int y)
210 XMoveWindow(dpy, aicon->icon->core->window, x, y);
211 aicon->x_pos = x;
212 aicon->y_pos = y;
215 #ifdef WS_INDICATOR
216 static void updateDockNumbers(WScreen * scr)
218 int length;
219 char *ws_numbers;
220 WAppIcon *dicon = scr->dock->icon_array[0];
222 ws_numbers = wmalloc(20);
223 snprintf(ws_numbers, 20, "%i [ %i ]", scr->current_workspace + 1, ((scr->current_workspace / 10) + 1));
224 length = strlen(ws_numbers);
226 XClearArea(dpy, dicon->icon->core->window, 2, 2, 50, WMFontHeight(scr->icon_title_font) + 1, False);
228 WMDrawString(scr->wmscreen, dicon->icon->core->window, scr->black,
229 scr->icon_title_font, 4, 3, ws_numbers, length);
231 WMDrawString(scr->wmscreen, dicon->icon->core->window, scr->white,
232 scr->icon_title_font, 3, 2, ws_numbers, length);
234 wfree(ws_numbers);
236 #endif /* WS_INDICATOR */
238 void wAppIconPaint(WAppIcon * aicon)
240 WApplication *wapp;
241 WScreen *scr = aicon->icon->core->screen_ptr;
243 if (aicon->icon->owner)
244 wapp = wApplicationOf(aicon->icon->owner->main_window);
245 else
246 wapp = NULL;
248 wIconPaint(aicon->icon);
250 # ifdef WS_INDICATOR
251 if (aicon->docked && scr->dock && scr->dock == aicon->dock && aicon->yindex == 0)
252 updateDockNumbers(scr);
253 # endif
254 if (scr->dock_dots && aicon->docked && !aicon->running && aicon->command != NULL) {
255 XSetClipMask(dpy, scr->copy_gc, scr->dock_dots->mask);
256 XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
257 XCopyArea(dpy, scr->dock_dots->image, aicon->icon->core->window,
258 scr->copy_gc, 0, 0, scr->dock_dots->width, scr->dock_dots->height, 0, 0);
260 #ifdef HIDDENDOT
261 if (wapp && wapp->flags.hidden) {
262 XSetClipMask(dpy, scr->copy_gc, scr->dock_dots->mask);
263 XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
264 XCopyArea(dpy, scr->dock_dots->image,
265 aicon->icon->core->window, scr->copy_gc, 0, 0, 7, scr->dock_dots->height, 0, 0);
267 #endif /* HIDDENDOT */
269 if (aicon->omnipresent)
270 drawCorner(aicon->icon);
272 XSetClipMask(dpy, scr->copy_gc, None);
273 if (aicon->launching)
274 XFillRectangle(dpy, aicon->icon->core->window, scr->stipple_gc,
275 0, 0, wPreferences.icon_size, wPreferences.icon_size);
278 Bool wAppIconSave(WAppIcon *aicon)
280 char *path;
282 if (!aicon->docked || aicon->attracted) return True;
284 path = wIconStore(aicon->icon);
285 if (!path)
286 return False;
288 wApplicationSaveIconPathFor(path, aicon->wm_instance, aicon->wm_class);
290 wfree(path);
291 return True;
294 #define canBeDocked(wwin) ((wwin) && ((wwin)->wm_class||(wwin)->wm_instance))
296 /* main_window may not have the full command line; try to find one which does */
297 static void relaunchApplication(WApplication *wapp)
299 WScreen *scr;
300 WWindow *wlist, *next;
302 scr = wapp->main_window_desc->screen_ptr;
303 wlist = scr->focused_window;
304 if (! wlist)
305 return;
307 while (wlist->prev)
308 wlist = wlist->prev;
310 while (wlist) {
311 next = wlist->next;
313 if (wlist->main_window == wapp->main_window) {
314 if (RelaunchWindow(wlist))
315 return;
318 wlist = next;
322 static void relaunchCallback(WMenu * menu, WMenuEntry * entry)
324 WApplication *wapp = (WApplication *) entry->clientdata;
326 relaunchApplication(wapp);
329 static void hideCallback(WMenu * menu, WMenuEntry * entry)
331 WApplication *wapp = (WApplication *) entry->clientdata;
333 if (wapp->flags.hidden) {
334 wWorkspaceChange(menu->menu->screen_ptr, wapp->last_workspace);
335 wUnhideApplication(wapp, False, False);
336 } else {
337 wHideApplication(wapp);
341 static void unhideHereCallback(WMenu * menu, WMenuEntry * entry)
343 WApplication *wapp = (WApplication *) entry->clientdata;
345 wUnhideApplication(wapp, False, True);
348 static void setIconCallback(WMenu * menu, WMenuEntry * entry)
350 WAppIcon *icon = ((WApplication *) entry->clientdata)->app_icon;
351 char *file = NULL;
352 WScreen *scr;
353 int result;
355 assert(icon != NULL);
357 if (icon->editing)
358 return;
360 icon->editing = 1;
361 scr = icon->icon->core->screen_ptr;
363 wretain(icon);
365 result = wIconChooserDialog(scr, &file, icon->wm_instance, icon->wm_class);
367 if (result && !icon->destroyed) {
368 if (file && *file == 0) {
369 wfree(file);
370 file = NULL;
372 if (!wIconChangeImageFile(icon->icon, file)) {
373 wMessageDialog(scr, _("Error"),
374 _("Could not open specified icon file"), _("OK"), NULL, NULL);
375 } else {
376 wDefaultChangeIcon(scr, icon->wm_instance, icon->wm_class, file);
377 wAppIconPaint(icon);
379 if (file)
380 wfree(file);
382 icon->editing = 0;
383 wrelease(icon);
386 static void killCallback(WMenu * menu, WMenuEntry * entry)
388 WApplication *wapp = (WApplication *) entry->clientdata;
389 WFakeGroupLeader *fPtr;
390 char *buffer;
391 char *shortname;
392 char *basename(const char *shortname);
394 if (!WCHECK_STATE(WSTATE_NORMAL))
395 return;
397 WCHANGE_STATE(WSTATE_MODAL);
399 assert(entry->clientdata != NULL);
401 shortname = basename(wapp->app_icon->wm_instance);
403 buffer = wstrconcat(wapp->app_icon ? shortname : NULL,
404 _(" will be forcibly closed.\n"
405 "Any unsaved changes will be lost.\n" "Please confirm."));
407 fPtr = wapp->main_window_desc->fake_group;
409 wretain(wapp->main_window_desc);
410 if (wPreferences.dont_confirm_kill
411 || wMessageDialog(menu->frame->screen_ptr, _("Kill Application"),
412 buffer, _("Yes"), _("No"), NULL) == WAPRDefault) {
413 if (fPtr != NULL) {
414 WWindow *wwin, *twin;
416 wwin = wapp->main_window_desc->screen_ptr->focused_window;
417 while (wwin) {
418 twin = wwin->prev;
419 if (wwin->fake_group == fPtr)
420 wClientKill(wwin);
421 wwin = twin;
423 } else if (!wapp->main_window_desc->flags.destroyed) {
424 wClientKill(wapp->main_window_desc);
427 wrelease(wapp->main_window_desc);
428 wfree(buffer);
429 WCHANGE_STATE(WSTATE_NORMAL);
432 static WMenu *createApplicationMenu(WScreen * scr)
434 WMenu *menu;
436 menu = wMenuCreate(scr, NULL, False);
437 wMenuAddCallback(menu, _("Launch"), relaunchCallback, NULL);
438 wMenuAddCallback(menu, _("Unhide Here"), unhideHereCallback, NULL);
439 wMenuAddCallback(menu, _("Hide"), hideCallback, NULL);
440 wMenuAddCallback(menu, _("Set Icon..."), setIconCallback, NULL);
441 wMenuAddCallback(menu, _("Kill"), killCallback, NULL);
443 return menu;
446 static void openApplicationMenu(WApplication * wapp, int x, int y)
448 WMenu *menu;
449 WScreen *scr = wapp->main_window_desc->screen_ptr;
450 int i;
452 if (!scr->icon_menu) {
453 scr->icon_menu = createApplicationMenu(scr);
454 wfree(scr->icon_menu->entries[1]->text);
457 menu = scr->icon_menu;
459 if (wapp->flags.hidden)
460 menu->entries[1]->text = _("Unhide");
461 else
462 menu->entries[1]->text = _("Hide");
464 menu->flags.realized = 0;
465 wMenuRealize(menu);
467 x -= menu->frame->core->width / 2;
468 if (x + menu->frame->core->width > scr->scr_width)
469 x = scr->scr_width - menu->frame->core->width;
471 if (x < 0)
472 x = 0;
474 /* set client data */
475 for (i = 0; i < menu->entry_no; i++)
476 menu->entries[i]->clientdata = wapp;
478 wMenuMapAt(menu, x, y, False);
481 /******************************************************************/
483 static void iconExpose(WObjDescriptor * desc, XEvent * event)
485 wAppIconPaint(desc->parent);
488 static void iconDblClick(WObjDescriptor * desc, XEvent * event)
490 WAppIcon *aicon = desc->parent;
491 WApplication *wapp;
492 WScreen *scr = aicon->icon->core->screen_ptr;
493 int unhideHere;
495 assert(aicon->icon->owner != NULL);
497 wapp = wApplicationOf(aicon->icon->owner->main_window);
499 if (event->xbutton.state & ControlMask) {
500 relaunchApplication(wapp);
501 return;
504 unhideHere = (event->xbutton.state & ShiftMask);
505 /* go to the last workspace that the user worked on the app */
506 if (!unhideHere && wapp->last_workspace != scr->current_workspace)
507 wWorkspaceChange(scr, wapp->last_workspace);
509 wUnhideApplication(wapp, event->xbutton.button == Button2, unhideHere);
511 if (event->xbutton.state & MOD_MASK)
512 wHideOtherApplications(aicon->icon->owner);
515 void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
517 WAppIcon *aicon = desc->parent;
518 WIcon *icon = aicon->icon;
519 XEvent ev;
520 int x = aicon->x_pos, y = aicon->y_pos;
521 int dx = event->xbutton.x, dy = event->xbutton.y;
522 int grabbed = 0;
523 int done = 0;
524 int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */
525 WScreen *scr = icon->core->screen_ptr;
526 WWorkspace *workspace = scr->workspaces[scr->current_workspace];
527 int shad_x = 0, shad_y = 0, docking = 0, dockable, collapsed = 0;
528 int ix, iy;
529 int clickButton = event->xbutton.button;
530 Pixmap ghost = None;
531 Window wins[2];
532 Bool movingSingle = False;
533 int oldX = x;
534 int oldY = y;
535 Bool hasMoved = False;
537 if (aicon->editing || WCHECK_STATE(WSTATE_MODAL))
538 return;
540 if (IsDoubleClick(scr, event)) {
541 /* Middle or right mouse actions were handled on first click */
542 if (event->xbutton.button == Button1)
543 iconDblClick(desc, event);
544 return;
547 if (event->xbutton.button == Button2) {
548 WApplication *wapp = wApplicationOf(aicon->icon->owner->main_window);
550 if (!wapp)
551 return;
553 relaunchApplication(wapp);
554 return;
557 if (event->xbutton.button == Button3) {
558 WObjDescriptor *desc;
559 WApplication *wapp = wApplicationOf(aicon->icon->owner->main_window);
561 if (!wapp)
562 return;
564 if (event->xbutton.send_event &&
565 XGrabPointer(dpy, aicon->icon->core->window, True, ButtonMotionMask
566 | ButtonReleaseMask | ButtonPressMask, GrabModeAsync,
567 GrabModeAsync, None, None, CurrentTime) != GrabSuccess) {
568 wwarning("pointer grab failed for appicon menu");
569 return;
572 openApplicationMenu(wapp, event->xbutton.x_root, event->xbutton.y_root);
574 /* allow drag select of menu */
575 desc = &scr->icon_menu->menu->descriptor;
576 event->xbutton.send_event = True;
577 (*desc->handle_mousedown) (desc, event);
578 return;
581 if (event->xbutton.state & MOD_MASK)
582 wLowerFrame(icon->core);
583 else
584 wRaiseFrame(icon->core);
586 if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask
587 | ButtonReleaseMask | ButtonPressMask, GrabModeAsync,
588 GrabModeAsync, None, None, CurrentTime) != GrabSuccess)
589 wwarning("pointer grab failed for appicon move");
591 if (wPreferences.flags.nodock && wPreferences.flags.noclip)
592 dockable = 0;
593 else
594 dockable = canBeDocked(icon->owner);
596 wins[0] = icon->core->window;
597 wins[1] = scr->dock_shadow;
598 XRestackWindows(dpy, wins, 2);
599 if (superfluous) {
600 if (icon->pixmap != None)
601 ghost = MakeGhostIcon(scr, icon->pixmap);
602 else
603 ghost = MakeGhostIcon(scr, icon->core->window);
604 XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost);
605 XClearWindow(dpy, scr->dock_shadow);
608 while (!done) {
609 WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask
610 | ButtonMotionMask | ExposureMask | EnterWindowMask, &ev);
611 switch (ev.type) {
612 case Expose:
613 WMHandleEvent(&ev);
614 break;
616 case EnterNotify:
617 /* It means the cursor moved so fast that it entered
618 * something else (if moving slowly, it would have
619 * stayed in the appIcon that is being moved. Ignore
620 * such "spurious" EnterNotifiy's */
621 break;
623 case MotionNotify:
624 hasMoved = True;
625 if (!grabbed) {
626 if (abs(dx - ev.xmotion.x) >= MOVE_THRESHOLD
627 || abs(dy - ev.xmotion.y) >= MOVE_THRESHOLD) {
628 XChangeActivePointerGrab(dpy, ButtonMotionMask
629 | ButtonReleaseMask | ButtonPressMask,
630 wCursor[WCUR_MOVE], CurrentTime);
631 grabbed = 1;
632 } else {
633 break;
636 x = ev.xmotion.x_root - dx;
637 y = ev.xmotion.y_root - dy;
639 if (movingSingle)
640 XMoveWindow(dpy, icon->core->window, x, y);
641 else
642 wAppIconMove(aicon, x, y);
644 if (dockable) {
645 if (scr->dock && wDockSnapIcon(scr->dock, aicon, x, y, &ix, &iy, False)) {
646 shad_x = scr->dock->x_pos + ix * wPreferences.icon_size;
647 shad_y = scr->dock->y_pos + iy * wPreferences.icon_size;
649 if (scr->last_dock != scr->dock && collapsed) {
650 scr->last_dock->collapsed = 1;
651 wDockHideIcons(scr->last_dock);
652 collapsed = 0;
654 if (!collapsed && (collapsed = scr->dock->collapsed)) {
655 scr->dock->collapsed = 0;
656 wDockShowIcons(scr->dock);
659 if (scr->dock->auto_raise_lower)
660 wDockRaise(scr->dock);
662 scr->last_dock = scr->dock;
664 XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y);
665 if (!docking)
666 XMapWindow(dpy, scr->dock_shadow);
668 docking = 1;
669 } else if (workspace->clip &&
670 wDockSnapIcon(workspace->clip, aicon, x, y, &ix, &iy, False)) {
671 shad_x = workspace->clip->x_pos + ix * wPreferences.icon_size;
672 shad_y = workspace->clip->y_pos + iy * wPreferences.icon_size;
674 if (scr->last_dock != workspace->clip && collapsed) {
675 scr->last_dock->collapsed = 1;
676 wDockHideIcons(scr->last_dock);
677 collapsed = 0;
679 if (!collapsed && (collapsed = workspace->clip->collapsed)) {
680 workspace->clip->collapsed = 0;
681 wDockShowIcons(workspace->clip);
684 if (workspace->clip->auto_raise_lower)
685 wDockRaise(workspace->clip);
687 scr->last_dock = workspace->clip;
689 XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y);
690 if (!docking)
691 XMapWindow(dpy, scr->dock_shadow);
693 docking = 1;
694 } else if (docking) {
695 XUnmapWindow(dpy, scr->dock_shadow);
696 docking = 0;
699 break;
701 case ButtonPress:
702 break;
704 case ButtonRelease:
705 if (ev.xbutton.button != clickButton)
706 break;
707 XUngrabPointer(dpy, CurrentTime);
709 if (docking) {
710 Bool docked;
712 /* icon is trying to be docked */
713 SlideWindow(icon->core->window, x, y, shad_x, shad_y);
714 XUnmapWindow(dpy, scr->dock_shadow);
715 docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy);
716 if (scr->last_dock->auto_collapse)
717 collapsed = 0;
719 if (workspace->clip &&
720 workspace->clip != scr->last_dock && workspace->clip->auto_raise_lower)
721 wDockLower(workspace->clip);
723 if (!docked) {
724 /* If icon could not be docked, slide it back to the old
725 * position */
726 SlideWindow(icon->core->window, x, y, oldX, oldY);
728 } else {
729 if (movingSingle) {
730 /* move back to its place */
731 SlideWindow(icon->core->window, x, y, oldX, oldY);
732 wAppIconMove(aicon, oldX, oldY);
733 } else {
734 XMoveWindow(dpy, icon->core->window, x, y);
735 aicon->x_pos = x;
736 aicon->y_pos = y;
738 if (workspace->clip && workspace->clip->auto_raise_lower)
739 wDockLower(workspace->clip);
741 if (collapsed) {
742 scr->last_dock->collapsed = 1;
743 wDockHideIcons(scr->last_dock);
744 collapsed = 0;
746 if (superfluous) {
747 if (ghost != None)
748 XFreePixmap(dpy, ghost);
749 XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel);
752 if (wPreferences.auto_arrange_icons)
753 wArrangeIcons(scr, True);
755 if (wPreferences.single_click && !hasMoved)
756 iconDblClick(desc, event);
758 done = 1;
759 break;