1 /* usermenu.c- user defined menu
3 * Window Maker window manager
5 * Copyright (c) hmmm... Should I put everybody's name here?
6 * Where's my lawyer?? -- ]d :D
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
24 * User defined menu is good, but beer's always better
25 * if someone wanna start hacking something, He heard...
27 * - enhance commands. (eg, exit, hide, list all app's member
29 * - cache menu... dunno.. if people really use this feature :P
30 * - Violins, senseless violins!
31 * that's all, right now :P
32 * - external! WINGs menu editor.
34 * - allow applications to share their menu. ] think it
35 * looks wierd since there still are more than 1 appicon.
40 * ("Command 1", SHORTCUT, 1),
41 * ("Command 2", SHORTCUT, 2, ("Allowed_instant_1", "Allowed_instant_2")),
42 * ("Command 3", SHORTCUT, (3,4,5), ("Allowed_instant_1")),
45 * ("Kill Command", KILL),
46 * ("Hide Command", HIDE),
47 * ("Hide Others Command", HIDE_OTHERS),
48 * ("Members", MEMBERS),
49 * ("Exit Command", EXIT)
54 * - If you don't want short cut keys to be listed
55 * in the right side of entries, you can just put them
56 * in array instead of using the string directly.
65 #include <X11/Xutil.h>
66 #include <X11/Xproto.h>
67 #include <X11/Xatom.h>
73 #include "WindowMaker.h"
83 extern proplist_t
ReadProplistFromFile(char *file
);
85 extern WPreferences wPreferences
;
95 notifyClient(WMenu
*menu
, WMenuEntry
*entry
)
98 WUserMenuData
*data
= entry
->clientdata
;
99 WScreen
*scr
= data
->screen
;
103 window
=scr
->focused_window
->client_win
;
105 for(i
=0;i
<data
->key_no
;i
++) {
106 event
.xkey
.type
= KeyPress
;
107 event
.xkey
.display
= dpy
;
108 event
.xkey
.window
= window
;
109 event
.xkey
.root
= DefaultRootWindow(dpy
);
110 event
.xkey
.subwindow
= (Window
)None
;
113 event
.xkey
.x_root
= 0x0;
114 event
.xkey
.y_root
= 0x0;
115 event
.xkey
.keycode
= data
->key
[i
].keycode
;
116 event
.xkey
.state
= data
->key
[i
].modifier
;
117 event
.xkey
.same_screen
= True
;
118 event
.xkey
.time
= CurrentTime
;
119 if (XSendEvent(dpy
, window
, False
, KeyPressMask
, &event
)) {
120 event
.xkey
.type
= KeyRelease
;
121 event
.xkey
.time
= CurrentTime
;
122 XSendEvent(dpy
, window
, True
, KeyReleaseMask
, &event
);
128 removeUserMenudata(void *menudata
)
130 WUserMenuData
*data
= menudata
;
131 if(data
->key
) wfree(data
->key
);
136 static WUserMenuData
*
137 convertShortcuts(WScreen
*scr
, proplist_t shortcut
)
144 int keycount
,i
,j
,mod
;
146 if (PLIsString(shortcut
)) {
149 else if (PLIsArray(shortcut
)) {
150 keycount
= PLGetNumberOfElements(shortcut
);
153 /*for (i=0;i<keycount;i++){*/
155 data
= wmalloc(sizeof(WUserMenuData
));
156 if (!data
) return NULL
;
157 data
->key
= wmalloc(sizeof(WShortKey
)*keycount
);
164 for (i
=0,j
=0;i
<keycount
;i
++) {
165 data
->key
[j
].modifier
= 0;
166 if (PLIsArray(shortcut
)) {
167 strcpy(buf
, PLGetString(PLGetArrayElement(shortcut
, i
)));
169 strcpy(buf
, PLGetString(shortcut
));
173 while ((k
= strchr(b
, '+'))!=NULL
) {
175 mod
= wXModifierFromKey(b
);
179 data
->key
[j
].modifier
|= mod
;
183 ksym
= XStringToKeysym(b
);
184 if (ksym
==NoSymbol
) {
188 data
->key
[j
].keycode
= XKeysymToKeycode(dpy
, ksym
);
189 if (data
->key
[j
].keycode
) {
210 configureUserMenu(WScreen
*scr
, proplist_t plum
)
214 proplist_t elem
, title
, command
, params
;
218 if (!plum
) return NULL
;
219 if (!PLIsArray(plum
)) {
223 count
= PLGetNumberOfElements(plum
);
224 if (!count
) return NULL
;
226 elem
= PLGetArrayElement(plum
, 0);
227 if (!PLIsString(elem
)) {
231 mtitle
= PLGetString(elem
);
233 menu
=wMenuCreateForApp(scr
, mtitle
, True
);
235 for(i
=1; i
<count
; i
++) {
236 elem
= PLGetArrayElement(plum
,i
);
237 if(PLIsArray(PLGetArrayElement(elem
,1))) {
241 submenu
= configureUserMenu(scr
,elem
);
243 mentry
= wMenuAddCallback(menu
, submenu
->frame
->title
,
245 wMenuEntrySetCascade(menu
, mentry
, submenu
);
249 proplist_t instances
=0;
251 title
= PLGetArrayElement(elem
,idx
++);
252 command
= PLGetArrayElement(elem
,idx
++);
253 if (PLGetNumberOfElements(elem
) >= 3)
254 params
= PLGetArrayElement(elem
,idx
++);
256 if (!title
|| !command
)
259 if (!strcmp("SHORTCUT",PLGetString(command
))) {
262 data
= convertShortcuts(scr
, params
);
264 entry
= wMenuAddCallback(menu
, PLGetString(title
),
268 if (PLIsString(params
)) {
269 entry
->rtext
= GetShortcutString(PLGetString(params
));
271 entry
->free_cdata
= removeUserMenudata
;
273 if (PLGetNumberOfElements(elem
) >= 4) {
274 instances
= PLGetArrayElement(elem
,idx
++);
275 if(PLIsArray(instances
))
276 if (instances
&& PLGetNumberOfElements(instances
)
277 && PLIsArray(instances
)){
278 entry
->instances
= PLRetain(instances
);
292 wUserMenuRefreshInstances(WMenu
*menu
, WWindow
*wwin
)
295 int i
,j
,count
,paintflag
;
301 for (i
=0; i
<menu
->entry_no
; i
++) {
302 if (menu
->entries
[i
]->instances
){
305 count
= PLGetNumberOfElements(menu
->entries
[i
]->instances
);
307 oldflag
= menu
->entries
[i
]->flags
.enabled
;
308 menu
->entries
[i
]->flags
.enabled
= 0;
309 for (j
=0; j
<count
;j
++) {
310 ins
= PLGetArrayElement(menu
->entries
[i
]->instances
,j
);
311 if (!strcmp(wwin
->wm_instance
,PLGetString(ins
))) {
312 menu
->entries
[i
]->flags
.enabled
= 1;
316 if (oldflag
!= menu
->entries
[i
]->flags
.enabled
)
320 for (i
=0; i
< menu
->cascade_no
; i
++) {
321 if (!menu
->cascades
[i
]->flags
.brother
)
322 wUserMenuRefreshInstances(menu
->cascades
[i
], wwin
);
324 wUserMenuRefreshInstances(menu
->cascades
[i
]->brother
, wwin
);
333 readUserMenuFile(WScreen
*scr
, char *file_name
)
337 proplist_t plum
, elem
, title
, command
, params
;
341 plum
= ReadProplistFromFile(file_name
);
345 menu
= configureUserMenu(scr
, plum
);
353 wUserMenuGet(WScreen
*scr
, WWindow
*wwin
)
359 if ( wwin
->wm_instance
&& wwin
->wm_class
) {
360 tmp
=wmalloc(strlen(wwin
->wm_instance
)+strlen(wwin
->wm_class
)+7);
361 sprintf(tmp
,"%s.%s.menu",wwin
->wm_instance
,wwin
->wm_class
);
362 path
= wfindfile(DEF_USER_MENU_PATHS
,tmp
);
365 if (!path
) return NULL
;
368 menu
= readUserMenuFile(scr
, path
);
376 #endif /* USER_MENU */