├── autogen.sh ├── po ├── LINGUAS ├── quot.sed ├── boldquot.sed ├── remove-potcdate.sin ├── insert-header.sin ├── POTFILES.in ├── en@quot.header ├── en@boldquot.header └── Makevars ├── contrib ├── CREDITS ├── jwm-blue.svg ├── jwm-gray.svg ├── jwm-orange.svg ├── jwm-red.svg ├── Makefile.in └── jwm.xbm ├── doc-footer.shtml ├── .gitignore ├── src ├── grab.h ├── default.h ├── help.h ├── spacer.h ├── match.h ├── outline.h ├── grab.c ├── parse.h ├── pager.h ├── match.c ├── move.h ├── background.h ├── resize.h ├── confirm.h ├── gradient.h ├── popup.h ├── error.h ├── winmenu.h ├── main.h ├── status.h ├── Makefile.in ├── clock.h ├── render.h ├── outline.c ├── command.h ├── timing.h ├── swallow.h ├── screen.h ├── clientlist.h ├── dock.h ├── traybutton.h ├── taskbar.h ├── image.h ├── button.h ├── root.h ├── spacer.c ├── font.h ├── default.c ├── event.h ├── desktop.h ├── help.c ├── binding.h ├── cursor.h ├── gradient.c ├── misc.h ├── timing.c ├── error.c ├── place.h ├── debug.h ├── border.h ├── screen.c ├── action.h ├── lex.h ├── jwm.h ├── icon.h ├── color.h ├── settings.c ├── settings.h ├── menu.h ├── group.h ├── status.c ├── action.c ├── render.c ├── command.c ├── cursor.c ├── root.c ├── misc.c ├── clientlist.c ├── button.c └── popup.c ├── doc-header.shtml ├── LICENSE ├── README.md ├── Makefile.in ├── README.upgrading ├── CONTRIBUTING.md └── xslt ├── jwm-2.4.xslt └── jwm-2.3.xslt /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | aclocal 3 | automake -ac 4 | autoreconf -fi 5 | touch config.rpath 6 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | da 2 | de 3 | es 4 | fr 5 | hu 6 | it 7 | lt 8 | nl 9 | pl 10 | pt 11 | pt_BR 12 | ru 13 | zh_CN 14 | zh_TW 15 | -------------------------------------------------------------------------------- /po/quot.sed: -------------------------------------------------------------------------------- 1 | s/"\([^"]*\)"/“\1”/g 2 | s/`\([^`']*\)'/‘\1’/g 3 | s/ '\([^`']*\)' / ‘\1’ /g 4 | s/ '\([^`']*\)'$/ ‘\1’/g 5 | s/^'\([^`']*\)' /‘\1’ /g 6 | s/“”/""/g 7 | -------------------------------------------------------------------------------- /contrib/CREDITS: -------------------------------------------------------------------------------- 1 | Original logo design: Vitor Lopes (@vmnlopes) 2 | Original SVG logo: Israel (@Israel-) 3 | Minified SVG logo: @technosaurus 4 | XBM logo: Mick Amadio (@01micko) 5 | -------------------------------------------------------------------------------- /po/boldquot.sed: -------------------------------------------------------------------------------- 1 | s/"\([^"]*\)"/“\1”/g 2 | s/`\([^`']*\)'/‘\1’/g 3 | s/ '\([^`']*\)' / ‘\1’ /g 4 | s/ '\([^`']*\)'$/ ‘\1’/g 5 | s/^'\([^`']*\)' /‘\1’ /g 6 | s/“”/""/g 7 | s/“/“/g 8 | s/”/”/g 9 | s/‘/‘/g 10 | s/’/’/g 11 | -------------------------------------------------------------------------------- /doc-footer.shtml: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | joewing.net / 5 | Projects / 6 | JWM 7 |

8 | 9 | 10 | -------------------------------------------------------------------------------- /contrib/jwm-blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /contrib/jwm-gray.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /contrib/jwm-orange.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /contrib/jwm-red.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | Makefile 3 | autom4te.cache 4 | config.guess 5 | config.h 6 | config.h.in 7 | config.h.in~ 8 | config.log 9 | config.status 10 | config.sub 11 | config.rpath 12 | configure 13 | jwm.1 14 | po/Makefile 15 | po/Makefile.in 16 | po/POTFILES 17 | po/*.gmo 18 | po/stamp-* 19 | src/Makefile 20 | src/jwm 21 | doc 22 | -------------------------------------------------------------------------------- /contrib/Makefile.in: -------------------------------------------------------------------------------- 1 | ICONDIR = $(DESTDIR)@DATADIR@/jwm 2 | 3 | ICONS = jwm.xbm jwm-gray.svg jwm-blue.svg jwm-orange.svg jwm-red.svg 4 | 5 | install: 6 | install -d $(ICONDIR) 7 | for f in $(ICONS) ; do \ 8 | install -m 0644 $$f $(ICONDIR)/$$f ; \ 9 | done 10 | 11 | uninstall: 12 | for f in $(ICONS) ; do \ 13 | rm -f $(ICONDIR)/$$f ; \ 14 | done 15 | -------------------------------------------------------------------------------- /src/grab.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file grab.h 3 | * @author Joe Wingbermuehle 4 | * @date 2013 5 | * 6 | * @brief Header file for managing server grabs. 7 | * 8 | */ 9 | 10 | #ifndef GRAB_H 11 | #define GRAB_H 12 | 13 | /** Grab the server and sync. */ 14 | void GrabServer(void); 15 | 16 | /** Ungrab the server. */ 17 | void UngrabServer(void); 18 | 19 | #endif /* GRAB_H */ 20 | 21 | -------------------------------------------------------------------------------- /src/default.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file default.h 3 | * @author Joe Wingbermuehle 4 | * @date 2017 5 | * 6 | * @brief Default configuration. 7 | * 8 | */ 9 | 10 | #ifndef DEFAULT_H 11 | #define DEFAULT_H 12 | 13 | /** Base configuration that is always included first. */ 14 | extern const char * const BASE_CONFIG; 15 | 16 | /** A default configuration that is included if no configuration is found. */ 17 | extern const char * const DEFAULT_CONFIG; 18 | 19 | #endif /* DEFAULT_H */ 20 | -------------------------------------------------------------------------------- /src/help.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file help.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the help functions. 7 | * 8 | */ 9 | 10 | #ifndef HELP_H 11 | #define HELP_H 12 | 13 | /** Display program name, version, and compiled options . */ 14 | void DisplayAbout(void); 15 | 16 | /** Display compiled options. */ 17 | void DisplayCompileOptions(void); 18 | 19 | /** Display all help. */ 20 | void DisplayHelp(void); 21 | 22 | #endif /* HELP_H */ 23 | 24 | -------------------------------------------------------------------------------- /src/spacer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file spacer.h 3 | * @author Joe Wingbermuehle 4 | * @date 2011 5 | * 6 | * @brief Spacer tray component. 7 | * 8 | */ 9 | #ifndef SPACER_H 10 | #define SPACER_H 11 | 12 | struct TrayComponentType; 13 | 14 | /** Create a spacer tray component. 15 | * @param width Minimum width. 16 | * @param height Minimum height. 17 | * @return A new spacer tray component. 18 | */ 19 | struct TrayComponentType *CreateSpacer(int width, int height); 20 | 21 | #endif /* SPACER_H */ 22 | 23 | -------------------------------------------------------------------------------- /src/match.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file match.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Expression matching. 7 | * 8 | */ 9 | 10 | #ifndef MATCH_H 11 | #define MATCH_H 12 | 13 | /** Check if an expression matches a pattern. 14 | * @param pattern The pattern to match against. 15 | * @param expression The expression to check. 16 | * @return 1 if there is a match, 0 otherwise. 17 | */ 18 | char Match(const char *pattern, const char *expression); 19 | 20 | #endif /* MATCH_H */ 21 | 22 | -------------------------------------------------------------------------------- /po/remove-potcdate.sin: -------------------------------------------------------------------------------- 1 | # Sed script that remove the POT-Creation-Date line in the header entry 2 | # from a POT file. 3 | # 4 | # The distinction between the first and the following occurrences of the 5 | # pattern is achieved by looking at the hold space. 6 | /^"POT-Creation-Date: .*"$/{ 7 | x 8 | # Test if the hold space is empty. 9 | s/P/P/ 10 | ta 11 | # Yes it was empty. First occurrence. Remove the line. 12 | g 13 | d 14 | bb 15 | :a 16 | # The hold space was nonempty. Following occurrences. Do nothing. 17 | x 18 | :b 19 | } 20 | -------------------------------------------------------------------------------- /src/outline.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file outline.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Outlines for moving and resizing client windows. 7 | * 8 | */ 9 | 10 | #ifndef OUTLINE_H 11 | #define OUTLINE_H 12 | 13 | /** Draw an outline. 14 | * @param x The x-coordinate. 15 | * @param y The y-coordinate. 16 | * @param width The width of the outline. 17 | * @param height The height of the outline. 18 | */ 19 | void DrawOutline(int x, int y, int width, int height); 20 | 21 | /** Clear an outline. */ 22 | void ClearOutline(void); 23 | 24 | #endif /* OUTLINE_H */ 25 | 26 | -------------------------------------------------------------------------------- /src/grab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file grab.c 3 | * @author Joe Wingbermuehle 4 | * @date 2013 5 | * 6 | * @brief Functions for managing server grabs. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "main.h" 12 | 13 | static unsigned int grabCount = 0; 14 | 15 | /** Grab the server and sync. */ 16 | void GrabServer(void) 17 | { 18 | if(grabCount == 0) { 19 | JXGrabServer(display); 20 | JXSync(display, False); 21 | } 22 | grabCount += 1; 23 | } 24 | 25 | /** Ungrab the server. */ 26 | void UngrabServer(void) 27 | { 28 | Assert(grabCount > 0); 29 | grabCount -= 1; 30 | if(grabCount == 0) { 31 | JXUngrabServer(display); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/parse.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file parse.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header file for the JWM configuration parser. 7 | * 8 | */ 9 | 10 | #ifndef PARSE_H 11 | #define PARSE_H 12 | 13 | struct Menu; 14 | 15 | /** Parse a configuration file. 16 | * @param fileName The user-specified config file to parse. 17 | */ 18 | void ParseConfig(const char *fileName); 19 | 20 | /** Parse a dynamic menu. 21 | * @param timeout_ms The timeout in milliseconds. 22 | * @param command The command to generate the menu. 23 | * @return The menu. 24 | */ 25 | struct Menu *ParseDynamicMenu(unsigned timeout_ms, const char *command); 26 | 27 | #endif /* PARSE_H */ 28 | 29 | -------------------------------------------------------------------------------- /src/pager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file pager.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Pager tray component. 7 | * 8 | */ 9 | 10 | #ifndef PAGER_H 11 | #define PAGER_H 12 | 13 | struct TrayComponentType; 14 | 15 | /*@{*/ 16 | #define InitializePager() (void)(0) 17 | #define StartupPager() (void)(0) 18 | void ShutdownPager(void); 19 | void DestroyPager(void); 20 | /*@}*/ 21 | 22 | /** Create a pager tray component. 23 | * @param labeled Set to label the pager. 24 | * @return A new pager tray component. 25 | */ 26 | struct TrayComponentType *CreatePager(char labeled); 27 | 28 | /** Update pagers. */ 29 | void UpdatePager(void); 30 | 31 | #endif /* PAGER_H */ 32 | 33 | -------------------------------------------------------------------------------- /po/insert-header.sin: -------------------------------------------------------------------------------- 1 | # Sed script that inserts the file called HEADER before the header entry. 2 | # 3 | # At each occurrence of a line starting with "msgid ", we execute the following 4 | # commands. At the first occurrence, insert the file. At the following 5 | # occurrences, do nothing. The distinction between the first and the following 6 | # occurrences is achieved by looking at the hold space. 7 | /^msgid /{ 8 | x 9 | # Test if the hold space is empty. 10 | s/m/m/ 11 | ta 12 | # Yes it was empty. First occurrence. Read the file. 13 | r HEADER 14 | # Output the file's contents by reading the next line. But don't lose the 15 | # current line while doing this. 16 | g 17 | N 18 | bb 19 | :a 20 | # The hold space was nonempty. Following occurrences. Do nothing. 21 | x 22 | :b 23 | } 24 | -------------------------------------------------------------------------------- /src/match.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file match.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Expression matching. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "match.h" 12 | 13 | #include 14 | 15 | /** Determine if expression matches pattern. */ 16 | char Match(const char *pattern, const char *expression) 17 | { 18 | 19 | regex_t re; 20 | regmatch_t rm; 21 | int rc; 22 | 23 | if(!pattern && !expression) { 24 | return 1; 25 | } else if(!pattern || !expression) { 26 | return 0; 27 | } 28 | 29 | if(regcomp(&re, pattern, REG_EXTENDED) != 0) { 30 | return 0; 31 | } 32 | 33 | rc = regexec(&re, expression, 0, &rm, 0); 34 | 35 | regfree(&re); 36 | 37 | return rc == 0 ? 1 : 0; 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/move.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file move.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for client window move functions. 7 | * 8 | */ 9 | 10 | #ifndef MOVE_H 11 | #define MOVE_H 12 | 13 | struct ClientNode; 14 | 15 | /** Move a client window. 16 | * @param np The client to move. 17 | * @param startx The starting mouse x-coordinate (window relative). 18 | * @param starty The starting mouse y-coordinate (window relative). 19 | * @return 1 if the client moved, 0 otherwise. 20 | */ 21 | char MoveClient(struct ClientNode *np, int startx, int starty); 22 | 23 | /** Move a client window using the keyboard (mouse optional). 24 | * @param np The client to move. 25 | * @return 1 if the client moved, 0 otherwise. 26 | */ 27 | char MoveClientKeyboard(struct ClientNode *np); 28 | 29 | #endif /* MOVE_H */ 30 | 31 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | src/action.c 2 | src/background.c 3 | src/border.c 4 | src/button.c 5 | src/client.c 6 | src/clientlist.c 7 | src/clock.c 8 | src/color.c 9 | src/command.c 10 | src/confirm.c 11 | src/cursor.c 12 | src/debug.c 13 | src/desktop.c 14 | src/dock.c 15 | src/error.c 16 | src/event.c 17 | src/font.c 18 | src/grab.c 19 | src/gradient.c 20 | src/group.c 21 | src/help.c 22 | src/hint.c 23 | src/icon.c 24 | src/image.c 25 | src/key.c 26 | src/lex.c 27 | src/main.c 28 | src/match.c 29 | src/menu.c 30 | src/misc.c 31 | src/move.c 32 | src/outline.c 33 | src/pager.c 34 | src/parse.c 35 | src/place.c 36 | src/popup.c 37 | src/render.c 38 | src/resize.c 39 | src/root.c 40 | src/screen.c 41 | src/settings.c 42 | src/spacer.c 43 | src/status.c 44 | src/swallow.c 45 | src/taskbar.c 46 | src/timing.c 47 | src/tray.c 48 | src/traybutton.c 49 | src/winmenu.c 50 | -------------------------------------------------------------------------------- /src/background.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file background.h 3 | * @author Joe Wingbermuehle 4 | * @date 2007 5 | * 6 | * @brief Background control functions. 7 | * 8 | */ 9 | 10 | #ifndef BACKGROUND_H 11 | #define BACKGROUND_H 12 | 13 | /*@{*/ 14 | void InitializeBackgrounds(void); 15 | void StartupBackgrounds(void); 16 | void ShutdownBackgrounds(void); 17 | void DestroyBackgrounds(void); 18 | /*@}*/ 19 | 20 | /** Set the background to use for the specified desktops. 21 | * @param desktop The desktop whose background to set (-1 for the default). 22 | * @param type The type of background. 23 | * @param value The background. 24 | */ 25 | void SetBackground(int desktop, const char *type, const char *value); 26 | 27 | /** Load the background for the specified desktop. 28 | * @param desktop The current desktop. 29 | */ 30 | void LoadBackground(int desktop); 31 | 32 | #endif /* BACKGROUND_H */ 33 | 34 | -------------------------------------------------------------------------------- /src/resize.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file resize.h 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Header for client window resize functions. 7 | * 8 | */ 9 | 10 | #ifndef RESIZE_H 11 | #define RESIZE_H 12 | 13 | #include "border.h" 14 | 15 | struct ClientNode; 16 | 17 | /** Resize a client window. 18 | * @param np The client to resize. 19 | * @param context The mouse context. 20 | * @param startx The starting mouse x-coordinate (window relative). 21 | * @param starty The starting mouse y-coordinate (window relative). 22 | */ 23 | void ResizeClient(struct ClientNode *np, MouseContextType context, 24 | int startx, int starty); 25 | 26 | /** Resize a client window using the keyboard (mouse optional). 27 | * @param np The client to resize. 28 | * @param context The mouse context. 29 | */ 30 | void ResizeClientKeyboard(struct ClientNode *np, MouseContextType context); 31 | 32 | #endif /* RESIZE_H */ 33 | 34 | -------------------------------------------------------------------------------- /src/confirm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file confirm.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the confirm dialog functions. 7 | * 8 | */ 9 | 10 | #ifndef CONFIRM_H 11 | #define CONFIRM_H 12 | 13 | struct ClientNode; 14 | 15 | /*@{*/ 16 | #define InitializeDialogs() (void)(0) 17 | #define StartupDialogs() (void)(0) 18 | void ShutdownDialogs(void); 19 | #define DestroyDialogs() (void)(0) 20 | /*@}*/ 21 | 22 | /** Handle an event on a dialog window. 23 | * @param event The event. 24 | * @return 1 if handled, 0 if not handled. 25 | */ 26 | char ProcessDialogEvent(const XEvent *event); 27 | 28 | /** Show a confirm dialog. 29 | * @param np A client window associated with the dialog. 30 | * @param action A callback to run if "OK" is clicked. 31 | */ 32 | void ShowConfirmDialog(struct ClientNode *np, 33 | void (*action)(struct ClientNode*), ...); 34 | 35 | #endif /* CONFIRM_H */ 36 | 37 | -------------------------------------------------------------------------------- /src/gradient.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gradient.h 3 | * @author Joe Wingbermuehle 4 | * @date 2006 5 | * 6 | * @brief Gradient fill functions. 7 | * 8 | */ 9 | 10 | #ifndef GRADIENT_H 11 | #define GRADIENT_H 12 | 13 | /** Draw a horizontal gradient. 14 | * Note that no action is taken if fromColor == toColor. 15 | * @param d The drawable on which to draw the gradient. 16 | * @param g The graphics context to use. 17 | * @param fromColor The starting color pixel value. 18 | * @param toColor The ending color pixel value. 19 | * @param x The x-coordinate. 20 | * @param y The y-coordinate. 21 | * @param width The width of the area to fill. 22 | * @param height The height of the area to fill. 23 | */ 24 | void DrawHorizontalGradient(Drawable d, GC g, 25 | long fromColor, long toColor, 26 | int x, int y, 27 | unsigned int width, unsigned int height); 28 | 29 | #endif /* GRADIENT_H */ 30 | 31 | -------------------------------------------------------------------------------- /src/popup.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file popup.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for popup functions. 7 | * 8 | */ 9 | 10 | #ifndef POPUP_H 11 | #define POPUP_H 12 | 13 | #include "settings.h" 14 | 15 | /*@{*/ 16 | #define InitializePopup() (void)(0) 17 | void StartupPopup(void); 18 | void ShutdownPopup(void); 19 | #define DestroyPopup() (void)(0) 20 | /*@}*/ 21 | 22 | /** Show a popup window. 23 | * @param x The x coordinate of the left edge of the popup window. 24 | * @param y The y coordinate of the bottom edge of the popup window. 25 | * @param text The text to display in the popup. 26 | * @param context The popup context. 27 | */ 28 | void ShowPopup(int x, int y, const char *text, 29 | const PopupMaskType context); 30 | 31 | /** Process a popup event. 32 | * @param event The event to process. 33 | * @return 1 if handled, 0 otherwise. 34 | */ 35 | char ProcessPopupEvent(const XEvent *event); 36 | 37 | #endif /* POPUP_H */ 38 | 39 | -------------------------------------------------------------------------------- /src/error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file error.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the error functions. 7 | * 8 | */ 9 | 10 | #ifndef ERROR_H 11 | #define ERROR_H 12 | 13 | /** Display and error message and terminate the program. 14 | * @param str The format of the message to display. 15 | */ 16 | void FatalError(const char *str, ...); 17 | 18 | /** Display a warning message. 19 | * @param str The format of the message to display. 20 | */ 21 | void Warning(const char *str, ...); 22 | 23 | /** Display a warning message. 24 | * @param part A section identifier for the message. 25 | * @param str The format string of the message to display. 26 | * @param ap The argument list. 27 | */ 28 | void WarningVA(const char *part, const char *str, va_list ap); 29 | 30 | /** Handle an XError event. 31 | * @param d The display on which the event occurred. 32 | * @param e The error event. 33 | * @return 0 34 | */ 35 | int ErrorHandler(Display *d, XErrorEvent *e); 36 | 37 | #endif 38 | 39 | -------------------------------------------------------------------------------- /src/winmenu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file winmenu.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for handling window menus. 7 | * 8 | */ 9 | 10 | #ifndef WINMENU_H 11 | #define WINMENU_H 12 | 13 | #include "menu.h" 14 | 15 | struct ClientNode; 16 | 17 | /** Create a window menu. */ 18 | Menu *CreateWindowMenu(struct ClientNode *np); 19 | 20 | /** Show a window menu. 21 | * @param np The client for the window menu. 22 | * @param x The x-coordinate of the menu (root relative). 23 | * @param y The y-coordinate of the menu (root relative). 24 | * @param keyboard Set if this request came from a key binding. 25 | */ 26 | void ShowWindowMenu(struct ClientNode *np, int x, int y, char keyboard); 27 | 28 | /** Grab the mouse to select a window. 29 | * @param action The action to perform when a window is selected. 30 | */ 31 | void ChooseWindow(MenuAction *action); 32 | 33 | /** Run a menu action for selected client. */ 34 | void RunWindowCommand(MenuAction *action, unsigned button); 35 | 36 | #endif /* WINMENU_H */ 37 | -------------------------------------------------------------------------------- /src/main.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the main functions. 7 | * 8 | */ 9 | 10 | #ifndef MAIN_H 11 | #define MAIN_H 12 | 13 | extern Display *display; 14 | extern Window rootWindow; 15 | extern int rootWidth, rootHeight; 16 | extern int rootScreen; 17 | extern Colormap rootColormap; 18 | extern Visual *rootVisual; 19 | extern int rootDepth; 20 | extern GC rootGC; 21 | extern int colormapCount; 22 | extern Window supportingWindow; 23 | extern Atom managerSelection; 24 | 25 | extern char *exitCommand; 26 | 27 | extern unsigned int currentDesktop; 28 | 29 | extern char shouldExit; 30 | extern char shouldRestart; 31 | extern char isRestarting; 32 | extern char shouldReload; 33 | extern char initializing; 34 | 35 | extern XContext clientContext; 36 | extern XContext frameContext; 37 | 38 | #ifdef USE_SHAPE 39 | extern char haveShape; 40 | extern int shapeEvent; 41 | #endif 42 | #ifdef USE_XRENDER 43 | extern char haveRender; 44 | #endif 45 | 46 | extern char *configPath; 47 | 48 | #endif /* MAIN_H */ 49 | 50 | -------------------------------------------------------------------------------- /doc-header.shtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JWM Source Documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | 24 | 25 | 26 |
20 |
21 | JWM Source Documentation 22 |
23 |
27 |
28 | -------------------------------------------------------------------------------- /src/status.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file status.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the status functions. 7 | * 8 | */ 9 | 10 | #ifndef STATUS_H 11 | #define STATUS_H 12 | 13 | struct ClientNode; 14 | 15 | /** Create a move status window. 16 | * @param np The client to be moved. 17 | */ 18 | void CreateMoveWindow(struct ClientNode *np); 19 | 20 | /** Update a move status window. 21 | * @param np The client being moved. 22 | */ 23 | void UpdateMoveWindow(struct ClientNode *np); 24 | 25 | /** Destroy a move status window. */ 26 | void DestroyMoveWindow(void); 27 | 28 | /** Create a resize status window. 29 | * @param np The client being resized. 30 | */ 31 | void CreateResizeWindow(struct ClientNode *np); 32 | 33 | /** Update a resize status window. 34 | * @param np The client being resized. 35 | * @param gwidth The width to display. 36 | * @param gheight The height to display. 37 | */ 38 | void UpdateResizeWindow(struct ClientNode *np, int gwidth, int gheight); 39 | 40 | /** Destroy a resize status window. */ 41 | void DestroyResizeWindow(void); 42 | 43 | #endif /* STATUS_H */ 44 | 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Joe Wingbermuehle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Makefile.in: -------------------------------------------------------------------------------- 1 | CC = @CC@ 2 | CFLAGS = @CFLAGS@ 3 | CPPFLAGS = @CPPFLAGS@ 4 | LDFLAGS = @LDFLAGS@ 5 | BINDIR = $(DESTDIR)@BINDIR@ 6 | 7 | VPATH=.:os 8 | 9 | OBJECTS = action.o background.o binding.o border.o button.o client.o \ 10 | clientlist.o clock.o color.o command.o confirm.o cursor.o debug.o \ 11 | default.o desktop.o dock.o event.o error.o font.o grab.o gradient.o \ 12 | group.o help.o hint.o icon.o image.o lex.o main.o match.o menu.o misc.o \ 13 | move.o outline.o pager.o parse.o place.o popup.o render.o resize.o \ 14 | root.o screen.o settings.o spacer.o status.o swallow.o taskbar.o \ 15 | timing.o tray.o traybutton.o winmenu.o 16 | 17 | EXE = jwm 18 | 19 | .SUFFIXES: .o .h .c 20 | 21 | all: $(EXE) 22 | 23 | install: all 24 | install -d $(BINDIR) 25 | install $(EXE) $(BINDIR)/$(EXE) 26 | 27 | install-strip: install 28 | strip $(BINDIR)/$(EXE) 29 | 30 | uninstall: 31 | rm -f $(BINDIR)/$(EXE) 32 | 33 | $(EXE): $(OBJECTS) 34 | $(CC) -o $(EXE) $(OBJECTS) $(LDFLAGS) 35 | 36 | .c.o: 37 | $(CC) -c $(CFLAGS) $(CPPFLAGS) $< 38 | 39 | $(OBJECTS): *.h ../config.h 40 | 41 | clean: 42 | rm -f $(OBJECTS) $(EXE) core 43 | 44 | -------------------------------------------------------------------------------- /src/clock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file clock.h 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Clock tray component. 7 | * 8 | */ 9 | 10 | #ifndef CLOCK_H 11 | #define CLOCK_H 12 | 13 | struct TrayComponentType; 14 | 15 | /*@{*/ 16 | void InitializeClock(void); 17 | void StartupClock(void); 18 | #define ShutdownClock() (void)(0) 19 | void DestroyClock(void); 20 | /*@}*/ 21 | 22 | /** Create a clock component for the tray. 23 | * @param format The format of the clock. 24 | * @param zone The timezone of the clock (NULL for local time). 25 | * @param width The width of the clock (0 for auto). 26 | * @param height The height of the clock (0 for auto). 27 | */ 28 | struct TrayComponentType *CreateClock(const char *format, 29 | const char *zone, 30 | int width, int height); 31 | 32 | /** Add an action to a clock. 33 | * @param cp The clock. 34 | * @param action The action to take. 35 | * @param mask The mouse button mask. 36 | */ 37 | void AddClockAction(struct TrayComponentType *cp, 38 | const char *action, 39 | int mask); 40 | 41 | #endif /* CLOCK_H */ 42 | -------------------------------------------------------------------------------- /src/render.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file render.h 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Functions to render icons using the XRender extension. 7 | * 8 | */ 9 | 10 | #ifndef RENDER_H 11 | #define RENDER_H 12 | 13 | struct IconNode; 14 | struct ImageNode; 15 | struct ScaledIconNode; 16 | 17 | /** Put a scaled icon. 18 | * @param image The image to display. 19 | * @param node The rendered image to display. 20 | * @param d The drawable on which to render the icon. 21 | * @param x The x-coordinate to place the icon. 22 | * @param y The y-coordinate to place the icon. 23 | * @param width The width of the icon. 24 | * @param height The height of the icon. 25 | * @return 1 if the icon was successfully rendered, 0 otherwise. 26 | */ 27 | void PutScaledRenderIcon(const struct IconNode *image, 28 | const struct ScaledIconNode *node, 29 | Drawable d, int x, int y, int width, int height); 30 | 31 | /** Create a scaled icon. 32 | * @param image The image. 33 | * @param fg The foreground color (for bitmaps). 34 | * @return The scaled icon. 35 | */ 36 | struct ScaledIconNode *CreateScaledRenderIcon(struct ImageNode *image, long fg); 37 | 38 | #endif /* RENDER_H */ 39 | -------------------------------------------------------------------------------- /po/en@quot.header: -------------------------------------------------------------------------------- 1 | # All this catalog "translates" are quotation characters. 2 | # The msgids must be ASCII and therefore cannot contain real quotation 3 | # characters, only substitutes like grave accent (0x60), apostrophe (0x27) 4 | # and double quote (0x22). These substitutes look strange; see 5 | # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html 6 | # 7 | # This catalog translates grave accent (0x60) and apostrophe (0x27) to 8 | # left single quotation mark (U+2018) and right single quotation mark (U+2019). 9 | # It also translates pairs of apostrophe (0x27) to 10 | # left single quotation mark (U+2018) and right single quotation mark (U+2019) 11 | # and pairs of quotation mark (0x22) to 12 | # left double quotation mark (U+201C) and right double quotation mark (U+201D). 13 | # 14 | # When output to an UTF-8 terminal, the quotation characters appear perfectly. 15 | # When output to an ISO-8859-1 terminal, the single quotation marks are 16 | # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to 17 | # grave/acute accent (by libiconv), and the double quotation marks are 18 | # transliterated to 0x22. 19 | # When output to an ASCII terminal, the single quotation marks are 20 | # transliterated to apostrophes, and the double quotation marks are 21 | # transliterated to 0x22. 22 | # 23 | -------------------------------------------------------------------------------- /src/outline.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file outline.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Outlines for moving and resizing client windows. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "outline.h" 12 | #include "main.h" 13 | #include "grab.h" 14 | 15 | static GC outlineGC = None; 16 | static int lastX, lastY; 17 | static int lastWidth, lastHeight; 18 | 19 | /** Draw an outline. */ 20 | void DrawOutline(int x, int y, int width, int height) 21 | { 22 | XGCValues gcValues; 23 | gcValues.function = GXinvert; 24 | gcValues.subwindow_mode = IncludeInferiors; 25 | gcValues.line_width = 2; 26 | outlineGC = JXCreateGC(display, rootWindow, 27 | GCFunction | GCSubwindowMode | GCLineWidth, 28 | &gcValues); 29 | GrabServer(); 30 | JXDrawRectangle(display, rootWindow, outlineGC, x, y, width, height); 31 | lastX = x; 32 | lastY = y; 33 | lastWidth = width; 34 | lastHeight = height; 35 | } 36 | 37 | /** Clear the last outline. */ 38 | void ClearOutline(void) 39 | { 40 | if(outlineGC != None) { 41 | JXDrawRectangle(display, rootWindow, outlineGC, 42 | lastX, lastY, lastWidth, lastHeight); 43 | UngrabServer(); 44 | JXFreeGC(display, outlineGC); 45 | outlineGC = None; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/command.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file command.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Handle running startup, shutdown, and restart commands. 7 | * 8 | */ 9 | 10 | #ifndef COMMAND_H 11 | #define COMMAND_H 12 | 13 | /*@{*/ 14 | #define InitializeCommands() (void)(0) 15 | void StartupCommands(void); 16 | void ShutdownCommands(void); 17 | void DestroyCommands(void); 18 | /*@}*/ 19 | 20 | /** Add a command to be executed at startup. 21 | * @param command The command to execute. 22 | */ 23 | void AddStartupCommand(const char *command); 24 | 25 | /** Add a command to be executed at shutdown. 26 | * @param command The command to execute. 27 | */ 28 | void AddShutdownCommand(const char *command); 29 | 30 | /** Add a command to be executed after a restart. 31 | * @param command The command to execute. 32 | */ 33 | void AddRestartCommand(const char *command); 34 | 35 | /** Run a command. 36 | * @param command The command to run (run in sh). 37 | */ 38 | void RunCommand(const char *command); 39 | 40 | /** Read output from a process. 41 | * @param command The command to run (run in sh). 42 | * @param timeout_ms The timeout in milliseconds. 43 | * @return The output (must be freed, NULL on timeout). 44 | */ 45 | char *ReadFromProcess(const char *command, unsigned timeout_ms); 46 | 47 | #endif /* COMMAND_H */ 48 | 49 | -------------------------------------------------------------------------------- /src/timing.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file timing.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Timing functions. 7 | * 8 | */ 9 | 10 | #ifndef TIMING_H 11 | #define TIMING_H 12 | 13 | /** Initializer for TimeType to indicate that it is not set. */ 14 | #define ZERO_TIME { 0, 0 } 15 | 16 | /** Structure to represent time since January 1, 1970 GMT. */ 17 | typedef struct TimeType { 18 | 19 | unsigned long seconds; /**< Seconds. */ 20 | int ms; /**< Milliseconds. */ 21 | 22 | } TimeType; 23 | 24 | /** Get the current time. 25 | * @param t The TimeType to fill. 26 | */ 27 | void GetCurrentTime(TimeType *t); 28 | 29 | /** Get the difference between two times. 30 | * Note that the times must be normalized. 31 | * @param t1 The first time. 32 | * @param t2 The second time. 33 | * @return The difference in milliseconds (maximum of 60000 ms). 34 | */ 35 | unsigned long GetTimeDifference(const TimeType *t1, const TimeType *t2); 36 | 37 | /** Get a time string. 38 | * Note that the string returned is a static value and should not be 39 | * deleted. Therefore, this function is not thread safe. 40 | * @param format The format to use for the string. 41 | * @param zone The timezone in tzset() format to use (defaults to local) 42 | * @return The time string. 43 | */ 44 | const char *GetTimeString(const char *format, const char *zone); 45 | 46 | #endif /* TIMING_H */ 47 | 48 | -------------------------------------------------------------------------------- /po/en@boldquot.header: -------------------------------------------------------------------------------- 1 | # All this catalog "translates" are quotation characters. 2 | # The msgids must be ASCII and therefore cannot contain real quotation 3 | # characters, only substitutes like grave accent (0x60), apostrophe (0x27) 4 | # and double quote (0x22). These substitutes look strange; see 5 | # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html 6 | # 7 | # This catalog translates grave accent (0x60) and apostrophe (0x27) to 8 | # left single quotation mark (U+2018) and right single quotation mark (U+2019). 9 | # It also translates pairs of apostrophe (0x27) to 10 | # left single quotation mark (U+2018) and right single quotation mark (U+2019) 11 | # and pairs of quotation mark (0x22) to 12 | # left double quotation mark (U+201C) and right double quotation mark (U+201D). 13 | # 14 | # When output to an UTF-8 terminal, the quotation characters appear perfectly. 15 | # When output to an ISO-8859-1 terminal, the single quotation marks are 16 | # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to 17 | # grave/acute accent (by libiconv), and the double quotation marks are 18 | # transliterated to 0x22. 19 | # When output to an ASCII terminal, the single quotation marks are 20 | # transliterated to apostrophes, and the double quotation marks are 21 | # transliterated to 0x22. 22 | # 23 | # This catalog furthermore displays the text between the quotation marks in 24 | # bold face, assuming the VT100/XTerm escape sequences. 25 | # 26 | -------------------------------------------------------------------------------- /src/swallow.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file swallow.h 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Swallow tray component. 7 | * 8 | */ 9 | 10 | #ifndef SWALLOW_H 11 | #define SWALLOW_H 12 | 13 | /*@{*/ 14 | #define InitializeSwallow() (void)(0) 15 | void StartupSwallow(void); 16 | #define ShutdownSwallow() (void)(0) 17 | void DestroySwallow(void); 18 | /*@}*/ 19 | 20 | /** Create a swallowed application tray component. 21 | * @param name The name of the application to swallow. 22 | * @param command The command used to start the swallowed application. 23 | * @param width The width to use (0 for default). 24 | * @param height the height to use (0 for default). 25 | */ 26 | struct TrayComponentType *CreateSwallow(const char *name, 27 | const char *command, 28 | int width, int height); 29 | 30 | /** Determine if a window should be swallowed. 31 | * @param win The window. 32 | * @return 1 if this window should be swallowed, 0 if not. 33 | */ 34 | char CheckSwallowMap(Window win); 35 | 36 | /** Process an event on a swallowed window. 37 | * @param event The event to process. 38 | * @return 1 if the event was for a swallowed window, 0 if not. 39 | */ 40 | char ProcessSwallowEvent(const XEvent *event); 41 | 42 | /** Determine if there are swallow processes pending. 43 | * @return 1 if there are still pending swallow processes, 0 otherwise. 44 | */ 45 | char IsSwallowPending(void); 46 | 47 | #endif /* SWALLOW_H */ 48 | 49 | -------------------------------------------------------------------------------- /src/screen.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file screen.h 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Header for screen functions. 7 | * 8 | * Note that screen here refers to physical monitors. Screens are 9 | * determined using the xinerama extension (if available). There will 10 | * always be at least one screen. 11 | * 12 | */ 13 | 14 | #ifndef SCREEN_H 15 | #define SCREEN_H 16 | 17 | /** Structure to contain information about a screen. */ 18 | typedef struct ScreenType { 19 | int index; /**< The index of this screen. */ 20 | int x, y; /**< The location of this screen. */ 21 | int width, height; /**< The size of this screen. */ 22 | } ScreenType; 23 | 24 | /*@{*/ 25 | #define InitializeScreens() (void)(0) 26 | void StartupScreens(void); 27 | void ShutdownScreens(void); 28 | #define DestroyScreens() (void)(0) 29 | /*@}*/ 30 | 31 | /** Get the screen of the specified coordinates. 32 | * @param x The x-coordinate. 33 | * @param y The y-coordinate. 34 | * @return The screen. 35 | */ 36 | const ScreenType *GetCurrentScreen(int x, int y); 37 | 38 | /** Get the screen containing the mouse. 39 | * @return The screen containing the mouse. 40 | */ 41 | const ScreenType *GetMouseScreen(void); 42 | 43 | /** Get the screen of the specified index. 44 | * @param index The screen index (0 based). 45 | * @return The screen. 46 | */ 47 | const ScreenType *GetScreen(int index); 48 | 49 | /** Get the number of screens. 50 | * @return The number of screens. 51 | */ 52 | int GetScreenCount(void); 53 | 54 | #endif /* SCREEN_H */ 55 | 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JWM (Joe's Window Manager) 2 | ============================================================================== 3 | 4 | JWM is a light-weight window manager for the X11 Window System. 5 | 6 | Requirements 7 | ------------------------------------------------------------------------------ 8 | To build JWM you will need a C compiler (gcc works), X11, and the 9 | "development headers" for X11 and Xlib. 10 | If available and not disabled at compile time, JWM will also use 11 | the following libraries: 12 | 13 | - cairo and librsvg2 for SVG icons and backgrounds. 14 | - fribidi for bi-directional text support. 15 | - libjpeg for JPEG icons and backgrounds. 16 | - libpng for PNG icons and backgrounds. 17 | - libXext for the shape extension. 18 | - libXrender for the render extension. 19 | - libXmu for rounded corners. 20 | - libXft for anti-aliased and true type fonts. 21 | - libXinerama for multiple head support. 22 | - libXpm for XPM icons and backgrounds. 23 | 24 | Installation 25 | ------------------------------------------------------------------------------ 26 | 27 | 0. For building from the git repository, run "./autogen.sh". 28 | 1. Run "./configure --help" for configuration options. 29 | 2. Run "./configure [options]" 30 | 3. Run "make" to build JWM. 31 | 4. Run "make install" to install JWM. Depending on where you are installing 32 | JWM, you may need to perform this step as root ("sudo make install"). 33 | 34 | License 35 | ------------------------------------------------------------------------------ 36 | See LICENSE for license information. 37 | 38 | For more information see http://joewing.net/projects/jwm/ 39 | -------------------------------------------------------------------------------- /src/clientlist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file clientlist.h 3 | * @author Joe Wingbermuehle 4 | * @date 2007 5 | * 6 | * @brief Functions to manage lists of clients. 7 | * 8 | */ 9 | 10 | #ifndef CLIENTLIST_H 11 | #define CLIENTLIST_H 12 | 13 | #include "hint.h" 14 | 15 | struct ClientNode; 16 | 17 | /** Client windows in linked lists for each layer. */ 18 | extern struct ClientNode *nodes[LAYER_COUNT]; 19 | 20 | /** Client windows in linked lists for each layer (pointer to the tail). */ 21 | extern struct ClientNode *nodeTail[LAYER_COUNT]; 22 | 23 | /** Determine if a client is on the current desktop. 24 | * @param np The client. 25 | * @return 1 if on the current desktop, 0 otherwise. 26 | */ 27 | #define IsClientOnCurrentDesktop( np ) \ 28 | ((np->state.desktop == currentDesktop) \ 29 | || (np->state.status & STAT_STICKY)) 30 | 31 | /** Determine if a client is allowed focus. 32 | * @param np The client. 33 | * @param current 1 if only showing clients on the current desktop. 34 | * @return 1 if focus is allowed, 0 otherwise. 35 | */ 36 | char ShouldFocus(const struct ClientNode *np, char current); 37 | 38 | /** Start walking the window client list. */ 39 | void StartWindowWalk(void); 40 | 41 | /** Start walking the window stack. */ 42 | void StartWindowStackWalk(); 43 | 44 | /** Move to the next/previous window in the window stack. */ 45 | void WalkWindowStack(char forward); 46 | 47 | /** Stop walking the window stack or client list. */ 48 | void StopWindowWalk(void); 49 | 50 | /** Set the keyboard focus to the next client. 51 | * This is used to focus the next client in the stacking order. 52 | * @param np The client before the client to focus. 53 | */ 54 | void FocusNextStacked(struct ClientNode *np); 55 | 56 | #endif /* CLIENTLIST_H */ 57 | -------------------------------------------------------------------------------- /src/dock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dock.h 3 | * @author Joe Wingbermuehle 4 | * @date 2006 5 | * 6 | * @brief Dock tray component (used for system notifications). 7 | * 8 | */ 9 | 10 | #ifndef DOCK_H 11 | #define DOCK_H 12 | 13 | struct TrayComponentType; 14 | 15 | /*@{*/ 16 | void InitializeDock(void); 17 | void StartupDock(void); 18 | void ShutdownDock(void); 19 | void DestroyDock(void); 20 | /*@}*/ 21 | 22 | /** Create a dock to be used for notifications. 23 | * Note that only one dock can be created. 24 | * @param width The width of an item in the dock. 25 | */ 26 | struct TrayComponentType *CreateDock(int width); 27 | 28 | /** Handle a client message sent to the dock window. 29 | * @param event The event. 30 | */ 31 | void HandleDockEvent(const XClientMessageEvent *event); 32 | 33 | /** Handle a destroy event. 34 | * @param win The window that was destroyed. 35 | * @return 1 if handled, 0 otherwise. 36 | */ 37 | char HandleDockDestroy(Window win); 38 | 39 | /** Handle a selection clear event. 40 | * @param event The selection clear event. 41 | * @return 1 if handled, 0 otherwise. 42 | */ 43 | char HandleDockSelectionClear(const XSelectionClearEvent *event); 44 | 45 | /** Handle a resize request. 46 | * @param event The resize request event. 47 | * @return 1 if handled, 0 otherwise. 48 | */ 49 | char HandleDockResizeRequest(const XResizeRequestEvent *event); 50 | 51 | /** Handle a configure request. 52 | * @param event The configure request event. 53 | * @return 1 if handled, 0 otherwise. 54 | */ 55 | char HandleDockConfigureRequest(const XConfigureRequestEvent *event); 56 | 57 | /** Handle a reparent notify event. 58 | * @param event The reparent notify event. 59 | * @return 1 if handled, 0 otherwise. 60 | */ 61 | char HandleDockReparentNotify(const XReparentEvent *event); 62 | 63 | #endif 64 | 65 | -------------------------------------------------------------------------------- /src/traybutton.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file traybutton.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Button tray component. 7 | * 8 | */ 9 | 10 | #ifndef TRAY_BUTTON_H 11 | #define TRAY_BUTTON_H 12 | 13 | struct TrayComponentType; 14 | struct TimeType; 15 | 16 | /*@{*/ 17 | #define InitializeTrayButtons() (void)(0) 18 | void StartupTrayButtons(void); 19 | #define ShutdownTrayButtons() (void)(0) 20 | void DestroyTrayButtons(void); 21 | /*@}*/ 22 | 23 | /** Create a tray button component. 24 | * @param iconName The name of the icon to use for the button. 25 | * @param label The label to use for the button. 26 | * @param popup Text to display in a popup window. 27 | * @param width The width to use for the button (0 for default). 28 | * @param height The height to use for the button (0 for default). 29 | * @return A new tray button component. 30 | */ 31 | struct TrayComponentType *CreateTrayButton(const char *iconName, 32 | const char *label, 33 | const char *popup, 34 | unsigned int width, 35 | unsigned int height); 36 | 37 | /** Add an action to a tray button. 38 | * @param cp The tray button. 39 | * @param action The action to take. 40 | * @param mask The mouse button mask. 41 | */ 42 | void AddTrayButtonAction(struct TrayComponentType *cp, 43 | const char *action, 44 | int mask); 45 | 46 | /** Validate the tray buttons and print a warning if something is wrong. 47 | * This is called after parsing the configuration file(s) to determine 48 | * if a root menu is defined for each each tray button that specifies 49 | * a root menu. 50 | */ 51 | void ValidateTrayButtons(void); 52 | 53 | #endif /* TRAY_BUTTON_H */ 54 | 55 | -------------------------------------------------------------------------------- /src/taskbar.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file taskbar.h 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Task list tray component. 7 | * 8 | */ 9 | 10 | #ifndef TASKBAR_H 11 | #define TASKBAR_H 12 | 13 | struct ClientNode; 14 | struct TimeType; 15 | 16 | /*@{*/ 17 | void InitializeTaskBar(void); 18 | #define StartupTaskBar() (void)(0) 19 | void ShutdownTaskBar(void); 20 | void DestroyTaskBar(void); 21 | /*@}*/ 22 | 23 | /** Create a new task bar tray component. */ 24 | struct TrayComponentType *CreateTaskBar(); 25 | 26 | /** Add a client to the task bar(s). 27 | * @param np The client to add. 28 | */ 29 | void AddClientToTaskBar(struct ClientNode *np); 30 | 31 | /** Remove a client from the task bar(s). 32 | * @param np The client to remove. 33 | */ 34 | void RemoveClientFromTaskBar(struct ClientNode *np); 35 | 36 | /** Update all task bars. */ 37 | void UpdateTaskBar(void); 38 | 39 | /** Focus the next client in the task bar. */ 40 | void FocusNext(void); 41 | 42 | /** Focus the previous client in the task bar. */ 43 | void FocusPrevious(void); 44 | 45 | /** Set the maximum width of task bar items. 46 | * @param cp The task bar component. 47 | * @param value The maximum width. 48 | */ 49 | void SetMaxTaskBarItemWidth(struct TrayComponentType *cp, const char *value); 50 | 51 | /** Set the preferred height of task bar items. 52 | * @param cp The task bar component. 53 | * @param value The height. 54 | */ 55 | void SetTaskBarHeight(struct TrayComponentType *cp, const char *value); 56 | 57 | /** Set whether labels should be displayed (or icon only). 58 | * @param cp The task bar component. 59 | * @param value 1 if labeled, 0 if no label is to be shown. 60 | */ 61 | void SetTaskBarLabeled(struct TrayComponentType *cp, char value); 62 | 63 | /** Update the _NET_CLIENT_LIST property. */ 64 | void UpdateNetClientList(void); 65 | 66 | #endif /* TASKBAR_H */ 67 | -------------------------------------------------------------------------------- /src/image.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file image.h 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2014 5 | * 6 | * @brief Functions to load images. 7 | * 8 | */ 9 | 10 | #ifndef IMAGE_H 11 | #define IMAGE_H 12 | 13 | /** Structure to represent an image. */ 14 | typedef struct ImageNode { 15 | 16 | struct ImageNode *next; /**< Next image node (if multiple sizes). */ 17 | unsigned char *data; /**< Image data. */ 18 | int width; /**< Width of the image. */ 19 | int height; /**< Height of the image. */ 20 | char bitmap; /**< 1 if a bitmap, 0 otherwise. */ 21 | #ifdef USE_XRENDER 22 | char render; /**< 1 to use render, 0 otherwise. */ 23 | #endif 24 | 25 | } ImageNode; 26 | 27 | /** Load an image from a file. 28 | * @param fileName The file containing the image. 29 | * @param rwidth The preferred width. 30 | * @param rheight The preferred height. 31 | * @param preserveAspect Set to preserve image aspect when scaling. 32 | * @return A new image node (NULL if the image could not be loaded). 33 | */ 34 | ImageNode *LoadImage(const char *fileName, int rwidth, int rheight, 35 | char preserveAspect); 36 | 37 | /** Load an image from a Drawable. 38 | * @param pmap The drawable. 39 | * @param mask The mask (may be None). 40 | * @return a new image node (NULL if there were errors). 41 | */ 42 | ImageNode *LoadImageFromDrawable(Drawable pmap, Pixmap mask); 43 | 44 | /** Create an image node. 45 | * @param width The image width. 46 | * @param height The image height. 47 | * @param bitmap 1 if a bitmap, 0 otherwise. 48 | * @return A newly allocated image node. 49 | */ 50 | ImageNode *CreateImage(unsigned int width, unsigned int height, char bitmap); 51 | 52 | /** Destroy an image node. 53 | * @param image The image to destroy. 54 | */ 55 | void DestroyImage(ImageNode *image); 56 | 57 | #endif /* IMAGE_H */ 58 | -------------------------------------------------------------------------------- /src/button.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file button.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for rendering buttons. 7 | * 8 | */ 9 | 10 | #ifndef BUTTON_H 11 | #define BUTTON_H 12 | 13 | #include "font.h" 14 | #include "settings.h" 15 | 16 | struct IconNode; 17 | 18 | /** Button types. */ 19 | typedef unsigned char ButtonType; 20 | #define BUTTON_LABEL 0 /**< Label. */ 21 | #define BUTTON_MENU 1 /**< Menu item. */ 22 | #define BUTTON_MENU_ACTIVE 2 /**< Active menu item. */ 23 | #define BUTTON_TRAY 3 /**< Inactive tray button. */ 24 | #define BUTTON_TRAY_ACTIVE 4 /**< Active tray button. */ 25 | #define BUTTON_TASK 5 /**< Item in the task list. */ 26 | #define BUTTON_TASK_ACTIVE 6 /**< Active item in the task list. */ 27 | 28 | /** Data used for drawing a button. */ 29 | typedef struct { 30 | 31 | ButtonType type; /**< The type of button to draw. */ 32 | AlignmentType alignment; /**< Alignment of the button content. */ 33 | FontType font; /**< The font for button text. */ 34 | char fill; /**< Determine if we should fill. */ 35 | char border; /**< Determine if we should draw a border. */ 36 | 37 | Drawable drawable; /**< The place to put the button. */ 38 | 39 | int x, y; /**< The coordinates to render the button. */ 40 | int width, height; /**< The size of the button. */ 41 | 42 | struct IconNode *icon; /**< Icon used in the button. */ 43 | const char *text; /**< Text used in the button. */ 44 | 45 | } ButtonNode; 46 | 47 | /** Draw a button. 48 | * @param bp The button to draw. 49 | */ 50 | void DrawButton(ButtonNode *bp); 51 | 52 | /** Reset the contents of a ButtonNode structure. 53 | * @param bp The structure to reset. 54 | * @param d The drawable to use. 55 | */ 56 | void ResetButton(ButtonNode *bp, Drawable d); 57 | 58 | #endif /* BUTTON_H */ 59 | -------------------------------------------------------------------------------- /po/Makevars: -------------------------------------------------------------------------------- 1 | # Makefile variables for PO directory in any package using GNU gettext. 2 | 3 | # Usually the message domain is the same as the package name. 4 | DOMAIN = jwm 5 | 6 | # These two variables depend on the location of this directory. 7 | subdir = po 8 | top_builddir = .. 9 | 10 | # These options get passed to xgettext. 11 | XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ 12 | 13 | # This is the copyright holder that gets inserted into the header of the 14 | # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding 15 | # package. (Note that the msgstr strings, extracted from the package's 16 | # sources, belong to the copyright holder of the package.) Translators are 17 | # expected to transfer the copyright for their translations to this person 18 | # or entity, or to disclaim their copyright. The empty string stands for 19 | # the public domain; in this case the translators are expected to disclaim 20 | # their copyright. 21 | COPYRIGHT_HOLDER = Free Software Foundation, Inc. 22 | 23 | # This is the email address or URL to which the translators shall report 24 | # bugs in the untranslated strings: 25 | # - Strings which are not entire sentences, see the maintainer guidelines 26 | # in the GNU gettext documentation, section 'Preparing Strings'. 27 | # - Strings which use unclear terms or require additional context to be 28 | # understood. 29 | # - Strings which make invalid assumptions about notation of date, time or 30 | # money. 31 | # - Pluralisation problems. 32 | # - Incorrect English spelling. 33 | # - Incorrect formatting. 34 | # It can be your email address, or a mailing list address where translators 35 | # can write to without being subscribed, or the URL of a web page through 36 | # which the translators can contact you. 37 | MSGID_BUGS_ADDRESS = joewing@joewing.net 38 | 39 | # This is the list of locale categories, beyond LC_MESSAGES, for which the 40 | # message catalogs shall be used. It is usually empty. 41 | EXTRA_LOCALE_CATEGORIES = 42 | -------------------------------------------------------------------------------- /src/root.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file root.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Root menu functions. 7 | * 8 | */ 9 | 10 | #ifndef ROOT_H 11 | #define ROOT_H 12 | 13 | struct Menu; 14 | 15 | /*@{*/ 16 | void InitializeRootMenu(void); 17 | void StartupRootMenu(void); 18 | #define ShutdownRootMenu() (void)(0) 19 | void DestroyRootMenu(void); 20 | /*@}*/ 21 | 22 | /** Set the root menu to be used for the specified indexes. 23 | * @param indexes The indexes (ASCII string of '0' to '9'). 24 | * @param m The menu to use for the specified indexes. 25 | */ 26 | void SetRootMenu(const char *indexes, struct Menu *m); 27 | 28 | /** Get the index for a root menu character. 29 | * @return The menu index, -1 if not found. 30 | */ 31 | int GetRootMenuIndex(char ch); 32 | 33 | /** Get the index for a root menu string. 34 | * @return The menu index, -1 if not found. 35 | */ 36 | int GetRootMenuIndexFromString(const char *str); 37 | 38 | /** Determine if a root menu is defined for the specified index. 39 | * @return 1 if it is defined, 0 if not. 40 | */ 41 | char IsRootMenuDefined(int index); 42 | 43 | /** Get the size of a root menu. 44 | * @param index The root menu index. 45 | * @param width The width output. 46 | * @param height The height output. 47 | */ 48 | void GetRootMenuSize(int index, int *width, int *height); 49 | 50 | /** Show a root menu. 51 | * @param index The root menu index. 52 | * @param x The x-coordinate. 53 | * @param y The y-coordinate. 54 | * @param keyboard Set if this request came from a key binding. 55 | * @return 1 if a menu was displayed, 0 if not. 56 | */ 57 | char ShowRootMenu(int index, int x, int y, char keyboard); 58 | 59 | /** Restart the window manager. */ 60 | void Restart(void); 61 | 62 | /** Exit the window manager. 63 | * @param confirm 1 to confirm exit, 0 for immediate exit. 64 | */ 65 | void Exit(char confirm); 66 | 67 | /** Reload the menu. */ 68 | void ReloadMenu(void); 69 | 70 | #endif /* ROOT_H */ 71 | 72 | -------------------------------------------------------------------------------- /src/spacer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file spacer.h 3 | * @author Joe Wingbermuehle 4 | * @date 2011 5 | * 6 | * @brief Spacer tray component. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "main.h" 12 | #include "spacer.h" 13 | #include "tray.h" 14 | 15 | static void Create(TrayComponentType *cp); 16 | static void Destroy(TrayComponentType *cp); 17 | static void SetSize(TrayComponentType *cp, int width, int height); 18 | static void Resize(TrayComponentType *cp); 19 | 20 | /** Create a spacer tray component. */ 21 | TrayComponentType *CreateSpacer(int width, int height) 22 | { 23 | 24 | TrayComponentType *cp; 25 | 26 | if(JUNLIKELY(width < 0)) { 27 | width = 0; 28 | } 29 | if(JUNLIKELY(height < 0)) { 30 | height = 0; 31 | } 32 | 33 | cp = CreateTrayComponent(); 34 | cp->requestedWidth = width; 35 | cp->requestedHeight = height; 36 | 37 | cp->Create = Create; 38 | cp->Destroy = Destroy; 39 | cp->SetSize = SetSize; 40 | cp->Resize = Resize; 41 | 42 | return cp; 43 | 44 | } 45 | 46 | /** Set the size. */ 47 | void SetSize(TrayComponentType *cp, int width, int height) 48 | { 49 | if(width == 0) { 50 | cp->width = cp->requestedWidth; 51 | cp->height = height; 52 | } else { 53 | cp->width = width; 54 | cp->height = cp->requestedHeight; 55 | } 56 | } 57 | 58 | /** Initialize. */ 59 | void Create(TrayComponentType *cp) 60 | { 61 | cp->pixmap = JXCreatePixmap(display, rootWindow, cp->width, cp->height, 62 | rootDepth); 63 | ClearTrayDrawable(cp); 64 | } 65 | 66 | /** Resize. */ 67 | void Resize(TrayComponentType *cp) 68 | { 69 | if(cp->pixmap != None) { 70 | JXFreePixmap(display, cp->pixmap); 71 | } 72 | cp->pixmap = JXCreatePixmap(display, rootWindow, cp->width, cp->height, 73 | rootDepth); 74 | ClearTrayDrawable(cp); 75 | } 76 | 77 | /** Destroy. */ 78 | void Destroy(TrayComponentType *cp) 79 | { 80 | if(cp->pixmap != None) { 81 | JXFreePixmap(display, cp->pixmap); 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/font.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file font.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the font functions. 7 | * 8 | */ 9 | 10 | #ifndef FONT_H 11 | #define FONT_H 12 | 13 | #include "color.h" 14 | 15 | /** Enumeration of different components that use fonts. */ 16 | typedef unsigned char FontType; 17 | #define FONT_BORDER 0 18 | #define FONT_MENU 1 19 | #define FONT_POPUP 2 20 | #define FONT_TRAY 3 21 | #define FONT_PAGER 4 22 | #define FONT_CLOCK 5 23 | #define FONT_TASKLIST 6 24 | #define FONT_TRAYBUTTON 7 25 | #define FONT_COUNT 8 26 | 27 | void InitializeFonts(void); 28 | void StartupFonts(void); 29 | void ShutdownFonts(void); 30 | void DestroyFonts(void); 31 | 32 | /** Set the font to use for a component. 33 | * @param type The font component. 34 | * @param value The font to use. 35 | */ 36 | void SetFont(FontType type, const char *value); 37 | 38 | /** Render a string. 39 | * @param d The drawable on which to render the string. 40 | * @param font The font to use. 41 | * @param color The text color to use. 42 | * @param x The x-coordinate at which to render. 43 | * @param y The y-coordinate at which to render. 44 | * @param width The maximum width allowed. 45 | * @param str The string to render. 46 | */ 47 | void RenderString(Drawable d, FontType font, ColorType color, 48 | int x, int y, int width, const char *str); 49 | 50 | /** Get the width of a string. 51 | * @param ft The font used to determine the width. 52 | * @param str The string whose width to get. 53 | * @return The width of the string in pixels. 54 | */ 55 | int GetStringWidth(FontType ft, const char *str); 56 | 57 | /** Get the height of a string. 58 | * @param ft The font used to determine the height. 59 | * @return The height in pixels. 60 | */ 61 | int GetStringHeight(FontType ft); 62 | 63 | /** Convert a string from UTF-8. 64 | * Note that the string passed into this function is freed via Release 65 | * if the same string is not returned from the function. 66 | */ 67 | char *ConvertFromUTF8(char *str); 68 | 69 | #endif /* FONT_H */ 70 | 71 | -------------------------------------------------------------------------------- /src/default.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file default.c 3 | * @author Joe Wingbermuehle 4 | * @date 2017 5 | * 6 | * @brief Default configuration. 7 | * 8 | */ 9 | 10 | #include "default.h" 11 | 12 | const char * const BASE_CONFIG = 13 | "" 14 | "up" 15 | "down" 16 | "right" 17 | "left" 18 | "select" 19 | "escape" 20 | "nextstacked" 21 | "close" 22 | "move" 23 | "move" 24 | "window" 25 | "maximize" 26 | "window" 27 | "move" 28 | "window" 29 | "resize" 30 | "move" 31 | "window" 32 | "close" 33 | "move" 34 | "close" 35 | "maximize" 36 | "maxv" 37 | "maxh" 38 | "minimize" 39 | "move" 40 | "shade" 41 | "" 42 | ; 43 | 44 | const char * const DEFAULT_CONFIG = 45 | "" 46 | "" 47 | "xterm" 48 | "" 49 | "" 50 | "" 51 | "" 52 | "" 53 | "" 54 | "" 55 | ; 56 | -------------------------------------------------------------------------------- /src/event.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file event.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the event functions. 7 | * 8 | */ 9 | 10 | #ifndef EVENT_H 11 | #define EVENT_H 12 | 13 | struct TimeType; 14 | 15 | typedef void (*SignalCallback)(const struct TimeType *now, 16 | int x, int y, 17 | Window w, 18 | void *data); 19 | 20 | /** Last event time. */ 21 | extern Time eventTime; 22 | 23 | /** Wait for an event and process it. 24 | * @return 1 if there is an event to process, 0 otherwise. 25 | */ 26 | char WaitForEvent(XEvent *event); 27 | 28 | /** Process an event. 29 | * @param event The event to process. 30 | */ 31 | void ProcessEvent(XEvent *event); 32 | 33 | /** Descard excess button events. */ 34 | void DiscardButtonEvents(void); 35 | 36 | /** Discard excess motion events. 37 | * @param event The event to return. 38 | * @param w The window whose events to discard. 39 | */ 40 | void DiscardMotionEvents(XEvent *event, Window w); 41 | 42 | /** Discard excess key events. 43 | * @param event The event to return. 44 | * @param w The window whose events to discard. 45 | */ 46 | void DiscardKeyEvents(XEvent *event, Window w); 47 | 48 | /** Update the last event time. 49 | * @param event The event containing the time to use. 50 | */ 51 | void UpdateTime(const XEvent *event); 52 | 53 | /** Register a callback. 54 | * @param freq The frequency in milliseconds. 55 | * @param callback The callback function. 56 | * @param data Data to pass to the callback. 57 | */ 58 | void RegisterCallback(int freq, SignalCallback callback, void *data); 59 | 60 | /** Unregister a callback. 61 | * @param callback The callback to remove. 62 | * @param data The data passed to the register function. 63 | */ 64 | void UnregisterCallback(SignalCallback callback, void *data); 65 | 66 | /** Restack clients before waiting for an event. */ 67 | void RequireRestack(); 68 | 69 | /** Update the task bar before waiting for an event. */ 70 | void RequireTaskUpdate(); 71 | 72 | /** Update the pager before waiting for an event. */ 73 | void RequirePagerUpdate(); 74 | 75 | #endif /* EVENT_H */ 76 | 77 | -------------------------------------------------------------------------------- /src/desktop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file desktop.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the desktop management functions. 7 | * 8 | */ 9 | 10 | #ifndef DESKTOP_H 11 | #define DESKTOP_H 12 | 13 | struct MenuType; 14 | 15 | /*@{*/ 16 | #define InitializeDesktops() (void)(0) 17 | void StartupDesktops(void); 18 | #define ShutdownDesktops() (void)(0) 19 | void DestroyDesktops(void); 20 | /*@}*/ 21 | 22 | /** Get a relative desktop. */ 23 | unsigned int GetRightDesktop(unsigned int desktop); 24 | unsigned int GetLeftDesktop(unsigned int desktop); 25 | unsigned int GetAboveDesktop(unsigned int desktop); 26 | unsigned int GetBelowDesktop(unsigned int desktop); 27 | 28 | /** Switch to a relative desktop. */ 29 | char RightDesktop(void); 30 | char LeftDesktop(void); 31 | char AboveDesktop(void); 32 | char BelowDesktop(void); 33 | 34 | /** Switch to a specific desktop. 35 | * @param desktop The desktop to show (0 based). 36 | */ 37 | void ChangeDesktop(unsigned int desktop); 38 | 39 | /** Toggle the "show desktop" state. 40 | * This will either minimize or restore all items on the current desktop. 41 | */ 42 | void ShowDesktop(void); 43 | 44 | /** Create a menu containing a list of desktops. 45 | * @param mask A bit mask of desktops to highlight. 46 | * @param context Context to pass the action handler. 47 | * @return A menu containing all the desktops. 48 | */ 49 | struct Menu *CreateDesktopMenu(unsigned int mask, void *context); 50 | 51 | /** Create a menu containing a list of desktops. 52 | * @param mask Mask to OR onto the action. 53 | * @param context Context to pass the action handler. 54 | * @return A menu containing all the desktops. 55 | */ 56 | struct Menu *CreateSendtoMenu(unsigned char mask, void *context); 57 | 58 | /** Set the name of a desktop. 59 | * This is called before startup. 60 | * @param desktop The desktop to name (0 based). 61 | * @param str The name to assign. 62 | */ 63 | void SetDesktopName(unsigned int desktop, const char *str); 64 | 65 | /** Get the name of a desktop. 66 | * @param desktop The desktop (0 based). 67 | * @return The name of the desktop. 68 | */ 69 | const char *GetDesktopName(unsigned int desktop); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/help.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file help.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for displaying information about JWM. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "help.h" 12 | 13 | static void DisplayUsage(void); 14 | 15 | /** Display program name, version, and compiled options . */ 16 | void DisplayAbout(void) 17 | { 18 | printf("JWM v" PACKAGE_VERSION " by Joe Wingbermuehle\n"); 19 | DisplayCompileOptions(); 20 | } 21 | 22 | /** Display compiled options. */ 23 | void DisplayCompileOptions(void) 24 | { 25 | printf("compiled options: " 26 | #ifndef DISABLE_CONFIRM 27 | "confirm " 28 | #endif 29 | #ifdef DEBUG 30 | "debug " 31 | #endif 32 | #ifdef USE_FRIBIDI 33 | "fribidi " 34 | #endif 35 | #ifdef USE_ICONS 36 | "icons " 37 | #endif 38 | #ifdef USE_JPEG 39 | "jpeg " 40 | #endif 41 | #ifdef ENABLE_NLS 42 | "nls " 43 | #endif 44 | #ifdef USE_PNG 45 | "png " 46 | #endif 47 | #ifdef USE_SHAPE 48 | "shape " 49 | #endif 50 | #if defined(USE_CAIRO) && defined(USE_RSVG) 51 | "svg " 52 | #endif 53 | #ifdef USE_XBM 54 | "xbm " 55 | #endif 56 | #ifdef USE_XFT 57 | "xft " 58 | #endif 59 | #ifdef USE_XINERAMA 60 | "xinerama " 61 | #endif 62 | #ifdef USE_XPM 63 | "xpm " 64 | #endif 65 | #ifdef USE_XRENDER 66 | "xrender " 67 | #endif 68 | "\nsystem configuration: " SYSTEM_CONFIG "\n"); 69 | } 70 | 71 | /** Display all help. */ 72 | void DisplayHelp(void) 73 | { 74 | DisplayUsage(); 75 | printf(" -display X Set the X display to use\n" 76 | " -exit Exit JWM (send _JWM_EXIT to the root)\n" 77 | " -f file Use specified configuration file\n" 78 | " -h Display this help message\n" 79 | " -p Parse the configuration file and exit\n" 80 | " -reload Reload menu (send _JWM_RELOAD to the root)\n" 81 | " -restart Restart JWM (send _JWM_RESTART to the root)\n" 82 | " -v Display version information\n"); 83 | } 84 | 85 | /** Display program usage information. */ 86 | void DisplayUsage(void) 87 | { 88 | DisplayAbout(); 89 | printf("usage: jwm [ options ]\n"); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/binding.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file binding.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2017 5 | * 6 | * @brief Header for mouse/key bindings. 7 | * 8 | */ 9 | 10 | #ifndef KEY_H 11 | #define KEY_H 12 | 13 | #include "action.h" 14 | #include "settings.h" 15 | 16 | void InitializeBindings(void); 17 | void StartupBindings(void); 18 | void ShutdownBindings(void); 19 | void DestroyBindings(void); 20 | 21 | /** Mask of 'lock' keys. */ 22 | extern unsigned int lockMask; 23 | 24 | /** Get the action to take from a key event. */ 25 | ActionType GetKey(MouseContextType context, unsigned state, int code); 26 | 27 | /** Parse a modifier string. 28 | * @param str The modifier string. 29 | * @return The modifier mask. 30 | */ 31 | unsigned int ParseModifierString(const char *str); 32 | 33 | /** Insert a key binding. 34 | * @param action The action. 35 | * @param modifiers The modifier mask. 36 | * @param stroke The key stroke (not needed if code given). 37 | * @param code The key code (not needed if stroke given). 38 | * @param command Extra parameter needed for some key binding types. 39 | */ 40 | void InsertBinding(ActionType action, const char *modifiers, 41 | const char *stroke, const char *code, const char *command); 42 | 43 | /** Insert a mouse binding. 44 | * A mouse binding maps a mouse click in a certain context to an action. 45 | * @param button The mouse button. 46 | * @param mask The modifier mask. 47 | * @param context The mouse context. 48 | * @param action The action binding. 49 | * @param command Extra parameter needed for some bindings. 50 | */ 51 | void InsertMouseBinding( 52 | int button, 53 | const char *mask, 54 | MouseContextType context, 55 | ActionType action, 56 | const char *command); 57 | 58 | /** Run a command caused by a key binding. */ 59 | void RunKeyCommand(MouseContextType context, unsigned state, int code); 60 | 61 | /** Show a root menu caused by a key binding. 62 | * @param event The event that caused the menu to be shown. 63 | */ 64 | void ShowKeyMenu(MouseContextType context, unsigned state, int code); 65 | 66 | /** Validate key bindings. 67 | * This will log an error if an invalid key binding is found. 68 | * This is called after parsing the configuration file. 69 | */ 70 | void ValidateKeys(void); 71 | 72 | #endif /* KEY_H */ 73 | -------------------------------------------------------------------------------- /src/cursor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cursor.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the cursor functions. 7 | * 8 | */ 9 | 10 | #ifndef CURSOR_H 11 | #define CURSOR_H 12 | 13 | #include "border.h" 14 | 15 | /*@{*/ 16 | #define InitializeCursors() (void)(0) 17 | void StartupCursors(void); 18 | void ShutdownCursors(void); 19 | #define DestroyCursors() (void)(0) 20 | /*@}*/ 21 | 22 | /** Grab the mouse for resizing a window. 23 | * @param action The resize action. 24 | * @return 1 on success, 0 on failure. 25 | */ 26 | char GrabMouseForResize(MouseContextType context); 27 | 28 | /** Grab the mouse for moving a window. 29 | * @return 1 on success, 0 on failure. 30 | */ 31 | char GrabMouseForMove(void); 32 | 33 | /** Grab the mouse. 34 | * @return 1 on success, 0 on failure. 35 | */ 36 | char GrabMouse(Window w); 37 | 38 | /** Grab the mouse to select a window. 39 | * @return 1 on success, 0 on failure. 40 | */ 41 | char GrabMouseForChoose(void); 42 | 43 | /** Get the cursor to use given a border action. 44 | * @param action The border action. 45 | * @return The cursor to use. 46 | */ 47 | Cursor GetFrameCursor(MouseContextType action); 48 | 49 | /** Move the mouse cursor. 50 | * @param win The window to act as an origin for the coordinates. 51 | * @param x The x-coordinate. 52 | * @param y The y-coordinate. 53 | */ 54 | void MoveMouse(Window win, int x, int y); 55 | 56 | /** Set the current mouse position. 57 | * @param x The x-coordinate (relative to the current desktop). 58 | * @param y The y-coordinate (relative to the current desktop). 59 | * @param w The window under the mouse. 60 | */ 61 | void SetMousePosition(int x, int y, Window w); 62 | 63 | /** Get the current mouse position. 64 | * @param x Location to store the x-coordinate. 65 | * @param y Location to store the y-coordinate. 66 | * @param w The window under the mouse. 67 | */ 68 | void GetMousePosition(int *x, int *y, Window *w); 69 | 70 | /** Get a mask of the current mouse buttons pressed. 71 | * @return A mask of the current mouse buttons pressed. 72 | */ 73 | unsigned int GetMouseMask(void); 74 | 75 | /** Reset to the default cursor on a window. 76 | * @param w The window whose cursor to change. 77 | */ 78 | void SetDefaultCursor(Window w); 79 | 80 | #endif /* CURSOR_H */ 81 | 82 | -------------------------------------------------------------------------------- /src/gradient.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gradient.c 3 | * @author Joe Wingbermuehle 4 | * @date 2006 5 | * 6 | * @brief Gradient fill functions. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "gradient.h" 12 | #include "color.h" 13 | #include "main.h" 14 | 15 | /** Draw a horizontal gradient. */ 16 | void DrawHorizontalGradient(Drawable d, GC g, 17 | long fromColor, long toColor, 18 | int x, int y, 19 | unsigned int width, unsigned int height) 20 | { 21 | 22 | const int shift = 15; 23 | unsigned int line; 24 | XColor colors[2]; 25 | int red, green, blue; 26 | int ared, agreen, ablue; 27 | int bred, bgreen, bblue; 28 | int redStep, greenStep, blueStep; 29 | 30 | /* Return if there's nothing to do. */ 31 | if(width == 0 || height == 0) { 32 | return; 33 | } 34 | 35 | /* Here we assume that the background was filled elsewhere. */ 36 | if(fromColor == toColor) { 37 | return; 38 | } 39 | 40 | /* Query the from/to colors. */ 41 | colors[0].pixel = fromColor; 42 | colors[1].pixel = toColor; 43 | JXQueryColors(display, rootColormap, colors, 2); 44 | 45 | /* Set the "from" color. */ 46 | ared = (unsigned int)colors[0].red << shift; 47 | agreen = (unsigned int)colors[0].green << shift; 48 | ablue = (unsigned int)colors[0].blue << shift; 49 | 50 | /* Set the "to" color. */ 51 | bred = (unsigned int)colors[1].red << shift; 52 | bgreen = (unsigned int)colors[1].green << shift; 53 | bblue = (unsigned int)colors[1].blue << shift; 54 | 55 | /* Determine the step. */ 56 | redStep = (bred - ared) / (int)height; 57 | greenStep = (bgreen - agreen) / (int)height; 58 | blueStep = (bblue - ablue) / (int)height; 59 | 60 | /* Loop over each line. */ 61 | red = ared; 62 | blue = ablue; 63 | green = agreen; 64 | for(line = 0; line < height; line++) { 65 | 66 | /* Determine the color for this line. */ 67 | colors[0].red = (unsigned short)(red >> shift); 68 | colors[0].green = (unsigned short)(green >> shift); 69 | colors[0].blue = (unsigned short)(blue >> shift); 70 | 71 | GetColor(&colors[0]); 72 | 73 | /* Draw the line. */ 74 | JXSetForeground(display, g, colors[0].pixel); 75 | JXDrawLine(display, d, g, x, y + line, x + width - 1, y + line); 76 | 77 | red += redStep; 78 | green += greenStep; 79 | blue += blueStep; 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/misc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file misc.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Miscellaneous functions and macros. 7 | * 8 | */ 9 | 10 | #ifndef MISC_H 11 | #define MISC_H 12 | 13 | /** Mapping between a string and integer. 14 | * This is used with FindValue and FindKey. 15 | * Note that mappings must be sorted. 16 | */ 17 | typedef struct { 18 | const char *key; 19 | int value; 20 | } StringMappingType; 21 | 22 | /** Get the length of an array. */ 23 | #define ARRAY_LENGTH( a ) (sizeof(a) / sizeof(a[0])) 24 | 25 | /** Return the minimum of two values. */ 26 | #define Min( x, y ) ( (x) > (y) ? (y) : (x) ) 27 | 28 | /** Return the maximum of two values. */ 29 | #define Max( x, y ) ( (x) > (y) ? (x) : (y) ) 30 | 31 | /** Determine if a character is a space character. 32 | * @param ch The character to check. 33 | * @param lineNumber The line number to update. 34 | */ 35 | char IsSpace(char ch, unsigned int *lineNumber); 36 | 37 | /** Perform shell-like macro path expansion. 38 | * @param path The path to expand (possibly reallocated). 39 | */ 40 | void ExpandPath(char **path); 41 | 42 | /** Trim leading and trailing whitespace from a string. 43 | * @param str The string to trim. 44 | */ 45 | void Trim(char *str); 46 | 47 | /** Copy a string. 48 | * Note that NULL is accepted. When provided NULL, NULL will be returned. 49 | * @param str The string to copy. 50 | * @return A copy of the string. 51 | */ 52 | char *CopyString(const char *str); 53 | 54 | /** Read a float in a locale-independent way. 55 | * @param str The string containing the float. 56 | * @return The float. 57 | */ 58 | float ParseFloat(const char *str); 59 | 60 | /** Find a value in a string mapping. 61 | * This uses binary search. 62 | * @param mapping The mapping. 63 | * @param key The item to find. 64 | * @param count The number of items in the mapping. 65 | * @return The value or -1 if not found. 66 | */ 67 | int FindValue(const StringMappingType *mapping, int count, const char *key); 68 | 69 | /** Find a key in a string mapping. 70 | * This uses linear search. 71 | * @param mapping The mapping. 72 | * @param value The value to find. 73 | * @param count The number of items in the mapping. 74 | * @return The key or NULL if not found. 75 | */ 76 | const char *FindKey(const StringMappingType *mapping, int count, int value); 77 | 78 | /** Case insensitive string compare. */ 79 | int StrCmpNoCase(const char *a, const char *b); 80 | 81 | #endif /* MISC_H */ 82 | -------------------------------------------------------------------------------- /contrib/jwm.xbm: -------------------------------------------------------------------------------- 1 | #define jwm_width 68 2 | #define jwm_height 42 3 | static unsigned char jwm_bits[] = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 7 | 0x00, 0xC0, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0x7F, 8 | 0x80, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, 9 | 0x7F, 0x00, 0x00, 0x00, 0x40, 0xFF, 0x40, 0xFF, 0x40, 0xFF, 0x00, 0x00, 10 | 0x00, 0x40, 0xFF, 0x40, 0xFF, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x40, 0xFF, 11 | 0x20, 0xFF, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x40, 0xFF, 0x20, 0xFF, 0x20, 12 | 0xFF, 0x00, 0x00, 0x00, 0x40, 0xFE, 0x21, 0xFE, 0x21, 0xFE, 0x01, 0x00, 13 | 0x00, 0x40, 0xFE, 0x11, 0xFE, 0x11, 0xFE, 0x01, 0x00, 0x00, 0x40, 0xFE, 14 | 0x11, 0xFE, 0x11, 0xFE, 0x01, 0x00, 0x00, 0x40, 0xFE, 0x11, 0xFE, 0x11, 15 | 0xFE, 0x01, 0x00, 0x00, 0x40, 0xFC, 0x0B, 0xFC, 0x0B, 0xFC, 0x03, 0x00, 16 | 0x00, 0x40, 0xFC, 0x0B, 0xFC, 0x0B, 0xFC, 0x03, 0x00, 0x00, 0x40, 0xFC, 17 | 0x0B, 0xFC, 0x0B, 0xFC, 0x03, 0x00, 0x00, 0x40, 0xFC, 0x07, 0xFC, 0x07, 18 | 0xFC, 0x03, 0x00, 0x00, 0x40, 0xF8, 0x07, 0xFC, 0x07, 0xFC, 0x07, 0x00, 19 | 0x00, 0x40, 0xF8, 0x07, 0xFC, 0x07, 0xFC, 0x07, 0x00, 0x00, 0x40, 0xF8, 20 | 0x07, 0xFC, 0x07, 0xFC, 0x07, 0x00, 0x00, 0x40, 0xF8, 0x07, 0xFC, 0x07, 21 | 0xFC, 0x07, 0x00, 0x00, 0x40, 0xF0, 0x0F, 0xF2, 0x0F, 0xF2, 0x0F, 0x00, 22 | 0x00, 0x40, 0xF0, 0x0F, 0xF2, 0x0F, 0xF2, 0x0F, 0x00, 0x00, 0x40, 0xF0, 23 | 0x0F, 0xF2, 0x0F, 0xF2, 0x0F, 0x00, 0x00, 0x40, 0xF0, 0x0F, 0xF2, 0x0F, 24 | 0xF2, 0x0F, 0x00, 0x00, 0x40, 0xE0, 0x1F, 0xE1, 0x1F, 0xE1, 0x1F, 0x00, 25 | 0x00, 0x40, 0xE0, 0x1F, 0xE1, 0x1F, 0xE1, 0x1F, 0x00, 0x20, 0x20, 0xE0, 26 | 0x1F, 0xE1, 0x1F, 0xE1, 0x1F, 0x00, 0x60, 0x18, 0xE0, 0x1F, 0xE1, 0x1F, 27 | 0xE1, 0x1F, 0x00, 0x90, 0x07, 0xE0, 0xBF, 0xC0, 0xBF, 0xC0, 0x3F, 0x00, 28 | 0x10, 0x00, 0xD0, 0xBF, 0xC0, 0xBF, 0xC0, 0x3F, 0x00, 0x10, 0x00, 0xD0, 29 | 0xBF, 0xC0, 0xBF, 0xC0, 0x3F, 0x00, 0x08, 0x00, 0xC8, 0xBF, 0xC0, 0xBF, 30 | 0xC0, 0x3F, 0x00, 0x08, 0x00, 0x84, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x00, 31 | 0x08, 0x00, 0x83, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x00, 0x30, 0xC0, 0x80, 32 | 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x00, 0xC0, 0x3F, 0x80, 0x7F, 0x80, 0x7F, 33 | 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 36 | -------------------------------------------------------------------------------- /src/timing.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file timing.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Timing functions. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "timing.h" 12 | 13 | static const unsigned long MAX_TIME_SECONDS = 60; 14 | 15 | /** Get the current time in milliseconds since midnight 1970-01-01 UTC. */ 16 | void GetCurrentTime(TimeType *t) 17 | { 18 | struct timeval val; 19 | gettimeofday(&val, NULL); 20 | t->seconds = val.tv_sec; 21 | t->ms = val.tv_usec / 1000; 22 | } 23 | 24 | /** Get the absolute difference between two times in milliseconds. 25 | * If the difference is larger than a MAX_TIME_SECONDS, then 26 | * MAX_TIME_SECONDS will be returned. 27 | * Note that the times must be normalized. 28 | */ 29 | unsigned long GetTimeDifference(const TimeType *t1, const TimeType *t2) 30 | { 31 | unsigned long deltaSeconds; 32 | int deltaMs; 33 | 34 | if(t1->seconds > t2->seconds) { 35 | deltaSeconds = t1->seconds - t2->seconds; 36 | deltaMs = t1->ms - t2->ms; 37 | } else if(t1->seconds < t2->seconds) { 38 | deltaSeconds = t2->seconds - t1->seconds; 39 | deltaMs = t2->ms - t1->ms; 40 | } else if(t1->ms > t2->ms) { 41 | deltaSeconds = 0; 42 | deltaMs = t1->ms - t2->ms; 43 | } else { 44 | deltaSeconds = 0; 45 | deltaMs = t2->ms - t1->ms; 46 | } 47 | 48 | if(JUNLIKELY(deltaSeconds > MAX_TIME_SECONDS)) { 49 | return MAX_TIME_SECONDS * 1000; 50 | } else { 51 | return deltaSeconds * 1000 + deltaMs; 52 | } 53 | 54 | } 55 | 56 | /** Get the current time. */ 57 | const char *GetTimeString(const char *format, const char *zone) 58 | { 59 | static char saveTZ[256]; 60 | static char newTZ[256]; 61 | static char str[80]; 62 | time_t t; 63 | 64 | time(&t); 65 | if(zone) { 66 | const char *oldTZ = getenv("TZ"); 67 | if(oldTZ) { 68 | snprintf(saveTZ, sizeof(saveTZ), "TZ=%s", oldTZ); 69 | #ifndef HAVE_UNSETENV 70 | } else { 71 | strcpy(saveTZ, "TZ="); 72 | #endif 73 | } 74 | snprintf(newTZ, sizeof(newTZ), "TZ=%s", zone); 75 | putenv(newTZ); 76 | tzset(); 77 | strftime(str, sizeof(str), format, localtime(&t)); 78 | #ifdef HAVE_UNSETENV 79 | if(oldTZ) { 80 | putenv(saveTZ); 81 | } else { 82 | unsetenv("TZ"); 83 | } 84 | #else 85 | putenv(saveTZ); 86 | #endif 87 | } else { 88 | strftime(str, sizeof(str), format, localtime(&t)); 89 | } 90 | 91 | return str; 92 | } 93 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file error.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Error handling functions. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "error.h" 12 | #include "main.h" 13 | 14 | /** Log a fatal error and exit. */ 15 | void FatalError(const char *str, ...) { 16 | 17 | va_list ap; 18 | va_start(ap, str); 19 | 20 | Assert(str); 21 | 22 | fprintf(stderr, _("JWM: error: ")); 23 | vfprintf(stderr, str, ap); 24 | fprintf(stderr, "\n"); 25 | 26 | va_end(ap); 27 | 28 | exit(1); 29 | 30 | } 31 | 32 | /** Log a warning. */ 33 | void Warning(const char *str, ...) { 34 | 35 | va_list ap; 36 | va_start(ap, str); 37 | 38 | Assert(str); 39 | 40 | WarningVA(NULL, str, ap); 41 | 42 | va_end(ap); 43 | 44 | } 45 | 46 | /** Log a warning. */ 47 | void WarningVA(const char *part, const char *str, va_list ap) { 48 | 49 | Assert(str); 50 | 51 | fprintf(stderr, _("JWM: warning: ")); 52 | if(part) { 53 | fprintf(stderr, "%s: ", part); 54 | } 55 | vfprintf(stderr, str, ap); 56 | fprintf(stderr, "\n"); 57 | 58 | } 59 | 60 | /** Callback to handle errors from Xlib. 61 | * Note that if debug output is directed to an X terminal, emitting too 62 | * much output can cause a dead lock (this happens on HP-UX). Therefore 63 | * ShowCheckpoint isn't used by default. 64 | */ 65 | int ErrorHandler(Display *d, XErrorEvent *e) { 66 | 67 | #ifdef DEBUG 68 | 69 | char buffer[64]; 70 | char code[32]; 71 | 72 | #endif 73 | 74 | if(initializing) { 75 | if(e->request_code == X_ChangeWindowAttributes 76 | && e->error_code == BadAccess) { 77 | FatalError(_("display is already managed")); 78 | } 79 | } 80 | 81 | #ifdef DEBUG 82 | 83 | if(!e) { 84 | fprintf(stderr, "XError: [no information]\n"); 85 | return 0; 86 | } 87 | 88 | XGetErrorText(display, e->error_code, buffer, sizeof(buffer)); 89 | Debug("XError: %s", buffer); 90 | 91 | snprintf(code, sizeof(code), "%d", e->request_code); 92 | XGetErrorDatabaseText(display, "XRequest", code, "?", 93 | buffer, sizeof(buffer)); 94 | Debug(" Request Code: %d (%s)", e->request_code, buffer); 95 | Debug(" Minor Code: %d", e->minor_code); 96 | Debug(" Resource ID: 0x%lx", (unsigned long)e->resourceid); 97 | Debug(" Error Serial: %lu", (unsigned long)e->serial); 98 | 99 | #if 1 100 | ShowCheckpoint(); 101 | #endif 102 | 103 | #endif 104 | 105 | return 0; 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/place.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file place.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for client placement functions. 7 | * 8 | */ 9 | 10 | #ifndef PLACE_H 11 | #define PLACE_H 12 | 13 | #include "client.h" 14 | 15 | struct ScreenType; 16 | struct TrayType; 17 | 18 | /** Bounding box. */ 19 | typedef struct BoundingBox { 20 | int x; /**< x-coordinate of the bounding box. */ 21 | int y; /**< y-coordinate of the bounding box. */ 22 | int width; /**< Width of the bounding box. */ 23 | int height; /**< Height of the bounding box. */ 24 | } BoundingBox; 25 | 26 | /*@{*/ 27 | #define InitializePlacement() (void)(0) 28 | void StartupPlacement(void); 29 | void ShutdownPlacement(void); 30 | #define DestroyPlacement() (void)(0) 31 | /*@}*/ 32 | 33 | /** Remove struts associated with a client. 34 | * @param np The client. 35 | */ 36 | void RemoveClientStrut(ClientNode *np); 37 | 38 | /** Read struts associated with a client. 39 | * @param np The client. 40 | */ 41 | void ReadClientStrut(ClientNode *np); 42 | 43 | /** Place a client on the screen. 44 | * @param np The client to place. 45 | * @param alreadyMapped 1 if already mapped, 0 if unmapped. 46 | */ 47 | void PlaceClient(ClientNode *np, char alreadyMapped); 48 | 49 | /** Place a maximized client on the screen. 50 | * @param np The client to place. 51 | * @param flags The type of maximization to perform. 52 | */ 53 | void PlaceMaximizedClient(ClientNode *np, MaxFlags flags); 54 | 55 | /** Move a client window for a border. 56 | * @param np The client. 57 | * @param negate 0 to gravitate for a border, 1 to gravitate for no border. 58 | */ 59 | void GravitateClient(ClientNode *np, char negate); 60 | 61 | /** Get the x and y deltas for gravitating a client. 62 | * @param np The client. 63 | * @param gravity The gravity to use. 64 | * @param x Location to store the x delta. 65 | * @param y Location to store the y delta. 66 | */ 67 | void GetGravityDelta(const ClientNode *np, int gravity, int *x, int *y); 68 | 69 | /** Constrain the size of a client. 70 | * @param np The client. 71 | * @return 1 if the size changed, 0 otherwise. 72 | */ 73 | char ConstrainSize(ClientNode *np); 74 | 75 | /** Constrain the position of a client. 76 | * @param np The client. 77 | */ 78 | void ConstrainPosition(ClientNode *np); 79 | 80 | /** Get the bounding box for the screen. 81 | * @param sp A pointer to the screen whose bounds to get. 82 | * @param box The bounding box for the screen. 83 | */ 84 | void GetScreenBounds(const struct ScreenType *sp, BoundingBox *box); 85 | 86 | #endif /* PLACE_H */ 87 | 88 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file debug.h 3 | * @author Joe Wingbermuehle 4 | * @date 2003-2006 5 | * 6 | * @brief Header for the debug functions. 7 | * 8 | */ 9 | 10 | #ifndef DEBUG_H 11 | #define DEBUG_H 12 | 13 | #include "../config.h" 14 | 15 | #ifndef MAKE_DEPEND 16 | # include 17 | # ifdef HAVE_ALLOCA_H 18 | # include 19 | # elif defined __GNUC__ 20 | # define alloca __builtin_alloca 21 | # elif defined _AIX 22 | # define alloca __alloca 23 | # elif defined _MSC_VER 24 | # include 25 | # define alloca _alloca 26 | # elif defined HAVE_ALLOCA 27 | void *alloca(size_t); 28 | # endif 29 | #endif /* MAKE_DEPEND */ 30 | 31 | void Debug(const char *str, ...); 32 | 33 | #ifdef HAVE_ALLOCA 34 | 35 | # define AllocateStack( x ) alloca( x ) 36 | # define ReleaseStack( x ) ((void)0) 37 | 38 | #else 39 | 40 | # define AllocateStack( x ) Allocate( x ) 41 | # define ReleaseStack( x ) Release( x ) 42 | 43 | #endif 44 | 45 | #ifdef DEBUG 46 | 47 | # define Assert( x ) \ 48 | if(!( x )) { \ 49 | Debug("ASSERT FAILED: %s[%u]", __FILE__, __LINE__ ); \ 50 | abort(); \ 51 | } 52 | 53 | # define SetCheckpoint() \ 54 | DEBUG_SetCheckpoint( __FILE__, __LINE__ ) 55 | # define ShowCheckpoint() \ 56 | DEBUG_ShowCheckpoint() 57 | 58 | # define StartDebug() \ 59 | DEBUG_StartDebug( __FILE__, __LINE__ ) 60 | # define StopDebug() \ 61 | DEBUG_StopDebug( __FILE__, __LINE__ ) 62 | 63 | # define Allocate( x ) \ 64 | DEBUG_Allocate( (x), __FILE__, __LINE__ ) 65 | # define Reallocate( x, y ) \ 66 | DEBUG_Reallocate( (x), (y), __FILE__, __LINE__ ) 67 | # define Release( x ) \ 68 | DEBUG_Release( (void*)(& x), __FILE__, __LINE__ ) 69 | 70 | void DEBUG_SetCheckpoint(const char*, unsigned int); 71 | void DEBUG_ShowCheckpoint(void); 72 | 73 | void DEBUG_StartDebug(const char*, unsigned int); 74 | void DEBUG_StopDebug(const char*, unsigned int); 75 | 76 | void *DEBUG_Allocate(size_t, const char*, unsigned int); 77 | void *DEBUG_Reallocate(void*, size_t, const char*, unsigned int); 78 | void DEBUG_Release(void**, const char*, unsigned int); 79 | 80 | #else /* DEBUG */ 81 | 82 | # define Assert( x ) ((void)0) 83 | 84 | # define SetCheckpoint() ((void)0) 85 | # define ShowCheckpoint() ((void)0) 86 | 87 | # define StartDebug() ((void)0) 88 | # define StopDebug() ((void)0) 89 | 90 | # define Allocate( x ) malloc( (x) ) 91 | # define Reallocate( x, y ) realloc( (x), (y) ) 92 | # define Release( x ) free( (x) ) 93 | 94 | #endif /* DEBUG */ 95 | 96 | #endif /* DEBUG_H */ 97 | 98 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | PACKAGE = jwm 2 | SYSCONF = $(DESTDIR)@SYSCONF@ 3 | MANDIR = $(DESTDIR)@MANDIR@ 4 | ICONDIR = $(DESTDIR)@ICONDIR@ 5 | VERSION ?= @VERSION@ 6 | USE_NLS = @USE_NLS@ 7 | 8 | all: 9 | $(MAKE) -C src all 10 | $(MAKE) -C po all 11 | 12 | install: all 13 | $(MAKE) -C src install 14 | $(MAKE) -C po install 15 | $(MAKE) -C contrib install 16 | install -d -m 0755 $(SYSCONF) 17 | install -m 644 example.jwmrc $(SYSCONF)/system.jwmrc 18 | install -d -m 0755 $(MANDIR)/man1 19 | install -m 644 jwm.1 $(MANDIR)/man1/jwm.1 20 | 21 | install-strip: all install-conf 22 | $(MAKE) -C src install-strip 23 | $(MAKE) -C po install-strip 24 | $(MAKE) -C contrib install 25 | install -d -m 0755 $(SYSCONF) 26 | install -m 644 example.jwmrc $(SYSCONF)/system.jwmrc 27 | install -d -m 0755 $(MANDIR)/man1 28 | install -m 644 jwm.1 $(MANDIR)/man1/jwm.1 29 | install -d -m 0755 $(ICONDIR) 30 | 31 | uninstall: 32 | $(MAKE) -C src uninstall 33 | $(MAKE) -C po uninstall 34 | $(MAKE) -C contrib uninstall 35 | rm -f $(SYSCONF)/system.jwmrc 36 | rm -f $(MANDIR)/man1/jwm.1 37 | 38 | tarball: 39 | rm -f ../jwm-$(VERSION).tar.xz ; 40 | rm -fr ../jwm-$(VERSION) ; 41 | cp -r ../jwm ../jwm-$(VERSION) ; 42 | (cd ../jwm-$(VERSION) && $(MAKE) distclean) ; 43 | (cd .. && tar -cf jwm-$(VERSION).tar jwm-$(VERSION)); 44 | rm -fr ../jwm-$(VERSION) ; 45 | (cd .. && xz jwm-$(VERSION).tar) 46 | 47 | clean: 48 | (cd src && $(MAKE) clean) 49 | (cd po && $(MAKE) clean) 50 | rm -rf doc 51 | 52 | distclean: clean 53 | rm -f *[~#] config.cache config.log config.status config.h 54 | rm -f Makefile src/Makefile jwm.1 55 | rm -fr autom4te.cache 56 | rm -f Makefile.bak src/Makefile.bak 57 | rm -fr .git .gitignore 58 | 59 | check-gettext: 60 | @if test x$(USE_NLS) != "xyes" ; then \ 61 | echo "Missing gettext. Rerun configure and check for" \ 62 | "'checking whether to use NLS... yes'!" ; exit 1 ; fi 63 | 64 | update-po: check-gettext 65 | @find src/ -name "*.c" -print | sort > po/POTFILES.in.2 ; \ 66 | if diff po/POTFILES.in po/POTFILES.in.2 >/dev/null 2>&1 ; then \ 67 | rm -f po/POTFILES.in.2 ; \ 68 | else \ 69 | mv po/POTFILES.in.2 po/POTFILES.in ; \ 70 | fi 71 | cd po && $(MAKE) $(AM_MAKEFLAGS) update-po 72 | 73 | update-gmo: check-gettext 74 | cd po && $(MAKE) $(AM_MAKEFLAGS) update-gmo 75 | 76 | force-update-gmo: check-gettext 77 | touch po/*.po 78 | cd po && $(MAKE) $(AM_MAKEFLAGS) update-gmo 79 | 80 | force-update-gmo-%: check-gettext 81 | @language=`echo $@ | sed s/force-update-gmo-//` ; \ 82 | if test ! -f po/$$language.po ; then \ 83 | echo "file po/$$language.po does not exist" ; exit 1 ; fi ; \ 84 | touch po/$$language.po ; \ 85 | cd po && $(MAKE) $(AM_MAKEFLAGS) update-gmo 86 | 87 | .PHONY: check-gettext update-po update-gmo force-update-gmo 88 | -------------------------------------------------------------------------------- /README.upgrading: -------------------------------------------------------------------------------- 1 | 2 | This file describes configuration changes required for upgrading to newer 3 | versions of JWM. In general, JWM revisions (changes to the third number) 4 | will not contain changes that break a configuration, though minor 5 | modifications may be included if using an old configuration with the new 6 | version will not cause problems. New configuration options are not 7 | described. See the release notes at http://joewing.net/projects/jwm/ for 8 | more information. 9 | 10 | Changes from 2.3.7 to 2.4.0 11 | ============================================================================== 12 | * Mouse bindings must now be specified explicitly. 13 | * The group and list attributes on TrayStyle have been moved to 14 | TaskListStyle. 15 | 16 | Changes from 2.3.6 to 2.3.7 17 | ============================================================================== 18 | * No breaking changes. 19 | 20 | Changes from 2.3.5 to 2.3.6 21 | ============================================================================== 22 | * No breaking changes. 23 | * TaskListStyle and TrayButtonStyle are back (removed in v2.3.2). 24 | 25 | 26 | Changes from 2.3.4 to 2.3.5 27 | ============================================================================== 28 | * No breaking changes. 29 | * ClockStyle is back (removed in v2.3.2). 30 | 31 | 32 | Changes from 2.3.3 to 2.3.4 33 | ============================================================================== 34 | * No breaking changes. 35 | 36 | 37 | Changes from 2.3.2 to 2.3.3 38 | ============================================================================== 39 | * No breaking changes. 40 | 41 | 42 | Changes from 2.3.1 to 2.3.2 43 | ============================================================================== 44 | * The TaskListStyle, TrayButtonStyle, and ClockStyle tags have been removed. 45 | These options are now set from TrayStyle. 46 | 47 | 48 | Changes from 2.3.0 to 2.3.1 49 | ============================================================================== 50 | * No breaking changes. 51 | 52 | 53 | Changes from 2.2.x to 2.3.0 54 | ============================================================================== 55 | * The ActiveBackground and ActiveForeground tags have been replaced by 56 | Background and Foreground nested under the Active tag. This applies 57 | to TrayStyle, TaskListStyle, TrayButtonStyle, PagerStyle, and MenuStyle. 58 | * The Inactive tag under WindowStyle has been removed. The tags that 59 | used to go within this tag now go directly under the WindowStyle tag. 60 | * The autohide attribute in Tray now selects where the tray should be 61 | hidden (left, right, top, bottom, or off) instead of true or false. 62 | * Now actions in the Clock tag must be prefixed with "exec:" to run 63 | an external program. 64 | -------------------------------------------------------------------------------- /src/border.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file border.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for handling window borders. 7 | * 8 | */ 9 | 10 | #ifndef BORDER_H 11 | #define BORDER_H 12 | 13 | #include "gradient.h" 14 | #include "binding.h" 15 | 16 | struct ClientNode; 17 | struct ClientState; 18 | 19 | /** Border icon types. */ 20 | typedef unsigned char BorderIconType; 21 | #define BI_CLOSE 0 22 | #define BI_MAX 1 23 | #define BI_MAX_ACTIVE 2 24 | #define BI_MENU 3 25 | #define BI_MIN 4 26 | #define BI_COUNT 5 27 | 28 | /*@{*/ 29 | void InitializeBorders(void); 30 | void StartupBorders(void); 31 | #define ShutdownBorders() (void)(0) 32 | void DestroyBorders(void); 33 | /*@}*/ 34 | 35 | /** Determine the mouse context for a location. 36 | * @param np The client. 37 | * @param x The x-coordinate of the mouse (frame relative). 38 | * @param y The y-coordinate of the mouse (frame relative). 39 | * @return The context. 40 | */ 41 | MouseContextType GetBorderContext(const struct ClientNode *np, 42 | int x, int y); 43 | 44 | /** Reset the shape of a window border. 45 | * @param np The client. 46 | */ 47 | void ResetBorder(const struct ClientNode *np); 48 | 49 | /** Draw a window border. 50 | * @param np The client whose frame to draw. 51 | */ 52 | void DrawBorder(struct ClientNode *np); 53 | 54 | /** Get the size of a border icon. 55 | * @return The size in pixels (note that icons are square). 56 | */ 57 | int GetBorderIconSize(void); 58 | 59 | /** Get the height of a window title bar. */ 60 | unsigned GetTitleHeight(void); 61 | 62 | /** Get the size of a window border. 63 | * @param state The client state. 64 | * @param north Pointer to the value to contain the north border size. 65 | * @param south Pointer to the value to contain the south border size. 66 | * @param east Pointer to the value to contain the east border size. 67 | * @param west Pointer to the value to contain the west border size. 68 | */ 69 | void GetBorderSize(const struct ClientState *state, 70 | int *north, int *south, int *east, int *west); 71 | 72 | /** Redraw all borders on the current desktop. */ 73 | void ExposeCurrentDesktop(void); 74 | 75 | /** Draw a rounded rectangle. 76 | * @param d The drawable on which to render. 77 | * @param gc The graphics context. 78 | * @param x The x-coodinate. 79 | * @param y The y-coordinate. 80 | * @param width The width. 81 | * @param height The height. 82 | * @param radius The corner radius. 83 | */ 84 | void DrawRoundedRectangle(Drawable d, GC gc, int x, int y, 85 | int width, int height, int radius); 86 | 87 | /** Set the icon to use for a border button. */ 88 | void SetBorderIcon(BorderIconType t, const char *name); 89 | 90 | #endif /* BORDER_H */ 91 | 92 | -------------------------------------------------------------------------------- /src/screen.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file screen.c 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Screen functions. 7 | * 8 | * Note that screen here refers to physical monitors. Screens are 9 | * determined using the xinerama extension (if available). There will 10 | * always be at least one screen. 11 | * 12 | */ 13 | 14 | #include "jwm.h" 15 | #include "screen.h" 16 | #include "main.h" 17 | #include "cursor.h" 18 | #include "misc.h" 19 | 20 | static ScreenType *screens = NULL; 21 | static int screenCount; 22 | 23 | /** Startup screens. */ 24 | void StartupScreens(void) 25 | { 26 | #ifdef USE_XINERAMA 27 | 28 | XineramaScreenInfo *info; 29 | int x; 30 | 31 | if(XineramaIsActive(display)) { 32 | 33 | info = XineramaQueryScreens(display, &screenCount); 34 | 35 | screens = Allocate(sizeof(ScreenType) * screenCount); 36 | for(x = 0; x < screenCount; x++) { 37 | screens[x].index = x; 38 | screens[x].x = info[x].x_org; 39 | screens[x].y = info[x].y_org; 40 | screens[x].width = info[x].width; 41 | screens[x].height = info[x].height; 42 | } 43 | 44 | JXFree(info); 45 | 46 | } else { 47 | 48 | screenCount = 1; 49 | screens = Allocate(sizeof(ScreenType)); 50 | screens->index = 0; 51 | screens->x = 0; 52 | screens->y = 0; 53 | screens->width = rootWidth; 54 | screens->height = rootHeight; 55 | 56 | } 57 | 58 | #else 59 | 60 | screenCount = 1; 61 | screens = Allocate(sizeof(ScreenType)); 62 | screens->index = 0; 63 | screens->x = 0; 64 | screens->y = 0; 65 | screens->width = rootWidth; 66 | screens->height = rootHeight; 67 | 68 | #endif /* USE_XINERAMA */ 69 | } 70 | 71 | /** Shutdown screens. */ 72 | void ShutdownScreens(void) 73 | { 74 | if(screens) { 75 | Release(screens); 76 | screens = NULL; 77 | } 78 | } 79 | 80 | /** Get the screen given global screen coordinates. */ 81 | const ScreenType *GetCurrentScreen(int x, int y) 82 | { 83 | 84 | ScreenType *sp; 85 | int index; 86 | 87 | x = Max(0, x); 88 | x = Min(x, rootWidth - 1); 89 | y = Max(0, y); 90 | y = Min(y, rootHeight - 1); 91 | for(index = 1; index < screenCount; index++) { 92 | sp = &screens[index]; 93 | if(x >= sp->x && x < sp->x + sp->width) { 94 | if(y >= sp->y && y < sp->y + sp->height) { 95 | return sp; 96 | } 97 | } 98 | } 99 | 100 | return &screens[0]; 101 | 102 | } 103 | 104 | /** Get the screen the mouse is currently on. */ 105 | const ScreenType *GetMouseScreen(void) 106 | { 107 | #ifdef USE_XINERAMA 108 | 109 | Window w; 110 | int x, y; 111 | 112 | GetMousePosition(&x, &y, &w); 113 | return GetCurrentScreen(x, y); 114 | 115 | #else 116 | 117 | return &screens[0]; 118 | 119 | #endif 120 | } 121 | 122 | /** Get data for a screen. */ 123 | const ScreenType *GetScreen(int index) 124 | { 125 | 126 | Assert(index >= 0); 127 | Assert(index < screenCount); 128 | 129 | return &screens[index]; 130 | 131 | } 132 | 133 | /** Get the number of screens. */ 134 | int GetScreenCount(void) 135 | { 136 | return screenCount; 137 | } 138 | 139 | 140 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to JWM 2 | =================== 3 | 4 | Filing Issues 5 | ------------- 6 | 7 | Issues on GitHub are very much appreciated. These can be bug reports and 8 | feature requests. Don't assume that everyone knows about a bug, please 9 | file an issue. If you don't have a GitHub account, emailing me is also 10 | acceptable (joewing@joewing.net). 11 | 12 | Before filing an issue, please check for duplicates. If there is a 13 | duplicate, feel free to comment on the issue even if you have nothing 14 | to say other than "this also affects me". This helps prioritize. 15 | 16 | When filing an issue, call out the version of JWM (the version, commit hash, 17 | or snapshot number). Although it's recommended that you try the newest 18 | snapshot before filing an issue, sometimes that isn't easy to do, so 19 | feel free to file the issue anyway. Most of the time, I'll know if the 20 | issue has already been fixed. 21 | 22 | For bug reports, please try to use a configuration file as close as possible 23 | to the default JWM configuration. Please describe the program or programs 24 | affected along with their versions and provide a detailed list of steps 25 | to reproduce the problem. Keep in mind, that if I am unable to reproduce a 26 | bug, it is unlikely that I will be able to fix it. Also note that the 27 | platform you are using (processor architecture, OS, etc.) likely will not 28 | match mine. Screen shots can be helpful if there is a platform-specific 29 | or closed-source program involved. 30 | 31 | Contributing Code 32 | ----------------- 33 | 34 | Code contributions in the form of bug fixes and features are welcome. 35 | Please file an issue before submitting a PR and announce your intent 36 | to address the issue yourself. This allows discussion of the bug or 37 | feature and prevents duplicate work. Likewise, please announce your 38 | intent to work on existing issues. For issues that take longer than 39 | a few days to address, updating the status on the issue every few days 40 | is recommended. 41 | 42 | JWM adheres to a fairly strict coding standard. Please take a look 43 | around and try to mimic what is already there. 44 | 45 | For pull requests, please squash your commits into logical changes. 46 | Commits should have a meaningful commit message. It should be possible 47 | to compile and run JWM at every commit. 48 | 49 | Although I will accept patches via email, I much prefer pull requests. 50 | A PR allows GitHub to track contributions and keeps the process in the 51 | open. 52 | 53 | Updating Documentation 54 | ---------------------- 55 | 56 | The documentation for JWM is available in "man page" form in the 57 | main JWM repository as well as online at http://joewing.net/projects/jwm . 58 | To make a correction or addition to the man page, please open a pull request. 59 | The online documentation is stored in a separate repository (joewing/www). 60 | Feel free to either open a pull request there too. 61 | 62 | The documentation is currently only available in English. Unfortunately, 63 | I lack the resources and knowledge to keep documentation in other languages 64 | up-to-date. There would need to be some restructuring to make other 65 | languages work. If you are interested in working on documentation 66 | translations, please contact me. 67 | 68 | As with code contributions, I recommend contacting me or filing an issue 69 | before making larger changes to allow discussion and avoid unaccepted 70 | changes. 71 | -------------------------------------------------------------------------------- /xslt/jwm-2.4.xslt: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ldesktop 39 | rdesktop 40 | move 41 | move 42 | window 43 | shade 44 | shade 45 | maximize 46 | window 47 | move 48 | window 49 | shade 50 | shade 51 | resize 52 | move 53 | window 54 | close 55 | move 56 | close 57 | maximize 58 | maxv 59 | maxh 60 | minimize 61 | move 62 | shade 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/action.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file action.h 3 | * @author Joe Wingbermuehle 4 | * 5 | * @brief Tray component actions. 6 | * 7 | */ 8 | 9 | #ifndef ACTION_H 10 | #define ACTION_H 11 | 12 | struct ActionNode; 13 | struct TrayComponentType; 14 | 15 | /** Enumeration of actions. 16 | * Note that we use the high bits to store additional information 17 | * for some key types (for example the desktop number). 18 | */ 19 | typedef struct { 20 | unsigned char action; 21 | unsigned char extra; 22 | } ActionType; 23 | #define ACTION_NONE 0 24 | #define ACTION_UP 1 25 | #define ACTION_DOWN 2 26 | #define ACTION_RIGHT 3 27 | #define ACTION_LEFT 4 28 | #define ACTION_ESC 5 29 | #define ACTION_ENTER 6 30 | #define ACTION_NEXT 7 31 | #define ACTION_NEXTSTACK 8 32 | #define ACTION_PREV 9 33 | #define ACTION_PREVSTACK 10 34 | #define ACTION_CLOSE 11 35 | #define ACTION_MIN 12 36 | #define ACTION_MAX 13 37 | #define ACTION_SHADE 14 38 | #define ACTION_STICK 15 39 | #define ACTION_MOVE 16 40 | #define ACTION_RESIZE 17 41 | #define ACTION_ROOT 18 42 | #define ACTION_WIN 19 43 | #define ACTION_DESKTOP 20 44 | #define ACTION_RDESKTOP 21 45 | #define ACTION_LDESKTOP 22 46 | #define ACTION_UDESKTOP 23 47 | #define ACTION_DDESKTOP 24 48 | #define ACTION_SHOWDESK 25 49 | #define ACTION_SHOWTRAY 26 50 | #define ACTION_EXEC 27 51 | #define ACTION_RESTART 28 52 | #define ACTION_EXIT 29 53 | #define ACTION_FULLSCREEN 30 54 | #define ACTION_SEND 31 55 | #define ACTION_SENDR 32 56 | #define ACTION_SENDL 33 57 | #define ACTION_SENDU 34 58 | #define ACTION_SENDD 35 59 | #define ACTION_MAXTOP 36 60 | #define ACTION_MAXBOTTOM 37 61 | #define ACTION_MAXLEFT 38 62 | #define ACTION_MAXRIGHT 39 63 | #define ACTION_MAXV 40 64 | #define ACTION_MAXH 41 65 | #define ACTION_RESTORE 42 66 | #define ACTION_INVALID 255 67 | #define ACTION_RESIZE_N 1 /* Extra value mask for resize north. */ 68 | #define ACTION_RESIZE_S 2 /* Extra value mask for resize south. */ 69 | #define ACTION_RESIZE_E 4 /* Extra value mask for resize east. */ 70 | #define ACTION_RESIZE_W 8 /* Extra value mask for resize west. */ 71 | 72 | /** Add an action to a list of actions. 73 | * @param actions The action list to update. 74 | * @param action The action to add to the list. 75 | * @param mask The mouse button mask. 76 | */ 77 | void AddAction(struct ActionNode **actions, const char *action, int mask); 78 | 79 | /** Destroy a list of actions. */ 80 | void DestroyActions(struct ActionNode *actions); 81 | 82 | /** Process a button press event. 83 | * @param actions The action list. 84 | * @param cp The tray component. 85 | * @param x The mouse x-coordinate. 86 | * @param y The mouse y-coordinate. 87 | * @param button The mouse button. 88 | */ 89 | void ProcessActionPress(struct ActionNode *actions, 90 | struct TrayComponentType *cp, 91 | int x, int y, int button); 92 | 93 | /** Process a button release event. 94 | * @param actions The action list. 95 | * @param cp The tray component. 96 | * @param x The mouse x-coordinate. 97 | * @param y The mouse y-coordinate. 98 | * @param button The mouse button. 99 | */ 100 | void ProcessActionRelease(struct ActionNode *actions, 101 | struct TrayComponentType *cp, 102 | int x, int y, int button); 103 | 104 | /** Validate actions. 105 | * @param actions The action list to validate. 106 | */ 107 | void ValidateActions(const struct ActionNode *actions); 108 | 109 | #endif /* ACTION_H */ 110 | -------------------------------------------------------------------------------- /src/lex.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lex.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief XML lexer header file. 7 | * 8 | */ 9 | 10 | #ifndef LEX_H 11 | #define LEX_H 12 | 13 | /** Tokens. */ 14 | typedef enum { 15 | 16 | TOK_INVALID, 17 | 18 | TOK_ACTIVE, 19 | TOK_BACKGROUND, 20 | TOK_BUTTON, 21 | TOK_BUTTONCLOSE, 22 | TOK_BUTTONMAX, 23 | TOK_BUTTONMAXACTIVE, 24 | TOK_BUTTONMENU, 25 | TOK_BUTTONMIN, 26 | TOK_CLASS, 27 | TOK_CLOCK, 28 | TOK_CLOCKSTYLE, 29 | TOK_CLOSE, 30 | TOK_CORNER, 31 | TOK_DEFAULTICON, 32 | TOK_DESKTOP, 33 | TOK_DESKTOPS, 34 | TOK_DOCK, 35 | TOK_DOUBLECLICKDELTA, 36 | TOK_DOUBLECLICKSPEED, 37 | TOK_DYNAMIC, 38 | TOK_EXIT, 39 | TOK_FOCUSMODEL, 40 | TOK_FONT, 41 | TOK_FOREGROUND, 42 | TOK_GROUP, 43 | TOK_HEIGHT, 44 | TOK_ICONPATH, 45 | TOK_INCLUDE, 46 | TOK_JWM, 47 | TOK_KEY, 48 | TOK_KILL, 49 | TOK_LAYER, 50 | TOK_MACHINE, 51 | TOK_MAXIMIZE, 52 | TOK_MENU, 53 | TOK_MENUSTYLE, 54 | TOK_MINIMIZE, 55 | TOK_MOUSE, 56 | TOK_MOVE, 57 | TOK_MOVEMODE, 58 | TOK_NAME, 59 | TOK_OPACITY, 60 | TOK_OPTION, 61 | TOK_OUTLINE, 62 | TOK_PAGER, 63 | TOK_PAGERSTYLE, 64 | TOK_POPUP, 65 | TOK_POPUPSTYLE, 66 | TOK_PROGRAM, 67 | TOK_RESIZE, 68 | TOK_RESIZEMODE, 69 | TOK_RESTART, 70 | TOK_RESTARTCOMMAND, 71 | TOK_ROOTMENU, 72 | TOK_SENDTO, 73 | TOK_SEPARATOR, 74 | TOK_SHADE, 75 | TOK_SHUTDOWNCOMMAND, 76 | TOK_SNAPMODE, 77 | TOK_SPACER, 78 | TOK_STARTUPCOMMAND, 79 | TOK_STICK, 80 | TOK_SWALLOW, 81 | TOK_TASKLIST, 82 | TOK_TASKLISTSTYLE, 83 | TOK_TEXT, 84 | TOK_TITLEBUTTONORDER, 85 | TOK_TRAY, 86 | TOK_TRAYBUTTON, 87 | TOK_TRAYBUTTONSTYLE, 88 | TOK_TRAYSTYLE, 89 | TOK_TYPE, 90 | TOK_WIDTH, 91 | TOK_WINDOWSTYLE 92 | 93 | } TokenType; 94 | 95 | /** Structure to represent an XML attribute. */ 96 | typedef struct AttributeNode { 97 | 98 | char *name; /**< The name of the attribute. */ 99 | char *value; /**< The value for the attribute. */ 100 | struct AttributeNode *next; /**< The next attribute in the list. */ 101 | 102 | } AttributeNode; 103 | 104 | /** Structure to represent an XML tag. */ 105 | typedef struct TokenNode { 106 | 107 | TokenType type; /**< Tag type. */ 108 | char *invalidName; /**< Name of the tag if invalid. */ 109 | char *value; /**< Body of the tag. */ 110 | const char *fileName; /**< Name of the file containing this tag. */ 111 | unsigned int line; /**< Line number of the start of this tag. */ 112 | struct AttributeNode *attributes; /**< Linked list of attributes. */ 113 | struct TokenNode *parent; /**< Parent tag. */ 114 | struct TokenNode *subnodeHead; /**< Start of children. */ 115 | struct TokenNode *subnodeTail; /**< End of children. */ 116 | struct TokenNode *next; /**< Next tag at the current level. */ 117 | 118 | } TokenNode; 119 | 120 | /** Tokenize a buffer. 121 | * @param line The buffer to tokenize. 122 | * @param fileName The name of the file for error reporting. 123 | * @return A linked list of tokens from the buffer. 124 | */ 125 | TokenNode *Tokenize(const char *line, const char *fileName); 126 | 127 | /** Get a string represention of a token. 128 | * This is identical to GetTokenTypeName if tp is a valid token. 129 | * @param tp The token node. 130 | * @return The name (never NULL). 131 | */ 132 | const char *GetTokenName(const TokenNode *tp); 133 | 134 | /** Get a string represention of a token. 135 | * @param type The token. 136 | * @return The name (never NULL). 137 | */ 138 | const char *GetTokenTypeName(TokenType type); 139 | 140 | /** Release token nodes. 141 | * @param np The top-level token to release. 142 | */ 143 | void ReleaseTokens(TokenNode *np); 144 | 145 | #endif /* LEX_H */ 146 | -------------------------------------------------------------------------------- /src/jwm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file jwm.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief The main JWM header file. 7 | * 8 | */ 9 | 10 | #ifndef JWM_H 11 | #define JWM_H 12 | 13 | #include "../config.h" 14 | 15 | #ifndef MAKE_DEPEND 16 | 17 | # include 18 | # include 19 | # include 20 | # include 21 | # include 22 | 23 | /* Ideally png.h would be included in image.c, which is the only 24 | * file that references it. Unfortunately, if setjmp.h is included 25 | * before png.h, png.h will complain about only including setjmp.h 26 | * once. The X headers apparently include setjmp.h, so I don't have 27 | * any control over the situation. Fortunately png.h can't complain 28 | * if it was included first. */ 29 | # ifdef USE_PNG 30 | # include 31 | # else 32 | # include 33 | # endif 34 | 35 | # ifdef HAVE_LOCALE_H 36 | # include 37 | # endif 38 | # ifdef HAVE_LIBINTL_H 39 | # include 40 | # endif 41 | # ifdef HAVE_STDARG_H 42 | # include 43 | # endif 44 | # ifdef HAVE_SIGNAL_H 45 | # include 46 | # endif 47 | # ifdef HAVE_UNISTD_H 48 | # include 49 | # endif 50 | # ifdef HAVE_TIME_H 51 | # include 52 | # endif 53 | # ifdef HAVE_SYS_WAIT_H 54 | # include 55 | # endif 56 | # ifdef HAVE_SYS_TIME_H 57 | # include 58 | # endif 59 | # ifdef HAVE_SYS_SELECT_H 60 | # include 61 | # endif 62 | 63 | # include 64 | # ifdef HAVE_X11_XUTIL_H 65 | # include 66 | # endif 67 | # ifdef HAVE_X11_XRESOURCE_H 68 | # include 69 | # endif 70 | # ifdef HAVE_X11_CURSORFONT_H 71 | # include 72 | # endif 73 | # ifdef HAVE_X11_XPROTO_H 74 | # include 75 | # endif 76 | # ifdef HAVE_X11_XATOM_H 77 | # include 78 | # endif 79 | # ifdef HAVE_X11_KEYSYM_H 80 | # include 81 | # endif 82 | 83 | # ifdef USE_SHAPE 84 | # include 85 | # endif 86 | 87 | # ifdef USE_XMU 88 | # include 89 | # endif 90 | 91 | # ifdef USE_XINERAMA 92 | # include 93 | # endif 94 | # ifdef USE_XFT 95 | # ifdef HAVE_FT2BUILD_H 96 | # include 97 | # endif 98 | # include 99 | # endif 100 | # ifdef USE_XRENDER 101 | # include 102 | # endif 103 | # ifdef USE_FRIBIDI 104 | # include 105 | # endif 106 | 107 | #endif /* MAKE_DEPEND */ 108 | 109 | #ifndef _ 110 | # ifdef HAVE_GETTEXT 111 | # define _ gettext 112 | # else 113 | # define _ 114 | # endif 115 | #endif 116 | 117 | /** Maximum window size. 118 | * Making this larger will require code changes in some places where 119 | * there are fixed point calculations. */ 120 | #define MAX_WINDOW_WIDTH (1 << 15) 121 | #define MAX_WINDOW_HEIGHT (1 << 15) 122 | 123 | #define MAX_INCLUDE_DEPTH 16 /**< Max includes. */ 124 | #define MOVE_DELTA 3 /**< Pixels before trigging a move. */ 125 | #define RESTART_DELAY 1000 /**< Max timeout in ms before restarting. */ 126 | #define URGENCY_DELAY 500 /**< Flash timeout in ms for urgency. */ 127 | #define DEFAULT_TIMEOUT_MS 5000 /**< Default pipe timeout. */ 128 | 129 | #define SHELL_NAME "/bin/sh" 130 | 131 | #ifdef __GNUC__ 132 | # if __GNUC__ >= 3 133 | # define JLIKELY(x) __builtin_expect(!!(x), 1) 134 | # define JUNLIKELY(x) __builtin_expect(!!(x), 0) 135 | # else 136 | # warning "JLIKELY/JUNLIKELY not available with this version of gcc" 137 | # define JLIKELY(x) (x) 138 | # define JUNLIKELY(x) (x) 139 | # endif 140 | #else 141 | # warning "JLIKELY/JUNLIKELY not available with this compiler" 142 | # define JLIKELY(x) (x) 143 | # define JUNLIKELY(x) (x) 144 | #endif 145 | 146 | #include "debug.h" 147 | #include "jxlib.h" 148 | 149 | #endif /* JWM_H */ 150 | 151 | -------------------------------------------------------------------------------- /xslt/jwm-2.3.xslt: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | bottom 28 | 29 | 30 | off 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /src/icon.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file icon.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header file for icon functions. 7 | * 8 | */ 9 | 10 | #ifndef ICON_H 11 | #define ICON_H 12 | 13 | struct ClientNode; 14 | 15 | /** Structure to hold a scaled icon. */ 16 | typedef struct ScaledIconNode { 17 | 18 | int width; /**< The scaled width of the icon. */ 19 | int height; /**< The scaled height of the icon. */ 20 | long fg; /**< Foreground color for bitmaps. */ 21 | 22 | XID image; 23 | XID mask; 24 | 25 | struct ScaledIconNode *next; 26 | 27 | } ScaledIconNode; 28 | 29 | /** Structure to hold an icon. */ 30 | typedef struct IconNode { 31 | 32 | char *name; /**< The name of the icon. */ 33 | struct ImageNode *images; /**< Images associated with this icon. */ 34 | struct ScaledIconNode *nodes; /**< Scaled icons. */ 35 | int width; /**< Natural width. */ 36 | int height; /**< Natural height. */ 37 | 38 | struct IconNode *next; /**< The next icon in the list. */ 39 | struct IconNode *prev; /**< The previous icon in the list. */ 40 | 41 | char preserveAspect; /**< Set to preserve the aspect ratio 42 | * of the icon when scaling. */ 43 | char bitmap; /**< Set if this is a bitmap. */ 44 | char transient; /**< Set if this icon is transient. */ 45 | #ifdef USE_XRENDER 46 | char render; /**< Set to use render. */ 47 | #endif 48 | 49 | } IconNode; 50 | 51 | extern IconNode emptyIcon; 52 | 53 | #ifdef USE_ICONS 54 | 55 | /*@{*/ 56 | void InitializeIcons(void); 57 | void StartupIcons(void); 58 | void ShutdownIcons(void); 59 | void DestroyIcons(void); 60 | /*@}*/ 61 | 62 | /** Add an icon path. 63 | * This adds a path to the list of icon search paths. 64 | * @param path The icon path to add. 65 | */ 66 | void AddIconPath(char *path); 67 | 68 | /** Render an icon. 69 | * This will scale an icon if necessary to fit the requested size. The 70 | * aspect ratio of the icon is preserved. 71 | * @param icon The icon to render. 72 | * @param d The drawable on which to place the icon. 73 | * @param fg The foreground color. 74 | * @param x The x offset on the drawable to render the icon. 75 | * @param y The y offset on the drawable to render the icon. 76 | * @param width The width of the icon to display. 77 | * @param height The height of the icon to display. 78 | */ 79 | void PutIcon(IconNode *icon, Drawable d, 80 | long fg, int x, int y, int width, int height); 81 | 82 | /** Load an icon for a client. 83 | * @param np The client. 84 | */ 85 | void LoadIcon(struct ClientNode *np); 86 | 87 | /** Load an icon. 88 | * @param name The name of the icon to load. 89 | * @param save Set if this icon should be saved in the icon hash. 90 | * @param preserveAspect Set to preserve the aspect ratio when scaling. 91 | * @return A pointer to the icon (NULL if not found). 92 | */ 93 | IconNode *LoadNamedIcon(const char *name, char save, char preserveAspect); 94 | 95 | /** Load the default icon. 96 | * @return The default icon. 97 | */ 98 | IconNode *GetDefaultIcon(void); 99 | 100 | /** Destroy an icon. 101 | * @param icon The icon to destroy. 102 | */ 103 | void DestroyIcon(IconNode *icon); 104 | 105 | /** Set the default icon. */ 106 | void SetDefaultIcon(const char *name); 107 | 108 | #else 109 | 110 | #define ICON_DUMMY_FUNCTION ((void)0) 111 | 112 | #define InitializeIcons() ICON_DUMMY_FUNCTION 113 | #define StartupIcons() ICON_DUMMY_FUNCTION 114 | #define ShutdownIcons() ICON_DUMMY_FUNCTION 115 | #define DestroyIcons() ICON_DUMMY_FUNCTION 116 | #define AddIconPath( a ) ICON_DUMMY_FUNCTION 117 | #define PutIcon( a, b, c, d, e, f, g ) ICON_DUMMY_FUNCTION 118 | #define LoadIcon( a ) ICON_DUMMY_FUNCTION 119 | #define GetDefaultIcon() NULL 120 | #define LoadNamedIcon( a, b, c ) NULL 121 | #define DestroyIcon( a ) ICON_DUMMY_FUNCTION 122 | #define SetDefaultIcon( a ) ICON_DUMMY_FUNCTION 123 | 124 | #endif /* USE_ICONS */ 125 | 126 | #endif /* ICON_H */ 127 | 128 | -------------------------------------------------------------------------------- /src/color.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file color.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions to handle loading colors. 7 | * 8 | */ 9 | 10 | #ifndef COLOR_H 11 | #define COLOR_H 12 | 13 | /** Enumeration of colors used for various JWM components. 14 | * For easier parsing, tray components must all have colors ordered the 15 | * same way as COLOR_TRAY_*. 16 | */ 17 | typedef unsigned char ColorType; 18 | #define COLOR_TITLE_FG 0 19 | #define COLOR_TITLE_ACTIVE_FG 1 20 | #define COLOR_TITLE_BG1 2 21 | #define COLOR_TITLE_BG2 3 22 | #define COLOR_TITLE_ACTIVE_BG1 4 23 | #define COLOR_TITLE_ACTIVE_BG2 5 24 | #define COLOR_TRAY_FG 6 25 | #define COLOR_TRAY_BG1 7 26 | #define COLOR_TRAY_BG2 8 27 | #define COLOR_TRAY_ACTIVE_FG 9 28 | #define COLOR_TRAY_ACTIVE_BG1 10 29 | #define COLOR_TRAY_ACTIVE_BG2 11 30 | #define COLOR_TRAY_UP 12 31 | #define COLOR_TRAY_DOWN 13 32 | #define COLOR_TRAY_ACTIVE_UP 14 33 | #define COLOR_TRAY_ACTIVE_DOWN 15 34 | #define COLOR_TASKLIST_FG 16 35 | #define COLOR_TASKLIST_BG1 17 36 | #define COLOR_TASKLIST_BG2 18 37 | #define COLOR_TASKLIST_ACTIVE_FG 19 38 | #define COLOR_TASKLIST_ACTIVE_BG1 20 39 | #define COLOR_TASKLIST_ACTIVE_BG2 21 40 | #define COLOR_TASKLIST_UP 22 41 | #define COLOR_TASKLIST_DOWN 23 42 | #define COLOR_TASKLIST_ACTIVE_UP 24 43 | #define COLOR_TASKLIST_ACTIVE_DOWN 25 44 | #define COLOR_TRAYBUTTON_FG 26 45 | #define COLOR_TRAYBUTTON_BG1 27 46 | #define COLOR_TRAYBUTTON_BG2 28 47 | #define COLOR_TRAYBUTTON_ACTIVE_FG 29 48 | #define COLOR_TRAYBUTTON_ACTIVE_BG1 30 49 | #define COLOR_TRAYBUTTON_ACTIVE_BG2 31 50 | #define COLOR_TRAYBUTTON_UP 32 51 | #define COLOR_TRAYBUTTON_DOWN 33 52 | #define COLOR_TRAYBUTTON_ACTIVE_UP 34 53 | #define COLOR_TRAYBUTTON_ACTIVE_DOWN 35 54 | #define COLOR_PAGER_BG 36 55 | #define COLOR_PAGER_FG 37 56 | #define COLOR_PAGER_ACTIVE_BG 38 57 | #define COLOR_PAGER_ACTIVE_FG 39 58 | #define COLOR_PAGER_OUTLINE 40 59 | #define COLOR_PAGER_TEXT 41 60 | #define COLOR_MENU_BG 42 61 | #define COLOR_MENU_FG 43 62 | #define COLOR_MENU_UP 44 63 | #define COLOR_MENU_DOWN 45 64 | #define COLOR_MENU_ACTIVE_BG1 46 65 | #define COLOR_MENU_ACTIVE_BG2 47 66 | #define COLOR_MENU_ACTIVE_FG 48 67 | #define COLOR_MENU_ACTIVE_UP 49 68 | #define COLOR_MENU_ACTIVE_DOWN 50 69 | #define COLOR_POPUP_BG 51 70 | #define COLOR_POPUP_FG 52 71 | #define COLOR_POPUP_OUTLINE 53 72 | #define COLOR_TITLE_UP 54 73 | #define COLOR_TITLE_DOWN 55 74 | #define COLOR_TITLE_ACTIVE_UP 56 75 | #define COLOR_TITLE_ACTIVE_DOWN 57 76 | #define COLOR_CLOCK_FG 58 77 | #define COLOR_CLOCK_BG1 59 78 | #define COLOR_CLOCK_BG2 60 79 | #define COLOR_COUNT 61 80 | 81 | extern unsigned long colors[COLOR_COUNT]; 82 | 83 | /*@{*/ 84 | #define InitializeColors() (void)(0) 85 | void StartupColors(void); 86 | void ShutdownColors(void); 87 | void DestroyColors(void); 88 | /*@}*/ 89 | 90 | /** Set the color to use for a component. 91 | * @param c The component whose color to set. 92 | * @param value The color to use. 93 | */ 94 | void SetColor(ColorType c, const char *value); 95 | 96 | /** Parse a color. 97 | * @param value The color name or hex value. 98 | * @param c The color return value (with pixel and components filled). 99 | * @return 1 on success, 0 on failure. 100 | */ 101 | char ParseColor(const char *value, XColor *c); 102 | 103 | /** Get the color pixel from red, green, and blue values. 104 | * @param c The structure containing the rgb values and the pixel value. 105 | */ 106 | void GetColor(XColor *c); 107 | 108 | #ifdef USE_XFT 109 | /** Get an XFT color. 110 | * @param type The color whose XFT color to get. 111 | * @return The XFT color. 112 | */ 113 | XftColor *GetXftColor(ColorType type); 114 | #endif 115 | 116 | #endif /* COLOR_H */ 117 | -------------------------------------------------------------------------------- /src/settings.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file settings.c 3 | * @author Joe Wingbermuehle 4 | * @date 2012 5 | * 6 | * @brief JWM settings. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "settings.h" 12 | #include "misc.h" 13 | 14 | Settings settings; 15 | 16 | static const MouseContextType DEFAULT_TITLE_BAR_LAYOUT[TBC_COUNT] = { 17 | MC_ICON, 18 | MC_MOVE, 19 | MC_MINIMIZE, 20 | MC_MAXIMIZE, 21 | MC_CLOSE, 22 | MC_NONE 23 | }; 24 | 25 | static void FixRange(unsigned int *value, 26 | unsigned int min_value, 27 | unsigned int max_value, 28 | unsigned int def_value); 29 | 30 | /** Initialize settings. */ 31 | void InitializeSettings(void) 32 | { 33 | settings.moveMask = (1 << Mod1MapIndex); 34 | settings.doubleClickSpeed = 400; 35 | settings.doubleClickDelta = 2; 36 | settings.snapMode = SNAP_BORDER; 37 | settings.snapDistance = 5; 38 | settings.moveMode = MOVE_OPAQUE; 39 | settings.moveStatusType = SW_SCREEN; 40 | settings.resizeStatusType = SW_SCREEN; 41 | settings.focusModel = FOCUS_SLOPPY; 42 | settings.resizeMode = RESIZE_OPAQUE; 43 | settings.popupDelay = 600; 44 | settings.desktopDelay = 1000; 45 | settings.trayOpacity = UINT_MAX; 46 | settings.popupMask = POPUP_ALL; 47 | settings.activeClientOpacity = UINT_MAX; 48 | settings.inactiveClientOpacity = (unsigned int)(0.75 * UINT_MAX); 49 | settings.borderWidth = 5; 50 | settings.titleHeight = 0; 51 | settings.titleTextAlignment = ALIGN_LEFT; 52 | settings.desktopWidth = 4; 53 | settings.desktopHeight = 1; 54 | settings.menuOpacity = UINT_MAX; 55 | settings.windowDecorations = DECO_FLAT; 56 | settings.trayDecorations = DECO_FLAT; 57 | settings.taskListDecorations = DECO_UNSET; 58 | settings.menuDecorations = DECO_FLAT; 59 | settings.cornerRadius = 4; 60 | settings.groupTasks = 0; 61 | settings.listAllTasks = 0; 62 | settings.dockSpacing = 0; 63 | memcpy(settings.titleBarLayout, DEFAULT_TITLE_BAR_LAYOUT, 64 | sizeof(settings.titleBarLayout)); 65 | } 66 | 67 | /** Make sure settings are reasonable. */ 68 | void StartupSettings(void) 69 | { 70 | 71 | FixRange(&settings.cornerRadius, 0, 5, 4); 72 | 73 | FixRange(&settings.borderWidth, 1, 128, 4); 74 | FixRange(&settings.titleHeight, 0, 256, 0); 75 | 76 | FixRange(&settings.doubleClickDelta, 0, 64, 2); 77 | FixRange(&settings.doubleClickSpeed, 1, 2000, 400); 78 | 79 | FixRange(&settings.desktopWidth, 1, 64, 4); 80 | FixRange(&settings.desktopHeight, 1, 64, 1); 81 | settings.desktopCount = settings.desktopWidth * settings.desktopHeight; 82 | 83 | if(settings.taskListDecorations == DECO_UNSET) { 84 | settings.taskListDecorations = settings.trayDecorations; 85 | } 86 | 87 | FixRange(&settings.dockSpacing, 0, 64, 0); 88 | } 89 | 90 | /** Update a string setting. */ 91 | void SetPathString(char **dest, const char *src) 92 | { 93 | if(*dest) { 94 | Release(*dest); 95 | } 96 | *dest = CopyString(src); 97 | if(JLIKELY(*dest)) { 98 | ExpandPath(dest); 99 | } 100 | } 101 | 102 | /** Make sure a value is in range. */ 103 | void FixRange(unsigned int *value, 104 | unsigned int min_value, 105 | unsigned int max_value, 106 | unsigned int def_value) 107 | { 108 | if(JUNLIKELY(*value < min_value || *value > max_value)) { 109 | *value = def_value; 110 | } 111 | } 112 | 113 | /** Set the title button order. */ 114 | void SetTitleButtonOrder(const char *order) 115 | { 116 | unsigned i = 0; 117 | memset(settings.titleBarLayout, 0, sizeof(settings.titleBarLayout)); 118 | while(*order && i < TBC_COUNT) { 119 | switch(tolower(*order)) { 120 | case 'x': /* Close */ 121 | settings.titleBarLayout[i++] = MC_CLOSE; 122 | break; 123 | case 'i': /* Minimize (iconify) */ 124 | settings.titleBarLayout[i++] = MC_MINIMIZE; 125 | break; 126 | case 't': /* Title */ 127 | settings.titleBarLayout[i++] = MC_MOVE; 128 | break; 129 | case 'm': /* Maximize */ 130 | settings.titleBarLayout[i++] = MC_MAXIMIZE; 131 | break; 132 | case 'w': /* Window */ 133 | settings.titleBarLayout[i++] = MC_ICON; 134 | break; 135 | default: 136 | break; 137 | } 138 | order += 1; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/settings.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file settings.h 3 | * @author Joe Wingbermuehle 4 | * @date 2012 5 | * 6 | * @brief JWM settings. 7 | * 8 | */ 9 | 10 | #ifndef SETTINGS_H 11 | #define SETTINGS_H 12 | 13 | /** Window snap modes. */ 14 | typedef unsigned char SnapModeType; 15 | #define SNAP_NONE 0 /**< Don't snap. */ 16 | #define SNAP_SCREEN 1 /**< Snap to the edges of the screen. */ 17 | #define SNAP_BORDER 2 /**< Snap to all borders. */ 18 | 19 | /** Window move modes. */ 20 | typedef unsigned char MoveModeType; 21 | #define MOVE_OPAQUE 0 /**< Show window contents while moving. */ 22 | #define MOVE_OUTLINE 1 /**< Show an outline while moving. */ 23 | 24 | /** Window resize modes. */ 25 | typedef unsigned char ResizeModeType; 26 | #define RESIZE_OPAQUE 0 /**< Show window contents while resizing. */ 27 | #define RESIZE_OUTLINE 1 /**< Show an outline while resizing. */ 28 | 29 | /** Status window types. */ 30 | typedef unsigned char StatusWindowType; 31 | #define SW_OFF 0 /**< No status window. */ 32 | #define SW_SCREEN 1 /**< Centered on screen. */ 33 | #define SW_WINDOW 2 /**< Centered on window. */ 34 | #define SW_CORNER 3 /**< Upper-left corner. */ 35 | 36 | /** Focus models. */ 37 | typedef unsigned char FocusModelType; 38 | #define FOCUS_SLOPPY 0 /**< Sloppy focus, click to raise. */ 39 | #define FOCUS_CLICK 1 /**< Click to focus, click to raise. */ 40 | #define FOCUS_SLOPPY_TITLE 2 /**< Sloppy focus, title to raise. */ 41 | #define FOCUS_CLICK_TITLE 3 /**< Click to focus, title to raise. */ 42 | 43 | /** Decorations. */ 44 | typedef unsigned char DecorationsType; 45 | #define DECO_UNSET 0 46 | #define DECO_FLAT 1 47 | #define DECO_MOTIF 2 48 | 49 | /** Popup mask. */ 50 | typedef unsigned char PopupMaskType; 51 | #define POPUP_NONE 0 52 | #define POPUP_TASK 1 53 | #define POPUP_PAGER 2 54 | #define POPUP_BUTTON 4 55 | #define POPUP_CLOCK 8 56 | #define POPUP_MENU 16 57 | #define POPUP_ALL 255 58 | 59 | /** Text alignment. */ 60 | typedef unsigned char AlignmentType; 61 | #define ALIGN_LEFT 0 62 | #define ALIGN_CENTER 1 63 | #define ALIGN_RIGHT 2 64 | 65 | /** Mouse binding contexts. */ 66 | typedef unsigned char MouseContextType; 67 | #define MC_NONE 0 /**< Keyboard/none. */ 68 | #define MC_ROOT 1 /**< Root window. */ 69 | #define MC_BORDER 2 /**< Resize handle. */ 70 | #define MC_MOVE 3 /**< Move handle. */ 71 | #define MC_CLOSE 4 /**< Close button. */ 72 | #define MC_MAXIMIZE 5 /**< Maximize button. */ 73 | #define MC_MINIMIZE 6 /**< Minimize button. */ 74 | #define MC_ICON 7 /**< Window menu button. */ 75 | #define MC_COUNT 8 /**< Number of contexts. */ 76 | #define MC_MASK 0x0F /**< Context type mask. */ 77 | #define MC_BORDER_N 0x10 /**< North border. */ 78 | #define MC_BORDER_S 0x20 /**< South border. */ 79 | #define MC_BORDER_E 0x40 /**< East border. */ 80 | #define MC_BORDER_W 0x80 /**< West border. */ 81 | 82 | /** Maximimum number of title bar components 83 | * For now, we allow each component to be used twice. */ 84 | #define TBC_COUNT 9 85 | 86 | /** Settings. */ 87 | typedef struct { 88 | unsigned doubleClickSpeed; 89 | unsigned doubleClickDelta; 90 | unsigned snapDistance; 91 | unsigned popupDelay; 92 | unsigned trayOpacity; 93 | unsigned activeClientOpacity; 94 | unsigned inactiveClientOpacity; 95 | unsigned borderWidth; 96 | unsigned titleHeight; 97 | unsigned desktopWidth; 98 | unsigned desktopHeight; 99 | unsigned desktopCount; 100 | unsigned menuOpacity; 101 | unsigned desktopDelay; 102 | unsigned cornerRadius; 103 | unsigned moveMask; 104 | unsigned dockSpacing; 105 | AlignmentType titleTextAlignment; 106 | SnapModeType snapMode; 107 | MoveModeType moveMode; 108 | StatusWindowType moveStatusType; 109 | StatusWindowType resizeStatusType; 110 | FocusModelType focusModel; 111 | ResizeModeType resizeMode; 112 | DecorationsType windowDecorations; 113 | DecorationsType trayDecorations; 114 | DecorationsType taskListDecorations; 115 | DecorationsType menuDecorations; 116 | PopupMaskType popupMask; 117 | MouseContextType titleBarLayout[TBC_COUNT + 1]; 118 | char groupTasks; 119 | char listAllTasks; 120 | } Settings; 121 | 122 | extern Settings settings; 123 | 124 | /*@{*/ 125 | void InitializeSettings(void); 126 | void StartupSettings(void); 127 | #define ShutdownSettings() (void)(0) 128 | #define DestroySettings() (void)(0) 129 | /*@}*/ 130 | 131 | /** Update a string setting. */ 132 | void SetPathString(char **dest, const char *src); 133 | 134 | /** Set the title button order. */ 135 | void SetTitleButtonOrder(const char *order); 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/menu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file menu.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Header for the menu functions. 7 | * 8 | */ 9 | 10 | #ifndef MENU_H 11 | #define MENU_H 12 | 13 | #include "timing.h" 14 | 15 | struct ScreenType; 16 | 17 | /** Enumeration of menu action types. */ 18 | typedef unsigned char MenuActionType; 19 | #define MA_NONE 0 20 | #define MA_EXECUTE 1 21 | #define MA_DESKTOP 2 22 | #define MA_SENDTO 3 23 | #define MA_LAYER 4 24 | #define MA_STICK 5 25 | #define MA_MAXIMIZE 6 26 | #define MA_MAXIMIZE_H 7 27 | #define MA_MAXIMIZE_V 8 28 | #define MA_MINIMIZE 9 29 | #define MA_RESTORE 10 30 | #define MA_SHADE 11 31 | #define MA_MOVE 12 32 | #define MA_RESIZE 13 33 | #define MA_KILL 14 34 | #define MA_CLOSE 15 35 | #define MA_EXIT 16 36 | #define MA_RESTART 17 37 | #define MA_DYNAMIC 18 38 | #define MA_SENDTO_MENU 19 39 | #define MA_DESKTOP_MENU 20 40 | #define MA_WINDOW_MENU 21 41 | #define MA_ACTION_MASK 0x7F 42 | #define MA_GROUP_MASK 0x80 43 | 44 | /** Structure to represent a menu action for callbacks. */ 45 | typedef struct MenuAction { 46 | 47 | void *context; /**< Action context (client, etc.). */ 48 | 49 | /* Extra data for the action. */ 50 | char *str; 51 | unsigned value; 52 | unsigned timeout_ms; 53 | 54 | MenuActionType type; /**< Type of action. */ 55 | 56 | } MenuAction; 57 | 58 | /** Enumeration of possible menu elements. */ 59 | typedef unsigned char MenuItemType; 60 | #define MENU_ITEM_NORMAL 0 /**< Normal menu item (button). */ 61 | #define MENU_ITEM_SUBMENU 1 /**< Submenu. */ 62 | #define MENU_ITEM_SEPARATOR 2 /**< Item separator. */ 63 | 64 | /** Structure to represent a menu item. */ 65 | typedef struct MenuItem { 66 | 67 | MenuItemType type; /**< The menu item type. */ 68 | char *name; /**< Name to display (or NULL). */ 69 | char *tooltip; /**< Tooltip to display (or NULL). */ 70 | MenuAction action; /**< Action to take if selected (or NULL). */ 71 | char *iconName; /**< Name of an icon to show (or NULL). */ 72 | struct Menu *submenu; /**< Submenu (or NULL). */ 73 | struct MenuItem *next; /**< Next item in the menu. */ 74 | 75 | /** An icon for this menu item. 76 | * This field is handled by menu.c if iconName is set. */ 77 | struct IconNode *icon; /**< Icon to display. */ 78 | 79 | } MenuItem; 80 | 81 | /** Structure to represent a menu or submenu. */ 82 | typedef struct Menu { 83 | 84 | /* These fields must be set before calling ShowMenu */ 85 | struct MenuItem *items; /**< Menu items. */ 86 | char *label; /**< Menu label (NULL for no label). */ 87 | char *dynamic; /**< Generating command of dynamic menu. */ 88 | unsigned timeout_ms; /**< Timeout in milliseconds for dynamic menus. */ 89 | int itemHeight; /**< User-specified menu item height. */ 90 | 91 | /* These fields are handled by menu.c */ 92 | Window window; /**< The menu window. */ 93 | Pixmap pixmap; /**< Pixmap where the menu is rendered. */ 94 | int x; /**< The x-coordinate of the menu. */ 95 | int y; /**< The y-coordinate of the menu. */ 96 | int width; /**< The width of the menu. */ 97 | int height; /**< The height of the menu. */ 98 | int currentIndex; /**< The current menu selection. */ 99 | int lastIndex; /**< The last menu selection. */ 100 | unsigned int itemCount; /**< Number of menu items (excluding separators). */ 101 | int parentOffset; /**< y-offset of this menu wrt the parent. */ 102 | int textOffset; /**< x-offset of text in the menu. */ 103 | int *offsets; /**< y-offsets of menu items. */ 104 | struct Menu *parent; /**< The parent menu (or NULL). */ 105 | const struct ScreenType *screen; 106 | int mousex, mousey; 107 | TimeType lastTime; 108 | 109 | } Menu; 110 | 111 | typedef void (*RunMenuCommandType)(MenuAction *action, unsigned button); 112 | 113 | /** Allocate an empty menu. */ 114 | Menu *CreateMenu(); 115 | 116 | /** Create an empty menu item. */ 117 | MenuItem *CreateMenuItem(MenuItemType type); 118 | 119 | /** Initialize a menu structure to be shown. 120 | * @param menu The menu to initialize. 121 | */ 122 | void InitializeMenu(Menu *menu); 123 | 124 | /** Show a menu. 125 | * @param menu The menu to show. 126 | * @param runner Callback executed when an item is selected. 127 | * @param x The x-coordinate of the menu. 128 | * @param y The y-coordinate of the menu. 129 | * @param keyboard Set if the request came from a key binding. 130 | * @return 1 if the menu was shown, 0 otherwise. 131 | */ 132 | char ShowMenu(Menu *menu, RunMenuCommandType runner, 133 | int x, int y, char keyboard); 134 | 135 | /** Destroy a menu structure. 136 | * @param menu The menu to destroy. 137 | */ 138 | void DestroyMenu(Menu *menu); 139 | 140 | /** The number of open menus. */ 141 | extern int menuShown; 142 | 143 | #endif /* MENU_H */ 144 | 145 | -------------------------------------------------------------------------------- /src/group.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file group.h 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for handling window groups. 7 | * 8 | */ 9 | 10 | #ifndef GROUP_H 11 | #define GROUP_H 12 | 13 | struct ClientNode; 14 | struct GroupType; 15 | 16 | /** Enumeration of group options. */ 17 | typedef unsigned char OptionType; 18 | #define OPTION_INVALID 0 19 | #define OPTION_STICKY 1 /**< Start in the sticky state. */ 20 | #define OPTION_LAYER 2 /**< Start on a specific layer. */ 21 | #define OPTION_DESKTOP 3 /**< Start on a specific desktop. */ 22 | #define OPTION_ICON 4 /**< Set the icon to use. */ 23 | #define OPTION_NOLIST 5 /**< Don't display in the task list. */ 24 | #define OPTION_BORDER 6 /**< Force a window border. */ 25 | #define OPTION_NOBORDER 7 /**< Don't draw a window border. */ 26 | #define OPTION_TITLE 8 /**< Force a window title bar. */ 27 | #define OPTION_NOTITLE 9 /**< Don't draw a window title bar. */ 28 | #define OPTION_PIGNORE 10 /**< Ignore program-specified location. */ 29 | #define OPTION_MAXIMIZED 11 /**< Start maximized. */ 30 | #define OPTION_MINIMIZED 12 /**< Start minimized. */ 31 | #define OPTION_SHADED 13 /**< Start shaded. */ 32 | #define OPTION_OPACITY 14 /**< Set the opacity. */ 33 | #define OPTION_MAX_H 15 /**< Use horizontal maximization. */ 34 | #define OPTION_MAX_V 16 /**< Use vertical maximization. */ 35 | #define OPTION_NOFOCUS 17 /**< Don't focus on map. */ 36 | #define OPTION_NOSHADE 18 /**< Don't allow shading. */ 37 | #define OPTION_CENTERED 19 /**< Centered placement. */ 38 | #define OPTION_TILED 20 /**< Tiled placement. */ 39 | #define OPTION_IIGNORE 21 /**< Ignore increment when maximized. */ 40 | #define OPTION_NOPAGER 22 /**< Do not show in pager. */ 41 | #define OPTION_NOTURGENT 23 /**< Ignore the urgency hint. */ 42 | #define OPTION_CONSTRAIN 24 /**< Constrain the window to the screen. */ 43 | #define OPTION_FULLSCREEN 25 /**< Start fullscreen. */ 44 | #define OPTION_NOMIN 26 /**< Disallow minimization. */ 45 | #define OPTION_NOMAX 27 /**< Disallow maximization. */ 46 | #define OPTION_NOCLOSE 28 /**< Disallow closing (from title bar). */ 47 | #define OPTION_NOMOVE 29 /**< Disallow moving. */ 48 | #define OPTION_NORESIZE 30 /**< Disallow resizing. */ 49 | #define OPTION_NOFULLSCREEN 31 /**< Disallow fullscreen. */ 50 | #define OPTION_DRAG 32 /**< Pass mouse events to JWM. */ 51 | #define OPTION_ILIST 33 /**< Ignore program-specified list. */ 52 | #define OPTION_IPAGER 34 /**< Ignore program-specified pager. */ 53 | #define OPTION_FIXED 35 /**< Keep on the specified desktop. */ 54 | #define OPTION_AEROSNAP 36 /**< Enable Aero Snap. */ 55 | #define OPTION_NODRAG 37 /**< Disable mod1+drag/resize. */ 56 | #define OPTION_X 38 /**< Window X position. */ 57 | #define OPTION_Y 39 /**< Window Y position. */ 58 | #define OPTION_WIDTH 40 /**< Initial window width. */ 59 | #define OPTION_HEIGHT 41 /**< Initial window height. */ 60 | 61 | /*@{*/ 62 | #define InitializeGroups() (void)(0) 63 | #define StartupGroups() (void)(0) 64 | #define ShutdownGroups() (void)(0) 65 | void DestroyGroups(void); 66 | /*@}*/ 67 | 68 | /** Create an empty group. 69 | * @return An empty group. 70 | */ 71 | struct GroupType *CreateGroup(void); 72 | 73 | /** Add a window class to a group. 74 | * @param gp The group. 75 | * @param pattern A pattern to match with the window class. 76 | */ 77 | void AddGroupClass(struct GroupType *gp, const char *pattern); 78 | 79 | /** Add a window name to a group. 80 | * @param gp The group. 81 | * @param pattern A pattern to match with the window name. 82 | */ 83 | void AddGroupName(struct GroupType *gp, const char *pattern); 84 | 85 | /** Add a window type to a group. 86 | * @param gp The group. 87 | * @param pattern A pattern to match with the window type. 88 | */ 89 | void AddGroupType(struct GroupType *gp, const char *pattern); 90 | 91 | /** Add a window machine to a group. 92 | * @param gp The group. 93 | * @param pattern A pattern to match with the window type. 94 | */ 95 | void AddGroupMachine(struct GroupType *gp, const char *pattern); 96 | 97 | /** Add a group option that doesn't take a value. 98 | * @param gp The group. 99 | * @param option The option. 100 | */ 101 | void AddGroupOption(struct GroupType *gp, OptionType option); 102 | 103 | /** Add a group option that takes a string. 104 | * @param gp The group. 105 | * @param option The option. 106 | * @param value The option value. 107 | */ 108 | void AddGroupOptionString(struct GroupType *gp, OptionType option, 109 | const char *value); 110 | 111 | /** Add a group option that takes an unsigned integer. 112 | * @param gp The group. 113 | * @param option The option. 114 | * @param value The option value. 115 | */ 116 | void AddGroupOptionUnsigned(struct GroupType *gp, OptionType option, 117 | unsigned value); 118 | 119 | /** Add a group option that takes a signed integer. 120 | * @param gp The group. 121 | * @param option The option. 122 | * @param value The option value. 123 | */ 124 | void AddGroupOptionSigned(struct GroupType *gp, OptionType option, 125 | int value); 126 | 127 | /** Apply any matching groups to a client. 128 | * @param np The client. 129 | */ 130 | void ApplyGroups(struct ClientNode *np); 131 | 132 | #endif /* GROUP_H */ 133 | 134 | -------------------------------------------------------------------------------- /src/status.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file status.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for display window move/resize status. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "status.h" 12 | #include "font.h" 13 | #include "screen.h" 14 | #include "main.h" 15 | #include "client.h" 16 | #include "settings.h" 17 | #include "hint.h" 18 | 19 | static Window statusWindow; 20 | static unsigned int statusWindowHeight; 21 | static unsigned int statusWindowWidth; 22 | static int statusWindowX, statusWindowY; 23 | 24 | static void CreateMoveResizeWindow(const ClientNode *np, 25 | StatusWindowType type); 26 | static void DrawMoveResizeWindow(const ClientNode *np, StatusWindowType type); 27 | static void DestroyMoveResizeWindow(void); 28 | static void GetMoveResizeCoordinates(const ClientNode *np, 29 | StatusWindowType type, int *x, int *y); 30 | 31 | /** Get the location to place the status window. */ 32 | void GetMoveResizeCoordinates(const ClientNode *np, StatusWindowType type, 33 | int *x, int *y) 34 | { 35 | 36 | const ScreenType *sp; 37 | 38 | if(type == SW_WINDOW) { 39 | *x = np->x + (np->width - statusWindowWidth) / 2; 40 | *y = np->y + (np->height - statusWindowHeight) / 2; 41 | return; 42 | } 43 | 44 | sp = GetCurrentScreen(np->x, np->y); 45 | 46 | if(type == SW_CORNER) { 47 | *x = sp->x; 48 | *y = sp->y; 49 | return; 50 | } 51 | 52 | /* SW_SCREEN */ 53 | *x = sp->x + (sp->width - statusWindowWidth) / 2; 54 | *y = sp->y + (sp->height - statusWindowHeight) / 2; 55 | 56 | } 57 | 58 | /** Create the status window. */ 59 | void CreateMoveResizeWindow(const ClientNode *np, StatusWindowType type) 60 | { 61 | 62 | XSetWindowAttributes attrs; 63 | long attrMask; 64 | 65 | if(type == SW_OFF) { 66 | return; 67 | } 68 | 69 | statusWindowHeight = GetStringHeight(FONT_MENU) + 10; 70 | statusWindowWidth = GetStringWidth(FONT_MENU, " 00000 x 00000 ") + 2; 71 | 72 | GetMoveResizeCoordinates(np, type, &statusWindowX, &statusWindowY); 73 | 74 | attrMask = 0; 75 | 76 | attrMask |= CWBackPixel; 77 | attrs.background_pixel = colors[COLOR_MENU_BG]; 78 | 79 | attrMask |= CWSaveUnder; 80 | attrs.save_under = True; 81 | 82 | attrMask |= CWOverrideRedirect; 83 | attrs.override_redirect = True; 84 | 85 | statusWindow = JXCreateWindow(display, rootWindow, 86 | statusWindowX, statusWindowY, 87 | statusWindowWidth, statusWindowHeight, 0, 88 | CopyFromParent, InputOutput, CopyFromParent, 89 | attrMask, &attrs); 90 | SetAtomAtom(statusWindow, ATOM_NET_WM_WINDOW_TYPE, 91 | ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION); 92 | 93 | JXMapRaised(display, statusWindow); 94 | 95 | } 96 | 97 | /** Draw the status window. */ 98 | void DrawMoveResizeWindow(const ClientNode *np, StatusWindowType type) 99 | { 100 | 101 | int x, y; 102 | 103 | GetMoveResizeCoordinates(np, type, &x, &y); 104 | if(x != statusWindowX || y != statusWindowX) { 105 | statusWindowX = x; 106 | statusWindowY = y; 107 | JXMoveResizeWindow(display, statusWindow, x, y, 108 | statusWindowWidth, statusWindowHeight); 109 | } 110 | 111 | /* Clear the background. */ 112 | JXClearWindow(display, statusWindow); 113 | 114 | /* Draw the border. */ 115 | if(settings.menuDecorations == DECO_MOTIF) { 116 | JXSetForeground(display, rootGC, colors[COLOR_MENU_UP]); 117 | JXDrawLine(display, statusWindow, rootGC, 118 | 0, 0, statusWindowWidth, 0); 119 | JXDrawLine(display, statusWindow, rootGC, 120 | 0, 0, 0, statusWindowHeight); 121 | JXSetForeground(display, rootGC, colors[COLOR_MENU_DOWN]); 122 | JXDrawLine(display, statusWindow, rootGC, 0, statusWindowHeight - 1, 123 | statusWindowWidth, statusWindowHeight - 1); 124 | JXDrawLine(display, statusWindow, rootGC, statusWindowWidth - 1, 0, 125 | statusWindowWidth - 1, statusWindowHeight); 126 | } else { 127 | JXSetForeground(display, rootGC, colors[COLOR_MENU_DOWN]); 128 | JXDrawRectangle(display, statusWindow, rootGC, 0, 0, 129 | statusWindowWidth - 1, statusWindowHeight - 1); 130 | } 131 | 132 | } 133 | 134 | /** Destroy the status window. */ 135 | void DestroyMoveResizeWindow(void) 136 | { 137 | if(statusWindow != None) { 138 | JXDestroyWindow(display, statusWindow); 139 | statusWindow = None; 140 | } 141 | } 142 | 143 | /** Create a move status window. */ 144 | void CreateMoveWindow(ClientNode *np) 145 | { 146 | CreateMoveResizeWindow(np, settings.moveStatusType); 147 | } 148 | 149 | /** Update the move status window. */ 150 | void UpdateMoveWindow(ClientNode *np) 151 | { 152 | char str[80]; 153 | unsigned int width; 154 | 155 | if(settings.moveStatusType == SW_OFF) { 156 | return; 157 | } 158 | 159 | DrawMoveResizeWindow(np, settings.moveStatusType); 160 | 161 | snprintf(str, sizeof(str), "(%d, %d)", np->x, np->y); 162 | width = GetStringWidth(FONT_MENU, str); 163 | RenderString(statusWindow, FONT_MENU, COLOR_MENU_FG, 164 | (statusWindowWidth - width) / 2, 5, rootWidth, str); 165 | } 166 | 167 | /** Destroy the move status window. */ 168 | void DestroyMoveWindow(void) 169 | { 170 | DestroyMoveResizeWindow(); 171 | } 172 | 173 | /** Create a resize status window. */ 174 | void CreateResizeWindow(ClientNode *np) 175 | { 176 | CreateMoveResizeWindow(np, settings.resizeStatusType); 177 | } 178 | 179 | /** Update the resize status window. */ 180 | void UpdateResizeWindow(ClientNode *np, int gwidth, int gheight) 181 | { 182 | 183 | char str[80]; 184 | unsigned int fontWidth; 185 | 186 | if(settings.resizeStatusType == SW_OFF) { 187 | return; 188 | } 189 | 190 | DrawMoveResizeWindow(np, settings.resizeStatusType); 191 | 192 | snprintf(str, sizeof(str), "%d x %d", gwidth, gheight); 193 | fontWidth = GetStringWidth(FONT_MENU, str); 194 | RenderString(statusWindow, FONT_MENU, COLOR_MENU_FG, 195 | (statusWindowWidth - fontWidth) / 2, 5, rootWidth, str); 196 | 197 | } 198 | 199 | /** Destroy the resize status window. */ 200 | void DestroyResizeWindow(void) 201 | { 202 | DestroyMoveResizeWindow(); 203 | } 204 | -------------------------------------------------------------------------------- /src/action.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file action.c 3 | * @author Joe Wingbermuehle 4 | * 5 | * @brief Tray component actions. 6 | */ 7 | 8 | #include "jwm.h" 9 | #include "action.h" 10 | #include "tray.h" 11 | #include "root.h" 12 | #include "screen.h" 13 | #include "misc.h" 14 | #include "error.h" 15 | #include "cursor.h" 16 | #include "command.h" 17 | #include "desktop.h" 18 | #include "menu.h" 19 | 20 | typedef struct ActionNode { 21 | char *action; 22 | struct ActionNode *next; 23 | int mask; 24 | } ActionNode; 25 | 26 | /** Add an action. */ 27 | void AddAction(ActionNode **actions, const char *action, int mask) 28 | { 29 | ActionNode *ap; 30 | 31 | /* Make sure we actually have an action. */ 32 | if(action == NULL || action[0] == 0 || mask == 0) { 33 | /* Valid (root menu 1). */ 34 | } else if(!strncmp(action, "exec:", 5)) { 35 | /* Valid. */ 36 | } else if(!strncmp(action, "root:", 5)) { 37 | /* Valid. However, the specified root menu may not exist. 38 | * This case is handled in ValidateTrayButtons. 39 | */ 40 | } else if(!strcmp(action, "showdesktop")) { 41 | /* Valid. */ 42 | } else { 43 | /* Invalid; don't add the action. */ 44 | Warning(_("invalid action: \"%s\""), action); 45 | return; 46 | } 47 | 48 | ap = Allocate(sizeof(ActionNode)); 49 | ap->action = CopyString(action); 50 | ap->mask = mask; 51 | ap->next = *actions; 52 | *actions = ap; 53 | } 54 | 55 | /** Destroy an action list. */ 56 | void DestroyActions(ActionNode *actions) 57 | { 58 | while(actions) { 59 | ActionNode *next = actions->next; 60 | Release(actions->action); 61 | Release(actions); 62 | actions = next; 63 | } 64 | } 65 | 66 | /** Process a button press. */ 67 | void ProcessActionPress(struct ActionNode *actions, 68 | struct TrayComponentType *cp, 69 | int x, int y, int button) 70 | { 71 | const ScreenType *sp; 72 | const ActionNode *ap; 73 | const int mask = 1 << button; 74 | int mwidth, mheight; 75 | int menu; 76 | 77 | if(JUNLIKELY(menuShown)) { 78 | return; 79 | } 80 | if (x < -1 || x > cp->width) { 81 | return; 82 | } 83 | if (y < -1 || y > cp->height) { 84 | return; 85 | } 86 | 87 | menu = -1; 88 | for(ap = actions; ap; ap = ap->next) { 89 | if(ap->mask & mask) { 90 | if(ap->action && ap->action[0]) { 91 | if(strncmp(ap->action, "root:", 5) != 0) { 92 | if(button == Button4 || button == Button5) { 93 | 94 | /* Don't wait for a release if the scroll wheel is used. */ 95 | if(!strncmp(ap->action, "exec:", 5)) { 96 | RunCommand(ap->action + 5); 97 | } else if(!strcmp(ap->action, "showdesktop")) { 98 | ShowDesktop(); 99 | } 100 | 101 | } else { 102 | 103 | if(!GrabMouse(cp->tray->window)) { 104 | return; 105 | } 106 | 107 | /* Show the button being pressed. */ 108 | cp->grabbed = 1; 109 | if(cp->Redraw) { 110 | (cp->Redraw)(cp); 111 | UpdateSpecificTray(cp->tray, cp); 112 | } 113 | } 114 | return; 115 | 116 | } else { 117 | menu = GetRootMenuIndexFromString(&ap->action[5]); 118 | } 119 | } else { 120 | menu = 1; 121 | } 122 | break; 123 | } 124 | } 125 | if(menu < 0) { 126 | return; 127 | } 128 | 129 | GetRootMenuSize(menu, &mwidth, &mheight); 130 | sp = GetCurrentScreen(cp->screenx, cp->screeny); 131 | if(cp->tray->layout == LAYOUT_HORIZONTAL) { 132 | x = cp->screenx - 1; 133 | if(cp->screeny + cp->height / 2 < sp->y + sp->height / 2) { 134 | y = cp->screeny + cp->height; 135 | } else { 136 | y = cp->screeny - mheight; 137 | } 138 | } else { 139 | y = cp->screeny - 1; 140 | if(cp->screenx + cp->width / 2 < sp->x + sp->width / 2) { 141 | x = cp->screenx + cp->width; 142 | } else { 143 | x = cp->screenx - mwidth; 144 | } 145 | } 146 | 147 | cp->grabbed = 1; 148 | if(cp->Redraw) { 149 | (cp->Redraw)(cp); 150 | UpdateSpecificTray(cp->tray, cp); 151 | } 152 | if(ShowRootMenu(menu, x, y, 0)) { 153 | cp->grabbed = 0; 154 | if(cp->Redraw) { 155 | (cp->Redraw)(cp); 156 | UpdateSpecificTray(cp->tray, cp); 157 | } 158 | } 159 | } 160 | 161 | /** Process a button release. */ 162 | void ProcessActionRelease(struct ActionNode *actions, 163 | struct TrayComponentType *cp, 164 | int x, int y, int button) 165 | { 166 | const ActionNode *ap; 167 | const int mask = 1 << button; 168 | 169 | if(JUNLIKELY(menuShown)) { 170 | return; 171 | } 172 | 173 | cp->grabbed = 0; 174 | if(cp->Redraw) { 175 | (cp->Redraw)(cp); 176 | UpdateSpecificTray(cp->tray, cp); 177 | } 178 | 179 | /* Since we grab the mouse, make sure the mouse is actually over 180 | * the button. */ 181 | if(x < -1 || x > cp->width) { 182 | return; 183 | } 184 | if(y < -1 || y > cp->height) { 185 | return; 186 | } 187 | 188 | /* Run the action (if any). */ 189 | for(ap = actions; ap; ap = ap->next) { 190 | if(ap->mask & mask) { 191 | if(ap->action && strlen(ap->action) > 0) { 192 | if(!strncmp(ap->action, "exec:", 5)) { 193 | RunCommand(ap->action + 5); 194 | } else if(!strcmp(ap->action, "showdesktop")) { 195 | ShowDesktop(); 196 | } 197 | } 198 | return; 199 | } 200 | } 201 | } 202 | 203 | /** Validate actions. */ 204 | void ValidateActions(const ActionNode *actions) 205 | { 206 | const ActionNode *ap; 207 | for(ap = actions; ap; ap = ap->next) { 208 | if(ap->action && !strncmp(ap->action, "root:", 5)) { 209 | const int bindex = GetRootMenuIndexFromString(&ap->action[5]); 210 | if(JUNLIKELY(!IsRootMenuDefined(bindex))) { 211 | Warning(_("action: root menu \"%s\" not defined"), 212 | &ap->action[5]); 213 | } 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/render.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file render.c 3 | * @author Joe Wingbermuehle 4 | * @date 2005-2006 5 | * 6 | * @brief Functions to render icons using the XRender extension. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "render.h" 12 | #include "icon.h" 13 | #include "image.h" 14 | #include "main.h" 15 | #include "color.h" 16 | #include "misc.h" 17 | 18 | /** Draw a scaled icon. */ 19 | void PutScaledRenderIcon(const IconNode *icon, 20 | const ScaledIconNode *node, 21 | Drawable d, int x, int y, int width, int height) 22 | { 23 | 24 | #ifdef USE_XRENDER 25 | 26 | Picture source; 27 | 28 | Assert(icon); 29 | Assert(haveRender); 30 | 31 | source = node->image; 32 | if(source != None) { 33 | 34 | XRenderPictureAttributes pa; 35 | XTransform xf; 36 | int xscale, yscale; 37 | int nwidth, nheight; 38 | Picture dest; 39 | Picture alpha = node->mask; 40 | XRenderPictFormat *fp = JXRenderFindVisualFormat(display, rootVisual); 41 | Assert(fp); 42 | 43 | pa.subwindow_mode = IncludeInferiors; 44 | dest = JXRenderCreatePicture(display, d, fp, CPSubwindowMode, &pa); 45 | 46 | width = width == 0 ? node->width : width; 47 | height = height == 0 ? node->height : height; 48 | if(icon->preserveAspect) { 49 | const int ratio = (icon->width << 16) / icon->height; 50 | nwidth = Min(width, (height * ratio) >> 16); 51 | nheight = Min(height, (nwidth << 16) / ratio); 52 | nwidth = (nheight * ratio) >> 16; 53 | nwidth = Max(1, nwidth); 54 | nheight = Max(1, nheight); 55 | x += (width - nwidth) / 2; 56 | y += (height - nheight) / 2; 57 | } else { 58 | nwidth = width; 59 | nheight = height; 60 | } 61 | xscale = (node->width << 16) / nwidth; 62 | yscale = (node->height << 16) / nheight; 63 | 64 | memset(&xf, 0, sizeof(xf)); 65 | xf.matrix[0][0] = xscale; 66 | xf.matrix[1][1] = yscale; 67 | xf.matrix[2][2] = 65536; 68 | XRenderSetPictureTransform(display, source, &xf); 69 | XRenderSetPictureFilter(display, source, FilterBest, NULL, 0); 70 | XRenderSetPictureTransform(display, alpha, &xf); 71 | XRenderSetPictureFilter(display, alpha, FilterBest, NULL, 0); 72 | 73 | JXRenderComposite(display, PictOpOver, source, alpha, dest, 74 | 0, 0, 0, 0, x, y, width, height); 75 | 76 | JXRenderFreePicture(display, dest); 77 | 78 | } 79 | 80 | #endif 81 | 82 | } 83 | 84 | /** Create a scaled icon. */ 85 | ScaledIconNode *CreateScaledRenderIcon(ImageNode *image, long fg) 86 | { 87 | 88 | ScaledIconNode *result = NULL; 89 | 90 | #ifdef USE_XRENDER 91 | 92 | XRenderPictFormat *fp; 93 | XColor color; 94 | GC maskGC; 95 | XImage *destImage; 96 | XImage *destMask; 97 | Pixmap pmap, mask; 98 | const unsigned width = image->width; 99 | const unsigned height = image->height; 100 | unsigned perLine; 101 | int x, y; 102 | int maskLine; 103 | 104 | Assert(haveRender); 105 | 106 | result = Allocate(sizeof(ScaledIconNode)); 107 | result->fg = fg; 108 | result->width = width; 109 | result->height = height; 110 | 111 | mask = JXCreatePixmap(display, rootWindow, width, height, 8); 112 | maskGC = JXCreateGC(display, mask, 0, NULL); 113 | pmap = JXCreatePixmap(display, rootWindow, width, height, rootDepth); 114 | 115 | destImage = JXCreateImage(display, rootVisual, rootDepth, 116 | ZPixmap, 0, NULL, width, height, 8, 0); 117 | destImage->data = Allocate(sizeof(unsigned long) * width * height); 118 | 119 | destMask = JXCreateImage(display, rootVisual, 8, ZPixmap, 120 | 0, NULL, width, height, 8, 0); 121 | destMask->data = Allocate(width * height); 122 | 123 | if(image->bitmap) { 124 | perLine = (image->width >> 3) + ((image->width & 7) ? 1 : 0); 125 | } else { 126 | perLine = image->width; 127 | } 128 | maskLine = 0; 129 | for(y = 0; y < height; y++) { 130 | const int yindex = y * perLine; 131 | for(x = 0; x < width; x++) { 132 | if(image->bitmap) { 133 | 134 | const int offset = yindex + (x >> 3); 135 | const int mask = 1 << (x & 7); 136 | unsigned long alpha = 0; 137 | if(image->data[offset] & mask) { 138 | alpha = 255; 139 | XPutPixel(destImage, x, y, fg); 140 | } 141 | destMask->data[maskLine + x] = alpha; 142 | 143 | } else { 144 | 145 | const int index = 4 * (yindex + x); 146 | const unsigned long alpha = image->data[index]; 147 | color.red = image->data[index + 1]; 148 | color.red |= color.red << 8; 149 | color.green = image->data[index + 2]; 150 | color.green |= color.green << 8; 151 | color.blue = image->data[index + 3]; 152 | color.blue |= color.blue << 8; 153 | 154 | color.red = (color.red * alpha) >> 8; 155 | color.green = (color.green * alpha) >> 8; 156 | color.blue = (color.blue * alpha) >> 8; 157 | 158 | GetColor(&color); 159 | XPutPixel(destImage, x, y, color.pixel); 160 | destMask->data[maskLine + x] = alpha; 161 | } 162 | } 163 | maskLine += destMask->bytes_per_line; 164 | } 165 | 166 | /* Render the image data to the image pixmap. */ 167 | JXPutImage(display, pmap, rootGC, destImage, 0, 0, 0, 0, width, height); 168 | Release(destImage->data); 169 | destImage->data = NULL; 170 | JXDestroyImage(destImage); 171 | 172 | /* Render the alpha data to the mask pixmap. */ 173 | JXPutImage(display, mask, maskGC, destMask, 0, 0, 0, 0, width, height); 174 | Release(destMask->data); 175 | destMask->data = NULL; 176 | JXDestroyImage(destMask); 177 | JXFreeGC(display, maskGC); 178 | 179 | /* Create the alpha picture. */ 180 | fp = JXRenderFindStandardFormat(display, PictStandardA8); 181 | Assert(fp); 182 | result->mask = JXRenderCreatePicture(display, mask, fp, 0, NULL); 183 | JXFreePixmap(display, mask); 184 | 185 | /* Create the render picture. */ 186 | fp = JXRenderFindVisualFormat(display, rootVisual); 187 | Assert(fp); 188 | result->image = JXRenderCreatePicture(display, pmap, fp, 0, NULL); 189 | JXFreePixmap(display, pmap); 190 | 191 | #endif 192 | 193 | return result; 194 | 195 | } 196 | -------------------------------------------------------------------------------- /src/command.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file command.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Handle running startup, shutdown, and restart commands. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "command.h" 12 | #include "misc.h" 13 | #include "main.h" 14 | #include "error.h" 15 | #include "timing.h" 16 | 17 | #include 18 | 19 | /** Structure to represent a list of commands. */ 20 | typedef struct CommandNode { 21 | char *command; /**< The command. */ 22 | struct CommandNode *next; /**< The next command in the list. */ 23 | } CommandNode; 24 | 25 | static CommandNode *startupCommands = NULL; 26 | static CommandNode *shutdownCommands = NULL; 27 | static CommandNode *restartCommands = NULL; 28 | 29 | static void RunCommands(CommandNode *commands); 30 | static void ReleaseCommands(CommandNode **commands); 31 | static void AddCommand(CommandNode **commands, const char *command); 32 | 33 | /** Process startup/restart commands. */ 34 | void StartupCommands(void) 35 | { 36 | if(isRestarting) { 37 | RunCommands(restartCommands); 38 | } else { 39 | RunCommands(startupCommands); 40 | } 41 | } 42 | 43 | /** Process shutdown commands. */ 44 | void ShutdownCommands(void) 45 | { 46 | if(!shouldRestart) { 47 | RunCommands(shutdownCommands); 48 | } 49 | } 50 | 51 | /** Destroy the command lists. */ 52 | void DestroyCommands(void) 53 | { 54 | ReleaseCommands(&startupCommands); 55 | ReleaseCommands(&shutdownCommands); 56 | ReleaseCommands(&restartCommands); 57 | } 58 | 59 | /** Run the commands in a command list. */ 60 | void RunCommands(CommandNode *commands) { 61 | 62 | CommandNode *cp; 63 | 64 | for(cp = commands; cp; cp = cp->next) { 65 | RunCommand(cp->command); 66 | } 67 | 68 | } 69 | 70 | /** Release a command list. */ 71 | void ReleaseCommands(CommandNode **commands) 72 | { 73 | 74 | CommandNode *cp; 75 | 76 | Assert(commands); 77 | while(*commands) { 78 | cp = (*commands)->next; 79 | Release((*commands)->command); 80 | Release(*commands); 81 | *commands = cp; 82 | } 83 | 84 | } 85 | 86 | /** Add a command to a command list. */ 87 | void AddCommand(CommandNode **commands, const char *command) 88 | { 89 | 90 | CommandNode *cp; 91 | 92 | Assert(commands); 93 | if(!command) { 94 | return; 95 | } 96 | 97 | cp = Allocate(sizeof(CommandNode)); 98 | cp->next = *commands; 99 | *commands = cp; 100 | cp->command = CopyString(command); 101 | 102 | } 103 | 104 | /** Add a startup command. */ 105 | void AddStartupCommand(const char *command) 106 | { 107 | AddCommand(&startupCommands, command); 108 | } 109 | 110 | /** Add a shutdown command. */ 111 | void AddShutdownCommand(const char *command) { 112 | AddCommand(&shutdownCommands, command); 113 | } 114 | 115 | /** Add a restart command. */ 116 | void AddRestartCommand(const char *command) { 117 | AddCommand(&restartCommands, command); 118 | } 119 | 120 | /** Execute an external program. */ 121 | void RunCommand(const char *command) 122 | { 123 | 124 | const char *displayString; 125 | 126 | if(JUNLIKELY(!command)) { 127 | return; 128 | } 129 | 130 | displayString = DisplayString(display); 131 | if(!fork()) { 132 | close(ConnectionNumber(display)); 133 | if(displayString && displayString[0]) { 134 | const size_t var_len = strlen(displayString) + 9; 135 | char *str = malloc(var_len); 136 | snprintf(str, var_len, "DISPLAY=%s", displayString); 137 | putenv(str); 138 | } 139 | setsid(); 140 | execl(SHELL_NAME, SHELL_NAME, "-c", command, NULL); 141 | Warning(_("exec failed: (%s) %s"), SHELL_NAME, command); 142 | exit(EXIT_SUCCESS); 143 | } 144 | 145 | } 146 | 147 | /** Reads the output of an exernal program. */ 148 | char *ReadFromProcess(const char *command, unsigned timeout_ms) 149 | { 150 | const unsigned BLOCK_SIZE = 256; 151 | pid_t pid; 152 | int fds[2]; 153 | 154 | if(pipe(fds)) { 155 | Warning(_("could not create pipe")); 156 | return NULL; 157 | } 158 | if(fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1) { 159 | /* We don't return here since we can still process the output 160 | * of the command, but the timeout won't work. */ 161 | Warning(_("could not set O_NONBLOCK")); 162 | } 163 | 164 | pid = fork(); 165 | if(pid == 0) { 166 | /* The child process. */ 167 | close(ConnectionNumber(display)); 168 | close(fds[0]); 169 | dup2(fds[1], 1); /* stdout */ 170 | setsid(); 171 | execl("/bin/sh", "/bin/sh", "-c", command, NULL); 172 | Warning(_("exec failed: (%s) %s"), SHELL_NAME, command); 173 | exit(EXIT_SUCCESS); 174 | } else if(pid > 0) { 175 | char *buffer; 176 | unsigned buffer_size, max_size; 177 | TimeType start_time, current_time; 178 | 179 | max_size = BLOCK_SIZE; 180 | buffer_size = 0; 181 | buffer = Allocate(max_size); 182 | 183 | GetCurrentTime(&start_time); 184 | for(;;) { 185 | struct timeval tv; 186 | unsigned long diff_ms; 187 | fd_set fs; 188 | int rc; 189 | 190 | /* Make sure we have room to read. */ 191 | if(buffer_size + BLOCK_SIZE > max_size) { 192 | max_size *= 2; 193 | buffer = Reallocate(buffer, max_size); 194 | } 195 | 196 | FD_ZERO(&fs); 197 | FD_SET(fds[0], &fs); 198 | 199 | /* Determine the max time to sit in select. */ 200 | GetCurrentTime(¤t_time); 201 | diff_ms = GetTimeDifference(&start_time, ¤t_time); 202 | diff_ms = timeout_ms > diff_ms ? (timeout_ms - diff_ms) : 0; 203 | tv.tv_sec = diff_ms / 1000; 204 | tv.tv_usec = (diff_ms % 1000) * 1000; 205 | 206 | /* Wait for data (or a timeout). */ 207 | rc = select(fds[0] + 1, &fs, NULL, &fs, &tv); 208 | if(rc == 0) { 209 | /* Timeout */ 210 | Warning(_("timeout: %s did not complete in %u milliseconds"), 211 | command, timeout_ms); 212 | kill(pid, SIGKILL); 213 | waitpid(pid, NULL, 0); 214 | break; 215 | } 216 | 217 | rc = read(fds[0], &buffer[buffer_size], BLOCK_SIZE); 218 | if(rc > 0) { 219 | buffer_size += rc; 220 | } else { 221 | /* Process exited, check for any leftovers and return. */ 222 | do { 223 | if(buffer_size + BLOCK_SIZE > max_size) { 224 | max_size *= 2; 225 | buffer = Reallocate(buffer, max_size); 226 | } 227 | rc = read(fds[0], &buffer[buffer_size], BLOCK_SIZE); 228 | buffer_size += (rc > 0) ? rc : 0; 229 | } while(rc > 0); 230 | break; 231 | } 232 | } 233 | close(fds[1]); 234 | buffer[buffer_size] = 0; 235 | return buffer; 236 | } 237 | 238 | return NULL; 239 | } 240 | -------------------------------------------------------------------------------- /src/cursor.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cursor.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Cursor functions. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "cursor.h" 12 | #include "main.h" 13 | 14 | /** Cursor types. */ 15 | typedef enum { 16 | CURSOR_DEFAULT, 17 | CURSOR_MOVE, 18 | CURSOR_NORTH, 19 | CURSOR_SOUTH, 20 | CURSOR_EAST, 21 | CURSOR_WEST, 22 | CURSOR_NE, 23 | CURSOR_NW, 24 | CURSOR_SE, 25 | CURSOR_SW, 26 | CURSOR_CHOOSE, 27 | CURSOR_COUNT 28 | } CursorType; 29 | 30 | /** Cursors to load for the various cursor types. 31 | * This must be ordered the same as CursorType. 32 | */ 33 | static const unsigned int cursor_shapes[CURSOR_COUNT] = { 34 | XC_left_ptr, 35 | XC_fleur, 36 | XC_top_side, 37 | XC_bottom_side, 38 | XC_right_side, 39 | XC_left_side, 40 | XC_top_right_corner, 41 | XC_top_left_corner, 42 | XC_bottom_right_corner, 43 | XC_bottom_left_corner, 44 | XC_tcross 45 | }; 46 | 47 | static Cursor cursors[CURSOR_COUNT]; 48 | 49 | static Cursor GetResizeCursor(MouseContextType context); 50 | static Cursor CreateCursor(unsigned int shape); 51 | 52 | static int mousex; 53 | static int mousey; 54 | static Window mousew; 55 | 56 | /** Startup cursor support. */ 57 | void StartupCursors(void) 58 | { 59 | 60 | Window win1; 61 | int winx, winy; 62 | unsigned int mask; 63 | int x; 64 | 65 | for(x = 0; x < CURSOR_COUNT; x++) { 66 | cursors[x] = CreateCursor(cursor_shapes[x]); 67 | } 68 | 69 | JXQueryPointer(display, rootWindow, &win1, &mousew, 70 | &mousex, &mousey, &winx, &winy, &mask); 71 | 72 | } 73 | 74 | /** Create a cursor for the specified shape. */ 75 | Cursor CreateCursor(unsigned int shape) 76 | { 77 | return JXCreateFontCursor(display, shape); 78 | } 79 | 80 | /** Shutdown cursor support. */ 81 | void ShutdownCursors(void) 82 | { 83 | int x; 84 | for(x = 0; x < CURSOR_COUNT; x++) { 85 | JXFreeCursor(display, cursors[x]); 86 | } 87 | } 88 | 89 | /** Get the cursor for the specified location on the frame. */ 90 | Cursor GetFrameCursor(MouseContextType context) 91 | { 92 | switch(context & MC_MASK) { 93 | case MC_BORDER: 94 | return GetResizeCursor(context); 95 | case MC_CLOSE: 96 | break; 97 | case MC_MAXIMIZE: 98 | break; 99 | case MC_MINIMIZE: 100 | break; 101 | case MC_MOVE: 102 | break; 103 | default: 104 | break; 105 | } 106 | return cursors[CURSOR_DEFAULT]; 107 | } 108 | 109 | /** Get the cursor for resizing on the specified frame location. */ 110 | Cursor GetResizeCursor(MouseContextType context) 111 | { 112 | if(context & MC_BORDER_N) { 113 | if(context & MC_BORDER_E) { 114 | return cursors[CURSOR_NE]; 115 | } else if(context & MC_BORDER_W) { 116 | return cursors[CURSOR_NW]; 117 | } else { 118 | return cursors[CURSOR_NORTH]; 119 | } 120 | } else if(context & MC_BORDER_S) { 121 | if(context & MC_BORDER_E) { 122 | return cursors[CURSOR_SE]; 123 | } else if(context & MC_BORDER_W) { 124 | return cursors[CURSOR_SW]; 125 | } else { 126 | return cursors[CURSOR_SOUTH]; 127 | } 128 | } else if(context & MC_BORDER_E) { 129 | return cursors[CURSOR_EAST]; 130 | } else if(context & MC_BORDER_W) { 131 | return cursors[CURSOR_WEST]; 132 | } else { 133 | return cursors[CURSOR_DEFAULT]; 134 | } 135 | } 136 | 137 | /** Grab the mouse for resizing a window. */ 138 | char GrabMouseForResize(MouseContextType context) 139 | { 140 | Cursor cur; 141 | int result; 142 | unsigned int mask; 143 | 144 | cur = GetFrameCursor(context); 145 | mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask; 146 | result = JXGrabPointer(display, rootWindow, False, mask, 147 | GrabModeAsync, GrabModeAsync, None, 148 | cur, CurrentTime); 149 | if(JLIKELY(result == GrabSuccess)) { 150 | mousew = rootWindow; 151 | return 1; 152 | } else { 153 | return 0; 154 | } 155 | } 156 | 157 | /** Grab the mouse for moving a window. */ 158 | char GrabMouseForMove(void) 159 | { 160 | int result; 161 | unsigned int mask; 162 | mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask; 163 | result = JXGrabPointer(display, rootWindow, False, mask, 164 | GrabModeAsync, GrabModeAsync, None, 165 | cursors[CURSOR_MOVE], CurrentTime); 166 | if(JLIKELY(result == GrabSuccess)) { 167 | mousew = rootWindow; 168 | return 1; 169 | } else { 170 | return 0; 171 | } 172 | } 173 | 174 | /** Grab the mouse. */ 175 | char GrabMouse(Window w) 176 | { 177 | int result; 178 | unsigned int mask; 179 | mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask; 180 | result = JXGrabPointer(display, w, False, mask, 181 | GrabModeAsync, GrabModeAsync, None, 182 | cursors[CURSOR_DEFAULT], CurrentTime); 183 | if(JLIKELY(result == GrabSuccess)) { 184 | mousew = w; 185 | return 1; 186 | } else { 187 | return 0; 188 | } 189 | } 190 | 191 | /** Grab the mouse for choosing a window. */ 192 | char GrabMouseForChoose(void) 193 | { 194 | int result; 195 | unsigned int mask; 196 | mask = ButtonPressMask | ButtonReleaseMask; 197 | result = JXGrabPointer(display, rootWindow, False, mask, 198 | GrabModeAsync, GrabModeAsync, None, 199 | cursors[CURSOR_CHOOSE], CurrentTime); 200 | if(JLIKELY(result == GrabSuccess)) { 201 | mousew = rootWindow; 202 | return 1; 203 | } else { 204 | return 0; 205 | } 206 | } 207 | 208 | /** Set the default cursor for a window. */ 209 | void SetDefaultCursor(Window w) 210 | { 211 | if(JLIKELY(w != None)) { 212 | JXDefineCursor(display, w, cursors[CURSOR_DEFAULT]); 213 | } 214 | } 215 | 216 | /** Move the mouse to the specified coordinates on a window. */ 217 | void MoveMouse(Window win, int x, int y) 218 | { 219 | Window win1; 220 | int winx, winy; 221 | unsigned int mask; 222 | JXWarpPointer(display, None, win, 0, 0, 0, 0, x, y); 223 | JXQueryPointer(display, rootWindow, &win1, &mousew, 224 | &mousex, &mousey, &winx, &winy, &mask); 225 | } 226 | 227 | /** Set the current mouse position. */ 228 | void SetMousePosition(int x, int y, Window w) 229 | { 230 | mousex = x; 231 | mousey = y; 232 | mousew = w; 233 | } 234 | 235 | /** Get the current mouse position. */ 236 | void GetMousePosition(int *x, int *y, Window *w) 237 | { 238 | *x = mousex; 239 | *y = mousey; 240 | *w = mousew; 241 | } 242 | 243 | /** Get the current mouse buttons pressed. */ 244 | unsigned int GetMouseMask(void) 245 | { 246 | Window win1; 247 | int winx, winy; 248 | unsigned int mask; 249 | JXQueryPointer(display, rootWindow, &win1, &mousew, 250 | &mousex, &mousey, &winx, &winy, &mask); 251 | return mask; 252 | } 253 | -------------------------------------------------------------------------------- /src/root.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file root.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Root menu functions. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "root.h" 12 | #include "menu.h" 13 | #include "client.h" 14 | #include "error.h" 15 | #include "confirm.h" 16 | #include "misc.h" 17 | #include "winmenu.h" 18 | #include "command.h" 19 | #include "parse.h" 20 | #include "settings.h" 21 | #include "desktop.h" 22 | 23 | /** Number of root menus to support. */ 24 | #define ROOT_MENU_COUNT 36 25 | 26 | static Menu *rootMenu[ROOT_MENU_COUNT]; 27 | 28 | static void ExitHandler(ClientNode *np); 29 | 30 | static void RunRootCommand(MenuAction *action, unsigned button); 31 | 32 | /** Initialize root menu data. */ 33 | void InitializeRootMenu(void) 34 | { 35 | unsigned int x; 36 | for(x = 0; x < ROOT_MENU_COUNT; x++) { 37 | rootMenu[x] = NULL; 38 | } 39 | } 40 | 41 | /** Startup root menus. */ 42 | void StartupRootMenu(void) 43 | { 44 | 45 | unsigned int x, y; 46 | char found; 47 | 48 | for(x = 0; x < ROOT_MENU_COUNT; x++) { 49 | if(rootMenu[x]) { 50 | found = 0; 51 | for(y = 0; y < x; y++) { 52 | if(rootMenu[y] == rootMenu[x]) { 53 | found = 1; 54 | break; 55 | } 56 | } 57 | if(!found) { 58 | InitializeMenu(rootMenu[x]); 59 | } 60 | } 61 | } 62 | 63 | } 64 | 65 | /** Destroy root menu data. */ 66 | void DestroyRootMenu(void) 67 | { 68 | 69 | unsigned int x, y; 70 | 71 | for(x = 0; x < ROOT_MENU_COUNT; x++) { 72 | if(rootMenu[x]) { 73 | DestroyMenu(rootMenu[x]); 74 | for(y = x + 1; y < ROOT_MENU_COUNT; y++) { 75 | if(rootMenu[x] == rootMenu[y]) { 76 | rootMenu[y] = NULL; 77 | } 78 | } 79 | rootMenu[x] = NULL; 80 | } 81 | } 82 | 83 | } 84 | 85 | /** Get the index for a root menu character. */ 86 | int GetRootMenuIndex(char ch) 87 | { 88 | if(ch >= '0' && ch <= '9') { 89 | return ch - '0'; 90 | } else if(ch >= 'A' && ch <= 'Z') { 91 | return ch - 'A' + 10; 92 | } else if(ch >= 'a' && ch <= 'z') { 93 | return ch - 'a' + 10; 94 | } else { 95 | return -1; 96 | } 97 | } 98 | 99 | /** Get the index for a root menu string. */ 100 | int GetRootMenuIndexFromString(const char *str) 101 | { 102 | unsigned int temp = 0; 103 | while(*str && IsSpace(*str, &temp)) { 104 | str += 1; 105 | } 106 | if(JUNLIKELY(!*str)) { 107 | return -1; 108 | } 109 | const int result = GetRootMenuIndex(*str); 110 | str += 1; 111 | while(*str && IsSpace(*str, &temp)) { 112 | str += 1; 113 | } 114 | return *str ? -1 : result; 115 | } 116 | 117 | /** Set a root menu. */ 118 | void SetRootMenu(const char *indexes, Menu *m) 119 | { 120 | 121 | unsigned x; 122 | 123 | /* Loop over each index to consider. */ 124 | for(x = 0; indexes[x]; x++) { 125 | 126 | /* Get the index and make sure it's in range. */ 127 | const int index = GetRootMenuIndex(indexes[x]); 128 | if(JUNLIKELY(index < 0)) { 129 | Warning(_("invalid root menu specified: \"%c\""), indexes[x]); 130 | continue; 131 | } 132 | 133 | if(rootMenu[index] && rootMenu[index] != m) { 134 | 135 | /* See if replacing this value will cause an orphan. */ 136 | unsigned y; 137 | char found = 0; 138 | for(y = 0; y < ROOT_MENU_COUNT; y++) { 139 | if(index != y && rootMenu[y] == rootMenu[index]) { 140 | found = 1; 141 | break; 142 | } 143 | } 144 | 145 | /* If we have an orphan, destroy it. */ 146 | if(!found) { 147 | DestroyMenu(rootMenu[index]); 148 | } 149 | 150 | } 151 | 152 | rootMenu[index] = m; 153 | 154 | } 155 | 156 | } 157 | 158 | /** Determine if the specified root menu is defined. */ 159 | char IsRootMenuDefined(int index) 160 | { 161 | if(index >= 0 && index < ROOT_MENU_COUNT && rootMenu[index]) { 162 | return 1; 163 | } else { 164 | return 0; 165 | } 166 | } 167 | 168 | /** Determine the size of a root menu. */ 169 | void GetRootMenuSize(int index, int *width, int *height) 170 | { 171 | 172 | if(!rootMenu[index]) { 173 | *width = 0; 174 | *height = 0; 175 | return; 176 | } 177 | *width = rootMenu[index]->width; 178 | *height = rootMenu[index]->height; 179 | 180 | } 181 | 182 | /** Show a root menu. */ 183 | char ShowRootMenu(int index, int x, int y, char keyboard) 184 | { 185 | if(!rootMenu[index]) { 186 | return 0; 187 | } 188 | if(menuShown) { 189 | return 1; 190 | } 191 | if(rootMenu[index]->dynamic) { 192 | Menu *menu = rootMenu[index]; 193 | menu = ParseDynamicMenu(menu->timeout_ms, menu->dynamic); 194 | if(menu) { 195 | InitializeMenu(menu); 196 | ShowMenu(menu, RunRootCommand, x, y, keyboard); 197 | DestroyMenu(menu); 198 | return 1; 199 | } 200 | } 201 | ShowMenu(rootMenu[index], RunRootCommand, x, y, keyboard); 202 | return 1; 203 | } 204 | 205 | /** Exit callback for the exit menu item. */ 206 | void ExitHandler(ClientNode *np) 207 | { 208 | shouldExit = 1; 209 | } 210 | 211 | /** Restart callback for the restart menu item. */ 212 | void Restart(void) 213 | { 214 | shouldRestart = 1; 215 | shouldExit = 1; 216 | } 217 | 218 | /** Exit with optional confirmation. */ 219 | void Exit(char confirm) 220 | { 221 | if(confirm) { 222 | ShowConfirmDialog(NULL, ExitHandler, 223 | _("Exit JWM"), 224 | _("Are you sure?"), 225 | NULL); 226 | } else { 227 | ExitHandler(NULL); 228 | } 229 | } 230 | 231 | /** Reload the menu. */ 232 | void ReloadMenu(void) 233 | { 234 | shouldReload = 1; 235 | if(!menuShown) { 236 | ShutdownRootMenu(); 237 | DestroyRootMenu(); 238 | InitializeRootMenu(); 239 | ParseConfig(configPath); 240 | StartupRootMenu(); 241 | shouldReload = 0; 242 | } 243 | } 244 | 245 | /** Root menu callback. */ 246 | void RunRootCommand(MenuAction *action, unsigned button) 247 | { 248 | 249 | switch(action->type) { 250 | case MA_EXECUTE: 251 | RunCommand(action->str); 252 | break; 253 | case MA_RESTART: 254 | Restart(); 255 | break; 256 | case MA_EXIT: 257 | if(exitCommand) { 258 | Release(exitCommand); 259 | } 260 | exitCommand = CopyString(action->str); 261 | Exit(action->value); 262 | break; 263 | case MA_DESKTOP: 264 | ChangeDesktop(action->value); 265 | break; 266 | 267 | case MA_SENDTO: 268 | case MA_LAYER: 269 | case MA_MAXIMIZE: 270 | case MA_MINIMIZE: 271 | case MA_RESTORE: 272 | case MA_SHADE: 273 | case MA_MOVE: 274 | case MA_RESIZE: 275 | case MA_KILL: 276 | case MA_CLOSE: 277 | ChooseWindow(action); 278 | break; 279 | 280 | default: 281 | break; 282 | } 283 | 284 | } 285 | 286 | -------------------------------------------------------------------------------- /src/misc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file misc.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Miscellaneous functions and macros. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "misc.h" 12 | #include "debug.h" 13 | 14 | static char ToLower(char ch); 15 | static char IsSymbolic(char ch); 16 | static char *GetSymbolName(const char *str); 17 | static void ReplaceSymbol(char **str, unsigned int offset, 18 | const char *name, const char *value); 19 | 20 | /** Determine if a character is a space character. */ 21 | char IsSpace(char ch, unsigned int *lineNumber) 22 | { 23 | switch(ch) { 24 | case ' ': 25 | case '\t': 26 | case '\r': 27 | return 1; 28 | case '\n': 29 | *lineNumber += 1; 30 | return 1; 31 | default: 32 | return 0; 33 | } 34 | } 35 | 36 | /** Convert to lower case. */ 37 | char ToLower(char ch) 38 | { 39 | /* This should work in either ASCII or EBCDIC. */ 40 | if( (ch >= 'A' && ch <= 'I') 41 | || (ch >= 'J' && ch <= 'R') 42 | || (ch >= 'S' && ch <= 'Z')) { 43 | return ch - 'A' + 'a'; 44 | } else { 45 | return ch; 46 | } 47 | } 48 | 49 | /** Determine if a character is a valid for a shell variable. */ 50 | char IsSymbolic(char ch) 51 | { 52 | /* This should work in either ASCII or EBCDIC. */ 53 | if(ch >= 'A' && ch <= 'I') { 54 | return 1; 55 | } else if(ch >= 'J' && ch <= 'R') { 56 | return 1; 57 | } else if(ch >= 'S' && ch <= 'Z') { 58 | return 1; 59 | } else if(ch >= 'a' && ch <= 'i') { 60 | return 1; 61 | } else if(ch >= 'j' && ch <= 'r') { 62 | return 1; 63 | } else if(ch >= 's' && ch <= 'z') { 64 | return 1; 65 | } else if(ch >= '0' && ch <= '9') { 66 | return 1; 67 | } else if(ch == '_') { 68 | return 1; 69 | } else { 70 | return 0; 71 | } 72 | } 73 | 74 | /** Get the name of a shell variable (returns a copy). */ 75 | char *GetSymbolName(const char *str) 76 | { 77 | 78 | char *temp; 79 | 80 | if(*str == '$') { 81 | temp = Allocate(2); 82 | temp[0] = '$'; 83 | temp[1] = 0; 84 | } else { 85 | int stop; 86 | for(stop = 0; IsSymbolic(str[stop]); stop++); 87 | temp = Allocate(stop + 1); 88 | memcpy(temp, str, stop); 89 | temp[stop] = 0; 90 | } 91 | 92 | return temp; 93 | 94 | } 95 | 96 | /** Replace "name" with "value" at offset in str (reallocates if needed). */ 97 | void ReplaceSymbol(char **str, unsigned int offset, 98 | const char *name, const char *value) 99 | { 100 | 101 | char *temp; 102 | int strLength; 103 | int nameLength; 104 | int valueLength; 105 | 106 | Assert(str); 107 | Assert(name); 108 | 109 | /* Determine string lengths. */ 110 | strLength = strlen(*str); 111 | nameLength = strlen(name) + 1; /* Account for the '$'. */ 112 | if(value) { 113 | valueLength = strlen(value); 114 | } else { 115 | valueLength = 0; 116 | } 117 | 118 | /* Allocate extra space if necessary. */ 119 | if(valueLength > nameLength) { 120 | const size_t totalLen = strLength - nameLength + valueLength + 1; 121 | temp = Allocate(totalLen); 122 | memcpy(temp, *str, strLength + 1); 123 | Release(*str); 124 | *str = temp; 125 | } 126 | 127 | /* Offset to '$'. */ 128 | temp = *str + offset; 129 | 130 | if(nameLength > valueLength) { 131 | 132 | /* Move left */ 133 | memmove(temp, temp + nameLength - valueLength, 134 | strLength - offset - nameLength + valueLength + 1); 135 | 136 | } else if(nameLength < valueLength) { 137 | 138 | /* Move right */ 139 | memmove(temp + valueLength, temp + nameLength, 140 | strLength + - nameLength - offset + 1); 141 | 142 | } 143 | 144 | if(value) { 145 | memcpy(temp, value, valueLength); 146 | } 147 | 148 | } 149 | 150 | /** Perform shell-like macro path expansion. */ 151 | void ExpandPath(char **path) 152 | { 153 | 154 | char *name; 155 | char *value; 156 | unsigned int x; 157 | 158 | Assert(path); 159 | 160 | for(x = 0; (*path)[x]; x++) { 161 | 162 | if((*path)[x] == '$') { 163 | name = GetSymbolName(*path + x + 1); 164 | value = getenv(name); 165 | ReplaceSymbol(path, x, name, value); 166 | Release(name); 167 | if(value) { 168 | x += strlen(value) - 1; 169 | } 170 | } 171 | 172 | } 173 | 174 | } 175 | 176 | /** Trim leading and trailing whitespace from a string. */ 177 | void Trim(char *str) 178 | { 179 | 180 | unsigned int length; 181 | unsigned int start; 182 | unsigned int x; 183 | unsigned int line; 184 | 185 | Assert(str); 186 | 187 | length = strlen(str); 188 | 189 | /* Determine how much to cut off of the left. */ 190 | line = 0; 191 | for(start = 0; IsSpace(str[start], &line); start++); 192 | 193 | /* Trim the left. */ 194 | if(start > 0) { 195 | length -= start; 196 | for(x = 0; x < length + 1; x++) { 197 | str[x] = str[x + start]; 198 | } 199 | } 200 | 201 | /* Trim the right. */ 202 | while(length > 0 && IsSpace(str[length - 1], &line)) { 203 | length -= 1; 204 | str[length] = 0; 205 | } 206 | 207 | } 208 | 209 | /** Copy a string. */ 210 | char *CopyString(const char *str) 211 | { 212 | 213 | char *temp; 214 | unsigned int len; 215 | 216 | if(!str) { 217 | return NULL; 218 | } 219 | 220 | len = strlen(str) + 1; 221 | temp = Allocate(len); 222 | memcpy(temp, str, len); 223 | 224 | return temp; 225 | 226 | } 227 | 228 | /** Parse a float. */ 229 | float ParseFloat(const char *str) 230 | { 231 | float result; 232 | #if defined(HAVE_SETLOCALE) && (defined(ENABLE_NLS) || defined(ENABLE_ICONV)) 233 | setlocale(LC_ALL, "C"); 234 | #endif 235 | result = atof(str); 236 | #if defined(HAVE_SETLOCALE) && (defined(ENABLE_NLS) || defined(ENABLE_ICONV)) 237 | setlocale(LC_ALL, ""); 238 | #endif 239 | return result; 240 | } 241 | 242 | /** Find a value in a string mapping. */ 243 | int FindValue(const StringMappingType *mapping, int count, const char *key) 244 | { 245 | int left = 0; 246 | int right = count - 1; 247 | while(right >= left) { 248 | const int x = (left + right) / 2; 249 | Assert(x >= 0); 250 | Assert(x < count); 251 | const int rc = strcmp(key, mapping[x].key); 252 | if(rc < 0) { 253 | right = x - 1; 254 | } else if(rc > 0) { 255 | left = x + 1; 256 | } else { 257 | return mapping[x].value; 258 | } 259 | } 260 | return -1; 261 | } 262 | 263 | /** Find a key in a string mapping. */ 264 | const char *FindKey(const StringMappingType *mapping, int count, int value) 265 | { 266 | int x; 267 | for(x = 0; x < count; x++) { 268 | if(mapping[x].value == value) { 269 | return mapping[x].key; 270 | } 271 | } 272 | return NULL; 273 | } 274 | 275 | /** Case insensitive string compare. */ 276 | int StrCmpNoCase(const char *a, const char *b) 277 | { 278 | while(*a && *b && ToLower(*a) == ToLower(*b)) { 279 | a += 1; 280 | b += 1; 281 | } 282 | return *b - *a; 283 | } 284 | -------------------------------------------------------------------------------- /src/clientlist.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file clientlist.c 3 | * @author Joe Wingbermuehle 4 | * @date 2007 5 | * 6 | * @brief Functions to manage lists of clients. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "clientlist.h" 12 | #include "client.h" 13 | #include "binding.h" 14 | #include "event.h" 15 | #include "tray.h" 16 | #include "settings.h" 17 | 18 | ClientNode *nodes[LAYER_COUNT]; 19 | ClientNode *nodeTail[LAYER_COUNT]; 20 | 21 | static Window *windowStack = NULL; /**< Image of the window stack. */ 22 | static int windowStackSize = 0; /**< Size of the image. */ 23 | static int windowStackCurrent = 0; /**< Current location in the image. */ 24 | static char walkingWindows = 0; /**< Are we walking windows? */ 25 | static char wasMinimized = 0; /**< Was the current window minimized? */ 26 | 27 | /** Determine if a client is allowed focus. */ 28 | char ShouldFocus(const ClientNode *np, char current) 29 | { 30 | 31 | /* Only display clients on the current desktop or clients that are sticky. */ 32 | if(!settings.listAllTasks || current) { 33 | if(!IsClientOnCurrentDesktop(np)) { 34 | return 0; 35 | } 36 | } 37 | 38 | /* Don't display a client if it doesn't want to be displayed. */ 39 | if(np->state.status & STAT_NOLIST) { 40 | return 0; 41 | } 42 | 43 | /* Don't display a client on the tray if it has an owner. */ 44 | if(np->owner != None) { 45 | return 0; 46 | } 47 | 48 | if(!(np->state.status & (STAT_MAPPED | STAT_MINIMIZED | STAT_SHADED))) { 49 | return 0; 50 | } 51 | 52 | return 1; 53 | 54 | } 55 | 56 | /** Start walking windows in client list order. */ 57 | void StartWindowWalk(void) 58 | { 59 | JXGrabKeyboard(display, rootWindow, False, GrabModeAsync, 60 | GrabModeAsync, CurrentTime); 61 | RaiseTrays(); 62 | walkingWindows = 1; 63 | } 64 | 65 | /** Start walking the window stack. */ 66 | void StartWindowStackWalk(void) 67 | { 68 | 69 | /* Get an image of the window stack. 70 | * Here we get the Window IDs rather than client pointers so 71 | * clients can be added/removed without disrupting the stack walk. 72 | */ 73 | 74 | ClientNode *np; 75 | int layer; 76 | int count; 77 | 78 | /* If we are already walking the stack, just return. */ 79 | if(windowStack != NULL) { 80 | return; 81 | } 82 | 83 | /* First determine how much space to allocate for windows. */ 84 | count = 0; 85 | for(layer = LAST_LAYER; layer >= FIRST_LAYER; layer--) { 86 | for(np = nodes[layer]; np; np = np->next) { 87 | if(ShouldFocus(np, 1)) { 88 | ++count; 89 | } 90 | } 91 | } 92 | 93 | /* If there were no windows to walk, don't even start. */ 94 | if(count == 0) { 95 | return; 96 | } 97 | 98 | /* Allocate space for the windows. */ 99 | windowStack = Allocate(sizeof(Window) * count); 100 | 101 | /* Copy windows into the array. */ 102 | windowStackSize = 0; 103 | for(layer = LAST_LAYER; layer >= FIRST_LAYER; layer--) { 104 | for(np = nodes[layer]; np; np = np->next) { 105 | if(ShouldFocus(np, 1)) { 106 | windowStack[windowStackSize++] = np->window; 107 | } 108 | } 109 | } 110 | 111 | Assert(windowStackSize == count); 112 | 113 | windowStackCurrent = 0; 114 | 115 | JXGrabKeyboard(display, rootWindow, False, GrabModeAsync, 116 | GrabModeAsync, CurrentTime); 117 | 118 | RaiseTrays(); 119 | 120 | walkingWindows = 1; 121 | wasMinimized = 0; 122 | 123 | } 124 | 125 | /** Move to the next window in the window stack. */ 126 | void WalkWindowStack(char forward) 127 | { 128 | 129 | ClientNode *np; 130 | 131 | if(windowStack != NULL) { 132 | int x; 133 | 134 | if(wasMinimized) { 135 | np = FindClientByWindow(windowStack[windowStackCurrent]); 136 | if(np) { 137 | MinimizeClient(np, 1); 138 | } 139 | } 140 | 141 | /* Loop until we either raise a window or go through them all. */ 142 | for(x = 0; x < windowStackSize; x++) { 143 | 144 | /* Move to the next/previous window (wrap if needed). */ 145 | if(forward) { 146 | windowStackCurrent = (windowStackCurrent + 1) % windowStackSize; 147 | } else { 148 | if(windowStackCurrent == 0) { 149 | windowStackCurrent = windowStackSize; 150 | } 151 | windowStackCurrent -= 1; 152 | } 153 | 154 | /* Look up the window. */ 155 | np = FindClientByWindow(windowStack[windowStackCurrent]); 156 | 157 | /* Skip this window if it no longer exists or is currently in 158 | * a state that doesn't allow focus. 159 | */ 160 | if(np == NULL || !ShouldFocus(np, 1) 161 | || (np->state.status & STAT_ACTIVE)) { 162 | continue; 163 | } 164 | 165 | /* Show the window. 166 | * Only when the walk completes do we update the stacking order. */ 167 | RestackClients(); 168 | if(np->state.status & STAT_MINIMIZED) { 169 | RestoreClient(np, 1); 170 | wasMinimized = 1; 171 | } else { 172 | wasMinimized = 0; 173 | } 174 | JXRaiseWindow(display, np->parent ? np->parent : np->window); 175 | FocusClient(np); 176 | break; 177 | 178 | } 179 | 180 | } 181 | 182 | } 183 | 184 | /** Stop walking the window stack or client list. */ 185 | void StopWindowWalk(void) 186 | { 187 | 188 | ClientNode *np; 189 | 190 | /* Raise the selected window and free the window array. */ 191 | if(windowStack != NULL) { 192 | 193 | /* Look up the current window. */ 194 | np = FindClientByWindow(windowStack[windowStackCurrent]); 195 | if(np) { 196 | if(np->state.status & STAT_MINIMIZED) { 197 | RestoreClient(np, 1); 198 | } else { 199 | RaiseClient(np); 200 | } 201 | } 202 | 203 | Release(windowStack); 204 | windowStack = NULL; 205 | 206 | windowStackSize = 0; 207 | windowStackCurrent = 0; 208 | 209 | } 210 | 211 | if(walkingWindows) { 212 | JXUngrabKeyboard(display, CurrentTime); 213 | LowerTrays(); 214 | walkingWindows = 0; 215 | } 216 | 217 | } 218 | 219 | /** Focus the next client in the stacking order. */ 220 | void FocusNextStacked(ClientNode *np) 221 | { 222 | 223 | int x; 224 | ClientNode *tp; 225 | 226 | Assert(np); 227 | 228 | for(tp = np->next; tp; tp = tp->next) { 229 | if((tp->state.status & (STAT_MAPPED | STAT_SHADED)) 230 | && !(tp->state.status & STAT_HIDDEN)) { 231 | FocusClient(tp); 232 | return; 233 | } 234 | } 235 | for(x = np->state.layer - 1; x >= FIRST_LAYER; x--) { 236 | for(tp = nodes[x]; tp; tp = tp->next) { 237 | if((tp->state.status & (STAT_MAPPED | STAT_SHADED)) 238 | && !(tp->state.status & STAT_HIDDEN)) { 239 | FocusClient(tp); 240 | return; 241 | } 242 | } 243 | } 244 | 245 | /* No client to focus. */ 246 | JXSetInputFocus(display, rootWindow, RevertToParent, eventTime); 247 | 248 | } 249 | 250 | -------------------------------------------------------------------------------- /src/button.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file button.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for rendering buttons. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "button.h" 12 | #include "border.h" 13 | #include "main.h" 14 | #include "icon.h" 15 | #include "image.h" 16 | #include "misc.h" 17 | #include "settings.h" 18 | 19 | /** Draw a button. */ 20 | void DrawButton(ButtonNode *bp) 21 | { 22 | 23 | ColorType fg; 24 | long bg1, bg2; 25 | long up, down; 26 | DecorationsType decorations; 27 | 28 | Drawable drawable; 29 | GC gc; 30 | int x, y; 31 | int width, height; 32 | int xoffset, yoffset; 33 | 34 | int iconWidth, iconHeight; 35 | int textWidth, textHeight; 36 | 37 | Assert(bp); 38 | 39 | drawable = bp->drawable; 40 | x = bp->x; 41 | y = bp->y; 42 | width = bp->width; 43 | height = bp->height; 44 | gc = JXCreateGC(display, drawable, 0, NULL); 45 | 46 | /* Determine the colors to use. */ 47 | switch(bp->type) { 48 | case BUTTON_LABEL: 49 | fg = COLOR_MENU_FG; 50 | bg1 = colors[COLOR_MENU_BG]; 51 | bg2 = colors[COLOR_MENU_BG]; 52 | up = colors[COLOR_MENU_UP]; 53 | down = colors[COLOR_MENU_DOWN]; 54 | decorations = settings.menuDecorations; 55 | break; 56 | case BUTTON_MENU_ACTIVE: 57 | fg = COLOR_MENU_ACTIVE_FG; 58 | bg1 = colors[COLOR_MENU_ACTIVE_BG1]; 59 | bg2 = colors[COLOR_MENU_ACTIVE_BG2]; 60 | down = colors[COLOR_MENU_ACTIVE_UP]; 61 | up = colors[COLOR_MENU_ACTIVE_DOWN]; 62 | decorations = settings.menuDecorations; 63 | break; 64 | case BUTTON_TRAY: 65 | fg = COLOR_TRAYBUTTON_FG; 66 | bg1 = colors[COLOR_TRAYBUTTON_BG1]; 67 | bg2 = colors[COLOR_TRAYBUTTON_BG2]; 68 | up = colors[COLOR_TRAYBUTTON_UP]; 69 | down = colors[COLOR_TRAYBUTTON_DOWN]; 70 | decorations = settings.trayDecorations; 71 | break; 72 | case BUTTON_TRAY_ACTIVE: 73 | fg = COLOR_TRAYBUTTON_ACTIVE_FG; 74 | bg1 = colors[COLOR_TRAYBUTTON_ACTIVE_BG1]; 75 | bg2 = colors[COLOR_TRAYBUTTON_ACTIVE_BG2]; 76 | down = colors[COLOR_TRAYBUTTON_ACTIVE_UP]; 77 | up = colors[COLOR_TRAYBUTTON_ACTIVE_DOWN]; 78 | decorations = settings.trayDecorations; 79 | break; 80 | case BUTTON_TASK: 81 | fg = COLOR_TASKLIST_FG; 82 | bg1 = colors[COLOR_TASKLIST_BG1]; 83 | bg2 = colors[COLOR_TASKLIST_BG2]; 84 | up = colors[COLOR_TASKLIST_UP]; 85 | down = colors[COLOR_TASKLIST_DOWN]; 86 | decorations = settings.taskListDecorations; 87 | break; 88 | case BUTTON_TASK_ACTIVE: 89 | fg = COLOR_TASKLIST_ACTIVE_FG; 90 | bg1 = colors[COLOR_TASKLIST_ACTIVE_BG1]; 91 | bg2 = colors[COLOR_TASKLIST_ACTIVE_BG2]; 92 | down = colors[COLOR_TASKLIST_ACTIVE_UP]; 93 | up = colors[COLOR_TASKLIST_ACTIVE_DOWN]; 94 | decorations = settings.taskListDecorations; 95 | break; 96 | case BUTTON_MENU: 97 | default: 98 | fg = COLOR_MENU_FG; 99 | bg1 = colors[COLOR_MENU_BG]; 100 | bg2 = colors[COLOR_MENU_BG]; 101 | up = colors[COLOR_MENU_UP]; 102 | down = colors[COLOR_MENU_DOWN]; 103 | decorations = settings.menuDecorations; 104 | break; 105 | } 106 | 107 | /* Draw the background. */ 108 | if(bp->fill) { 109 | 110 | /* Draw the button background. */ 111 | JXSetForeground(display, gc, bg1); 112 | if(bg1 == bg2) { 113 | /* single color */ 114 | JXFillRectangle(display, drawable, gc, x, y, width, height); 115 | } else { 116 | /* gradient */ 117 | DrawHorizontalGradient(drawable, gc, bg1, bg2, 118 | x, y, width, height); 119 | } 120 | 121 | } 122 | 123 | /* Draw the border. */ 124 | if(bp->border) { 125 | if(decorations == DECO_MOTIF) { 126 | JXSetForeground(display, gc, up); 127 | JXDrawLine(display, drawable, gc, x, y, x + width - 1, y); 128 | JXDrawLine(display, drawable, gc, x, y, x, y + height - 1); 129 | JXSetForeground(display, gc, down); 130 | JXDrawLine(display, drawable, gc, x, y + height - 1, 131 | x + width - 1, y + height - 1); 132 | JXDrawLine(display, drawable, gc, x + width - 1, y, 133 | x + width - 1, y + height - 1); 134 | } else { 135 | JXSetForeground(display, gc, down); 136 | JXDrawRectangle(display, drawable, gc, x, y, width - 1, height - 1); 137 | } 138 | } 139 | 140 | /* Determine the size of the icon (if any) to display. */ 141 | iconWidth = 0; 142 | iconHeight = 0; 143 | if(bp->icon) { 144 | if(bp->icon == &emptyIcon) { 145 | iconWidth = Min(width - 4, height - 4); 146 | iconHeight = iconWidth; 147 | } else { 148 | const int ratio = (bp->icon->width << 16) / bp->icon->height; 149 | int maxIconWidth = width - 4; 150 | if(bp->text) { 151 | /* Showing text, keep the icon square. */ 152 | maxIconWidth = Min(width, height) - 4; 153 | } 154 | iconHeight = height - 4; 155 | iconWidth = (iconHeight * ratio) >> 16; 156 | if(iconWidth > maxIconWidth) { 157 | iconWidth = maxIconWidth; 158 | iconHeight = (iconWidth << 16) / ratio; 159 | } 160 | } 161 | } 162 | 163 | /* Determine how much room is left for text. */ 164 | textWidth = 0; 165 | textHeight = 0; 166 | if(bp->text && (width > height || !bp->icon)) { 167 | textWidth = GetStringWidth(bp->font, bp->text); 168 | textHeight = GetStringHeight(bp->font); 169 | if(iconWidth > 0 && textWidth + iconWidth + 7 > width) { 170 | textWidth = width - iconWidth - 7; 171 | } else if(iconWidth == 0 && textWidth + 5 > width) { 172 | textWidth = width - 5; 173 | } 174 | textWidth = textWidth < 0 ? 0 : textWidth; 175 | } 176 | 177 | /* Determine the offset of the text in the button. */ 178 | if(bp->alignment == ALIGN_CENTER || width <= height) { 179 | xoffset = (width - iconWidth - textWidth + 1) / 2; 180 | if(xoffset < 0) { 181 | xoffset = 0; 182 | } 183 | } else { 184 | xoffset = 2; 185 | } 186 | 187 | /* Display the icon. */ 188 | if(bp->icon) { 189 | yoffset = (height - iconHeight + 1) / 2; 190 | PutIcon(bp->icon, drawable, colors[fg], 191 | x + xoffset, y + yoffset, 192 | iconWidth, iconHeight); 193 | xoffset += iconWidth + 2; 194 | } 195 | 196 | /* Display the label. */ 197 | if(textWidth > 0) { 198 | yoffset = (height - textHeight + 1) / 2; 199 | RenderString(drawable, bp->font, fg, 200 | x + xoffset, y + yoffset, 201 | textWidth, bp->text); 202 | } 203 | 204 | JXFreeGC(display, gc); 205 | 206 | } 207 | 208 | /** Reset a button node with default values. */ 209 | void ResetButton(ButtonNode *bp, Drawable d) 210 | { 211 | 212 | Assert(bp); 213 | 214 | bp->type = BUTTON_MENU; 215 | bp->drawable = d; 216 | bp->font = FONT_TRAY; 217 | bp->alignment = ALIGN_LEFT; 218 | bp->x = 0; 219 | bp->y = 0; 220 | bp->width = 1; 221 | bp->height = 1; 222 | bp->icon = NULL; 223 | bp->text = NULL; 224 | bp->fill = 1; 225 | bp->border = 0; 226 | 227 | } 228 | -------------------------------------------------------------------------------- /src/popup.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file popup.c 3 | * @author Joe Wingbermuehle 4 | * @date 2004-2006 5 | * 6 | * @brief Functions for displaying popup windows. 7 | * 8 | */ 9 | 10 | #include "jwm.h" 11 | #include "popup.h" 12 | #include "main.h" 13 | #include "color.h" 14 | #include "font.h" 15 | #include "screen.h" 16 | #include "cursor.h" 17 | #include "timing.h" 18 | #include "misc.h" 19 | #include "settings.h" 20 | #include "event.h" 21 | #include "hint.h" 22 | 23 | typedef struct PopupType { 24 | int x, y; /* The coordinates of the upper-left corner of the popup. */ 25 | int mx, my; /* The mouse position when the popup was created. */ 26 | Window mw; 27 | int width, height; 28 | char *text; /* The raw popup text. */ 29 | char *lines; /* Popup text split into NUL-separated lines. */ 30 | int lineCount; /* The number of lines. */ 31 | Window window; 32 | Pixmap pmap; 33 | } PopupType; 34 | 35 | static PopupType popup; 36 | 37 | static void MeasurePopupText(); 38 | static void SignalPopup(const TimeType *now, int x, int y, Window w, 39 | void *data); 40 | 41 | /** Startup popups. */ 42 | void StartupPopup(void) 43 | { 44 | popup.text = NULL; 45 | popup.window = None; 46 | RegisterCallback(100, SignalPopup, NULL); 47 | } 48 | 49 | /** Shutdown popups. */ 50 | void ShutdownPopup(void) 51 | { 52 | UnregisterCallback(SignalPopup, NULL); 53 | if(popup.text) { 54 | Release(popup.text); 55 | Release(popup.lines); 56 | popup.text = NULL; 57 | } 58 | if(popup.window != None) { 59 | JXDestroyWindow(display, popup.window); 60 | JXFreePixmap(display, popup.pmap); 61 | popup.window = None; 62 | } 63 | } 64 | 65 | /** Calculate dimensions of a popup window given the popup text. */ 66 | void MeasurePopupText() 67 | { 68 | const int textHeight = GetStringHeight(FONT_POPUP) + 1; 69 | char *ptr; 70 | 71 | popup.lines = CopyString(popup.text); 72 | ptr = popup.lines; 73 | 74 | popup.width = 0; 75 | popup.height = 1; 76 | popup.lineCount = 0; 77 | for(;;) { 78 | char *end = strchr(ptr, '\n'); 79 | int currentWidth; 80 | if(end) { 81 | *end = 0; 82 | } 83 | currentWidth = GetStringWidth(FONT_POPUP, ptr) + 9; 84 | popup.width = Max(popup.width, currentWidth); 85 | popup.height += textHeight; 86 | popup.lineCount += 1; 87 | if(end) { 88 | ptr = end + 1; 89 | } else { 90 | break; 91 | } 92 | } 93 | } 94 | 95 | /** Show a popup window. */ 96 | void ShowPopup(int x, int y, const char *text, 97 | const PopupMaskType context) 98 | { 99 | const ScreenType *sp; 100 | char *ptr; 101 | int textHeight; 102 | int i; 103 | 104 | if(!(settings.popupMask & context)) { 105 | return; 106 | } 107 | 108 | if(popup.text) { 109 | if(x == popup.x && y == popup.y && !strcmp(popup.text, text)) { 110 | /* This popup is already shown. */ 111 | return; 112 | } 113 | Release(popup.text); 114 | Release(popup.lines); 115 | popup.text = NULL; 116 | } 117 | 118 | if(text[0] == 0) { 119 | return; 120 | } 121 | 122 | GetMousePosition(&popup.mx, &popup.my, &popup.mw); 123 | popup.text = CopyString(text); 124 | 125 | MeasurePopupText(); 126 | sp = GetCurrentScreen(x, y); 127 | if(popup.width > sp->width) { 128 | popup.width = sp->width; 129 | } 130 | 131 | popup.x = x; 132 | if(y + 2 * popup.height + 2 >= sp->height) { 133 | popup.y = y - popup.height - 2; 134 | } else { 135 | popup.y = y + GetStringHeight(FONT_POPUP) + 2; 136 | } 137 | 138 | if(popup.width + popup.x > sp->x + sp->width) { 139 | popup.x = sp->x + sp->width - popup.width - 2; 140 | } 141 | if(popup.height + popup.y > sp->y + sp->height) { 142 | popup.y = sp->y + sp->height - popup.height - 2; 143 | } 144 | if(popup.x < 2) { 145 | popup.x = 2; 146 | } 147 | if(popup.y < 2) { 148 | popup.y = 2; 149 | } 150 | 151 | if(popup.window == None) { 152 | 153 | XSetWindowAttributes attr; 154 | unsigned long attrMask = 0; 155 | 156 | attrMask |= CWEventMask; 157 | attr.event_mask = ExposureMask 158 | | PointerMotionMask | PointerMotionHintMask; 159 | 160 | attrMask |= CWSaveUnder; 161 | attr.save_under = True; 162 | 163 | attrMask |= CWDontPropagate; 164 | attr.do_not_propagate_mask = PointerMotionMask 165 | | ButtonPressMask 166 | | ButtonReleaseMask; 167 | 168 | popup.window = JXCreateWindow(display, rootWindow, popup.x, popup.y, 169 | popup.width, popup.height, 0, 170 | CopyFromParent, InputOutput, 171 | CopyFromParent, attrMask, &attr); 172 | SetAtomAtom(popup.window, ATOM_NET_WM_WINDOW_TYPE, 173 | ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION); 174 | JXMapRaised(display, popup.window); 175 | 176 | } else { 177 | 178 | JXMoveResizeWindow(display, popup.window, popup.x, popup.y, 179 | popup.width, popup.height); 180 | JXFreePixmap(display, popup.pmap); 181 | 182 | } 183 | 184 | popup.pmap = JXCreatePixmap(display, popup.window, 185 | popup.width, popup.height, 186 | rootDepth); 187 | 188 | JXSetForeground(display, rootGC, colors[COLOR_POPUP_BG]); 189 | JXFillRectangle(display, popup.pmap, rootGC, 0, 0, 190 | popup.width - 1, popup.height - 1); 191 | JXSetForeground(display, rootGC, colors[COLOR_POPUP_OUTLINE]); 192 | JXDrawRectangle(display, popup.pmap, rootGC, 0, 0, 193 | popup.width - 1, popup.height - 1); 194 | ptr = popup.lines; 195 | textHeight = GetStringHeight(FONT_POPUP) + 1; 196 | for(i = 0; i < popup.lineCount; i++) { 197 | RenderString(popup.pmap, FONT_POPUP, COLOR_POPUP_FG, 4, 198 | textHeight * i + 1, popup.width, ptr); 199 | ptr += strlen(ptr) + 1; 200 | } 201 | JXCopyArea(display, popup.pmap, popup.window, rootGC, 202 | 0, 0, popup.width, popup.height, 0, 0); 203 | 204 | } 205 | 206 | /** Signal popup (this is used to hide popups after awhile). */ 207 | void SignalPopup(const TimeType *now, int x, int y, Window w, void *data) 208 | { 209 | if(popup.window != None) { 210 | if(popup.mw != w || 211 | abs(popup.mx - x) > 0 || abs(popup.my - y) > 0) { 212 | JXDestroyWindow(display, popup.window); 213 | JXFreePixmap(display, popup.pmap); 214 | popup.window = None; 215 | } 216 | } 217 | } 218 | 219 | /** Process an event on a popup window. */ 220 | char ProcessPopupEvent(const XEvent *event) 221 | { 222 | if(popup.window != None && event->xany.window == popup.window) { 223 | if(event->type == Expose && event->xexpose.count == 0) { 224 | JXCopyArea(display, popup.pmap, popup.window, rootGC, 225 | 0, 0, popup.width, popup.height, 0, 0); 226 | } else if(event->type == MotionNotify) { 227 | JXDestroyWindow(display, popup.window); 228 | JXFreePixmap(display, popup.pmap); 229 | popup.window = None; 230 | } 231 | return 1; 232 | } 233 | return 0; 234 | } 235 | --------------------------------------------------------------------------------