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
;
63 extern XContext wWinContext
;
65 #define MOD_MASK wPreferences.modifier_mask
67 void appIconMouseDown(WObjDescriptor
* desc
, XEvent
* event
);
68 static void iconDblClick(WObjDescriptor
* desc
, XEvent
* event
);
69 static void iconExpose(WObjDescriptor
* desc
, XEvent
* event
);
70 static void wApplicationSaveIconPathFor(char *iconPath
, char *wm_instance
, char *wm_class
);
71 static WAppIcon
*wAppIconCreate(WWindow
* leader_win
);
72 static void add_to_appicon_list(WScreen
*scr
, WAppIcon
*appicon
);
73 static void remove_from_appicon_list(WScreen
*scr
, WAppIcon
*appicon
);
74 static void create_appicon_from_dock(WWindow
*wwin
, WApplication
*wapp
, Window main_window
);
76 /* This function is used if the application is a .app. It checks if it has an icon in it
77 * like for example /usr/local/GNUstep/Applications/WPrefs.app/WPrefs.tiff
79 void wApplicationExtractDirPackIcon(WScreen
* scr
, char *path
, char *wm_instance
, char *wm_class
)
81 char *iconPath
= NULL
;
84 if (strstr(path
, ".app")) {
85 tmp
= wmalloc(strlen(path
) + 16);
87 if (scr
->flags
.supports_tiff
) {
90 if (access(tmp
, R_OK
) == 0)
97 if (access(tmp
, R_OK
) == 0)
105 wApplicationSaveIconPathFor(iconPath
, wm_instance
, wm_class
);
111 WAppIcon
*wAppIconCreateForDock(WScreen
*scr
, char *command
, char *wm_instance
, char *wm_class
, int tile
)
115 aicon
= wmalloc(sizeof(WAppIcon
));
120 add_to_appicon_list(scr
, aicon
);
123 aicon
->command
= wstrdup(command
);
126 aicon
->wm_class
= wstrdup(wm_class
);
129 aicon
->wm_instance
= wstrdup(wm_instance
);
131 aicon
->icon
= icon_create_for_dock(scr
, command
, wm_instance
, wm_class
, tile
);
134 wXDNDMakeAwareness(aicon
->icon
->core
->window
);
137 /* will be overriden by dock */
138 aicon
->icon
->core
->descriptor
.handle_mousedown
= appIconMouseDown
;
139 aicon
->icon
->core
->descriptor
.handle_expose
= iconExpose
;
140 aicon
->icon
->core
->descriptor
.parent_type
= WCLASS_APPICON
;
141 aicon
->icon
->core
->descriptor
.parent
= aicon
;
142 AddToStackList(aicon
->icon
->core
);
147 void create_appicon_for_application(WApplication
*wapp
, WWindow
*wwin
)
149 /* Try to create an icon from the dock or clip */
150 create_appicon_from_dock(wwin
, wapp
, wapp
->main_window
);
152 /* If app_icon was not found, create it */
153 if (!wapp
->app_icon
) {
154 /* Create the icon */
155 wapp
->app_icon
= wAppIconCreate(wapp
->main_window_desc
);
156 wIconUpdate(wapp
->app_icon
->icon
, NULL
);
158 /* Now, paint the icon */
159 if (!WFLAGP(wapp
->main_window_desc
, no_appicon
))
160 paint_app_icon(wapp
);
163 /* Save the app_icon in a file */
164 save_appicon(wapp
->app_icon
, False
);
167 void unpaint_app_icon(WApplication
*wapp
)
173 if (!wapp
|| !wapp
->app_icon
)
176 aicon
= wapp
->app_icon
;
178 /* If the icon is docked, don't continue */
182 scr
= wapp
->main_window_desc
->screen_ptr
;
183 clip
= scr
->workspaces
[scr
->current_workspace
]->clip
;
185 if (!clip
|| !aicon
->attracted
|| !clip
->collapsed
)
186 XUnmapWindow(dpy
, aicon
->icon
->core
->window
);
188 /* We want to avoid having it on the list because otherwise
189 * there will be a hole when the icons are arranged with
191 remove_from_appicon_list(scr
, aicon
);
193 if (wPreferences
.auto_arrange_icons
&& !aicon
->attracted
)
194 wArrangeIcons(scr
, True
);
197 void paint_app_icon(WApplication
*wapp
)
200 WScreen
*scr
= wapp
->main_window_desc
->screen_ptr
;
201 WDock
*clip
= scr
->workspaces
[scr
->current_workspace
]->clip
;
203 Bool update_icon
= False
;
205 if (!wapp
|| !wapp
->app_icon
)
208 icon
= wapp
->app_icon
->icon
;
209 wapp
->app_icon
->main_window
= wapp
->main_window
;
211 /* If the icon is docked, don't continue */
212 if (wapp
->app_icon
->docked
)
215 if (clip
&& clip
->attract_icons
&& wDockFindFreeSlot(clip
, &x
, &y
)) {
216 wapp
->app_icon
->attracted
= 1;
217 if (!icon
->shadowed
) {
221 wDockAttachIcon(clip
, wapp
->app_icon
, x
, y
, update_icon
);
223 /* We must know if the icon is painted in the screen,
224 * because if painted, then PlaceIcon will return the next
225 * space on the screen, and the icon will move */
226 if (wapp
->app_icon
->next
== NULL
&& wapp
->app_icon
->prev
== NULL
) {
227 PlaceIcon(scr
, &x
, &y
, wGetHeadForWindow(wapp
->main_window_desc
));
228 wAppIconMove(wapp
->app_icon
, x
, y
);
229 wLowerFrame(icon
->core
);
233 /* If we want appicon (no_appicon is not set) and the icon is not
234 * in the appicon_list, we must add it. Else, we want to avoid
235 * having it on the list */
236 if (!WFLAGP(wapp
->main_window_desc
, no_appicon
) &&
237 wapp
->app_icon
->next
== NULL
&& wapp
->app_icon
->prev
== NULL
)
238 add_to_appicon_list(scr
, wapp
->app_icon
);
240 if (!clip
|| !wapp
->app_icon
->attracted
|| !clip
->collapsed
)
241 XMapWindow(dpy
, icon
->core
->window
);
243 if (wPreferences
.auto_arrange_icons
&& !wapp
->app_icon
->attracted
)
244 wArrangeIcons(scr
, True
);
247 void removeAppIconFor(WApplication
*wapp
)
252 if (wPreferences
.highlight_active_app
)
253 wIconSetHighlited(wapp
->app_icon
->icon
, False
);
254 if (wapp
->app_icon
->docked
&& !wapp
->app_icon
->attracted
) {
255 wapp
->app_icon
->running
= 0;
256 /* since we keep it, we don't care if it was attracted or not */
257 wapp
->app_icon
->attracted
= 0;
258 wapp
->app_icon
->icon
->shadowed
= 0;
259 wapp
->app_icon
->main_window
= None
;
260 wapp
->app_icon
->pid
= 0;
261 wapp
->app_icon
->icon
->owner
= NULL
;
262 wapp
->app_icon
->icon
->icon_win
= None
;
264 /* Set the icon image */
265 set_icon_image_from_database(wapp
->app_icon
->icon
, wapp
->app_icon
->wm_instance
,
266 wapp
->app_icon
->wm_class
, wapp
->app_icon
->command
);
269 wAppIconPaint(wapp
->app_icon
);
270 } else if (wapp
->app_icon
->docked
) {
271 wapp
->app_icon
->running
= 0;
272 wDockDetach(wapp
->app_icon
->dock
, wapp
->app_icon
);
274 wAppIconDestroy(wapp
->app_icon
);
277 wapp
->app_icon
= NULL
;
279 if (wPreferences
.auto_arrange_icons
)
280 wArrangeIcons(wapp
->main_window_desc
->screen_ptr
, True
);
283 static WAppIcon
*wAppIconCreate(WWindow
*leader_win
)
287 aicon
= wmalloc(sizeof(WAppIcon
));
294 if (leader_win
->wm_class
)
295 aicon
->wm_class
= wstrdup(leader_win
->wm_class
);
297 if (leader_win
->wm_instance
)
298 aicon
->wm_instance
= wstrdup(leader_win
->wm_instance
);
300 aicon
->icon
= icon_create_for_wwindow(leader_win
);
302 wXDNDMakeAwareness(aicon
->icon
->core
->window
);
305 /* will be overriden if docked */
306 aicon
->icon
->core
->descriptor
.handle_mousedown
= appIconMouseDown
;
307 aicon
->icon
->core
->descriptor
.handle_expose
= iconExpose
;
308 aicon
->icon
->core
->descriptor
.parent_type
= WCLASS_APPICON
;
309 aicon
->icon
->core
->descriptor
.parent
= aicon
;
310 AddToStackList(aicon
->icon
->core
);
311 aicon
->icon
->show_title
= 0;
316 void wAppIconDestroy(WAppIcon
* aicon
)
318 WScreen
*scr
= aicon
->icon
->core
->screen_ptr
;
320 RemoveFromStackList(aicon
->icon
->core
);
321 wIconDestroy(aicon
->icon
);
323 wfree(aicon
->command
);
325 if (aicon
->dnd_command
)
326 wfree(aicon
->dnd_command
);
328 if (aicon
->wm_instance
)
329 wfree(aicon
->wm_instance
);
332 wfree(aicon
->wm_class
);
334 remove_from_appicon_list(scr
, aicon
);
336 aicon
->destroyed
= 1;
340 static void drawCorner(WIcon
* icon
)
342 WScreen
*scr
= icon
->core
->screen_ptr
;
351 XFillPolygon(dpy
, icon
->core
->window
, scr
->icon_title_texture
->normal_gc
,
352 points
, 3, Convex
, CoordModeOrigin
);
353 XDrawLine(dpy
, icon
->core
->window
, scr
->icon_title_texture
->light_gc
, 0, 0, 0, 12);
354 XDrawLine(dpy
, icon
->core
->window
, scr
->icon_title_texture
->light_gc
, 0, 0, 12, 0);
357 void wAppIconMove(WAppIcon
* aicon
, int x
, int y
)
359 XMoveWindow(dpy
, aicon
->icon
->core
->window
, x
, y
);
365 static void updateDockNumbers(WScreen
* scr
)
369 WAppIcon
*dicon
= scr
->dock
->icon_array
[0];
371 ws_numbers
= wmalloc(20);
372 snprintf(ws_numbers
, 20, "%i [ %i ]", scr
->current_workspace
+ 1, ((scr
->current_workspace
/ 10) + 1));
373 length
= strlen(ws_numbers
);
375 XClearArea(dpy
, dicon
->icon
->core
->window
, 2, 2, 50, WMFontHeight(scr
->icon_title_font
) + 1, False
);
377 WMDrawString(scr
->wmscreen
, dicon
->icon
->core
->window
, scr
->black
,
378 scr
->icon_title_font
, 4, 3, ws_numbers
, length
);
380 WMDrawString(scr
->wmscreen
, dicon
->icon
->core
->window
, scr
->white
,
381 scr
->icon_title_font
, 3, 2, ws_numbers
, length
);
385 #endif /* WS_INDICATOR */
387 void wAppIconPaint(WAppIcon
*aicon
)
390 WScreen
*scr
= aicon
->icon
->core
->screen_ptr
;
392 if (aicon
->icon
->owner
)
393 wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
397 wIconPaint(aicon
->icon
);
400 if (aicon
->docked
&& scr
->dock
&& scr
->dock
== aicon
->dock
&& aicon
->yindex
== 0)
401 updateDockNumbers(scr
);
403 if (scr
->dock_dots
&& aicon
->docked
&& !aicon
->running
&& aicon
->command
!= NULL
) {
404 XSetClipMask(dpy
, scr
->copy_gc
, scr
->dock_dots
->mask
);
405 XSetClipOrigin(dpy
, scr
->copy_gc
, 0, 0);
406 XCopyArea(dpy
, scr
->dock_dots
->image
, aicon
->icon
->core
->window
,
407 scr
->copy_gc
, 0, 0, scr
->dock_dots
->width
, scr
->dock_dots
->height
, 0, 0);
410 if (wapp
&& wapp
->flags
.hidden
) {
411 XSetClipMask(dpy
, scr
->copy_gc
, scr
->dock_dots
->mask
);
412 XSetClipOrigin(dpy
, scr
->copy_gc
, 0, 0);
413 XCopyArea(dpy
, scr
->dock_dots
->image
,
414 aicon
->icon
->core
->window
, scr
->copy_gc
, 0, 0, 7, scr
->dock_dots
->height
, 0, 0);
416 #endif /* HIDDENDOT */
418 if (aicon
->omnipresent
)
419 drawCorner(aicon
->icon
);
421 XSetClipMask(dpy
, scr
->copy_gc
, None
);
422 if (aicon
->launching
)
423 XFillRectangle(dpy
, aicon
->icon
->core
->window
, scr
->stipple_gc
,
424 0, 0, wPreferences
.icon_size
, wPreferences
.icon_size
);
427 /* Save the application icon, if it's a dockapp then use it with dock = True */
428 void save_appicon(WAppIcon
*aicon
, Bool dock
)
435 if (dock
&& (!aicon
->docked
|| aicon
->attracted
))
438 path
= wIconStore(aicon
->icon
);
442 wApplicationSaveIconPathFor(path
, aicon
->wm_instance
, aicon
->wm_class
);
446 #define canBeDocked(wwin) ((wwin) && ((wwin)->wm_class||(wwin)->wm_instance))
448 /* main_window may not have the full command line; try to find one which does */
449 static void relaunchApplication(WApplication
*wapp
)
452 WWindow
*wlist
, *next
;
454 scr
= wapp
->main_window_desc
->screen_ptr
;
455 wlist
= scr
->focused_window
;
465 if (wlist
->main_window
== wapp
->main_window
) {
466 if (RelaunchWindow(wlist
))
474 static void relaunchCallback(WMenu
* menu
, WMenuEntry
* entry
)
476 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
478 relaunchApplication(wapp
);
481 static void hideCallback(WMenu
* menu
, WMenuEntry
* entry
)
483 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
485 if (wapp
->flags
.hidden
) {
486 wWorkspaceChange(menu
->menu
->screen_ptr
, wapp
->last_workspace
);
487 wUnhideApplication(wapp
, False
, False
);
489 wHideApplication(wapp
);
493 static void unhideHereCallback(WMenu
* menu
, WMenuEntry
* entry
)
495 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
497 wUnhideApplication(wapp
, False
, True
);
500 static void setIconCallback(WMenu
*menu
, WMenuEntry
*entry
)
502 WAppIcon
*icon
= ((WApplication
*) entry
->clientdata
)->app_icon
;
507 assert(icon
!= NULL
);
513 scr
= icon
->icon
->core
->screen_ptr
;
517 result
= wIconChooserDialog(scr
, &file
, icon
->wm_instance
, icon
->wm_class
);
519 if (result
&& !icon
->destroyed
) {
520 if (file
&& *file
== 0) {
524 if (!wIconChangeImageFile(icon
->icon
, file
)) {
525 wMessageDialog(scr
, _("Error"),
526 _("Could not open specified icon file"), _("OK"), NULL
, NULL
);
528 wDefaultChangeIcon(scr
, icon
->wm_instance
, icon
->wm_class
, file
);
538 static void killCallback(WMenu
* menu
, WMenuEntry
* entry
)
540 WApplication
*wapp
= (WApplication
*) entry
->clientdata
;
541 WFakeGroupLeader
*fPtr
;
544 char *basename(const char *shortname
);
546 if (!WCHECK_STATE(WSTATE_NORMAL
))
549 WCHANGE_STATE(WSTATE_MODAL
);
551 assert(entry
->clientdata
!= NULL
);
553 shortname
= basename(wapp
->app_icon
->wm_instance
);
555 buffer
= wstrconcat(wapp
->app_icon
? shortname
: NULL
,
556 _(" will be forcibly closed.\n"
557 "Any unsaved changes will be lost.\n" "Please confirm."));
559 fPtr
= wapp
->main_window_desc
->fake_group
;
561 wretain(wapp
->main_window_desc
);
562 if (wPreferences
.dont_confirm_kill
563 || wMessageDialog(menu
->frame
->screen_ptr
, _("Kill Application"),
564 buffer
, _("Yes"), _("No"), NULL
) == WAPRDefault
) {
566 WWindow
*wwin
, *twin
;
568 wwin
= wapp
->main_window_desc
->screen_ptr
->focused_window
;
571 if (wwin
->fake_group
== fPtr
)
575 } else if (!wapp
->main_window_desc
->flags
.destroyed
) {
576 wClientKill(wapp
->main_window_desc
);
579 wrelease(wapp
->main_window_desc
);
581 WCHANGE_STATE(WSTATE_NORMAL
);
584 static WMenu
*createApplicationMenu(WScreen
*scr
)
588 menu
= wMenuCreate(scr
, NULL
, False
);
589 wMenuAddCallback(menu
, _("Unhide Here"), unhideHereCallback
, NULL
);
590 wMenuAddCallback(menu
, _("Hide"), hideCallback
, NULL
);
591 wMenuAddCallback(menu
, _("Launch"), relaunchCallback
, NULL
);
592 wMenuAddCallback(menu
, _("Set Icon..."), setIconCallback
, NULL
);
593 wMenuAddCallback(menu
, _("Kill"), killCallback
, NULL
);
598 static void openApplicationMenu(WApplication
* wapp
, int x
, int y
)
601 WScreen
*scr
= wapp
->main_window_desc
->screen_ptr
;
604 if (!scr
->icon_menu
) {
605 scr
->icon_menu
= createApplicationMenu(scr
);
606 wfree(scr
->icon_menu
->entries
[1]->text
);
609 menu
= scr
->icon_menu
;
611 if (wapp
->flags
.hidden
)
612 menu
->entries
[1]->text
= _("Unhide");
614 menu
->entries
[1]->text
= _("Hide");
616 menu
->flags
.realized
= 0;
619 x
-= menu
->frame
->core
->width
/ 2;
620 if (x
+ menu
->frame
->core
->width
> scr
->scr_width
)
621 x
= scr
->scr_width
- menu
->frame
->core
->width
;
626 /* set client data */
627 for (i
= 0; i
< menu
->entry_no
; i
++)
628 menu
->entries
[i
]->clientdata
= wapp
;
630 wMenuMapAt(menu
, x
, y
, False
);
633 /******************************************************************/
635 static void iconExpose(WObjDescriptor
*desc
, XEvent
*event
)
637 wAppIconPaint(desc
->parent
);
640 static void iconDblClick(WObjDescriptor
*desc
, XEvent
*event
)
642 WAppIcon
*aicon
= desc
->parent
;
644 WScreen
*scr
= aicon
->icon
->core
->screen_ptr
;
647 assert(aicon
->icon
->owner
!= NULL
);
649 wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
651 if (event
->xbutton
.state
& ControlMask
) {
652 relaunchApplication(wapp
);
656 unhideHere
= (event
->xbutton
.state
& ShiftMask
);
657 /* go to the last workspace that the user worked on the app */
658 if (!unhideHere
&& wapp
->last_workspace
!= scr
->current_workspace
)
659 wWorkspaceChange(scr
, wapp
->last_workspace
);
661 wUnhideApplication(wapp
, event
->xbutton
.button
== Button2
, unhideHere
);
663 if (event
->xbutton
.state
& MOD_MASK
)
664 wHideOtherApplications(aicon
->icon
->owner
);
667 void appIconMouseDown(WObjDescriptor
* desc
, XEvent
* event
)
669 WAppIcon
*aicon
= desc
->parent
;
670 WIcon
*icon
= aicon
->icon
;
672 int x
= aicon
->x_pos
, y
= aicon
->y_pos
;
673 int dx
= event
->xbutton
.x
, dy
= event
->xbutton
.y
;
676 int superfluous
= wPreferences
.superfluous
; /* we catch it to avoid problems */
677 WScreen
*scr
= icon
->core
->screen_ptr
;
678 WWorkspace
*workspace
= scr
->workspaces
[scr
->current_workspace
];
679 int shad_x
= 0, shad_y
= 0, docking
= 0, dockable
, collapsed
= 0;
681 int clickButton
= event
->xbutton
.button
;
684 Bool movingSingle
= False
;
687 Bool hasMoved
= False
;
689 if (aicon
->editing
|| WCHECK_STATE(WSTATE_MODAL
))
692 if (IsDoubleClick(scr
, event
)) {
693 /* Middle or right mouse actions were handled on first click */
694 if (event
->xbutton
.button
== Button1
)
695 iconDblClick(desc
, event
);
699 if (event
->xbutton
.button
== Button2
) {
700 WApplication
*wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
703 relaunchApplication(wapp
);
708 if (event
->xbutton
.button
== Button3
) {
709 WObjDescriptor
*desc
;
710 WApplication
*wapp
= wApplicationOf(aicon
->icon
->owner
->main_window
);
715 if (event
->xbutton
.send_event
&&
716 XGrabPointer(dpy
, aicon
->icon
->core
->window
, True
, ButtonMotionMask
717 | ButtonReleaseMask
| ButtonPressMask
, GrabModeAsync
,
718 GrabModeAsync
, None
, None
, CurrentTime
) != GrabSuccess
) {
719 wwarning("pointer grab failed for appicon menu");
723 openApplicationMenu(wapp
, event
->xbutton
.x_root
, event
->xbutton
.y_root
);
725 /* allow drag select of menu */
726 desc
= &scr
->icon_menu
->menu
->descriptor
;
727 event
->xbutton
.send_event
= True
;
728 (*desc
->handle_mousedown
) (desc
, event
);
732 if (event
->xbutton
.state
& MOD_MASK
)
733 wLowerFrame(icon
->core
);
735 wRaiseFrame(icon
->core
);
737 if (XGrabPointer(dpy
, icon
->core
->window
, True
, ButtonMotionMask
738 | ButtonReleaseMask
| ButtonPressMask
, GrabModeAsync
,
739 GrabModeAsync
, None
, None
, CurrentTime
) != GrabSuccess
)
740 wwarning("pointer grab failed for appicon move");
742 if (wPreferences
.flags
.nodock
&& wPreferences
.flags
.noclip
)
745 dockable
= canBeDocked(icon
->owner
);
747 wins
[0] = icon
->core
->window
;
748 wins
[1] = scr
->dock_shadow
;
749 XRestackWindows(dpy
, wins
, 2);
751 if (icon
->pixmap
!= None
)
752 ghost
= MakeGhostIcon(scr
, icon
->pixmap
);
754 ghost
= MakeGhostIcon(scr
, icon
->core
->window
);
755 XSetWindowBackgroundPixmap(dpy
, scr
->dock_shadow
, ghost
);
756 XClearWindow(dpy
, scr
->dock_shadow
);
760 WMMaskEvent(dpy
, PointerMotionMask
| ButtonReleaseMask
| ButtonPressMask
761 | ButtonMotionMask
| ExposureMask
| EnterWindowMask
, &ev
);
768 /* It means the cursor moved so fast that it entered
769 * something else (if moving slowly, it would have
770 * stayed in the appIcon that is being moved. Ignore
771 * such "spurious" EnterNotifiy's */
777 if (abs(dx
- ev
.xmotion
.x
) >= MOVE_THRESHOLD
778 || abs(dy
- ev
.xmotion
.y
) >= MOVE_THRESHOLD
) {
779 XChangeActivePointerGrab(dpy
, ButtonMotionMask
780 | ButtonReleaseMask
| ButtonPressMask
,
781 wCursor
[WCUR_MOVE
], CurrentTime
);
787 x
= ev
.xmotion
.x_root
- dx
;
788 y
= ev
.xmotion
.y_root
- dy
;
791 XMoveWindow(dpy
, icon
->core
->window
, x
, y
);
793 wAppIconMove(aicon
, x
, y
);
796 if (scr
->dock
&& wDockSnapIcon(scr
->dock
, aicon
, x
, y
, &ix
, &iy
, False
)) {
797 shad_x
= scr
->dock
->x_pos
+ ix
* wPreferences
.icon_size
;
798 shad_y
= scr
->dock
->y_pos
+ iy
* wPreferences
.icon_size
;
800 if (scr
->last_dock
!= scr
->dock
&& collapsed
) {
801 scr
->last_dock
->collapsed
= 1;
802 wDockHideIcons(scr
->last_dock
);
805 if (!collapsed
&& (collapsed
= scr
->dock
->collapsed
)) {
806 scr
->dock
->collapsed
= 0;
807 wDockShowIcons(scr
->dock
);
810 if (scr
->dock
->auto_raise_lower
)
811 wDockRaise(scr
->dock
);
813 scr
->last_dock
= scr
->dock
;
815 XMoveWindow(dpy
, scr
->dock_shadow
, shad_x
, shad_y
);
817 XMapWindow(dpy
, scr
->dock_shadow
);
820 } else if (workspace
->clip
&&
821 wDockSnapIcon(workspace
->clip
, aicon
, x
, y
, &ix
, &iy
, False
)) {
822 shad_x
= workspace
->clip
->x_pos
+ ix
* wPreferences
.icon_size
;
823 shad_y
= workspace
->clip
->y_pos
+ iy
* wPreferences
.icon_size
;
825 if (scr
->last_dock
!= workspace
->clip
&& collapsed
) {
826 scr
->last_dock
->collapsed
= 1;
827 wDockHideIcons(scr
->last_dock
);
830 if (!collapsed
&& (collapsed
= workspace
->clip
->collapsed
)) {
831 workspace
->clip
->collapsed
= 0;
832 wDockShowIcons(workspace
->clip
);
835 if (workspace
->clip
->auto_raise_lower
)
836 wDockRaise(workspace
->clip
);
838 scr
->last_dock
= workspace
->clip
;
840 XMoveWindow(dpy
, scr
->dock_shadow
, shad_x
, shad_y
);
842 XMapWindow(dpy
, scr
->dock_shadow
);
845 } else if (docking
) {
846 XUnmapWindow(dpy
, scr
->dock_shadow
);
856 if (ev
.xbutton
.button
!= clickButton
)
858 XUngrabPointer(dpy
, CurrentTime
);
863 /* icon is trying to be docked */
864 SlideWindow(icon
->core
->window
, x
, y
, shad_x
, shad_y
);
865 XUnmapWindow(dpy
, scr
->dock_shadow
);
866 docked
= wDockAttachIcon(scr
->last_dock
, aicon
, ix
, iy
, False
);
867 if (scr
->last_dock
->auto_collapse
)
870 if (workspace
->clip
&&
871 workspace
->clip
!= scr
->last_dock
&& workspace
->clip
->auto_raise_lower
)
872 wDockLower(workspace
->clip
);
875 /* If icon could not be docked, slide it back to the old
877 SlideWindow(icon
->core
->window
, x
, y
, oldX
, oldY
);
881 /* move back to its place */
882 SlideWindow(icon
->core
->window
, x
, y
, oldX
, oldY
);
883 wAppIconMove(aicon
, oldX
, oldY
);
885 XMoveWindow(dpy
, icon
->core
->window
, x
, y
);
889 if (workspace
->clip
&& workspace
->clip
->auto_raise_lower
)
890 wDockLower(workspace
->clip
);
893 scr
->last_dock
->collapsed
= 1;
894 wDockHideIcons(scr
->last_dock
);
899 XFreePixmap(dpy
, ghost
);
900 XSetWindowBackground(dpy
, scr
->dock_shadow
, scr
->white_pixel
);
903 if (wPreferences
.auto_arrange_icons
)
904 wArrangeIcons(scr
, True
);
906 if (wPreferences
.single_click
&& !hasMoved
)
907 iconDblClick(desc
, event
);
915 /* This function save the application icon and store the path in the Dictionary */
916 static void wApplicationSaveIconPathFor(char *iconPath
, char *wm_instance
, char *wm_class
)
918 WMPropList
*dict
= WDWindowAttributes
->dictionary
;
919 WMPropList
*adict
, *key
, *iconk
;
923 tmp
= get_name_for_instance_class(wm_instance
, wm_class
);
924 key
= WMCreatePLString(tmp
);
927 adict
= WMGetFromPLDictionary(dict
, key
);
928 iconk
= WMCreatePLString("Icon");
931 val
= WMGetFromPLDictionary(adict
, iconk
);
933 /* no dictionary for app, so create one */
934 adict
= WMCreatePLDictionary(NULL
, NULL
);
935 WMPutInPLDictionary(dict
, key
, adict
);
936 WMReleasePropList(adict
);
941 val
= WMCreatePLString(iconPath
);
942 WMPutInPLDictionary(adict
, iconk
, val
);
943 WMReleasePropList(val
);
948 WMReleasePropList(key
);
949 WMReleasePropList(iconk
);
951 if (val
&& !wPreferences
.flags
.noupdates
)
952 UpdateDomainFile(WDWindowAttributes
);
955 static WAppIcon
*findDockIconFor(WDock
*dock
, Window main_window
)
957 WAppIcon
*aicon
= NULL
;
959 aicon
= wDockFindIconForWindow(dock
, main_window
);
961 wDockTrackWindowLaunch(dock
, main_window
);
962 aicon
= wDockFindIconForWindow(dock
, main_window
);
967 static void create_appicon_from_dock(WWindow
*wwin
, WApplication
*wapp
, Window main_window
)
969 WScreen
*scr
= wwin
->screen_ptr
;
970 wapp
->app_icon
= NULL
;
973 wapp
->app_icon
= findDockIconFor(scr
->last_dock
, main_window
);
975 /* check main dock if we did not find it in last dock */
976 if (!wapp
->app_icon
&& scr
->dock
)
977 wapp
->app_icon
= findDockIconFor(scr
->dock
, main_window
);
979 /* finally check clips */
980 if (!wapp
->app_icon
) {
982 for (i
= 0; i
< scr
->workspace_count
; i
++) {
983 WDock
*dock
= scr
->workspaces
[i
]->clip
;
985 wapp
->app_icon
= findDockIconFor(dock
, main_window
);
991 /* If created, then set some flags */
992 if (wapp
->app_icon
) {
993 WWindow
*mainw
= wapp
->main_window_desc
;
995 wapp
->app_icon
->running
= 1;
996 wapp
->app_icon
->icon
->owner
= mainw
;
997 if (mainw
->wm_hints
&& (mainw
->wm_hints
->flags
& IconWindowHint
))
998 wapp
->app_icon
->icon
->icon_win
= mainw
->wm_hints
->icon_window
;
1000 /* Update the icon images */
1001 wIconUpdate(wapp
->app_icon
->icon
, NULL
);
1004 wAppIconPaint(wapp
->app_icon
);
1005 save_appicon(wapp
->app_icon
, True
);
1009 /* Add the appicon to the appiconlist */
1010 static void add_to_appicon_list(WScreen
*scr
, WAppIcon
*appicon
)
1012 appicon
->prev
= NULL
;
1013 appicon
->next
= scr
->app_icon_list
;
1014 if (scr
->app_icon_list
)
1015 scr
->app_icon_list
->prev
= appicon
;
1017 scr
->app_icon_list
= appicon
;
1020 /* Remove the appicon from the appiconlist */
1021 static void remove_from_appicon_list(WScreen
*scr
, WAppIcon
*appicon
)
1023 if (appicon
== scr
->app_icon_list
) {
1025 appicon
->next
->prev
= NULL
;
1026 scr
->app_icon_list
= appicon
->next
;
1029 appicon
->next
->prev
= appicon
->prev
;
1031 appicon
->prev
->next
= appicon
->next
;
1034 appicon
->prev
= NULL
;
1035 appicon
->next
= NULL
;
1038 /* Return the AppIcon associated with a given (Xlib) Window. */
1039 WAppIcon
*wAppIconFor(Window window
)
1041 WObjDescriptor
*desc
;
1046 if (XFindContext(dpy
, window
, wWinContext
, (XPointer
*) & desc
) == XCNOENT
)
1049 if (desc
->parent_type
== WCLASS_APPICON
|| desc
->parent_type
== WCLASS_DOCK_ICON
)
1050 return desc
->parent
;