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
)
75 WUserMenuData
*data
= entry
->clientdata
;
76 WScreen
*scr
= data
->screen
;
80 window
=scr
->focused_window
->client_win
;
82 for(i
=0;i
<data
->key_no
;i
++) {
83 event
.xkey
.type
= KeyPress
;
84 event
.xkey
.display
= dpy
;
85 event
.xkey
.window
= window
;
86 event
.xkey
.subwindow
= 0x0;
89 event
.xkey
.x_root
= 0x0;
90 event
.xkey
.y_root
= 0x0;
91 event
.xkey
.keycode
= data
->key
[i
].keycode
;
92 event
.xkey
.state
= data
->key
[i
].modifier
;
93 event
.xkey
.same_screen
= YES
;
94 XSendEvent(dpy
, window
, False
, NoEventMask
, &event
);
96 event
.xkey
.type
= KeyRelease
;
97 XSendEvent(dpy
, window
, False
, NoEventMask
, &event
);
103 removeUserMenudata(void *menudata
)
105 WUserMenuData
*data
= menudata
;
106 if(data
->key
) free(data
->key
);
111 static WUserMenuData
*
112 convertShortcuts(WScreen
*scr
, proplist_t shortcut
)
119 int keycount
,i
,j
,mod
;
121 if (PLIsString(shortcut
)) {
124 else if (PLIsArray(shortcut
)) {
125 keycount
= PLGetNumberOfElements(shortcut
);
128 /*for (i=0;i<keycount;i++){*/
130 data
= wmalloc(sizeof(WUserMenuData
));
131 if (!data
) return NULL
;
132 data
->key
= wmalloc(sizeof(WShortKey
)*keycount
);
139 for (i
=0,j
=0;i
<keycount
;i
++) {
140 data
->key
[j
].modifier
= 0;
141 if (PLIsArray(shortcut
)) {
142 strcpy(buf
, PLGetString(PLGetArrayElement(shortcut
, i
)));
144 strcpy(buf
, PLGetString(shortcut
));
148 while ((k
= strchr(b
, '+'))!=NULL
) {
150 mod
= wXModifierFromKey(b
);
154 data
->key
[j
].modifier
|= mod
;
158 ksym
= XStringToKeysym(b
);
159 if (ksym
==NoSymbol
) {
163 data
->key
[j
].keycode
= XKeysymToKeycode(dpy
, ksym
);
164 if (data
->key
[j
].keycode
) {
185 configureUserMenu(WScreen
*scr
, proplist_t plum
)
189 proplist_t elem
, title
, command
, params
;
193 if (!plum
) return NULL
;
194 if (!PLIsArray(plum
)) {
198 count
= PLGetNumberOfElements(plum
);
199 if (!count
) return NULL
;
201 elem
= PLGetArrayElement(plum
, 0);
202 if (!PLIsString(elem
)) {
206 mtitle
= PLGetString(elem
);
208 menu
=wMenuCreateForApp(scr
, mtitle
, True
);
210 for(i
=1; i
<count
; i
++) {
211 elem
= PLGetArrayElement(plum
,i
);
212 if(PLIsArray(PLGetArrayElement(elem
,1))) {
216 submenu
= configureUserMenu(scr
,elem
);
218 mentry
= wMenuAddCallback(menu
, submenu
->frame
->title
,
220 wMenuEntrySetCascade(menu
, mentry
, submenu
);
224 proplist_t instances
=0;
226 title
= PLGetArrayElement(elem
,idx
++);
227 command
= PLGetArrayElement(elem
,idx
++);
228 if (PLGetNumberOfElements(elem
) >= 3)
229 params
= PLGetArrayElement(elem
,idx
++);
231 if (!title
|| !command
)
234 if (!strcmp("SHORTCUT",PLGetString(command
))) {
237 data
= convertShortcuts(scr
, params
);
239 entry
= wMenuAddCallback(menu
, PLGetString(title
),
243 if (PLIsString(params
)) {
244 entry
->rtext
= GetShortcutString(PLGetString(params
));
246 entry
->free_cdata
= removeUserMenudata
;
248 if (PLGetNumberOfElements(elem
) >= 4) {
249 instances
= PLGetArrayElement(elem
,idx
++);
250 if(PLIsArray(instances
))
251 if (instances
&& PLGetNumberOfElements(instances
)
252 && PLIsArray(instances
)){
253 entry
->instances
= PLRetain(instances
);
267 wUserMenuRefreshInstances(WMenu
*menu
, WWindow
*wwin
)
270 int i
,j
,count
,paintflag
;
276 for (i
=0; i
<menu
->entry_no
; i
++) {
277 if (menu
->entries
[i
]->instances
){
280 count
= PLGetNumberOfElements(menu
->entries
[i
]->instances
);
282 oldflag
= menu
->entries
[i
]->flags
.enabled
;
283 menu
->entries
[i
]->flags
.enabled
= 0;
284 for (j
=0; j
<count
;j
++) {
285 ins
= PLGetArrayElement(menu
->entries
[i
]->instances
,j
);
286 if (!strcmp(wwin
->wm_instance
,PLGetString(ins
))) {
287 menu
->entries
[i
]->flags
.enabled
= 1;
291 if (oldflag
!= menu
->entries
[i
]->flags
.enabled
)
295 for (i
=0; i
< menu
->cascade_no
; i
++) {
296 if (!menu
->cascades
[i
]->flags
.brother
)
297 wUserMenuRefreshInstances(menu
->cascades
[i
], wwin
);
299 wUserMenuRefreshInstances(menu
->cascades
[i
]->brother
, wwin
);
308 readUserMenuFile(WScreen
*scr
, char *file_name
)
312 proplist_t plum
, elem
, title
, command
, params
;
316 plum
= ReadProplistFromFile(file_name
);
320 menu
= configureUserMenu(scr
, plum
);
328 wUserMenuGet(WScreen
*scr
, WWindow
*wwin
)
335 tmp
=wmalloc(strlen(wwin
->wm_instance
)+strlen(wwin
->wm_class
)+7);
336 sprintf(tmp
,"%s.%s.menu",wwin
->wm_instance
,wwin
->wm_class
);
337 path
= wfindfile(DEF_USER_MENU_PATHS
,tmp
);
340 if (!path
) return NULL
;
343 menu
= readUserMenuFile(scr
, path
);
350 #endif /* USER_MENU */