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
);
99 removeUserMenudata(void *menudata
){
100 WUserMenuData
*data
= menudata
;
101 if(data
->key
) free(data
->key
);
106 static WUserMenuData
*
107 convertShortcuts(WScreen
*scr
, proplist_t shortcut
){
113 int keycount
,i
,j
,mod
;
115 if (PLIsString(shortcut
)){
118 else if (PLIsArray(shortcut
)){
119 keycount
= PLGetNumberOfElements(shortcut
);
122 /*for (i=0;i<keycount;i++){*/
124 data
= wmalloc(sizeof(WUserMenuData
));
125 if (!data
) return NULL
;
126 data
->key
= wmalloc(sizeof(WShortKey
)*keycount
);
133 for (i
=0,j
=0;i
<keycount
;i
++) {
134 data
->key
[j
].modifier
= 0;
135 if (PLIsArray(shortcut
)) {
136 strcpy(buf
, PLGetString(PLGetArrayElement(shortcut
, i
)));
139 strcpy(buf
, PLGetString(shortcut
));
143 while ((k
= strchr(b
, '+'))!=NULL
) {
145 mod
= wXModifierFromKey(b
);
149 data
->key
[j
].modifier
|= mod
;
153 ksym
= XStringToKeysym(b
);
154 if (ksym
==NoSymbol
) {
158 data
->key
[j
].keycode
= XKeysymToKeycode(dpy
, ksym
);
159 if (data
->key
[j
].keycode
) {
180 configureUserMenu(WScreen
*scr
, proplist_t plum
){
183 proplist_t elem
, title
, command
, params
;
187 if (!plum
) return NULL
;
188 if (!PLIsArray(plum
)){
192 count
= PLGetNumberOfElements(plum
);
193 if (!count
) return NULL
;
195 elem
= PLGetArrayElement(plum
, 0);
196 if (!PLIsString(elem
)){
200 mtitle
= PLGetString(elem
);
202 menu
=wMenuCreateForApp(scr
, mtitle
, True
);
204 for(i
=1; i
<count
; i
++){
205 elem
= PLGetArrayElement(plum
,i
);
206 if(PLIsArray(PLGetArrayElement(elem
,1))){
210 submenu
= configureUserMenu(scr
,elem
);
212 mentry
= wMenuAddCallback(menu
, submenu
->frame
->title
,
214 wMenuEntrySetCascade(menu
, mentry
, submenu
);
218 proplist_t instances
=0;
220 title
= PLGetArrayElement(elem
,idx
++);
221 command
= PLGetArrayElement(elem
,idx
++);
222 if (PLGetNumberOfElements(elem
) >= 3)
223 params
= PLGetArrayElement(elem
,idx
++);
225 if (!title
|| !command
)
228 if (!strcmp("SHORTCUT",PLGetString(command
))){
231 data
= convertShortcuts(scr
, params
);
233 entry
= wMenuAddCallback(menu
, PLGetString(title
),
237 if (PLIsString(params
)) {
238 entry
->rtext
= GetShortcutString(PLGetString(params
));
240 entry
->free_cdata
= removeUserMenudata
;
242 if (PLGetNumberOfElements(elem
) >= 4){
243 instances
= PLGetArrayElement(elem
,idx
++);
244 if(PLIsArray(instances
))
245 if (instances
&& PLGetNumberOfElements(instances
)
246 && PLIsArray(instances
)){
247 entry
->instances
= PLRetain(instances
);
261 wUserMenuRefreshInstances(WMenu
*menu
, WWindow
*wwin
)
264 int i
,j
,count
,paintflag
;
270 for (i
=0; i
<menu
->entry_no
; i
++) {
271 if (menu
->entries
[i
]->instances
){
274 count
= PLGetNumberOfElements(menu
->entries
[i
]->instances
);
276 oldflag
= menu
->entries
[i
]->flags
.enabled
;
277 menu
->entries
[i
]->flags
.enabled
= 0;
278 for (j
=0; j
<count
;j
++){
279 ins
= PLGetArrayElement(menu
->entries
[i
]->instances
,j
);
280 if (!strcmp(wwin
->wm_instance
,PLGetString(ins
))){
281 menu
->entries
[i
]->flags
.enabled
= 1;
285 if (oldflag
!= menu
->entries
[i
]->flags
.enabled
)
289 for (i
=0; i
< menu
->cascade_no
; i
++) {
290 if (!menu
->cascades
[i
]->flags
.brother
)
291 wUserMenuRefreshInstances(menu
->cascades
[i
], wwin
);
293 wUserMenuRefreshInstances(menu
->cascades
[i
]->brother
, wwin
);
302 readUserMenuFile(WScreen
*scr
, char *file_name
)
306 proplist_t plum
, elem
, title
, command
, params
;
310 plum
= ReadProplistFromFile(file_name
);
314 menu
= configureUserMenu(scr
, plum
);
322 wUserMenuGet(WScreen
*scr
, WWindow
*wwin
){
325 char *prefix
, *menufile
;
327 prefix
= getenv("HOME");
330 /* this file/path code will be replaced :D - ]d */
331 menufile
= malloc(strlen(prefix
)+128);
332 if (!menufile
) return NULL
;
336 sprintf(menufile
, "%s/GNUstep/Library/WindowMaker/UserMenus/%s.%s.menu",
337 prefix
, wwin
->wm_instance
, wwin
->wm_class
);
338 f
= fopen(menufile
, "r");
341 menu
= readUserMenuFile(scr
, menufile
);
349 #endif /* USER_MENU */