2 /* User defined menu is good, but beer's always better
3 * if someone wanna start hacking something, He heard...
5 * - enhance commands. (eg, exit, hide, list all app's member
7 * - cache menu... dunno.. if people really use this feature :P
8 * - Violins, senseless violins!
9 * that's all, right now :P
10 * - external! WINGs menu editor.
12 * - allow applications to share their menu. ] think it
13 * looks wierd since there still are more than 1 appicon.
18 * ("Command 1", SHORTCUT, 1),
19 * ("Command 2", SHORTCUT, 2, ("Allowed_instant_1", "Allowed_instant_2")),
20 * ("Command 3", SHORTCUT, (3,4,5), ("Allowed_instant_1")),
23 * ("Kill Command", KILL),
24 * ("Hide Command", HIDE),
25 * ("Hide Others Command", HIDE_OTHERS),
26 * ("Members", MEMBERS),
27 * ("Exit Command", EXIT)
32 * - If you don't want short cut keys to be listed
33 * in the right side of entries, you can just put them
34 * in array instead of using the string directly.
41 #include <X11/Xutil.h>
42 #include <X11/Xproto.h>
43 #include <X11/Xatom.h>
49 #include "WindowMaker.h"
59 extern proplist_t
ReadProplistFromFile(char *file
);
61 extern WPreferences wPreferences
;
71 notifyClient(WMenu
*menu
, WMenuEntry
*entry
){
73 WUserMenuData
*data
= entry
->clientdata
;
74 WScreen
*scr
= data
->screen
;
78 window
=scr
->focused_window
->client_win
;
80 for(i
=0;i
<data
->key_no
;i
++){
81 event
.xkey
.type
= KeyPress
;
82 event
.xkey
.display
= dpy
;
83 event
.xkey
.window
= window
;
84 event
.xkey
.subwindow
= 0x0;
87 event
.xkey
.x_root
= 0x0;
88 event
.xkey
.y_root
= 0x0;
89 event
.xkey
.keycode
= data
->key
[i
].keycode
;
90 event
.xkey
.state
= data
->key
[i
].modifier
;
91 event
.xkey
.same_screen
= YES
;
92 XSendEvent(dpy
, window
, False
, NoEventMask
, &event
);
94 /* should i release key too? */
99 removeUserMenudata(void *menudata
){
100 WUserMenuData
*data
= menudata
;
105 static WUserMenuData
*
106 convertShortcut(WScreen
*scr
, proplist_t shortcut
){
112 data
= malloc(sizeof(WUserMenuData
));
113 data
->key
= malloc(sizeof(WUserMenuData
));
114 data
->key
[0].modifier
= 0;
116 strcpy(buf
, PLGetString(shortcut
));
120 while ((k
= strchr(b
, '+'))!=NULL
) {
124 mod
= wXModifierFromKey(b
);
129 data
->key
[0].modifier
|= mod
;
135 ksym
= XStringToKeysym(b
);
137 if (ksym
==NoSymbol
) {
142 data
->key
[0].keycode
= XKeysymToKeycode(dpy
, ksym
);
143 if (data
->key
[0].keycode
==0) {
153 static WUserMenuData
*
154 convertShortcuts(WScreen
*scr
, proplist_t shortcut
){
160 int keycount
,i
,j
,mod
;
162 if (PLIsString(shortcut
)){
165 else if (PLIsArray(shortcut
)){
166 keycount
= PLGetNumberOfElements(shortcut
);
169 /*for (i=0;i<keycount;i++){*/
171 data
= malloc(sizeof(WUserMenuData
));
172 data
->key
= malloc(sizeof(WShortKey
)*keycount
);
174 for (i
=0,j
=0;i
<keycount
;i
++) {
175 data
->key
[j
].modifier
= 0;
176 if (PLIsArray(shortcut
)) {
177 strcpy(buf
, PLGetString(PLGetArrayElement(shortcut
, i
)));
180 strcpy(buf
, PLGetString(shortcut
));
184 while ((k
= strchr(b
, '+'))!=NULL
) {
186 mod
= wXModifierFromKey(b
);
190 data
->key
[j
].modifier
|= mod
;
197 ksym
= XStringToKeysym(b
);
198 if (ksym
==NoSymbol
) {
202 data
->key
[j
].keycode
= XKeysymToKeycode(dpy
, ksym
);
203 if (data
->key
[j
].keycode
) {
222 configureUserMenu(WScreen
*scr
, proplist_t plum
){
225 proplist_t elem
, title
, command
, params
;
229 if (!plum
) return NULL
;
230 else if (!PLIsArray(plum
)){
235 count
= PLGetNumberOfElements(plum
);
236 if (!count
) return NULL
;
238 elem
= PLGetArrayElement(plum
, 0);
239 if (!PLIsString(elem
)){
243 mtitle
= PLGetString(elem
);
245 menu
=wMenuCreateForApp(scr
, mtitle
, True
);
247 for(i
=1; i
<count
; i
++){
248 elem
= PLGetArrayElement(plum
,i
);
249 if(PLIsArray(PLGetArrayElement(elem
,1))){
253 submenu
= configureUserMenu(scr
,elem
);
255 mentry
= wMenuAddCallback(menu
, submenu
->frame
->title
,NULL
,NULL
);
256 wMenuEntrySetCascade(menu
, mentry
, submenu
);
260 proplist_t instances
=0;
262 title
= PLGetArrayElement(elem
,idx
++);
263 command
= PLGetArrayElement(elem
,idx
++);
264 if (PLGetNumberOfElements(elem
) >= 3)
265 params
= PLGetArrayElement(elem
,idx
++);
267 if (!title
|| !command
)
270 if (!strcmp("SHORTCUT",PLGetString(command
))){
272 data
= convertShortcuts(scr
, params
);
274 entry
= wMenuAddCallback(menu
, PLGetString(title
),
276 if (PLIsString(params
)) {
277 entry
->rtext
= GetShortcutString(PLGetString(params
));
280 entry
->free_cdata
= removeUserMenudata
;
282 if (PLGetNumberOfElements(elem
) >= 4){
283 instances
= PLGetArrayElement(elem
,idx
++);
284 if(PLIsArray(instances
))
285 if (instances
&& PLGetNumberOfElements(instances
)
286 && PLIsArray(instances
)){
287 entry
->instances
= PLRetain(instances
);
301 wUserMenuRefreshInstances(WMenu
*menu
, WWindow
*wwin
)
304 int i
,j
,count
,paintflag
;
310 for (i
=0; i
<menu
->entry_no
; i
++) {
311 if (menu
->entries
[i
]->instances
){
314 count
= PLGetNumberOfElements(menu
->entries
[i
]->instances
);
316 oldflag
= menu
->entries
[i
]->flags
.enabled
;
317 menu
->entries
[i
]->flags
.enabled
= 0;
318 for (j
=0; j
<count
;j
++){
319 ins
= PLGetArrayElement(menu
->entries
[i
]->instances
,j
);
320 if (!strcmp(wwin
->wm_instance
,PLGetString(ins
))){
321 menu
->entries
[i
]->flags
.enabled
= 1;
325 if (oldflag
!= menu
->entries
[i
]->flags
.enabled
)
329 for (i
=0; i
< menu
->cascade_no
; i
++) {
330 if (!menu
->cascades
[i
]->flags
.brother
)
331 wUserMenuRefreshInstances(menu
->cascades
[i
], wwin
);
333 wUserMenuRefreshInstances(menu
->cascades
[i
]->brother
, wwin
);
342 readUserMenuFile(WScreen
*scr
, char *file_name
)
347 proplist_t plum
, elem
, title
, command
, params
;
351 plum
= ReadProplistFromFile(file_name
);
355 menu
= configureUserMenu(scr
, plum
);
363 wUserMenuGet(WScreen
*scr
, WWindow
*wwin
){
366 char *prefix
, *menufile
;
368 prefix
= getenv("HOME");
371 menufile
= malloc(strlen(prefix
)+64);
372 if (!menufile
) return NULL
;
376 sprintf(menufile
, "%s/%s.%s.menu",
377 prefix
, wwin
->wm_instance
, wwin
->wm_class
);
378 f
= fopen(menufile
, "r");
381 menu
= readUserMenuFile(scr
, menufile
);
389 #endif /* USER_MENU */