/* * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of the XFree86 Project * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * from the XFree86 Project. * * Authors: Earle F. Philhower, III */ /* $XFree86: $ */ #include #include #include #include "win.h" /* Fixups to prevent collisions between Windows and X headers */ #define ATOM DWORD #include #include #include "winprefs.h" #include "winmultiwindowclass.h" /* Where will the custom menu commands start counting from? */ #define STARTMENUID WM_USER /* External global variables */ #ifdef XWIN_MULTIWINDOW extern DWORD g_dwCurrentThreadID; #endif /* From winmultiwindowflex.l, the real parser */ extern void parse_file (FILE *fp); /* From winprefyacc.y, the pref structure loaded by the parser */ extern WINPREFS pref; /* The global X default icon */ extern HICON g_hIconX; extern HICON g_hSmallIconX; /* Currently in use command ID, incremented each new menu item created */ static int g_cmdid = STARTMENUID; /* Defined in DIX */ extern char *display; /* Local function to handle comma-ified icon names */ static HICON LoadImageComma (char *fname, int sx, int sy, int flags); /* * Creates or appends a menu from a MENUPARSED structure */ static HMENU MakeMenu (char *name, HMENU editMenu, int editItem) { int i; int item; MENUPARSED *m; HMENU hmenu, hsub; for (i=0; imenuItems; i++) { /* Only assign IDs one time... */ if ( m->menuItem[i].commandID == 0 ) m->menuItem[i].commandID = g_cmdid++; switch (m->menuItem[i].cmd) { case CMD_EXEC: case CMD_ALWAYSONTOP: case CMD_RELOAD: InsertMenu (hmenu, item, MF_BYPOSITION|MF_ENABLED|MF_STRING, m->menuItem[i].commandID, m->menuItem[i].text); break; case CMD_SEPARATOR: InsertMenu (hmenu, item, MF_BYPOSITION|MF_SEPARATOR, 0, NULL); break; case CMD_MENU: /* Recursive! */ hsub = MakeMenu (m->menuItem[i].param, 0, 0); if (hsub) InsertMenu (hmenu, item, MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING, (UINT_PTR)hsub, m->menuItem[i].text); break; } /* If item==-1 (means to add at end of menu) don't increment) */ if (item>=0) item++; } return hmenu; } #ifdef XWIN_MULTIWINDOW /* * Callback routine that is executed once per window class. * Removes or creates custom window settings depending on LPARAM */ static BOOL CALLBACK ReloadEnumWindowsProc (HWND hwnd, LPARAM lParam) { HICON hicon; Window wid; if (!hwnd) { ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n"); return FALSE; } /* It's our baby, either clean or dirty it */ if (lParam==FALSE) { hicon = (HICON)GetClassLong(hwnd, GCL_HICON); /* Unselect any icon in the class structure */ SetClassLong (hwnd, GCL_HICON, (LONG)LoadIcon (NULL, IDI_APPLICATION)); /* If it's generated on-the-fly, get rid of it, will regen */ winDestroyIcon (hicon); hicon = (HICON)GetClassLong(hwnd, GCL_HICONSM); /* Unselect any icon in the class structure */ SetClassLong (hwnd, GCL_HICONSM, 0); /* If it's generated on-the-fly, get rid of it, will regen */ winDestroyIcon (hicon); /* Remove any menu additions, use bRevert flag */ GetSystemMenu (hwnd, TRUE); /* This window is now clean of our taint */ } else { /* Make the icon default, dynamic, or from xwinrc */ SetClassLong (hwnd, GCL_HICON, (LONG)g_hIconX); SetClassLong (hwnd, GCL_HICONSM, (LONG)g_hSmallIconX); wid = (Window)GetProp (hwnd, WIN_WID_PROP); if (wid) winUpdateIcon (wid); /* Update the system menu for this window */ SetupSysMenu ((unsigned long)hwnd); /* That was easy... */ } return TRUE; } #endif /* * Removes any custom icons in classes, custom menus, etc. * Frees all members in pref structure. * Reloads the preferences file. * Set custom icons and menus again. */ static void ReloadPrefs (void) { int i; #ifdef XWIN_MULTIWINDOW /* First, iterate over all windows replacing their icon with system */ /* default one and deleting any custom system menus */ EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE); #endif /* Now, free/clear all info from our prefs structure */ for (i=0; imenuItems; j++) { if (command==m->menuItem[j].commandID) { /* Match! */ switch(m->menuItem[j].cmd) { case CMD_EXEC: if (fork()==0) { struct rlimit rl; unsigned long i; /* Close any open descriptors except for STD* */ getrlimit (RLIMIT_NOFILE, &rl); for (i = STDERR_FILENO+1; i < rl.rlim_cur; i++) close(i); /* Disassociate any TTYs */ setsid(); execl ("/bin/sh", "/bin/sh", "-c", m->menuItem[j].param, NULL); exit (0); } else return TRUE; break; case CMD_ALWAYSONTOP: if (!hwnd) return FALSE; /* Get extended window style */ dwExStyle = GetWindowLong (hwnd, GWL_EXSTYLE); /* Handle topmost windows */ if (dwExStyle & WS_EX_TOPMOST) SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); else SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); #if XWIN_MULTIWINDOW /* Reflect the changed Z order */ winReorderWindowsMultiWindow (); #endif return TRUE; case CMD_RELOAD: ReloadPrefs(); return TRUE; default: return FALSE; } } /* match */ } /* for j */ } /* for i */ return FALSE; } #ifdef XWIN_MULTIWINDOW /* * Add the default or a custom menu depending on the class match */ void SetupSysMenu (unsigned long hwndIn) { HWND hwnd; HMENU sys; int i; WindowPtr pWin; char *res_name, *res_class; hwnd = (HWND)hwndIn; if (!hwnd) return; pWin = GetProp (hwnd, WIN_WINDOW_PROP); sys = GetSystemMenu (hwnd, FALSE); if (!sys) return; if (pWin) { /* First see if there's a class match... */ if (winMultiWindowGetClassHint (pWin, &res_name, &res_class)) { for (i=0; i, */ *(strrchr (file, ',')) = 0; /* End string at comma */ index = atoi (strrchr (fname, ',') + 1); hicon = ExtractIcon (g_hInstance, file, index); } else { /* Just an .ico file... */ hicon = (HICON)LoadImage (NULL, file, IMAGE_ICON, sx, sy, LR_LOADFROMFILE|flags); } } return hicon; } /* * Check for a match of the window class to one specified in the * ICONS{} section in the prefs file, and load the icon from a file */ unsigned long winOverrideIcon (unsigned long longWin) { WindowPtr pWin = (WindowPtr) longWin; char *res_name, *res_class; int i; HICON hicon; char *wmName; if (pWin==NULL) return 0; /* If we can't find the class, we can't override from default! */ if (!winMultiWindowGetClassHint (pWin, &res_name, &res_class)) return 0; winMultiWindowGetWMName (pWin, &wmName); for (i=0; i