1 /* kwm.c-- stuff for support for kwm hints
3 * Window Maker window manager
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
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,
28 * kfm icon selection from krootbgwm
30 * kwm.h function/method Notes
31 *----------------------------------------------------------------------------
32 * setUnsavedDataHint() currently, only gives visual clue that
33 * there is unsaved data (broken X close button)
35 * setIcon() std X thing...
39 * setWmCommand() std X thing
43 * isKWMInitialized() not trustworthy
44 * activeWindow() dunno it's use, but since it's easy to
45 * implement it won't hurt to support
47 * (set/get)WindowRegion()
48 * (set)numberOfDesktops() KDE limits to 32, but wmaker is virtually
49 * unlimited. May raise some incompatibility
50 * in badly written KDE modules?
51 * (set/get)DesktopName()
52 * sendKWMCommand() also does the message relay thing
58 * moveToDesktop() WARNING: evil mechanism
59 * setGeometryRestore() WARNING: evil mechanism
60 * setMaximize() woo hoo! wanna race?
61 * setIconify() BAH!: why reinvent the f'ing wheel!?
64 * setGeometry() std X thing
70 * prepareForSwallowing() std X thing
71 * doNotManage() klugy thing...
72 * getBlablablaString()
73 * setKWMDockModule() maybe we can make the Dock behave as the KDE
74 * dock, but must figure where to show the windows
77 * Unsupported stuff (superfluous/not-essential/nonsense):
78 * =======================================================
84 * registerSoundEvent()
85 * unregisterSoundEvent()
88 * geometry() kde lib code makes it unnecessary
94 * These are clientmessage-type messages specific to Window Maker:
95 * wmaker:info - show info panel
96 * wmaker:legal - show legal panel
97 * wmaker:arrangeIcons - arrange icons
98 * wmaker:showAll - show all windows
99 * wmaker:hideOthers - hide others
100 * wmaker:restart - restart wmaker
101 * wmaker:exit - exit wmaker
106 * different WORKAREA for each workspace
107 * -- done by rebuilding usableArea at each workspace switch.
115 #include <X11/Xlib.h>
116 #include <X11/Xutil.h>
117 #include <X11/Xatom.h>
124 #include <sys/types.h>
125 #include <sys/socket.h>
130 #include "WindowMaker.h"
134 #include "framewin.h"
136 #include "properties.h"
141 #include "workspace.h"
143 #include "stacking.h"
144 #include "xinerama.h"
150 /******* Global ******/
152 extern Time LastFocusChange
;
153 extern Time LastTimestamp
;
156 extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW
;
157 extern Atom _XA_WM_DELETE_WINDOW
;
161 static Atom _XA_KWM_COMMAND
= 0;
162 static Atom _XA_KWM_ACTIVATE_WINDOW
= 0;
163 static Atom _XA_KWM_ACTIVE_WINDOW
= 0;
164 static Atom _XA_KWM_DO_NOT_MANAGE
= 0;
165 static Atom _XA_KWM_DOCKWINDOW
= 0;
166 static Atom _XA_KWM_RUNNING
= 0;
168 static Atom _XA_KWM_MODULE
= 0;
170 static Atom _XA_KWM_MODULE_INIT
= 0;
171 static Atom _XA_KWM_MODULE_INITIALIZED
= 0;
172 static Atom _XA_KWM_MODULE_DESKTOP_CHANGE
= 0;
173 static Atom _XA_KWM_MODULE_DESKTOP_NAME_CHANGE
= 0;
174 static Atom _XA_KWM_MODULE_DESKTOP_NUMBER_CHANGE
= 0;
175 static Atom _XA_KWM_MODULE_WIN_ADD
= 0;
176 static Atom _XA_KWM_MODULE_WIN_REMOVE
= 0;
177 static Atom _XA_KWM_MODULE_WIN_CHANGE
= 0;
178 static Atom _XA_KWM_MODULE_WIN_RAISE
= 0;
179 static Atom _XA_KWM_MODULE_WIN_LOWER
= 0;
180 static Atom _XA_KWM_MODULE_WIN_ACTIVATE
= 0;
181 static Atom _XA_KWM_MODULE_WIN_ICON_CHANGE
= 0;
182 static Atom _XA_KWM_MODULE_DOCKWIN_ADD
= 0;
183 static Atom _XA_KWM_MODULE_DOCKWIN_REMOVE
= 0;
185 static Atom _XA_KWM_WIN_UNSAVED_DATA
= 0;
186 static Atom _XA_KWM_WIN_DECORATION
= 0;
187 static Atom _XA_KWM_WIN_DESKTOP
= 0;
188 static Atom _XA_KWM_WIN_GEOMETRY_RESTORE
= 0;
189 static Atom _XA_KWM_WIN_ICONIFIED
= 0;
190 static Atom _XA_KWM_WIN_MAXIMIZED
= 0;
191 static Atom _XA_KWM_WIN_STICKY
= 0;
193 static Atom _XA_KWM_WIN_ICON_GEOMETRY
= 0;
195 static Atom _XA_KWM_CURRENT_DESKTOP
= 0;
196 static Atom _XA_KWM_NUMBER_OF_DESKTOPS
= 0;
197 static Atom _XA_KWM_DESKTOP_NAME_
[MAX_WORKSPACES
];
198 static Atom _XA_KWM_WINDOW_REGION_
[MAX_WORKSPACES
];
202 /* list of window titles that must not be managed */
203 typedef struct KWMDoNotManageList
{
205 struct KWMDoNotManageList
*next
;
206 } KWMDoNotManageList
;
208 static KWMDoNotManageList
*KWMDoNotManageCrap
= NULL
;
211 /* list of KWM modules */
212 typedef struct KWMModuleList
{
214 struct KWMModuleList
*next
;
220 static KWMModuleList
*KWMModules
= NULL
;
222 static KWMModuleList
*KWMDockWindows
= NULL
;
224 /* window decoration types */
227 KWMnormalDecoration
= 1,
228 KWMtinyDecoration
= 2,
230 KWMstandaloneMenuBar
= 512,
231 KWMdesktopIcon
= 1024,
237 static void observer(void *self
, WMNotification
*notif
);
238 static void wsobserver(void *self
, WMNotification
*notif
);
243 getSimpleHint(Window win
, Atom atom
, long *retval
)
249 data
= (long*)PropGetCheckProperty(win
, atom
, atom
, 32, 1, NULL
);
264 setSimpleHint(Window win
, Atom atom
, long value
)
267 XChangeProperty(dpy
, win
, atom
, atom
,
268 32, PropModeReplace
, (unsigned char*)&value
, 1);
273 sendClientMessage(WScreen
*scr
, Window window
, Atom atom
, long value
)
280 memset(&event
, 0, sizeof(XEvent
));
281 event
.xclient
.type
= ClientMessage
;
282 event
.xclient
.message_type
= atom
;
283 event
.xclient
.window
= window
;
284 event
.xclient
.format
= 32;
285 event
.xclient
.data
.l
[0] = value
;
286 event
.xclient
.data
.l
[1] = LastTimestamp
;
288 if (scr
&& scr
->root_win
== window
)
289 mask
= SubstructureRedirectMask
;
291 XSendEvent(dpy
, window
, False
, mask
, &event
);
296 sendTextMessage(WScreen
*scr
, Window window
, Atom atom
, char *text
)
304 memset(&event
, 0, sizeof(XEvent
));
305 event
.xclient
.type
= ClientMessage
;
306 event
.xclient
.message_type
= atom
;
307 event
.xclient
.window
= window
;
308 event
.xclient
.format
= 8;
310 for (i
=0; i
<20 && text
[i
]; i
++)
311 event
.xclient
.data
.b
[i
] = text
[i
];
313 if (scr
&& scr
->root_win
== window
)
314 mask
= SubstructureRedirectMask
;
316 XSendEvent(dpy
, window
, False
, mask
, &event
);
321 getAreaHint(Window win
, Atom atom
, WArea
*area
)
325 data
= (long*)PropGetCheckProperty(win
, atom
, atom
, 32, 4, NULL
);
332 area
->x2
= data
[2] + area
->x1
;
333 area
->y2
= data
[3] + area
->y1
;
342 setAreaHint(Window win
, Atom atom
, WArea area
)
349 value
[2] = area
.x2
- area
.x1
;
350 value
[3] = area
.y2
- area
.y1
;
351 XChangeProperty(dpy
, win
, atom
, atom
, 32, PropModeReplace
,
352 (unsigned char*)&value
, 4);
357 addModule(WScreen
*scr
, Window window
)
363 node
= malloc(sizeof(KWMModuleList
));
365 wwarning("out of memory while registering KDE module");
369 node
->next
= KWMModules
;
370 node
->window
= window
;
373 sendClientMessage(scr
, window
, _XA_KWM_MODULE_INIT
, 0);
375 if (getSimpleHint(window
, _XA_KWM_MODULE
, &val
) && val
==2) {
376 if (scr
->kwm_dock
!= None
) {
377 setSimpleHint(window
, _XA_KWM_MODULE
, 1);
381 scr
->kwm_dock
= window
;
383 for (ptr
= KWMDockWindows
; ptr
!=NULL
; ptr
= ptr
->next
) {
384 sendClientMessage(scr
, scr
->kwm_dock
, _XA_KWM_MODULE_DOCKWIN_ADD
,
390 /* send list of windows */
391 for (ptr
= scr
->focused_window
; ptr
!=NULL
; ptr
= ptr
->prev
) {
392 if (!ptr
->flags
.kwm_hidden_for_modules
393 && !WFLAGP(ptr
, skip_window_list
)) {
394 sendClientMessage(scr
, window
, _XA_KWM_MODULE_WIN_ADD
,
399 /* send window stacking order */
400 wKWMSendStacking(scr
, window
);
402 /* send focused window */
403 if (scr
->focused_window
&& scr
->focused_window
->flags
.focused
) {
404 sendClientMessage(scr
, window
, _XA_KWM_MODULE_WIN_ACTIVATE
,
405 scr
->focused_window
->client_win
);
408 /* tell who we are */
409 sendTextMessage(scr
, window
, _XA_KWM_COMMAND
, "wm:wmaker");
412 sendClientMessage(scr
, window
, _XA_KWM_MODULE_INITIALIZED
, 0);
414 KWMModules
->title
= NULL
;
415 XFetchName(dpy
, window
, &KWMModules
->title
);
416 printf("NEW MODULE %s\n", KWMModules
->title
);
422 removeModule(WScreen
*scr
, Window window
)
430 if (KWMModules
->window
== window
) {
431 next
= KWMModules
->next
;
433 printf("REMOVING MODULE %s\n", KWMModules
->title
);
434 if (KWMModules
->title
)
435 XFree(KWMModules
->title
);
444 if (ptr
->next
->window
== window
) {
445 next
= ptr
->next
->next
;
447 printf("REMOVING MODULE %s\n", ptr
->next
->title
);
448 if (ptr
->next
->title
)
449 XFree(ptr
->next
->title
);
452 ptr
->next
->next
= next
;
455 ptr
->next
= ptr
->next
->next
;
459 if (scr
->kwm_dock
== window
)
460 scr
->kwm_dock
= None
;
466 addDockWindow(WScreen
*scr
, Window window
)
470 for (ptr
= KWMDockWindows
; ptr
!= NULL
; ptr
= ptr
->next
) {
471 if (ptr
->window
== window
)
477 node
= malloc(sizeof(KWMModuleList
));
479 wwarning("out of memory while processing KDE dock window");
482 node
->next
= KWMDockWindows
;
483 KWMDockWindows
= node
;
484 node
->window
= window
;
485 XSelectInput(dpy
, window
, StructureNotifyMask
);
487 sendClientMessage(scr
, scr
->kwm_dock
, _XA_KWM_MODULE_DOCKWIN_ADD
,
494 removeDockWindow(WScreen
*scr
, Window window
)
499 if (KWMDockWindows
->window
== window
) {
502 sendClientMessage(scr
, scr
->kwm_dock
, _XA_KWM_MODULE_DOCKWIN_REMOVE
,
505 next
= KWMDockWindows
->next
;
506 wfree(KWMDockWindows
);
507 KWMDockWindows
= next
;
510 KWMModuleList
*ptr
, *next
;
512 ptr
= KWMDockWindows
;
514 if (ptr
->next
->window
== window
) {
515 sendClientMessage(scr
, scr
->kwm_dock
,
516 _XA_KWM_MODULE_DOCKWIN_REMOVE
, window
);
517 next
= ptr
->next
->next
;
529 sendToModules(WScreen
*scr
, Atom atom
, WWindow
*wwin
, long data
)
536 if (wwin
->flags
.kwm_hidden_for_modules
537 || WFLAGP(wwin
, skip_window_list
))
539 data
= wwin
->client_win
;
542 printf("notifying %s\n",XGetAtomName(dpy
, atom
));
544 memset(&event
, 0, sizeof(XEvent
));
545 event
.xclient
.type
= ClientMessage
;
546 event
.xclient
.message_type
= atom
;
547 event
.xclient
.format
= 32;
548 event
.xclient
.data
.l
[1] = LastTimestamp
;
551 if (scr
&& scr
->root_win
== data
)
552 mask
= SubstructureRedirectMask
;
554 for (ptr
= KWMModules
; ptr
!=NULL
; ptr
= ptr
->next
) {
555 event
.xclient
.window
= ptr
->window
;
556 event
.xclient
.data
.l
[0] = data
;
557 XSendEvent(dpy
, ptr
->window
, False
, mask
, &event
);
563 wKWMInitStuff(WScreen
*scr
)
565 if (!_XA_KWM_WIN_STICKY
) {
566 _XA_KWM_WIN_UNSAVED_DATA
= XInternAtom(dpy
, "KWM_WIN_UNSAVED_DATA",
569 _XA_KWM_WIN_DECORATION
= XInternAtom(dpy
, "KWM_WIN_DECORATION", False
);
571 _XA_KWM_WIN_DESKTOP
= XInternAtom(dpy
, "KWM_WIN_DESKTOP", False
);
573 _XA_KWM_WIN_GEOMETRY_RESTORE
= XInternAtom(dpy
,
574 "KWM_WIN_GEOMETRY_RESTORE",
577 _XA_KWM_WIN_STICKY
= XInternAtom(dpy
, "KWM_WIN_STICKY", False
);
579 _XA_KWM_WIN_ICONIFIED
= XInternAtom(dpy
, "KWM_WIN_ICONIFIED", False
);
581 _XA_KWM_WIN_MAXIMIZED
= XInternAtom(dpy
, "KWM_WIN_MAXIMIZED", False
);
583 _XA_KWM_WIN_ICON_GEOMETRY
= XInternAtom(dpy
, "KWM_WIN_ICON_GEOMETRY",
586 _XA_KWM_COMMAND
= XInternAtom(dpy
, "KWM_COMMAND", False
);
588 _XA_KWM_ACTIVE_WINDOW
= XInternAtom(dpy
, "KWM_ACTIVE_WINDOW", False
);
590 _XA_KWM_ACTIVATE_WINDOW
= XInternAtom(dpy
, "KWM_ACTIVATE_WINDOW",
593 _XA_KWM_DO_NOT_MANAGE
= XInternAtom(dpy
, "KWM_DO_NOT_MANAGE", False
);
595 _XA_KWM_CURRENT_DESKTOP
= XInternAtom(dpy
, "KWM_CURRENT_DESKTOP",
598 _XA_KWM_NUMBER_OF_DESKTOPS
= XInternAtom(dpy
, "KWM_NUMBER_OF_DESKTOPS",
601 _XA_KWM_DOCKWINDOW
= XInternAtom(dpy
, "KWM_DOCKWINDOW", False
);
603 _XA_KWM_RUNNING
= XInternAtom(dpy
, "KWM_RUNNING", False
);
605 _XA_KWM_MODULE
= XInternAtom(dpy
, "KWM_MODULE", False
);
607 _XA_KWM_MODULE_INIT
= XInternAtom(dpy
, "KWM_MODULE_INIT", False
);
608 _XA_KWM_MODULE_INITIALIZED
= XInternAtom(dpy
, "KWM_MODULE_INITIALIZED", False
);
610 /* dunno what these do, but Matthias' patch contains it... */
611 _XA_KWM_MODULE_DESKTOP_CHANGE
= XInternAtom(dpy
, "KWM_MODULE_DESKTOP_CHANGE", False
);
612 _XA_KWM_MODULE_DESKTOP_NAME_CHANGE
= XInternAtom(dpy
, "KWM_MODULE_DESKTOP_NAME_CHANGE", False
);
613 _XA_KWM_MODULE_DESKTOP_NUMBER_CHANGE
= XInternAtom(dpy
, "KWM_MODULE_DESKTOP_NUMBER_CHANGE", False
);
615 _XA_KWM_MODULE_WIN_ADD
= XInternAtom(dpy
, "KWM_MODULE_WIN_ADD", False
);
616 _XA_KWM_MODULE_WIN_REMOVE
= XInternAtom(dpy
, "KWM_MODULE_WIN_REMOVE", False
);
617 _XA_KWM_MODULE_WIN_CHANGE
= XInternAtom(dpy
, "KWM_MODULE_WIN_CHANGE", False
);
618 _XA_KWM_MODULE_WIN_RAISE
= XInternAtom(dpy
, "KWM_MODULE_WIN_RAISE", False
);
619 _XA_KWM_MODULE_WIN_LOWER
= XInternAtom(dpy
, "KWM_MODULE_WIN_LOWER", False
);
620 _XA_KWM_MODULE_WIN_ACTIVATE
= XInternAtom(dpy
, "KWM_MODULE_WIN_ACTIVATE", False
);
621 _XA_KWM_MODULE_WIN_ICON_CHANGE
= XInternAtom(dpy
, "KWM_MODULE_WIN_ICON_CHANGE", False
);
622 _XA_KWM_MODULE_DOCKWIN_ADD
= XInternAtom(dpy
, "KWM_MODULE_DOCKWIN_ADD", False
);
623 _XA_KWM_MODULE_DOCKWIN_REMOVE
= XInternAtom(dpy
, "KWM_MODULE_DOCKWIN_REMOVE", False
);
625 memset(_XA_KWM_WINDOW_REGION_
, 0, sizeof(_XA_KWM_WINDOW_REGION_
));
627 memset(_XA_KWM_DESKTOP_NAME_
, 0, sizeof(_XA_KWM_DESKTOP_NAME_
));
630 #define SETSTR(hint, str) {\
631 static Atom a = 0; if (!a) a = XInternAtom(dpy, #hint, False);\
632 XChangeProperty(dpy, scr->root_win, a, XA_STRING, 8, PropModeReplace,\
633 (unsigned char*)str, strlen(str));}
635 SETSTR(KWM_STRING_MAXIMIZE
, _("Maximize"));
636 SETSTR(KWM_STRING_UNMAXIMIZE
, _("Unmaximize"));
637 SETSTR(KWM_STRING_ICONIFY
, _("Miniaturize"));
638 SETSTR(KWM_STRING_UNICONIFY
, _("Deminiaturize"));
639 SETSTR(KWM_STRING_STICKY
, _("Omnipresent"));
640 SETSTR(KWM_STRING_UNSTICKY
, _("Not Omnipresent"));
641 SETSTR(KWM_STRING_STRING_MOVE
, _("Move"));
642 SETSTR(KWM_STRING_STRING_RESIZE
, _("Resize"));
643 SETSTR(KWM_STRING_CLOSE
, _("Close"));
644 SETSTR(KWM_STRING_TODESKTOP
, _("Move To"));
645 SETSTR(KWM_STRING_ONTOCURRENTDESKTOP
, _("Bring Here"));
648 /* catch any notifications from any objects */
650 WMAddNotificationObserver(observer
, scr
, WMNManaged
, NULL
);
651 WMAddNotificationObserver(observer
, scr
, WMNUnmanaged
, NULL
);
652 WMAddNotificationObserver(observer
, scr
, WMNChangedWorkspace
, NULL
);
653 WMAddNotificationObserver(observer
, scr
, WMNChangedState
, NULL
);
654 WMAddNotificationObserver(observer
, scr
, WMNChangedFocus
, NULL
);
655 WMAddNotificationObserver(observer
, scr
, WMNChangedStacking
, NULL
);
656 WMAddNotificationObserver(observer
, scr
, WMNChangedName
, NULL
);
658 WMAddNotificationObserver(wsobserver
, scr
, WMNWorkspaceCreated
, NULL
);
659 WMAddNotificationObserver(wsobserver
, scr
, WMNWorkspaceDestroyed
, NULL
);
660 WMAddNotificationObserver(wsobserver
, scr
, WMNWorkspaceChanged
, NULL
);
661 WMAddNotificationObserver(wsobserver
, scr
, WMNWorkspaceNameChanged
, NULL
);
663 WMAddNotificationObserver(wsobserver
, scr
, WMNResetStacking
, NULL
);
668 wKWMSendStacking(WScreen
*scr
, Window module
)
673 WM_ITERATE_BAG(scr
->stacking_list
, core
, i
) {
674 for (; core
!= NULL
; core
= core
->stacking
->under
) {
677 wwin
= wWindowFor(core
->window
);
679 sendClientMessage(scr
, module
, _XA_KWM_MODULE_WIN_RAISE
,
687 wKWMBroadcastStacking(WScreen
*scr
)
689 KWMModuleList
*ptr
= KWMModules
;
692 wKWMSendStacking(scr
, ptr
->window
);
700 wKWMGetWorkspaceName(WScreen
*scr
, int workspace
)
704 unsigned long nitems_ret
;
705 unsigned long bytes_after_ret
;
706 char *data
= NULL
, *tmp
;
709 assert(workspace
>= 0 && workspace
< MAX_WORKSPACES
);
711 if (_XA_KWM_DESKTOP_NAME_
[workspace
]==0) {
712 snprintf(buffer
, sizeof(buffer
), "KWM_DESKTOP_NAME_%d", workspace
+ 1);
714 _XA_KWM_DESKTOP_NAME_
[workspace
] = XInternAtom(dpy
, buffer
, False
);
717 /* What do these people have against correctly using property types? */
718 if (XGetWindowProperty(dpy
, scr
->root_win
,
719 _XA_KWM_DESKTOP_NAME_
[workspace
], 0, 128, False
,
721 &type_ret
, &fmt_ret
, &nitems_ret
, &bytes_after_ret
,
722 (unsigned char**)&data
)!=Success
|| !data
)
733 wKWMSetInitializedHint(WScreen
*scr
)
735 setSimpleHint(scr
->root_win
, _XA_KWM_RUNNING
, 1);
740 wKWMShutdown(WScreen
*scr
, Bool closeModules
)
744 XDeleteProperty(dpy
, scr
->root_win
, _XA_KWM_RUNNING
);
747 for (ptr
= KWMModules
; ptr
!= NULL
; ptr
= ptr
->next
) {
748 XKillClient(dpy
, ptr
->window
);
755 wKWMCheckClientHints(WWindow
*wwin
, int *layer
, int *workspace
)
758 Bool hasHint
= False
;
760 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_UNSAVED_DATA
, &val
)
763 wwin
->client_flags
.broken_close
= 1;
766 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_DECORATION
, &val
)) {
767 if (val
& KWMnoFocus
) {
768 wwin
->client_flags
.no_focusable
= 1;
770 switch (val
& ~KWMnoFocus
) {
771 case KWMnoDecoration
:
772 wwin
->client_flags
.no_titlebar
= 1;
773 wwin
->client_flags
.no_resizebar
= 1;
775 case KWMtinyDecoration
:
776 wwin
->client_flags
.no_resizebar
= 1;
778 case KWMstandaloneMenuBar
:
779 wwin
->client_flags
.no_titlebar
= 1;
780 wwin
->client_flags
.no_resizebar
= 1;
781 wwin
->client_flags
.no_resizable
= 1;
782 wwin
->client_flags
.skip_window_list
= 1;
783 wwin
->client_flags
.no_hide_others
= 1;
784 wwin
->flags
.kwm_menubar
= 1;
785 *layer
= WMMainMenuLevel
;
788 *layer
= WMDesktopLevel
;
791 *layer
= WMFloatingLevel
;
793 case KWMnormalDecoration
:
799 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_DESKTOP
, &val
)) {
800 *workspace
= val
- 1;
809 wKWMCheckClientInitialState(WWindow
*wwin
)
813 Bool hasHint
= False
;
815 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_STICKY
, &val
) && val
) {
817 wwin
->client_flags
.omnipresent
= 1;
820 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_ICONIFIED
, &val
) && val
) {
822 wwin
->flags
.miniaturized
= 1;
825 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_MAXIMIZED
, &val
)) {
827 wwin
->flags
.maximized
= MAX_VERTICAL
;
829 wwin
->flags
.maximized
= MAX_HORIZONTAL
;
831 wwin
->flags
.maximized
= MAX_VERTICAL
|MAX_HORIZONTAL
;
834 if (getAreaHint(wwin
->client_win
, _XA_KWM_WIN_GEOMETRY_RESTORE
, &area
)
835 && (wwin
->old_geometry
.x
!= area
.x1
836 || wwin
->old_geometry
.y
!= area
.y1
837 || wwin
->old_geometry
.width
!= area
.x2
- area
.x1
838 || wwin
->old_geometry
.height
!= area
.y2
- area
.y1
)) {
840 wwin
->old_geometry
.x
= area
.x1
;
841 wwin
->old_geometry
.y
= area
.y1
;
842 wwin
->old_geometry
.width
= area
.x2
- area
.x1
;
843 wwin
->old_geometry
.height
= area
.y2
- area
.y1
;
852 wKWMCheckClientHintChange(WWindow
*wwin
, XPropertyEvent
*event
)
854 Bool processed
= True
;
863 if (event
->atom
== _XA_KWM_WIN_UNSAVED_DATA
) {
865 printf("got KDE unsaved data change\n");
868 flag
= getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_UNSAVED_DATA
,
871 if (flag
!= wwin
->client_flags
.broken_close
) {
872 wwin
->client_flags
.broken_close
= flag
;
874 wWindowUpdateButtonImages(wwin
);
876 } else if (event
->atom
== _XA_KWM_WIN_STICKY
) {
879 printf("got KDE sticky change\n");
881 flag
= !getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_STICKY
,
884 if (flag
!= wwin
->client_flags
.omnipresent
) {
886 wWindowSetOmnipresent(wwin
, flag
);
888 } else if (event
->atom
== _XA_KWM_WIN_MAXIMIZED
) {
892 printf("got KDE maximize change\n");
894 flag
= getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_MAXIMIZED
, &value
);
898 bla
= MAX_VERTICAL
|MAX_HORIZONTAL
;
902 bla
= MAX_HORIZONTAL
;
905 if (bla
!= wwin
->flags
.maximized
) {
907 wMaximizeWindow(wwin
, bla
);
909 wUnmaximizeWindow(wwin
);
911 } else if (event
->atom
== _XA_KWM_WIN_ICONIFIED
) {
914 printf("got KDE iconify change\n");
916 flag
= !getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_ICONIFIED
,
919 if (flag
!= wwin
->flags
.miniaturized
) {
922 wIconifyWindow(wwin
);
924 wDeiconifyWindow(wwin
);
927 } else if (event
->atom
== _XA_KWM_WIN_DECORATION
) {
928 Bool refresh
= False
;
932 printf("got KDE decoration change\n");
935 oldnofocus
= wwin
->client_flags
.no_focusable
;
937 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_DECORATION
, &value
)) {
938 wwin
->client_flags
.no_focusable
= (value
& KWMnoFocus
)!=0;
940 switch (value
& ~KWMnoFocus
) {
941 case KWMnoDecoration
:
942 if (!WFLAGP(wwin
, no_titlebar
) || !WFLAGP(wwin
, no_resizebar
))
945 wwin
->client_flags
.no_titlebar
= 1;
946 wwin
->client_flags
.no_resizebar
= 1;
949 case KWMtinyDecoration
:
950 if (WFLAGP(wwin
, no_titlebar
) || !WFLAGP(wwin
, no_resizebar
))
953 wwin
->client_flags
.no_titlebar
= 0;
954 wwin
->client_flags
.no_resizebar
= 1;
957 case KWMnormalDecoration
:
959 if (WFLAGP(wwin
, no_titlebar
) || WFLAGP(wwin
, no_resizebar
))
962 wwin
->client_flags
.no_titlebar
= 0;
963 wwin
->client_flags
.no_resizebar
= 0;
967 if (WFLAGP(wwin
, no_titlebar
) || WFLAGP(wwin
, no_resizebar
))
969 wwin
->client_flags
.no_focusable
= (value
& KWMnoFocus
)!=0;
970 wwin
->client_flags
.no_titlebar
= 0;
971 wwin
->client_flags
.no_resizebar
= 0;
975 wWindowConfigureBorders(wwin
);
977 if (wwin
->client_flags
.no_focusable
&& !oldnofocus
) {
979 sendToModules(wwin
->screen_ptr
, _XA_KWM_MODULE_WIN_REMOVE
,
981 wwin
->flags
.kwm_hidden_for_modules
= 1;
983 } else if (!wwin
->client_flags
.no_focusable
&& oldnofocus
) {
985 if (wwin
->flags
.kwm_hidden_for_modules
) {
986 sendToModules(wwin
->screen_ptr
, _XA_KWM_MODULE_WIN_ADD
,
988 wwin
->flags
.kwm_hidden_for_modules
= 0;
991 } else if (event
->atom
== _XA_KWM_WIN_DESKTOP
&& wwin
->frame
) {
993 printf("got KDE workspace change for %s\n", wwin
->frame
->title
);
995 if (getSimpleHint(wwin
->client_win
, _XA_KWM_WIN_DESKTOP
, &value
)
996 && value
-1 != wwin
->frame
->workspace
) {
997 wWindowChangeWorkspace(wwin
, value
-1);
1000 } else if (event
->atom
== _XA_KWM_WIN_GEOMETRY_RESTORE
) {
1004 printf("got KDE geometry restore change\n");
1006 if (getAreaHint(wwin
->client_win
, _XA_KWM_WIN_GEOMETRY_RESTORE
, &area
)
1007 && (wwin
->old_geometry
.x
!= area
.x1
1008 || wwin
->old_geometry
.y
!= area
.y1
1009 || wwin
->old_geometry
.width
!= area
.x2
- area
.x1
1010 || wwin
->old_geometry
.height
!= area
.y2
- area
.y1
)) {
1012 wwin
->old_geometry
.x
= area
.x1
;
1013 wwin
->old_geometry
.y
= area
.y1
;
1014 wwin
->old_geometry
.width
= area
.x2
- area
.x1
;
1015 wwin
->old_geometry
.height
= area
.y2
- area
.y1
;
1026 performWindowCommand(WScreen
*scr
, char *command
)
1028 WWindow
*wwin
= NULL
;
1031 wwin
= scr
->focused_window
;
1032 if (!wwin
|| !wwin
->flags
.focused
|| !wwin
->flags
.mapped
) {
1036 CloseWindowMenu(scr
);
1039 if (strcmp(command
, "winMove")==0 || strcmp(command
, "winResize")==0) {
1042 wKeyboardMoveResizeWindow(wwin
);
1044 } else if (strcmp(command
, "winMaximize")==0) {
1047 wMaximizeWindow(wwin
, MAX_VERTICAL
|MAX_HORIZONTAL
);
1049 } else if (strcmp(command
, "winRestore")==0) {
1051 if (wwin
&& wwin
->flags
.maximized
)
1052 wUnmaximizeWindow(wwin
);
1054 } else if (strcmp(command
, "winIconify")==0) {
1057 if (wwin
&& !WFLAGP(wwin
, no_miniaturizable
)) {
1058 if (wwin
->protocols
.MINIATURIZE_WINDOW
)
1059 wClientSendProtocol(wwin
, _XA_GNUSTEP_WM_MINIATURIZE_WINDOW
,
1062 wIconifyWindow(wwin
);
1066 } else if (strcmp(command
, "winClose")==0) {
1068 if (wwin
&& !WFLAGP(wwin
, no_closable
)) {
1069 if (wwin
->protocols
.DELETE_WINDOW
)
1070 wClientSendProtocol(wwin
, _XA_WM_DELETE_WINDOW
, LastTimestamp
);
1073 } else if (strcmp(command
, "winSticky")==0) {
1076 wWindowSetOmnipresent(wwin
, !wwin
->client_flags
.omnipresent
);
1079 } else if (strcmp(command
, "winShade")==0) {
1081 if (wwin
&& !WFLAGP(wwin
, no_shadeable
)) {
1082 if (wwin
->flags
.shaded
)
1083 wUnshadeWindow(wwin
);
1088 } else if (strcmp(command
, "winOperation")==0) {
1091 OpenWindowMenu(wwin
, wwin
->frame_x
,
1092 wwin
->frame_y
+wwin
->frame
->top_width
, True
);
1103 performCommand(WScreen
*scr
, char *command
, XClientMessageEvent
*event
)
1105 assert(scr
!= NULL
);
1107 if (strcmp(command
, "commandLine")==0
1108 || strcmp(command
, "execute")==0) {
1111 cmd
= ExpandOptions(scr
, _("%a(Run Command,Type the command to run:)"));
1113 ExecuteShellCommand(scr
, cmd
);
1116 } else if (strcmp(command
, "logout")==0) {
1118 Shutdown(WSLogoutMode
);
1120 } else if (strcmp(command
, "refreshScreen")==0) {
1122 wRefreshDesktop(scr
);
1124 } else if (strncmp(command
, "go:", 3)==0) {
1126 Shutdown(WSRestartPreparationMode
);
1127 Restart(&command
[3], False
);
1128 Restart(NULL
, True
);
1130 } else if (strcmp(command
, "desktop+1")==0) {
1132 wWorkspaceRelativeChange(scr
, 1);
1134 } else if (strcmp(command
, "desktop-1")==0) {
1136 wWorkspaceRelativeChange(scr
, -1);
1138 } else if (strcmp(command
, "desktop+2")==0) {
1140 wWorkspaceRelativeChange(scr
, 2);
1142 } else if (strcmp(command
, "desktop-2")==0) {
1144 wWorkspaceRelativeChange(scr
, -2);
1146 } else if (strcmp(command
, "desktop%%2")==0) {
1148 if (scr
->current_workspace
% 2 == 1)
1149 wWorkspaceRelativeChange(scr
, 1);
1151 wWorkspaceRelativeChange(scr
, -1);
1152 } else if (strncmp(command
, "desktop", 7)==0) {
1155 ws
= atoi(&command
[7]);
1156 wWorkspaceChange(scr
, ws
);
1158 /* wmaker specific stuff */
1159 } else if (strcmp(command
, "wmaker:info")==0) {
1161 wShowInfoPanel(scr
);
1163 } else if (strcmp(command
, "wmaker:legal")==0) {
1165 wShowLegalPanel(scr
);
1167 } else if (strcmp(command
, "wmaker:arrangeIcons")==0) {
1169 wArrangeIcons(scr
, True
);
1171 } else if (strcmp(command
, "wmaker:showAll")==0) {
1173 wShowAllWindows(scr
);
1175 } else if (strcmp(command
, "wmaker:hideOthers")==0) {
1177 wHideOtherApplications(scr
->focused_window
);
1179 } else if (strcmp(command
, "wmaker:restart")==0) {
1181 Shutdown(WSRestartPreparationMode
);
1182 Restart(NULL
, True
);
1184 } else if (strcmp(command
, "wmaker:exit")==0) {
1186 Shutdown(WSExitMode
);
1188 #ifdef UNSUPPORTED_STUFF
1189 } else if (strcmp(command
, "moduleRaised")==0) { /* useless */
1190 } else if (strcmp(command
, "deskUnclutter")==0) {
1191 } else if (strcmp(command
, "deskCascade")==0) {
1192 } else if (strcmp(command
, "configure")==0) {
1193 } else if (strcmp(command
, "taskManager")==0) {
1194 } else if (strcmp(command
, "darkenScreen")==0) { /* breaks consistency */
1196 } else if (!performWindowCommand(scr
, command
)) {
1197 KWMModuleList
*module
;
1200 /* do message relay thing */
1202 ev
.xclient
= *event
;
1203 for (module
= KWMModules
; module
!= NULL
; module
= module
->next
) {
1205 ev
.xclient
.window
= module
->window
;
1206 if (module
->window
== scr
->root_win
)
1207 mask
= SubstructureRedirectMask
;
1211 XSendEvent(dpy
, module
->window
, False
, mask
, &ev
);
1218 wKWMProcessClientMessage(XClientMessageEvent
*event
)
1220 Bool processed
= True
;
1223 printf("CLIENT MESS %s\n", XGetAtomName(dpy
, event
->message_type
));
1225 if (event
->message_type
== _XA_KWM_COMMAND
&& event
->format
==8) {
1229 scr
= wScreenForRootWindow(event
->window
);
1231 for (i
=0; i
<20; i
++) {
1232 buffer
[i
] = event
->data
.b
[i
];
1237 printf("got KDE command %s\n", buffer
);
1239 performCommand(scr
, buffer
, event
);
1241 } else if (event
->message_type
== _XA_KWM_ACTIVATE_WINDOW
) {
1245 printf("got KDE activate internal\n");
1247 wwin
= wWindowFor(event
->data
.l
[0]);
1250 wSetFocusTo(wwin
->screen_ptr
, wwin
);
1252 } else if (event
->message_type
== _XA_KWM_DO_NOT_MANAGE
1253 && event
->format
== 8) {
1254 KWMDoNotManageList
*node
;
1258 printf("got KDE dont manage\n");
1261 node
= malloc(sizeof(KWMDoNotManageList
));
1263 wwarning("out of memory processing KWM_DO_NOT_MANAGE message");
1265 for (i
=0; i
<20 && event
->data
.b
[i
]; i
++)
1266 node
->title
[i
] = event
->data
.b
[i
];
1269 node
->next
= KWMDoNotManageCrap
;
1270 KWMDoNotManageCrap
= node
;
1272 } else if (event
->message_type
== _XA_KWM_MODULE
) {
1274 Window modwin
= event
->data
.l
[0];
1276 scr
= wScreenForRootWindow(event
->window
);
1278 if (getSimpleHint(modwin
, _XA_KWM_MODULE
, &val
) && val
) {
1280 puts("got KDE module startup");
1282 addModule(scr
, modwin
);
1285 puts("got KDE module finish");
1287 removeModule(scr
, modwin
);
1298 wKWMCheckModule(WScreen
*scr
, Window window
)
1302 if (getSimpleHint(window
, _XA_KWM_MODULE
, &val
) && val
) {
1304 puts("got KDE module startup");
1306 addModule(scr
, window
);
1312 wKWMCheckRootHintChange(WScreen
*scr
, XPropertyEvent
*event
)
1314 Bool processed
= True
;
1317 if (event
->atom
== _XA_KWM_CURRENT_DESKTOP
) {
1318 if (getSimpleHint(scr
->root_win
, _XA_KWM_CURRENT_DESKTOP
, &value
)) {
1320 printf("got KDE workspace switch to %li\n", value
);
1322 if (value
-1 != scr
->current_workspace
) {
1323 wWorkspaceChange(scr
, value
-1);
1326 } else if (event
->atom
== _XA_KWM_NUMBER_OF_DESKTOPS
) {
1328 printf("got KDE workspace number change\n");
1331 if (getSimpleHint(scr
->root_win
, _XA_KWM_NUMBER_OF_DESKTOPS
, &value
)) {
1333 /* increasing is easy... */
1334 if (value
> scr
->workspace_count
) {
1335 scr
->flags
.kwm_syncing_count
= 1;
1337 wWorkspaceMake(scr
, value
- scr
->workspace_count
);
1339 scr
->flags
.kwm_syncing_count
= 0;
1341 } else if (value
< scr
->workspace_count
) {
1343 Bool rebuild
= False
;
1345 scr
->flags
.kwm_syncing_count
= 1;
1347 /* decrease all we can do */
1348 for (i
= scr
->workspace_count
; i
>= value
; i
--) {
1349 if (!wWorkspaceDelete(scr
, i
)) {
1355 scr
->flags
.kwm_syncing_count
= 0;
1357 /* someone destroyed a workspace that can't be destroyed.
1358 * Reset the hints to reflect our internal state.
1361 wKWMUpdateWorkspaceCountHint(scr
);
1370 for (i
= 0; i
< MAX_WORKSPACES
&& i
< scr
->workspace_count
; i
++) {
1371 if (event
->atom
== _XA_KWM_DESKTOP_NAME_
[i
]) {
1374 name
= wKWMGetWorkspaceName(scr
, i
);
1377 printf("got KDE workspace name change to %s\n", name
);
1380 if (name
&& strncmp(name
, scr
->workspaces
[i
]->name
,
1381 MAX_WORKSPACENAME_WIDTH
)!=0) {
1382 scr
->flags
.kwm_syncing_name
= 1;
1383 wWorkspaceRename(scr
, i
, name
);
1384 scr
->flags
.kwm_syncing_name
= 0;
1390 } else if (event
->atom
== _XA_KWM_WINDOW_REGION_
[i
]) {
1394 if (getAreaHint(scr
->root_win
, event
->atom
, &area
)) {
1396 if (scr
->totalUsableArea
.x1
!= area
.x1
1397 || scr
->totalUsableArea
.y1
!= area
.y1
1398 || scr
->totalUsableArea
.x2
!= area
.x2
1399 || scr
->totalUsableArea
.y2
!= area
.y2
) {
1400 wScreenUpdateUsableArea(scr
);
1404 if (i
== scr
->current_workspace
% MAX_WORKSPACES
)
1405 wScreenUpdateUsableArea(scr
);
1419 wKWMManageableClient(WScreen
*scr
, Window win
, char *title
)
1421 KWMDoNotManageList
*ptr
, *next
;
1424 if (getSimpleHint(win
, _XA_KWM_DOCKWINDOW
, &val
) && val
) {
1425 addDockWindow(scr
, win
);
1429 ptr
= KWMDoNotManageCrap
;
1431 * TODO: support for glob patterns or regexes
1433 if (ptr
&& strncmp(ptr
->title
, title
, strlen(ptr
->title
))==0) {
1436 KWMDoNotManageCrap
= next
;
1438 printf("window %s not managed per KDE request\n", title
);
1441 sendToModules(scr
, _XA_KWM_MODULE_WIN_ADD
, NULL
, win
);
1442 sendToModules(scr
, _XA_KWM_MODULE_WIN_REMOVE
, NULL
, win
);
1447 if (strncmp(ptr
->next
->title
, title
, strlen(ptr
->next
->title
))==0) {
1449 printf("window %s not managed per KDE request\n", title
);
1451 next
= ptr
->next
->next
;
1455 sendToModules(scr
, _XA_KWM_MODULE_WIN_ADD
, NULL
, win
);
1456 sendToModules(scr
, _XA_KWM_MODULE_WIN_REMOVE
, NULL
, win
);
1470 wKWMUpdateCurrentWorkspaceHint(WScreen
*scr
)
1472 setSimpleHint(scr
->root_win
, _XA_KWM_CURRENT_DESKTOP
,
1473 scr
->current_workspace
+1);
1475 sendToModules(scr
, _XA_KWM_MODULE_DESKTOP_CHANGE
, NULL
,
1476 scr
->current_workspace
+1);
1481 wKWMUpdateActiveWindowHint(WScreen
*scr
)
1484 WWindow
*wwin
, *tmp
;
1486 if (!scr
->focused_window
|| !scr
->focused_window
->flags
.focused
)
1489 val
= (long)(scr
->focused_window
->client_win
);
1491 /* raise the menubar thing */
1492 wwin
= scr
->focused_window
;
1495 if (tmp
->flags
.kwm_menubar
1496 && tmp
->transient_for
== wwin
->client_win
) {
1497 wRaiseFrame(tmp
->frame
->core
);
1504 XChangeProperty(dpy
, scr
->root_win
, _XA_KWM_ACTIVE_WINDOW
,
1505 _XA_KWM_ACTIVE_WINDOW
, 32, PropModeReplace
,
1506 (unsigned char*)&val
, 1);
1512 wKWMUpdateWorkspaceCountHint(WScreen
*scr
)
1514 if (scr
->flags
.kwm_syncing_count
)
1517 setSimpleHint(scr
->root_win
, _XA_KWM_NUMBER_OF_DESKTOPS
,
1518 scr
->workspace_count
);
1520 sendToModules(scr
, _XA_KWM_MODULE_DESKTOP_NUMBER_CHANGE
, NULL
,
1521 scr
->workspace_count
);
1526 wKWMCheckDestroy(XDestroyWindowEvent
*event
)
1530 if (event
->event
== event
->window
) {
1534 scr
= wScreenSearchForRootWindow(event
->event
);
1539 removeModule(scr
, event
->window
);
1540 removeDockWindow(scr
, event
->window
);
1545 wKWMUpdateWorkspaceNameHint(WScreen
*scr
, int workspace
)
1549 assert(workspace
>= 0 && workspace
< MAX_WORKSPACES
);
1551 if (_XA_KWM_DESKTOP_NAME_
[workspace
]==0) {
1552 snprintf(buffer
, sizeof(buffer
), "KWM_DESKTOP_NAME_%d", workspace
+ 1);
1554 _XA_KWM_DESKTOP_NAME_
[workspace
] = XInternAtom(dpy
, buffer
, False
);
1557 XChangeProperty(dpy
, scr
->root_win
, _XA_KWM_DESKTOP_NAME_
[workspace
],
1558 XA_STRING
, 8, PropModeReplace
,
1559 (unsigned char*)scr
->workspaces
[workspace
]->name
,
1560 strlen(scr
->workspaces
[workspace
]->name
)+1);
1562 sendToModules(scr
, _XA_KWM_MODULE_DESKTOP_NAME_CHANGE
, NULL
, workspace
+1);
1568 wKWMUpdateClientWorkspace(WWindow
*wwin
)
1571 printf("updating workspace of %s to %i\n",
1572 wwin
->frame
->title
, wwin
->frame
->workspace
+1);
1574 setSimpleHint(wwin
->client_win
, _XA_KWM_WIN_DESKTOP
,
1575 wwin
->frame
->workspace
+1);
1580 wKWMUpdateClientGeometryRestore(WWindow
*wwin
)
1584 rect
.x1
= wwin
->old_geometry
.x
;
1585 rect
.y1
= wwin
->old_geometry
.y
;
1586 rect
.x2
= wwin
->old_geometry
.x
+ wwin
->old_geometry
.width
;
1587 rect
.y2
= wwin
->old_geometry
.y
+ wwin
->old_geometry
.height
;
1589 setAreaHint(wwin
->client_win
, _XA_KWM_WIN_GEOMETRY_RESTORE
, rect
);
1594 wKWMUpdateClientStateHint(WWindow
*wwin
, WKWMStateFlag flags
)
1596 if (flags
& KWMIconifiedFlag
) {
1597 setSimpleHint(wwin
->client_win
, _XA_KWM_WIN_ICONIFIED
,
1598 wwin
->flags
.miniaturized
/*|| wwin->flags.shaded
1599 || wwin->flags.hidden*/);
1601 if (flags
& KWMStickyFlag
) {
1602 setSimpleHint(wwin
->client_win
, _XA_KWM_WIN_STICKY
,
1603 IS_OMNIPRESENT(wwin
));
1605 if (flags
& KWMMaximizedFlag
) {
1608 if (wwin
->flags
.maximized
& MAX_VERTICAL
)
1610 if (wwin
->flags
.maximized
& MAX_HORIZONTAL
)
1613 setSimpleHint(wwin
->client_win
, _XA_KWM_WIN_MAXIMIZED
, value
);
1619 wKWMGetUsableArea(WScreen
*scr
, int head
, WArea
*area
)
1623 int region
= scr
->current_workspace
% MAX_WORKSPACES
;
1625 if (_XA_KWM_WINDOW_REGION_
[region
]==0) {
1626 snprintf(buffer
, sizeof(buffer
), "KWM_WINDOW_REGION_%d", 1+region
);
1628 _XA_KWM_WINDOW_REGION_
[region
] = XInternAtom(dpy
, buffer
, False
);
1631 ok
= getAreaHint(scr
->root_win
, _XA_KWM_WINDOW_REGION_
[region
], area
);
1634 WMRect rect
= wGetRectForHead(scr
, head
);
1636 area
->x1
= WMAX(area
->x1
, rect
.pos
.x
);
1637 area
->x2
= WMIN(area
->x2
, rect
.pos
.x
+ rect
.size
.width
);
1638 area
->y1
= WMAX(area
->y1
, rect
.pos
.y
);
1639 area
->y2
= WMIN(area
->y2
, rect
.pos
.y
+ rect
.size
.height
);
1648 wKWMGetIconGeometry(WWindow
*wwin
, WArea
*area
)
1650 return getAreaHint(wwin
->client_win
, _XA_KWM_WIN_ICON_GEOMETRY
, area
);
1657 wKWMSetUsableAreaHint(WScreen
*scr
, int workspace
)
1659 /* if we set this after making changes of our own to the area,
1660 * the next time the area changes, we won't know what should
1661 * be the new final area. This protocol isn't worth a shit :/
1664 * According to Matthias Ettrich:
1665 * Indeed, there's no protocol to deal with the area yet in case several
1666 * clients want to influence it. It is sufficent, though, if it is clear
1667 * that one process is responsable for the area. For KDE this is kpanel, but
1668 * I see that there might be a conflict with the docking area of windowmaker
1676 assert(workspace
>= 0 && workspace
< MAX_WORKSPACES
);
1678 if (_XA_KWM_WINDOW_REGION_
[workspace
]==0) {
1679 snprintf(buffer
, sizeof(buffer
), "KWM_WINDOW_REGION_%d", workspace
+1);
1681 _XA_KWM_WINDOW_REGION_
[workspace
] = XInternAtom(dpy
, buffer
, False
);
1684 setAreaHint(scr
->root_win
, _XA_KWM_WINDOW_REGION_
[workspace
],
1685 scr
->totalUsableArea
);
1688 #endif /* not_used */
1691 wKWMSendEventMessage(WWindow
*wwin
, WKWMEventMessage message
)
1695 if (wwin
&& (wwin
->flags
.internal_window
1696 || wwin
->flags
.kwm_hidden_for_modules
1697 || !wwin
->flags
.kwm_managed
1698 || WFLAGP(wwin
, skip_window_list
)))
1703 msg
= _XA_KWM_MODULE_WIN_ADD
;
1705 case WKWMRemoveWindow
:
1706 msg
= _XA_KWM_MODULE_WIN_REMOVE
;
1708 case WKWMFocusWindow
:
1709 msg
= _XA_KWM_MODULE_WIN_ACTIVATE
;
1711 case WKWMRaiseWindow
:
1712 msg
= _XA_KWM_MODULE_WIN_RAISE
;
1714 case WKWMLowerWindow
:
1715 msg
= _XA_KWM_MODULE_WIN_LOWER
;
1717 case WKWMChangedClient
:
1718 msg
= _XA_KWM_MODULE_WIN_CHANGE
;
1720 case WKWMIconChange
:
1721 msg
= _XA_KWM_MODULE_WIN_ICON_CHANGE
;
1727 sendToModules(wwin
? wwin
->screen_ptr
: NULL
, msg
, wwin
, 0);
1732 writeSocket(int sock
, char *data
)
1736 snprintf(buffer
, sizeof(buffer
), "%i ", strlen(data
));
1737 write(sock
, buffer
, strlen(buffer
));
1738 write(sock
, data
, strlen(data
));
1743 connectKFM(WScreen
*scr
)
1751 struct sockaddr_un addr
;
1754 path
= wstrconcat(wgethomedir(), "/.kde/share/apps/kfm/pid");
1755 buffer
= wstrdup(getenv("DISPLAY"));
1757 ptr
= strchr(buffer
, ':');
1761 ptr
= strrchr(buffer
, '.');
1767 snprintf(b
, sizeof(b
), ".%i", scr
->screen
);
1769 buffer
= wstrappend(buffer
, b
);
1771 path
= wstrappend(path
, buffer
);
1775 f
= fopen(path
, "rb");
1781 fgets(buf
, sizeof(buf
), f
);
1782 buf
[sizeof(buf
)] = 0;
1787 if (kill(pid
, 0) != 0)
1791 fgets(buf
, sizeof(buf
), f
);
1792 buf
[sizeof(buf
)] = 0;
1795 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1798 addr
.sun_family
= AF_UNIX
;
1799 strcpy(addr
.sun_path
, buf
);
1801 if (connect(sock
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0) {
1806 path
= wstrconcat(wgethomedir(), "/.kde/share/apps/kfm/magic");
1807 f
= fopen(path
, "rb");
1812 ptr
= fgets(buf
, sizeof(buf
), f
);
1819 ptr
= wstrconcat("auth", buf
);
1821 writeSocket(sock
, ptr
);
1829 wKWMSelectRootRegion(WScreen
*scr
, int x
, int y
, int w
, int h
, Bool control
)
1836 sock
= connectKFM(scr
);
1839 puts("SENDING DATA");
1841 sprintf(buffer
, "selectRootIcons %i %i %i %i %c", x
, y
, w
, h
, control
);
1842 writeSocket(sock
, buffer
);
1850 observer(void *self
, WMNotification
*notif
)
1852 WScreen
*scr
= (WScreen
*)self
;
1853 WWindow
*wwin
= (WWindow
*)WMGetNotificationObject(notif
);
1854 const char *name
= WMGetNotificationName(notif
);
1855 void *data
= WMGetNotificationClientData(notif
);
1857 if (strcmp(name
, WMNManaged
) == 0 && wwin
) {
1858 wKWMUpdateClientWorkspace(wwin
);
1859 wKWMUpdateClientStateHint(wwin
, KWMAllFlags
);
1861 wwin
->flags
.kwm_managed
= 1;
1863 wKWMSendEventMessage(wwin
, WKWMAddWindow
);
1865 } else if (strcmp(name
, WMNUnmanaged
) == 0 && wwin
) {
1866 wwin
->frame
->workspace
= -1;
1868 wKWMUpdateClientWorkspace(wwin
);
1870 wKWMSendEventMessage(wwin
, WKWMRemoveWindow
);
1872 } else if (strcmp(name
, WMNChangedWorkspace
) == 0 && wwin
) {
1873 wKWMUpdateClientWorkspace(wwin
);
1874 wKWMSendEventMessage(wwin
, WKWMChangedClient
);
1876 } else if (strcmp(name
, WMNChangedFocus
) == 0) {
1877 wKWMUpdateActiveWindowHint(scr
);
1878 wKWMSendEventMessage(wwin
, WKWMFocusWindow
);
1880 } else if (strcmp(name
, WMNChangedName
) == 0) {
1881 wKWMSendEventMessage(wwin
, WKWMChangedClient
);
1883 } else if (strcmp(name
, WMNChangedState
) == 0) {
1884 char *detail
= (char*)data
;
1886 if (strcmp(detail
, "shade") == 0) {
1887 wKWMUpdateClientStateHint(wwin
, KWMIconifiedFlag
);
1888 wKWMSendEventMessage(wwin
, WKWMChangedClient
);
1889 } else if (strcmp(detail
, "omnipresent") == 0) {
1890 wKWMUpdateClientStateHint(wwin
, KWMStickyFlag
);
1891 wKWMSendEventMessage(wwin
, WKWMChangedClient
);
1892 } else if (strcmp(detail
, "maximize") == 0) {
1893 wKWMUpdateClientStateHint(wwin
, KWMMaximizedFlag
);
1894 wKWMSendEventMessage(wwin
, WKWMChangedClient
);
1895 } else if (strcmp(detail
, "iconify-transient") == 0) {
1896 if (wwin
->flags
.miniaturized
) {
1897 wKWMUpdateClientStateHint(wwin
, KWMIconifiedFlag
);
1898 wKWMSendEventMessage(wwin
, WKWMRemoveWindow
);
1899 wwin
->flags
.kwm_hidden_for_modules
= 1;
1901 wKWMUpdateClientStateHint(wwin
, KWMIconifiedFlag
);
1902 if (wwin
->flags
.kwm_hidden_for_modules
) {
1903 wKWMSendEventMessage(wwin
, WKWMAddWindow
);
1904 wwin
->flags
.kwm_hidden_for_modules
= 0;
1907 } else if (strcmp(detail
, "iconify") == 0) {
1908 wKWMUpdateClientStateHint(wwin
, KWMIconifiedFlag
);
1909 wKWMSendEventMessage(wwin
, WKWMChangedClient
);
1910 } else if (strcmp(detail
, "hide") == 0) {
1911 wKWMUpdateClientStateHint(wwin
, KWMIconifiedFlag
);
1912 wKWMSendEventMessage(wwin
, WKWMChangedClient
);
1915 } else if (strcmp(name
, WMNChangedStacking
) == 0 && wwin
) {
1917 wKWMBroadcastStacking(wwin
->screen_ptr
);
1918 else if (strcmp(data
, "lower") == 0)
1919 wKWMSendEventMessage(wwin
, WKWMLowerWindow
);
1920 else if (strcmp(data
, "raise") == 0)
1921 wKWMSendEventMessage(wwin
, WKWMRaiseWindow
);
1927 wsobserver(void *self
, WMNotification
*notif
)
1929 WScreen
*scr
= (WScreen
*)WMGetNotificationObject(notif
);
1930 const char *name
= WMGetNotificationName(notif
);
1931 void *data
= WMGetNotificationClientData(notif
);
1933 if (strcmp(name
, WMNWorkspaceCreated
) == 0) {
1934 if (!scr
->flags
.kwm_syncing_count
) {
1935 wKWMUpdateWorkspaceCountHint(scr
);
1936 wKWMUpdateWorkspaceNameHint(scr
, (int)data
);
1939 wKWMSetUsableAreaHint(scr
, scr
->workspace_count
-1);
1941 } else if (strcmp(name
, WMNWorkspaceDestroyed
) == 0) {
1942 wKWMUpdateWorkspaceCountHint(scr
);
1943 } else if (strcmp(name
, WMNWorkspaceNameChanged
) == 0) {
1944 wKWMUpdateWorkspaceNameHint(scr
, (int)data
);
1945 } else if (strcmp(name
, WMNWorkspaceChanged
) == 0) {
1946 wKWMUpdateCurrentWorkspaceHint(scr
);
1948 } else if (strcmp(name
, WMNResetStacking
) == 0) {
1949 wKWMBroadcastStacking(scr
);
1954 #endif /* KWM_HINTS */