Fix some bugs, DisableMiniwindows, _KWM_WIN_ICON_GEOMETRY..
[wmaker-crm.git] / src / kwm.c
bloba888b60831b8b712bb39c1a969b20b3c93c38dca
1 /* kwm.c-- stuff for support for kwm hints
3 * Window Maker window manager
4 *
5 * Copyright (c) 1998, 1999 Alfredo K. Kojima
6 *
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,
20 * USA.
25 * Supported stuff:
26 * ================
27 * kwm.h function/method Notes
28 *----------------------------------------------------------------------------
29 * setUnsavedDataHint() currently, only gives visual clue that
30 * there is unsaved data (broken X close button)
31 * setSticky()
32 * setIcon() std X thing...
33 * setDecoration()
34 * logout()
35 * refreshScreen()
36 * setWmCommand() std X thing
37 * currentDesktop()
38 * setKWMModule()
40 * isKWMInitialized() not trustworthy
41 * activeWindow() dunno it's use, but since it's easy to
42 * implement it won't hurt to support
43 * switchToDesktop()
44 * (set/get)WindowRegion()
45 * (set)numberOfDesktops() KDE limits to 32, but wmaker is virtually
46 * unlimited. May raise some incompatibility
47 * in badly written KDE modules?
48 * (set/get)DesktopName()
49 * sendKWMCommand() also does the message relay thing
50 * desktop()
51 * geometryRestore()
52 * isIconified()
53 * isMaximized()
54 * isSticky()
55 * moveToDesktop() WARNING: evil mechanism
56 * setGeometryRestore() WARNING: evil mechanism
57 * setMaximize() woo hoo! wanna race?
58 * setIconify() BAH!: why reinvent the f'ing wheel!?
59 * its even broken!!!
60 * move() std X thing
61 * setGeometry() std X thing
62 * close() std X thing
63 * activate()
64 * activateInternal()
65 * raise() std X thing
66 * lower() std X thing
67 * prepareForSwallowing() std X thing
68 * doNotManage() klugy thing...
69 * getBlablablaString()
70 * setKWMDockModule() maybe we can make the Dock behave as the KDE
71 * dock, but must figure where to show the windows
72 * setDockWindow()
74 * Unsupported stuff (superfluous/not-essential/nonsense):
75 * =======================================================
77 * darkenScreen()
78 * setMiniIcon()
79 * configureWm()
80 * raiseSoundEvent()
81 * registerSoundEvent()
82 * unregisterSoundEvent()
83 * title()
84 * titleWithState()
85 * geometry() kde lib code makes it unnecessary
88 * Extensions to KDE:
89 * ==================
91 * These are clientmessage-type messages specific to Window Maker:
92 * wmaker:info - show info panel
93 * wmaker:legal - show legal panel
94 * wmaker:arrangeIcons - arrange icons
95 * wmaker:showAll - show all windows
96 * wmaker:hideOthers - hide others
97 * wmaker:restart - restart wmaker
98 * wmaker:exit - exit wmaker
102 * TODO
103 * different WORKAREA for each workspace
107 #include "wconfig.h"
109 #ifdef KWM_HINTS
111 #include <X11/Xlib.h>
112 #include <X11/Xutil.h>
113 #include <X11/Xatom.h>
115 #include <stdlib.h>
116 #include <stdio.h>
117 #include <string.h>
120 #include "WindowMaker.h"
122 #include "screen.h"
123 #include "wcore.h"
124 #include "framewin.h"
125 #include "window.h"
126 #include "properties.h"
127 #include "icon.h"
128 #include "client.h"
129 #include "funcs.h"
130 #include "actions.h"
131 #include "workspace.h"
132 #include "dialog.h"
134 #include "kwm.h"
136 /*#define DEBUG1
138 /******* Global ******/
140 extern Time LastFocusChange;
141 extern Time LastTimestamp;
144 extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW;
145 extern Atom _XA_WM_DELETE_WINDOW;
147 /** Local **/
149 static Atom _XA_KWM_COMMAND = 0;
150 static Atom _XA_KWM_ACTIVATE_WINDOW = 0;
151 static Atom _XA_KWM_ACTIVE_WINDOW = 0;
152 static Atom _XA_KWM_DO_NOT_MANAGE = 0;
153 static Atom _XA_KWM_DOCKWINDOW = 0;
154 static Atom _XA_KWM_RUNNING = 0;
156 static Atom _XA_KWM_MODULE = 0;
158 static Atom _XA_KWM_MODULE_INIT = 0;
159 static Atom _XA_KWM_MODULE_INITIALIZED = 0;
160 static Atom _XA_KWM_MODULE_DESKTOP_CHANGE = 0;
161 static Atom _XA_KWM_MODULE_DESKTOP_NAME_CHANGE = 0;
162 static Atom _XA_KWM_MODULE_DESKTOP_NUMBER_CHANGE = 0;
163 static Atom _XA_KWM_MODULE_WIN_ADD = 0;
164 static Atom _XA_KWM_MODULE_WIN_REMOVE = 0;
165 static Atom _XA_KWM_MODULE_WIN_CHANGE = 0;
166 static Atom _XA_KWM_MODULE_WIN_RAISE = 0;
167 static Atom _XA_KWM_MODULE_WIN_LOWER = 0;
168 static Atom _XA_KWM_MODULE_WIN_ACTIVATE = 0;
169 static Atom _XA_KWM_MODULE_WIN_ICON_CHANGE = 0;
170 static Atom _XA_KWM_MODULE_DOCKWIN_ADD = 0;
171 static Atom _XA_KWM_MODULE_DOCKWIN_REMOVE = 0;
173 static Atom _XA_KWM_WIN_UNSAVED_DATA = 0;
174 static Atom _XA_KWM_WIN_DECORATION = 0;
175 static Atom _XA_KWM_WIN_DESKTOP = 0;
176 static Atom _XA_KWM_WIN_GEOMETRY_RESTORE = 0;
177 static Atom _XA_KWM_WIN_ICONIFIED = 0;
178 static Atom _XA_KWM_WIN_MAXIMIZED = 0;
179 static Atom _XA_KWM_WIN_STICKY = 0;
181 static Atom _XA_KWM_WIN_ICON_GEOMETRY = 0;
183 static Atom _XA_KWM_CURRENT_DESKTOP = 0;
184 static Atom _XA_KWM_NUMBER_OF_DESKTOPS = 0;
185 static Atom _XA_KWM_DESKTOP_NAME_[MAX_WORKSPACES];
186 static Atom _XA_KWM_WINDOW_REGION_[MAX_WORKSPACES];
190 /* list of window titles that must not be managed */
191 typedef struct KWMDoNotManageList {
192 char title[20];
193 struct KWMDoNotManageList *next;
194 } KWMDoNotManageList;
196 static KWMDoNotManageList *KWMDoNotManageCrap = NULL;
199 /* list of KWM modules */
200 typedef struct KWMModuleList {
201 Window window;
202 struct KWMModuleList *next;
203 #ifdef DEBUG1
204 char *title;
205 #endif
206 } KWMModuleList;
208 static KWMModuleList *KWMModules = NULL;
210 static KWMModuleList *KWMDockWindows = NULL;
212 /* window decoration types */
213 enum {
214 KWMnoDecoration = 0,
215 KWMnormalDecoration = 1,
216 KWMtinyDecoration = 2,
217 KWMnoFocus = 256
222 static Bool
223 getSimpleHint(Window win, Atom atom, long *retval)
225 long *data = 0;
227 assert(atom!=0);
229 data = (long*)PropGetCheckProperty(win, atom, atom, 32, 1, NULL);
231 if (!data)
232 return False;
234 *retval = *data;
236 XFree(data);
238 return True;
243 static void
244 setSimpleHint(Window win, Atom atom, long value)
246 assert(atom!=0);
247 XChangeProperty(dpy, win, atom, atom,
248 32, PropModeReplace, (unsigned char*)&value, 1);
252 static void
253 sendClientMessage(WScreen *scr, Window window, Atom atom, long value)
255 XEvent event;
256 long mask = 0;
258 assert(atom!=0);
260 memset(&event, 0, sizeof(XEvent));
261 event.xclient.type = ClientMessage;
262 event.xclient.message_type = atom;
263 event.xclient.window = window;
264 event.xclient.format = 32;
265 event.xclient.data.l[0] = value;
266 event.xclient.data.l[1] = LastTimestamp;
268 if (scr && scr->root_win == window)
269 mask = SubstructureRedirectMask;
271 XSendEvent(dpy, window, False, mask, &event);
275 static void
276 sendTextMessage(WScreen *scr, Window window, Atom atom, char *text)
278 XEvent event;
279 long mask = 0;
280 int i;
282 assert(atom!=0);
284 memset(&event, 0, sizeof(XEvent));
285 event.xclient.type = ClientMessage;
286 event.xclient.message_type = atom;
287 event.xclient.window = window;
288 event.xclient.format = 8;
290 for (i=0; i<20 && text[i]; i++)
291 event.xclient.data.b[i] = text[i];
293 if (scr && scr->root_win == window)
294 mask = SubstructureRedirectMask;
296 XSendEvent(dpy, window, False, mask, &event);
300 static Bool
301 getAreaHint(Window win, Atom atom, WArea *area)
303 long *data = 0;
305 data = (long*)PropGetCheckProperty(win, atom, atom, 32, 4, NULL);
307 if (!data)
308 return False;
310 area->x1 = data[0];
311 area->y1 = data[1];
312 area->x2 = data[2] + area->x1;
313 area->y2 = data[3] + area->y1;
315 XFree(data);
317 return True;
321 static void
322 setAreaHint(Window win, Atom atom, WArea area)
324 long value[4];
326 assert(atom!=0);
327 value[0] = area.x1;
328 value[1] = area.y1;
329 value[2] = area.x2 - area.x1;
330 value[3] = area.y2 - area.y1;
331 XChangeProperty(dpy, win, atom, atom, 32, PropModeReplace,
332 (unsigned char*)&value, 4);
336 static void
337 addModule(WScreen *scr, Window window)
339 KWMModuleList *node;
340 long val;
341 WWindow *ptr;
343 node = malloc(sizeof(KWMModuleList));
344 if (!node) {
345 wwarning("out of memory while registering KDE module");
346 return;
349 node->next = KWMModules;
350 node->window = window;
351 KWMModules = node;
353 sendClientMessage(scr, window, _XA_KWM_MODULE_INIT, 0);
355 if (getSimpleHint(window, _XA_KWM_MODULE, &val) && val==2) {
356 if (scr->kwm_dock != None) {
357 setSimpleHint(window, _XA_KWM_MODULE, 1);
358 } else {
359 KWMModuleList *ptr;
361 scr->kwm_dock = window;
363 for (ptr = KWMDockWindows; ptr!=NULL; ptr = ptr->next) {
364 sendClientMessage(scr, scr->kwm_dock, _XA_KWM_MODULE_DOCKWIN_ADD,
365 ptr->window);
370 /* send list of windows */
371 for (ptr = scr->focused_window; ptr!=NULL; ptr = ptr->prev) {
372 if (!ptr->flags.kwm_hidden_for_modules
373 && !WFLAGP(ptr, skip_window_list)) {
374 sendClientMessage(scr, window, _XA_KWM_MODULE_WIN_ADD,
375 ptr->client_win);
379 /* send window stacking order */
380 wKWMSendStacking(scr, window);
382 /* send focused window */
383 if (scr->focused_window && scr->focused_window->flags.focused) {
384 sendClientMessage(scr, window, _XA_KWM_MODULE_WIN_ACTIVATE,
385 scr->focused_window->client_win);
388 /* tell who we are */
389 sendTextMessage(scr, window, _XA_KWM_COMMAND, "wm:wmaker");
392 sendClientMessage(scr, window, _XA_KWM_MODULE_INITIALIZED, 0);
393 #ifdef DEBUG1
394 KWMModules->title = NULL;
395 XFetchName(dpy, window, &KWMModules->title);
396 printf("NEW MODULE %s\n", KWMModules->title);
397 #endif
401 static void
402 removeModule(WScreen *scr, Window window)
404 KWMModuleList *next;
406 if (!KWMModules) {
407 return;
410 if (KWMModules->window == window) {
411 next = KWMModules->next;
412 #ifdef DEBUG1
413 printf("REMOVING MODULE %s\n", KWMModules->title);
414 if (KWMModules->title)
415 XFree(KWMModules->title);
416 #endif
417 free(KWMModules);
418 KWMModules = next;
419 } else {
420 KWMModuleList *ptr;
422 ptr = KWMModules;
423 while (ptr->next) {
424 if (ptr->next->window == window) {
425 next = ptr->next->next;
426 #ifdef DEBUG1
427 printf("REMOVING MODULE %s\n", ptr->next->title);
428 if (ptr->next->title)
429 XFree(ptr->next->title);
430 #endif
431 free(ptr->next);
432 ptr->next->next = next;
433 break;
435 ptr->next = ptr->next->next;
439 if (scr->kwm_dock == window)
440 scr->kwm_dock = None;
445 static void
446 addDockWindow(WScreen *scr, Window window)
448 KWMModuleList *ptr;
450 for (ptr = KWMDockWindows; ptr != NULL; ptr = ptr->next) {
451 if (ptr->window == window)
452 break;
454 if (!ptr) {
455 KWMModuleList *node;
457 node = malloc(sizeof(KWMModuleList));
458 if (!node) {
459 wwarning("out of memory while processing KDE dock window");
460 return;
462 node->next = KWMDockWindows;
463 KWMDockWindows = node;
464 node->window = window;
465 XSelectInput(dpy, window, StructureNotifyMask);
467 sendClientMessage(scr, scr->kwm_dock, _XA_KWM_MODULE_DOCKWIN_ADD,
468 window);
473 static void
474 removeDockWindow(WScreen *scr, Window window)
476 if (!KWMDockWindows)
477 return;
479 if (KWMDockWindows->window == window) {
480 KWMModuleList *next;
482 sendClientMessage(scr, scr->kwm_dock, _XA_KWM_MODULE_DOCKWIN_REMOVE,
483 window);
485 next = KWMDockWindows->next;
486 free(KWMDockWindows);
487 KWMDockWindows = next;
489 } else {
490 KWMModuleList *ptr, *next;
492 ptr = KWMDockWindows;
493 while (ptr->next) {
494 if (ptr->next->window == window) {
495 sendClientMessage(scr, scr->kwm_dock,
496 _XA_KWM_MODULE_DOCKWIN_REMOVE, window);
497 next = ptr->next->next;
498 free(ptr->next);
499 ptr->next = next;
500 return;
502 ptr = ptr->next;
508 static void
509 sendToModules(WScreen *scr, Atom atom, WWindow *wwin, long data)
511 KWMModuleList *ptr;
512 XEvent event;
513 long mask;
515 if (wwin) {
516 if (wwin->flags.kwm_hidden_for_modules
517 || WFLAGP(wwin, skip_window_list))
518 return;
519 data = wwin->client_win;
521 #ifdef DEBUG1
522 printf("notifying %s\n",XGetAtomName(dpy, atom));
523 #endif
524 memset(&event, 0, sizeof(XEvent));
525 event.xclient.type = ClientMessage;
526 event.xclient.message_type = atom;
527 event.xclient.format = 32;
528 event.xclient.data.l[1] = LastTimestamp;
530 mask = 0;
531 if (scr && scr->root_win == data)
532 mask = SubstructureRedirectMask;
534 for (ptr = KWMModules; ptr!=NULL; ptr = ptr->next) {
535 event.xclient.window = ptr->window;
536 event.xclient.data.l[0] = data;
537 XSendEvent(dpy, ptr->window, False, mask, &event);
542 void
543 wKWMInitStuff(WScreen *scr)
545 if (!_XA_KWM_WIN_STICKY) {
546 _XA_KWM_WIN_UNSAVED_DATA = XInternAtom(dpy, "KWM_WIN_UNSAVED_DATA",
547 False);
549 _XA_KWM_WIN_DECORATION = XInternAtom(dpy, "KWM_WIN_DECORATION", False);
551 _XA_KWM_WIN_DESKTOP = XInternAtom(dpy, "KWM_WIN_DESKTOP", False);
553 _XA_KWM_WIN_GEOMETRY_RESTORE = XInternAtom(dpy,
554 "KWM_WIN_GEOMETRY_RESTORE",
555 False);
557 _XA_KWM_WIN_STICKY = XInternAtom(dpy, "KWM_WIN_STICKY", False);
559 _XA_KWM_WIN_ICONIFIED = XInternAtom(dpy, "KWM_WIN_ICONIFIED", False);
561 _XA_KWM_WIN_MAXIMIZED = XInternAtom(dpy, "KWM_WIN_MAXIMIZED", False);
563 _XA_KWM_WIN_ICON_GEOMETRY = XInternAtom(dpy, "KWM_WIN_ICON_GEOMETRY",
564 False);
566 _XA_KWM_COMMAND = XInternAtom(dpy, "KWM_COMMAND", False);
568 _XA_KWM_ACTIVE_WINDOW = XInternAtom(dpy, "KWM_ACTIVE_WINDOW", False);
570 _XA_KWM_ACTIVATE_WINDOW = XInternAtom(dpy, "KWM_ACTIVATE_WINDOW",
571 False);
573 _XA_KWM_DO_NOT_MANAGE = XInternAtom(dpy, "KWM_DO_NOT_MANAGE", False);
575 _XA_KWM_CURRENT_DESKTOP = XInternAtom(dpy, "KWM_CURRENT_DESKTOP",
576 False);
578 _XA_KWM_NUMBER_OF_DESKTOPS = XInternAtom(dpy, "KWM_NUMBER_OF_DESKTOPS",
579 False);
581 _XA_KWM_DOCKWINDOW = XInternAtom(dpy, "KWM_DOCKWINDOW", False);
583 _XA_KWM_RUNNING = XInternAtom(dpy, "KWM_RUNNING", False);
585 _XA_KWM_MODULE = XInternAtom(dpy, "KWM_MODULE", False);
587 _XA_KWM_MODULE_INIT = XInternAtom(dpy, "KWM_MODULE_INIT", False);
588 _XA_KWM_MODULE_INITIALIZED = XInternAtom(dpy, "KWM_MODULE_INITIALIZED", False);
590 /* dunno what these do, but Matthias' patch contains it... */
591 _XA_KWM_MODULE_DESKTOP_CHANGE = XInternAtom(dpy, "KWM_MODULE_DESKTOP_CHANGE", False);
592 _XA_KWM_MODULE_DESKTOP_NAME_CHANGE = XInternAtom(dpy, "KWM_MODULE_DESKTOP_NAME_CHANGE", False);
593 _XA_KWM_MODULE_DESKTOP_NUMBER_CHANGE = XInternAtom(dpy, "KWM_MODULE_DESKTOP_NUMBER_CHANGE", False);
595 _XA_KWM_MODULE_WIN_ADD = XInternAtom(dpy, "KWM_MODULE_WIN_ADD", False);
596 _XA_KWM_MODULE_WIN_REMOVE = XInternAtom(dpy, "KWM_MODULE_WIN_REMOVE", False);
597 _XA_KWM_MODULE_WIN_CHANGE = XInternAtom(dpy, "KWM_MODULE_WIN_CHANGE", False);
598 _XA_KWM_MODULE_WIN_RAISE = XInternAtom(dpy, "KWM_MODULE_WIN_RAISE", False);
599 _XA_KWM_MODULE_WIN_LOWER = XInternAtom(dpy, "KWM_MODULE_WIN_LOWER", False);
600 _XA_KWM_MODULE_WIN_ACTIVATE = XInternAtom(dpy, "KWM_MODULE_WIN_ACTIVATE", False);
601 _XA_KWM_MODULE_WIN_ICON_CHANGE = XInternAtom(dpy, "KWM_MODULE_WIN_ICON_CHANGE", False);
602 _XA_KWM_MODULE_DOCKWIN_ADD = XInternAtom(dpy, "KWM_MODULE_DOCKWIN_ADD", False);
603 _XA_KWM_MODULE_DOCKWIN_REMOVE = XInternAtom(dpy, "KWM_MODULE_DOCKWIN_REMOVE", False);
605 memset(_XA_KWM_WINDOW_REGION_, 0, sizeof(_XA_KWM_WINDOW_REGION_));
607 memset(_XA_KWM_DESKTOP_NAME_, 0, sizeof(_XA_KWM_DESKTOP_NAME_));
610 #define SETSTR(hint, str) {\
611 static Atom a = 0; if (!a) a = XInternAtom(dpy, #hint, False);\
612 XChangeProperty(dpy, scr->root_win, a, XA_STRING, 8, PropModeReplace,\
613 (unsigned char*)str, strlen(str));}
615 SETSTR(KWM_STRING_MAXIMIZE, _("Maximize"));
616 SETSTR(KWM_STRING_UNMAXIMIZE, _("Unmaximize"));
617 SETSTR(KWM_STRING_ICONIFY, _("Miniaturize"));
618 SETSTR(KWM_STRING_UNICONIFY, _("Deminiaturize"));
619 SETSTR(KWM_STRING_STICKY, _("Omnipresent"));
620 SETSTR(KWM_STRING_UNSTICKY, _("Not Omnipresent"));
621 SETSTR(KWM_STRING_STRING_MOVE, _("Move"));
622 SETSTR(KWM_STRING_STRING_RESIZE, _("Resize"));
623 SETSTR(KWM_STRING_CLOSE, _("Close"));
624 SETSTR(KWM_STRING_TODESKTOP, _("Move To"));
625 SETSTR(KWM_STRING_ONTOCURRENTDESKTOP, _("Bring Here"));
626 #undef SETSTR
630 void
631 wKWMSendStacking(WScreen *scr, Window module)
633 int i;
634 WCoreWindow *core;
636 for (i = 0; i < MAX_WINDOW_LEVELS; i++) {
637 for (core = scr->stacking_list[i]; core != NULL;
638 core = core->stacking->under) {
639 WWindow *wwin;
641 wwin = wWindowFor(core->window);
642 if (wwin)
643 sendClientMessage(scr, module, _XA_KWM_MODULE_WIN_RAISE,
644 wwin->client_win);
650 void
651 wKWMBroadcastStacking(WScreen *scr)
653 KWMModuleList *ptr = KWMModules;
655 while (ptr) {
656 wKWMSendStacking(scr, ptr->window);
658 ptr = ptr->next;
663 char*
664 wKWMGetWorkspaceName(WScreen *scr, int workspace)
666 Atom type_ret;
667 int fmt_ret;
668 unsigned long nitems_ret;
669 unsigned long bytes_after_ret;
670 char *data = NULL, *tmp;
671 char buffer[64];
673 assert(workspace >= 0 && workspace < MAX_WORKSPACES);
675 if (_XA_KWM_DESKTOP_NAME_[workspace]==0) {
676 sprintf(buffer, "KWM_DESKTOP_NAME_%d", workspace + 1);
678 _XA_KWM_DESKTOP_NAME_[workspace] = XInternAtom(dpy, buffer, False);
681 /* What do these people have against correctly using property types? */
682 if (XGetWindowProperty(dpy, scr->root_win,
683 _XA_KWM_DESKTOP_NAME_[workspace], 0, 128, False,
684 XA_STRING,
685 &type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
686 (unsigned char**)&data)!=Success || !data)
687 return NULL;
689 tmp = wstrdup(data);
690 XFree(data);
692 return tmp;
696 void
697 wKWMSetInitializedHint(WScreen *scr)
699 setSimpleHint(scr->root_win, _XA_KWM_RUNNING, 1);
703 void
704 wKWMShutdown(WScreen *scr, Bool closeModules)
706 KWMModuleList *ptr;
708 XDeleteProperty(dpy, scr->root_win, _XA_KWM_RUNNING);
710 if (closeModules) {
711 for (ptr = KWMModules; ptr != NULL; ptr = ptr->next) {
712 XKillClient(dpy, ptr->window);
718 void
719 wKWMCheckClientHints(WWindow *wwin, int *workspace)
721 long val;
723 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_UNSAVED_DATA, &val)
724 && val) {
726 wwin->client_flags.broken_close = 1;
728 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_DECORATION, &val)) {
729 if (val & KWMnoFocus) {
730 wwin->client_flags.no_focusable = 1;
732 switch (val & ~KWMnoFocus) {
733 case KWMnoDecoration:
734 wwin->client_flags.no_titlebar = 1;
735 wwin->client_flags.no_resizebar = 1;
736 break;
737 case KWMtinyDecoration:
738 wwin->client_flags.no_resizebar = 1;
739 break;
740 case KWMnormalDecoration:
741 default:
742 break;
745 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_DESKTOP, &val)) {
746 *workspace = val - 1;
751 void
752 wKWMCheckClientInitialState(WWindow *wwin)
754 long val;
756 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_STICKY, &val) && val) {
758 wwin->client_flags.omnipresent = 1;
760 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_ICONIFIED, &val)
761 && val) {
763 wwin->flags.miniaturized = 1;
765 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_MAXIMIZED, &val)
766 && val) {
768 wwin->flags.maximized = MAX_VERTICAL|MAX_HORIZONTAL;
773 Bool
774 wKWMCheckClientHintChange(WWindow *wwin, XPropertyEvent *event)
776 Bool processed = True;
777 Bool flag;
778 long value;
781 if (!wwin->frame) {
782 return False;
785 if (event->atom == _XA_KWM_WIN_UNSAVED_DATA) {
786 #ifdef DEBUG1
787 printf("got KDE unsaved data change\n");
788 #endif
790 flag = getSimpleHint(wwin->client_win, _XA_KWM_WIN_UNSAVED_DATA,
791 &value) && value;
793 if (flag != wwin->client_flags.broken_close) {
794 wwin->client_flags.broken_close = flag;
795 if (wwin->frame)
796 wWindowUpdateButtonImages(wwin);
798 } else if (event->atom == _XA_KWM_WIN_STICKY) {
800 #ifdef DEBUG1
801 printf("got KDE sticky change\n");
802 #endif
803 flag = !getSimpleHint(wwin->client_win, _XA_KWM_WIN_STICKY,
804 &value) || value;
806 if (flag != wwin->client_flags.omnipresent) {
808 wwin->client_flags.omnipresent = flag;
810 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_WORKSPACE);
813 } else if (event->atom == _XA_KWM_WIN_MAXIMIZED) {
815 #ifdef DEBUG1
816 printf("got KDE maximize change\n");
817 #endif
818 flag = !getSimpleHint(wwin->client_win, _XA_KWM_WIN_MAXIMIZED,
819 &value) || value;
821 if (flag != (wwin->flags.maximized!=0)) {
823 if (flag)
824 wMaximizeWindow(wwin, flag*(MAX_VERTICAL|MAX_HORIZONTAL));
825 else
826 wUnmaximizeWindow(wwin);
828 } else if (event->atom == _XA_KWM_WIN_ICONIFIED) {
830 #ifdef DEBUG1
831 printf("got KDE iconify change\n");
832 #endif
833 flag = !getSimpleHint(wwin->client_win, _XA_KWM_WIN_ICONIFIED,
834 &value) || value;
836 if (flag != wwin->flags.miniaturized) {
838 if (flag)
839 wIconifyWindow(wwin);
840 else
841 wDeiconifyWindow(wwin);
844 } else if (event->atom == _XA_KWM_WIN_DECORATION) {
845 Bool refresh = False;
846 int oldnofocus;
848 #ifdef DEBUG1
849 printf("got KDE decoration change\n");
850 #endif
852 oldnofocus = wwin->client_flags.no_focusable;
854 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_DECORATION, &value)) {
855 wwin->client_flags.no_focusable = (value & KWMnoFocus)!=0;
857 switch (value & ~KWMnoFocus) {
858 case KWMnoDecoration:
859 if (!WFLAGP(wwin, no_titlebar) || !WFLAGP(wwin, no_resizebar))
860 refresh = True;
862 wwin->client_flags.no_titlebar = 1;
863 wwin->client_flags.no_resizebar = 1;
864 break;
866 case KWMtinyDecoration:
867 if (WFLAGP(wwin, no_titlebar) || !WFLAGP(wwin, no_resizebar))
868 refresh = True;
870 wwin->client_flags.no_titlebar = 0;
871 wwin->client_flags.no_resizebar = 1;
872 break;
874 case KWMnormalDecoration:
875 default:
876 if (WFLAGP(wwin, no_titlebar) || WFLAGP(wwin, no_resizebar))
877 refresh = True;
879 wwin->client_flags.no_titlebar = 0;
880 wwin->client_flags.no_resizebar = 0;
881 break;
883 } else {
884 if (WFLAGP(wwin, no_titlebar) || WFLAGP(wwin, no_resizebar))
885 refresh = True;
886 wwin->client_flags.no_focusable = (value & KWMnoFocus)!=0;
887 wwin->client_flags.no_titlebar = 0;
888 wwin->client_flags.no_resizebar = 0;
891 if (refresh)
892 wWindowConfigureBorders(wwin);
894 if (wwin->client_flags.no_focusable && !oldnofocus) {
896 sendToModules(wwin->screen_ptr, _XA_KWM_MODULE_WIN_REMOVE,
897 wwin, 0);
898 wwin->flags.kwm_hidden_for_modules = 1;
900 } else if (!wwin->client_flags.no_focusable && oldnofocus) {
902 if (wwin->flags.kwm_hidden_for_modules) {
903 sendToModules(wwin->screen_ptr, _XA_KWM_MODULE_WIN_ADD,
904 wwin, 0);
905 wwin->flags.kwm_hidden_for_modules = 0;
908 } else if (event->atom == _XA_KWM_WIN_DESKTOP && wwin->frame) {
909 #ifdef DEBUG1
910 printf("got KDE workspace change for %s\n", wwin->frame->title);
911 #endif
912 if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_DESKTOP, &value)
913 && value-1 != wwin->frame->workspace) {
914 wWindowChangeWorkspace(wwin, value-1);
917 } else if (event->atom == _XA_KWM_WIN_GEOMETRY_RESTORE) {
918 WArea area;
920 #ifdef DEBUG1
921 printf("got KDE geometry restore change\n");
922 #endif
923 if (getAreaHint(wwin->client_win, _XA_KWM_WIN_GEOMETRY_RESTORE, &area)
924 && (wwin->old_geometry.x != area.x1
925 || wwin->old_geometry.y != area.y1
926 || wwin->old_geometry.width != area.x2 - area.x1
927 || wwin->old_geometry.height != area.y2 - area.y1)) {
929 wwin->old_geometry.x = area.x1;
930 wwin->old_geometry.y = area.y1;
931 wwin->old_geometry.width = area.x2 - area.x1;
932 wwin->old_geometry.height = area.y2 - area.y1;
934 } else {
935 processed = False;
938 return processed;
942 static Bool
943 performWindowCommand(WScreen *scr, char *command)
945 WWindow *wwin = NULL;
948 wwin = scr->focused_window;
949 if (!wwin || !wwin->flags.focused || !wwin->flags.mapped) {
950 wwin = NULL;
953 CloseWindowMenu(scr);
956 if (strcmp(command, "winMove")==0 || strcmp(command, "winResize")==0) {
958 if (wwin)
959 wKeyboardMoveResizeWindow(wwin);
961 } else if (strcmp(command, "winMaximize")==0) {
963 if (wwin)
964 wMaximizeWindow(wwin, MAX_VERTICAL|MAX_HORIZONTAL);
966 } else if (strcmp(command, "winRestore")==0) {
968 if (wwin && wwin->flags.maximized)
969 wUnmaximizeWindow(wwin);
971 } else if (strcmp(command, "winIconify")==0) {
974 if (wwin && !WFLAGP(wwin, no_miniaturizable)) {
975 if (wwin->protocols.MINIATURIZE_WINDOW)
976 wClientSendProtocol(wwin, _XA_GNUSTEP_WM_MINIATURIZE_WINDOW,
977 LastTimestamp);
978 else {
979 wIconifyWindow(wwin);
983 } else if (strcmp(command, "winClose")==0) {
985 if (wwin && !WFLAGP(wwin, no_closable)) {
986 if (wwin->protocols.DELETE_WINDOW)
987 wClientSendProtocol(wwin, _XA_WM_DELETE_WINDOW, LastTimestamp);
990 } else if (strcmp(command, "winSticky")==0) {
992 if (wwin) {
993 wwin->client_flags.omnipresent ^= 1;
994 UpdateSwitchMenu(scr, wwin, ACTION_CHANGE_WORKSPACE);
997 } else if (strcmp(command, "winShade")==0) {
999 if (wwin && !WFLAGP(wwin, no_shadeable)) {
1000 if (wwin->flags.shaded)
1001 wUnshadeWindow(wwin);
1002 else
1003 wShadeWindow(wwin);
1006 } else if (strcmp(command, "winOperation")==0) {
1008 if (wwin)
1009 OpenWindowMenu(wwin, wwin->frame_x,
1010 wwin->frame_y+wwin->frame->top_width, True);
1012 } else {
1013 return False;
1016 return True;
1020 static void
1021 performCommand(WScreen *scr, char *command, XClientMessageEvent *event)
1023 assert(scr != NULL);
1025 if (strcmp(command, "commandLine")==0
1026 || strcmp(command, "execute")==0) {
1027 char *cmd;
1029 cmd = ExpandOptions(scr, _("%a(Run Command,Type the command to run:)"));
1030 if (cmd) {
1031 ExecuteShellCommand(scr, cmd);
1032 free(cmd);
1034 } else if (strcmp(command, "logout")==0) {
1036 Shutdown(WSLogoutMode);
1038 } else if (strcmp(command, "refreshScreen")==0) {
1040 wRefreshDesktop(scr);
1042 } else if (strncmp(command, "go:", 3)==0) {
1044 Shutdown(WSRestartPreparationMode);
1045 Restart(&command[3]);
1047 } else if (strcmp(command, "desktop+1")==0) {
1049 wWorkspaceRelativeChange(scr, 1);
1051 } else if (strcmp(command, "desktop-1")==0) {
1053 wWorkspaceRelativeChange(scr, -1);
1055 } else if (strcmp(command, "desktop+2")==0) {
1057 wWorkspaceRelativeChange(scr, 2);
1059 } else if (strcmp(command, "desktop-2")==0) {
1061 wWorkspaceRelativeChange(scr, -2);
1063 } else if (strcmp(command, "desktop%%2")==0) {
1065 if (scr->current_workspace % 2 == 1)
1066 wWorkspaceRelativeChange(scr, 1);
1067 else
1068 wWorkspaceRelativeChange(scr, -1);
1069 } else if (strncmp(command, "desktop", 7)==0) {
1070 int ws;
1072 ws = atoi(&command[7]);
1073 wWorkspaceChange(scr, ws);
1075 /* wmaker specific stuff */
1076 } else if (strcmp(command, "wmaker:info")==0) {
1078 wShowInfoPanel(scr);
1080 } else if (strcmp(command, "wmaker:legal")==0) {
1082 wShowLegalPanel(scr);
1084 } else if (strcmp(command, "wmaker:arrangeIcons")==0) {
1086 wArrangeIcons(scr, True);
1088 } else if (strcmp(command, "wmaker:showAll")==0) {
1090 wShowAllWindows(scr);
1092 } else if (strcmp(command, "wmaker:hideOthers")==0) {
1094 wHideOtherApplications(scr->focused_window);
1096 } else if (strcmp(command, "wmaker:restart")==0) {
1098 Shutdown(WSRestartPreparationMode);
1099 Restart(NULL);
1101 } else if (strcmp(command, "wmaker:exit")==0) {
1103 Shutdown(WSExitMode);
1105 #ifdef UNSUPPORTED_STUFF
1106 } else if (strcmp(command, "moduleRaised")==0) { /* useless */
1107 } else if (strcmp(command, "deskUnclutter")==0) {
1108 } else if (strcmp(command, "deskCascade")==0) {
1109 } else if (strcmp(command, "configure")==0) {
1110 } else if (strcmp(command, "taskManager")==0) {
1111 } else if (strcmp(command, "darkenScreen")==0) { /* breaks consistency */
1112 #endif
1113 } else if (!performWindowCommand(scr, command)) {
1114 KWMModuleList *module;
1115 long mask = 0;
1116 XEvent ev;
1117 /* do message relay thing */
1119 ev.xclient = *event;
1120 for (module = KWMModules; module != NULL; module = module->next) {
1122 ev.xclient.window = module->window;
1123 if (module->window == scr->root_win)
1124 mask = SubstructureRedirectMask;
1125 else
1126 mask = 0;
1128 XSendEvent(dpy, module->window, False, mask, &ev);
1134 Bool
1135 wKWMProcessClientMessage(XClientMessageEvent *event)
1137 Bool processed = True;
1138 WScreen *scr;
1139 #ifdef DEBUG1
1140 printf("CLIENT MESS %s\n", XGetAtomName(dpy, event->message_type));
1141 #endif
1142 if (event->message_type == _XA_KWM_COMMAND && event->format==8) {
1143 char buffer[24];
1144 int i;
1146 scr = wScreenForRootWindow(event->window);
1148 for (i=0; i<20; i++) {
1149 buffer[i] = event->data.b[i];
1151 buffer[i] = 0;
1153 #ifdef DEBUG1
1154 printf("got KDE command %s\n", buffer);
1155 #endif
1156 performCommand(scr, buffer, event);
1158 } else if (event->message_type == _XA_KWM_ACTIVATE_WINDOW) {
1159 WWindow *wwin;
1161 #ifdef DEBUG1
1162 printf("got KDE activate internal\n");
1163 #endif
1164 wwin = wWindowFor(event->data.l[0]);
1166 if (wwin)
1167 wSetFocusTo(wwin->screen_ptr, wwin);
1169 } else if (event->message_type == _XA_KWM_DO_NOT_MANAGE
1170 && event->format == 8) {
1171 KWMDoNotManageList *node;
1172 int i;
1174 #ifdef DEBUG1
1175 printf("got KDE dont manage\n");
1176 #endif
1178 node = malloc(sizeof(KWMDoNotManageList));
1179 if (!node) {
1180 wwarning("out of memory processing KWM_DO_NOT_MANAGE message");
1182 for (i=0; i<20 && event->data.b[i]; i++)
1183 node->title[i] = event->data.b[i];
1184 node->title[i] = 0;
1186 node->next = KWMDoNotManageCrap;
1187 KWMDoNotManageCrap = node;
1189 } else if (event->message_type == _XA_KWM_MODULE) {
1190 long val;
1191 Window modwin = event->data.l[0];
1193 scr = wScreenForRootWindow(event->window);
1195 if (getSimpleHint(modwin, _XA_KWM_MODULE, &val) && val) {
1196 #ifdef DEBUG1
1197 puts("got KDE module startup");
1198 #endif
1199 addModule(scr, modwin);
1200 } else {
1201 #ifdef DEBUG1
1202 puts("got KDE module finish");
1203 #endif
1204 removeModule(scr, modwin);
1206 } else {
1207 processed = False;
1210 return processed;
1214 void
1215 wKWMCheckModule(WScreen *scr, Window window)
1217 long val;
1219 if (getSimpleHint(window, _XA_KWM_MODULE, &val) && val) {
1220 #ifdef DEBUG1
1221 puts("got KDE module startup");
1222 #endif
1223 addModule(scr, window);
1228 Bool
1229 wKWMCheckRootHintChange(WScreen *scr, XPropertyEvent *event)
1231 Bool processed = True;
1232 long value;
1234 if (event->atom == _XA_KWM_CURRENT_DESKTOP) {
1235 if (getSimpleHint(scr->root_win, _XA_KWM_CURRENT_DESKTOP, &value)) {
1236 #ifdef DEBUG1
1237 printf("got KDE workspace switch to %li\n", value);
1238 #endif
1239 if (value-1 != scr->current_workspace) {
1240 wWorkspaceChange(scr, value-1);
1243 } else if (event->atom == _XA_KWM_NUMBER_OF_DESKTOPS) {
1244 #ifdef DEBUG1
1245 printf("got KDE workspace number change\n");
1246 #endif
1248 if (getSimpleHint(scr->root_win, _XA_KWM_NUMBER_OF_DESKTOPS, &value)) {
1250 /* increasing is easy... */
1251 if (value > scr->workspace_count) {
1252 scr->flags.kwm_syncing_count = 1;
1254 wWorkspaceMake(scr, value - scr->workspace_count);
1256 scr->flags.kwm_syncing_count = 0;
1258 } else if (value < scr->workspace_count) {
1259 int i;
1260 Bool rebuild = False;
1262 scr->flags.kwm_syncing_count = 1;
1264 /* decrease all we can do */
1265 for (i = scr->workspace_count; i >= value; i--) {
1266 if (!wWorkspaceDelete(scr, i)) {
1267 rebuild = True;
1268 break;
1272 scr->flags.kwm_syncing_count = 0;
1274 /* someone destroyed a workspace that can't be destroyed.
1275 * Reset the hints to reflect our internal state.
1277 if (rebuild) {
1278 wKWMUpdateWorkspaceCountHint(scr);
1282 } else {
1283 int i;
1285 processed = False;
1287 for (i = 0; i < MAX_WORKSPACES; i++) {
1288 if (event->atom == _XA_KWM_DESKTOP_NAME_[i]) {
1289 char *name;
1291 name = wKWMGetWorkspaceName(scr, i);
1293 #ifdef DEBUG1
1294 printf("got KDE workspace name change to %s\n", name);
1295 #endif
1297 if (name && strncmp(name, scr->workspaces[i]->name,
1298 MAX_WORKSPACENAME_WIDTH)!=0) {
1299 scr->flags.kwm_syncing_name = 1;
1300 wWorkspaceRename(scr, i, name);
1301 scr->flags.kwm_syncing_name = 0;
1303 if (name)
1304 XFree(name);
1305 processed = True;
1306 break;
1307 } else if (event->atom == _XA_KWM_WINDOW_REGION_[i]) {
1308 WArea area;
1310 if (getAreaHint(scr->root_win, event->atom, &area)) {
1312 if (scr->totalUsableArea.x1 != area.x1
1313 || scr->totalUsableArea.y1 != area.y1
1314 || scr->totalUsableArea.x2 != area.x2
1315 || scr->totalUsableArea.y2 != area.y2) {
1316 wScreenUpdateUsableArea(scr);
1320 processed = True;
1321 break;
1326 return processed;
1330 Bool
1331 wKWMManageableClient(WScreen *scr, Window win, char *title)
1333 KWMDoNotManageList *ptr, *next;
1334 long val;
1336 if (getSimpleHint(win, _XA_KWM_DOCKWINDOW, &val) && val) {
1337 addDockWindow(scr, win);
1338 return False;
1341 ptr = KWMDoNotManageCrap;
1343 * TODO: support for glob patterns or regexes
1345 if (ptr && strncmp(ptr->title, title, strlen(ptr->title))==0) {
1346 next = ptr->next;
1347 free(ptr);
1348 KWMDoNotManageCrap = next;
1349 #ifdef DEBUG1
1350 printf("window %s not managed per KDE request\n", title);
1351 #endif
1353 sendToModules(scr, _XA_KWM_MODULE_WIN_ADD, NULL, win);
1354 sendToModules(scr, _XA_KWM_MODULE_WIN_REMOVE, NULL, win);
1356 return False;
1357 } else if (ptr) {
1358 while (ptr->next) {
1359 if (strncmp(ptr->next->title, title, strlen(ptr->next->title))==0) {
1360 #ifdef DEBUG1
1361 printf("window %s not managed per KDE request\n", title);
1362 #endif
1363 next = ptr->next->next;
1364 free(ptr->next);
1365 ptr->next = next;
1367 sendToModules(scr, _XA_KWM_MODULE_WIN_ADD, NULL, win);
1368 sendToModules(scr, _XA_KWM_MODULE_WIN_REMOVE, NULL, win);
1370 return False;
1373 ptr = ptr->next;
1377 return True;
1381 void
1382 wKWMUpdateCurrentWorkspaceHint(WScreen *scr)
1384 setSimpleHint(scr->root_win, _XA_KWM_CURRENT_DESKTOP,
1385 scr->current_workspace+1);
1387 sendToModules(scr, _XA_KWM_MODULE_DESKTOP_CHANGE, NULL,
1388 scr->current_workspace+1);
1392 void
1393 wKWMUpdateActiveWindowHint(WScreen *scr)
1395 long val;
1397 if (!scr->focused_window || !scr->focused_window->flags.focused)
1398 val = None;
1399 else
1400 val = (long)(scr->focused_window->client_win);
1402 XChangeProperty(dpy, scr->root_win, _XA_KWM_ACTIVE_WINDOW,
1403 _XA_KWM_ACTIVE_WINDOW, 32, PropModeReplace,
1404 (unsigned char*)&val, 1);
1405 XFlush(dpy);
1409 void
1410 wKWMUpdateWorkspaceCountHint(WScreen *scr)
1412 if (scr->flags.kwm_syncing_count)
1413 return;
1415 setSimpleHint(scr->root_win, _XA_KWM_NUMBER_OF_DESKTOPS,
1416 scr->workspace_count);
1418 sendToModules(scr, _XA_KWM_MODULE_DESKTOP_NUMBER_CHANGE, NULL,
1419 scr->workspace_count);
1423 void
1424 wKWMCheckDestroy(XDestroyWindowEvent *event)
1426 WScreen *scr;
1428 if (event->event == event->window) {
1429 return;
1432 scr = wScreenSearchForRootWindow(event->event);
1433 if (!scr) {
1434 return;
1437 removeModule(scr, event->window);
1438 removeDockWindow(scr, event->window);
1442 void
1443 wKWMUpdateWorkspaceNameHint(WScreen *scr, int workspace)
1445 char buffer[64];
1447 assert(workspace >= 0 && workspace < MAX_WORKSPACES);
1449 if (_XA_KWM_DESKTOP_NAME_[workspace]==0) {
1450 sprintf(buffer, "KWM_DESKTOP_NAME_%d", workspace + 1);
1452 _XA_KWM_DESKTOP_NAME_[workspace] = XInternAtom(dpy, buffer, False);
1455 XChangeProperty(dpy, scr->root_win, _XA_KWM_DESKTOP_NAME_[workspace],
1456 XA_STRING, 8, PropModeReplace,
1457 (unsigned char*)scr->workspaces[workspace]->name,
1458 strlen(scr->workspaces[workspace]->name)+1);
1460 sendToModules(scr, _XA_KWM_MODULE_DESKTOP_NAME_CHANGE, NULL, workspace+1);
1465 void
1466 wKWMUpdateClientWorkspace(WWindow *wwin)
1468 #ifdef DEBUG1
1469 printf("updating workspace of %s to %i\n",
1470 wwin->frame->title, wwin->frame->workspace+1);
1471 #endif
1472 setSimpleHint(wwin->client_win, _XA_KWM_WIN_DESKTOP,
1473 wwin->frame->workspace+1);
1477 void
1478 wKWMUpdateClientGeometryRestore(WWindow *wwin)
1480 WArea rect;
1482 rect.x1 = wwin->old_geometry.x;
1483 rect.y1 = wwin->old_geometry.y;
1484 rect.x2 = wwin->old_geometry.x + wwin->old_geometry.width;
1485 rect.y2 = wwin->old_geometry.y + wwin->old_geometry.height;
1487 setAreaHint(wwin->client_win, _XA_KWM_WIN_GEOMETRY_RESTORE, rect);
1491 void
1492 wKWMUpdateClientStateHint(WWindow *wwin, WKWMStateFlag flags)
1494 if (flags & KWMIconifiedFlag) {
1495 setSimpleHint(wwin->client_win, _XA_KWM_WIN_ICONIFIED,
1496 wwin->flags.miniaturized /*|| wwin->flags.shaded
1497 || wwin->flags.hidden*/);
1499 if (flags & KWMStickyFlag) {
1500 setSimpleHint(wwin->client_win, _XA_KWM_WIN_STICKY,
1501 IS_OMNIPRESENT(wwin));
1503 if (flags & KWMMaximizedFlag) {
1504 setSimpleHint(wwin->client_win, _XA_KWM_WIN_MAXIMIZED,
1505 wwin->flags.maximized!=0);
1510 Bool
1511 wKWMGetUsableArea(WScreen *scr, WArea *area)
1513 char buffer[64];
1515 if (_XA_KWM_WINDOW_REGION_[0]==0) {
1516 sprintf(buffer, "KWM_WINDOW_REGION_%d", 1);
1518 _XA_KWM_WINDOW_REGION_[0] = XInternAtom(dpy, buffer, False);
1521 return getAreaHint(scr->root_win, _XA_KWM_WINDOW_REGION_[0], area);
1526 Bool
1527 wKWMGetIconGeometry(WWindow *wwin, WArea *area)
1529 return getAreaHint(wwin->client_win, _XA_KWM_WIN_ICON_GEOMETRY, area);
1534 #ifdef not_used
1535 void
1536 wKWMSetUsableAreaHint(WScreen *scr, int workspace)
1538 /* if we set this after making changes of our own to the area,
1539 * the next time the area changes, we won't know what should
1540 * be the new final area. This protocol isn't worth a shit :/
1543 * According to Matthias Ettrich:
1544 * Indeed, there's no protocol to deal with the area yet in case several
1545 * clients want to influence it. It is sufficent, though, if it is clear
1546 * that one process is responsable for the area. For KDE this is kpanel, but
1547 * I see that there might be a conflict with the docking area of windowmaker
1548 * itself.
1552 #ifdef notdef
1553 char buffer[64];
1555 assert(workspace >= 0 && workspace < MAX_WORKSPACES);
1557 if (_XA_KWM_WINDOW_REGION_[workspace]==0) {
1558 sprintf(buffer, "KWM_WINDOW_REGION_%d", workspace+1);
1560 _XA_KWM_WINDOW_REGION_[workspace] = XInternAtom(dpy, buffer, False);
1563 setAreaHint(scr->root_win, _XA_KWM_WINDOW_REGION_[workspace],
1564 scr->totalUsableArea);
1565 #endif
1567 #endif /* not_used */
1569 void
1570 wKWMSendEventMessage(WWindow *wwin, WKWMEventMessage message)
1572 Atom msg;
1574 if (wwin && (wwin->flags.internal_window
1575 || wwin->flags.kwm_hidden_for_modules
1576 || !wwin->flags.kwm_managed
1577 || WFLAGP(wwin, skip_window_list)))
1578 return;
1580 switch (message) {
1581 case WKWMAddWindow:
1582 msg = _XA_KWM_MODULE_WIN_ADD;
1583 break;
1584 case WKWMRemoveWindow:
1585 msg = _XA_KWM_MODULE_WIN_REMOVE;
1586 break;
1587 case WKWMFocusWindow:
1588 msg = _XA_KWM_MODULE_WIN_ACTIVATE;
1589 break;
1590 case WKWMRaiseWindow:
1591 msg = _XA_KWM_MODULE_WIN_RAISE;
1592 break;
1593 case WKWMLowerWindow:
1594 msg = _XA_KWM_MODULE_WIN_LOWER;
1595 break;
1596 case WKWMChangedClient:
1597 msg = _XA_KWM_MODULE_WIN_CHANGE;
1598 break;
1599 case WKWMIconChange:
1600 msg = _XA_KWM_MODULE_WIN_ICON_CHANGE;
1601 break;
1602 default:
1603 return;
1606 sendToModules(wwin ? wwin->screen_ptr : NULL, msg, wwin, 0);
1610 #endif /* KWM_HINTS */