1 /* User defined menu is good, but beer's always better
2 * if someone wanna start hacking something, He heard...
4 * - enhance commands. (eg, exit, hide, list all app's member
6 * - cache menu... dunno.. if people really use this feature :P
7 * - Violins, senseless violins!
8 * that's all, right now :P
9 * - external! WINGs menu editor.
11 * - allow applications to share their menu. ] think it
12 * looks wierd since there still are more than 1 appicon.
17 * ("Command 1", SHORTCUT, 1),
18 * ("Command 2", SHORTCUT, 2, ("Allowed_instant_1", "Allowed_instant_2")),
19 * ("Command 3", SHORTCUT, (3,4,5), ("Allowed_instant_1")),
22 * ("Kill Command", KILL),
23 * ("Hide Command", HIDE),
24 * ("Hide Others Command", HIDE_OTHERS),
25 * ("Members", MEMBERS),
26 * ("Exit Command", EXIT)
31 * - If you don't want short cut keys to be listed
32 * in the right side of entries, you can just put them
33 * in array instead of using the string directly.
42 #include <X11/Xutil.h>
43 #include <X11/Xproto.h>
44 #include <X11/Xatom.h>
50 #include "WindowMaker.h"
60 extern proplist_t
ReadProplistFromFile(char *file
);
62 extern WPreferences wPreferences
;
72 notifyClient(WMenu
*menu
, WMenuEntry
*entry
){
74 WUserMenuData
*data
= entry
->clientdata
;
75 WScreen
*scr
= data
->screen
;
79 window
=scr
->focused_window
->client_win
;
81 for(i
=0;i
<data
->key_no
;i
++){
82 event
.xkey
.type
= KeyPress
;
83 event
.xkey
.display
= dpy
;
84 event
.xkey
.window
= window
;
85 event
.xkey
.subwindow
= 0x0;
88 event
.xkey
.x_root
= 0x0;
89 event
.xkey
.y_root
= 0x0;
90 event
.xkey
.keycode
= data
->key
[i
].keycode
;
91 event
.xkey
.state
= data
->key
[i
].modifier
;
92 event
.xkey
.same_screen
= YES
;
93 XSendEvent(dpy
, window
, False
, NoEventMask
, &event
);
95 /* should i release key too? */
100 removeUserMenudata(void *menudata
){
101 WUserMenuData
*data
= menudata
;
106 static WUserMenuData
*
107 convertShortcut(WScreen
*scr
, proplist_t shortcut
){
113 data
= malloc(sizeof(WUserMenuData
));
114 data
->key
= malloc(sizeof(WUserMenuData
));
115 data
->key
[0].modifier
= 0;
117 strcpy(buf
, PLGetString(shortcut
));
121 while ((k
= strchr(b
, '+'))!=NULL
) {
125 mod
= wXModifierFromKey(b
);
130 data
->key
[0].modifier
|= mod
;
136 ksym
= XStringToKeysym(b
);
138 if (ksym
==NoSymbol
) {
143 data
->key
[0].keycode
= XKeysymToKeycode(dpy
, ksym
);
144 if (data
->key
[0].keycode
==0) {
154 static WUserMenuData
*
155 convertShortcuts(WScreen
*scr
, proplist_t shortcut
){
161 int keycount
,i
,j
,mod
;
163 if (PLIsString(shortcut
)){
166 else if (PLIsArray(shortcut
)){
167 keycount
= PLGetNumberOfElements(shortcut
);
170 /*for (i=0;i<keycount;i++){*/
172 data
= malloc(sizeof(WUserMenuData
));
173 data
->key
= malloc(sizeof(WShortKey
)*keycount
);
175 for (i
=0,j
=0;i
<keycount
;i
++) {
176 data
->key
[j
].modifier
= 0;
177 if (PLIsArray(shortcut
)) {
178 strcpy(buf
, PLGetString(PLGetArrayElement(shortcut
, i
)));
181 strcpy(buf
, PLGetString(shortcut
));
185 while ((k
= strchr(b
, '+'))!=NULL
) {
187 mod
= wXModifierFromKey(b
);
191 data
->key
[j
].modifier
|= mod
;
198 ksym
= XStringToKeysym(b
);
199 if (ksym
==NoSymbol
) {
203 data
->key
[j
].keycode
= XKeysymToKeycode(dpy
, ksym
);
204 if (data
->key
[j
].keycode
) {
223 configureUserMenu(WScreen
*scr
, proplist_t plum
){
226 proplist_t elem
, title
, command
, params
;
230 if (!plum
) return NULL
;
231 else if (!PLIsArray(plum
)){
236 count
= PLGetNumberOfElements(plum
);
237 if (!count
) return NULL
;
239 elem
= PLGetArrayElement(plum
, 0);
240 if (!PLIsString(elem
)){
244 mtitle
= PLGetString(elem
);
246 menu
=wMenuCreateForApp(scr
, mtitle
, True
);
248 for(i
=1; i
<count
; i
++){
249 elem
= PLGetArrayElement(plum
,i
);
250 if(PLIsArray(PLGetArrayElement(elem
,1))){
254 submenu
= configureUserMenu(scr
,elem
);
256 mentry
= wMenuAddCallback(menu
, submenu
->frame
->title
,NULL
,NULL
);
257 wMenuEntrySetCascade(menu
, mentry
, submenu
);
261 proplist_t instances
=0;
263 title
= PLGetArrayElement(elem
,idx
++);
264 command
= PLGetArrayElement(elem
,idx
++);
265 if (PLGetNumberOfElements(elem
) >= 3)
266 params
= PLGetArrayElement(elem
,idx
++);
268 if (!title
|| !command
)
271 if (!strcmp("SHORTCUT",PLGetString(command
))){
273 data
= convertShortcuts(scr
, params
);
275 entry
= wMenuAddCallback(menu
, PLGetString(title
),
277 if (PLIsString(params
)) {
278 entry
->rtext
= GetShortcutString(PLGetString(params
));
281 entry
->free_cdata
= removeUserMenudata
;
283 if (PLGetNumberOfElements(elem
) >= 4){
284 instances
= PLGetArrayElement(elem
,idx
++);
285 if(PLIsArray(instances
))
286 if (instances
&& PLGetNumberOfElements(instances
)
287 && PLIsArray(instances
)){
288 entry
->instances
= PLRetain(instances
);
302 wUserMenuRefreshInstances(WMenu
*menu
, WWindow
*wwin
)
305 int i
,j
,count
,paintflag
;
311 for (i
=0; i
<menu
->entry_no
; i
++) {
312 if (menu
->entries
[i
]->instances
){
315 count
= PLGetNumberOfElements(menu
->entries
[i
]->instances
);
317 oldflag
= menu
->entries
[i
]->flags
.enabled
;
318 menu
->entries
[i
]->flags
.enabled
= 0;
319 for (j
=0; j
<count
;j
++){
320 ins
= PLGetArrayElement(menu
->entries
[i
]->instances
,j
);
321 if (!strcmp(wwin
->wm_instance
,PLGetString(ins
))){
322 menu
->entries
[i
]->flags
.enabled
= 1;
326 if (oldflag
!= menu
->entries
[i
]->flags
.enabled
)
330 for (i
=0; i
< menu
->cascade_no
; i
++) {
331 if (!menu
->cascades
[i
]->flags
.brother
)
332 wUserMenuRefreshInstances(menu
->cascades
[i
], wwin
);
334 wUserMenuRefreshInstances(menu
->cascades
[i
]->brother
, wwin
);
343 readUserMenuFile(WScreen
*scr
, char *file_name
)
348 proplist_t plum
, elem
, title
, command
, params
;
352 plum
= ReadProplistFromFile(file_name
);
356 menu
= configureUserMenu(scr
, plum
);
364 wUserMenuGet(WScreen
*scr
, WWindow
*wwin
){
367 char *prefix
, *menufile
;
369 prefix
= getenv("HOME");
372 menufile
= malloc(strlen(prefix
)+64);
373 if (!menufile
) return NULL
;
377 sprintf(menufile
, "%s/%s.%s.menu",
378 prefix
, wwin
->wm_instance
, wwin
->wm_class
);
379 f
= fopen(menufile
, "r");
382 menu
= readUserMenuFile(scr
, menufile
);
390 #endif /* USER_MENU */