2 * Window Maker window manager
4 * Copyright (c) 1997, 1998 Alfredo K. Kojima
5 * Copyright (c) 1998 Dan Pascu
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
29 #include <sys/types.h>
34 #include "WindowMaker.h"
39 #endif /* USER_MENU */
42 #include "application.h"
44 #include "properties.h"
49 #include "workspace.h"
58 /******** Global variables ********/
60 extern XContext wAppWinContext
;
61 extern XContext wWinContext
;
62 extern WPreferences wPreferences
;
64 extern WDDomain
*WDWindowAttributes
;
66 /******** Local variables ********/
70 makeMainWindow(WScreen
*scr
, Window window
)
73 XWindowAttributes attr
;
75 if (!XGetWindowAttributes(dpy
, window
, &attr
)) {
79 wwin
= wWindowCreate();
80 wwin
->screen_ptr
= scr
;
81 wwin
->client_win
= window
;
82 wwin
->main_window
= window
;
83 wwin
->wm_hints
= XGetWMHints(dpy
, window
);
84 /* if (!MyXFetchName(dpy, window, &(wwin->frame->title))) {
85 wwin->frame->title = NULL;
88 PropGetWMClass(window
, &wwin
->wm_class
, &wwin
->wm_instance
);
91 wDefaultFillAttributes(scr
, wwin
->wm_instance
, wwin
->wm_class
,
92 &wwin
->user_flags
, &wwin
->defined_user_flags
, True
);
94 XSelectInput(dpy
, window
, attr
.your_event_mask
| PropertyChangeMask
95 | StructureNotifyMask
);
101 wApplicationOf(Window window
)
107 if (XFindContext(dpy
, window
, wAppWinContext
, (XPointer
*)&wapp
)!=XCSUCCESS
)
114 findDockIconFor(WDock
*dock
, Window main_window
)
116 WAppIcon
*aicon
= NULL
;
118 aicon
= wDockFindIconForWindow(dock
, main_window
);
120 wDockTrackWindowLaunch(dock
, main_window
);
121 aicon
= wDockFindIconForWindow(dock
, main_window
);
128 extractIcon(WWindow
*wwin
)
133 if (!XGetCommand(dpy
, wwin
->client_win
, &argv
, &argc
) || argc
< 1)
136 wApplicationExtractDirPackIcon(wwin
->screen_ptr
,argv
[0],
139 XFreeStringList(argv
);
144 saveIconNameFor(char *iconPath
, char *wm_instance
, char *wm_class
)
146 proplist_t dict
= WDWindowAttributes
->dictionary
;
147 proplist_t adict
, key
, iconk
;
154 i
+= strlen(wm_instance
);
156 i
+= strlen(wm_class
);
160 if (wm_class
&& wm_instance
) {
161 sprintf(tmp
, "%s.%s", wm_instance
, wm_class
);
164 strcat(tmp
, wm_instance
);
166 strcat(tmp
, wm_class
);
169 key
= PLMakeString(tmp
);
171 adict
= PLGetDictionaryEntry(dict
, key
);
173 iconk
= PLMakeString("Icon");
176 val
= PLGetDictionaryEntry(adict
, iconk
);
178 /* no dictionary for app, so create one */
179 adict
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
180 PLInsertDictionaryEntry(dict
, key
, adict
);
185 val
= PLMakeString(iconPath
);
186 PLInsertDictionaryEntry(adict
, iconk
, val
);
192 if (val
&& !wPreferences
.flags
.noupdates
)
198 wApplicationExtractDirPackIcon(WScreen
*scr
, char *path
,
199 char *wm_instance
, char *wm_class
)
202 /* Maybe the app is a .app and it has an icon in it, like
203 * /usr/local/GNUstep/Apps/WPrefs.app/WPrefs.tiff
205 if (strstr(path
, ".app")) {
208 tmp
= wmalloc(strlen(path
)+16);
210 if (scr
->flags
.supports_tiff
) {
212 strcat(tmp
, ".tiff");
213 if (access(tmp
, R_OK
)==0)
219 if (access(tmp
, R_OK
)==0)
227 saveIconNameFor(iconPath
, wm_instance
, wm_class
);
235 extractClientIcon(WAppIcon
*icon
)
239 path
= wIconStore(icon
->icon
);
243 saveIconNameFor(path
, icon
->wm_instance
, icon
->wm_class
);
252 wApplicationCreate(WScreen
*scr
, Window main_window
)
257 if (main_window
==None
|| main_window
==scr
->root_win
) {
259 wwarning("trying to create application for %x",(unsigned)main_window
);
268 /* check if the window is valid */
269 if (!XGetGeometry(dpy
, main_window
, &root
, &foo
, &foo
, &bar
, &bar
,
275 wapp
= wApplicationOf(main_window
);
281 wapp
= wmalloc(sizeof(WApplication
));
282 memset(wapp
, 0, sizeof(WApplication
));
285 wapp
->last_focused
= NULL
;
287 wapp
->last_workspace
= 0;
289 wapp
->main_window
= main_window
;
290 wapp
->main_window_desc
= makeMainWindow(scr
, main_window
);
291 if (!wapp
->main_window_desc
) {
296 extractIcon(wapp
->main_window_desc
);
298 leader
= wWindowFor(main_window
);
300 leader
->main_window
= main_window
;
302 wapp
->menu
= wAppMenuGet(scr
, main_window
);
304 if (!wapp
->menu
) wapp
->menu
= wUserMenuGet(scr
, wapp
->main_window_desc
);
305 #endif /* USER_MENU */
309 WApplication
*tmp
= scr
->wapp_list
;
314 /* append to app list */
316 scr
->wapp_list
= wapp
;
328 * Set application wide attributes from the leader.
330 wapp
->flags
.hidden
= WFLAGP(wapp
->main_window_desc
, start_hidden
);
332 wapp
->flags
.emulated
= WFLAGP(wapp
->main_window_desc
, emulate_appicon
);
334 /* application descriptor */
335 XSaveContext(dpy
, main_window
, wAppWinContext
, (XPointer
)wapp
);
337 if (!WFLAGP(wapp
->main_window_desc
, no_appicon
)) {
338 wapp
->app_icon
= NULL
;
340 wapp
->app_icon
= findDockIconFor(scr
->last_dock
, main_window
);
341 /* check main dock if we did not find it in last dock */
342 if (!wapp
->app_icon
&& scr
->dock
) {
343 wapp
->app_icon
= findDockIconFor(scr
->dock
, main_window
);
345 /* finally check clips */
346 if (!wapp
->app_icon
) {
348 for (i
=0; i
<scr
->workspace_count
; i
++) {
349 WDock
*dock
= scr
->workspaces
[i
]->clip
;
351 wapp
->app_icon
= findDockIconFor(dock
, main_window
);
357 if (wapp
->app_icon
) {
358 WWindow
*mainw
= wapp
->main_window_desc
;
360 wapp
->app_icon
->running
= 1;
361 wapp
->app_icon
->icon
->force_paint
= 1;
362 wapp
->app_icon
->icon
->owner
= mainw
;
363 if (mainw
->wm_hints
&& (mainw
->wm_hints
->flags
&IconWindowHint
))
364 wapp
->app_icon
->icon
->icon_win
= mainw
->wm_hints
->icon_window
;
365 wAppIconPaint(wapp
->app_icon
);
367 wapp
->app_icon
= wAppIconCreate(wapp
->main_window_desc
);
370 wapp
->app_icon
= NULL
;
373 if (wapp
->app_icon
) {
374 wapp
->app_icon
->main_window
= main_window
;
377 if (wapp
->app_icon
&& !wapp
->app_icon
->docked
) {
378 WIcon
*icon
= wapp
->app_icon
->icon
;
379 WDock
*clip
= scr
->workspaces
[scr
->current_workspace
]->clip
;
382 if (clip
&& clip
->attract_icons
&& wDockFindFreeSlot(clip
, &x
, &y
)) {
383 wapp
->app_icon
->attracted
= 1;
384 if (!wapp
->app_icon
->icon
->shadowed
) {
385 wapp
->app_icon
->icon
->shadowed
= 1;
386 wapp
->app_icon
->icon
->force_paint
= 1;
387 /* We don't do an wAppIconPaint() here because it's in
388 * wDockAttachIcon(). -Dan.
391 wDockAttachIcon(clip
, wapp
->app_icon
, x
, y
);
393 PlaceIcon(scr
, &x
, &y
);
394 wAppIconMove(wapp
->app_icon
, x
, y
);
395 wLowerFrame(icon
->core
);
397 if (!clip
|| !wapp
->app_icon
->attracted
|| !clip
->collapsed
)
398 XMapWindow(dpy
, icon
->core
->window
);
401 if (wPreferences
.auto_arrange_icons
&& wapp
->app_icon
&& !wapp
->app_icon
->attracted
) {
402 wArrangeIcons(scr
, True
);
405 if (wapp
->app_icon
) {
410 tmp
= wDefaultGetIconFile(scr
, wapp
->app_icon
->wm_instance
,
411 wapp
->app_icon
->wm_class
, True
);
413 /* If the icon was saved by us from the client supplied icon, but is
414 * missing, recreate it. */
415 if (tmp
&& strstr(tmp
, ".AppInfo/WindowMaker")!=NULL
&&
416 stat(tmp
, &dummy
)!=0 && errno
==ENOENT
) {
417 wmessage(_("recreating missing icon '%s'"), tmp
);
418 path
= wIconStore(wapp
->app_icon
->icon
);
422 image
= wDefaultGetImage(scr
, wapp
->app_icon
->wm_instance
,
423 wapp
->app_icon
->wm_class
);
425 wIconChangeImage(wapp
->app_icon
->icon
, image
);
426 wAppIconPaint(wapp
->app_icon
);
428 * wIconChangeImage() should be rewriten to use retain/release
429 * The way it is now is too confusing about where the icon is
430 * finally released. -Dan */
431 /* --this is wrong at the moment-- RReleaseImage(image);*/
435 /* if the displayed icon was supplied by the client, save the icon */
437 extractClientIcon(wapp
->app_icon
);
442 wSoundPlay(WSOUND_APPSTART
);
446 printf("Created application for %x\n", (unsigned)main_window
);
453 wApplicationDestroy(WApplication
*wapp
)
463 if (wapp
->refcount
>0)
467 scr
= wapp
->main_window_desc
->screen_ptr
;
468 main_window
= wapp
->main_window
;
470 if (wapp
== scr
->wapp_list
) {
472 wapp
->next
->prev
= NULL
;
473 scr
->wapp_list
= wapp
->next
;
476 wapp
->next
->prev
= wapp
->prev
;
478 wapp
->prev
->next
= wapp
->next
;
481 XDeleteContext(dpy
, wapp
->main_window
, wAppWinContext
);
482 wAppMenuDestroy(wapp
->menu
);
483 if (wapp
->app_icon
) {
484 if (wapp
->app_icon
->docked
&& !wapp
->app_icon
->attracted
) {
485 wapp
->app_icon
->running
= 0;
486 /* since we keep it, we don't care if it was attracted or not */
487 wapp
->app_icon
->attracted
= 0;
488 wapp
->app_icon
->icon
->shadowed
= 0;
489 wapp
->app_icon
->main_window
= None
;
490 wapp
->app_icon
->pid
= 0;
491 wapp
->app_icon
->icon
->owner
= NULL
;
492 wapp
->app_icon
->icon
->icon_win
= None
;
493 wapp
->app_icon
->icon
->force_paint
= 1;
494 wAppIconPaint(wapp
->app_icon
);
495 } else if (wapp
->app_icon
->docked
) {
496 wapp
->app_icon
->running
= 0;
497 wDockDetach(wapp
->app_icon
->dock
, wapp
->app_icon
);
499 wAppIconDestroy(wapp
->app_icon
);
502 wwin
= wWindowFor(wapp
->main_window_desc
->client_win
);
504 wWindowDestroy(wapp
->main_window_desc
);
506 /* undelete client window context that was deleted in
508 XSaveContext(dpy
, wwin
->client_win
, wWinContext
,
509 (XPointer
)&wwin
->client_descriptor
);
514 printf("Destroyed application for %x\n", (unsigned)main_window
);
516 if (wPreferences
.auto_arrange_icons
) {
517 wArrangeIcons(scr
, True
);
521 wSoundPlay(WSOUND_APPEXIT
);
528 wApplicationSetCollapse(WApplication
*app
, Bool flag
)
530 WApplication
*list
= app
->main_window_desc
->screen_ptr
->wapp_list
;
532 WWindow
*wwin
= app
->main_window_desc
;
534 if (WFLAGP(app
->main_window_desc
, collapse_appicons
) == flag
)
539 if (strcmp(wwin
->wm_instance
,
540 list
->main_window_desc
->wm_instance
) == 0
542 strcmp(wwin
->wm_class
,
543 list
->main_window_desc
->wm_class
) == 0)
544 WSETUFLAG(list
->main_window_desc
, collapse_appicons
, flag
);
549 if (app
->app_icon
&& flag
)
550 wAppIconMove(app
->app_icon
, app
->app_icon
->x_pos
, app
->app_icon
->y_pos
);
557 * Returns index number of the app in case there are more than
558 * one instance of the same class/name.
561 wApplicationIndexOfGroup(WApplication
*app
)
563 WApplication
*list
= app
->main_window_desc
->screen_ptr
->wapp_list
;
565 WWindow
*wwin
= app
->main_window_desc
;
567 if (!WFLAGP(wwin, collapse_appicons))
575 if (strcmp(wwin
->wm_instance
,
576 list
->main_window_desc
->wm_instance
) == 0
578 strcmp(wwin
->wm_class
,
579 list
->main_window_desc
->wm_class
) == 0)
585 puts("OH SHIT!?!?!? HOW THE FUCK DID WE GET HERE!?!?!?!?!");