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.
26 #include <X11/Xutil.h>
33 #include "WindowMaker.h"
36 #include "application.h"
43 #include "workspace.h"
44 #include "superfluous.h"
55 * icon_file for the dock is got from the preferences file by
56 * using the classname/instancename
59 /**** Global variables ****/
60 extern Cursor wCursor
[WCUR_LAST
];
61 extern WPreferences wPreferences
;
62 extern WDDomain
*WDWindowAttributes
;
64 #define MOD_MASK wPreferences.modifier_mask
66 void appIconMouseDown(WObjDescriptor
* desc
, XEvent
* event
);
67 static void iconDblClick(WObjDescriptor
* desc
, XEvent
* event
);
68 static void iconExpose(WObjDescriptor
* desc
, XEvent
* event
);
69 static void wApplicationSaveIconPathFor(char *iconPath
, char *wm_instance
, char *wm_class
);
70 static WAppIcon
*wAppIconCreate(WWindow
* leader_win
);
72 /* This function is used if the application is a .app. It checks if it has an icon in it
73 * like for example /usr/local/GNUstep/Applications/WPrefs.app/WPrefs.tiff
75 static void wApplicationExtractDirPackIcon(WScreen
* scr
, char *path
, char *wm_instance
, char *wm_class
)
77 char *iconPath
= NULL
;
80 if (strstr(path
, ".app")) {
81 tmp
= wmalloc(strlen(path
) + 16);
83 if (scr
->flags
.supports_tiff
) {
86 if (access(tmp
, R_OK
) == 0)
93 if (access(tmp
, R_OK
) == 0)
101 wApplicationSaveIconPathFor(iconPath
, wm_instance
, wm_class
);
107 WAppIcon
*wAppIconCreateForDock(WScreen
* scr
, char *command
, char *wm_instance
, char *wm_class
, int tile
)
112 dicon
= wmalloc(sizeof(WAppIcon
));
118 dicon
->next
= scr
->app_icon_list
;
119 if (scr
->app_icon_list
)
120 scr
->app_icon_list
->prev
= dicon
;
122 scr
->app_icon_list
= dicon
;
125 dicon
->command
= wstrdup(command
);
128 dicon
->wm_class
= wstrdup(wm_class
);
131 dicon
->wm_instance
= wstrdup(wm_instance
);
133 path
= wDefaultGetIconFile(scr
, wm_instance
, wm_class
, True
);
134 if (!path
&& command
) {
135 wApplicationExtractDirPackIcon(scr
, command
, wm_instance
, wm_class
);
136 path
= wDefaultGetIconFile(scr
, wm_instance
, wm_class
, False
);
140 path
= FindImage(wPreferences
.icon_path
, path
);
142 dicon
->icon
= wIconCreateWithIconFile(scr
, path
, tile
);
146 wXDNDMakeAwareness(dicon
->icon
->core
->window
);
149 /* will be overriden by dock */
150 dicon
->icon
->core
->descriptor
.handle_mousedown
= appIconMouseDown
;
151 dicon
->icon
->core
->descriptor
.handle_expose
= iconExpose
;
152 dicon
->icon
->core
->descriptor
.parent_type
= WCLASS_APPICON
;
153 dicon
->icon
->core
->descriptor
.parent
= dicon
;
154 AddToStackList(dicon
->icon
->core
);
159 void makeAppIconFor(WApplication
* wapp
)
161 /* If app_icon, work is done, return */
165 /* Create the icon */
166 wapp
->app_icon
= wAppIconCreate(wapp
->main_window_desc
);
168 /* Now, paint the icon */
169 if (!WFLAGP(wapp
->main_window_desc
, no_appicon
))
170 paint_app_icon(wapp
);
173 void paint_app_icon(WApplication
*wapp
)
176 WScreen
*scr
= wapp
->main_window_desc
->screen_ptr
;
177 WDock
*clip
= scr
->workspaces
[scr
->current_workspace
]->clip
;
180 if (!wapp
|| !wapp
->app_icon
)
183 icon
= wapp
->app_icon
->icon
;
184 wapp
->app_icon
->main_window
= wapp
->main_window
;
186 /* If the icon is docked, don't continue */
187 if (wapp
->app_icon
->docked
)
190 if (clip
&& clip
->attract_icons
&& wDockFindFreeSlot(clip
, &x
, &y
)) {
191 wapp
->app_icon
->attracted
= 1;
192 if (!icon
->shadowed
) {
194 icon
->force_paint
= 1;
196 wDockAttachIcon(clip
, wapp
->app_icon
, x
, y
);
198 PlaceIcon(scr
, &x
, &y
, wGetHeadForWindow(wapp
->main_window_desc
));
199 wAppIconMove(wapp
->app_icon
, x
, y
);
200 wLowerFrame(icon
->core
);
203 if (!clip
|| !wapp
->app_icon
->attracted
|| !clip
->collapsed
)
204 XMapWindow(dpy
, icon
->core
->window
);
206 if (wPreferences
.auto_arrange_icons
&& !wapp
->app_icon
->attracted
)
207 wArrangeIcons(scr
, True
);
210 void removeAppIconFor(WApplication
* wapp
)
215 if (wapp
->app_icon
->docked
&& !wapp
->app_icon
->attracted
) {
216 wapp
->app_icon
->running
= 0;
217 /* since we keep it, we don't care if it was attracted or not */
218 wapp
->app_icon
->attracted
= 0;
219 wapp
->app_icon
->icon
->shadowed
= 0;
220 wapp
->app_icon
->main_window
= None
;
221 wapp
->app_icon
->pid
= 0;
222 wapp
->app_icon
->icon
->owner
= NULL
;
223 wapp
->app_icon
->icon
->icon_win
= None
;
224 wapp
->app_icon
->icon
->force_paint
= 1;
225 wAppIconPaint(wapp
->app_icon
);
226 } else if (wapp
->app_icon
->docked
) {
227 wapp
->app_icon
->running
= 0;
228 wDockDetach(wapp
->app_icon
->dock
, wapp
->app_icon
);
230 wAppIconDestroy(wapp
->app_icon
);
233 wapp
->app_icon
= NULL
;
235 if (wPreferences
.auto_arrange_icons
)
236 wArrangeIcons(wapp
->main_window_desc
->screen_ptr
, True
);
239 static WAppIcon
*wAppIconCreate(WWindow
* leader_win
)
242 WScreen
*scr
= leader_win
->screen_ptr
;
244 aicon
= wmalloc(sizeof(WAppIcon
));
251 aicon
->next
= scr
->app_icon_list
;
252 if (scr
->app_icon_list
)
253 scr
->app_icon_list
->prev
= aicon
;
255 scr
->app_icon_list
= aicon
;
257 if (leader_win
->wm_class
)
258 aicon
->wm_class
= wstrdup(leader_win
->wm_class
);
260 if (leader_win
->wm_instance
)
261 aicon
->wm_instance
= wstrdup(leader_win
->wm_instance
);
263 aicon
->icon
= wIconCreate(leader_win
);
265 wXDNDMakeAwareness(aicon
->icon
->core
->window
);
268 /* will be overriden if docked */
269 aicon
->icon
->core
->descriptor
.handle_mousedown
= appIconMouseDown
;
270 aicon
->icon
->core
->descriptor
.handle_expose
= iconExpose
;
271 aicon
->icon
->core
->descriptor
.parent_type
= WCLASS_APPICON
;
272 aicon
->icon
->core
->descriptor
.parent
= aicon
;
273 AddToStackList(aicon
->icon
->core
);
274 aicon
->icon
->show_title
= 0;
275 wIconUpdate(aicon
->icon
);
280 void wAppIconDestroy(WAppIcon
* aicon
)
282 WScreen
*scr
= aicon
->icon
->core
->screen_ptr
;
284 RemoveFromStackList(aicon
->icon
->core
);
285 wIconDestroy(aicon
->icon
);
287 wfree(aicon
->command
);
289 if (aicon
->dnd_command
)
290 wfree(aicon
->dnd_command
);
292 if (aicon
->wm_instance
)
293 wfree(aicon
->wm_instance
);
296 wfree(aicon
->wm_class
);
298 if (aicon
== scr
->app_icon_list
) {
300 aicon
->next
->prev
= NULL
;
301 scr
->app_icon_list
= aicon
->next
;
304 aicon
->next
->prev
= aicon
->prev
;
306 aicon
->prev
->next
= aicon
->next
;
309 aicon
->destroyed
= 1;
313 static void drawCorner(WIcon
* icon
)
315 WScreen
*scr
= icon
->core
->screen_ptr
;
324 XFillPolygon(dpy
, icon
->core
->window
, scr
->icon_title_texture
->normal_gc
,
325 points
, 3, Convex
, CoordModeOrigin
);
326 XDrawLine(dpy
, icon
->core
->window
, scr
->icon_title_texture
->light_gc
, 0, 0, 0, 12);
327 XDrawLine(dpy
, icon
->core
->window
, scr
->icon_title_texture
->light_gc
, 0, 0, 12, 0);
330 void wAppIconMove(WAppIcon
* aicon
, int x
, int y
)
332 XMoveWindow(dpy
, aicon
->icon
->core
->window
, x
, y
);
338 static void updateDockNumbers(WScreen
* scr
)
342 WAppIcon
*dicon
= scr
->dock
->icon_array
[0];
344 ws_numbers
= wmalloc(20);
345 snprintf(ws_numbers
, 20, "%i [ %i ]", scr
->current_workspace
+ 1, ((scr
->current_workspace
/ 10) + 1));
346 length
= strlen(ws_numbers
);
348 XClearArea(dpy
, dicon
->icon
->core
->window
, 2, 2, 50, WMFontHeight(scr
->icon_title_font
) + 1, False
);
350 WMDrawString(scr
->wmscreen
, dicon
->icon
->core
->window
, scr
->black
,
351 scr
->icon_title_font
, 4, 3, ws_numbers
, length
);
353 WMDrawString(scr
->wmscreen
, dicon
->icon
->core
->window
, scr
->white
,
354 scr
->icon_title_font
, 3, 2, ws_numbers
, length
);
358 #endif /* WS_INDICATOR */
360 void wAppIconPaint(WAppIcon
* aicon
)
363 WScreen
*scr
= aicon
->icon
->core
->screen_ptr
;
365 if (aicon
->icon
->owner
)
366 wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
370 wIconPaint(aicon
->icon
);
373 if (aicon
->docked
&& scr
->dock
&& scr
->dock
== aicon
->dock
&& aicon
->yindex
== 0)
374 updateDockNumbers(scr
);
376 if (scr
->dock_dots
&& aicon
->docked
&& !aicon
->running
&& aicon
->command
!= NULL
) {
377 XSetClipMask(dpy
, scr
->copy_gc
, scr
->dock_dots
->mask
);
378 XSetClipOrigin(dpy
, scr
->copy_gc
, 0, 0);
379 XCopyArea(dpy
, scr
->dock_dots
->image
, aicon
->icon
->core
->window
,
380 scr
->copy_gc
, 0, 0, scr
->dock_dots
->width
, scr
->dock_dots
->height
, 0, 0);
383 if (wapp
&& wapp
->flags
.hidden
) {
384 XSetClipMask(dpy
, scr
->copy_gc
, scr
->dock_dots
->mask
);
385 XSetClipOrigin(dpy
, scr
->copy_gc
, 0, 0);
386 XCopyArea(dpy
, scr
->dock_dots
->image
,
387 aicon
->icon
->core
->window
, scr
->copy_gc
, 0, 0, 7, scr
->dock_dots
->height
, 0, 0);
389 #endif /* HIDDENDOT */
391 if (aicon
->omnipresent
)
392 drawCorner(aicon
->icon
);
394 XSetClipMask(dpy
, scr
->copy_gc
, None
);
395 if (aicon
->launching
)
396 XFillRectangle(dpy
, aicon
->icon
->core
->window
, scr
->stipple_gc
,
397 0, 0, wPreferences
.icon_size
, wPreferences
.icon_size
);
400 /* Internal application to save the application icon */
401 static void save_app_icon_core(WAppIcon
*aicon
)
405 path
= wIconStore(aicon
->icon
);
409 wApplicationSaveIconPathFor(path
, aicon
->wm_instance
, aicon
->wm_class
);
414 /* Save the application icon */
415 /* This function is used when the icon doesn't have window, like dock or clip */
416 void wAppIconSave(WAppIcon
*aicon
)
418 if (!aicon
->docked
|| aicon
->attracted
)
421 save_app_icon_core(aicon
);
424 #define canBeDocked(wwin) ((wwin) && ((wwin)->wm_class||(wwin)->wm_instance))
426 /* main_window may not have the full command line; try to find one which does */
427 static void relaunchApplication(WApplication
*wapp
)
430 WWindow
*wlist
, *next
;
432 scr
= wapp
->main_window_desc
->screen_ptr
;
433 wlist
= scr
->focused_window
;
443 if (wlist
->main_window
== wapp
->main_window
) {
444 if (RelaunchWindow(wlist
))
452 static void relaunchCallback(WMenu
* menu
, WMenuEntry
* entry
)
454 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
456 relaunchApplication(wapp
);
459 static void hideCallback(WMenu
* menu
, WMenuEntry
* entry
)
461 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
463 if (wapp
->flags
.hidden
) {
464 wWorkspaceChange(menu
->menu
->screen_ptr
, wapp
->last_workspace
);
465 wUnhideApplication(wapp
, False
, False
);
467 wHideApplication(wapp
);
471 static void unhideHereCallback(WMenu
* menu
, WMenuEntry
* entry
)
473 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
475 wUnhideApplication(wapp
, False
, True
);
478 static void setIconCallback(WMenu
* menu
, WMenuEntry
* entry
)
480 WAppIcon
*icon
= ((WApplication
*) entry
->clientdata
)->app_icon
;
485 assert(icon
!= NULL
);
491 scr
= icon
->icon
->core
->screen_ptr
;
495 result
= wIconChooserDialog(scr
, &file
, icon
->wm_instance
, icon
->wm_class
);
497 if (result
&& !icon
->destroyed
) {
498 if (file
&& *file
== 0) {
502 if (!wIconChangeImageFile(icon
->icon
, file
)) {
503 wMessageDialog(scr
, _("Error"),
504 _("Could not open specified icon file"), _("OK"), NULL
, NULL
);
506 wDefaultChangeIcon(scr
, icon
->wm_instance
, icon
->wm_class
, file
);
516 static void killCallback(WMenu
* menu
, WMenuEntry
* entry
)
518 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
519 WFakeGroupLeader
*fPtr
;
522 char *basename(const char *shortname
);
524 if (!WCHECK_STATE(WSTATE_NORMAL
))
527 WCHANGE_STATE(WSTATE_MODAL
);
529 assert(entry
->clientdata
!= NULL
);
531 shortname
= basename(wapp
->app_icon
->wm_instance
);
533 buffer
= wstrconcat(wapp
->app_icon
? shortname
: NULL
,
534 _(" will be forcibly closed.\n"
535 "Any unsaved changes will be lost.\n" "Please confirm."));
537 fPtr
= wapp
->main_window_desc
->fake_group
;
539 wretain(wapp
->main_window_desc
);
540 if (wPreferences
.dont_confirm_kill
541 || wMessageDialog(menu
->frame
->screen_ptr
, _("Kill Application"),
542 buffer
, _("Yes"), _("No"), NULL
) == WAPRDefault
) {
544 WWindow
*wwin
, *twin
;
546 wwin
= wapp
->main_window_desc
->screen_ptr
->focused_window
;
549 if (wwin
->fake_group
== fPtr
)
553 } else if (!wapp
->main_window_desc
->flags
.destroyed
) {
554 wClientKill(wapp
->main_window_desc
);
557 wrelease(wapp
->main_window_desc
);
559 WCHANGE_STATE(WSTATE_NORMAL
);
562 static WMenu
*createApplicationMenu(WScreen
* scr
)
566 menu
= wMenuCreate(scr
, NULL
, False
);
567 wMenuAddCallback(menu
, _("Launch"), relaunchCallback
, NULL
);
568 wMenuAddCallback(menu
, _("Unhide Here"), unhideHereCallback
, NULL
);
569 wMenuAddCallback(menu
, _("Hide"), hideCallback
, NULL
);
570 wMenuAddCallback(menu
, _("Set Icon..."), setIconCallback
, NULL
);
571 wMenuAddCallback(menu
, _("Kill"), killCallback
, NULL
);
576 static void openApplicationMenu(WApplication
* wapp
, int x
, int y
)
579 WScreen
*scr
= wapp
->main_window_desc
->screen_ptr
;
582 if (!scr
->icon_menu
) {
583 scr
->icon_menu
= createApplicationMenu(scr
);
584 wfree(scr
->icon_menu
->entries
[1]->text
);
587 menu
= scr
->icon_menu
;
589 if (wapp
->flags
.hidden
)
590 menu
->entries
[1]->text
= _("Unhide");
592 menu
->entries
[1]->text
= _("Hide");
594 menu
->flags
.realized
= 0;
597 x
-= menu
->frame
->core
->width
/ 2;
598 if (x
+ menu
->frame
->core
->width
> scr
->scr_width
)
599 x
= scr
->scr_width
- menu
->frame
->core
->width
;
604 /* set client data */
605 for (i
= 0; i
< menu
->entry_no
; i
++)
606 menu
->entries
[i
]->clientdata
= wapp
;
608 wMenuMapAt(menu
, x
, y
, False
);
611 /******************************************************************/
613 static void iconExpose(WObjDescriptor
* desc
, XEvent
* event
)
615 wAppIconPaint(desc
->parent
);
618 static void iconDblClick(WObjDescriptor
* desc
, XEvent
* event
)
620 WAppIcon
*aicon
= desc
->parent
;
622 WScreen
*scr
= aicon
->icon
->core
->screen_ptr
;
625 assert(aicon
->icon
->owner
!= NULL
);
627 wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
629 if (event
->xbutton
.state
& ControlMask
) {
630 relaunchApplication(wapp
);
634 unhideHere
= (event
->xbutton
.state
& ShiftMask
);
635 /* go to the last workspace that the user worked on the app */
636 if (!unhideHere
&& wapp
->last_workspace
!= scr
->current_workspace
)
637 wWorkspaceChange(scr
, wapp
->last_workspace
);
639 wUnhideApplication(wapp
, event
->xbutton
.button
== Button2
, unhideHere
);
641 if (event
->xbutton
.state
& MOD_MASK
)
642 wHideOtherApplications(aicon
->icon
->owner
);
645 void appIconMouseDown(WObjDescriptor
* desc
, XEvent
* event
)
647 WAppIcon
*aicon
= desc
->parent
;
648 WIcon
*icon
= aicon
->icon
;
650 int x
= aicon
->x_pos
, y
= aicon
->y_pos
;
651 int dx
= event
->xbutton
.x
, dy
= event
->xbutton
.y
;
654 int superfluous
= wPreferences
.superfluous
; /* we catch it to avoid problems */
655 WScreen
*scr
= icon
->core
->screen_ptr
;
656 WWorkspace
*workspace
= scr
->workspaces
[scr
->current_workspace
];
657 int shad_x
= 0, shad_y
= 0, docking
= 0, dockable
, collapsed
= 0;
659 int clickButton
= event
->xbutton
.button
;
662 Bool movingSingle
= False
;
665 Bool hasMoved
= False
;
667 if (aicon
->editing
|| WCHECK_STATE(WSTATE_MODAL
))
670 if (IsDoubleClick(scr
, event
)) {
671 /* Middle or right mouse actions were handled on first click */
672 if (event
->xbutton
.button
== Button1
)
673 iconDblClick(desc
, event
);
677 if (event
->xbutton
.button
== Button2
) {
678 WApplication
*wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
681 relaunchApplication(wapp
);
686 if (event
->xbutton
.button
== Button3
) {
687 WObjDescriptor
*desc
;
688 WApplication
*wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
693 if (event
->xbutton
.send_event
&&
694 XGrabPointer(dpy
, aicon
->icon
->core
->window
, True
, ButtonMotionMask
695 | ButtonReleaseMask
| ButtonPressMask
, GrabModeAsync
,
696 GrabModeAsync
, None
, None
, CurrentTime
) != GrabSuccess
) {
697 wwarning("pointer grab failed for appicon menu");
701 openApplicationMenu(wapp
, event
->xbutton
.x_root
, event
->xbutton
.y_root
);
703 /* allow drag select of menu */
704 desc
= &scr
->icon_menu
->menu
->descriptor
;
705 event
->xbutton
.send_event
= True
;
706 (*desc
->handle_mousedown
) (desc
, event
);
710 if (event
->xbutton
.state
& MOD_MASK
)
711 wLowerFrame(icon
->core
);
713 wRaiseFrame(icon
->core
);
715 if (XGrabPointer(dpy
, icon
->core
->window
, True
, ButtonMotionMask
716 | ButtonReleaseMask
| ButtonPressMask
, GrabModeAsync
,
717 GrabModeAsync
, None
, None
, CurrentTime
) != GrabSuccess
)
718 wwarning("pointer grab failed for appicon move");
720 if (wPreferences
.flags
.nodock
&& wPreferences
.flags
.noclip
)
723 dockable
= canBeDocked(icon
->owner
);
725 wins
[0] = icon
->core
->window
;
726 wins
[1] = scr
->dock_shadow
;
727 XRestackWindows(dpy
, wins
, 2);
729 if (icon
->pixmap
!= None
)
730 ghost
= MakeGhostIcon(scr
, icon
->pixmap
);
732 ghost
= MakeGhostIcon(scr
, icon
->core
->window
);
733 XSetWindowBackgroundPixmap(dpy
, scr
->dock_shadow
, ghost
);
734 XClearWindow(dpy
, scr
->dock_shadow
);
738 WMMaskEvent(dpy
, PointerMotionMask
| ButtonReleaseMask
| ButtonPressMask
739 | ButtonMotionMask
| ExposureMask
| EnterWindowMask
, &ev
);
746 /* It means the cursor moved so fast that it entered
747 * something else (if moving slowly, it would have
748 * stayed in the appIcon that is being moved. Ignore
749 * such "spurious" EnterNotifiy's */
755 if (abs(dx
- ev
.xmotion
.x
) >= MOVE_THRESHOLD
756 || abs(dy
- ev
.xmotion
.y
) >= MOVE_THRESHOLD
) {
757 XChangeActivePointerGrab(dpy
, ButtonMotionMask
758 | ButtonReleaseMask
| ButtonPressMask
,
759 wCursor
[WCUR_MOVE
], CurrentTime
);
765 x
= ev
.xmotion
.x_root
- dx
;
766 y
= ev
.xmotion
.y_root
- dy
;
769 XMoveWindow(dpy
, icon
->core
->window
, x
, y
);
771 wAppIconMove(aicon
, x
, y
);
774 if (scr
->dock
&& wDockSnapIcon(scr
->dock
, aicon
, x
, y
, &ix
, &iy
, False
)) {
775 shad_x
= scr
->dock
->x_pos
+ ix
* wPreferences
.icon_size
;
776 shad_y
= scr
->dock
->y_pos
+ iy
* wPreferences
.icon_size
;
778 if (scr
->last_dock
!= scr
->dock
&& collapsed
) {
779 scr
->last_dock
->collapsed
= 1;
780 wDockHideIcons(scr
->last_dock
);
783 if (!collapsed
&& (collapsed
= scr
->dock
->collapsed
)) {
784 scr
->dock
->collapsed
= 0;
785 wDockShowIcons(scr
->dock
);
788 if (scr
->dock
->auto_raise_lower
)
789 wDockRaise(scr
->dock
);
791 scr
->last_dock
= scr
->dock
;
793 XMoveWindow(dpy
, scr
->dock_shadow
, shad_x
, shad_y
);
795 XMapWindow(dpy
, scr
->dock_shadow
);
798 } else if (workspace
->clip
&&
799 wDockSnapIcon(workspace
->clip
, aicon
, x
, y
, &ix
, &iy
, False
)) {
800 shad_x
= workspace
->clip
->x_pos
+ ix
* wPreferences
.icon_size
;
801 shad_y
= workspace
->clip
->y_pos
+ iy
* wPreferences
.icon_size
;
803 if (scr
->last_dock
!= workspace
->clip
&& collapsed
) {
804 scr
->last_dock
->collapsed
= 1;
805 wDockHideIcons(scr
->last_dock
);
808 if (!collapsed
&& (collapsed
= workspace
->clip
->collapsed
)) {
809 workspace
->clip
->collapsed
= 0;
810 wDockShowIcons(workspace
->clip
);
813 if (workspace
->clip
->auto_raise_lower
)
814 wDockRaise(workspace
->clip
);
816 scr
->last_dock
= workspace
->clip
;
818 XMoveWindow(dpy
, scr
->dock_shadow
, shad_x
, shad_y
);
820 XMapWindow(dpy
, scr
->dock_shadow
);
823 } else if (docking
) {
824 XUnmapWindow(dpy
, scr
->dock_shadow
);
834 if (ev
.xbutton
.button
!= clickButton
)
836 XUngrabPointer(dpy
, CurrentTime
);
841 /* icon is trying to be docked */
842 SlideWindow(icon
->core
->window
, x
, y
, shad_x
, shad_y
);
843 XUnmapWindow(dpy
, scr
->dock_shadow
);
844 docked
= wDockAttachIcon(scr
->last_dock
, aicon
, ix
, iy
);
845 if (scr
->last_dock
->auto_collapse
)
848 if (workspace
->clip
&&
849 workspace
->clip
!= scr
->last_dock
&& workspace
->clip
->auto_raise_lower
)
850 wDockLower(workspace
->clip
);
853 /* If icon could not be docked, slide it back to the old
855 SlideWindow(icon
->core
->window
, x
, y
, oldX
, oldY
);
859 /* move back to its place */
860 SlideWindow(icon
->core
->window
, x
, y
, oldX
, oldY
);
861 wAppIconMove(aicon
, oldX
, oldY
);
863 XMoveWindow(dpy
, icon
->core
->window
, x
, y
);
867 if (workspace
->clip
&& workspace
->clip
->auto_raise_lower
)
868 wDockLower(workspace
->clip
);
871 scr
->last_dock
->collapsed
= 1;
872 wDockHideIcons(scr
->last_dock
);
877 XFreePixmap(dpy
, ghost
);
878 XSetWindowBackground(dpy
, scr
->dock_shadow
, scr
->white_pixel
);
881 if (wPreferences
.auto_arrange_icons
)
882 wArrangeIcons(scr
, True
);
884 if (wPreferences
.single_click
&& !hasMoved
)
885 iconDblClick(desc
, event
);
893 /* This function save the application icon and store the path in the Dictionary */
894 static void wApplicationSaveIconPathFor(char *iconPath
, char *wm_instance
, char *wm_class
)
896 WMPropList
*dict
= WDWindowAttributes
->dictionary
;
897 WMPropList
*adict
, *key
, *iconk
;
901 tmp
= get_name_for_instance_class(wm_instance
, wm_class
);
902 key
= WMCreatePLString(tmp
);
905 adict
= WMGetFromPLDictionary(dict
, key
);
906 iconk
= WMCreatePLString("Icon");
909 val
= WMGetFromPLDictionary(adict
, iconk
);
911 /* no dictionary for app, so create one */
912 adict
= WMCreatePLDictionary(NULL
, NULL
);
913 WMPutInPLDictionary(dict
, key
, adict
);
914 WMReleasePropList(adict
);
919 val
= WMCreatePLString(iconPath
);
920 WMPutInPLDictionary(adict
, iconk
, val
);
921 WMReleasePropList(val
);
926 WMReleasePropList(key
);
927 WMReleasePropList(iconk
);
929 if (val
&& !wPreferences
.flags
.noupdates
)
930 UpdateDomainFile(WDWindowAttributes
);
933 /* Save the application icon */
934 /* This function is used by normal windows */
935 void save_app_icon(WApplication
*wapp
)
940 save_app_icon_core(wapp
->app_icon
);
943 static WAppIcon
*findDockIconFor(WDock
*dock
, Window main_window
)
945 WAppIcon
*aicon
= NULL
;
947 aicon
= wDockFindIconForWindow(dock
, main_window
);
949 wDockTrackWindowLaunch(dock
, main_window
);
950 aicon
= wDockFindIconForWindow(dock
, main_window
);
955 void app_icon_create_from_docks(WWindow
*wwin
, WApplication
*wapp
, Window main_window
)
957 WScreen
*scr
= wwin
->screen_ptr
;
959 /* Create the application icon */
960 wapp
->app_icon
= NULL
;
963 wapp
->app_icon
= findDockIconFor(scr
->last_dock
, main_window
);
965 /* check main dock if we did not find it in last dock */
966 if (!wapp
->app_icon
&& scr
->dock
)
967 wapp
->app_icon
= findDockIconFor(scr
->dock
, main_window
);
969 /* finally check clips */
970 if (!wapp
->app_icon
) {
972 for (i
= 0; i
< scr
->workspace_count
; i
++) {
973 WDock
*dock
= scr
->workspaces
[i
]->clip
;
975 wapp
->app_icon
= findDockIconFor(dock
, main_window
);
981 /* If created, then set some flags */
982 if (wapp
->app_icon
) {
983 WWindow
*mainw
= wapp
->main_window_desc
;
985 wapp
->app_icon
->running
= 1;
986 wapp
->app_icon
->icon
->force_paint
= 1;
987 wapp
->app_icon
->icon
->owner
= mainw
;
988 if (mainw
->wm_hints
&& (mainw
->wm_hints
->flags
& IconWindowHint
))
989 wapp
->app_icon
->icon
->icon_win
= mainw
->wm_hints
->icon_window
;
991 wAppIconPaint(wapp
->app_icon
);
992 wAppIconSave(wapp
->app_icon
);
994 makeAppIconFor(wapp
);