diff --git a/ChangeLog b/ChangeLog index 8ed04745..a8c8ade7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -110,7 +110,6 @@ Changes since version 0.80.2: (Marcelo E. Magallon ) - Do not use the disabled clip color for the clip's workspace navigation arrows when the clip is collapsed (it made them look like disabled) -- Fixed the 'focus flicker' problem, seen with GTK2 applications. - Fixed bug with incorrect un-escaping if there is a dot in wm_class. - Updated Catalan translations (Ernest Adrogue ) - Updated Spanish translation of WPrefs (Alberto Gimenez ) @@ -123,12 +122,42 @@ Changes since version 0.80.2: appicon when a KDE3 application opens a config panel. - Updated slovak translation (Jan Tomka ) - Added xdnd v3 support in WINGs (Sylvain Reynal ) +- Check whether libXft is at least version 2.1.2 else refuse to compile. +- Fixed bug in icon chooser dialog that could cause a segmentation fault + in some cases (Pascal Hofstee ) +- Fixed crash in asm code in wrlib, with new versions of gcc. +- Fixed bug in the x86_PseudoColor_32_to_8() function which incorrectly + used the r, g, b fields in the conversion. +- Fixed x86 ASM code in wrlib to work on 64 bit architectures. +- Fixed the focus flicker seen with some apps (notably gtk2) + (Alexey Spiridonov ) +- Fixed all crashing bugs that were generated by wmaker starting with the + WMState file missing. +- Added NetWM support (a modified version of the patch originaly written + by Peter Zijlstra ) +- Applied patch to enhance the Virtual Desktop behaviour, and to integrate + it with the NetWM code (Peter Zijlstra ) +- Applied a few xinerama and placement fixes (Peter Zijlstra + ) +- Fixed memory leak in dock code. +- Fixed and enhanced the text wrapping in WINGs. +- Fixed the layout of some elements in WPrefs.app +- Added workaround for aplications that don't set the required hints on the + client leader window, but they set them on normal windows (observer with + KDE 3.3.0 mainly). This will allow these apps to get an appicon again. + (they should be fixed still) +- Added workaround for applications that do not set a command with + XSetCommand(), but instead they set the _NET_WM_PID property. This works + with operating systems that offer a /proc interface similar to what linux + has. (This also is to fix problems with KDE 3.3.0 apps, but not only them). +- Fixed bug with autostart and exit scripts not being executed if user + GNUstep path was different from ~/GNUstep (when setting GNUSTEP_USER_ROOT) Changes since version 0.80.1: ............................. -- Fixed a buffer overflow when allocating an RImage struct. +- Fixed a buffer overflow when allocating a RImage struct. Changes since version 0.80.0: diff --git a/TODO b/TODO index b5663c13..31abecb6 100644 --- a/TODO +++ b/TODO @@ -61,4 +61,3 @@ sample implementation (twm?) it might be supported. Maybe dtwm supports it? I dont know... - diff --git a/WINGs/ChangeLog b/WINGs/ChangeLog index 6dcd582c..51b93469 100644 --- a/WINGs/ChangeLog +++ b/WINGs/ChangeLog @@ -1,8 +1,8 @@ Changes since wmaker 0.80.1: ............................ -- added WMSetConnectionShutdownOnClose() -- added an extra member to the ConnectionDelegate: canResumeSending +- Added WMSetConnectionShutdownOnClose() +- Added an extra member to the ConnectionDelegate: canResumeSending see NEWS for details. - WMDrawString() and WMDrawImageString() now take WMColor instead of GC as arguments. WMDrawImageString() receives 2 colors (text & background). @@ -49,12 +49,13 @@ Changes since wmaker 0.80.1: - Fixed a memleak in the file panel. - Double/triple-click selection in text widgets (Vitaly Ovtchinnikov ) -- fixed bug in tableview (clicked row callback got incorrect row) +- Fixed bug in tableview (clicked row callback got incorrect row) (Carlos Torres ) - Fixed bug in resizing a scrollview - Fixed bug with wrong text wrapping (Alexey Voinov ) - Added wmkrect() - Added xdnd v3 support (Sylvain Reynal ) +- Fixed and enhanced text wrapping. Changes since wmaker 0.80.0: diff --git a/WINGs/Examples/puzzle.c b/WINGs/Examples/puzzle.c index b99da4e0..22f2249c 100644 --- a/WINGs/Examples/puzzle.c +++ b/WINGs/Examples/puzzle.c @@ -21,7 +21,8 @@ int MoveCount; int WinSize = 120; -Bool CheckWin(void) +Bool +CheckWin(void) { int i; @@ -34,15 +35,17 @@ Bool CheckWin(void) } -void MoveButton(int button, int x, int y) +void +MoveButton(int button, int x, int y) { WMMoveWidget(Button[button], x*(WinSize/Size), y*(WinSize/Size)); } -Bool SlideButton(int button) +Bool +SlideButton(int button) { - int x, y, done = 0; + int x=0, y=0, done = 0; /* locate the button */ for (y = 0; y < Size; y++) { diff --git a/WINGs/Extras/Makefile.am b/WINGs/Extras/Makefile.am index c3a693f8..63119aec 100644 --- a/WINGs/Extras/Makefile.am +++ b/WINGs/Extras/Makefile.am @@ -22,6 +22,7 @@ libExtraWINGs_a_SOURCES = \ wtableview.h \ wtabledelegates.h +AM_CFLAGS = -fno-strict-aliasing INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/WINGs \ -DRESOURCE_PATH=\"$(datadir)/WINGs\" @HEADER_SEARCH_PATH@ -DDEBUG diff --git a/WINGs/Makefile.am b/WINGs/Makefile.am index 9df6a54d..3ff80d6e 100644 --- a/WINGs/Makefile.am +++ b/WINGs/Makefile.am @@ -108,7 +108,9 @@ libWUtil_a_SOURCES = \ wutil.c -AM_CPPFLAGS = @CPPFLAGS@ -DLOCALEDIR=\"$(NLSDIR)\" +AM_CPPFLAGS = -DLOCALEDIR=\"$(NLSDIR)\" + +AM_CFLAGS = -fno-strict-aliasing INCLUDES = -I$(top_srcdir)/WINGs/WINGs -I$(top_srcdir)/wrlib -I$(top_srcdir)/src \ -DRESOURCE_PATH=\"$(datadir)/WINGs\" @XFTFLAGS@ @HEADER_SEARCH_PATH@ -DDEBUG diff --git a/WINGs/Tests/wtest.c b/WINGs/Tests/wtest.c index d180a6a9..7339061e 100644 --- a/WINGs/Tests/wtest.c +++ b/WINGs/Tests/wtest.c @@ -116,14 +116,14 @@ testFrame(WMScreen *scr) } -static void +/*static void resizedWindow(void *self, WMNotification *notif) { WMView *view = (WMView*)WMGetNotificationObject(notif); WMSize size = WMGetViewSize(view); WMResizeWidget((WMWidget*)self, size.width, size.height); -} +}*/ void testBox(WMScreen *scr) @@ -609,7 +609,8 @@ testText(WMScreen *scr) WMFont *font, *ifont; font = WMDefaultSystemFont(scr); - ifont = WMCopyFontWithStyle(scr, font, WFSEmphasized); + //ifont = WMCopyFontWithStyle(scr, font, WFSEmphasized); + ifont = WMCreateFont(scr, "verdana,sans:pixelsize=12:italic"); if (ifont) { WMSetTextDefaultFont(text, ifont); WMReleaseFont(ifont); @@ -619,7 +620,7 @@ testText(WMScreen *scr) WMReleaseFont(font); } - if(file) { + if (file) { char buf[1024]; WMFreezeText(text); @@ -1042,6 +1043,7 @@ main(int argc, char **argv) testColorPanel(scr); + testFrame(scr); #if 0 testBox(scr); diff --git a/WINGs/WINGs/WINGs.h b/WINGs/WINGs/WINGs.h index f3805b04..d08936b9 100644 --- a/WINGs/WINGs/WINGs.h +++ b/WINGs/WINGs/WINGs.h @@ -1834,12 +1834,11 @@ void WMShowFontPanel(WMFontPanel *panel); void WMHideFontPanel(WMFontPanel *panel); +void WMFreeFontPanel(WMFontPanel *panel); + void WMSetFontPanelAction(WMFontPanel *panel, WMAction2 *action, void *data); -void WMSetFontPanelFont(WMFontPanel *panel, WMFont *font); - -/* you can free the returned string */ -char* WMGetFontPanelFontName(WMFontPanel *panel); +void WMSetFontPanelFont(WMFontPanel *panel, char *fontName); WMFont* WMGetFontPanelFont(WMFontPanel *panel); diff --git a/WINGs/WINGs/WINGsP.h b/WINGs/WINGs/WINGsP.h index 7f42ed60..673e9c54 100644 --- a/WINGs/WINGs/WINGsP.h +++ b/WINGs/WINGs/WINGsP.h @@ -22,19 +22,14 @@ extern "C" { #endif /* __cplusplus */ -#define DOUBLE_BUFFER - +#define DOUBLE_BUFFER 1 #define WC_UserWidget 128 +#define SCROLLER_WIDTH 20 - -#define SCROLLER_WIDTH 20 - - - -#define XDND_VERSION 4 +#define XDND_VERSION 4 typedef struct W_Application { diff --git a/WINGs/configuration.c b/WINGs/configuration.c index 0baf60bf..7d8d0c15 100644 --- a/WINGs/configuration.c +++ b/WINGs/configuration.c @@ -14,10 +14,6 @@ _WINGsConfiguration WINGsConfiguration; #define BOLD_SYSTEM_FONT "-*-helvetica-bold-r-normal-*-%d-*-*-*-*-*-*-*,-*-*-bold-r-*-*-%d-*-*-*-*-*-*-*" -#define XFTSYSTEM_FONT "-*-arial-medium-r-normal-*-%d-*-*-*-*-*-*-*" - -#define XFTBOLD_SYSTEM_FONT "-*-arial-bold-r-normal-*-%d-*-*-*-*-*-*-*" - #define FLOPPY_PATH "/floppy" @@ -45,6 +41,7 @@ getButtonWithName(const char *name, unsigned defaultButton) } +// fix this static Bool missingOrInvalidXLFD(char *xlfd) { diff --git a/WINGs/dragcommon.c b/WINGs/dragcommon.c index 77053783..c877d2a4 100644 --- a/WINGs/dragcommon.c +++ b/WINGs/dragcommon.c @@ -193,14 +193,15 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event) WMDraggingInfo *info = &scr->dragInfo; Atom messageType = event->message_type; - char* msgTypeName = XGetAtomName(scr->display, messageType); - #ifdef XDND_DEBUG + { + char* msgTypeName = XGetAtomName(scr->display, messageType); - if (msgTypeName != NULL) - printf("event type = %s\n", msgTypeName); - else - printf("pb with event type !\n"); + if (msgTypeName != NULL) + printf("event type = %s\n", msgTypeName); + else + printf("pb with event type !\n"); + } #endif diff --git a/WINGs/dragdestination.c b/WINGs/dragdestination.c index e982dacf..03dcd9bd 100644 --- a/WINGs/dragdestination.c +++ b/WINGs/dragdestination.c @@ -79,7 +79,7 @@ createDropDataArray(WMArray *requiredTypes) static WMArray* getTypesFromTypeList(WMScreen *scr, Window sourceWin) { - WMDraggingInfo *info = &scr->dragInfo; + /* // WMDraggingInfo *info = &scr->dragInfo;*/ Atom dataType; Atom* typeAtomList; WMArray* typeList; @@ -365,7 +365,6 @@ W_DragDestinationStoreEnterMsgInfo(WMDraggingInfo *info, WMView *toplevel, XClientMessageEvent *event) { WMScreen *scr = W_VIEW_SCREEN(toplevel); - int i,j, typesCount; if (XDND_DEST_INFO(info) == NULL) initDestinationDragInfo(info); @@ -609,7 +608,7 @@ static void sendAllowedAction(WMView *destView, Atom action) { WMScreen *scr = W_VIEW_SCREEN(destView); - WMPoint destPos = WMGetViewScreenPosition(destView); + /* // WMPoint destPos = WMGetViewScreenPosition(destView); */ WMSize destSize = WMGetViewSize(destView); int destX, destY; Window foo; diff --git a/WINGs/dragsource.c b/WINGs/dragsource.c index b08ee783..3b26499c 100644 --- a/WINGs/dragsource.c +++ b/WINGs/dragsource.c @@ -425,6 +425,8 @@ sendEnterMessage(WMDraggingInfo *info) } +// this functon doesn't return something in all cases. +// control reaches end of non-void function. fix this -Dan static Bool sendPositionMessage(WMDraggingInfo *info, WMPoint *mousePos) { @@ -740,7 +742,6 @@ isXdndAware(WMScreen *scr, Window win) int format; unsigned long count, remain; unsigned char *winXdndVersion; - unsigned char *proxy; if (win == None) return False; @@ -876,7 +877,7 @@ initMotionProcess(WMView *view, WMDraggingInfo *info, static void processMotion(WMDraggingInfo *info, Window windowUnderDrag, WMPoint *mousePos) { - WMScreen *scr = sourceScreen(info); + /* // WMScreen *scr = sourceScreen(info); */ Window newDestination = findDestination(info, mousePos); W_DragSourceStopTimer(); @@ -1058,6 +1059,7 @@ traceStatusMsg(Display *dpy, XClientMessageEvent *statusEvent) #endif +static void storeDropAction(WMDraggingInfo *info, Atom destAction) { WMView* sourceView = XDND_SOURCE_VIEW(info); diff --git a/WINGs/python/WINGs.py b/WINGs/python/WINGs.py index 3d008316..dbdccde2 100644 --- a/WINGs/python/WINGs.py +++ b/WINGs/python/WINGs.py @@ -26,10 +26,11 @@ class WMTimer: self._o = wings.pyWMAddPersistentTimerHandler(milliseconds, (callback, cdata)) else: self._o = wings.pyWMAddTimerHandler(milliseconds, (callback, cdata)) + self.__WMDeleteTimerHandler = wings.pyWMDeleteTimerHandler def __del__(self): - wings.pyWMDeleteTimerHandler(self._o) - #delete = __del__ + self.__WMDeleteTimerHandler(self._o) + class WMPersistentTimer(WMTimer): def __init__(self, milliseconds, callback, cdata=None): @@ -87,14 +88,15 @@ class WMView: class WMWidget(WMView): def __init__(self): - self._o = None if self.__class__ == WMWidget: raise Error, "a WMWidget can't be instantiated directly" + self._o = None + self.__WMDestroyWidget = wings.WMDestroyWidget def __del__(self): - if (self._o != None): - wings.WMDestroyWidget(self._o) - + if self._o is not None: + self.__WMDestroyWidget(self._o) + def resize(self, width, height): wings.WMResizeWidget(self._o, width, height) diff --git a/WINGs/userdefaults.c b/WINGs/userdefaults.c index b6744070..566f8e0e 100644 --- a/WINGs/userdefaults.c +++ b/WINGs/userdefaults.c @@ -272,7 +272,7 @@ WMGetStandardUserDefaults(void) defaults = wmalloc(sizeof(WMUserDefaults)); memset(defaults, 0, sizeof(WMUserDefaults)); - defaults->defaults = WMCreatePLDictionary(NULL, NULL, NULL); + defaults->defaults = WMCreatePLDictionary(NULL, NULL); defaults->searchList = wmalloc(sizeof(WMPropList*)*3); @@ -293,7 +293,7 @@ WMGetStandardUserDefaults(void) domain = WMReadPropListFromFile(path); if (!domain) - domain = WMCreatePLDictionary(NULL, NULL, NULL); + domain = WMCreatePLDictionary(NULL, NULL); if (path) wfree(path); @@ -314,7 +314,7 @@ WMGetStandardUserDefaults(void) wfree(path); if (!domain) - domain = WMCreatePLDictionary(NULL, NULL, NULL); + domain = WMCreatePLDictionary(NULL, NULL); if (domain) WMPutInPLDictionary(defaults->defaults, key, domain); @@ -367,7 +367,7 @@ WMGetDefaultsFromPath(char *path) defaults = wmalloc(sizeof(WMUserDefaults)); memset(defaults, 0, sizeof(WMUserDefaults)); - defaults->defaults = WMCreatePLDictionary(NULL, NULL, NULL); + defaults->defaults = WMCreatePLDictionary(NULL, NULL); defaults->searchList = wmalloc(sizeof(WMPropList*)*2); @@ -387,7 +387,7 @@ WMGetDefaultsFromPath(char *path) domain = WMReadPropListFromFile(path); if (!domain) - domain = WMCreatePLDictionary(NULL, NULL, NULL); + domain = WMCreatePLDictionary(NULL, NULL); defaults->path = wstrdup(path); diff --git a/WINGs/wevent.c b/WINGs/wevent.c index 28cd4e0e..f1a62a38 100644 --- a/WINGs/wevent.c +++ b/WINGs/wevent.c @@ -66,8 +66,8 @@ static WMEventHook *extraEventHandler=NULL; * */ void - WMCreateEventHandler(WMView *view, unsigned long mask, WMEventProc *eventProc, - void *clientData) +WMCreateEventHandler(WMView *view, unsigned long mask, WMEventProc *eventProc, + void *clientData) { W_EventHandler *hPtr; WMArrayIterator iter; diff --git a/WINGs/wfont.c b/WINGs/wfont.c index 6acc278d..89742f8d 100644 --- a/WINGs/wfont.c +++ b/WINGs/wfont.c @@ -2,12 +2,11 @@ #include "wconfig.h" #ifdef XFT -# include -# ifdef HAVE_WCHAR_H -# include -# endif -# include -#endif + +#include +#include + +#include #include "WINGsP.h" @@ -16,141 +15,52 @@ #include -#ifdef XFT +#define DEFAULT_SIZE WINGsConfiguration.defaultFontSize -#if defined(HAVE_MBSNRTOWCS) - -static size_t -wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) +static char* +fixXLFD(char *xlfd, int size) { - mbstate_t ps; - size_t n; + char *fname, *ptr; - memset(&ps, 0, sizeof(mbstate_t)); - n = mbsnrtowcs(dest, src, nbytes, len, &ps); - if (n!=(size_t)-1 && *src) { - *src -= ps.__count; + fname = wmalloc(strlen(xlfd) + 20); + if (strstr(xlfd, "%d")!=NULL) + sprintf(fname, xlfd, size ? size : DEFAULT_SIZE); + else + strcpy(fname, xlfd); + + if ((ptr = strchr(fname, ','))) { + *ptr = 0; } - return n; + return fname; } -#elif defined(HAVE_MBRTOWC) - -// This is 8 times slower than the version above. -static size_t -wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) -{ - mbstate_t ps; - const char *ptr; - size_t n; - int nb; - - if (nbytes==0) - return 0; - - memset(&ps, 0, sizeof(mbstate_t)); - - if (dest == NULL) { - for (ptr=*src, n=0; nbytes>0; n++) { - nb = mbrtowc(NULL, ptr, nbytes, &ps); - if (nb == -1) { - return ((size_t)-1); - } else if (nb==0 || nb==-2) { - return n; - } - ptr += nb; - nbytes -= nb; - } - } - - for (ptr=*src, n=0; n0; n++, dest++) { - nb = mbrtowc(dest, ptr, nbytes, &ps); - if (nb == -2) { - *src = ptr; - return n; - } else if (nb == -1) { - *src = ptr; - return ((size_t)-1); - } else if (nb == 0) { - *src = NULL; - return n; - } - ptr += nb; - nbytes -= nb; - } - - *src = ptr; - return n; -} - -#else - -// Not only 8 times slower than the version based on mbsnrtowcs -// but also this version is not thread safe nor reentrant - -static size_t -wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) -{ - const char *ptr; - size_t n; - int nb; - - if (nbytes==0) - return 0; - - mbtowc(NULL, NULL, 0); /* reset shift state */ - - if (dest == NULL) { - for (ptr=*src, n=0; nbytes>0; n++) { - nb = mbtowc(NULL, ptr, nbytes); - if (nb == -1) { - mbtowc(NULL, NULL, 0); - nb = mbtowc(NULL, ptr, strlen(ptr)); - return (nb == -1 ? (size_t)-1 : n); - } else if (nb==0) { - return n; - } - ptr += nb; - nbytes -= nb; - } - } - - for (ptr=*src, n=0; n0; n++, dest++) { - nb = mbtowc(dest, ptr, nbytes); - if (nb == -1) { - mbtowc(NULL, NULL, 0); - nb = mbtowc(NULL, ptr, strlen(ptr)); - *src = ptr; - return (nb == -1 ? (size_t)-1 : n); - } else if (nb == 0) { - *src = NULL; - return n; - } - ptr += nb; - nbytes -= nb; - } - - *src = ptr; - return n; -} - -#endif - static Bool -alreadyHasStringValue(XftPattern *pattern, const char *object, char *value) +hasProperty(FcPattern *pattern, const char *property) { - XftResult r; - char *s; + FcValue val; + + if (FcPatternGet(pattern, property, 0, &val)==FcResultMatch) { + return True; + } + + return False; +} + + +static Bool +hasPropertyWithStringValue(FcPattern *pattern, const char *object, char *value) +{ + FcChar8 *str; int id; if (!value || value[0]==0) return True; id = 0; - while ((r=XftPatternGetString(pattern, object, id, &s))==XftResultMatch) { - if (strcasecmp(value, s) == 0) { + while (FcPatternGetString(pattern, object, id, &str)==FcResultMatch) { + if (strcasecmp(value, (char*)str) == 0) { return True; } id++; @@ -160,7 +70,6 @@ alreadyHasStringValue(XftPattern *pattern, const char *object, char *value) } -// check if to add a fallback size too. -Dan // also handle an xlfd with %d for size? static char* makeFontOfSize(char *font, int size, char *fallback) @@ -168,14 +77,27 @@ makeFontOfSize(char *font, int size, char *fallback) FcPattern *pattern; char *result; - pattern = XftNameParse(font); - XftPatternDel(pattern, "pixelsize"); - XftPatternAddDouble(pattern, "pixelsize", (double)size); + if (font[0]=='-') { + char *fname; - if (fallback) { - if (!alreadyHasStringValue(pattern, "family", fallback)) { - XftPatternAddString(pattern, "family", fallback); - } + fname = fixXLFD(font, size); + pattern = XftXlfdParse(fname, False, False); + wfree(fname); + } else { + pattern = FcNameParse(font); + } + + //FcPatternPrint(pattern); + if (size > 0) { + FcPatternDel(pattern, "pixelsize"); + FcPatternAddDouble(pattern, "pixelsize", (double)size); + } else if (size==0 && !hasProperty(pattern, "size") && + !hasProperty(pattern, "pixelsize")) { + FcPatternAddDouble(pattern, "pixelsize", (double)DEFAULT_SIZE); + } + + if (fallback && !hasPropertyWithStringValue(pattern, "family", fallback)) { + FcPatternAddString(pattern, "family", fallback); } result = FcNameUnparse(pattern); @@ -353,34 +275,10 @@ WMWidthOfString(WMFont *font, char *text, int length) { XGlyphInfo extents; - wassertrv(font!=NULL, 0); - wassertrv(text!=NULL, 0); + wassertrv(font!=NULL && text!=NULL, 0); - if (font->screen->useWideChar) { - wchar_t *wtext; - const char *mtext; - int len; - - wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); - mtext = text; - len = wmbsnrtowcs(wtext, &mtext, length, length); - if (len>0) { - wtext[len] = L'\0'; /* not really necessary here */ - XftTextExtents32(font->screen->display, font->font, - (XftChar32 *)wtext, len, &extents); - } else { - if (len==-1) { - wwarning(_("Conversion to widechar failed (possible " - "invalid multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - } - extents.xOff = 0; - } - wfree(wtext); - } else { - XftTextExtents8(font->screen->display, font->font, - (XftChar8 *)text, length, &extents); - } + XftTextExtentsUtf8(font->screen->display, font->font, + (XftChar8 *)text, length, &extents); return extents.xOff; /* don't ask :P */ } @@ -403,31 +301,8 @@ WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font, XftDrawChange(scr->xftdraw, d); - if (font->screen->useWideChar) { - wchar_t *wtext; - const char *mtext; - int len; - - wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); - mtext = text; - len = wmbsnrtowcs(wtext, &mtext, length, length); - if (len>0) { - XftDrawString32(scr->xftdraw, &xftcolor, font->font, - x, y + font->y, (XftChar32*)wtext, len); - } else if (len==-1) { - wwarning(_("Conversion to widechar failed (possible invalid " - "multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - /* we can draw normal text, or we can draw as much widechar - * text as was already converted until the error. go figure */ - /*XftDrawString8(scr->xftdraw, &xftcolor, font->font, - x, y + font->y, (XftChar8*)text, length);*/ - } - wfree(wtext); - } else { - XftDrawString8(scr->xftdraw, &xftcolor, font->font, - x, y + font->y, (XftChar8*)text, length); - } + XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, + x, y + font->y, (XftChar8*)text, length); } @@ -458,31 +333,8 @@ WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background WMWidthOfString(font, text, length), font->height); - if (font->screen->useWideChar) { - wchar_t *wtext; - const char *mtext; - int len; - - mtext = text; - wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); - len = wmbsnrtowcs(wtext, &mtext, length, length); - if (len>0) { - XftDrawString32(scr->xftdraw, &textColor, font->font, - x, y + font->y, (XftChar32*)wtext, len); - } else if (len==-1) { - wwarning(_("Conversion to widechar failed (possible invalid " - "multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - /* we can draw normal text, or we can draw as much widechar - * text as was already converted until the error. go figure */ - /*XftDrawString8(scr->xftdraw, &textColor, font->font, - x, y + font->y, (XftChar8*)text, length);*/ - } - wfree(wtext); - } else { - XftDrawString8(scr->xftdraw, &textColor, font->font, - x, y + font->y, (XftChar8*)text, length); - } + XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, + x, y + font->y, (XftChar8*)text, length); } @@ -496,29 +348,30 @@ WMCopyFontWithStyle(WMScreen *scrPtr, WMFont *font, WMFontStyle style) if (!font) return NULL; - pattern = XftNameParse(WMGetFontName(font)); + pattern = FcNameParse(WMGetFontName(font)); switch (style) { case WFSNormal: - XftPatternDel(pattern, "weight"); - XftPatternDel(pattern, "slant"); - XftPatternAddString(pattern, "weight", "medium"); - XftPatternAddString(pattern, "slant", "roman"); + FcPatternDel(pattern, "weight"); + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "weight", "regular"); + FcPatternAddString(pattern, "weight", "medium"); + FcPatternAddString(pattern, "slant", "roman"); break; case WFSBold: - XftPatternDel(pattern, "weight"); - XftPatternAddString(pattern, "weight", "bold"); + FcPatternDel(pattern, "weight"); + FcPatternAddString(pattern, "weight", "bold"); break; case WFSEmphasized: - XftPatternDel(pattern, "slant"); - XftPatternAddString(pattern, "slant", "italic"); - XftPatternAddString(pattern, "slant", "oblique"); + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "slant", "italic"); + FcPatternAddString(pattern, "slant", "oblique"); break; case WFSBoldEmphasized: - XftPatternDel(pattern, "weight"); - XftPatternDel(pattern, "slant"); - XftPatternAddString(pattern, "weight", "bold"); - XftPatternAddString(pattern, "slant", "italic"); - XftPatternAddString(pattern, "slant", "oblique"); + FcPatternDel(pattern, "weight"); + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "weight", "bold"); + FcPatternAddString(pattern, "slant", "italic"); + FcPatternAddString(pattern, "slant", "oblique"); break; } @@ -531,1131 +384,6 @@ WMCopyFontWithStyle(WMScreen *scrPtr, WMFont *font, WMFontStyle style) } -#else /* No XFT support */ - - -static char *makeFontSetOfSize(char *fontset, int size); - - - -/* XLFD pattern matching */ -static char* -getElementFromXLFD(const char *xlfd, int index) -{ - const char *p = xlfd; - while (*p != 0) { - if (*p == '-' && --index == 0) { - const char *end = strchr(p + 1, '-'); - char *buf; - size_t len; - if (end == 0) end = p + strlen(p); - len = end - (p + 1); - buf = wmalloc(len); - memcpy(buf, p + 1, len); - buf[len] = 0; - return buf; - } - p++; - } - return strdup("*"); -} - - -/* XLFD pattern matching */ -static char* -generalizeXLFD(const char *xlfd) -{ - char *buf; - int len; - char *weight = getElementFromXLFD(xlfd, 3); - char *slant = getElementFromXLFD(xlfd, 4); - char *pxlsz = getElementFromXLFD(xlfd, 7); - -#define Xstrlen(A) ((A)?strlen(A):0) - len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+60; -#undef Xstrlen - - buf = wmalloc(len + 1); - snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*," - "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*", - xlfd, weight, slant, pxlsz, pxlsz); - - wfree(pxlsz); - wfree(slant); - wfree(weight); - - return buf; -} - -/* XLFD pattern matching */ -static XFontSet -W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing, - int *nmissing, char **def_string) -{ - XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string); - - if (fs != NULL && *nmissing == 0) return fs; - - /* for non-iso8859-1 language and iso8859-1 specification - (this fontset is only for pattern analysis) */ - if (fs == NULL) { - if (*nmissing != 0) XFreeStringList(*missing); - setlocale(LC_CTYPE, "C"); - fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string); - setlocale(LC_CTYPE, ""); - } - - /* make XLFD font name for pattern analysis */ - if (fs != NULL) { - XFontStruct **fontstructs; - char **fontnames; - if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0) - xlfd = fontnames[0]; - } - - xlfd = generalizeXLFD(xlfd); - - if (*nmissing != 0) XFreeStringList(*missing); - if (fs != NULL) XFreeFontSet(dpy, fs); - - fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string); - - wfree(xlfd); - return fs; -} - - -static char* -xlfdFromFontName(char *fontName, Bool antialiased) -{ - char *systemFont, *boldSystemFont; - char *font; - int size; - - if (antialiased) { - systemFont = WINGsConfiguration.antialiasedSystemFont; - boldSystemFont = WINGsConfiguration.antialiasedBoldSystemFont; - } else { - systemFont = WINGsConfiguration.systemFont; - boldSystemFont = WINGsConfiguration.boldSystemFont; - } - - size = WINGsConfiguration.defaultFontSize; - - if (strcmp(fontName, "SystemFont")==0) { - font = systemFont; - size = WINGsConfiguration.defaultFontSize; - } else if (strncmp(fontName, "SystemFont-", 11)==0) { - font = systemFont; - if (sscanf(&fontName[11], "%i", &size)!=1) { - size = WINGsConfiguration.defaultFontSize; - wwarning(_("Invalid size specification '%s' in %s. " - "Using default %d\n"), &fontName[11], fontName, size); - } - } else if (strcmp(fontName, "BoldSystemFont")==0) { - font = boldSystemFont; - size = WINGsConfiguration.defaultFontSize; - } else if (strncmp(fontName, "BoldSystemFont-", 15)==0) { - font = boldSystemFont; - if (sscanf(&fontName[15], "%i", &size)!=1) { - size = WINGsConfiguration.defaultFontSize; - wwarning(_("Invalid size specification '%s' in %s. " - "Using default %d\n"), &fontName[15], fontName, size); - } - } else { - font = NULL; - } - - return (font!=NULL ? makeFontSetOfSize(font, size) : wstrdup(fontName)); -} - - -WMFont* -WMCreateFontSet(WMScreen *scrPtr, char *fontName) -{ - WMFont *font; - Display *display = scrPtr->display; - char **missing; - int nmissing = 0; - char *defaultString; - char *fname; - XFontSetExtents *extents; - - fname = xlfdFromFontName(fontName, False); - - font = WMHashGet(scrPtr->fontSetCache, fname); - if (font) { - WMRetainFont(font); - wfree(fname); - return font; - } - - font = wmalloc(sizeof(WMFont)); - memset(font, 0, sizeof(WMFont)); - - font->notFontSet = 0; - font->antialiased = 0; - - font->screen = scrPtr; - - font->font.set = W_CreateFontSetWithGuess(display, fname, &missing, - &nmissing, &defaultString); - if (nmissing > 0 && font->font.set) { - int i; - - wwarning(_("the following character sets are missing in %s:"), fname); - for (i = 0; i < nmissing; i++) { - wwarning(missing[i]); - } - XFreeStringList(missing); - if (defaultString) - wwarning(_("the string \"%s\" will be used in place of any characters from those sets."), - defaultString); - } - if (!font->font.set) { - wfree(font); - wfree(fname); - return NULL; - } - - extents = XExtentsOfFontSet(font->font.set); - - font->height = extents->max_logical_extent.height; - font->y = font->height - (font->height + extents->max_logical_extent.y); - - font->refCount = 1; - - font->name = fname; - - assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL); - - return font; -} - - - -WMFont* -WMCreateNormalFont(WMScreen *scrPtr, char *fontName) -{ - WMFont *font; - Display *display = scrPtr->display; - char *fname, *ptr; - - fontName = xlfdFromFontName(fontName, False); - - if ((ptr = strchr(fontName, ','))) { - fname = wmalloc(ptr - fontName + 1); - strncpy(fname, fontName, ptr - fontName); - fname[ptr - fontName] = 0; - } else { - fname = wstrdup(fontName); - } - - wfree(fontName); - - font = WMHashGet(scrPtr->fontCache, fname); - if (font) { - WMRetainFont(font); - wfree(fname); - return font; - } - - font = wmalloc(sizeof(WMFont)); - memset(font, 0, sizeof(WMFont)); - - font->notFontSet = 1; - font->antialiased = 0; - - font->screen = scrPtr; - - font->font.normal = XLoadQueryFont(display, fname); - if (!font->font.normal) { - wfree(font); - wfree(fname); - return NULL; - } - font->height = font->font.normal->ascent+font->font.normal->descent; - font->y = font->font.normal->ascent; - - font->refCount = 1; - - font->name = fname; - - assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL); - - return font; -} - - -WMFont* -WMCreateAntialiasedFont(WMScreen *scrPtr, char *fontName) -{ -#ifdef XFT - WMFont *font; - Display *display = scrPtr->display; - char *fname, *ptr; - - fontName = xlfdFromFontName(fontName, True); - - if ((ptr = strchr(fontName, ','))) { - fname = wmalloc(ptr - fontName + 1); - strncpy(fname, fontName, ptr - fontName); - fname[ptr - fontName] = 0; - } else { - fname = wstrdup(fontName); - } - - wfree(fontName); - - font = WMHashGet(scrPtr->xftFontCache, fname); - if (font) { - WMRetainFont(font); - wfree(fname); - return font; - } - - font = wmalloc(sizeof(WMFont)); - memset(font, 0, sizeof(WMFont)); - - font->notFontSet = 1; - font->antialiased = 1; - - font->screen = scrPtr; - - /* Xft sux. Loading a font with an invalid XLFD will give strange results - * sometimes without returning any warning or error. - * However Xft's idea of what font is invalid is quite strange: - * 1. If the XLFD doesn't have all its fields present will fail and - * return NULL. - * 2. If all fields are present, but hold invalid values then it will: - * a. If family is invalid, will load a default font without warning. - * b. If the font size is invalid (non-numerical) it will fail and - * return NULL. - * c. If other fields are invalid, will load the font specified by - * the valid family name, ignoring any invalid fields. It will - * use a default medium weight and a default roman slant if they - * are invalid. - */ - printf("%s\n", fname); - if (fname[0] == '-') { - font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname); - } else { - font->font.xft = XftFontOpenName(display, scrPtr->screen, fname); - } - if (!font->font.xft) { - wfree(font); - wfree(fname); - return NULL; - } - font->height = font->font.xft->ascent+font->font.xft->descent; - font->y = font->font.xft->ascent; - - font->refCount = 1; - - font->name = fname; - - assert(WMHashInsert(scrPtr->xftFontCache, font->name, font)==NULL); - - return font; -#else - return NULL; -#endif -} - - -WMFont* -WMCreateAntialiasedFontSet(WMScreen *scrPtr, char *fontName) -{ -#ifdef XFT - WMFont *font; - Display *display = scrPtr->display; - char *fname, *ptr; - - fontName = xlfdFromFontName(fontName, True); - - if ((ptr = strchr(fontName, ','))) { - fname = wmalloc(ptr - fontName + 1); - strncpy(fname, fontName, ptr - fontName); - fname[ptr - fontName] = 0; - } else { - fname = wstrdup(fontName); - } - - wfree(fontName); - - font = WMHashGet(scrPtr->xftFontSetCache, fname); - if (font) { - WMRetainFont(font); - wfree(fname); - return font; - } - - font = wmalloc(sizeof(WMFont)); - memset(font, 0, sizeof(WMFont)); - - font->notFontSet = 0; - font->antialiased = 1; - - font->screen = scrPtr; - - /* Xft sux. Loading a font with an invalid XLFD will give strange results - * sometimes without returning any warning or error. - * However Xft's idea of what font is invalid is quite strange: - * 1. If the XLFD doesn't have all its fields present will fail and - * return NULL. - * 2. If all fields are present, but hold invalid values then it will: - * a. If family is invalid, will load a default font without warning. - * b. If the font size is invalid (non-numerical) it will fail and - * return NULL. - * c. If other fields are invalid, will load the font specified by - * the valid family name, ignoring any invalid fields. It will - * use a default medium weight and a default roman slant if they - * are invalid. - */ - if (fname[0] == '-') { - font->font.xft = XftFontOpenXlfd(display, scrPtr->screen, fname); - } else { - font->font.xft = XftFontOpenName(display, scrPtr->screen, fname); - } - if (!font->font.xft) { - wfree(font); - wfree(fname); - return NULL; - } - font->height = font->font.xft->ascent+font->font.xft->descent; - font->y = font->font.xft->ascent; - - font->refCount = 1; - - font->name = fname; - - assert(WMHashInsert(scrPtr->xftFontSetCache, font->name, font)==NULL); - - return font; -#else - return NULL; -#endif -} - - -WMFont* -WMCreateFont(WMScreen *scrPtr, char *fontName) -{ - return WMCreateFontWithFlags(scrPtr, fontName, WFDefaultFont); -} - - -WMFont* -WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags) -{ - Bool multiByte = scrPtr->useMultiByte; - Bool antialiased = scrPtr->antialiasedText; - WMFont *font; - - if (flags & WFFontSet) { - multiByte = True; - } else if (flags & WFNormalFont) { - multiByte = False; - } - if (flags & WFAntialiased) { - antialiased = True; - } else if (flags & WFNotAntialiased) { - antialiased = False; - } - - if (antialiased && multiByte) { - font = WMCreateAntialiasedFontSet(scrPtr, fontName); - /* If we cannot create an antialiased font set and antialiasing is - * not explicitly requested in flags, fallback to standard font sets */ - if (!font && (flags & WFAntialiased)==0) { - font = WMCreateFontSet(scrPtr, fontName); - } - } else if (antialiased) { - font = WMCreateAntialiasedFont(scrPtr, fontName); - /* If we cannot create an antialiased font and antialiasing is - * not explicitly requested in flags, fallback to normal font */ - if (!font && (flags & WFAntialiased)==0) { - font = WMCreateNormalFont(scrPtr, fontName); - } - } else if (multiByte) { - font = WMCreateFontSet(scrPtr, fontName); - } else { - font = WMCreateNormalFont(scrPtr, fontName); - } - - return font; -} - - -WMFont* -WMRetainFont(WMFont *font) -{ - wassertrv(font!=NULL, NULL); - - font->refCount++; - - return font; -} - - -void -WMReleaseFont(WMFont *font) -{ - wassertr(font!=NULL); - - font->refCount--; - if (font->refCount < 1) { - if (font->antialiased) { -#ifdef XFT - XftFontClose(font->screen->display, font->font.xft); -#else - assert(False); -#endif - } else if (font->notFontSet) { - XFreeFont(font->screen->display, font->font.normal); - } else { - XFreeFontSet(font->screen->display, font->font.set); - } - - if (font->name) { - if (font->antialiased && !font->notFontSet) { - WMHashRemove(font->screen->xftFontSetCache, font->name); - } else if (font->antialiased) { - WMHashRemove(font->screen->xftFontCache, font->name); - } else if (font->notFontSet) { - WMHashRemove(font->screen->fontCache, font->name); - } else { - WMHashRemove(font->screen->fontSetCache, font->name); - } - wfree(font->name); - } - wfree(font); - } -} - - -Bool -WMIsAntialiasingEnabled(WMScreen *scrPtr) -{ - return scrPtr->antialiasedText; -} - - -Bool -WMIsAntialiasedFont(WMFont *font) -{ - wassertrv(font!=NULL, False); - - return font->antialiased; -} - - -unsigned int -WMFontHeight(WMFont *font) -{ - wassertrv(font!=NULL, 0); - - return font->height; -} - - -char* -WMGetFontName(WMFont *font) -{ - wassertrv(font!=NULL, NULL); - - return font->name; -} - - -WMFont* -WMDefaultSystemFont(WMScreen *scrPtr) -{ - return WMRetainFont(scrPtr->normalFont); -} - - -WMFont* -WMDefaultBoldSystemFont(WMScreen *scrPtr) -{ - return WMRetainFont(scrPtr->boldFont); -} - - -static WMFont* -makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold) -{ - WMFont *font; - char *fontSpec, *xftFontSpec; - -#define WConf WINGsConfiguration - if (bold) { - fontSpec = makeFontSetOfSize(WConf.boldSystemFont, size); - xftFontSpec = makeFontSetOfSize(WConf.antialiasedBoldSystemFont, size); - } else { - fontSpec = makeFontSetOfSize(WConf.systemFont, size); - xftFontSpec = makeFontSetOfSize(WConf.antialiasedSystemFont, size); - } -#undef WConf - - if (scrPtr->antialiasedText && scrPtr->useMultiByte) { - font = WMCreateAntialiasedFontSet(scrPtr, xftFontSpec); - } else if (scrPtr->antialiasedText) { - font = WMCreateAntialiasedFont(scrPtr, xftFontSpec); - } else if (scrPtr->useMultiByte) { - font = WMCreateFontSet(scrPtr, fontSpec); - } else { - font = WMCreateNormalFont(scrPtr, fontSpec); - } - - if (!font) { - if (scrPtr->antialiasedText && scrPtr->useMultiByte) { - // is arial a good fallback for multibyte? - wwarning(_("could not load font %s. Trying arial."), xftFontSpec); - if (bold) { - font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*"); - } else { - font = WMCreateAntialiasedFontSet(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*"); - } - if (!font) { - wwarning(_("could not load antialiased font set. Reverting to standard font sets.")); - font = WMCreateFontSet(scrPtr, fontSpec); - if (!font) { - wwarning(_("could not load FontSet %s. Trying fixed."), fontSpec); - font = WMCreateFontSet(scrPtr, "fixed"); - } - } - } else if (scrPtr->antialiasedText) { - wwarning(_("could not load font %s. Trying arial."), xftFontSpec); - if (bold) { - font = WMCreateAntialiasedFont(scrPtr, "-*-arial-bold-r-normal-*-12-*-*-*-*-*-*-*"); - } else { - font = WMCreateAntialiasedFont(scrPtr, "-*-arial-medium-r-normal-*-12-*-*-*-*-*-*-*"); - } - if (!font) { - wwarning(_("could not load antialiased fonts. Reverting to normal fonts.")); - font = WMCreateNormalFont(scrPtr, fontSpec); - if (!font) { - wwarning(_("could not load font %s. Trying fixed."), fontSpec); - font = WMCreateNormalFont(scrPtr, "fixed"); - } - } - } else if (scrPtr->useMultiByte) { - wwarning(_("could not load font set %s. Trying fixed."), fontSpec); - font = WMCreateFontSet(scrPtr, "fixed"); - if (!font) { - font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*"); - } - } else { - wwarning(_("could not load font %s. Trying fixed."), fontSpec); - font = WMCreateNormalFont(scrPtr, "fixed"); - } - if (!font) { - wwarning(_("could not load fixed font!")); - wfree(fontSpec); - wfree(xftFontSpec); - return NULL; - } - } - wfree(fontSpec); - wfree(xftFontSpec); - - return font; -} - - -WMFont* -WMSystemFontOfSize(WMScreen *scrPtr, int size) -{ - return makeSystemFontOfSize(scrPtr, size, False); -} - - -WMFont* -WMBoldSystemFontOfSize(WMScreen *scrPtr, int size) -{ - return makeSystemFontOfSize(scrPtr, size, True); -} - - -XFontSet -WMGetFontFontSet(WMFont *font) -{ - wassertrv(font!=NULL, NULL); - - if (!font->notFontSet && !font->antialiased) - return font->font.set; - - return NULL; -} - - -int -WMWidthOfString(WMFont *font, char *text, int length) -{ - wassertrv(font!=NULL, 0); - wassertrv(text!=NULL, 0); - - if (font->antialiased) { -#ifdef XFT - XGlyphInfo extents; - - if (!font->notFontSet) { - wchar_t *wtext; - char *mtext; - int len; - - /* Use mtext instead of text, because mbstrtowcs() alters it */ - mtext = text; - wtext = (wchar_t *)wmalloc(4*length+4); - /* pass a real ps instead of NULL below? for multithread safety - * as from manual page */ - len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL); - if (len>0) { - XftTextExtents32(font->screen->display, font->font.xft, - (XftChar32 *)wtext, len, &extents); - } else { - if (len==-1) { - wwarning(_("Conversion to widechar failed (possible " - "invalid multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - } - extents.xOff = 0; - } - wfree(wtext); - } else { - XftTextExtents8(font->screen->display, font->font.xft, - (XftChar8 *)text, length, &extents); - } - - return extents.xOff; /* don't ask :P */ -#else - wassertrv(False, 0); -#endif - } else if (font->notFontSet) { - return XTextWidth(font->font.normal, text, length); - } else { - XRectangle rect; - XRectangle AIXsucks; - - XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect); - - return rect.width; - } -} - - - -void -WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font, - int x, int y, char *text, int length) -{ - wassertr(font!=NULL); - - if (font->antialiased) { -#ifdef XFT - XftColor xftcolor; - - xftcolor.color.red = color->color.red; - xftcolor.color.green = color->color.green; - xftcolor.color.blue = color->color.blue; - xftcolor.color.alpha = color->alpha;; - xftcolor.pixel = W_PIXEL(color); - - XftDrawChange(scr->xftdraw, d); - - if (!font->notFontSet) { - wchar_t *wtext; - char *mtext; - int len; - - /* Use mtext instead of text, because mbstrtowcs() alters it */ - mtext = text; - wtext = (wchar_t *)wmalloc(4*length+4); - len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL); - if (len>0) { - XftDrawString32(scr->xftdraw, &xftcolor, font->font.xft, - x, y + font->y, (XftChar32*)wtext, len); - } else if (len==-1) { - wwarning(_("Conversion to widechar failed (possible invalid " - "multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - /* we can draw normal text, or we can draw as much widechar - * text as was already converted until the error. go figure */ - /*XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft, - x, y + font->y, (XftChar8*)text, length);*/ - } - wfree(wtext); - } else { - XftDrawString8(scr->xftdraw, &xftcolor, font->font.xft, - x, y + font->y, (XftChar8*)text, length); - } -#else - wassertr(False); -#endif - } else if (font->notFontSet) { - XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid); - XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color)); - XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y, - text, length); - } else { - XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color)); - XmbDrawString(scr->display, d, font->font.set, scr->drawStringGC, - x, y + font->y, text, length); - } -} - - -void -WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background, - WMFont *font, int x, int y, char *text, int length) -{ - wassertr(font!=NULL); - - if (font->antialiased) { -#ifdef XFT - XftColor textColor; - XftColor bgColor; - - textColor.color.red = color->color.red; - textColor.color.green = color->color.green; - textColor.color.blue = color->color.blue; - textColor.color.alpha = color->alpha;; - textColor.pixel = W_PIXEL(color); - - bgColor.color.red = background->color.red; - bgColor.color.green = background->color.green; - bgColor.color.blue = background->color.blue; - bgColor.color.alpha = background->alpha;; - bgColor.pixel = W_PIXEL(background); - - - XftDrawChange(scr->xftdraw, d); - - XftDrawRect(scr->xftdraw, &bgColor, x, y, - WMWidthOfString(font, text, length), font->height); - - if (!font->notFontSet) { - wchar_t *wtext; - char *mtext; - int len; - - /* Use mtext instead of text, because mbstrtowcs() alters it */ - mtext = text; - wtext = (wchar_t *)wmalloc(4*length+4); - len = mbsrtowcs(wtext, (const char **) &mtext, length, NULL); - if (len>0) { - XftDrawString32(scr->xftdraw, &textColor, font->font.xft, - x, y + font->y, (XftChar32*)wtext, len); - } else if (len==-1) { - wwarning(_("Conversion to widechar failed (possible invalid " - "multibyte sequence): '%s':(pos %d)\n"), - text, mtext-text+1); - /* we can draw normal text, or we can draw as much widechar - * text as was already converted until the error. go figure */ - /*XftDrawString8(scr->xftdraw, &textColor, font->font.xft, - x, y + font->y, (XftChar8*)text, length);*/ - } - wfree(wtext); - } else { - XftDrawString8(scr->xftdraw, &textColor, font->font.xft, - x, y + font->y, (XftChar8*)text, length); - } -#else - wassertr(False); -#endif - } else if (font->notFontSet) { - XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color)); - XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background)); - XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid); - XDrawImageString(scr->display, d, scr->drawImStringGC, - x, y + font->y, text, length); - } else { - XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color)); - XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background)); - XmbDrawImageString(scr->display, d, font->font.set, scr->drawImStringGC, - x, y + font->y, text, length); - } -} - - - - -static char* -makeFontSetOfSize(char *fontset, int size) -{ - char font[300], *f; - char *newfs = NULL; - char *ptr; - - do { - char *tmp; - int end; - - - f = fontset; - ptr = strchr(fontset, ','); - if (ptr) { - int count = ptr-fontset; - - if (count > 255) { - wwarning(_("font description %s is too large."), fontset); - } else { - memcpy(font, fontset, count); - font[count] = 0; - f = (char*)font; - } - } - - if (newfs) - end = strlen(newfs); - else - end = 0; - - tmp = wmalloc(end + strlen(f) + 8); - if (end != 0) { - sprintf(tmp, "%s,", newfs); - sprintf(tmp + end + 1, f, size); - } else { - sprintf(tmp + end, f, size); - } - - if (newfs) - wfree(newfs); - newfs = tmp; - - fontset = ptr+1; - } while (ptr!=NULL); - - return newfs; -} - - -#define FONT_PROPS 14 - -typedef struct { - char *props[FONT_PROPS]; -} W_FontAttributes; - - -static void -changeFontProp(char *buf, char *newprop, int position) -{ - char buf2[512]; - char *ptr, *pptr, *rptr; - int count; - - if (buf[0]!='-') { - /* // remove warning later. or maybe not */ - wwarning(_("Invalid font specification: '%s'\n"), buf); - return; - } - - ptr = pptr = rptr = buf; - count = 0; - while (*ptr && *ptr!=',') { - if (*ptr == '-') { - count++; - if (count-1==position+1) { - rptr = ptr; - break; - } - if (count-1==position) { - pptr = ptr+1; - } - } - ptr++; - } - if (position==FONT_PROPS-1) { - rptr = ptr; - } - - *pptr = 0; - snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr); - strcpy(buf, buf2); -} - - -static WMArray* -getOptions(char *options) -{ - char *ptr, *ptr2, *str; - WMArray *result; - int count; - - result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree); - - ptr = options; - while (1) { - ptr2 = strchr(ptr, ','); - if (!ptr2) { - WMAddToArray(result, wstrdup(ptr)); - break; - } else { - count = ptr2 - ptr; - str = wmalloc(count+1); - memcpy(str, ptr, count); - str[count] = 0; - WMAddToArray(result, str); - ptr = ptr2 + 1; - } - } - - return result; -} - - -#define WFAUnchanged (NULL) -/* Struct for font change operations */ -typedef struct WMFontAttributes { - char *foundry; - char *family; - char *weight; - char *slant; - char *setWidth; - char *addStyle; - char *pixelSize; - char *pointSize; - char *resolutionX; - char *resolutionY; - char *spacing; - char *averageWidth; - char *registry; - char *encoding; -} WMFontAttributes; - -WMFont* -WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font, - const WMFontAttributes *changes) -{ - int index[FONT_PROPS], count[FONT_PROPS]; - int totalProps, i, j, carry; - char fname[512]; - WMFontFlags fFlags; - WMBag *props; - WMArray *options; - WMFont *result; - char *prop; - - snprintf(fname, 512, "%s", font->name); - - fFlags = (font->antialiased ? WFAntialiased : WFNotAntialiased); - fFlags |= (font->notFontSet ? WFNormalFont : WFFontSet); - - props = WMCreateBagWithDestructor(1, (WMFreeDataProc*)WMFreeArray); - - totalProps = 0; - for (i=0; iprops[i]; - count[i] = index[i] = 0; - if (!prop) { - /* No change for this property */ - continue; - } else if (strchr(prop, ',')==NULL) { - /* Simple option */ - changeFontProp(fname, prop, i); - } else { - /* Option with fallback alternatives */ - if ((changes==WFAEmphasized || changes==WFABoldEmphasized) && - font->antialiased && strcmp(prop, "o,i")==0) { - options = getOptions("i,o"); - } else { - options = getOptions(prop); - } - WMInsertInBag(props, i, options); - count[i] = WMGetArrayItemCount(options); - if (totalProps==0) - totalProps = 1; - totalProps = totalProps * count[i]; - } - } - - if (totalProps == 0) { - /* No options with fallback alternatives at all */ - WMFreeBag(props); - return WMCreateFontWithFlags(scrPtr, fname, fFlags); - } - - for (i=0; i=0; j--) { - if (count[j]!=0) { - index[j] += carry; - carry = (index[j]==count[j]); - index[j] %= count[j]; - } - } - } - - WMFreeBag(props); - - return NULL; -} - -// should WFANormal also set "normal" or leave it alone? -static const WMFontAttributes W_FANormal = { - WFAUnchanged, WFAUnchanged, "medium,normal,regular", "r", "normal", - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged -}; - - -static const WMFontAttributes W_FABold = { - WFAUnchanged, WFAUnchanged, "bold", WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged -}; - - -static const WMFontAttributes W_FANotBold = { - WFAUnchanged, WFAUnchanged, "medium,normal,regular", WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged -}; - - -static const WMFontAttributes W_FAEmphasized = { - WFAUnchanged, WFAUnchanged, WFAUnchanged, "o,i", - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged -}; - - -static const WMFontAttributes W_FANotEmphasized = { - WFAUnchanged, WFAUnchanged, WFAUnchanged, "r", - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged -}; - - -static const WMFontAttributes W_FABoldEmphasized = { - WFAUnchanged, WFAUnchanged, "bold", "o,i", - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, - WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged -}; - - -const WMFontAttributes *WFANormal = &W_FANormal; -const WMFontAttributes *WFABold = &W_FABold; -const WMFontAttributes *WFANotBold = &W_FANotBold; -const WMFontAttributes *WFAEmphasized = &W_FAEmphasized; -const WMFontAttributes *WFANotEmphasized = &W_FANotEmphasized; -const WMFontAttributes *WFABoldEmphasized = &W_FABoldEmphasized; - - -#endif +#endif /* XFT */ diff --git a/WINGs/wfont_noxft.c b/WINGs/wfont_noxft.c new file mode 100644 index 00000000..ffd817c7 --- /dev/null +++ b/WINGs/wfont_noxft.c @@ -0,0 +1,769 @@ + + +#include "wconfig.h" + +#ifndef XFT + +#include "WINGsP.h" + +#include +#include +#include + + +static char *makeFontSetOfSize(char *fontset, int size); + + +/* XLFD pattern matching */ +static char* +getElementFromXLFD(const char *xlfd, int index) +{ + const char *p = xlfd; + while (*p != 0) { + if (*p == '-' && --index == 0) { + const char *end = strchr(p + 1, '-'); + char *buf; + size_t len; + if (end == 0) end = p + strlen(p); + len = end - (p + 1); + buf = wmalloc(len); + memcpy(buf, p + 1, len); + buf[len] = 0; + return buf; + } + p++; + } + return strdup("*"); +} + + +/* XLFD pattern matching */ +static char* +generalizeXLFD(const char *xlfd) +{ + char *buf; + int len; + char *weight = getElementFromXLFD(xlfd, 3); + char *slant = getElementFromXLFD(xlfd, 4); + char *pxlsz = getElementFromXLFD(xlfd, 7); + +#define Xstrlen(A) ((A)?strlen(A):0) + len = Xstrlen(xlfd)+Xstrlen(weight)+Xstrlen(slant)+Xstrlen(pxlsz)*2+60; +#undef Xstrlen + + buf = wmalloc(len + 1); + snprintf(buf, len + 1, "%s,-*-*-%s-%s-*-*-%s-*-*-*-*-*-*-*," + "-*-*-*-*-*-*-%s-*-*-*-*-*-*-*,*", + xlfd, weight, slant, pxlsz, pxlsz); + + wfree(pxlsz); + wfree(slant); + wfree(weight); + + return buf; +} + +/* XLFD pattern matching */ +static XFontSet +W_CreateFontSetWithGuess(Display *dpy, char *xlfd, char ***missing, + int *nmissing, char **def_string) +{ + XFontSet fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string); + + if (fs != NULL && *nmissing == 0) return fs; + + /* for non-iso8859-1 language and iso8859-1 specification + (this fontset is only for pattern analysis) */ + if (fs == NULL) { + if (*nmissing != 0) XFreeStringList(*missing); + setlocale(LC_CTYPE, "C"); + fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string); + setlocale(LC_CTYPE, ""); + } + + /* make XLFD font name for pattern analysis */ + if (fs != NULL) { + XFontStruct **fontstructs; + char **fontnames; + if (XFontsOfFontSet(fs, &fontstructs, &fontnames) > 0) + xlfd = fontnames[0]; + } + + xlfd = generalizeXLFD(xlfd); + + if (*nmissing != 0) XFreeStringList(*missing); + if (fs != NULL) XFreeFontSet(dpy, fs); + + fs = XCreateFontSet(dpy, xlfd, missing, nmissing, def_string); + + wfree(xlfd); + return fs; +} + + +static char* +xlfdFromFontName(char *fontName) +{ + char *systemFont, *boldSystemFont; + char *font; + int size; + + systemFont = WINGsConfiguration.systemFont; + boldSystemFont = WINGsConfiguration.boldSystemFont; + + size = WINGsConfiguration.defaultFontSize; + + if (strcmp(fontName, "SystemFont")==0) { + font = systemFont; + } else if (strncmp(fontName, "SystemFont-", 11)==0) { + font = systemFont; + if (sscanf(&fontName[11], "%i", &size)!=1) { + size = WINGsConfiguration.defaultFontSize; + wwarning(_("Invalid size specification '%s' in %s. " + "Using default %d\n"), &fontName[11], fontName, size); + } + } else if (strcmp(fontName, "BoldSystemFont")==0) { + font = boldSystemFont; + } else if (strncmp(fontName, "BoldSystemFont-", 15)==0) { + font = boldSystemFont; + if (sscanf(&fontName[15], "%i", &size)!=1) { + size = WINGsConfiguration.defaultFontSize; + wwarning(_("Invalid size specification '%s' in %s. " + "Using default %d\n"), &fontName[15], fontName, size); + } + } else { + font = NULL; + } + + return (font!=NULL ? makeFontSetOfSize(font, size) : wstrdup(fontName)); +} + + +WMFont* +WMCreateFontSet(WMScreen *scrPtr, char *fontName) +{ + WMFont *font; + Display *display = scrPtr->display; + char **missing; + int nmissing = 0; + char *defaultString; + char *fname; + XFontSetExtents *extents; + + fname = xlfdFromFontName(fontName); + + font = WMHashGet(scrPtr->fontSetCache, fname); + if (font) { + WMRetainFont(font); + wfree(fname); + return font; + } + + font = wmalloc(sizeof(WMFont)); + memset(font, 0, sizeof(WMFont)); + + font->notFontSet = 0; + + font->screen = scrPtr; + + font->font.set = W_CreateFontSetWithGuess(display, fname, &missing, + &nmissing, &defaultString); + if (nmissing > 0 && font->font.set) { + int i; + + wwarning(_("the following character sets are missing in %s:"), fname); + for (i = 0; i < nmissing; i++) { + wwarning(missing[i]); + } + XFreeStringList(missing); + if (defaultString) + wwarning(_("the string \"%s\" will be used in place of any characters from those sets."), + defaultString); + } + if (!font->font.set) { + wfree(font); + wfree(fname); + return NULL; + } + + extents = XExtentsOfFontSet(font->font.set); + + font->height = extents->max_logical_extent.height; + font->y = font->height - (font->height + extents->max_logical_extent.y); + + font->refCount = 1; + + font->name = fname; + + assert(WMHashInsert(scrPtr->fontSetCache, font->name, font)==NULL); + + return font; +} + + + +WMFont* +WMCreateNormalFont(WMScreen *scrPtr, char *fontName) +{ + WMFont *font; + Display *display = scrPtr->display; + char *fname, *ptr; + + fontName = xlfdFromFontName(fontName); + + if ((ptr = strchr(fontName, ','))) { + fname = wmalloc(ptr - fontName + 1); + strncpy(fname, fontName, ptr - fontName); + fname[ptr - fontName] = 0; + } else { + fname = wstrdup(fontName); + } + + wfree(fontName); + + font = WMHashGet(scrPtr->fontCache, fname); + if (font) { + WMRetainFont(font); + wfree(fname); + return font; + } + + font = wmalloc(sizeof(WMFont)); + memset(font, 0, sizeof(WMFont)); + + font->notFontSet = 1; + + font->screen = scrPtr; + + font->font.normal = XLoadQueryFont(display, fname); + if (!font->font.normal) { + wfree(font); + wfree(fname); + return NULL; + } + font->height = font->font.normal->ascent+font->font.normal->descent; + font->y = font->font.normal->ascent; + + font->refCount = 1; + + font->name = fname; + + assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL); + + return font; +} + + +WMFont* +WMCreateFont(WMScreen *scrPtr, char *fontName) +{ + return WMCreateFontWithFlags(scrPtr, fontName, WFDefaultFont); +} + + +WMFont* +WMCreateFontWithFlags(WMScreen *scrPtr, char *fontName, WMFontFlags flags) +{ + Bool multiByte = scrPtr->useMultiByte; + WMFont *font; + + if (flags & WFFontSet) { + multiByte = True; + } else if (flags & WFNormalFont) { + multiByte = False; + } + + } else if (multiByte) { + font = WMCreateFontSet(scrPtr, fontName); + } else { + font = WMCreateNormalFont(scrPtr, fontName); + } + + return font; +} + + +WMFont* +WMRetainFont(WMFont *font) +{ + wassertrv(font!=NULL, NULL); + + font->refCount++; + + return font; +} + + +void +WMReleaseFont(WMFont *font) +{ + wassertr(font!=NULL); + + font->refCount--; + if (font->refCount < 1) { + if (font->notFontSet) { + XFreeFont(font->screen->display, font->font.normal); + } else { + XFreeFontSet(font->screen->display, font->font.set); + } + + if (font->name) { + if (font->notFontSet) { + WMHashRemove(font->screen->fontCache, font->name); + } else { + WMHashRemove(font->screen->fontSetCache, font->name); + } + wfree(font->name); + } + wfree(font); + } +} + + +Bool +WMIsAntialiasingEnabled(WMScreen *scrPtr) +{ + return False; +} + + +unsigned int +WMFontHeight(WMFont *font) +{ + wassertrv(font!=NULL, 0); + + return font->height; +} + + +char* +WMGetFontName(WMFont *font) +{ + wassertrv(font!=NULL, NULL); + + return font->name; +} + + +WMFont* +WMDefaultSystemFont(WMScreen *scrPtr) +{ + return WMRetainFont(scrPtr->normalFont); +} + + +WMFont* +WMDefaultBoldSystemFont(WMScreen *scrPtr) +{ + return WMRetainFont(scrPtr->boldFont); +} + + +static WMFont* +makeSystemFontOfSize(WMScreen *scrPtr, int size, Bool bold) +{ + WMFont *font; + char *fontSpec; + +#define WConf WINGsConfiguration + if (bold) { + fontSpec = makeFontSetOfSize(WConf.boldSystemFont, size); + } else { + fontSpec = makeFontSetOfSize(WConf.systemFont, size); + } +#undef WConf + + if (scrPtr->useMultiByte) { + font = WMCreateFontSet(scrPtr, fontSpec); + } else { + font = WMCreateNormalFont(scrPtr, fontSpec); + } + + if (!font) { + if (scrPtr->useMultiByte) { + wwarning(_("could not load font set %s. Trying fixed."), fontSpec); + font = WMCreateFontSet(scrPtr, "fixed"); + if (!font) { + font = WMCreateFontSet(scrPtr, "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*"); + } + } else { + wwarning(_("could not load font %s. Trying fixed."), fontSpec); + font = WMCreateNormalFont(scrPtr, "fixed"); + } + if (!font) { + wwarning(_("could not load fixed font!")); + wfree(fontSpec); + return NULL; + } + } + wfree(fontSpec); + + return font; +} + + +WMFont* +WMSystemFontOfSize(WMScreen *scrPtr, int size) +{ + return makeSystemFontOfSize(scrPtr, size, False); +} + + +WMFont* +WMBoldSystemFontOfSize(WMScreen *scrPtr, int size) +{ + return makeSystemFontOfSize(scrPtr, size, True); +} + + +XFontSet +WMGetFontFontSet(WMFont *font) +{ + wassertrv(font!=NULL, NULL); + + if (!font->notFontSet && !font->antialiased) + return font->font.set; + + return NULL; +} + + +int +WMWidthOfString(WMFont *font, char *text, int length) +{ + wassertrv(font!=NULL, 0); + wassertrv(text!=NULL, 0); + + if (font->notFontSet) { + return XTextWidth(font->font.normal, text, length); + } else { + XRectangle rect; + XRectangle AIXsucks; + + XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect); + + return rect.width; + } +} + + + +void +WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font, + int x, int y, char *text, int length) +{ + wassertr(font!=NULL); + + if (font->notFontSet) { + XSetFont(scr->display, scr->drawStringGC, font->font.normal->fid); + XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color)); + XDrawString(scr->display, d, scr->drawStringGC, x, y + font->y, + text, length); + } else { + XSetForeground(scr->display, scr->drawStringGC, W_PIXEL(color)); + XmbDrawString(scr->display, d, font->font.set, scr->drawStringGC, + x, y + font->y, text, length); + } +} + + +void +WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background, + WMFont *font, int x, int y, char *text, int length) +{ + wassertr(font!=NULL); + + if (font->notFontSet) { + XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color)); + XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background)); + XSetFont(scr->display, scr->drawImStringGC, font->font.normal->fid); + XDrawImageString(scr->display, d, scr->drawImStringGC, + x, y + font->y, text, length); + } else { + XSetForeground(scr->display, scr->drawImStringGC, W_PIXEL(color)); + XSetBackground(scr->display, scr->drawImStringGC, W_PIXEL(background)); + XmbDrawImageString(scr->display, d, font->font.set, scr->drawImStringGC, + x, y + font->y, text, length); + } +} + + + + +static char* +makeFontSetOfSize(char *fontset, int size) +{ + char font[300], *f; + char *newfs = NULL; + char *ptr; + + do { + char *tmp; + int end; + + + f = fontset; + ptr = strchr(fontset, ','); + if (ptr) { + int count = ptr-fontset; + + if (count > 255) { + wwarning(_("font description %s is too large."), fontset); + } else { + memcpy(font, fontset, count); + font[count] = 0; + f = (char*)font; + } + } + + if (newfs) + end = strlen(newfs); + else + end = 0; + + tmp = wmalloc(end + strlen(f) + 8); + if (end != 0) { + sprintf(tmp, "%s,", newfs); + sprintf(tmp + end + 1, f, size); + } else { + sprintf(tmp + end, f, size); + } + + if (newfs) + wfree(newfs); + newfs = tmp; + + fontset = ptr+1; + } while (ptr!=NULL); + + return newfs; +} + + +#define FONT_PROPS 14 + +typedef struct { + char *props[FONT_PROPS]; +} W_FontAttributes; + + +static void +changeFontProp(char *buf, char *newprop, int position) +{ + char buf2[512]; + char *ptr, *pptr, *rptr; + int count; + + if (buf[0]!='-') { + /* // remove warning later. or maybe not */ + wwarning(_("Invalid font specification: '%s'\n"), buf); + return; + } + + ptr = pptr = rptr = buf; + count = 0; + while (*ptr && *ptr!=',') { + if (*ptr == '-') { + count++; + if (count-1==position+1) { + rptr = ptr; + break; + } + if (count-1==position) { + pptr = ptr+1; + } + } + ptr++; + } + if (position==FONT_PROPS-1) { + rptr = ptr; + } + + *pptr = 0; + snprintf(buf2, 512, "%s%s%s", buf, newprop, rptr); + strcpy(buf, buf2); +} + + +static WMArray* +getOptions(char *options) +{ + char *ptr, *ptr2, *str; + WMArray *result; + int count; + + result = WMCreateArrayWithDestructor(2, (WMFreeDataProc*)wfree); + + ptr = options; + while (1) { + ptr2 = strchr(ptr, ','); + if (!ptr2) { + WMAddToArray(result, wstrdup(ptr)); + break; + } else { + count = ptr2 - ptr; + str = wmalloc(count+1); + memcpy(str, ptr, count); + str[count] = 0; + WMAddToArray(result, str); + ptr = ptr2 + 1; + } + } + + return result; +} + + +#define WFAUnchanged (NULL) +/* Struct for font change operations */ +typedef struct WMFontAttributes { + char *foundry; + char *family; + char *weight; + char *slant; + char *setWidth; + char *addStyle; + char *pixelSize; + char *pointSize; + char *resolutionX; + char *resolutionY; + char *spacing; + char *averageWidth; + char *registry; + char *encoding; +} WMFontAttributes; + +WMFont* +WMCopyFontWithChanges(WMScreen *scrPtr, WMFont *font, + const WMFontAttributes *changes) +{ + int index[FONT_PROPS], count[FONT_PROPS]; + int totalProps, i, j, carry; + char fname[512]; + WMFontFlags fFlags; + WMBag *props; + WMArray *options; + WMFont *result; + char *prop; + + snprintf(fname, 512, "%s", font->name); + + fFlags = (font->antialiased ? WFAntialiased : WFNotAntialiased); + fFlags |= (font->notFontSet ? WFNormalFont : WFFontSet); + + props = WMCreateBagWithDestructor(1, (WMFreeDataProc*)WMFreeArray); + + totalProps = 0; + for (i=0; iprops[i]; + count[i] = index[i] = 0; + if (!prop) { + /* No change for this property */ + continue; + } else if (strchr(prop, ',')==NULL) { + /* Simple option */ + changeFontProp(fname, prop, i); + } else { + /* Option with fallback alternatives */ + if ((changes==WFAEmphasized || changes==WFABoldEmphasized) && + font->antialiased && strcmp(prop, "o,i")==0) { + options = getOptions("i,o"); + } else { + options = getOptions(prop); + } + WMInsertInBag(props, i, options); + count[i] = WMGetArrayItemCount(options); + if (totalProps==0) + totalProps = 1; + totalProps = totalProps * count[i]; + } + } + + if (totalProps == 0) { + /* No options with fallback alternatives at all */ + WMFreeBag(props); + return WMCreateFontWithFlags(scrPtr, fname, fFlags); + } + + for (i=0; i=0; j--) { + if (count[j]!=0) { + index[j] += carry; + carry = (index[j]==count[j]); + index[j] %= count[j]; + } + } + } + + WMFreeBag(props); + + return NULL; +} + +// should WFANormal also set "normal" or leave it alone? +static const WMFontAttributes W_FANormal = { + WFAUnchanged, WFAUnchanged, "medium,normal,regular", "r", "normal", + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged +}; + + +static const WMFontAttributes W_FABold = { + WFAUnchanged, WFAUnchanged, "bold", WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged +}; + + +static const WMFontAttributes W_FANotBold = { + WFAUnchanged, WFAUnchanged, "medium,normal,regular", WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged +}; + + +static const WMFontAttributes W_FAEmphasized = { + WFAUnchanged, WFAUnchanged, WFAUnchanged, "o,i", + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged +}; + + +static const WMFontAttributes W_FANotEmphasized = { + WFAUnchanged, WFAUnchanged, WFAUnchanged, "r", + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged +}; + + +static const WMFontAttributes W_FABoldEmphasized = { + WFAUnchanged, WFAUnchanged, "bold", "o,i", + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, + WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged, WFAUnchanged +}; + + +const WMFontAttributes *WFANormal = &W_FANormal; +const WMFontAttributes *WFABold = &W_FABold; +const WMFontAttributes *WFANotBold = &W_FANotBold; +const WMFontAttributes *WFAEmphasized = &W_FAEmphasized; +const WMFontAttributes *WFANotEmphasized = &W_FANotEmphasized; +const WMFontAttributes *WFABoldEmphasized = &W_FABoldEmphasized; + + +#endif + diff --git a/WINGs/wfont_wchar.c b/WINGs/wfont_wchar.c new file mode 100644 index 00000000..cfc6f03c --- /dev/null +++ b/WINGs/wfont_wchar.c @@ -0,0 +1,599 @@ + +#include "wconfig.h" + +#ifdef XFT + +#include +#include + +#if defined(HAVE_MBSNRTOWCS) +# define __USE_GNU +#endif + +#ifdef HAVE_WCHAR_H +# include +#endif + +#include + +#include "WINGsP.h" + +#include +#include +#include + + +// && defined(HAVE_MBSTATE_T___COUNT) +// in configure.ac use AC_CHECK_MEMBER(struct mbstate_t.__count, +// have=1, have=0, [#include ]) +#if defined(HAVE_MBSNRTOWCS) + +static size_t +wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) +{ + mbstate_t ps; + size_t n; + + memset(&ps, 0, sizeof(mbstate_t)); + n = mbsnrtowcs(dest, src, nbytes, len, &ps); + if (n!=(size_t)-1 && *src) { + *src -= ps.__count; + } + + return n; +} + +#elif defined(HAVE_MBRTOWC) + +// This is 8 times slower than the version above. +static size_t +wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) +{ + mbstate_t ps; + const char *ptr; + size_t n; + int nb; + + if (nbytes==0) + return 0; + + memset(&ps, 0, sizeof(mbstate_t)); + + if (dest == NULL) { + for (ptr=*src, n=0; nbytes>0; n++) { + nb = mbrtowc(NULL, ptr, nbytes, &ps); + if (nb == -1) { + return ((size_t)-1); + } else if (nb==0 || nb==-2) { + return n; + } + ptr += nb; + nbytes -= nb; + } + } + + for (ptr=*src, n=0; n0; n++, dest++) { + nb = mbrtowc(dest, ptr, nbytes, &ps); + if (nb == -2) { + *src = ptr; + return n; + } else if (nb == -1) { + *src = ptr; + return ((size_t)-1); + } else if (nb == 0) { + *src = NULL; + return n; + } + ptr += nb; + nbytes -= nb; + } + + *src = ptr; + return n; +} + +#else + +// Not only 8 times slower than the version based on mbsnrtowcs +// but also this version is not thread safe nor reentrant + +static size_t +wmbsnrtowcs(wchar_t *dest, const char **src, size_t nbytes, size_t len) +{ + const char *ptr; + size_t n; + int nb; + + if (nbytes==0) + return 0; + + mbtowc(NULL, NULL, 0); /* reset shift state */ + + if (dest == NULL) { + for (ptr=*src, n=0; nbytes>0; n++) { + nb = mbtowc(NULL, ptr, nbytes); + if (nb == -1) { + mbtowc(NULL, NULL, 0); + nb = mbtowc(NULL, ptr, strlen(ptr)); + return (nb == -1 ? (size_t)-1 : n); + } else if (nb==0) { + return n; + } + ptr += nb; + nbytes -= nb; + } + } + + for (ptr=*src, n=0; n0; n++, dest++) { + nb = mbtowc(dest, ptr, nbytes); + if (nb == -1) { + mbtowc(NULL, NULL, 0); + nb = mbtowc(NULL, ptr, strlen(ptr)); + *src = ptr; + return (nb == -1 ? (size_t)-1 : n); + } else if (nb == 0) { + *src = NULL; + return n; + } + ptr += nb; + nbytes -= nb; + } + + *src = ptr; + return n; +} + +#endif + + +#define DEFAULT_SIZE 12 + +static char* +fixXLFD(char *xlfd, int size) +{ + char *fname, *ptr; + + fname = wmalloc(strlen(xlfd) + 20); + if (strstr(xlfd, "%d")!=NULL) + sprintf(fname, xlfd, size ? size : DEFAULT_SIZE); + else + strcpy(fname, xlfd); + + if ((ptr = strchr(fname, ','))) { + *ptr = 0; + } + + return fname; +} + + +static Bool +hasProperty(FcPattern *pattern, const char *property) +{ + FcValue val; + + if (FcPatternGet(pattern, property, 0, &val)==FcResultMatch) { + return True; + } + + return False; +} + + +static Bool +hasPropertyWithStringValue(FcPattern *pattern, const char *object, char *value) +{ + FcChar8 *str; + int id; + + if (!value || value[0]==0) + return True; + + id = 0; + while (FcPatternGetString(pattern, object, id, &str)==FcResultMatch) { + if (strcasecmp(value, (char*)str) == 0) { + return True; + } + id++; + } + + return False; +} + + +// also handle an xlfd with %d for size? +static char* +makeFontOfSize(char *font, int size, char *fallback) +{ + FcPattern *pattern; + char *result; + + if (font[0]=='-') { + char *fname; + + fname = fixXLFD(font, size); + pattern = XftXlfdParse(fname, False, False); + wfree(fname); + } else { + pattern = FcNameParse(font); + } + + //FcPatternPrint(pattern); + if (size > 0) { + FcPatternDel(pattern, "pixelsize"); + FcPatternAddDouble(pattern, "pixelsize", (double)size); + } else if (size==0 && !hasProperty(pattern, "size") && + !hasProperty(pattern, "pixelsize")) { + FcPatternAddDouble(pattern, "pixelsize", (double)DEFAULT_SIZE); + } + + if (fallback && !hasPropertyWithStringValue(pattern, "family", fallback)) { + FcPatternAddString(pattern, "family", fallback); + } + + result = FcNameUnparse(pattern); + FcPatternDestroy(pattern); + + return result; +} + + +WMFont* +WMCreateFont(WMScreen *scrPtr, char *fontName) +{ + WMFont *font; + Display *display = scrPtr->display; + char *fname, *ptr; + + /* This is for back-compat (to allow reading of old xlfd descriptions) */ + if (fontName[0]=='-' && (ptr = strchr(fontName, ','))) { + // warn for deprecation + fname = wmalloc(ptr - fontName + 1); + strncpy(fname, fontName, ptr - fontName); + fname[ptr - fontName] = 0; + } else { + fname = wstrdup(fontName); + } + + font = WMHashGet(scrPtr->fontCache, fname); + if (font) { + WMRetainFont(font); + wfree(fname); + return font; + } + + font = wmalloc(sizeof(WMFont)); + memset(font, 0, sizeof(WMFont)); + + font->screen = scrPtr; + + // remove + printf("WMCreateFont: %s\n", fname); + + if (fname[0] == '-') { + // Backward compat thing. Remove in a later version + font->font = XftFontOpenXlfd(display, scrPtr->screen, fname); + } else { + font->font = XftFontOpenName(display, scrPtr->screen, fname); + } + if (!font->font) { + wfree(font); + wfree(fname); + return NULL; + } + font->height = font->font->ascent+font->font->descent; + font->y = font->font->ascent; + + font->refCount = 1; + + font->name = fname; + + assert(WMHashInsert(scrPtr->fontCache, font->name, font)==NULL); + + return font; +} + + +WMFont* +WMRetainFont(WMFont *font) +{ + wassertrv(font!=NULL, NULL); + + font->refCount++; + + return font; +} + + +void +WMReleaseFont(WMFont *font) +{ + wassertr(font!=NULL); + + font->refCount--; + if (font->refCount < 1) { + XftFontClose(font->screen->display, font->font); + if (font->name) { + WMHashRemove(font->screen->fontCache, font->name); + wfree(font->name); + } + wfree(font); + } +} + + +Bool +WMIsAntialiasingEnabled(WMScreen *scrPtr) +{ + return scrPtr->antialiasedText; +} + + +unsigned int +WMFontHeight(WMFont *font) +{ + wassertrv(font!=NULL, 0); + + return font->height; +} + + +char* +WMGetFontName(WMFont *font) +{ + wassertrv(font!=NULL, NULL); + + return font->name; +} + + +WMFont* +WMDefaultSystemFont(WMScreen *scrPtr) +{ + return WMRetainFont(scrPtr->normalFont); +} + + +WMFont* +WMDefaultBoldSystemFont(WMScreen *scrPtr) +{ + return WMRetainFont(scrPtr->boldFont); +} + + +WMFont* +WMSystemFontOfSize(WMScreen *scrPtr, int size) +{ + WMFont *font; + char *fontSpec; + + fontSpec = makeFontOfSize(WINGsConfiguration.systemFont, size, "sans"); + + font = WMCreateFont(scrPtr, fontSpec); + + if (!font) { + wwarning(_("could not load font %s."), fontSpec); + } + + wfree(fontSpec); + + return font; +} + + +WMFont* +WMBoldSystemFontOfSize(WMScreen *scrPtr, int size) +{ + WMFont *font; + char *fontSpec; + + fontSpec = makeFontOfSize(WINGsConfiguration.boldSystemFont, size, "sans"); + + font = WMCreateFont(scrPtr, fontSpec); + + if (!font) { + wwarning(_("could not load font %s."), fontSpec); + } + + wfree(fontSpec); + + return font; +} + + +int +WMWidthOfString(WMFont *font, char *text, int length) +{ + XGlyphInfo extents; + + wassertrv(font!=NULL, 0); + wassertrv(text!=NULL, 0); + + if (font->screen->useWideChar) { + wchar_t *wtext; + const char *mtext; + int len; + + wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); + mtext = text; + len = wmbsnrtowcs(wtext, &mtext, length, length); + if (len>0) { + wtext[len] = L'\0'; /* not really necessary here */ + XftTextExtents32(font->screen->display, font->font, + (XftChar32 *)wtext, len, &extents); + } else { + if (len==-1) { + wwarning(_("Conversion to widechar failed (possible " + "invalid multibyte sequence): '%s':(pos %d)\n"), + text, mtext-text+1); + } + extents.xOff = 0; + } + wfree(wtext); + } else if (font->screen->useMultiByte) { + XftTextExtentsUtf8(font->screen->display, font->font, + (XftChar8 *)text, length, &extents); + } else { + XftTextExtents8(font->screen->display, font->font, + (XftChar8 *)text, length, &extents); + } + + return extents.xOff; /* don't ask :P */ +} + + + +void +WMDrawString(WMScreen *scr, Drawable d, WMColor *color, WMFont *font, + int x, int y, char *text, int length) +{ + XftColor xftcolor; + + wassertr(font!=NULL); + + xftcolor.color.red = color->color.red; + xftcolor.color.green = color->color.green; + xftcolor.color.blue = color->color.blue; + xftcolor.color.alpha = color->alpha;; + xftcolor.pixel = W_PIXEL(color); + + XftDrawChange(scr->xftdraw, d); + + if (font->screen->useWideChar) { + wchar_t *wtext; + const char *mtext; + int len; + + wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); + mtext = text; + len = wmbsnrtowcs(wtext, &mtext, length, length); + if (len>0) { + XftDrawString32(scr->xftdraw, &xftcolor, font->font, + x, y + font->y, (XftChar32*)wtext, len); + } else if (len==-1) { + wwarning(_("Conversion to widechar failed (possible invalid " + "multibyte sequence): '%s':(pos %d)\n"), + text, mtext-text+1); + /* we can draw normal text, or we can draw as much widechar + * text as was already converted until the error. go figure */ + /*XftDrawString8(scr->xftdraw, &xftcolor, font->font, + x, y + font->y, (XftChar8*)text, length);*/ + } + wfree(wtext); + } else if (font->screen->useMultiByte) { + XftDrawStringUtf8(scr->xftdraw, &xftcolor, font->font, + x, y + font->y, (XftChar8*)text, length); + } else { + XftDrawString8(scr->xftdraw, &xftcolor, font->font, + x, y + font->y, (XftChar8*)text, length); + } +} + + +void +WMDrawImageString(WMScreen *scr, Drawable d, WMColor *color, WMColor *background, + WMFont *font, int x, int y, char *text, int length) +{ + XftColor textColor; + XftColor bgColor; + + wassertr(font!=NULL); + + textColor.color.red = color->color.red; + textColor.color.green = color->color.green; + textColor.color.blue = color->color.blue; + textColor.color.alpha = color->alpha;; + textColor.pixel = W_PIXEL(color); + + bgColor.color.red = background->color.red; + bgColor.color.green = background->color.green; + bgColor.color.blue = background->color.blue; + bgColor.color.alpha = background->alpha;; + bgColor.pixel = W_PIXEL(background); + + XftDrawChange(scr->xftdraw, d); + + XftDrawRect(scr->xftdraw, &bgColor, x, y, + WMWidthOfString(font, text, length), + font->height); + + if (font->screen->useWideChar) { + wchar_t *wtext; + const char *mtext; + int len; + + mtext = text; + wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); + len = wmbsnrtowcs(wtext, &mtext, length, length); + if (len>0) { + XftDrawString32(scr->xftdraw, &textColor, font->font, + x, y + font->y, (XftChar32*)wtext, len); + } else if (len==-1) { + wwarning(_("Conversion to widechar failed (possible invalid " + "multibyte sequence): '%s':(pos %d)\n"), + text, mtext-text+1); + /* we can draw normal text, or we can draw as much widechar + * text as was already converted until the error. go figure */ + /*XftDrawString8(scr->xftdraw, &textColor, font->font, + x, y + font->y, (XftChar8*)text, length);*/ + } + wfree(wtext); + } else if (font->screen->useMultiByte) { + XftDrawStringUtf8(scr->xftdraw, &textColor, font->font, + x, y + font->y, (XftChar8*)text, length); + } else { + XftDrawString8(scr->xftdraw, &textColor, font->font, + x, y + font->y, (XftChar8*)text, length); + } +} + + +WMFont* +WMCopyFontWithStyle(WMScreen *scrPtr, WMFont *font, WMFontStyle style) +{ + FcPattern *pattern; + WMFont *copy; + char *name; + + if (!font) + return NULL; + + pattern = FcNameParse(WMGetFontName(font)); + switch (style) { + case WFSNormal: + FcPatternDel(pattern, "weight"); + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "weight", "regular"); + FcPatternAddString(pattern, "weight", "medium"); + FcPatternAddString(pattern, "slant", "roman"); + break; + case WFSBold: + FcPatternDel(pattern, "weight"); + FcPatternAddString(pattern, "weight", "bold"); + break; + case WFSEmphasized: + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "slant", "italic"); + FcPatternAddString(pattern, "slant", "oblique"); + break; + case WFSBoldEmphasized: + FcPatternDel(pattern, "weight"); + FcPatternDel(pattern, "slant"); + FcPatternAddString(pattern, "weight", "bold"); + FcPatternAddString(pattern, "slant", "italic"); + FcPatternAddString(pattern, "slant", "oblique"); + break; + } + + name = FcNameUnparse(pattern); + copy = WMCreateFont(scrPtr, name); + FcPatternDestroy(pattern); + wfree(name); + + return copy; +} + + +#endif /* XFT */ + + diff --git a/WINGs/wfontpanel.c b/WINGs/wfontpanel.c index 5ee6bde8..48fe933f 100644 --- a/WINGs/wfontpanel.c +++ b/WINGs/wfontpanel.c @@ -9,6 +9,10 @@ #include #include +#ifdef XFT +#include +#include +#endif /* XXX TODO */ @@ -22,7 +26,7 @@ typedef struct W_FontPanel { WMFrame *upperF; WMTextField *sampleT; - + WMSplitView *split; WMFrame *lowerF; @@ -39,7 +43,7 @@ typedef struct W_FontPanel { WMButton *revertB; WMButton *setB; - + WMPropList *fdb; } FontPanel; @@ -65,24 +69,27 @@ typedef struct W_FontPanel { static int scalableFontSizes[] = { - 8, - 10, - 11, - 12, - 14, - 16, - 18, - 20, - 24, - 36, - 48, - 64 + 8, + 10, + 11, + 12, + 14, + 16, + 18, + 20, + 24, + 36, + 48, + 64 }; - -static void getSelectedFont(FontPanel *panel, char buffer[], int bufsize); +#ifdef XFT +static void setFontPanelFontName(FontPanel *panel, FcChar8 *family, FcChar8 *style, double size); +#endif + +static int isXLFD(char *font, int *length_ret); static void arrangeLowerFrame(FontPanel *panel); @@ -97,10 +104,10 @@ static void listFamilies(WMScreen *scr, WMFontPanel *panel); static void splitViewConstrainCallback(WMSplitView *sPtr, int indView, int *min, int *max) { - if (indView == 0) - *min = MIN_UPPER_HEIGHT; + if (indView == 0) + *min = MIN_UPPER_HEIGHT; else - *min = MIN_LOWER_HEIGHT; + *min = MIN_LOWER_HEIGHT; } static void @@ -110,42 +117,42 @@ notificationObserver(void *self, WMNotification *notif) void *object = WMGetNotificationObject(notif); if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) { - if (object == WMWidgetView(panel->win)) { - int h = WMWidgetHeight(panel->win); - int w = WMWidgetWidth(panel->win); + if (object == WMWidgetView(panel->win)) { + int h = WMWidgetHeight(panel->win); + int w = WMWidgetWidth(panel->win); - WMResizeWidget(panel->split, w, h-BUTTON_SPACE_HEIGHT); + WMResizeWidget(panel->split, w, h-BUTTON_SPACE_HEIGHT); - WMMoveWidget(panel->setB, w-80, h-(BUTTON_SPACE_HEIGHT-5)); + WMMoveWidget(panel->setB, w-80, h-(BUTTON_SPACE_HEIGHT-5)); - WMMoveWidget(panel->revertB, w-240, h-(BUTTON_SPACE_HEIGHT-5)); + WMMoveWidget(panel->revertB, w-240, h-(BUTTON_SPACE_HEIGHT-5)); - } else if (object == WMWidgetView(panel->upperF)) { + } else if (object == WMWidgetView(panel->upperF)) { - if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) { - WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), - MIN_UPPER_HEIGHT); - } else { - WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF)-20, - WMWidgetHeight(panel->upperF)-10); - } + if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) { + WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), + MIN_UPPER_HEIGHT); + } else { + WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF)-20, + WMWidgetHeight(panel->upperF)-10); + } - } else if (object == WMWidgetView(panel->lowerF)) { - - if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) { - WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), - MIN_UPPER_HEIGHT); + } else if (object == WMWidgetView(panel->lowerF)) { - WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF) - + WMGetSplitViewDividerThickness(panel->split)); + if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) { + WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), + MIN_UPPER_HEIGHT); - WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF), - WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT - - WMGetSplitViewDividerThickness(panel->split)); - } else { - arrangeLowerFrame(panel); - } - } + WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF) + + WMGetSplitViewDividerThickness(panel->split)); + + WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF), + WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT + - WMGetSplitViewDividerThickness(panel->split)); + } else { + arrangeLowerFrame(panel); + } + } } } @@ -154,7 +161,7 @@ static void closeWindow(WMWidget *w, void *data) { FontPanel *panel = (FontPanel*)data; - + WMHideFontPanel(panel); } @@ -165,16 +172,16 @@ static void setClickedAction(WMWidget *w, void *data) { FontPanel *panel = (FontPanel*)data; - + if (panel->action) - (*panel->action)(panel, panel->data); + (*panel->action)(panel, panel->data); } static void revertClickedAction(WMWidget *w, void *data) { - FontPanel *panel = (FontPanel*)data; + /*FontPanel *panel = (FontPanel*)data;*/ /* XXX TODO */ } @@ -189,18 +196,19 @@ WMGetFontPanel(WMScreen *scr) int divThickness; if (scr->sharedFontPanel) - return scr->sharedFontPanel; + return scr->sharedFontPanel; panel = wmalloc(sizeof(FontPanel)); memset(panel, 0, sizeof(FontPanel)); - + panel->win = WMCreateWindow(scr, "fontPanel"); -/* WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr));*/ + /* WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr));*/ + WMSetWindowTitle(panel->win, _("Font Panel")); WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT); WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT); WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True); - + WMSetWindowCloseAction(panel->win, closeWindow, panel); panel->split = WMCreateSplitView(panel->win); @@ -213,7 +221,7 @@ WMGetFontPanel(WMScreen *scr) WMSetFrameRelief(panel->upperF, WRFlat); WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True); panel->lowerF = WMCreateFrame(panel->win); -/* WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr));*/ + /* WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr));*/ WMSetFrameRelief(panel->lowerF, WRFlat); WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True); @@ -221,7 +229,7 @@ WMGetFontPanel(WMScreen *scr) WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF)); WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT); - + WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT); WMMoveWidget(panel->lowerF, 0, 60+divThickness); @@ -232,7 +240,7 @@ WMGetFontPanel(WMScreen *scr) panel->sampleT = WMCreateTextField(panel->upperF); WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50); WMMoveWidget(panel->sampleT, 10, 10); - WMSetTextFieldText(panel->sampleT, _("Test!!!")); + WMSetTextFieldText(panel->sampleT, _("The quick brown fox jumps over the lazy dog")); font = WMBoldSystemFontOfSize(scr, 12); @@ -243,7 +251,7 @@ WMGetFontPanel(WMScreen *scr) WMSetLabelTextColor(panel->famL, white); WMSetLabelRelief(panel->famL, WRSunken); WMSetLabelTextAlignment(panel->famL, WACenter); - + panel->famLs = WMCreateList(panel->lowerF); WMSetListAction(panel->famLs, familyClick, panel); @@ -253,7 +261,7 @@ WMGetFontPanel(WMScreen *scr) WMSetLabelFont(panel->typL, font); WMSetLabelTextColor(panel->typL, white); WMSetLabelRelief(panel->typL, WRSunken); - WMSetLabelTextAlignment(panel->typL, WACenter); + WMSetLabelTextAlignment(panel->typL, WACenter); panel->typLs = WMCreateList(panel->lowerF); WMSetListAction(panel->typLs, typefaceClick, panel); @@ -267,7 +275,7 @@ WMGetFontPanel(WMScreen *scr) WMSetLabelTextAlignment(panel->sizL, WACenter); panel->sizT = WMCreateTextField(panel->lowerF); -/* WMSetTextFieldAlignment(panel->sizT, WARight);*/ + /* WMSetTextFieldAlignment(panel->sizT, WARight);*/ panel->sizLs = WMCreateList(panel->lowerF); WMSetListAction(panel->sizLs, sizeClick, panel); @@ -275,7 +283,7 @@ WMGetFontPanel(WMScreen *scr) WMReleaseFont(font); WMReleaseColor(white); WMReleaseColor(dark); - + panel->setB = WMCreateCommandButton(panel->win); WMResizeWidget(panel->setB, 70, 24); WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5)); @@ -304,20 +312,20 @@ WMGetFontPanel(WMScreen *scr) /* register notification observers */ - WMAddNotificationObserver(notificationObserver, panel, - WMViewSizeDidChangeNotification, - WMWidgetView(panel->win)); - WMAddNotificationObserver(notificationObserver, panel, - WMViewSizeDidChangeNotification, - WMWidgetView(panel->upperF)); - WMAddNotificationObserver(notificationObserver, panel, - WMViewSizeDidChangeNotification, - WMWidgetView(panel->lowerF)); + WMAddNotificationObserver(notificationObserver, panel, + WMViewSizeDidChangeNotification, + WMWidgetView(panel->win)); + WMAddNotificationObserver(notificationObserver, panel, + WMViewSizeDidChangeNotification, + WMWidgetView(panel->upperF)); + WMAddNotificationObserver(notificationObserver, panel, + WMViewSizeDidChangeNotification, + WMWidgetView(panel->lowerF)); listFamilies(scr, panel); - - + + return panel; } @@ -326,7 +334,7 @@ void WMFreeFontPanel(WMFontPanel *panel) { if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) { - WMWidgetScreen(panel->win)->sharedFontPanel = NULL; + WMWidgetScreen(panel->win)->sharedFontPanel = NULL; } WMRemoveNotificationObserver(panel); WMUnmapWidget(panel->win); @@ -349,21 +357,6 @@ WMHideFontPanel(WMFontPanel *panel) } -void -WMSetFontPanelFont(WMFontPanel *panel, WMFont *font) -{ - -} - - -Bool -WMSetFontPanelFontName(WMFontPanel *panel, char *fontName) -{ - - return True; -} - - WMFont* WMGetFontPanelFont(WMFontPanel *panel) { @@ -371,19 +364,38 @@ WMGetFontPanelFont(WMFontPanel *panel) } -char* -WMGetFontPanelFontName(WMFontPanel *panel) +void +WMSetFontPanelFont(WMFontPanel *panel, char *fontName) { - char name[512]; +#ifdef XFT + int fname_len; + FcPattern *pattern; + FcChar8 *family, *style; + double size; - getSelectedFont(panel, name, sizeof(name)); + if (!isXLFD(fontName, &fname_len)) { + /* maybe its proper fontconfig and we can parse it */ + pattern = FcNameParse(fontName); + } else { + /* maybe its proper xlfd and we can convert it to an FcPattern */ + pattern = XftXlfdParse(fontName, False, False); + //FcPatternPrint(pattern); + } - return wstrdup(name); + if (!pattern) + return; + + if (FcPatternGetString(pattern, FC_FAMILY, 0, &family)==FcResultMatch) + if (FcPatternGetString(pattern, FC_STYLE, 0, &style)==FcResultMatch) + if (FcPatternGetDouble(pattern, "pixelsize", 0, &size)==FcResultMatch) + setFontPanelFontName(panel, family, style, size); + + FcPatternDestroy(pattern); +#endif } - -void +void WMSetFontPanelAction(WMFontPanel *panel, WMAction2 *action, void *data) { panel->action = action; @@ -404,7 +416,7 @@ arrangeLowerFrame(FontPanel *panel) #define LABEL_HEIGHT 20 height -= WMGetSplitViewDividerThickness(panel->split); - + height -= LABEL_HEIGHT + 8; @@ -458,6 +470,22 @@ arrangeLowerFrame(FontPanel *panel) +static int +isXLFD(char *font, int *length_ret) +{ + int c = 0; + + *length_ret = 0; + while (*font) { + (*length_ret)++; + if (*font++ == '-') + c++; + } + + return c==NUM_FIELDS; +} + +#ifndef XFT static Bool parseFont(char *font, char values[NUM_FIELDS][256]) { @@ -470,40 +498,24 @@ parseFont(char *font, char values[NUM_FIELDS][256]) ptr++; /* skip first - */ bptr = buffer; while (*ptr) { - if (*ptr == '-') { - *bptr = 0; - strcpy(values[part], buffer); - bptr = buffer; - part++; - } else { - *bptr++ = *ptr; - } - ptr++; + if (*ptr == '-') { + *bptr = 0; + strcpy(values[part], buffer); + bptr = buffer; + part++; + } else { + *bptr++ = *ptr; + } + ptr++; } *bptr = 0; strcpy(values[part], buffer); - + return True; } -static int -isXLFD(char *font, int *length_ret) -{ - int c = 0; - - *length_ret = 0; - while (*font) { - (*length_ret)++; - if (*font++ == '-') - c++; - } - - return c==NUM_FIELDS; -} - - typedef struct { @@ -512,10 +524,10 @@ typedef struct { char *setWidth; char *addStyle; - + char showSetWidth; /* when duplicated */ char showAddStyle; /* when duplicated */ - + WMArray *sizes; } Typeface; @@ -531,6 +543,18 @@ typedef struct { WMArray *typefaces; } Family; +#endif +#ifdef XFT +typedef struct { + char *typeface; + WMArray *sizes; +} Xft_Typeface; + +typedef struct { + char *name; /* gotta love simplicity */ + WMArray *typefaces; +} Xft_Family; +#endif @@ -542,38 +566,69 @@ compare_int(const void *a, const void *b) int i2 = *(int*)b; if (i1 < i2) - return -1; + return -1; else if (i1 > i2) - return 1; + return 1; else - return 0; + return 0; } - static void +#ifdef XFT +addSizeToTypeface(Xft_Typeface *face, int size) +#else addSizeToTypeface(Typeface *face, int size) +#endif { if (size == 0) { - int j; - - for (j = 0; j < sizeof(scalableFontSizes)/sizeof(int); j++) { - size = scalableFontSizes[j]; + int j; - if (!WMCountInArray(face->sizes, (void*)size)) { - WMAddToArray(face->sizes, (void*)size); - } - } - WMSortArray(face->sizes, compare_int); + for (j = 0; j < sizeof(scalableFontSizes)/sizeof(int); j++) { + size = scalableFontSizes[j]; + + if (!WMCountInArray(face->sizes, (void*)size)) { + WMAddToArray(face->sizes, (void*)size); + } + } + WMSortArray(face->sizes, compare_int); } else { - if (!WMCountInArray(face->sizes, (void*)size)) { - WMAddToArray(face->sizes, (void*)size); - WMSortArray(face->sizes, compare_int); - } + if (!WMCountInArray(face->sizes, (void*)size)) { + WMAddToArray(face->sizes, (void*)size); + WMSortArray(face->sizes, compare_int); + } } } +#ifdef XFT +static void +addTypefaceToXftFamily(Xft_Family *fam, char *style) +{ + Xft_Typeface *face; + WMArrayIterator i; + if(fam->typefaces) { + WM_ITERATE_ARRAY(fam->typefaces, face, i) { + if(strcmp(face->typeface, style) != 0) + continue; /* go to next interation */ + addSizeToTypeface(face, 0); + return; + } + } else { + fam->typefaces = WMCreateArray(4); + } + + face = wmalloc(sizeof(Xft_Typeface)); + memset(face, 0 , sizeof(Xft_Typeface)); + + face->typeface = wstrdup(style); + face->sizes = WMCreateArray(4); + addSizeToTypeface(face, 0); + + WMAddToArray(fam->typefaces, face); +} + +#else /* XFT */ static void addTypefaceToFamily(Family *family, char fontFields[NUM_FIELDS][256]) @@ -583,23 +638,23 @@ addTypefaceToFamily(Family *family, char fontFields[NUM_FIELDS][256]) if (family->typefaces) { WM_ITERATE_ARRAY(family->typefaces, face, i) { - int size; + int size; - if (strcmp(face->weight, fontFields[WEIGHT]) != 0) { - continue; - } - if (strcmp(face->slant, fontFields[SLANT]) != 0) { - continue; - } + if (strcmp(face->weight, fontFields[WEIGHT]) != 0) { + continue; + } + if (strcmp(face->slant, fontFields[SLANT]) != 0) { + continue; + } - size = atoi(fontFields[PIXEL_SIZE]); + size = atoi(fontFields[PIXEL_SIZE]); - addSizeToTypeface(face, size); + addSizeToTypeface(face, size); - return; - } + return; + } } else { - family->typefaces = WMCreateArray(4); + family->typefaces = WMCreateArray(4); } face = wmalloc(sizeof(Typeface)); @@ -615,14 +670,47 @@ addTypefaceToFamily(Family *family, char fontFields[NUM_FIELDS][256]) WMAddToArray(family->typefaces, face); } - +#endif /* * families (same family name) (Hashtable of family -> array) * registries (same family but different registries) - * + * */ +#ifdef XFT +static void +addFontToXftFamily(WMHashTable *families, char *name, char *style) +{ + WMArrayIterator i; + WMArray *array; + Xft_Family *fam; + + array = WMHashGet(families, name); + if(array) { + WM_ITERATE_ARRAY(array, fam, i) { + if(strcmp(fam->name, name) == 0 ) + addTypefaceToXftFamily(fam, style); + return; + } + } + + array = WMCreateArray(8); + + fam = wmalloc(sizeof(Xft_Family)); + memset(fam, 0, sizeof(Xft_Family)); + + fam->name = wstrdup(name); + + addTypefaceToXftFamily(fam, style); + + WMAddToArray(array, fam); + + WMHashInsert(families, fam->name, array); +} + +#else /* XFT */ + static void addFontToFamily(WMHashTable *families, char fontFields[NUM_FIELDS][256]) { @@ -632,87 +720,87 @@ addFontToFamily(WMHashTable *families, char fontFields[NUM_FIELDS][256]) family = WMHashGet(families, fontFields[FAMILY]); - + if (family) { - /* look for same encoding/registry and foundry */ + /* look for same encoding/registry and foundry */ WM_ITERATE_ARRAY(family, fam, i) { - int enc, reg, found; + int enc, reg, found; - enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0); - reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0); - found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0); + enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0); + reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0); + found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0); - if (enc && reg && found) { - addTypefaceToFamily(fam, fontFields); - return; - } - } - /* look for same encoding/registry */ + if (enc && reg && found) { + addTypefaceToFamily(fam, fontFields); + return; + } + } + /* look for same encoding/registry */ WM_ITERATE_ARRAY(family, fam, i) { - int enc, reg; - - enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0); - reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0); + int enc, reg; - if (enc && reg) { - /* has the same encoding, but the foundry is different */ - fam->showFoundry = 1; + enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0); + reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0); - fam = wmalloc(sizeof(Family)); - memset(fam, 0, sizeof(Family)); + if (enc && reg) { + /* has the same encoding, but the foundry is different */ + fam->showFoundry = 1; - fam->name = wstrdup(fontFields[FAMILY]); - fam->foundry = wstrdup(fontFields[FOUNDRY]); - fam->registry = wstrdup(fontFields[REGISTRY]); - fam->encoding = wstrdup(fontFields[ENCODING]); - fam->showFoundry = 1; + fam = wmalloc(sizeof(Family)); + memset(fam, 0, sizeof(Family)); - addTypefaceToFamily(fam, fontFields); + fam->name = wstrdup(fontFields[FAMILY]); + fam->foundry = wstrdup(fontFields[FOUNDRY]); + fam->registry = wstrdup(fontFields[REGISTRY]); + fam->encoding = wstrdup(fontFields[ENCODING]); + fam->showFoundry = 1; - WMAddToArray(family, fam); - return; - } - } - /* look for same foundry */ + addTypefaceToFamily(fam, fontFields); + + WMAddToArray(family, fam); + return; + } + } + /* look for same foundry */ WM_ITERATE_ARRAY(family, fam, i) { - int found; - - found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0); + int found; - if (found) { - /* has the same foundry, but encoding is different */ - fam->showRegistry = 1; + found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0); - fam = wmalloc(sizeof(Family)); - memset(fam, 0, sizeof(Family)); + if (found) { + /* has the same foundry, but encoding is different */ + fam->showRegistry = 1; - fam->name = wstrdup(fontFields[FAMILY]); - fam->foundry = wstrdup(fontFields[FOUNDRY]); - fam->registry = wstrdup(fontFields[REGISTRY]); - fam->encoding = wstrdup(fontFields[ENCODING]); - fam->showRegistry = 1; + fam = wmalloc(sizeof(Family)); + memset(fam, 0, sizeof(Family)); - addTypefaceToFamily(fam, fontFields); + fam->name = wstrdup(fontFields[FAMILY]); + fam->foundry = wstrdup(fontFields[FOUNDRY]); + fam->registry = wstrdup(fontFields[REGISTRY]); + fam->encoding = wstrdup(fontFields[ENCODING]); + fam->showRegistry = 1; - WMAddToArray(family, fam); - return; - } - } - /* foundry and encoding do not match anything known */ - fam = wmalloc(sizeof(Family)); - memset(fam, 0, sizeof(Family)); + addTypefaceToFamily(fam, fontFields); - fam->name = wstrdup(fontFields[FAMILY]); - fam->foundry = wstrdup(fontFields[FOUNDRY]); - fam->registry = wstrdup(fontFields[REGISTRY]); - fam->encoding = wstrdup(fontFields[ENCODING]); - fam->showFoundry = 1; - fam->showRegistry = 1; + WMAddToArray(family, fam); + return; + } + } + /* foundry and encoding do not match anything known */ + fam = wmalloc(sizeof(Family)); + memset(fam, 0, sizeof(Family)); - addTypefaceToFamily(fam, fontFields); + fam->name = wstrdup(fontFields[FAMILY]); + fam->foundry = wstrdup(fontFields[FOUNDRY]); + fam->registry = wstrdup(fontFields[REGISTRY]); + fam->encoding = wstrdup(fontFields[ENCODING]); + fam->showFoundry = 1; + fam->showRegistry = 1; - WMAddToArray(family, fam); - return; + addTypefaceToFamily(fam, fontFields); + + WMAddToArray(family, fam); + return; } family = WMCreateArray(8); @@ -724,87 +812,140 @@ addFontToFamily(WMHashTable *families, char fontFields[NUM_FIELDS][256]) fam->foundry = wstrdup(fontFields[FOUNDRY]); fam->registry = wstrdup(fontFields[REGISTRY]); fam->encoding = wstrdup(fontFields[ENCODING]); - + addTypefaceToFamily(fam, fontFields); - + WMAddToArray(family, fam); WMHashInsert(families, fam->name, family); } +#endif /* XFT */ static void listFamilies(WMScreen *scr, WMFontPanel *panel) { +#ifdef XFT + FcObjectSet *os = 0; + FcFontSet *fs; + FcPattern *pat; +#else /* XFT */ char **fontList; - WMHashTable *families; char fields[NUM_FIELDS][256]; + int count; +#endif /* XFT */ + WMHashTable *families; WMHashEnumerator enumer; WMArray *array; - int i, count; + int i; - fontList = XListFonts(scr->display, ALL_FONTS_MASK, MAX_FONTS_TO_RETRIEVE, +#ifdef XFT + pat = FcPatternCreate(); + os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, 0); + fs = FcFontList(0, pat, os); + if (!fs) { + WMRunAlertPanel(scr, panel->win, _("Error"), + _("Could not init font config library\n"), _("OK"), NULL, NULL); + return; + } + if (pat) + FcPatternDestroy (pat); +#else /* XFT */ + fontList = XListFonts(scr->display, ALL_FONTS_MASK, MAX_FONTS_TO_RETRIEVE, &count); if (!fontList) { - WMRunAlertPanel(scr, panel->win, _("Error"), - _("Could not retrieve font list"), _("OK"), NULL, NULL); - return; + WMRunAlertPanel(scr, panel->win, _("Error"), + _("Could not retrieve font list"), _("OK"), NULL, NULL); + return; } +#endif /* XFT */ families = WMCreateHashTable(WMStringPointerHashCallbacks); - for (i = 0; i < count; i++) { - int fname_len; +#ifdef XFT + if(fs) { + for (i = 0; i < fs->nfont; i++) { + FcChar8 *family; + FcChar8 *style; - if (!isXLFD(fontList[i], &fname_len)) { - *fontList[i] = '\0'; - continue; - } - if (fname_len > 255) { - wwarning(_("font name %s is longer than 256, which is invalid."), - fontList[i]); - *fontList[i] = '\0'; - continue; - } - if (!parseFont(fontList[i], fields)) { - *fontList[i] = '\0'; - continue; - } - addFontToFamily(families, fields); + if (FcPatternGetString(fs->fonts[i],FC_FAMILY,0,&family)==FcResultMatch) + if (FcPatternGetString(fs->fonts[i],FC_STYLE,0,&style)==FcResultMatch) + addFontToXftFamily(families, family, style); + } + FcFontSetDestroy(fs); } +#else /* XFT */ + for (i = 0; i < count; i++) { + int fname_len; + + if (!isXLFD(fontList[i], &fname_len)) { + *fontList[i] = '\0'; + continue; + } + if (fname_len > 255) { + wwarning(_("font name %s is longer than 256, which is invalid."), + fontList[i]); + *fontList[i] = '\0'; + continue; + } + if (!parseFont(fontList[i], fields)) { + *fontList[i] = '\0'; + continue; + } + addFontToFamily(families, fields); + } +#endif /* XFT */ enumer = WMEnumerateHashTable(families); - + +#ifdef XFT while ((array = WMNextHashEnumeratorItem(&enumer))) { - WMArrayIterator i; - Family *fam; - char buffer[256]; - WMListItem *item; + WMArrayIterator i; + Xft_Family *fam; + char buffer[256]; + WMListItem *item; WM_ITERATE_ARRAY(array, fam, i) { - strcpy(buffer, fam->name); + strcpy(buffer, fam->name); + item = WMAddListItem(panel->famLs, buffer); + + item->clientData = fam; + } - if (fam->showFoundry) { - strcat(buffer, " "); - strcat(buffer, fam->foundry); - strcat(buffer, " "); - } - if (fam->showRegistry) { - strcat(buffer, " ("); - strcat(buffer, fam->registry); - strcat(buffer, "-"); - strcat(buffer, fam->encoding); - strcat(buffer, ")"); - } - item = WMAddListItem(panel->famLs, buffer); - - item->clientData = fam; - } WMFreeArray(array); } +#else /* XFT */ + while ((array = WMNextHashEnumeratorItem(&enumer))) { + WMArrayIterator i; + Family *fam; + char buffer[256]; + WMListItem *item; + + WM_ITERATE_ARRAY(array, fam, i) { + strcpy(buffer, fam->name); + + if (fam->showFoundry) { + strcat(buffer, " "); + strcat(buffer, fam->foundry); + strcat(buffer, " "); + } + if (fam->showRegistry) { + strcat(buffer, " ("); + strcat(buffer, fam->registry); + strcat(buffer, "-"); + strcat(buffer, fam->encoding); + strcat(buffer, ")"); + } + item = WMAddListItem(panel->famLs, buffer); + + item->clientData = fam; + } + WMFreeArray(array); + } +#endif /* XFT */ WMSortListItems(panel->famLs); - + WMFreeHashTable(families); } @@ -813,23 +954,42 @@ static void getSelectedFont(FontPanel *panel, char buffer[], int bufsize) { WMListItem *item; +#ifdef XFT + Xft_Family *family; + Xft_Typeface *face; +#else Family *family; Typeface *face; +#endif char *size; - + item = WMGetListSelectedItem(panel->famLs); if (!item) - return; + return; +#ifdef XFT + family = (Xft_Family*)item->clientData; +#else family = (Family*)item->clientData; +#endif item = WMGetListSelectedItem(panel->typLs); if (!item) - return; + return; +#ifdef XFT + face = (Xft_Typeface*)item->clientData; +#else face = (Typeface*)item->clientData; +#endif size = WMGetTextFieldText(panel->sizT); +#ifdef XFT + snprintf(buffer, bufsize, "%s:style=%s:pixelsize=%s", + family->name, + face->typeface, + size); +#else snprintf(buffer, bufsize, "-%s-%s-%s-%s-%s-%s-%s-*-*-*-*-*-%s-%s", family->foundry, family->name, @@ -840,7 +1000,7 @@ getSelectedFont(FontPanel *panel, char buffer[], int bufsize) size, family->registry, family->encoding); - +#endif /* XFT */ wfree(size); } @@ -851,26 +1011,30 @@ preview(FontPanel *panel) { char buffer[512]; WMFont *font; - + getSelectedFont(panel, buffer, sizeof(buffer)); - font = WMCreateFont(WMWidgetScreen(panel->win), buffer); if (font) { - WMSetTextFieldFont(panel->sampleT, font); - WMReleaseFont(font); + WMSetTextFieldFont(panel->sampleT, font); + WMReleaseFont(font); } } -static void +static void familyClick(WMWidget *w, void *data) { WMList *lPtr = (WMList*)w; WMListItem *item; +#ifdef XFT + Xft_Family *family; + Xft_Typeface *face; +#else Family *family; - FontPanel *panel = (FontPanel*)data; Typeface *face; +#endif + FontPanel *panel = (FontPanel*)data; WMArrayIterator i; /* current typeface and size */ char *oface = NULL; @@ -881,92 +1045,107 @@ familyClick(WMWidget *w, void *data) /* must try to keep the same typeface and size for the new family */ item = WMGetListSelectedItem(panel->typLs); if (item) - oface = wstrdup(item->text); + oface = wstrdup(item->text); osize = WMGetTextFieldText(panel->sizT); item = WMGetListSelectedItem(lPtr); +#ifdef XFT + family = (Xft_Family*)item->clientData; +#else family = (Family*)item->clientData; +#endif WMClearList(panel->typLs); WM_ITERATE_ARRAY(family->typefaces, face, i) { - char buffer[256]; - int top=0; - WMListItem *fitem; - - if (strcmp(face->weight, "medium") == 0) { - buffer[0] = 0; - } else { - if (*face->weight) { - strcpy(buffer, face->weight); - buffer[0] = toupper(buffer[0]); - strcat(buffer, " "); - } else { - buffer[0] = 0; - } - } + char buffer[256]; + int top=0; + WMListItem *fitem; - if (strcmp(face->slant, "r") == 0) { - strcat(buffer, _("Roman")); - top = 1; - } else if (strcmp(face->slant, "i") == 0) { - strcat(buffer, _("Italic")); - } else if (strcmp(face->slant, "o") == 0) { - strcat(buffer, _("Oblique")); - } else if (strcmp(face->slant, "ri") == 0) { - strcat(buffer, _("Rev Italic")); - } else if (strcmp(face->slant, "ro") == 0) { - strcat(buffer, _("Rev Oblique")); - } else { - strcat(buffer, face->slant); - } +#ifdef XFT + strcpy(buffer, face->typeface); + if(strcasecmp(face->typeface, "Roman") == 0) + top = 1; + if(strcasecmp(face->typeface, "Regular") == 0) + top = 1; +#else + if (strcmp(face->weight, "medium") == 0) { + buffer[0] = 0; + } else { + if (*face->weight) { + strcpy(buffer, face->weight); + buffer[0] = toupper(buffer[0]); + strcat(buffer, " "); + } else { + buffer[0] = 0; + } + } - if (buffer[0] == 0) { - strcpy(buffer, _("Normal")); - } + if (strcmp(face->slant, "r") == 0) { + strcat(buffer, _("Roman")); + top = 1; + } else if (strcmp(face->slant, "i") == 0) { + strcat(buffer, _("Italic")); + } else if (strcmp(face->slant, "o") == 0) { + strcat(buffer, _("Oblique")); + } else if (strcmp(face->slant, "ri") == 0) { + strcat(buffer, _("Rev Italic")); + } else if (strcmp(face->slant, "ro") == 0) { + strcat(buffer, _("Rev Oblique")); + } else { + strcat(buffer, face->slant); + } - if (top) - fitem = WMInsertListItem(panel->typLs, 0, buffer); - else - fitem = WMAddListItem(panel->typLs, buffer); - fitem->clientData = face; + if (buffer[0] == 0) { + strcpy(buffer, _("Normal")); + } +#endif + if (top) + fitem = WMInsertListItem(panel->typLs, 0, buffer); + else + fitem = WMAddListItem(panel->typLs, buffer); + fitem->clientData = face; } if (oface) { - facei = WMFindRowOfListItemWithTitle(panel->typLs, oface); - wfree(oface); + facei = WMFindRowOfListItemWithTitle(panel->typLs, oface); + wfree(oface); } if (facei < 0) { - facei = 0; + facei = 0; } WMSelectListItem(panel->typLs, facei); typefaceClick(panel->typLs, panel); - + if (osize) { - sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); + sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); } if (sizei >= 0) { - WMSelectListItem(panel->sizLs, sizei); - sizeClick(panel->sizLs, panel); + WMSelectListItem(panel->sizLs, sizei); + sizeClick(panel->sizLs, panel); } if (osize) - wfree(osize); + wfree(osize); preview(panel); } -static void +static void typefaceClick(WMWidget *w, void *data) { FontPanel *panel = (FontPanel*)data; WMListItem *item; +#ifdef XFT + Xft_Typeface *face; +#else Typeface *face; +#endif WMArrayIterator i; char buffer[32]; @@ -978,50 +1157,138 @@ typefaceClick(WMWidget *w, void *data) item = WMGetListSelectedItem(panel->typLs); +#ifdef XFT + face = (Xft_Typeface*)item->clientData; +#else face = (Typeface*)item->clientData; - +#endif + WMClearList(panel->sizLs); WM_ITERATE_ARRAY(face->sizes, size, i) { - if ((int)size != 0) { - sprintf(buffer, "%i", (int)size); + if ((int)size != 0) { + sprintf(buffer, "%i", (int)size); - WMAddListItem(panel->sizLs, buffer); - } + WMAddListItem(panel->sizLs, buffer); + } } if (osize) { - sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); + sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); } if (sizei < 0) { - sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12"); + sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12"); } if (sizei < 0) { - sizei = 0; + sizei = 0; } WMSelectListItem(panel->sizLs, sizei); WMSetListPosition(panel->sizLs, sizei); sizeClick(panel->sizLs, panel); if (osize) - wfree(osize); + wfree(osize); preview(panel); } - -static void +static void sizeClick(WMWidget *w, void *data) { FontPanel *panel = (FontPanel*)data; WMListItem *item; - - item = WMGetListSelectedItem(panel->sizLs); + item = WMGetListSelectedItem(panel->sizLs); WMSetTextFieldText(panel->sizT, item->text); - + WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text))); preview(panel); } + +#ifdef XFT +static void +setFontPanelFontName(FontPanel *panel, FcChar8 *family, FcChar8 *style, double size) +{ + int famrow; + int stlrow; + int sz; + char asize[64]; + void *vsize; + WMListItem *item; + Xft_Family *fam; + Xft_Typeface *face; + WMArrayIterator i; + + famrow = WMFindRowOfListItemWithTitle(panel->famLs, family); + if (famrow < 0 ){ + famrow = 0; + return; + } + WMSelectListItem(panel->famLs, famrow); + WMSetListPosition(panel->famLs, famrow); + + WMClearList(panel->typLs); + + item = WMGetListSelectedItem(panel->famLs); + + fam = (Xft_Family*)item->clientData; + WM_ITERATE_ARRAY(fam->typefaces, face, i) { + char buffer[256]; + int top=0; + WMListItem *fitem; + + strcpy(buffer, face->typeface); + if(strcasecmp(face->typeface, "Roman") == 0) + top = 1; + if (top) + fitem = WMInsertListItem(panel->typLs, 0, buffer); + else + fitem = WMAddListItem(panel->typLs, buffer); + fitem->clientData = face; + } + + + stlrow = WMFindRowOfListItemWithTitle(panel->typLs, style); + + if (stlrow < 0) { + stlrow = 0; + return; + } + + WMSelectListItem(panel->typLs, stlrow); + + item = WMGetListSelectedItem(panel->typLs); + + face = (Xft_Typeface*)item->clientData; + + WMClearList(panel->sizLs); + + + WM_ITERATE_ARRAY(face->sizes, vsize, i) { + char buffer[32]; + if ((int)vsize != 0) { + sprintf(buffer, "%i", (int)vsize); + + WMAddListItem(panel->sizLs, buffer); + } + } + + snprintf(asize, sizeof(asize)-1, "%d",(int)(size+0.5)); + + sz = WMFindRowOfListItemWithTitle(panel->sizLs, asize); + + if (sz < 0) { + sz = 4; + return; + } + + WMSelectListItem(panel->sizLs, sz); + sizeClick(panel->sizLs, panel); + + return; +} + +#endif + diff --git a/WINGs/wframe.c b/WINGs/wframe.c index 60d5959b..5d286c96 100644 --- a/WINGs/wframe.c +++ b/WINGs/wframe.c @@ -149,6 +149,7 @@ paintFrame(Frame *fPtr) drawTitle = True; } else { + tw = tx = 0; drawTitle = False; } @@ -160,6 +161,11 @@ paintFrame(Frame *fPtr) region = XCreateRegion(); + rect.x = 0; + rect.y = 0; + rect.width = view->size.width; + rect.height = view->size.height; + XUnionRectWithRegion(&rect, region, region); if (drawTitle) { tmp = XCreateRegion(); rect.x = tx; @@ -167,13 +173,6 @@ paintFrame(Frame *fPtr) rect.width = tw; rect.height = th; XUnionRectWithRegion(&rect, tmp, tmp); - } - rect.x = 0; - rect.y = 0; - rect.width = view->size.width; - rect.height = view->size.height; - XUnionRectWithRegion(&rect, region, region); - if (drawTitle) { XSubtractRegion(region, tmp, region); XDestroyRegion(tmp); } diff --git a/WINGs/widgets.c b/WINGs/widgets.c index f06bdafd..1bc5b6e3 100644 --- a/WINGs/widgets.c +++ b/WINGs/widgets.c @@ -12,6 +12,8 @@ #include #include +#include + /********** data ************/ @@ -591,6 +593,7 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context) "WM_STATE" }; Atom atoms[sizeof(atomNames)/sizeof(char*)]; + char *locale; int i; if (!initialized) { @@ -756,16 +759,20 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context) scrPtr->stipple = stipple; scrPtr->useMultiByte = WINGsConfiguration.useMultiByte; + scrPtr->useMultiByte = 0; - scrPtr->useWideChar = 1; + locale = setlocale(LC_CTYPE, NULL); + //printf("LC_CTYPE=%s\n", locale); + if (!locale || strcmp(locale, "C")==0 || strcmp(locale, "POSIX")==0) + scrPtr->useWideChar = 0; + else + scrPtr->useWideChar = 1; scrPtr->antialiasedText = WINGsConfiguration.antialiasedText; - scrPtr->normalFont = WMSystemFontOfSize(scrPtr, - WINGsConfiguration.defaultFontSize); + scrPtr->normalFont = WMSystemFontOfSize(scrPtr, 0); - scrPtr->boldFont = WMBoldSystemFontOfSize(scrPtr, - WINGsConfiguration.defaultFontSize); + scrPtr->boldFont = WMBoldSystemFontOfSize(scrPtr, 0); if (!scrPtr->boldFont) scrPtr->boldFont = scrPtr->normalFont; diff --git a/WINGs/winputmethod.c b/WINGs/winputmethod.c index c0ed4ef8..eb91211d 100644 --- a/WINGs/winputmethod.c +++ b/WINGs/winputmethod.c @@ -22,7 +22,8 @@ typedef struct W_ICContext { -Bool W_InitIMStuff(WMScreen *scr) +Bool +W_InitIMStuff(WMScreen *scr) { WMIMContext *ctx; @@ -38,7 +39,8 @@ Bool W_InitIMStuff(WMScreen *scr) } -void W_CloseIMStuff(WMScreen *scr) +void +W_CloseIMStuff(WMScreen *scr) { if (!scr->imctx) return; @@ -51,7 +53,8 @@ void W_CloseIMStuff(WMScreen *scr) -WMICContext *W_CreateIC(WMView *view) +WMICContext* +W_CreateIC(WMView *view) { WMScreen *scr = W_VIEW_SCREEN(view); WMICContext *ctx; @@ -60,11 +63,12 @@ WMICContext *W_CreateIC(WMView *view) ctx->next = scr->imctx->icList; if (scr->imctx->icList) scr->imctx->icList->prev = ctx; - scr->imctx = ctx; + //scr->imctx = ctx; } -void W_DestroyIC(WMICContext *ctx) +void +W_DestroyIC(WMICContext *ctx) { XDestroyIC(ctx->xic); @@ -72,8 +76,9 @@ void W_DestroyIC(WMICContext *ctx) } -int W_LookupString(WMView *view, XKeyEvent *event, - char buffer, int bufsize, KeySym ksym) +int +W_LookupString(WMView *view, XKeyEvent *event, + char buffer, int bufsize, KeySym ksym) { } diff --git a/WINGs/wmisc.c b/WINGs/wmisc.c index f8bfdb47..41e50791 100644 --- a/WINGs/wmisc.c +++ b/WINGs/wmisc.c @@ -30,26 +30,26 @@ W_DrawReliefWithGC(W_Screen *scr, Drawable d, int x, int y, unsigned int width, case WRSimple: XDrawRectangle(dpy, d, black, x, y, width-1, height-1); return; - + case WRRaised: bgc = black; dgc = dark; wgc = white; lgc = light; break; - + case WRSunken: wgc = dark; lgc = black; bgc = white; dgc = light; break; - + case WRPushed: lgc = wgc = black; dgc = bgc = white; break; - + case WRRidge: lgc = bgc = dark; dgc = wgc = white; @@ -59,7 +59,7 @@ W_DrawReliefWithGC(W_Screen *scr, Drawable d, int x, int y, unsigned int width, wgc = dgc = dark; lgc = bgc = white; break; - + default: return; } @@ -68,12 +68,12 @@ W_DrawReliefWithGC(W_Screen *scr, Drawable d, int x, int y, unsigned int width, if (width > 2 && relief != WRRaised && relief!=WRPushed) { XDrawLine(dpy, d, lgc, x+1, y+1, x+width-3, y+1); } - + XDrawLine(dpy, d, wgc, x, y, x, y+height-1); if (height > 2 && relief != WRRaised && relief!=WRPushed) { XDrawLine(dpy, d, lgc, x+1, y+1, x+1, y+height-3); } - + /* bottom right */ XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1); if (width > 2 && relief!=WRPushed) { @@ -87,22 +87,82 @@ W_DrawReliefWithGC(W_Screen *scr, Drawable d, int x, int y, unsigned int width, } +static int +findNextWord(char *text, int limit) +{ + int pos, len; + + len = strcspn(text, " \t\n\r"); + pos = len + strspn(text+len, " \t\n\r"); + if (pos > limit) + pos = limit; + + return pos; +} +static int +fitText(char *text, WMFont *font, int width, int wrap) +{ + int i, w, beforecrlf, word1, word2; + + /* text length before first cr/lf */ + beforecrlf = strcspn(text, "\n\r"); + + if (!wrap || beforecrlf==0) + return beforecrlf; + + w = WMWidthOfString(font, text, beforecrlf); + if (w <= width) { + /* text up to first crlf fits */ + return beforecrlf; + } + + word1 = 0; + while (1) { + word2 = word1 + findNextWord(text+word1, beforecrlf-word1); + if (word2 >= beforecrlf) + break; + w = WMWidthOfString(font, text, word2); + if (w > width) + break; + word1 = word2; + } + + for (i=word1; i width) { + break; + } + } + + /* keep words complete if possible */ + if (!isspace(text[i]) && word1>0) { + i = word1; + } else if (isspace(text[i]) && idisplay, view->window, + d = XCreatePixmap(screen->display, view->window, view->size.width, view->size.height, screen->depth); #endif @@ -215,7 +275,7 @@ W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font, #ifndef DOUBLE_BUFFER XClearWindow(screen->display, d); #else - XSetForeground(screen->display, screen->copyGC, + XSetForeground(screen->display, screen->copyGC, view->attribs.background_pixel); XFillRectangle(screen->display, d, screen->copyGC, 0, 0, view->size.width, view->size.height); @@ -232,7 +292,7 @@ W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font, x = 1; y = 1; w = view->size.width - 3; - h = view->size.height - 3; + h = view->size.height - 3; } /* calc. image alignment */ @@ -247,7 +307,7 @@ W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font, y = 0; */ break; - + case WIPLeft: ix = x; iy = y + (h - image->height) / 2; @@ -255,20 +315,20 @@ W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font, y = 0; w -= image->width + 5; break; - + case WIPRight: ix = view->size.width - image->width - x; iy = y + (h - image->height) / 2; w -= image->width + 5; break; - + case WIPBelow: ix = (view->size.width - image->width) / 2; iy = h - image->height; y = 0; h -= image->height; break; - + default: case WIPAbove: ix = (view->size.width - image->width) / 2; @@ -277,7 +337,7 @@ W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font, h -= image->height; break; } - + ix += ofs; iy += ofs; @@ -295,7 +355,7 @@ W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font, /* draw text */ if (position != WIPImageOnly && text!=NULL) { int textHeight; - + textHeight = W_GetTextHeight(font, text, w-8, wrap); W_PaintText(view, d, font, x+ofs+4, y+ofs + (h-textHeight)/2, w-8, alignment, textColor, wrap, text, strlen(text)); @@ -314,26 +374,26 @@ W_PaintTextAndImage(W_View *view, int wrap, WMColor *textColor, W_Font *font, -WMPoint +WMPoint wmkpoint(int x, int y) { WMPoint point; - + point.x = x; point.y = y; - + return point; } -WMSize +WMSize wmksize(unsigned int width, unsigned int height) { WMSize size; - + size.width = width; size.height = height; - + return size; } diff --git a/WINGs/wscroller.c b/WINGs/wscroller.c index 4ddbd38e..263848aa 100644 --- a/WINGs/wscroller.c +++ b/WINGs/wscroller.c @@ -306,10 +306,9 @@ paintArrow(WMScroller *sPtr, Drawable d, int part) gc = scr->whiteGC; #endif } - - + + if (sPtr->flags.horizontal) { - /* paint button */ #ifndef DOUBLE_BUFFER XFillRectangle(scr->display, d, gc, @@ -326,7 +325,7 @@ paintArrow(WMScroller *sPtr, Drawable d, int part) XSetClipOrigin(scr->display, scr->clipGC, ofs + (BUTTON_SIZE - arrow->width) / 2, 2 + (BUTTON_SIZE - arrow->height) / 2); - + XCopyArea(scr->display, arrow->pixmap, d, scr->clipGC, 0, 0, arrow->width, arrow->height, ofs + (BUTTON_SIZE - arrow->width) / 2, diff --git a/WINGs/wtext.c b/WINGs/wtext.c index 45892e62..342fae70 100644 --- a/WINGs/wtext.c +++ b/WINGs/wtext.c @@ -2026,7 +2026,7 @@ insertTextInteractively(Text *tPtr, char *text, int len) int s = tb->used - tPtr->tpos; if (!tb->blank && nlen>0) { - char *save; + char *save=NULL; if (s > 0) { save = wmalloc(s); diff --git a/WPrefs.app/Appearance.c b/WPrefs.app/Appearance.c index 22f98fd4..6bf11c6a 100644 --- a/WPrefs.app/Appearance.c +++ b/WPrefs.app/Appearance.c @@ -109,9 +109,9 @@ typedef struct _Panel { char oldTabItem; - char menuStyle; + int menuStyle; - char titleAlignment; + int titleAlignment; Pixmap preview; Pixmap previewNoText; diff --git a/WPrefs.app/Expert.c b/WPrefs.app/Expert.c index ece04a7f..974e9fdb 100644 --- a/WPrefs.app/Expert.c +++ b/WPrefs.app/Expert.c @@ -84,7 +84,7 @@ createPanel(Panel *p) WMSetButtonText(panel->swi[7], _("Smooth font edges (needs restart).")); //if (!WMHasAntialiasingSupport(WMWidgetScreen(panel->box))) - WMSetButtonEnabled(panel->swi[7], False); + WMSetButtonEnabled(panel->swi[7], True); WMRealizeWidget(panel->box); WMMapSubwidgets(panel->box); diff --git a/WPrefs.app/Focus.c b/WPrefs.app/Focus.c index 422caa21..3fbf1cda 100644 --- a/WPrefs.app/Focus.c +++ b/WPrefs.app/Focus.c @@ -219,7 +219,7 @@ createPanel(Panel *p) WMSetBoxHorizontal(box, False); panel->kfocB[0] = WMCreateRadioButton(box); - WMSetButtonText(panel->kfocB[0], _("Manual: Click on the window to set "\ + WMSetButtonText(panel->kfocB[0], _("Manual: Click on the window to set "\ "keyboard input focus")); WMAddBoxSubview(box, WMWidgetView(panel->kfocB[0]), True, True, 20, 0, 0); @@ -243,13 +243,13 @@ createPanel(Panel *p) WMSetFrameTitle(panel->cfocF, _("Install colormap in the window...")); panel->manB = WMCreateRadioButton(panel->cfocF); - WMResizeWidget(panel->manB, 220, 20); - WMMoveWidget(panel->manB, 15, 18); + WMResizeWidget(panel->manB, 225, 20); + WMMoveWidget(panel->manB, 10, 18); WMSetButtonText(panel->manB, _("...that has the input focus.")); panel->autB = WMCreateRadioButton(panel->cfocF); - WMResizeWidget(panel->autB, 220, 20); - WMMoveWidget(panel->autB, 15, 40); + WMResizeWidget(panel->autB, 225, 20); + WMMoveWidget(panel->autB, 10, 43); WMSetButtonText(panel->autB, _("...that is under the mouse pointer.")); WMGroupButtons(panel->manB, panel->autB); @@ -331,15 +331,15 @@ createPanel(Panel *p) WMMoveWidget(panel->optF, 265, 95); panel->ignB = WMCreateSwitchButton(panel->optF); - WMResizeWidget(panel->ignB, 210, 50); - WMMoveWidget(panel->ignB, 15, 10); - WMSetButtonText(panel->ignB, _("Do not let applications receive\n" - "the click used to focus windows.")); + WMResizeWidget(panel->ignB, 225, 50); + WMMoveWidget(panel->ignB, 10, 10); + WMSetButtonText(panel->ignB, _("Do not let applications receive " + "the click used to focus windows.")); panel->newB = WMCreateSwitchButton(panel->optF); - WMResizeWidget(panel->newB, 210, 35); - WMMoveWidget(panel->newB, 15, 70); - WMSetButtonText(panel->newB, _("Automatically focus new\nwindows.")); + WMResizeWidget(panel->newB, 225, 35); + WMMoveWidget(panel->newB, 10, 70); + WMSetButtonText(panel->newB, _("Automatically focus new windows.")); WMMapSubwidgets(panel->optF); diff --git a/WPrefs.app/Font.c b/WPrefs.app/Font.c index 4d5c8b28..a6d01074 100644 --- a/WPrefs.app/Font.c +++ b/WPrefs.app/Font.c @@ -23,7 +23,7 @@ #include "WPrefs.h" #include - +#include typedef struct _Panel { WMBox *box; @@ -358,7 +358,7 @@ paintItems(WMScreen *scr, Drawable d, WMColor *color, WMFont *font, int l = strlen(text); int x = previewPositions[part].pos.x; int y = previewPositions[part].pos.y; - int w = previewPositions[part].size.width; + //int w = previewPositions[part].size.width; int h = previewPositions[part].size.height/4; int i; for( i = 0; i < 4 ; i++) { @@ -443,7 +443,7 @@ dumpRImage(char *path, RImage *image) } } -static int +/*static int isPixmap(WMPropList *prop) { WMPropList *p; @@ -455,7 +455,7 @@ isPixmap(WMPropList *prop) return 1; else return 0; -} +}*/ static Pixmap renderTexture(WMScreen *scr, WMPropList *texture, int width, int height, @@ -669,7 +669,7 @@ renderMenu(_Panel *panel, WMPropList *texture, int width, int iheight) WMScreen *scr = WMWidgetScreen(panel->parent); Display *dpy = WMScreenDisplay(scr); Pixmap pix, tmp; - RContext *rc = WMScreenRContext(scr); + //RContext *rc = WMScreenRContext(scr); GC gc = XCreateGC(dpy, WMWidgetXID(panel->parent), 0, NULL); int i; @@ -835,7 +835,7 @@ paintPreviewBox(Panel *panel, int elements) { WMScreen *scr = WMWidgetScreen(panel->parent); Display *dpy = WMScreenDisplay(scr); - int refresh = 0; + //int refresh = 0; GC gc; WMColor *black = WMBlackColor(scr); Pixmap mitem; @@ -926,7 +926,7 @@ static void paintTextField(void *data, int section) { _Panel *panel = (_Panel*)data; - char *sample = NULL; + //char *sample = NULL; int encoding; encoding = WMGetPopUpButtonSelectedItem(panel->langP); WMSetTextFieldFont(panel->fontT, getFontForPreview(panel, section)); @@ -1072,7 +1072,7 @@ refillFontSetList(void *data) char *encoding = getFontEncoding(panel); int section = WMGetPopUpButtonSelectedItem(panel->fontSel); int i; - int pos; + //int pos; WMClearList(panel->fsetLs); if(!encoding) { array = getCurrentFontProp(panel, section); @@ -1259,7 +1259,7 @@ static void changeLanguageAction(WMWidget *w, void *data) { Panel *panel = (Panel*)data; - WMScreen *scr = WMWidgetScreen(panel->box); + //WMScreen *scr = WMWidgetScreen(panel->box); int section; section = WMGetPopUpButtonSelectedItem(w); @@ -1314,7 +1314,7 @@ static char* getFontSampleString(void *data) { _Panel *panel = (_Panel*)data; - WMScreen *scr = WMWidgetScreen(panel->box); + //WMScreen *scr = WMWidgetScreen(panel->box); WMMenuItem *mi; WMPropList *pl; int section; @@ -1336,7 +1336,7 @@ static char* getFontEncoding(void *data) { _Panel *panel = (_Panel*)data; - WMScreen *scr = WMWidgetScreen(panel->box); + //WMScreen *scr = WMWidgetScreen(panel->box); WMMenuItem *mi; WMPropList *pl; int section; @@ -1358,7 +1358,7 @@ static Bool isEncodingMultiByte(void *data) { _Panel *panel = (_Panel*)data; - WMScreen *scr = WMWidgetScreen(panel->box); + //WMScreen *scr = WMWidgetScreen(panel->box); WMMenuItem *mi; WMPropList *pl; int section; @@ -1473,26 +1473,20 @@ getDefaultSystemFont(void *data, int element) { _Panel *panel = (_Panel*)data; WMScreen *scr = WMWidgetScreen(panel->box); - switch(element) { - case 0: - return WMBoldSystemFontOfSize(scr, 12); - break; - case 1: - return WMBoldSystemFontOfSize(scr, 24); - break; - case 2: - return WMBoldSystemFontOfSize(scr, 12); - break; - case 3: - return WMSystemFontOfSize(scr, 12); - break; - case 4: - return WMSystemFontOfSize(scr, 8); - break; - case 5: - return WMSystemFontOfSize(scr, 8); - break; - } + + switch(element) { + case 0: + case 2: + return WMBoldSystemFontOfSize(scr, 12); + case 1: + return WMBoldSystemFontOfSize(scr, 24); + case 4: + case 5: + return WMSystemFontOfSize(scr, 8); + case 3: + default: + return WMSystemFontOfSize(scr, 12); + } } static void @@ -1515,7 +1509,7 @@ static void toggleAA(WMWidget *w, void *data) { _Panel *panel = (_Panel*)data; - int section; + //int section; if(panel->AntialiasedText) panel->AntialiasedText = False; else @@ -1622,7 +1616,7 @@ addButtonAction(WMWidget *w, void *data) array = getDefaultFontProp(panel, encoding, section); WMHideFontPanel(panel->fontPanel); - chosenFont = WMGetFontPanelFontName(panel->fontPanel); + chosenFont = WMGetFontName(WMGetFontPanelFont(panel->fontPanel)); string = WMCreatePLString(chosenFont); pos = WMGetListSelectedItemRow(panel->fsetLs); WMInsertListItem(panel->fsetLs, pos+1, chosenFont); @@ -1651,7 +1645,7 @@ changeButtonAction(WMWidget *w, void *data) WMHideFontPanel(panel->fontPanel); - chosenFont = WMGetFontPanelFontName(panel->fontPanel); + chosenFont = WMGetFontName(WMGetFontPanelFont(panel->fontPanel)); string = WMCreatePLString(chosenFont); pos = WMGetListSelectedItemRow(panel->fsetLs); @@ -1720,7 +1714,7 @@ removeButtonClick(WMWidget *w, void *data) static void showData(_Panel *panel) { - WMScreen *scr = WMWidgetScreen(panel->parent); + //WMScreen *scr = WMWidgetScreen(panel->parent); char *str; int i; diff --git a/WPrefs.app/KeyboardShortcuts.c b/WPrefs.app/KeyboardShortcuts.c index 76e3eb27..fadee5da 100644 --- a/WPrefs.app/KeyboardShortcuts.c +++ b/WPrefs.app/KeyboardShortcuts.c @@ -112,6 +112,12 @@ static char *keyOptions[] = { "WindowShortcut9Key", "WindowShortcut10Key", "ScreenSwitchKey", +#ifdef VIRTUAL_DESKTOP + "VirtualEdgeLeftKey", + "VirtualEdgeRightKey", + "VirtualEdgeUpKey", + "VirtualEdgeDownKey", +#endif "ClipRaiseKey", "ClipLowerKey", #ifndef XKB_MODELOCK @@ -326,7 +332,7 @@ captureClick(WMWidget *w, void *data) } panel->capturing = 0; WMSetButtonText(w, _("Capture")); - WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key.")); + WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key.")); XUngrabKeyboard(dpy, CurrentTime); } @@ -537,6 +543,12 @@ createPanel(Panel *p) WMAddListItem(panel->actLs, _("Shortcut for window 9")); WMAddListItem(panel->actLs, _("Shortcut for window 10")); WMAddListItem(panel->actLs, _("Switch to Next Screen/Monitor")); +#ifdef VIRTUAL_DESKTOP + WMAddListItem(panel->actLs, _("Move VirtualDesktop to next left edge")); + WMAddListItem(panel->actLs, _("Move VirtualDesktop to next right edge")); + WMAddListItem(panel->actLs, _("Move VirtualDesktop to next top edge")); + WMAddListItem(panel->actLs, _("Move VirtualDesktop to next bottom edge")); +#endif WMAddListItem(panel->actLs, _("Raise Clip")); WMAddListItem(panel->actLs, _("Lower Clip")); WMAddListItem(panel->actLs, _("Raise/Lower Clip")); @@ -580,7 +592,7 @@ createPanel(Panel *p) WMMoveWidget(panel->instructionsL, 15, 140); WMSetLabelTextAlignment(panel->instructionsL, WACenter); WMSetLabelWraps(panel->instructionsL, True); - WMSetLabelText(panel->instructionsL, _("Click Capture to interactively define the shortcut key.")); + WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key.")); WMMapSubwidgets(panel->shoF); diff --git a/WPrefs.app/Makefile.am b/WPrefs.app/Makefile.am index e2e65d77..917ee3fa 100644 --- a/WPrefs.app/Makefile.am +++ b/WPrefs.app/Makefile.am @@ -42,7 +42,9 @@ WPrefs_SOURCES = \ imagebrowser.h \ xmodifier.c -AM_CPPFLAGS = @CPPFLAGS@ -DLOCALEDIR=\"$(NLSDIR)\" +AM_CPPFLAGS = -DLOCALEDIR=\"$(NLSDIR)\" + +AM_CFLAGS = -fno-strict-aliasing INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/WINGs @HEADER_SEARCH_PATH@ diff --git a/WPrefs.app/WPrefs.c b/WPrefs.app/WPrefs.c index f25853eb..fa06a73e 100644 --- a/WPrefs.app/WPrefs.c +++ b/WPrefs.app/WPrefs.c @@ -845,10 +845,10 @@ loadConfigurations(WMScreen *scr, WMWindow *mainw) } if (!db) { - db = WMCreatePLDictionary(NULL, NULL, NULL); + db = WMCreatePLDictionary(NULL, NULL); } if (!gdb) { - gdb = WMCreatePLDictionary(NULL, NULL, NULL); + gdb = WMCreatePLDictionary(NULL, NULL); } GlobalDB = gdb; diff --git a/WPrefs.app/WindowHandling.c b/WPrefs.app/WindowHandling.c index 2f802873..7965a015 100644 --- a/WPrefs.app/WindowHandling.c +++ b/WPrefs.app/WindowHandling.c @@ -397,18 +397,16 @@ createPanel(Panel *p) WMMoveWidget(panel->resL, 95, 20); panel->resaB = WMCreateRadioButton(panel->resF); - WMMoveWidget(panel->resaB, 130, 14); - WMResizeWidget(panel->resaB, 70, 26); + WMMoveWidget(panel->resaB, 130, 15); + WMResizeWidget(panel->resaB, 70, 25); WMSetButtonText(panel->resaB, _("Resist")); panel->resrB = WMCreateRadioButton(panel->resF); - WMMoveWidget(panel->resrB, 200, 12); - WMResizeWidget(panel->resrB, 65, 30); + WMMoveWidget(panel->resrB, 200, 15); + WMResizeWidget(panel->resrB, 70, 25); WMSetButtonText(panel->resrB, _("Attract")); WMGroupButtons(panel->resrB, panel->resaB); - - WMMapSubwidgets(panel->resF); /**************** Transients on Parent Workspace ****************/ @@ -420,7 +418,7 @@ createPanel(Panel *p) panel->tranB = WMCreateSwitchButton(panel->tranF); WMMoveWidget(panel->tranB, 10, 5); WMResizeWidget(panel->tranB, 250, 30); - WMSetButtonText(panel->tranB, _("Open dialogs in same workspace\nas their owners")); + WMSetButtonText(panel->tranB, _("Open dialogs in the same workspace\nas their owners")); WMMapSubwidgets(panel->tranF); diff --git a/WPrefs.app/Workspace.c b/WPrefs.app/Workspace.c index 5de76b40..2c1c9421 100644 --- a/WPrefs.app/Workspace.c +++ b/WPrefs.app/Workspace.c @@ -180,7 +180,7 @@ createPanel(Panel *p) WMResizeWidget(panel->cyclB, 280, 34); WMMoveWidget(panel->cyclB, 75, 30); WMSetButtonText(panel->cyclB, - _("wrap to the first workspace after the\nlast workspace.")); + _("Wrap to the first workspace from the last workspace.")); panel->cyclL = WMCreateLabel(panel->navF); WMResizeWidget(panel->cyclL, 60, 60); @@ -202,7 +202,7 @@ createPanel(Panel *p) WMResizeWidget(panel->linkB, 280, 34); WMMoveWidget(panel->linkB, 75, 75); WMSetButtonText(panel->linkB, - _("switch workspaces while dragging windows.")); + _("Switch workspaces while dragging windows.")); panel->linkL = WMCreateLabel(panel->navF); WMResizeWidget(panel->linkL, 60, 40); @@ -224,7 +224,7 @@ createPanel(Panel *p) WMResizeWidget(panel->newB, 280, 34); WMMoveWidget(panel->newB, 75, 120); WMSetButtonText(panel->newB, - _("automatically create new workspaces.")); + _("Automatically create new workspaces.")); panel->newL = WMCreateLabel(panel->navF); WMResizeWidget(panel->newL, 60, 20); diff --git a/WindowMaker/Defaults/WMWindowAttributes.in b/WindowMaker/Defaults/WMWindowAttributes.in index a6226750..aad41fa2 100644 --- a/WindowMaker/Defaults/WMWindowAttributes.in +++ b/WindowMaker/Defaults/WMWindowAttributes.in @@ -75,6 +75,9 @@ DontSaveSession = Yes; Unfocusable = Yes; }; + kio_uiserver = {NoAppIcon = Yes;}; + kcmshell = {NoAppIcon = Yes;}; + kded = {NoAppIcon = Yes;}; "." = {NoAppIcon = Yes;}; "*" = {Icon = defaultAppIcon.#extension#;SharedAppIcon = Yes;}; } diff --git a/acinclude.m4 b/acinclude.m4 index f0f906b1..ee22091b 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -24,6 +24,42 @@ CPPFLAGS="$CPPFLAGS_old" ]) +dnl +dnl WM_CHECK_XFT_VERSION(MIN_VERSION, [ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]) +dnl +dnl # $XFTFLAGS should be defined before calling this macro, +dnl # else it will not be able to find Xft.h +dnl +AC_DEFUN(WM_CHECK_XFT_VERSION, +[ +CPPFLAGS_old="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $XFTFLAGS $inc_search_path" +xft_major_version=`echo $1 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` +xft_minor_version=`echo $1 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` +xft_micro_version=`echo $1 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` +AC_MSG_CHECKING([whether libXft is at least version $1]) +AC_CACHE_VAL(ac_cv_lib_xft_version_ok, +[AC_TRY_LINK( +[/* Test version of libXft we have */ +#include + +#if !defined(XFT_VERSION) || XFT_VERSION < $xft_major_version*10000 + $xft_minor_version*100 + $xft_micro_version +#error libXft on this system is too old. Consider upgrading to at least $1 +#endif +], [], +eval "ac_cv_lib_xft_version_ok=yes", +eval "ac_cv_lib_xft_version_ok=no")]) +if eval "test \"`echo '$ac_cv_lib_xft_version_ok'`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) +fi +CPPFLAGS="$CPPFLAGS_old" +]) + + dnl dnl WM_CHECK_REDCRAP_BUGS(prefix,bindir,libdir) dnl diff --git a/configure.ac b/configure.ac index eabd927f..adfbd739 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ AC_INIT(src/WindowMaker.h) -AM_INIT_AUTOMAKE(WindowMaker, 0.90.0) +AM_INIT_AUTOMAKE(WindowMaker, 0.85.0) AC_PROG_LIBTOOL @@ -224,7 +224,7 @@ if test "$ac_cv_prog_gcc" = yes; then AC_CACHE_CHECK(whether gcc supports MMX(tm) inline asm, ac_cv_c_inline_mmx, - [AC_TRY_LINK(,[asm ("movq %mm0, %mm1");], + [AC_TRY_LINK(,[__asm__ ("movq %mm0, %mm1");], ac_cv_c_inline_mmx=yes, ac_cv_c_inline_mmx=no)]) @@ -295,7 +295,7 @@ dnl ================== dnl List of supported locales dnl ------------------------- -supported_locales="be bg ca cs da de el es et fi fr gl hr hu it ja ko ms nl no pl pt ro ru sk sv tr zh_CN zh_TW.Big5" +supported_locales="be bg bs ca cs da de el es et fi fr gl hr hu it ja ko ms nl no pl pt ro ru sk sv tr zh_CN zh_TW.Big5" supported_wprefs_locales="bg ca cs de es et fi fr hr hu it ja ko pt ru sk zh_CN zh_TW.Big5" supported_wings_locales="bg ca cs de fr sk" @@ -376,6 +376,12 @@ AC_SUBST(supported_locales) dnl Support for various hint things dnl =============================== +gnome_on="no" +kde_on="no" +openlook_on="no" +netwm_on="no" +vdesktop_on="no" + AC_ARG_ENABLE(gnome, [ --enable-gnome enable stuff needed for GNOME ], @@ -401,6 +407,22 @@ AC_ARG_ENABLE(openlook, fi]) +AC_ARG_ENABLE(netwm, + [ --enable-netwm enable support for FreeDesktop hints ], + [if test x$enableval = xyes; then + AC_DEFINE(NETWM_HINTS, 1, [define if you want NETWM hints support]) + netwm_on=yes + fi]) + + +AC_ARG_ENABLE(vdesktop, + [ --enable-vdesktop enable virtual desktop], + [if test x$enableval = xyes; then + AC_DEFINE(VIRTUAL_DESKTOP, 1, [define if you want virtual desktop support]) + vdesktop_on=yes + fi]) + + dnl dnl Disable some stuff that are duplicated in kde dnl --------------------------------------------- @@ -519,35 +541,54 @@ fi dnl Xft antialiased font support dnl ============================ + xft=yes XFTLIBS="" -AC_ARG_ENABLE(xft, -[ --disable-xft disable Xft antialiased font support], - xft=$enableval, xft=yes) -if test "$xft" = yes; then - if test "x$PKGCONFIG" != x -a "`$PKGCONFIG xft; echo $?`" = 0; then - XFTCONFIG="$PKGCONFIG xft" - pkgconfig_xft=yes - else - AC_CHECK_PROG(XFTCONFIG, xft-config, xft-config) - fi - AC_MSG_CHECKING([for the Xft2 library]) - if test "x$XFTCONFIG" != x; then - XFTLIBS=`$XFTCONFIG --libs` - XFTFLAGS=`$XFTCONFIG --cflags` - AC_MSG_RESULT([found]) - else - xft=no - AC_MSG_RESULT([not found]) - fi - if test "$xft" = yes; then - AC_SUBST(XFTFLAGS) - AC_SUBST(XFTLIBS) - AC_DEFINE(XFT, 1, [define if you want support for antialiased fonts (set by configure)]) - fi +if test "x$PKGCONFIG" != x -a "`$PKGCONFIG xft; echo $?`" = 0; then + XFTCONFIG="$PKGCONFIG xft" + pkgconfig_xft=yes +else + AC_CHECK_PROG(XFTCONFIG, xft-config, xft-config) fi +AC_MSG_CHECKING([for the Xft2 library]) + +if test "x$XFTCONFIG" != x; then + XFTLIBS=`$XFTCONFIG --libs` + XFTFLAGS=`$XFTCONFIG --cflags` + AC_MSG_RESULT([found]) +else + AC_MSG_RESULT([not found]) + echo + echo "ERROR!!! libXft2 is not installed or could not be found." + echo " Xft2 is a requirement for building Window Maker." + echo " Please install it (along with fontconfig) before continuing." + echo + exit 1 +fi + +minXFT="2.1.2" +goodxft="no" + +dnl +dnl The macro below will use $XFTFLAGS (defined above) to find Xft.h +dnl +WM_CHECK_XFT_VERSION($minXFT, goodxft=yes, goodxft=no) + +if test "$goodxft" = no; then + echo + echo "ERROR!!! libXft on this system is an old version." + echo " Please consider upgrading to at least version ${minXFT}." + echo + exit 1 +fi + +AC_SUBST(XFTFLAGS) +AC_SUBST(XFTLIBS) +AC_DEFINE(XFT, 1, [define if you want support for antialiased fonts (set by configure)]) + + dnl XINERAMA support dnl ================ xinerama=no @@ -845,14 +886,14 @@ AC_ARG_WITH(appspath, [ --with-appspath=PATH specify the directory for GNUstep applications], appspath=$withval ) if test "x$appspath" = "x"; then - gnustepdir='$(prefix)/GNUstep' + gnustepdir='${prefix}/GNUstep' if test "x$GNUSTEP_LOCAL_ROOT" != "x" ; then gnustepdir=`echo "$GNUSTEP_LOCAL_ROOT" | sed -e "s|^${prefix}|prefix|"` gnustepdir=`echo $gnustepdir | sed -e 's|^prefix|${prefix}|'` fi - with_appspath=$gnustepdir/Apps + with_appspath=$gnustepdir/Applications fi wprefsdir=$with_appspath/WPrefs.app @@ -1075,29 +1116,48 @@ dnl ========================== supported_gfx="$supported_gfx builtin-PPM" if test "x$MOFILES" = "x"; then - mof=none + mof=None else mof=`echo $MOFILES` fi if test "x$MOFILES" = "x"; then - languages=none + languages=None else languages=`echo $MOFILES | sed 's/.mo//g'` fi +extrasupport='' +if test "$openlook_on" = "yes"; then + extrasupport="OpenLook $extrasupport" +fi +if test "$gnome_on" = "yes"; then + extrasupport="Gnome $extrasupport" +fi +if test "$kde_on" = "yes"; then + extrasupport="KDE $extrasupport" +fi +if test "$netwm_on" = "yes"; then + extrasupport="NetWM $extrasupport" +fi + +if test "x$extrasupport" = "x"; then + extrasupport="None" +fi echo echo "Window Maker was configured as follows:" echo echo "Installation path prefix : $prefix" echo "Installation path for binaries : $_bindir" -echo "Installation path for WPrefs.app : $wprefsdir" | sed -e 's|\$(prefix)|'"$prefix|" +echo "Installation path for WPrefs.app : $with_appspath" | sed -e 's|\${prefix}|'"$prefix|" echo "Supported graphic format libraries : $supported_gfx" -echo "Antialiased text support for WINGs : $xft" -echo "Xinerama extension support : $xinerama" echo "Use assembly routines for wrlib : $asm_support" echo "Use inline MMX(tm) x86 assembly : $mmx_support" +echo "Antialiased text support in WINGs : $xft" +echo "Xinerama extension support : $xinerama" +echo "Virtual desktop support : $vdesktop_on" +echo "Additionally supported environments : $extrasupport" echo "Translated message files to install : $mof" dnl echo "Supported languages beside English : $languages" if test "x$MOFILES" != "x"; then diff --git a/src/Makefile.am b/src/Makefile.am index a89a5c02..3476125a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -96,6 +96,8 @@ wmaker_SOURCES = \ winmenu.c \ winspector.h \ winspector.c \ + wmspec.h \ + wmspec.c \ workspace.c \ workspace.h \ wsound.c \ @@ -104,7 +106,9 @@ wmaker_SOURCES = \ text.h -AM_CPPFLAGS = @CPPFLAGS@ $(DFLAGS) -DLOCALEDIR=\"$(NLSDIR)\" +AM_CPPFLAGS = $(DFLAGS) -DLOCALEDIR=\"$(NLSDIR)\" + +AM_CFLAGS = -fno-strict-aliasing INCLUDES = \ diff --git a/src/WindowMaker.h b/src/WindowMaker.h index e8c2bf59..711e133c 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -70,6 +70,7 @@ enum { WMSubmenuLevel = 6, WMMainMenuLevel = 20, WMStatusLevel = 21, + WMFullscreenLevel = 50, WMModalLevel = 100, WMPopUpLevel = 101, WMScreensaverLevel = 1000, @@ -118,40 +119,41 @@ typedef enum { #define WBUT_ICONIFY 2 #define WBUT_KILL 3 #ifdef XKB_BUTTON_HINT -#define WBUT_XKBGROUP1 4 -#define WBUT_XKBGROUP2 5 -#define WBUT_XKBGROUP3 6 -#define WBUT_XKBGROUP4 7 +#define WBUT_XKBGROUP1 4 +#define WBUT_XKBGROUP2 5 +#define WBUT_XKBGROUP3 6 +#define WBUT_XKBGROUP4 7 #define PRED_BPIXMAPS 8 /* reserved for 4 groups */ #else #define PRED_BPIXMAPS 4 /* count of WBUT icons */ #endif /* XKB_BUTTON_HINT */ /* cursors */ -#define WCUR_DEFAULT 0 -#define WCUR_NORMAL 0 -#define WCUR_MOVE 1 -#define WCUR_RESIZE 2 +#define WCUR_DEFAULT 0 +#define WCUR_NORMAL 0 +#define WCUR_MOVE 1 +#define WCUR_RESIZE 2 #define WCUR_TOPLEFTRESIZE 3 #define WCUR_TOPRIGHTRESIZE 4 #define WCUR_BOTTOMLEFTRESIZE 5 #define WCUR_BOTTOMRIGHTRESIZE 6 -#define WCUR_VERTICALRESIZE 7 -#define WCUR_HORIZONRESIZE 8 -#define WCUR_WAIT 9 -#define WCUR_ARROW 10 -#define WCUR_QUESTION 11 -#define WCUR_TEXT 12 -#define WCUR_SELECT 13 -#define WCUR_ROOT 14 -#define WCUR_LAST 15 +#define WCUR_VERTICALRESIZE 7 +#define WCUR_HORIZONRESIZE 8 +#define WCUR_WAIT 9 +#define WCUR_ARROW 10 +#define WCUR_QUESTION 11 +#define WCUR_TEXT 12 +#define WCUR_SELECT 13 +#define WCUR_ROOT 14 +#define WCUR_EMPTY 15 +#define WCUR_LAST 16 /* geometry displays */ -#define WDIS_NEW 0 /* new style */ -#define WDIS_CENTER 1 /* center of screen */ -#define WDIS_TOPLEFT 2 /* top left corner of screen */ -#define WDIS_FRAME_CENTER 3 /* center of the frame */ -#define WDIS_NONE 4 +#define WDIS_NEW 0 /* new style */ +#define WDIS_CENTER 1 /* center of screen */ +#define WDIS_TOPLEFT 2 /* top left corner of screen */ +#define WDIS_FRAME_CENTER 3 /* center of the frame */ +#define WDIS_NONE 4 /* keyboard input focus mode */ #define WKF_CLICK 0 @@ -181,10 +183,10 @@ typedef enum { #define WIS_RANDOM 4 /* secret */ /* switchmenu actions */ -#define ACTION_ADD 0 -#define ACTION_REMOVE 1 -#define ACTION_CHANGE 2 -#define ACTION_CHANGE_WORKSPACE 3 +#define ACTION_ADD 0 +#define ACTION_REMOVE 1 +#define ACTION_CHANGE 2 +#define ACTION_CHANGE_WORKSPACE 3 #define ACTION_CHANGE_STATE 4 @@ -202,8 +204,8 @@ typedef enum { #define WS_PFOCUSED 2 /* clip title colors */ -#define CLIP_NORMAL 0 -#define CLIP_COLLAPSED 1 +#define CLIP_NORMAL 0 +#define CLIP_COLLAPSED 1 /* icon yard position */ @@ -420,8 +422,8 @@ typedef struct WPreferences { unsigned int vedge_bordersize; unsigned int vedge_hscrollspeed; unsigned int vedge_vscrollspeed; - unsigned int vedge_maxheight; - unsigned int vedge_maxwidth; + unsigned int vedge_resistance; + unsigned int vedge_attraction; #endif char ws_cycle; /* Cycle existing workspaces */ diff --git a/src/actions.c b/src/actions.c index 47f42881..c218f17a 100644 --- a/src/actions.c +++ b/src/actions.c @@ -69,6 +69,8 @@ extern WPreferences wPreferences; extern Atom _XA_WM_TAKE_FOCUS; +extern void ProcessPendingEvents(); + /******* Local Variables *******/ static struct { @@ -85,37 +87,6 @@ static struct { #define SHADE_DELAY shadePars[(int)wPreferences.shade_speed].delay -static int ignoreTimestamp=0; - - -#ifdef ANIMATIONS -static void -processEvents(int event_count) -{ - XEvent event; - - /* - * This is a hack. When animations are enabled, processing of - * events ocurred during a animation are delayed until it's end. - * Calls that consider the TimeStamp, like XSetInputFocus(), will - * fail because the TimeStamp is too old. Then, for example, if - * the user changes window focus while a miniaturize animation is - * in course, the window will not get focus properly after the end - * of the animation. This tries to workaround it by passing CurrentTime - * as the TimeStamp for XSetInputFocus() for all events ocurred during - * the animation. - */ - ignoreTimestamp=1; - while (XPending(dpy) && event_count--) { - WMNextEvent(dpy, &event); - WMHandleEvent(&event); - } - ignoreTimestamp=0; -} -#endif /* ANIMATIONS */ - - - /* *---------------------------------------------------------------------- * wSetFocusTo-- @@ -139,33 +110,21 @@ wSetFocusTo(WScreen *scr, WWindow *wwin) int timestamp=LastTimestamp; WApplication *oapp=NULL, *napp=NULL; int wasfocused; + + if (scr->flags.ignore_focus_events || LastFocusChange > timestamp) + return; if (!old_scr) old_scr=scr; old_focused=old_scr->focused_window; - /* - * Safeguard: make sure the timestamp is monotonically increasing - * (very unlikely that this will be needed, still a safeguard) - */ - if (timestamp <= LastFocusChange) - timestamp = LastFocusChange + 1; - LastFocusChange = timestamp; - /* - * This is a hack, because XSetInputFocus() should have a proper - * timestamp instead of CurrentTime but it seems that some times - * clients will not receive focus properly that way. - */ - if (ignoreTimestamp) - timestamp = CurrentTime; - if (old_focused) oapp = wApplicationOf(old_focused->main_window); if (wwin == NULL) { - XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp); + XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, CurrentTime); if (old_focused) { wWindowUnfocus(old_focused); } @@ -199,12 +158,12 @@ wSetFocusTo(WScreen *scr, WWindow *wwin) /* set input focus */ switch (wwin->focus_mode) { case WFM_NO_INPUT: - XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp); + XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, CurrentTime); break; case WFM_PASSIVE: case WFM_LOCALLY_ACTIVE: - XSetInputFocus(dpy, wwin->client_win, RevertToParent, timestamp); + XSetInputFocus(dpy, wwin->client_win, RevertToParent, CurrentTime); break; case WFM_GLOBALLY_ACTIVE: @@ -216,7 +175,7 @@ wSetFocusTo(WScreen *scr, WWindow *wwin) } XSync(dpy, False); } else { - XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp); + XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, CurrentTime); } if (WFLAGP(wwin, no_focusable)) return; @@ -333,9 +292,8 @@ wShadeWindow(WWindow *wwin) #ifdef ANIMATIONS if (!wwin->screen_ptr->flags.startup) { - /* Look at processEvents() for reason of this code. */ - XSync(dpy, 0); - processEvents(XPending(dpy)); + /* Catch up with events not processed while animation was running */ + ProcessPendingEvents(); } #endif } @@ -419,7 +377,7 @@ wMaximizeWindow(WWindow *wwin, int directions) int changed_h, changed_v, shrink_h, shrink_v; WArea usableArea, totalArea; - if (WFLAGP(wwin, no_resizable)) + if (!IS_RESIZABLE(wwin)) return; totalArea.x1 = 0; @@ -550,6 +508,65 @@ wUnmaximizeWindow(WWindow *wwin) wSoundPlay(WSOUND_UNMAXIMIZE); } + +void +wFullscreenWindow(WWindow *wwin) +{ + int head; + WMRect rect; + + if (wwin->flags.fullscreen) + return; + + wwin->flags.fullscreen = True; + + wWindowConfigureBorders(wwin); + + ChangeStackingLevel(wwin->frame->core, WMFullscreenLevel); + + wwin->bfs_geometry.x = wwin->frame_x; + wwin->bfs_geometry.y = wwin->frame_y; + wwin->bfs_geometry.width = wwin->frame->core->width; + wwin->bfs_geometry.height = wwin->frame->core->height; + + head = wGetHeadForWindow(wwin); + rect = wGetRectForHead(wwin->screen_ptr, head); + wWindowConfigure(wwin, rect.pos.x, rect.pos.y, + rect.size.width, rect.size.height); + + WMPostNotificationName(WMNChangedState, wwin, "fullscreen"); +} + + +void +wUnfullscreenWindow(WWindow *wwin) +{ + if (!wwin->flags.fullscreen) + return; + + wwin->flags.fullscreen = False; + + if (wwin->frame->core->stacking->window_level == WMFullscreenLevel) { + if (WFLAGP(wwin, sunken)) { + ChangeStackingLevel(wwin->frame->core, WMSunkenLevel); + } else if (WFLAGP(wwin, floating)) { + ChangeStackingLevel(wwin->frame->core, WMFloatingLevel); + } else { + ChangeStackingLevel(wwin->frame->core, WMNormalLevel); + } + } + + wWindowConfigure(wwin, wwin->bfs_geometry.x, wwin->bfs_geometry.y, + wwin->bfs_geometry.width, wwin->bfs_geometry.height); + + wWindowConfigureBorders(wwin); + // seems unnecessary, but also harmless (doesn't generate flicker) -Dan + wFrameWindowPaint(wwin->frame); + + WMPostNotificationName(WMNChangedState, wwin, "fullscreen"); +} + + #ifdef ANIMATIONS static void animateResizeFlip(WScreen *scr, int x, int y, int w, int h, @@ -943,7 +960,11 @@ wIconifyWindow(WWindow *wwin) GrabModeAsync, None, None, CurrentTime); } - if (!wPreferences.disable_miniwindows) { + if (!wPreferences.disable_miniwindows +#ifdef NETWM_HINTS + && !wwin->flags.net_handle_icon +#endif + ) { if (!wwin->flags.icon_moved) { PlaceIcon(wwin->screen_ptr, &wwin->icon_x, &wwin->icon_y, wGetHeadForWindow(wwin)); } @@ -968,7 +989,11 @@ wIconifyWindow(WWindow *wwin) * something before the animation starts (and the server is grabbed) */ XSync(dpy, 0); - if (wPreferences.disable_miniwindows) + if (wPreferences.disable_miniwindows +#ifdef NETWM_HINTS + || wwin->flags.net_handle_icon +#endif + ) wClientSetState(wwin, IconicState, None); else wClientSetState(wwin, IconicState, wwin->icon->icon_win); @@ -979,7 +1004,11 @@ wIconifyWindow(WWindow *wwin) && !wPreferences.no_animations) { int ix, iy, iw, ih; - if (!wPreferences.disable_miniwindows) { + if (!wPreferences.disable_miniwindows +#ifdef NETWM_HINTS + && !wwin->flags.net_handle_icon +#endif + ) { ix = wwin->icon_x; iy = wwin->icon_y; iw = wwin->icon->core->width; @@ -995,6 +1024,14 @@ wIconifyWindow(WWindow *wwin) ih = area.y2 - iy; } else #endif /* KWM_HINTS */ +#ifdef NETWM_HINTS + if (wwin->flags.net_handle_icon) { + ix = wwin->icon_x; + iy = wwin->icon_y; + iw = wwin->icon_w; + ih = wwin->icon_h; + } else +#endif { ix = 0; iy = 0; @@ -1011,7 +1048,11 @@ wIconifyWindow(WWindow *wwin) wwin->flags.skip_next_animation = 0; - if (!wPreferences.disable_miniwindows) { + if (!wPreferences.disable_miniwindows +#ifdef NETWM_HINTS + && !wwin->flags.net_handle_icon +#endif + ) { if (wwin->screen_ptr->current_workspace==wwin->frame->workspace || IS_OMNIPRESENT(wwin) || wPreferences.sticky_icons) @@ -1051,20 +1092,27 @@ wIconifyWindow(WWindow *wwin) #ifdef ANIMATIONS if (!wwin->screen_ptr->flags.startup) { + /* Catch up with events not processed while animation was running */ Window clientwin = wwin->client_win; - XSync(dpy, 0); - processEvents(XPending(dpy)); + ProcessPendingEvents(); - /* the window can disappear while doing the processEvents() */ - if (!wWindowFor(clientwin)) + /* the window can disappear while ProcessPendingEvents() runs */ + if (!wWindowFor(clientwin)) { return; + } } #endif } - - if (wwin->flags.selected && !wPreferences.disable_miniwindows) + /* maybe we want to do this regardless of net_handle_icon + * it seems to me we might break behaviour this way. + */ + if (wwin->flags.selected && !wPreferences.disable_miniwindows +#ifdef NETWM_HINTS + && !wwin->flags.net_handle_icon +#endif + ) wIconSelect(wwin->icon); WMPostNotificationName(WMNChangedState, wwin, "iconify"); @@ -1076,7 +1124,16 @@ wIconifyWindow(WWindow *wwin) void wDeiconifyWindow(WWindow *wwin) { - wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace); +#ifdef NETWM_HINTS + /* we're hiding for show_desktop */ + int netwm_hidden = wwin->flags.net_show_desktop && + wwin->frame->workspace!=wwin->screen_ptr->current_workspace; +#else + int netwm_hidden = False; +#endif + + if (!netwm_hidden) + wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace); if (!wwin->flags.miniaturized) return; @@ -1094,86 +1151,121 @@ wDeiconifyWindow(WWindow *wwin) } wwin->flags.miniaturized = 0; - if (!wwin->flags.shaded) + + if (!netwm_hidden && !wwin->flags.shaded) { wwin->flags.mapped = 1; - - if (!wPreferences.disable_miniwindows && wwin->icon != NULL) { - if (wwin->icon->selected) - wIconSelect(wwin->icon); - - XUnmapWindow(dpy, wwin->icon->core->window); } - wSoundPlay(WSOUND_DEICONIFY); + if (!netwm_hidden || wPreferences.sticky_icons) { + /* maybe we want to do this regardless of net_handle_icon + * it seems to me we might break behaviour this way. + */ + if (!wPreferences.disable_miniwindows +#ifdef NETWM_HINTS + && !wwin->flags.net_handle_icon +#endif + && wwin->icon != NULL) { + if (wwin->icon->selected) + wIconSelect(wwin->icon); + + XUnmapWindow(dpy, wwin->icon->core->window); + } + } + + if (!netwm_hidden) + wSoundPlay(WSOUND_DEICONIFY); /* if the window is in another workspace, do it silently */ + if (!netwm_hidden) { #ifdef ANIMATIONS - if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations - && !wwin->flags.skip_next_animation && wwin->icon != NULL) { - int ix, iy, iw, ih; + if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations + && !wwin->flags.skip_next_animation && wwin->icon != NULL) { + int ix, iy, iw, ih; - if (!wPreferences.disable_miniwindows) { - ix = wwin->icon_x; - iy = wwin->icon_y; - iw = wwin->icon->core->width; - ih = wwin->icon->core->height; - } else { + if (!wPreferences.disable_miniwindows +#ifdef NETWM_HINTS + && !wwin->flags.net_handle_icon +#endif + ) { + ix = wwin->icon_x; + iy = wwin->icon_y; + iw = wwin->icon->core->width; + ih = wwin->icon->core->height; + } else { #ifdef KWM_HINTS - WArea area; + WArea area; - if (wKWMGetIconGeometry(wwin, &area)) { - ix = area.x1; - iy = area.y1; - iw = area.x2 - ix; - ih = area.y2 - iy; - } else + if (wKWMGetIconGeometry(wwin, &area)) { + ix = area.x1; + iy = area.y1; + iw = area.x2 - ix; + ih = area.y2 - iy; + } else #endif /* KWM_HINTS */ - { - ix = 0; - iy = 0; - iw = wwin->screen_ptr->scr_width; - ih = wwin->screen_ptr->scr_height; - } - } - animateResize(wwin->screen_ptr, ix, iy, iw, ih, - wwin->frame_x, wwin->frame_y, - wwin->frame->core->width, wwin->frame->core->height, - False); - } +#ifdef NETWM_HINTS + if (wwin->flags.net_handle_icon) { + ix = wwin->icon_x; + iy = wwin->icon_y; + iw = wwin->icon_w; + ih = wwin->icon_h; + } else +#endif + { + ix = 0; + iy = 0; + iw = wwin->screen_ptr->scr_width; + ih = wwin->screen_ptr->scr_height; + } + } + animateResize(wwin->screen_ptr, ix, iy, iw, ih, + wwin->frame_x, wwin->frame_y, + wwin->frame->core->width, wwin->frame->core->height, + False); + } #endif /* ANIMATIONS */ - wwin->flags.skip_next_animation = 0; - XGrabServer(dpy); - if (!wwin->flags.shaded) { - XMapWindow(dpy, wwin->client_win); + wwin->flags.skip_next_animation = 0; + XGrabServer(dpy); + if (!wwin->flags.shaded) { + XMapWindow(dpy, wwin->client_win); + } + XMapWindow(dpy, wwin->frame->core->window); + wRaiseFrame(wwin->frame->core); + if (!wwin->flags.shaded) { + wClientSetState(wwin, NormalState, None); + } + mapTransientsFor(wwin); } - XMapWindow(dpy, wwin->frame->core->window); - wRaiseFrame(wwin->frame->core); - if (!wwin->flags.shaded) { - wClientSetState(wwin, NormalState, None); - } - mapTransientsFor(wwin); - if (!wPreferences.disable_miniwindows && wwin->icon != NULL) { + if (!wPreferences.disable_miniwindows && wwin->icon != NULL +#ifdef NETWM_HINTS + && !wwin->flags.net_handle_icon +#endif + ) { RemoveFromStackList(wwin->icon->core); /* removeIconGrabs(wwin->icon);*/ wIconDestroy(wwin->icon); wwin->icon = NULL; } - XUngrabServer(dpy); - wSetFocusTo(wwin->screen_ptr, wwin); + if (!netwm_hidden) { + XUngrabServer(dpy); + + wSetFocusTo(wwin->screen_ptr, wwin); #ifdef ANIMATIONS - if (!wwin->screen_ptr->flags.startup) { - Window clientwin = wwin->client_win; + if (!wwin->screen_ptr->flags.startup) { + /* Catch up with events not processed while animation was running */ + Window clientwin = wwin->client_win; - XSync(dpy, 0); - processEvents(XPending(dpy)); + ProcessPendingEvents(); - if (!wWindowFor(clientwin)) - return; - } + /* the window can disappear while ProcessPendingEvents() runs */ + if (!wWindowFor(clientwin)) { + return; + } + } #endif + } if (wPreferences.auto_arrange_icons) { wArrangeIcons(wwin->screen_ptr, True); @@ -1182,7 +1274,8 @@ wDeiconifyWindow(WWindow *wwin) WMPostNotificationName(WMNChangedState, wwin, "iconify"); /* In case we were shaded and iconified, also unshade */ - wUnshadeWindow(wwin); + if (!netwm_hidden) + wUnshadeWindow(wwin); } @@ -1618,9 +1711,9 @@ wArrangeIcons(WScreen *scr, Bool arrangeAll) while (aicon) { if (!aicon->docked) { - /* XXX: can: icon == NULL ? */ - /* The intention here is to place the AppIcon on the head that contains most of the applications _main_ window. */ - /* printf("appicon: %x %x\n", aicon->icon->core->window, aicon->main_window); */ + /* CHECK: can icon be NULL here ? */ + /* The intention here is to place the AppIcon on the head that + * contains most of the applications _main_ window. */ head = wGetHeadForWindow(aicon->icon->owner); if (aicon->x_pos != X || aicon->y_pos != Y) { @@ -1847,7 +1940,7 @@ wSelectWindow(WWindow *wwin, Bool flag) wwin->flags.selected = 1; XSetWindowBorder(dpy, wwin->frame->core->window, scr->white_pixel); - if (WFLAGP(wwin, no_border)) { + if (!HAS_BORDER(wwin)) { XSetWindowBorderWidth(dpy, wwin->frame->core->window, FRAME_BORDER_WIDTH); } @@ -1860,7 +1953,7 @@ wSelectWindow(WWindow *wwin, Bool flag) XSetWindowBorder(dpy, wwin->frame->core->window, scr->frame_border_pixel); - if (WFLAGP(wwin, no_border)) { + if (!HAS_BORDER(wwin)) { XSetWindowBorderWidth(dpy, wwin->frame->core->window, 0); } diff --git a/src/actions.h b/src/actions.h index e3475bfe..bdabdb43 100644 --- a/src/actions.h +++ b/src/actions.h @@ -65,4 +65,8 @@ void wArrangeIcons(WScreen *scr, Bool arrangeAll); void wMakeWindowVisible(WWindow *wwin); +void wFullscreenWindow(WWindow *wwin); +void wUnfullscreenWindow(WWindow *wwin); + + #endif diff --git a/src/appicon.c b/src/appicon.c index 391dae7a..68a67527 100644 --- a/src/appicon.c +++ b/src/appicon.c @@ -407,7 +407,7 @@ setIconCallback(WMenu *menu, WMenuEntry *entry) result = wIconChooserDialog(scr, &file, icon->wm_instance, icon->wm_class); if (result && !icon->destroyed) { - if (file[0]==0) { + if (file && *file==0) { wfree(file); file = NULL; } diff --git a/src/application.c b/src/application.c index fe9b4843..9b6e1872 100644 --- a/src/application.c +++ b/src/application.c @@ -50,6 +50,8 @@ #include "dock.h" #include "wsound.h" +#include "xinerama.h" + /******** Global variables ********/ @@ -123,16 +125,14 @@ findDockIconFor(WDock *dock, Window main_window) static void extractIcon(WWindow *wwin) { - int argc; - char **argv; - - if (!XGetCommand(dpy, wwin->client_win, &argv, &argc) || argc < 1) - return; + char *progname; - wApplicationExtractDirPackIcon(wwin->screen_ptr,argv[0], - wwin->wm_instance, - wwin->wm_class); - XFreeStringList(argv); + progname = GetProgramNameForWindow(wwin->client_win); + if (progname) { + wApplicationExtractDirPackIcon(wwin->screen_ptr, progname, + wwin->wm_instance, wwin->wm_class); + wfree(progname); + } } @@ -172,7 +172,7 @@ saveIconNameFor(char *iconPath, char *wm_instance, char *wm_class) val = WMGetFromPLDictionary(adict, iconk); } else { /* no dictionary for app, so create one */ - adict = WMCreatePLDictionary(NULL, NULL, NULL); + adict = WMCreatePLDictionary(NULL, NULL); WMPutInPLDictionary(dict, key, adict); WMReleasePropList(adict); val = NULL; @@ -246,8 +246,10 @@ extractClientIcon(WAppIcon *icon) WApplication* -wApplicationCreate(WScreen *scr, Window main_window) +wApplicationCreate(WWindow *wwin) { + WScreen *scr = wwin->screen_ptr; + Window main_window = wwin->main_window; WApplication *wapp; WWindow *leader; @@ -295,6 +297,11 @@ wApplicationCreate(WScreen *scr, Window main_window) return NULL; } + wapp->main_window_desc->fake_group = wwin->fake_group; +#ifdef NETWM_HINTS + wapp->main_window_desc->net_icon_image = RRetainImage(wwin->net_icon_image); +#endif + extractIcon(wapp->main_window_desc); leader = wWindowFor(main_window); diff --git a/src/application.h b/src/application.h index f064ffee..c867298e 100644 --- a/src/application.h +++ b/src/application.h @@ -50,7 +50,7 @@ typedef struct WApplication { } WApplication; -WApplication *wApplicationCreate(WScreen *scr, Window main_window); +WApplication *wApplicationCreate(struct WWindow *wwin); void wApplicationDestroy(WApplication *wapp); WApplication *wApplicationOf(Window window); diff --git a/src/client.c b/src/client.c index 0cba6a44..96b5d90e 100644 --- a/src/client.c +++ b/src/client.c @@ -46,6 +46,9 @@ #ifdef KWM_HINTS #include "kwm.h" #endif +#ifdef NETWM_HINTS +# include "wmspec.h" +#endif /****** Global Variables ******/ @@ -239,7 +242,7 @@ wClientConfigure(WWindow *wwin, XConfigureRequestEvent *xcre) /* If the window is shaded, wrong height will be set for the window */ if (xcre->value_mask & CWX) { nx = xcre->x; - if (!WFLAGP(wwin, no_border)) + if (HAS_BORDER(wwin)) nx -= FRAME_BORDER_WIDTH; } else @@ -247,7 +250,7 @@ wClientConfigure(WWindow *wwin, XConfigureRequestEvent *xcre) if (xcre->value_mask & CWY) { ny = xcre->y - ((ofs_y < 0) ? 0 : wwin->frame->top_width); - if (!WFLAGP(wwin, no_border)) + if (HAS_BORDER(wwin)) ny -= FRAME_BORDER_WIDTH; } else @@ -353,22 +356,17 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) case XA_WM_COMMAND: if (wwin->main_window!=None) { WApplication *wapp = wApplicationOf(wwin->main_window); - char **argv; - int argc; + char *command; - if (!wapp || !wapp->app_icon) + if (!wapp || !wapp->app_icon || wapp->app_icon->docked) break; - if (XGetCommand(dpy, wwin->main_window, &argv, &argc)) { - if (argc > 0 && argv != NULL) { - if (wapp->app_icon->command) - wfree(wapp->app_icon->command); - wapp->app_icon->command = wtokenjoin(argv, argc); - } - if (argv) { - XFreeStringList(argv); - } - } + command = GetCommandForWindow(wwin->main_window); + if (command) { + if (wapp->app_icon->command) + wfree(wapp->app_icon->command); + wapp->app_icon->command = command; + } } break; @@ -457,7 +455,7 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) wApplicationDestroy(wApplicationOf(wwin->main_window)); wwin->main_window = wwin->client_leader; wwin->group_id = None; - wApplicationCreate(wwin->screen_ptr, wwin->main_window); + wApplicationCreate(wwin); break; /* 1,2,4 - change leader to new value of window_group */ @@ -467,7 +465,7 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) wApplicationDestroy(wApplicationOf(wwin->main_window)); wwin->main_window = new_hints->window_group; wwin->group_id = wwin->main_window; - wApplicationCreate(wwin->screen_ptr, wwin->main_window); + wApplicationCreate(wwin); break; /* 5 - destroy application */ @@ -481,7 +479,7 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) case 6: wwin->main_window = new_hints->window_group; wwin->group_id = wwin->main_window; - wApplicationCreate(wwin->screen_ptr, wwin->main_window); + wApplicationCreate(wwin); break; /* 7 - we have a fake window group id, so just ignore anything else */ case 7: @@ -630,7 +628,7 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) else foo->main_window = None; if (foo->main_window) { - wapp = wApplicationCreate(scr, foo->main_window); + wapp = wApplicationCreate(foo); } } foo = foo->prev; @@ -665,11 +663,18 @@ wClientCheckProperty(WWindow *wwin, XPropertyEvent *event) XFree(attr); } else { +#if defined(KWM_HINTS) || defined(NETWM_HINTS) + Bool done = False; +#endif #ifdef KWM_HINTS - Bool done; - - done = wKWMCheckClientHintChange(wwin, event); + if (!done) + done = wKWMCheckClientHintChange(wwin, event); #endif /* KWM_HINTS */ +#ifdef NETWM_HINTS + if (!done) { + done = wNETWMCheckClientHintChange(wwin, event); + } +#endif } } } diff --git a/src/cycling.c b/src/cycling.c index 8e0c98d2..e5ace829 100644 --- a/src/cycling.c +++ b/src/cycling.c @@ -198,7 +198,9 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next) if (hasModifier) { keymap = XGetModifierMapping(dpy); - +#ifdef DEBUG + printf("Grabbing keyboard\n"); +#endif XGrabKeyboard(dpy, scr->root_win, False, GrabModeAsync, GrabModeAsync, CurrentTime); } @@ -223,11 +225,6 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next) wWindowFocus(newFocused, scr->focused_window); oldFocused = newFocused; - if (hasModifier) - done = False; - else - done = True; - #if 0 if (wPreferences.popup_switchmenu && (!scr->switch_menu || !scr->switch_menu->flags.mapped)) { @@ -236,8 +233,9 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next) openedSwitchMenu = True; } #endif - while (!done) { - WMMaskEvent(dpy,KeyPressMask|KeyReleaseMask|ExposureMask, &ev); + + while (hasModifier && !done) { + WMMaskEvent(dpy, KeyPressMask|KeyReleaseMask|ExposureMask, &ev); if (ev.type != KeyRelease && ev.type != KeyPress) { WMHandleEvent(&ev); @@ -247,7 +245,10 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next) modifiers = ev.xkey.state & ValidModMask; if (ev.type == KeyPress) { - if (wKeyBindings[WKBD_FOCUSNEXT].keycode == ev.xkey.keycode +#ifdef DEBUG + printf("Got key press\n"); +#endif + if (wKeyBindings[WKBD_FOCUSNEXT].keycode == ev.xkey.keycode && wKeyBindings[WKBD_FOCUSNEXT].modifier == modifiers) { newFocused = nextToFocusAfter(newFocused); @@ -274,12 +275,18 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next) } } else { +#ifdef DEBUG + printf("Got something else\n"); +#endif somethingElse = True; done = True; } } else if (ev.type == KeyRelease) { int i; +#ifdef DEBUG + printf("Got key release\n"); +#endif for (i = 0; i < 8 * keymap->max_keypermod; i++) { if (keymap->modifiermap[i] == ev.xkey.keycode && wKeyBindings[WKBD_FOCUSNEXT].modifier @@ -294,6 +301,9 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next) XFreeModifiermap(keymap); if (hasModifier) { +#ifdef DEBUG + printf("Ungrabbing keyboard\n"); +#endif XUngrabKeyboard(dpy, CurrentTime); } wSetFocusTo(scr, newFocused); diff --git a/src/defaults.c b/src/defaults.c index cb16954f..de2c296e 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -155,6 +155,9 @@ static int setUTitleBack(); static int setResizebarBack(); static int setWorkspaceBack(); static int setWorkspaceSpecificBack(); +#ifdef VIRTUAL_DESKTOP +static int setVirtualEdgeThickness(); +#endif static int setMenuTitleColor(); static int setMenuTextColor(); static int setMenuDisabledColor(); @@ -436,22 +439,34 @@ WDefaultEntry optionList[] = { }, #ifdef VIRTUAL_DESKTOP {"VirtualEdgeThickness", "1", NULL, - &wPreferences.vedge_thickness, getInt, NULL + &wPreferences.vedge_thickness, getInt, setVirtualEdgeThickness }, {"VirtualEdgeExtendSpace", "0", NULL, &wPreferences.vedge_bordersize, getInt, NULL }, - {"VirtualEdgeHorizonScrollSpeed", "1", NULL, + {"VirtualEdgeHorizonScrollSpeed", "30", NULL, &wPreferences.vedge_hscrollspeed, getInt, NULL }, - {"VirtualEdgeVerticalScrollSpeed", "1", NULL, + {"VirtualEdgeVerticalScrollSpeed", "30", NULL, &wPreferences.vedge_vscrollspeed, getInt, NULL }, - {"VirtualEdgeMaximumWidth", "3000", NULL, - &wPreferences.vedge_maxwidth, getInt, NULL + {"VirtualEdgeResistance", "30", NULL, + &wPreferences.vedge_resistance, getInt, NULL }, - {"VirtualEdgeMaximumHeight", "3000", NULL, - &wPreferences.vedge_maxheight, getInt, NULL + {"VirtualEdgeAttraction", "30", NULL, + &wPreferences.vedge_attraction, getInt, NULL + }, + {"VirtualEdgeLeftKey", "None", (void*)WKBD_VDESK_LEFT, + NULL, getKeybind, setKeyGrab + }, + {"VirtualEdgeRightKey", "None", (void*)WKBD_VDESK_RIGHT, + NULL, getKeybind, setKeyGrab + }, + {"VirtualEdgeUpKey", "None", (void*)WKBD_VDESK_UP, + NULL, getKeybind, setKeyGrab + }, + {"VirtualEdgeDownKey", "None", (void*)WKBD_VDESK_DOWN, + NULL, getKeybind, setKeyGrab }, #endif {"StickyIcons", "NO", NULL, @@ -3352,6 +3367,16 @@ setWorkspaceBack(WScreen *scr, WDefaultEntry *entry, WMPropList *value, } +#ifdef VIRTUAL_DESKTOP +static int +setVirtualEdgeThickness(WScreen *scr, WDefaultEntry *entry, XColor *color, long index) +{ + wWorkspaceUpdateEdge(scr); + return 0; +} +#endif + + static int setWidgetColor(WScreen *scr, WDefaultEntry *entry, WTexture **texture, void *foo) { diff --git a/src/dialog.c b/src/dialog.c index 43a65dc6..418ec5e9 100644 --- a/src/dialog.c +++ b/src/dialog.c @@ -785,7 +785,7 @@ wIconChooserDialog(WScreen *scr, char **file, char *instance, char *class) /* check if the file the user selected is not the one that * would be loaded by default with the current search path */ *file = WMGetListSelectedItem(panel->iconList)->text; - if ((*file)[0]==0) { + if (**file==0) { wfree(*file); *file = NULL; } else { @@ -804,6 +804,8 @@ wIconChooserDialog(WScreen *scr, char **file, char *instance, char *class) *file = NULL; } + result = panel->result; + WMReleaseFont(panel->normalfont); WMUnmapWidget(panel->win); @@ -812,8 +814,6 @@ wIconChooserDialog(WScreen *scr, char **file, char *instance, char *class) wUnmanageWindow(wwin, False, False); - result= panel->result; - wfree(panel); XDestroyWindow(dpy, parent); @@ -862,8 +862,8 @@ typedef struct { #define COPYRIGHT_TEXT \ - "Copyright © 1997-2004 Alfredo K. Kojima \n"\ - "Copyright © 1998-2004 Dan Pascu " + "Copyright \xc2\xa9 1997-2004 Alfredo K. Kojima \n"\ + "Copyright \xc2\xa9 1998-2004 Dan Pascu " @@ -1314,8 +1314,6 @@ wShowInfoPanel(WScreen *scr) WMMoveWidget(panel->copyrL, 15, 185); WMSetLabelTextAlignment(panel->copyrL, WALeft); WMSetLabelText(panel->copyrL, COPYRIGHT_TEXT); - /* we want the (c) character in the font, so don't use a FontSet here */ - // fix this -Dan font = WMCreateFontWithFlags(scr->wmscreen, "SystemFont-11", WFNormalFont); font = WMSystemFontOfSize(scr->wmscreen, 11); if (font) { WMSetLabelFont(panel->copyrL, font); @@ -1368,7 +1366,7 @@ wShowInfoPanel(WScreen *scr) strbuf = wstrappend(strbuf, _("\nAdditional support for: ")); { - char *list[8]; + char *list[9]; char buf[80]; int j = 0; @@ -1384,6 +1382,9 @@ wShowInfoPanel(WScreen *scr) #ifdef OLWM_HINTS list[j++] = "OLWM"; #endif +#ifdef NETWM_HINTS + list[j++] = "WMSPEC"; +#endif buf[0] = 0; for (i = 0; i < j; i++) { @@ -1408,6 +1409,23 @@ wShowInfoPanel(WScreen *scr) strbuf = wstrappend(strbuf, _("; Antialiased text")); #endif +#ifdef VIRTUAL_DESKTOP + strbuf = wstrappend(strbuf, _("; VirtualDesktop")); +#endif + +#ifdef XINERAMA + strbuf = wstrappend(strbuf, _("\n")); +#ifdef SOLARIS_XINERAMA + strbuf = wstrappend(strbuf, _("Solaris ")); +#endif + strbuf = wstrappend(strbuf, _("Xinerama: ")); + { + char tmp[128]; + snprintf(tmp, sizeof(tmp)-1, "%d heads found.", scr->xine_info.count); + strbuf = wstrappend(strbuf, tmp); + } +#endif + panel->infoL = WMCreateLabel(panel->win); WMResizeWidget(panel->infoL, 350, 75); diff --git a/src/dock.c b/src/dock.c index daed30d2..c89fb275 100644 --- a/src/dock.c +++ b/src/dock.c @@ -956,9 +956,8 @@ launchDockedApplication(WAppIcon *btn, Bool withSelection) btn->drop_launch = 0; btn->paste_launch = withSelection; scr->last_dock = btn->dock; - btn->pid = execCommand(btn, - withSelection ? btn->paste_command : btn->command, - NULL); + btn->pid = execCommand(btn, (withSelection ? btn->paste_command : + btn->command), NULL); if (btn->pid>0) { if (btn->buggy_app) { /* give feedback that the app was launched */ @@ -972,8 +971,9 @@ launchDockedApplication(WAppIcon *btn, Bool withSelection) } else { wwarning(_("could not launch application %s\n"), btn->command); btn->launching = 0; - if (!btn->relaunching) + if (!btn->relaunching) { btn->running = 0; + } } } } @@ -1386,13 +1386,13 @@ make_icon_state(WAppIcon *btn) position = WMCreatePLString(buffer); node = WMCreatePLDictionary(dCommand, command, - dName, name, - dAutoLaunch, autolaunch, - dLock, lock, - dForced, forced, - dBuggyApplication, buggy, - dPosition, position, - NULL); + dName, name, + dAutoLaunch, autolaunch, + dLock, lock, + dForced, forced, + dBuggyApplication, buggy, + dPosition, position, + NULL); WMReleasePropList(command); WMReleasePropList(name); WMReleasePropList(position); @@ -1450,8 +1450,7 @@ dockSaveState(WDock *dock) } } - dock_state = WMCreatePLDictionary(dApplications, list, - NULL); + dock_state = WMCreatePLDictionary(dApplications, list, NULL); if (dock->type == WM_DOCK) { snprintf(buffer, sizeof(buffer), "Applications%i", dock->screen_ptr->scr_height); @@ -1512,9 +1511,8 @@ wDockSaveState(WScreen *scr, WMPropList *old_state) if (strncasecmp(WMGetFromPLString(tmp), "applications", 12) == 0 && !WMGetFromPLDictionary(dock_state, tmp)) { - WMPutInPLDictionary(dock_state, - tmp, - WMGetFromPLDictionary(old_state, tmp)); + WMPutInPLDictionary(dock_state, tmp, + WMGetFromPLDictionary(old_state, tmp)); } } WMReleasePropList(keys); @@ -1774,9 +1772,9 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) value = WMGetFromPLDictionary(dock_state, dPosition); if (value) { - if (!WMIsPLString(value)) + if (!WMIsPLString(value)) { COMPLAIN("Position"); - else { + } else { WMRect rect; int flags; @@ -1795,12 +1793,13 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) wScreenKeepInside(scr, &x, &dock->y_pos, ICON_SIZE, ICON_SIZE); } - /* This is no more needed. ??? */ + /* Is this needed any more? */ if (type == WM_CLIP) { - if (dock->x_pos < 0) + if (dock->x_pos < 0) { dock->x_pos = 0; - else if (dock->x_pos > scr->scr_width-ICON_SIZE) + } else if (dock->x_pos > scr->scr_width-ICON_SIZE) { dock->x_pos = scr->scr_width-ICON_SIZE; + } } else { if (dock->x_pos >= 0) { dock->x_pos = DOCK_EXTRA_SPACE; @@ -1820,11 +1819,12 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) value = WMGetFromPLDictionary(dock_state, dLowered); if (value) { - if (!WMIsPLString(value)) + if (!WMIsPLString(value)) { COMPLAIN("Lowered"); - else { - if (strcasecmp(WMGetFromPLString(value), "YES")==0) + } else { + if (strcasecmp(WMGetFromPLString(value), "YES")==0) { dock->lowered = 1; + } } } @@ -1836,11 +1836,12 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) value = WMGetFromPLDictionary(dock_state, dCollapsed); if (value) { - if (!WMIsPLString(value)) + if (!WMIsPLString(value)) { COMPLAIN("Collapsed"); - else { - if (strcasecmp(WMGetFromPLString(value), "YES")==0) + } else { + if (strcasecmp(WMGetFromPLString(value), "YES")==0) { dock->collapsed = 1; + } } } @@ -1850,9 +1851,9 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) value = WMGetFromPLDictionary(dock_state, dAutoCollapse); if (value) { - if (!WMIsPLString(value)) + if (!WMIsPLString(value)) { COMPLAIN("AutoCollapse"); - else { + } else { if (strcasecmp(WMGetFromPLString(value), "YES")==0) { dock->auto_collapse = 1; dock->collapsed = 1; @@ -1866,9 +1867,9 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) value = WMGetFromPLDictionary(dock_state, dAutoRaiseLower); if (value) { - if (!WMIsPLString(value)) + if (!WMIsPLString(value)) { COMPLAIN("AutoRaiseLower"); - else { + } else { if (strcasecmp(WMGetFromPLString(value), "YES")==0) { dock->auto_raise_lower = 1; } @@ -1882,11 +1883,12 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) value = WMGetFromPLDictionary(dock_state, dAutoAttractIcons); if (value) { - if (!WMIsPLString(value)) + if (!WMIsPLString(value)) { COMPLAIN("AutoAttractIcons"); - else { - if (strcasecmp(WMGetFromPLString(value), "YES")==0) + } else { + if (strcasecmp(WMGetFromPLString(value), "YES")==0) { dock->attract_icons = 1; + } } } @@ -2136,21 +2138,19 @@ Bool wDockAttachIcon(WDock *dock, WAppIcon *icon, int x, int y) { WWindow *wwin; - char **argv; - int argc; int index; wwin = icon->icon->owner; if (icon->command==NULL) { - icon->editing = 0; - if (XGetCommand(dpy, wwin->client_win, &argv, &argc) && argc>0) { + char *command; - icon->command = wtokenjoin(argv, argc); - XFreeStringList(argv); + icon->editing = 0; + + command = GetCommandForWindow(wwin->client_win); + if (command) { + icon->command = command; } else { - char *command=NULL; - -/* icon->forced_dock = 1;*/ + /* icon->forced_dock = 1;*/ if (dock->type!=WM_CLIP || !icon->attracted) { icon->editing = 1; if (wInputDialog(dock->screen_ptr, _("Dock Icon"), @@ -2181,7 +2181,7 @@ wDockAttachIcon(WDock *dock, WAppIcon *icon, int x, int y) } } } - } + } } else { icon->editing = 0; } @@ -2266,8 +2266,7 @@ Bool moveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y) { WWindow *wwin; - char **argv; - int argc; + char *command; int index; if (src == dest) @@ -2285,15 +2284,12 @@ moveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y) * moved icons it applies. -Dan */ if ((dest->type==WM_DOCK /*|| dest->keep_attracted*/) && icon->command==NULL) { - if (XGetCommand(dpy, wwin->client_win, &argv, &argc) && argc>0) { - - icon->command = wtokenjoin(argv, argc); - XFreeStringList(argv); + command = GetCommandForWindow(wwin->client_win); + if (command) { + icon->command = command; } else { - char *command=NULL; - icon->editing = 1; -/* icon->forced_dock = 1;*/ + /* icon->forced_dock = 1;*/ if (wInputDialog(src->screen_ptr, _("Dock Icon"), _("Type the command used to launch the application"), &command)) { @@ -3177,22 +3173,15 @@ wDockTrackWindowLaunch(WDock *dock, Window window) Bool found = False; char *command = NULL; - { - int argc; - char **argv; - - if (XGetCommand(dpy, window, &argv, &argc)) { - if (argc > 0 && argv != NULL) - command = wtokenjoin(argv, argc); - if (argv) { - XFreeStringList(argv); - } - } - } + command = GetCommandForWindow(window); if (!PropGetWMClass(window, &wm_class, &wm_instance) || - (!wm_class && !wm_instance)) - return; + (!wm_class && !wm_instance)) { + + if (command) + wfree(command); + return; + } retry: for (i=0; imax_icons; i++) { @@ -3232,9 +3221,9 @@ retry: icon->forced_dock = 1; icon->running = 0; } - if (!icon->forced_dock) - icon->main_window = window; - + if (!icon->forced_dock) { + icon->main_window = window; + } } found = True; if (!wPreferences.no_animations && !icon->launching && @@ -3598,8 +3587,7 @@ iconDblClick(WObjDescriptor *desc, XEvent *event) wWorkspaceChange(dock->screen_ptr, wapp->last_workspace); } - wUnhideApplication(wapp, event->xbutton.button==Button2, - unhideHere); + wUnhideApplication(wapp, event->xbutton.button==Button2, unhideHere); if (event->xbutton.state & MOD_MASK) { wHideOtherApplications(btn->icon->owner); @@ -3620,9 +3608,8 @@ iconDblClick(WObjDescriptor *desc, XEvent *event) (!btn->running || (event->xbutton.state & ControlMask))) { launchDockedApplication(btn, False); } - } else if (btn->xindex == 0 && btn->yindex == 0 - && btn->dock->type == WM_DOCK) { - + } else if (btn->xindex==0 && btn->yindex==0 && + btn->dock->type==WM_DOCK) { wShowGNUstepPanel(dock->screen_ptr); } } diff --git a/src/event.c b/src/event.c index 484de816..d5cab4dc 100644 --- a/src/event.c +++ b/src/event.c @@ -66,9 +66,13 @@ #ifdef KWM_HINTS # include "kwm.h" #endif +#ifdef NETWM_HINTS +# include "wmspec.h" +#endif /******** Global Variables **********/ extern XContext wWinContext; +extern XContext wVEdgeContext; extern Cursor wCursor[WCUR_LAST]; @@ -323,7 +327,7 @@ void EventLoop() { XEvent event; - + for(;;) { WMNextEvent(dpy, &event); WMHandleEvent(&event); @@ -331,6 +335,39 @@ EventLoop() } +/* + *---------------------------------------------------------------------- + * ProcessPendingEvents -- + * Processes the events that are currently pending (at the time + * this function is called) in the display's queue. + * + * Returns: + * After the pending events that were present at the function call + * are processed. + * + * Side effects: + * Many -- whatever handling events may involve. + * + *---------------------------------------------------------------------- + */ +void +ProcessPendingEvents() +{ + XEvent event; + int count; + + XSync(dpy, False); + + /* Take a snapshot of the event count in the queue */ + count = XPending(dpy); + + while (count>0 && XPending(dpy)) { + WMNextEvent(dpy, &event); + WMHandleEvent(&event); + count--; + } +} + Bool IsDoubleClick(WScreen *scr, XEvent *event) @@ -478,7 +515,7 @@ handleMapRequest(XEvent *ev) Window window = ev->xmaprequest.window; #ifdef DEBUG - L("got map request for %x\n", (unsigned)window); + printf("got map request for %x\n", (unsigned)window); #endif if ((wwin = wWindowFor(window))) { if (wwin->flags.shaded) { @@ -553,7 +590,7 @@ handleDestroyNotify(XEvent *event) int index; #ifdef DEBUG - L("got destroy notify"); + printf("got destroy notify\n"); #endif wwin = wWindowFor(window); if (wwin) { @@ -607,7 +644,7 @@ handleExpose(XEvent *event) XEvent ev; #ifdef DEBUG - L("got expose"); + printf("got expose\n"); #endif while (XCheckTypedWindowEvent(dpy, event->xexpose.window, Expose, &ev)); @@ -662,7 +699,7 @@ handleButtonPress(XEvent *event) WScreen *scr; #ifdef DEBUG - L("got button press"); + printf("got button press\n"); #endif scr = wScreenForRootWindow(event->xbutton.root); @@ -749,7 +786,7 @@ handleMapNotify(XEvent *event) { WWindow *wwin; #ifdef DEBUG - L("got map"); + printf("got map\n"); #endif wwin = wWindowFor(event->xmap.event); if (wwin && wwin->client_win == event->xmap.event) { @@ -772,7 +809,7 @@ handleUnmapNotify(XEvent *event) XEvent ev; Bool withdraw = False; #ifdef DEBUG - L("got unmap"); + printf("got unmap\n"); #endif /* only process windows with StructureNotify selected * (ignore SubstructureNotify) */ @@ -824,7 +861,7 @@ handleConfigureRequest(XEvent *event) { WWindow *wwin; #ifdef DEBUG - L("got configure request"); + printf("got configure request\n"); #endif if (!(wwin=wWindowFor(event->xconfigurerequest.window))) { /* @@ -847,7 +884,7 @@ handlePropertyNotify(XEvent *event) unsigned int ju; WScreen *scr; #ifdef DEBUG - L("got property notify"); + printf("got property notify\n"); #endif if ((wwin=wWindowFor(event->xproperty.window))) { if (!XGetGeometry(dpy, wwin->client_win, &jr, &ji, &ji, @@ -876,7 +913,7 @@ handleClientMessage(XEvent *event) WWindow *wwin; WObjDescriptor *desc; #ifdef DEBUG - L("got client message"); + printf("got client message\n"); #endif /* handle transition from Normal to Iconic state */ if (event->xclient.message_type == _XA_WM_CHANGE_STATE @@ -962,6 +999,10 @@ handleClientMessage(XEvent *event) wFrameWindowChangeState(wwin->frame, WS_FOCUSED); break; } +#ifdef NETWM_HINTS + } else if (wNETWMProcessClientMessage(&event->xclient)) { + /* do nothing */ +#endif #ifdef GNOME_STUFF } else if (wGNOMEProcessClientMessage(&event->xclient)) { /* do nothing */ @@ -1035,34 +1076,19 @@ handleEnterNotify(XEvent *event) { WWindow *wwin; WObjDescriptor *desc = NULL; +#ifdef VIRTUAL_DESKTOP + void (*vdHandler)(XEvent * event); +#endif XEvent ev; WScreen *scr = wScreenForRootWindow(event->xcrossing.root); #ifdef DEBUG - L("got enter notify"); + printf("got enter notify\n"); #endif #ifdef VIRTUAL_DESKTOP - /* TODO: acceleration code */ - if (wPreferences.vedge_thickness) { - int x,y; - if (event->xcrossing.window == scr->virtual_edge_r) { - XWarpPointer(dpy, None, scr->root_win, 0,0,0,0, scr->scr_width - wPreferences.vedge_thickness - 1, event->xcrossing.y_root); - wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); - wWorkspaceSetViewPort(scr, scr->current_workspace, x + VIRTUALEDGE_SCROLL_HSTEP, y); - } else if (event->xcrossing.window == scr->virtual_edge_l) { - XWarpPointer(dpy, None, scr->root_win, 0,0,0,0, wPreferences.vedge_thickness + 1, event->xcrossing.y_root); - wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); - wWorkspaceSetViewPort(scr, scr->current_workspace, x - VIRTUALEDGE_SCROLL_HSTEP, y); - } else if (event->xcrossing.window == scr->virtual_edge_u) { - XWarpPointer(dpy, None, scr->root_win, 0,0,0,0, event->xcrossing.x_root, wPreferences.vedge_thickness + 1); - wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); - wWorkspaceSetViewPort(scr, scr->current_workspace, x, y - VIRTUALEDGE_SCROLL_VSTEP); - } else if (event->xcrossing.window == scr->virtual_edge_d) { - printf("enter bottom\n"); - XWarpPointer(dpy, None, scr->root_win, 0,0,0,0, event->xcrossing.x_root, scr->scr_height - wPreferences.vedge_thickness - 1); - wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); - wWorkspaceSetViewPort(scr, scr->current_workspace, x, y + VIRTUALEDGE_SCROLL_VSTEP); - } + if (XFindContext(dpy, event->xcrossing.window, wVEdgeContext, + (XPointer *)&vdHandler)!=XCNOENT) { + (*vdHandler)( event); } #endif @@ -1178,7 +1204,7 @@ handleShapeNotify(XEvent *event) WWindow *wwin; XEvent ev; #ifdef DEBUG - L("got shape notify"); + printf("got shape notify\n"); #endif while (XCheckTypedWindowEvent(dpy, shev->window, event->type, &ev)) { XShapeEvent *sev = (XShapeEvent*)&ev; @@ -1446,7 +1472,7 @@ handleKeyPress(XEvent *event) } break; case WKBD_MAXIMIZE: - if (ISMAPPED(wwin) && ISFOCUSED(wwin) && !WFLAGP(wwin, no_resizable)) { + if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) { int newdir = (MAX_VERTICAL|MAX_HORIZONTAL); CloseWindowMenu(scr); @@ -1459,7 +1485,7 @@ handleKeyPress(XEvent *event) } break; case WKBD_VMAXIMIZE: - if (ISMAPPED(wwin) && ISFOCUSED(wwin) && !WFLAGP(wwin, no_resizable)) { + if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) { int newdir = (MAX_VERTICAL ^ wwin->flags.maximized); CloseWindowMenu(scr); @@ -1472,7 +1498,7 @@ handleKeyPress(XEvent *event) } break; case WKBD_HMAXIMIZE: - if (ISMAPPED(wwin) && ISFOCUSED(wwin) && !WFLAGP(wwin, no_resizable)) { + if (ISMAPPED(wwin) && ISFOCUSED(wwin) && IS_RESIZABLE(wwin)) { int newdir = (MAX_HORIZONTAL ^ wwin->flags.maximized); CloseWindowMenu(scr); @@ -1515,7 +1541,8 @@ handleKeyPress(XEvent *event) } break; case WKBD_MOVERESIZE: - if (ISMAPPED(wwin) && ISFOCUSED(wwin)) { + if (ISMAPPED(wwin) && ISFOCUSED(wwin) && + (IS_RESIZABLE(wwin) || IS_MOVABLE(wwin))) { CloseWindowMenu(scr); wKeyboardMoveResizeWindow(wwin); @@ -1718,6 +1745,23 @@ handleKeyPress(XEvent *event) } break; #endif /* KEEP_XKB_LOCK_STATUS */ +#ifdef VIRTUAL_DESKTOP + case WKBD_VDESK_LEFT: + wWorkspaceKeyboardMoveDesktop(scr, VEC_LEFT); + break; + + case WKBD_VDESK_RIGHT: + wWorkspaceKeyboardMoveDesktop(scr, VEC_RIGHT); + break; + + case WKBD_VDESK_UP: + wWorkspaceKeyboardMoveDesktop(scr, VEC_UP); + break; + + case WKBD_VDESK_DOWN: + wWorkspaceKeyboardMoveDesktop(scr, VEC_DOWN); + break; +#endif } } @@ -1739,7 +1783,7 @@ handleMotionNotify(XEvent *event) p.y >= (rect.pos.y + rect.size.height - 2)) { WMenu *menu; #ifdef DEBUG - L("pointer at screen edge"); + printf("pointer at screen edge\n"); #endif menu = wMenuUnderPointer(scr); if (menu!=NULL) @@ -1773,13 +1817,13 @@ handleMotionNotify(XEvent *event) && event->xmotion.x_root >= wwin->frame_x && event->xmotion.x_root <= wwin->frame_x + wwin->frame->core->width) { - if (!WFLAGP(wwin, no_titlebar) + if (HAS_BORDER(wwin) && wwin->frame_y <= - wwin->frame->top_width) { wWindowMove(wwin, wwin->frame_x, 0); wwin->flags.dragged_while_fmaximized = 0; - } else if (!WFLAGP(wwin, no_resizebar) + } else if (HAS_RESIZEBAR(wwin) && wwin->frame_y + wwin->frame->core->height >= scr->scr_height + wwin->frame->bottom_width) { diff --git a/src/framewin.c b/src/framewin.c index ce64c223..8e32326f 100644 --- a/src/framewin.c +++ b/src/framewin.c @@ -1488,11 +1488,13 @@ titlebarMouseDown(WObjDescriptor *desc, XEvent *event) WCoreWindow *titlebar = desc->self; if (IsDoubleClick(fwin->core->screen_ptr, event)) { - if (fwin->on_dblclick_titlebar) - (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event); + if (fwin->on_dblclick_titlebar) { + (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event); + } } else { - if (fwin->on_mousedown_titlebar) - (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event); + if (fwin->on_mousedown_titlebar) { + (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event); + } } } @@ -1534,8 +1536,9 @@ buttonMouseDown(WObjDescriptor *desc, XEvent *event) } #ifdef XKB_BUTTON_HINT if (button == fwin->language_button) { - if (!wPreferences.modelock) return; - image = fwin->languagebutton_image; + if (!wPreferences.modelock) + return; + image = fwin->languagebutton_image; } #endif diff --git a/src/funcs.h b/src/funcs.h index 2ecc6c71..86dc4cc5 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -152,6 +152,18 @@ void ExecExitScript(); Bool wFetchName(Display *dpy, Window win, char **winname); Bool wGetIconName(Display *dpy, Window win, char **iconname); +/* Free returned string it when done. (applies to the next 2 functions) */ +char* GetCommandForWindow(Window win); +char* GetProgramNameForWindow(Window win); + +Bool GetCommandForPid(int pid, char ***argv, int *argc); + +#ifdef NETWM_HINTS +#include "wmspec.h" +#define GetPidForWindow(win) wNETWMGetPidForWindow(win) +#else +int GetPidForWindow(Window win); +#endif #endif diff --git a/src/icon.c b/src/icon.c index fc5333cc..86efbb03 100644 --- a/src/icon.c +++ b/src/icon.c @@ -165,6 +165,11 @@ wIconCreate(WWindow *wwin) icon->show_title = 0; #else icon->show_title = 1; +#endif +#ifdef NETWM_HINTS + if (!icon->image && !WFLAGP(wwin, always_user_icon)) + icon->image = RRetainImage(wwin->net_icon_image); + if (!icon->image) #endif icon->image = wDefaultGetImage(scr, wwin->wm_instance, wwin->wm_class); @@ -631,7 +636,11 @@ wIconUpdate(WIcon *icon) icon->pixmap = None; - if (wwin && WFLAGP(wwin, always_user_icon)) + if (wwin && (WFLAGP(wwin, always_user_icon) +#ifdef NETWM_HINTS + || wwin->net_icon_image +#endif + )) goto user_icon; /* use client specified icon window */ diff --git a/src/keybind.h b/src/keybind.h index b2f0aef7..90004e1d 100644 --- a/src/keybind.h +++ b/src/keybind.h @@ -79,11 +79,21 @@ #define WKBD_SWITCH_SCREEN 45 #ifdef KEEP_XKB_LOCK_STATUS -# define WKBD_TOGGLE 46 -# define WKBD_LAST 47 +# define WKBD_TOGGLE 46 +# define WKBD_TMP 47 #else -# define WKBD_LAST 46 -#endif /* KEEP_XKB_LOCK_STATUS */ +# define WKBD_TMP 46 +#endif + +#ifdef VIRTUAL_DESKTOP +# define WKBD_VDESK_LEFT WKBD_TMP +# define WKBD_VDESK_RIGHT (WKBD_TMP+1) +# define WKBD_VDESK_UP (WKBD_TMP+2) +# define WKBD_VDESK_DOWN (WKBD_TMP+3) +# define WKBD_LAST (WKBD_TMP+4) +#else +# define WKBD_LAST WKBD_TMP +#endif /* VIRTUAL_DESKTOP */ typedef struct WShortKey { diff --git a/src/main.c b/src/main.c index 8f2103db..9f6a23d5 100644 --- a/src/main.c +++ b/src/main.c @@ -85,6 +85,7 @@ WDDomain *WDRootMenu = NULL; XContext wWinContext; XContext wAppWinContext; XContext wStackContext; +XContext wVEdgeContext; /* Atoms */ Atom _XA_WM_STATE; @@ -123,9 +124,9 @@ Atom _XA_DND_SELECTION; Cursor wCursor[WCUR_LAST]; /* last event timestamp for XSetInputFocus */ -Time LastTimestamp; +Time LastTimestamp = CurrentTime; /* timestamp on the last time we did XSetInputFocus() */ -Time LastFocusChange; +Time LastFocusChange = CurrentTime; #ifdef SHAPE Bool wShapeSupported; @@ -494,8 +495,10 @@ check_defaults() static void execInitScript() { - char *file; - char *paths = wstrconcat(wusergnusteppath(), ":"DEF_CONFIG_PATHS); + char *file, *paths; + + paths = wstrconcat(wusergnusteppath(), "/Library/WindowMaker"); + paths = wstrappend(paths, ":"DEF_CONFIG_PATHS); file = wfindfile(paths, DEF_INIT_SCRIPT); wfree(paths); @@ -519,8 +522,10 @@ execInitScript() void ExecExitScript() { - char *file; - char *paths = wstrconcat(wusergnusteppath(), ":"DEF_CONFIG_PATHS); + char *file, *paths; + + paths = wstrconcat(wusergnusteppath(), "/Library/WindowMaker"); + paths = wstrappend(paths, ":"DEF_CONFIG_PATHS); file = wfindfile(paths, DEF_EXIT_SCRIPT); wfree(paths); @@ -717,22 +722,25 @@ main(int argc, char **argv) } - if (!Locale) { - Locale = getenv("LC_ALL"); - } - if (!Locale) { - Locale = getenv("LANG"); + if (Locale) { + /* return of wstrconcat should not be free-ed! read putenv man page */ + putenv(wstrconcat("LANG=", Locale)); + } else { + Locale = getenv("LC_ALL"); + if (!Locale) { + Locale = getenv("LANG"); + } } setlocale(LC_ALL, ""); if (!Locale || strcmp(Locale, "C")==0 || strcmp(Locale, "POSIX")==0) - Locale = NULL; + Locale = NULL; #ifdef I18N if (getenv("NLSPATH")) - bindtextdomain("WindowMaker", getenv("NLSPATH")); + bindtextdomain("WindowMaker", getenv("NLSPATH")); else - bindtextdomain("WindowMaker", LOCALEDIR); + bindtextdomain("WindowMaker", LOCALEDIR); textdomain("WindowMaker"); if (!XSupportsLocale()) { diff --git a/src/menu.c b/src/menu.c index 8edb573a..18496093 100644 --- a/src/menu.c +++ b/src/menu.c @@ -43,6 +43,7 @@ #include "stacking.h" #include "text.h" #include "xinerama.h" +#include "workspace.h" /****** Global Variables ******/ @@ -2259,9 +2260,7 @@ byebye: ((WMenu*)desc->parent)->flags.inside_handler = 0; #ifdef VIRTUAL_DESKTOP - if (wPreferences.vedge_thickness) { wWorkspaceRaiseEdge(scr); - } #endif } @@ -2510,7 +2509,7 @@ wMenuSaveState(WScreen *scr) WMPropList *menus, *key; int save_menus = 0; - menus = WMCreatePLDictionary(NULL, NULL, NULL); + menus = WMCreatePLDictionary(NULL, NULL); #ifndef LITE if (scr->switch_menu && scr->switch_menu->flags.buttoned) { diff --git a/src/misc.c b/src/misc.c index d3ddf523..17dc4917 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1,8 +1,8 @@ -/* +/* * Window Maker window manager - * + * * Copyright (c) 1997-2003 Alfredo K. Kojima - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "wconfig.h" @@ -52,8 +52,6 @@ /**** global variables *****/ -extern char *DisplayName; - extern WPreferences wPreferences; extern Time LastTimestamp; @@ -91,7 +89,7 @@ static char* username() { char *tmp; - + tmp = getlogin(); if (!tmp) { struct passwd *user; @@ -109,7 +107,7 @@ username() } return tmp; } - + char * MakeCPPArgs(char *path) { @@ -117,7 +115,7 @@ MakeCPPArgs(char *path) char buffer[MAXLINE], *buf, *line; Visual *visual; char *tmp; - + line = wmalloc(MAXLINE); *line = 0; i=1; @@ -125,13 +123,13 @@ MakeCPPArgs(char *path) if (buf[0]=='(') { wwarning(_("your machine is misconfigured. HOSTNAME is set to %s"), buf); - } else + } else putdef(line, " -DHOST=", buf); } else if ((buf=getenv("HOST"))!=NULL) { if (buf[0]=='(') { wwarning(_("your machine is misconfigured. HOST is set to %s"), buf); - } else + } else putdef(line, " -DHOST=", buf); } buf = username(); @@ -141,14 +139,14 @@ MakeCPPArgs(char *path) buf = XDisplayName(DisplayString(dpy)); putdef(line, " -DDISPLAY=", buf); putdef(line, " -DWM_VERSION=", VERSION); - + visual = DefaultVisual(dpy, DefaultScreen(dpy)); putidef(line, " -DVISUAL=", visual->class); - + putidef(line, " -DDEPTH=", DefaultDepth(dpy, DefaultScreen(dpy))); putidef(line, " -DSCR_WIDTH=", WidthOfScreen(DefaultScreenOfDisplay(dpy))); - putidef(line, " -DSCR_HEIGHT=", + putidef(line, " -DSCR_HEIGHT=", HeightOfScreen(DefaultScreenOfDisplay(dpy))); /* put the dir where the menu is being read from to the @@ -181,7 +179,7 @@ MakeCPPArgs(char *path) char * wgethomedir(); /* home is statically allocated. Don't free it! */ char *home = wgethomedir(); - + strcpy(fullpath, home); strcat(fullpath, &(buf[1])); } @@ -189,7 +187,7 @@ MakeCPPArgs(char *path) putdef(line, " -I", fullpath); } while ((buf = strtok(NULL, ":"))!=NULL); - + #undef arg #ifdef DEBUG puts("CPP ARGS"); @@ -211,14 +209,14 @@ isBelow(WWindow *win1, WWindow *win2) { int i; WCoreWindow *tmp; - + tmp = win1->frame->core->stacking->under; while (tmp) { if (tmp == win2->frame->core) return True; tmp = tmp->stacking->under; } - + for (i=win1->frame->core->stacking->window_level-1; i>=0; i--) { tmp = win1->screen_ptr->stacking_list[i]; while (tmp) { @@ -272,7 +270,7 @@ char **winname; } else { /* the hint is probably not set */ *winname = NULL; - + return False; } } @@ -291,7 +289,7 @@ char **iconname; XTextProperty text_prop; char **list; int num; - + if (XGetWMIconName(dpy, win, &text_prop) != 0 && text_prop.value && text_prop.nitems > 0) { if (text_prop.encoding == XA_STRING) @@ -313,20 +311,20 @@ char **iconname; } -static void +static void eatExpose() { XEvent event, foo; - + /* compress all expose events into a single one */ - + if (XCheckMaskEvent(dpy, ExposureMask, &event)) { /* ignore other exposure events for this window */ while (XCheckWindowEvent(dpy, event.xexpose.window, ExposureMask, &foo)); /* eat exposes for other windows */ eatExpose(); - + event.xexpose.count = 0; XPutBackEvent(dpy, &event); } @@ -351,8 +349,8 @@ SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y) {ICON_SLIDE_DELAY_M, ICON_SLIDE_STEPS_M, ICON_SLIDE_SLOWDOWN_M}, {ICON_SLIDE_DELAY_S, ICON_SLIDE_STEPS_S, ICON_SLIDE_SLOWDOWN_S}, {ICON_SLIDE_DELAY_US, ICON_SLIDE_STEPS_US, ICON_SLIDE_SLOWDOWN_US}}; - - + + dx = (float)(to_x-from_x); dy = (float)(to_y-from_y); @@ -477,7 +475,7 @@ ShrinkString(WMFont *font, char *string, int width) } else if (winfo_window, clipboard); - + XConvertSelection(dpy, selection, XA_STRING, clipboard, screen->info_window, CurrentTime); - + timer = WMAddTimerHandler(1000, timeoutHandler, &timeout); - + while (!XCheckTypedWindowEvent(dpy, screen->info_window, SelectionNotify, &ev) && !timeout); - + if (!timeout) { WMDeleteTimerHandler(timer); } else { @@ -607,7 +605,7 @@ static char* getselection(WScreen *scr) { char *tmp; - + tmp = getTextSelection(scr, XA_PRIMARY); if (!tmp) tmp = getTextSelection(scr, XA_CUT_BUFFER0); @@ -623,10 +621,10 @@ getuserinput(WScreen *scr, char *line, int *ptr) char *prompt; int j, state; int begin = 0; -#define BUFSIZE 512 +#define BUFSIZE 512 char tbuffer[BUFSIZE], pbuffer[BUFSIZE]; - + title = _("Program Arguments"); prompt = _("Enter command arguments:"); ret = NULL; @@ -716,17 +714,17 @@ get_dnd_selection(WScreen *scr) char **list; char *flat_string; int count; - + result=XGetTextProperty(dpy, scr->root_win, &text_ret, _XA_DND_SELECTION); - + if (result==0 || text_ret.value==NULL || text_ret.encoding==None || text_ret.format==0 || text_ret.nitems == 0) { wwarning(_("unable to get dropped data from DND drop")); return NULL; } - + XTextPropertyToStringList(&text_ret, &list, &count); - + if (!list || count<1) { XFree(text_ret.value); wwarning(_("error getting dropped data from DND drop")); @@ -737,7 +735,7 @@ get_dnd_selection(WScreen *scr) if (!flat_string) { wwarning(_("out of memory while getting data from DND drop")); } - + XFreeStringList(list); XFree(text_ret.value); return flat_string; @@ -749,7 +747,7 @@ get_dnd_selection(WScreen *scr) #define S_ESCAPE 1 #define S_OPTION 2 -/* +/* * state input new-state output * NORMAL % OPTION * NORMAL \ ESCAPE @@ -808,15 +806,15 @@ ExpandOptions(WScreen *scr, char *cmdline) case 'n': out[optr++]=10; break; - + case 'r': out[optr++]=13; break; - + case 't': out[optr++]=9; break; - + default: out[optr++]=cmdline[ptr]; } @@ -828,7 +826,7 @@ ExpandOptions(WScreen *scr, char *cmdline) case 'w': if (scr->focused_window && scr->focused_window->flags.focused) { - snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", + snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->focused_window->client_win); slen = strlen(tmpbuf); olen += slen; @@ -844,9 +842,9 @@ ExpandOptions(WScreen *scr, char *cmdline) out[optr++]=' '; } break; - + case 'W': - snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", + snprintf(tmpbuf, sizeof(tmpbuf), "0x%x", (unsigned int)scr->current_workspace + 1); slen = strlen(tmpbuf); olen += slen; @@ -859,10 +857,10 @@ ExpandOptions(WScreen *scr, char *cmdline) strcat(out,tmpbuf); optr+=slen; break; - + case 'a': ptr++; - user_input = getuserinput(scr, cmdline, &ptr); + user_input = getuserinput(scr, cmdline, &ptr); if (user_input) { slen = strlen(user_input); olen += slen; @@ -907,7 +905,7 @@ ExpandOptions(WScreen *scr, char *cmdline) optr+=slen; break; #endif /* OFFIX_DND */ - + case 's': if (!selection) { selection = getselection(scr); @@ -940,7 +938,7 @@ ExpandOptions(WScreen *scr, char *cmdline) if (selection) XFree(selection); return out; - + error: wfree(out); if (selection) @@ -1007,21 +1005,21 @@ GetShortcutString(char *text) /* KeySym ksym;*/ int control = 0; char *tmp; - + tmp = text = wstrdup(text); /* get modifiers */ while ((k = strchr(text, '+'))!=NULL) { int mod; - + *k = 0; mod = wXModifierFromKey(text); if (mod<0) { return wstrdup("bug"); } - + modmask |= mod; - + if (strcasecmp(text, "Meta")==0) { buffer = wstrappend(buffer, "M+"); } else if (strcasecmp(text, "Alt")==0) { @@ -1029,15 +1027,15 @@ GetShortcutString(char *text) } else if (strcasecmp(text, "Shift")==0) { buffer = wstrappend(buffer, "Sh+"); } else if (strcasecmp(text, "Mod1")==0) { - buffer = wstrappend(buffer, "M1+"); + buffer = wstrappend(buffer, "M1+"); } else if (strcasecmp(text, "Mod2")==0) { - buffer = wstrappend(buffer, "M2+"); + buffer = wstrappend(buffer, "M2+"); } else if (strcasecmp(text, "Mod3")==0) { buffer = wstrappend(buffer, "M3+"); } else if (strcasecmp(text, "Mod4")==0) { - buffer = wstrappend(buffer, "M4+"); + buffer = wstrappend(buffer, "M4+"); } else if (strcasecmp(text, "Mod5")==0) { - buffer = wstrappend(buffer, "M5+"); + buffer = wstrappend(buffer, "M5+"); } else if (strcasecmp(text, "Control")==0) { control = 1; } else { @@ -1050,7 +1048,7 @@ GetShortcutString(char *text) buffer = wstrappend(buffer, "^"); } buffer = wstrappend(buffer, text); - + /* get key */ /* ksym = XStringToKeysym(text); tmp = keysymToString(ksym, modmask); @@ -1185,7 +1183,7 @@ SendHelperMessage(WScreen *scr, char type, int workspace, char *msg) if (!scr->flags.backimage_helper_launched) { return; } - + len = (msg ? strlen(msg) : 0) + (workspace >=0 ? 4 : 0) + 1 ; buffer = wmalloc(len+5); snprintf(buf, len, "%4i", len); @@ -1244,22 +1242,141 @@ UpdateDomainFile(WDDomain *domain) } - char* StrConcatDot(char *a, char *b) { int len; char *str; - + if (!a) a = ""; if (!b) b = ""; - + len = strlen(a)+strlen(b)+4; str = wmalloc(len); - + snprintf(str, len, "%s.%s", a, b); - + return str; } + + +#ifndef NETWM_HINTS + +static Atom net_wm_pid = None; + +int +GetPidForWindow(Window win) +{ + Atom type_ret; + int fmt_ret; + unsigned long nitems_ret; + unsigned long bytes_after_ret; + long *data = 0; + int pid; + + if (net_wm_pid == None) { + net_wm_pid = XInternAtom(dpy, "_NET_WM_PID", False); + } + + if (XGetWindowProperty(dpy, win, net_wm_pid, 0, 1, False, + XA_CARDINAL, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, + (unsigned char**)&data)==Success && data) { + + pid = *data; + XFree(data); + } else { + pid = 0; + } + + return pid; +} + +#endif + + +Bool +GetCommandForPid(int pid, char ***argv, int *argc) +{ + char buf[1024]; + FILE *fPtr; + int count, i, j; + + sprintf(buf, "/proc/%d/cmdline", pid); + fPtr = fopen(buf, "r"); + if (fPtr) { + count = read(fileno(fPtr), buf, 1024); + if (count > 0) { + buf[count] = 0; + for (i=0, *argc=0; i 0 && argv != NULL) { + if (elements==0) + elements = argc; + command = wtokenjoin(argv, WMIN(argc, elements)); + if (command[0] == 0) { + wfree(command); + command = NULL; + } + } + if (argv) { + XFreeStringList(argv); + } + } + + return command; +} + + +/* Free result when done */ +char* +GetCommandForWindow(Window win) +{ + return getCommandForWindow(win, 0); +} + + +/* Free result when done */ +char* +GetProgramNameForWindow(Window win) +{ + return getCommandForWindow(win, 1); +} + + diff --git a/src/moveres.c b/src/moveres.c index 5dd0d8ae..eaf7bb3c 100644 --- a/src/moveres.c +++ b/src/moveres.c @@ -66,7 +66,7 @@ /* True if window currently has a border. This also includes borderless * windows which are currently selected */ -#define HAS_BORDER(w) ((w)->flags.selected || !WFLAGP((w), no_border)) +#define HAS_BORDER_WITH_SELECT(w) ((w)->flags.selected || HAS_BORDER(w)) /****** Global Variables ******/ @@ -236,8 +236,7 @@ mapPositionDisplay(WWindow *wwin, int x, int y, int w, int h) return; } else if (wPreferences.move_display == WDIS_CENTER) { rect = wGetRectForHead(scr, wGetHeadForWindow(wwin)); - moveGeometryDisplayCentered(scr, - rect.pos.x + rect.size.width/2, + moveGeometryDisplayCentered(scr, rect.pos.x + rect.size.width/2, rect.pos.y + rect.size.height/2); } else if (wPreferences.move_display == WDIS_TOPLEFT) { rect = wGetRectForHead(scr, wGetHeadForWindow(wwin)); @@ -265,7 +264,7 @@ showGeometry(WWindow *wwin, int x1, int y1, int x2, int y2, int direction) * x2-1 everywhere below in the code). But why only for x? */ x1--; x2--; - if (HAS_BORDER(wwin)) { + if (HAS_BORDER_WITH_SELECT(wwin)) { x1 += FRAME_BORDER_WIDTH; x2 += FRAME_BORDER_WIDTH; y1 += FRAME_BORDER_WIDTH; @@ -407,8 +406,7 @@ cycleGeometryDisplay(WWindow *wwin, int x, int y, int w, int h, int dir) } else { if (wPreferences.size_display == WDIS_CENTER) { rect = wGetRectForHead(scr, wGetHeadForWindow(wwin)); - moveGeometryDisplayCentered(scr, - rect.pos.x + rect.size.width/2, + moveGeometryDisplayCentered(scr, rect.pos.x + rect.size.width/2, rect.pos.y + rect.size.height/2); } else if (wPreferences.size_display == WDIS_TOPLEFT) { rect = wGetRectForHead(scr, wGetHeadForWindow(wwin)); @@ -434,8 +432,7 @@ mapGeometryDisplay(WWindow *wwin, int x, int y, int w, int h) if (wPreferences.size_display == WDIS_CENTER) { rect = wGetRectForHead(scr, wGetHeadForWindow(wwin)); - moveGeometryDisplayCentered(scr, - rect.pos.x + rect.size.width/2, + moveGeometryDisplayCentered(scr, rect.pos.x + rect.size.width/2, rect.pos.y + rect.size.height/2); } else if (wPreferences.size_display == WDIS_TOPLEFT) { rect = wGetRectForHead(scr, wGetHeadForWindow(wwin)); @@ -497,15 +494,15 @@ drawTransparentFrame(WWindow *wwin, int x, int y, int width, int height) int h = 0; int bottom = 0; - if (HAS_BORDER(wwin)) { + if (HAS_BORDER_WITH_SELECT(wwin)) { x += FRAME_BORDER_WIDTH; y += FRAME_BORDER_WIDTH; } - if (!WFLAGP(wwin, no_titlebar) && !wwin->flags.shaded) { + if (HAS_TITLEBAR(wwin) && !wwin->flags.shaded) { h = WMFontHeight(wwin->screen_ptr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2; } - if (!WFLAGP(wwin, no_resizebar) && !wwin->flags.shaded) { + if (HAS_RESIZEBAR(wwin) && !wwin->flags.shaded) { /* Can't use wwin-frame->bottom_width because, in some cases (e.g. interactive placement), frame does not point to anything. */ bottom = RESIZEBAR_HEIGHT; @@ -640,9 +637,9 @@ typedef struct { #define WTOP(w) (w)->frame_y #define WLEFT(w) (w)->frame_x #define WRIGHT(w) ((w)->frame_x + (int)(w)->frame->core->width - 1 + \ - (HAS_BORDER(w) ? 2*FRAME_BORDER_WIDTH : 0)) + (HAS_BORDER_WITH_SELECT(w) ? 2*FRAME_BORDER_WIDTH : 0)) #define WBOTTOM(w) ((w)->frame_y + (int)(w)->frame->core->height - 1 + \ - (HAS_BORDER(w) ? 2*FRAME_BORDER_WIDTH : 0)) + (HAS_BORDER_WITH_SELECT(w) ? 2*FRAME_BORDER_WIDTH : 0)) static int compareWTop(const void *a, const void *b) @@ -900,9 +897,9 @@ initMoveData(WWindow *wwin, MoveData *data) data->calcY = wwin->frame_y; data->winWidth = wwin->frame->core->width + - (HAS_BORDER(wwin) ? 2*FRAME_BORDER_WIDTH : 0); + (HAS_BORDER_WITH_SELECT(wwin) ? 2*FRAME_BORDER_WIDTH : 0); data->winHeight = wwin->frame->core->height + - (HAS_BORDER(wwin) ? 2*FRAME_BORDER_WIDTH : 0); + (HAS_BORDER_WITH_SELECT(wwin) ? 2*FRAME_BORDER_WIDTH : 0); } @@ -1293,6 +1290,9 @@ updateWindowPosition(WWindow *wwin, MoveData *data, Bool doResistance, #define _KS KEY_CONTROL_WINDOW_WEIGHT +#define MOVABLE_BIT 0x01 +#define RESIZABLE_BIT 0x02 + int wKeyboardMoveResizeWindow(WWindow *wwin) { @@ -1309,15 +1309,24 @@ wKeyboardMoveResizeWindow(WWindow *wwin) int done,off_x,off_y,ww,wh; int kspeed = _KS; Time lastTime = 0; + KeyCode shiftl, shiftr, ctrll, ctrlmode; KeySym keysym=NoSymbol; int moment=0; - KeyCode shiftl,shiftr,ctrll,ctrlmode; + int modes = ((IS_MOVABLE(wwin) ? MOVABLE_BIT : 0) | + (IS_RESIZABLE(wwin) ? RESIZABLE_BIT : 0)); + int head = ((wPreferences.auto_arrange_icons && wXineramaHeads(scr)>1) + ? wGetHeadForWindow(wwin) + : scr->xine_info.primary_head); shiftl = XKeysymToKeycode(dpy, XK_Shift_L); shiftr = XKeysymToKeycode(dpy, XK_Shift_R); ctrll = XKeysymToKeycode(dpy, XK_Control_L); ctrlmode=done=off_x=off_y=0; + if (modes == RESIZABLE_BIT) { + ctrlmode = 1; + } + XSync(dpy, False); wusleep(10000); XGrabKeyboard(dpy, root, False, GrabModeAsync, GrabModeAsync, CurrentTime); @@ -1383,14 +1392,15 @@ wKeyboardMoveResizeWindow(WWindow *wwin) } if (kspeed < _KS) kspeed = _KS; lastTime = event.xkey.time; - - if (event.xkey.state & ControlMask && !wwin->flags.shaded) { - ctrlmode=1; - wUnselectWindows(scr); - } - else { - ctrlmode=0; - } + if (modes == (MOVABLE_BIT|RESIZABLE_BIT)) { + if ((event.xkey.state & ControlMask) && !wwin->flags.shaded) { + ctrlmode=1; + wUnselectWindows(scr); + } + else { + ctrlmode=0; + } + } if (event.xkey.keycode == shiftl || event.xkey.keycode == shiftr) { if (ctrlmode) cycleGeometryDisplay(wwin, src_x+off_x, src_y+off_y, ww, wh, 0); @@ -1544,7 +1554,7 @@ wKeyboardMoveResizeWindow(WWindow *wwin) showGeometry(wwin, src_x+off_x, src_y+off_y, src_x+off_x+ww, src_y+off_y+wh,0); } else if(!scr->selected_windows) showPosition(wwin, src_x+off_x, src_y+off_y); - /**/ + if (done) { scr->keymove_tick=0; @@ -1599,6 +1609,17 @@ wKeyboardMoveResizeWindow(WWindow *wwin) wWindowChangeWorkspace(wwin, scr->current_workspace); wSetFocusTo(scr, wwin); } + + if (wPreferences.auto_arrange_icons && wXineramaHeads(scr)>1 && + head != wGetHeadForWindow(wwin)) { + wArrangeIcons(scr, True); + } + + +#if defined(NETWM_HINTS) && defined(VIRTUAL_DESKTOP) + wWorkspaceResizeViewPort(scr, scr->current_workspace); +#endif + return 1; } } @@ -1638,12 +1659,15 @@ wMouseMoveWindow(WWindow *wwin, XEvent *ev) /* This needs not to change while moving, else bad things can happen */ int opaqueMove = wPreferences.opaque_move; MoveData moveData; + int head = ((wPreferences.auto_arrange_icons && wXineramaHeads(scr) > 1) + ? wGetHeadForWindow(wwin) + : scr->xine_info.primary_head); #ifdef GHOST_WINDOW_MOVE - RImage *rimg; - - rimg = InitGhostWindowMove(scr); + RImage *rimg = InitGhostWindowMove(scr); #endif + if (!IS_MOVABLE(wwin)) + return False; if (wPreferences.opaque_move && !wPreferences.use_saveunders) { XSetWindowAttributes attr; @@ -1873,7 +1897,6 @@ wMouseMoveWindow(WWindow *wwin, XEvent *ev) if (wPreferences.opaque_move && !wPreferences.use_saveunders) { XSetWindowAttributes attr; - attr.save_under = False; XChangeWindowAttributes(dpy, wwin->frame->core->window, CWSaveUnder, &attr); @@ -1882,6 +1905,16 @@ wMouseMoveWindow(WWindow *wwin, XEvent *ev) freeMoveData(&moveData); + if (started && wPreferences.auto_arrange_icons && wXineramaHeads(scr)>1 && + head != wGetHeadForWindow(wwin)) { + wArrangeIcons(scr, True); + } + +#if defined(NETWM_HINTS) && defined(VIRTUAL_DESKTOP) + if (started) + wWorkspaceResizeViewPort(scr, scr->current_workspace); +#endif + return started; } @@ -1964,6 +1997,12 @@ wMouseResizeWindow(WWindow *wwin, XEvent *ev) int orig_fy = fy; int orig_fw = fw; int orig_fh = fh; + int head = ((wPreferences.auto_arrange_icons && wXineramaHeads(scr)>1) + ? wGetHeadForWindow(wwin) + : scr->xine_info.primary_head); + + if (!IS_RESIZABLE(wwin)) + return; if (wwin->flags.shaded) { wwarning("internal error: tryein"); @@ -1984,7 +2023,7 @@ wMouseResizeWindow(WWindow *wwin, XEvent *ev) ry2 = fy + fh - 1; shiftl = XKeysymToKeycode(dpy, XK_Shift_L); shiftr = XKeysymToKeycode(dpy, XK_Shift_R); - if (!WFLAGP(wwin, no_titlebar)) + if (HAS_TITLEBAR(wwin)) h = WMFontHeight(wwin->screen_ptr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2; else h = 0; @@ -2165,6 +2204,15 @@ wMouseResizeWindow(WWindow *wwin, XEvent *ev) WMHandleEvent(&event); } } + + if (wPreferences.auto_arrange_icons && wXineramaHeads(scr) > 1 && + head != wGetHeadForWindow(wwin)) { + wArrangeIcons(scr, True); + } + +#if defined(NETWM_HINTS) && defined(VIRTUAL_DESKTOP) + wWorkspaceResizeViewPort(scr, scr->current_workspace); +#endif } #undef LEFT @@ -2316,11 +2364,11 @@ InteractivePlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, *y_ret = 0; return; } - if (!WFLAGP(wwin, no_titlebar)) { + if (HAS_TITLEBAR(wwin)) { h = WMFontHeight(scr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2; height += h; } - if (!WFLAGP(wwin, no_resizebar)) { + if (HAS_RESIZEBAR(wwin)) { height += RESIZEBAR_HEIGHT; } XGrabKeyboard(dpy, root, False, GrabModeAsync, GrabModeAsync, CurrentTime); diff --git a/src/placement.c b/src/placement.c index f5c0b529..47a1af6a 100644 --- a/src/placement.c +++ b/src/placement.c @@ -349,33 +349,32 @@ smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, unsigned int width, unsigned int height, WArea usableArea) { - WScreen *scr = wwin->screen_ptr; + //WScreen *scr = wwin->screen_ptr; int test_x = 0, test_y = Y_ORIGIN(scr); int from_x, to_x, from_y, to_y; int sx; int min_isect, min_isect_x, min_isect_y; int sum_isect; - int extra_height; - - if (wwin->frame) - extra_height = wwin->frame->top_width + wwin->frame->bottom_width; - else - extra_height = 24; /* random value */ + if (wwin->frame) { + height += wwin->frame->top_width + wwin->frame->bottom_width; + } else { + if (HAS_TITLEBAR(wwin)) height += 18; + if (HAS_RESIZEBAR(wwin)) height += 8; + } + if (HAS_BORDER(wwin)) { + height += 2; + width += 2; + } sx = X_ORIGIN(scr); min_isect = INT_MAX; min_isect_x = sx; min_isect_y = test_y; - height += extra_height; - while (((test_y + height) < usableArea.y2)) { - test_x = sx; - while ((test_x + width) < usableArea.x2) { - sum_isect = calcSumOfCoveredAreas(wwin, test_x, test_y, width, height); @@ -430,21 +429,23 @@ autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, int loc_ok = False, tw,tx,ty,th; int swidth, sx; WWindow *test_window; - int extra_height; - - if (wwin->frame) - extra_height = wwin->frame->top_width + wwin->frame->bottom_width + 2; - else - extra_height = 24; /* random value */ + if (wwin->frame) { + height += wwin->frame->top_width + wwin->frame->bottom_width; + } else { + if (HAS_TITLEBAR(wwin)) height += 18; + if (HAS_RESIZEBAR(wwin)) height += 8; + } + if (HAS_BORDER(wwin)) { + height += 2; + width += 2; + } swidth = usableArea.x2-usableArea.x1; sx = X_ORIGIN(scr); /* this was based on fvwm2's smart placement */ - height += extra_height; - while (((test_y + height) < (usableArea.y2 - usableArea.y1)) && !loc_ok) { test_x = sx; @@ -539,17 +540,19 @@ cascadeWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret, unsigned int width, unsigned int height, int h, WArea usableArea) { - unsigned int extra_height; - - - if (wwin->frame) - extra_height = wwin->frame->top_width + wwin->frame->bottom_width; - else - extra_height = 24; /* random value */ + if (wwin->frame) { + height += wwin->frame->top_width + wwin->frame->bottom_width; + } else { + if (HAS_TITLEBAR(wwin)) height += 18; + if (HAS_RESIZEBAR(wwin)) height += 8; + } + if (HAS_BORDER(wwin)) { + height += 2; + width += 2; + } *x_ret = h * scr->cascade_index + X_ORIGIN(scr); *y_ret = h * scr->cascade_index + Y_ORIGIN(scr); - height += extra_height; if (width + *x_ret > usableArea.x2 || height + *y_ret > usableArea.y2) { scr->cascade_index = 0; @@ -564,15 +567,21 @@ randomPlaceWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret, unsigned int width, unsigned int height, WArea usableArea) { - int w, h, extra_height; + int w, h; - if (wwin->frame) - extra_height = wwin->frame->top_width + wwin->frame->bottom_width + 2; - else - extra_height = 24; /* random value */ + if (wwin->frame) { + height += wwin->frame->top_width + wwin->frame->bottom_width; + } else { + if (HAS_TITLEBAR(wwin)) height += 18; + if (HAS_RESIZEBAR(wwin)) height += 8; + } + if (HAS_BORDER(wwin)) { + height += 2; + width += 2; + } w = ((usableArea.x2-X_ORIGIN(scr)) - width); - h = ((usableArea.y2-Y_ORIGIN(scr)) - height - extra_height); + h = ((usableArea.y2-Y_ORIGIN(scr)) - height); if (w<1) w = 1; if (h<1) h = 1; *x_ret = X_ORIGIN(scr) + rand()%w; diff --git a/src/screen.c b/src/screen.c index 8e619f4a..62cd0e7a 100644 --- a/src/screen.c +++ b/src/screen.c @@ -62,6 +62,9 @@ #ifdef OLWM_HINTS # include "openlook.h" #endif +#ifdef NETWM_HINTS +# include "wmspec.h" +#endif #include "xinerama.h" @@ -787,6 +790,10 @@ wScreenInit(int screen_number) wOLWMInitStuff(scr); #endif +#ifdef NETWM_HINTS + wNETWMInitStuff(scr); +#endif + /* create initial workspace */ wWorkspaceNew(scr); @@ -1014,10 +1021,21 @@ wScreenUpdateUsableArea(WScreen *scr) } } +#ifdef NETWM_HINTS + { + WArea area; + if (wNETWMGetUsableArea(scr, &area)) { + scr->totalUsableArea.x1 = WMAX(scr->totalUsableArea.x1, area.x1); + scr->totalUsableArea.y1 = WMAX(scr->totalUsableArea.y1, area.y1); + scr->totalUsableArea.x2 = WMIN(scr->totalUsableArea.x2, area.x2); + scr->totalUsableArea.y2 = WMIN(scr->totalUsableArea.y2, area.y2); + } + } +#endif + #ifdef KWM_HINTS { WArea area; - if (wKWMGetUsableArea(scr, &area)) { scr->totalUsableArea.x1 = WMAX(scr->totalUsableArea.x1, area.x1); scr->totalUsableArea.y1 = WMAX(scr->totalUsableArea.y1, area.y1); @@ -1094,6 +1112,10 @@ wScreenUpdateUsableArea(WScreen *scr) #endif #endif +#ifdef NETWM_HINTS + wNETWMUpdateWorkarea(scr); +#endif + { unsigned size = wPreferences.workspace_border_size; unsigned position = wPreferences.workspace_border_position; @@ -1146,7 +1168,16 @@ wScreenRestoreState(WScreen *scr) wfree(path); } - if (!wPreferences.flags.noclip && scr->session_state) { + if (!scr->session_state) { + scr->session_state = WMCreatePLDictionary(NULL, NULL); + } + + if (!wPreferences.flags.nodock) { + state = WMGetFromPLDictionary(scr->session_state, dDock); + scr->dock = wDockRestoreState(scr, state, WM_DOCK); + } + + if (!wPreferences.flags.noclip) { state = WMGetFromPLDictionary(scr->session_state, dClip); scr->clip_icon = wClipRestoreState(scr, state); } @@ -1154,17 +1185,10 @@ wScreenRestoreState(WScreen *scr) wWorkspaceRestoreState(scr); #ifdef VIRTUAL_DESKTOP - /* - * * create inputonly windows at the border of screen - * */ - wWorkspaceManageEdge(scr); + /* create inputonly windows at the border of screen */ + wWorkspaceManageEdge(scr); #endif - if (!wPreferences.flags.nodock && scr->session_state) { - state = WMGetFromPLDictionary(scr->session_state, dDock); - scr->dock = wDockRestoreState(scr, state, WM_DOCK); - } - wScreenUpdateUsableArea(scr); } @@ -1201,7 +1225,7 @@ wScreenSaveState(WScreen *scr) old_state = scr->session_state; - scr->session_state = WMCreatePLDictionary(NULL, NULL, NULL); + scr->session_state = WMCreatePLDictionary(NULL, NULL); WMPLSetCaseSensitive(True); @@ -1239,9 +1263,9 @@ wScreenSaveState(WScreen *scr) wMenuSaveState(scr); - if (wScreenCount == 1) + if (wScreenCount == 1) { str = wdefaultspathfordomain("WMState"); - else { + } else { char buf[16]; snprintf(buf, sizeof(buf), "WMState.%i", scr->screen); str = wdefaultspathfordomain(buf); diff --git a/src/screen.h b/src/screen.h index 1ae1971a..12514099 100644 --- a/src/screen.h +++ b/src/screen.h @@ -77,10 +77,8 @@ typedef struct _WScreen { int scr_height; #ifdef VIRTUAL_DESKTOP - Window virtual_edge_u; - Window virtual_edge_d; - Window virtual_edge_l; - Window virtual_edge_r; + int virtual_nr_edges; + Window * virtual_edges; #endif Window root_win; /* root window of screen */ @@ -328,6 +326,7 @@ typedef struct _WScreen { unsigned int colormap_stuff_blocked:1; unsigned int doing_alt_tab:1; unsigned int jump_back_pending:1; + unsigned int ignore_focus_events:1; #ifdef KWM_HINTS unsigned int kwm_syncing_name:1; unsigned int kwm_syncing_count:1; diff --git a/src/session.c b/src/session.c index d9a834ff..7020f6c5 100644 --- a/src/session.c +++ b/src/session.c @@ -211,8 +211,6 @@ makeWindowState(WWindow *wwin, WApplication *wapp) { WScreen *scr = wwin->screen_ptr; Window win; - int argc; - char **argv; int i; unsigned mask; char *class, *instance, *command=NULL, buffer[512]; @@ -225,10 +223,7 @@ makeWindowState(WWindow *wwin, WApplication *wapp) else win = wwin->client_win; - if (XGetCommand(dpy, win, &argv, &argc) && argc>0) { - command = wtokenjoin(argv, argc); - XFreeStringList(argv); - } + command = GetCommandForWindow(win); if (!command) return NULL; @@ -266,14 +261,14 @@ makeWindowState(WWindow *wwin, WApplication *wapp) shortcut = WMCreatePLString(buffer); win_state = WMCreatePLDictionary(sName, name, - sCommand, cmd, - sWorkspace, workspace, - sShaded, shaded, - sMiniaturized, miniaturized, - sHidden, hidden, - sShortcutMask, shortcut, - sGeometry, geometry, - NULL); + sCommand, cmd, + sWorkspace, workspace, + sShaded, shaded, + sMiniaturized, miniaturized, + sHidden, hidden, + sShortcutMask, shortcut, + sGeometry, geometry, + NULL); WMReleasePropList(name); WMReleasePropList(cmd); @@ -321,7 +316,7 @@ wSessionSaveState(WScreen *scr) make_keys(); if (!scr->session_state) { - scr->session_state = WMCreatePLDictionary(NULL, NULL, NULL); + scr->session_state = WMCreatePLDictionary(NULL, NULL); if (!scr->session_state) return; } @@ -1072,9 +1067,9 @@ smSaveYourselfPhase2Proc(SmcConn smc_conn, SmPointer client_data) } plState = WMCreatePLDictionary(WMCreatePLString("Version"), - WMCreatePLString("1.0"), - WMCreatePLString("Screens"), - state, NULL); + WMCreatePLString("1.0"), + WMCreatePLString("Screens"), + state, NULL); WMWritePropListToFile(plState, statefile, False); diff --git a/src/stacking.c b/src/stacking.c index e246983f..104b2a0e 100644 --- a/src/stacking.c +++ b/src/stacking.c @@ -35,6 +35,7 @@ #include "actions.h" #include "properties.h" #include "stacking.h" +#include "workspace.h" /*** Global Variables ***/ @@ -152,6 +153,9 @@ CommitStacking(WScreen *scr) XRestackWindows(dpy, windows, i); wfree(windows); +#ifdef VIRTUAL_DESKTOP + wWorkspaceRaiseEdge(scr); +#endif WMPostNotificationName(WMNResetStacking, scr, NULL); } @@ -376,6 +380,10 @@ wLowerFrame(WCoreWindow *frame) } notifyStackChange(frame, "lower"); + +#ifdef VIRTUAL_DESKTOP + wWorkspaceRaiseEdge(scr); +#endif } @@ -510,6 +518,10 @@ MoveInStackListAbove(WCoreWindow *next, WCoreWindow *frame) } WMPostNotificationName(WMNResetStacking, scr, NULL); + +#ifdef VIRTUAL_DESKTOP + wWorkspaceRaiseEdge(scr); +#endif } diff --git a/src/startup.c b/src/startup.c index 3eb6faf9..6d155f2e 100644 --- a/src/startup.c +++ b/src/startup.c @@ -111,6 +111,7 @@ extern int wXkbEventBase; extern XContext wWinContext; extern XContext wAppWinContext; extern XContext wStackContext; +extern XContext wVEdgeContext; /* atoms */ extern Atom _XA_WM_STATE; @@ -756,6 +757,7 @@ StartUp(Bool defaultScreenOnly) wWinContext = XUniqueContext(); wAppWinContext = XUniqueContext(); wStackContext = XUniqueContext(); + wVEdgeContext = XUniqueContext(); /* _XA_VERSION = XInternAtom(dpy, "VERSION", False);*/ @@ -820,6 +822,17 @@ StartUp(Bool defaultScreenOnly) wCursor[WCUR_QUESTION] = XCreateFontCursor(dpy, XC_question_arrow); wCursor[WCUR_TEXT] = XCreateFontCursor(dpy, XC_xterm); /* odd name???*/ wCursor[WCUR_SELECT] = XCreateFontCursor(dpy, XC_cross); + { + Pixmap cur = XCreatePixmap(dpy, DefaultRootWindow(dpy), 16, 16, 1); + GC gc = XCreateGC(dpy, cur, 0, NULL); + XColor black; + memset(&black, 0, sizeof(XColor)); + XSetForeground(dpy, gc, 0); + XFillRectangle(dpy, cur, gc, 0, 0, 16, 16); + XFreeGC(dpy, gc); + wCursor[WCUR_EMPTY] = XCreatePixmapCursor(dpy, cur, cur, &black, &black, 0, 0); + XFreePixmap(dpy, cur); + } /* signal handler stuff that gets called when a signal is caught */ WMAddPersistentTimerHandler(500, delayedAction, NULL); @@ -1119,7 +1132,7 @@ manageAllWindows(WScreen *scr, int crashRecovery) if (crashRecovery) { int border; - border = (WFLAGP(wwin, no_border) ? 0 : FRAME_BORDER_WIDTH); + border = (!HAS_BORDER(wwin) ? 0 : FRAME_BORDER_WIDTH); wWindowMove(wwin, wwin->frame_x - border, wwin->frame_y - border - diff --git a/src/text.c b/src/text.c index 58889306..c483d640 100644 --- a/src/text.c +++ b/src/text.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "WindowMaker.h" @@ -42,14 +43,14 @@ #endif -#if 0 +#ifdef DEBUG # define ENTER(X) fprintf(stderr,"Entering: %s()\n", X); # define LEAVE(X) fprintf(stderr,"Leaving: %s()\n", X); -# define DEBUG(X) fprintf(stderr,"debug: %s()\n", X); +# define PDEBUG(X) fprintf(stderr,"debug: %s()\n", X); #else # define ENTER(X) # define LEAVE(X) -# define DEBUG(X) +# define PDEBUG(X) #endif extern Cursor wCursor[WCUR_LAST]; @@ -582,32 +583,32 @@ textEventHandler( WObjDescriptor *desc, XEvent *event ) * text so we can wTextRefresh() */ if( event->xmotion.state & (Button1Mask|Button3Mask|Button2Mask) ) { - DEBUG("MotionNotify"); + PDEBUG("MotionNotify"); handled = True; wtext->text.endPos = textXtoPos( wtext, event->xmotion.x ); } break; case ButtonPress: - DEBUG("ButtonPress"); + PDEBUG("ButtonPress"); handled = True; wtext->text.startPos = textXtoPos( wtext, event->xbutton.x ); wtext->text.endPos = wtext->text.startPos; break; case ButtonRelease: - DEBUG("ButtonRelease"); + PDEBUG("ButtonRelease"); handled = True; wtext->text.endPos = textXtoPos( wtext, event->xbutton.x ); break; case KeyPress: - DEBUG("KeyPress"); + PDEBUG("KeyPress"); handled = handleKeyPress( wtext, &event->xkey ); break; case EnterNotify: - DEBUG("EnterNotify"); + PDEBUG("EnterNotify"); handled = True; #if 0 if (!wtext->magic) @@ -621,7 +622,7 @@ textEventHandler( WObjDescriptor *desc, XEvent *event ) break; case LeaveNotify: - DEBUG("LeaveNotify"); + PDEBUG("LeaveNotify"); handled = True; #if 0 wtext->blinking = 0; diff --git a/src/wdefaults.c b/src/wdefaults.c index 23f6ac58..7a481c8d 100644 --- a/src/wdefaults.c +++ b/src/wdefaults.c @@ -500,7 +500,7 @@ wDefaultChangeIcon(WScreen *scr, char *instance, char* class, char *file) int same = 0; if (!dict) { - dict = WMCreatePLDictionary(NULL, NULL, NULL); + dict = WMCreatePLDictionary(NULL, NULL); if (dict) { db->dictionary = dict; } else { diff --git a/src/window.c b/src/window.c index 9876b1af..9cc51af9 100644 --- a/src/window.c +++ b/src/window.c @@ -1,9 +1,9 @@ /* window.c - client window managing stuffs - * + * * Window Maker window manager - * + * * Copyright (c) 1997-2003 Alfredo K. Kojima - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ @@ -27,8 +27,8 @@ #ifdef SHAPE #include #endif -#ifdef KEEP_XKB_LOCK_STATUS -#include +#ifdef KEEP_XKB_LOCK_STATUS +#include #endif /* KEEP_XKB_LOCK_STATUS */ #include #include @@ -68,6 +68,9 @@ #ifdef OLWM_HINTS # include "openlook.h" #endif +#ifdef NETWM_HINTS +# include "wmspec.h" +#endif /****** Global Variables ******/ @@ -154,7 +157,7 @@ appearanceObserver(void *self, WMNotification *notif) wFrameWindowResize(wwin->frame, wwin->frame->core->width, wwin->frame->top_width - 1); - wwin->client.y = wwin->frame_y - wwin->client.height + wwin->client.y = wwin->frame_y - wwin->client.height + wwin->frame->top_width; wWindowSynthConfigureNotify(wwin); } @@ -199,7 +202,7 @@ WWindow* wWindowCreate() { WWindow *wwin; - + wwin = wmalloc(sizeof(WWindow)); wretain(wwin); @@ -222,9 +225,9 @@ wWindowDestroy(WWindow *wwin) if (wwin->screen_ptr->cmap_window == wwin) { wwin->screen_ptr->cmap_window = NULL; } - + WMRemoveNotificationObserver(wwin); - + wwin->flags.destroyed = 1; for (i = 0; i < MAX_WINDOW_SHORTCUTS; i++) { @@ -278,12 +281,16 @@ wWindowDestroy(WWindow *wwin) if (wPreferences.auto_arrange_icons) wArrangeIcons(wwin->screen_ptr, True); } + +#ifdef NETWM_HINTS + if (wwin->net_icon_image) + RReleaseImage(wwin->net_icon_image); +#endif + wrelease(wwin); } - - static void setupGNUstepHints(WWindow *wwin, GNUstepWMAttributes *gs_hints) { @@ -307,7 +314,7 @@ setupGNUstepHints(WWindow *wwin, GNUstepWMAttributes *gs_hints) wwin->client_flags.no_miniaturize_button = ((gs_hints->window_style & WMMiniaturizableWindowMask)?0:1); - wwin->client_flags.no_miniaturizable = + wwin->client_flags.no_miniaturizable = wwin->client_flags.no_miniaturize_button; wwin->client_flags.no_resizebar = @@ -322,7 +329,7 @@ setupGNUstepHints(WWindow *wwin, GNUstepWMAttributes *gs_hints) WMMiniaturizableWindowMask)) { wwin->client_flags.no_titlebar = 0; } else { - wwin->client_flags.no_titlebar = + wwin->client_flags.no_titlebar = ((gs_hints->window_style & WMTitledWindowMask)?0:1); } @@ -356,11 +363,11 @@ wWindowCheckAttributeSanity(WWindow *wwin, WWindowAttributes *wflags, if (wapp && !wapp->flags.emulated) wflags->emulate_appicon = 0; } - - if (wwin->transient_for!=None + + if (wwin->transient_for!=None && wwin->transient_for!=wwin->screen_ptr->root_win) wflags->emulate_appicon = 0; - + if (wflags->sunken && mask->sunken && wflags->floating && mask->floating) wflags->sunken = 0; } @@ -381,7 +388,7 @@ wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) * - guess some settings * - use GNUstep/external window attributes * - set hints specified for the app in the resource DB - * + * */ WSETUFLAG(wwin, broken_close, 0); @@ -403,7 +410,7 @@ wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) WSETUFLAG(wwin, no_resizable, 1); WSETUFLAG(wwin, no_resizebar, 1); } - + /* set GNUstep window attributes */ if (wwin->wm_gnustep_attr) { setupGNUstepHints(wwin, wwin->wm_gnustep_attr); @@ -424,20 +431,26 @@ wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) int tmp_workspace = -1; int tmp_level = INT_MIN; /* INT_MIN is never used by the window levels */ Bool check; - + check = False; - + #ifdef MWM_HINTS wMWMCheckClientHints(wwin); #endif /* MWM_HINTS */ +#ifdef NETWM_HINTS + if (!check) + check = wNETWMCheckClientHints(wwin, &tmp_level, &tmp_workspace); +#endif + #ifdef GNOME_STUFF - check = wGNOMECheckClientHints(wwin, &tmp_level, &tmp_workspace); + if (!check) + check = wGNOMECheckClientHints(wwin, &tmp_level, &tmp_workspace); #endif /* GNOME_STUFF */ - + #ifdef KWM_HINTS if (!check) - wKWMCheckClientHints(wwin, &tmp_level, &tmp_workspace); + check = wKWMCheckClientHints(wwin, &tmp_level, &tmp_workspace); #endif /* KWM_HINTS */ #ifdef OLWM_HINTS @@ -458,6 +471,14 @@ wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) *level = tmp_level; } + if (wwin->transient_for!=None && wwin->transient_for != scr->root_win) { + WWindow * transientOwner = wWindowFor(wwin->transient_for); + if (transientOwner) { + int ownerLevel = transientOwner->frame->core->stacking->window_level; + if (ownerLevel > *level) *level = ownerLevel; + } + } + if (tmp_workspace >= 0) { *workspace = tmp_workspace % scr->workspace_count; } @@ -467,7 +488,7 @@ wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) * Set attributes specified only for that window/class. * This might do duplicate work with the 1st wDefaultFillAttributes(). */ - wDefaultFillAttributes(scr, wwin->wm_instance, wwin->wm_class, + wDefaultFillAttributes(scr, wwin->wm_instance, wwin->wm_class, &wwin->user_flags, &wwin->defined_user_flags, False); /* @@ -491,8 +512,8 @@ wWindowSetupInitialAttributes(WWindow *wwin, int *level, int *workspace) wwin->user_flags.sunken = 0; WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar)); - - + + /* windows that have takefocus=False shouldn't take focus at all */ if (wwin->focus_mode == WFM_NO_INPUT) { wwin->client_flags.no_focusable = 1; @@ -541,6 +562,78 @@ wWindowObscuresWindow(WWindow *wwin, WWindow *obscured) } +static void +fixLeaderProperties(WWindow *wwin) +{ + XClassHint *classHint; + XWMHints *hints, *clientHints; + Window leaders[2], window; + char **argv, *command; + int argc, i, pid; + Bool haveCommand; + + classHint = XAllocClassHint(); + clientHints = XGetWMHints(dpy, wwin->client_win); + pid = GetPidForWindow(wwin->client_win); + if (pid > 0) { + haveCommand = GetCommandForPid(pid, &argv, &argc); + } else { + haveCommand = False; + } + + leaders[0] = wwin->client_leader; + leaders[1] = wwin->group_id; + + if (haveCommand) { + command = GetCommandForWindow(wwin->client_win); + if (command) { + /* command already set. nothing to do. */ + wfree(command); + } else { + XSetCommand(dpy, wwin->client_win, argv, argc); + } + } + + for (i=0; i<2; i++) { + window = leaders[i]; + if (window) { + if (XGetClassHint(dpy, window, classHint) == 0) { + classHint->res_name = wwin->wm_instance; + classHint->res_class = wwin->wm_class; + XSetClassHint(dpy, window, classHint); + } + hints = XGetWMHints(dpy, window); + if (hints) { + XFree(hints); + } else if (clientHints) { + /* set window group leader to self */ + clientHints->window_group = window; + clientHints->flags |= WindowGroupHint; + XSetWMHints(dpy, window, clientHints); + } + + if (haveCommand) { + command = GetCommandForWindow(window); + if (command) { + /* command already set. nothing to do. */ + wfree(command); + } else { + XSetCommand(dpy, window, argv, argc); + } + } + } + } + + XFree(classHint); + if (clientHints) { + XFree(clientHints); + } + if (haveCommand) { + wfree(argv); + } +} + + static Window createFakeWindowGroupLeader(WScreen *scr, Window win, char *instance, char *class) { @@ -592,24 +685,24 @@ matchIdentifier(void *item, void *cdata) * reparents the window and allocates a descriptor for it. * Window manager hints and other hints are fetched to configure * the window decoration attributes and others. User preferences - * for the window are used if available, to configure window + * for the window are used if available, to configure window * decorations and some behaviour. * If in startup, windows that are override redirect, * unmapped and never were managed and are Withdrawn are not * managed. - * + * * Returns: * the new window descriptor - * + * * Side effects: * The window is reparented and appropriate notification * is done to the client. Input mask for the window is setup. - * The window descriptor is also associated with various window + * The window descriptor is also associated with various window * contexts and inserted in the head of the window list. - * Event handler contexts are associated for some objects + * Event handler contexts are associated for some objects * (buttons, titlebar and resizebar) - * - *---------------------------------------------------------------- + * + *---------------------------------------------------------------- */ WWindow* wManageWindow(WScreen *scr, Window window) @@ -617,7 +710,7 @@ wManageWindow(WScreen *scr, Window window) WWindow *wwin; int x, y; unsigned width, height; - XWindowAttributes wattribs; + XWindowAttributes wattribs; XSetWindowAttributes attribs; WWindowState *win_state; WWindow *transientOwner = NULL; @@ -678,20 +771,20 @@ wManageWindow(WScreen *scr, Window window) int junk; unsigned int ujunk; int b_shaped; - + XShapeSelectInput(dpy, window, ShapeNotifyMask); - XShapeQueryExtents(dpy, window, &b_shaped, &junk, &junk, &ujunk, + XShapeQueryExtents(dpy, window, &b_shaped, &junk, &junk, &ujunk, &ujunk, &junk, &junk, &junk, &ujunk, &ujunk); wwin->flags.shaped = b_shaped; } #endif - + /* *-------------------------------------------------- - * + * * Get hints and other information in properties * - *-------------------------------------------------- + *-------------------------------------------------- */ PropGetWMClass(window, &wwin->wm_class, &wwin->wm_instance); @@ -706,7 +799,7 @@ wManageWindow(WScreen *scr, Window window) attribs.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask; attribs.save_under = False; XChangeWindowAttributes(dpy, window, CWEventMask|CWDontPropagate - |CWSaveUnder, &attribs); + |CWSaveUnder, &attribs); XSetWindowBorderWidth(dpy, window, 0); /* get hints from GNUstep app */ @@ -780,10 +873,10 @@ wManageWindow(WScreen *scr, Window window) /* *-------------------------------------------------- - * + * * Setup the decoration/window attributes and * geometry - * + * *-------------------------------------------------- */ @@ -812,6 +905,8 @@ wManageWindow(WScreen *scr, Window window) wwin->main_window = wwin->client_win; } + fixLeaderProperties(wwin); + wwin->orig_main_window = wwin->main_window; if (wwin->flags.is_gnustep) { @@ -835,7 +930,7 @@ wManageWindow(WScreen *scr, Window window) #define ADEQUATE(x) ((x)!=None && (x)!=wwin->client_win && (x)!=fPtr->leader) - + // only enter here if PropGetWMClass() succeds PropGetWMClass(wwin->main_window, &class, &instance); buffer = StrConcatDot(instance, class); @@ -924,20 +1019,26 @@ wManageWindow(WScreen *scr, Window window) wwin->flags.miniaturized = 1; } - if (WFLAGP(wwin, start_maximized) && !WFLAGP(wwin, no_resizable)) { + if (WFLAGP(wwin, start_maximized) && IS_RESIZABLE(wwin)) { wwin->flags.maximized = MAX_VERTICAL|MAX_HORIZONTAL; } { - Bool bla; - - bla = False; +#if defined(NETWM_HINTS) || defined(GNOME_STUFF) || defined(KWM_HINTS) + Bool bla = False; +#endif + +#ifdef NETWM_HINTS + if (!bla) + bla = wNETWMCheckInitialClientState(wwin); +#endif #ifdef GNOME_STUFF - bla = wGNOMECheckInitialClientState(wwin); + if (!bla) + bla = wGNOMECheckInitialClientState(wwin); #endif #ifdef KWM_HINTS if (!bla) - wKWMCheckClientInitialState(wwin); + bla = wKWMCheckClientInitialState(wwin); #endif } @@ -989,7 +1090,7 @@ wManageWindow(WScreen *scr, Window window) } } - /* if we're restarting, restore saved state (from hints). + /* if we're restarting, restore saved state (from hints). * This will overwrite previous */ { WSavedState *wstate; @@ -1017,7 +1118,7 @@ wManageWindow(WScreen *scr, Window window) if (win_state != NULL) mask = win_state->state->window_shortcuts; - + if (wstate != NULL && mask == 0) mask = wstate->window_shortcuts; @@ -1047,7 +1148,7 @@ wManageWindow(WScreen *scr, Window window) wwin->wm_hints->initial_state = NormalState; } - /* set workspace on which the window starts */ + /* set workspace on which the window starts */ if (workspace >= 0) { if (workspace > scr->workspace_count-1) { workspace = workspace % scr->workspace_count; @@ -1092,18 +1193,18 @@ wManageWindow(WScreen *scr, Window window) y = win_state->state->y; } else if ((wwin->transient_for==None || wPreferences.window_placement!=WPM_MANUAL) - && !scr->flags.startup + && !scr->flags.startup && workspace == scr->current_workspace && !wwin->flags.miniaturized && !wwin->flags.maximized && !(wwin->normal_hints->flags & (USPosition|PPosition))) { - + if (transientOwner && transientOwner->flags.mapped) { int offs = WMAX(20, 2*transientOwner->frame->top_width); WMRect rect; int head; - - x = transientOwner->frame_x + + + x = transientOwner->frame_x + abs((transientOwner->frame->core->width - width)/2) + offs; y = transientOwner->frame_y + abs((transientOwner->frame->core->height - height)/3) + offs; @@ -1115,15 +1216,15 @@ wManageWindow(WScreen *scr, Window window) rect.pos.y = transientOwner->frame_y; rect.size.width = transientOwner->frame->core->width; rect.size.height = transientOwner->frame->core->height; - + head = wGetHeadForRect(scr, rect); rect = wGetRectForHead(scr, head); - + if (x < rect.pos.x) x = rect.pos.x; else if (x + width > rect.pos.x + rect.size.width) x = rect.pos.x + rect.size.width - width; - + if (y < rect.pos.y) y = rect.pos.y; else if (y + height > rect.pos.y + rect.size.height) @@ -1140,14 +1241,14 @@ wManageWindow(WScreen *scr, Window window) int head, flags; WMRect rect; int reposition = 0; - + /* * Make spash screens come out in the center of a head * trouble is that most splashies never get here * they are managed trough atoms but god knows where. - * Dan, do you know ? - * - * Most of them are not managed, they are set + * Dan, do you know ? -peter + * + * Most of them are not managed, they have set * OverrideRedirect, which means we can't do anything about * them. -alfredo */ @@ -1160,7 +1261,7 @@ wManageWindow(WScreen *scr, Window window) reposition = 1; - } else + } else #endif { /* @@ -1179,31 +1280,31 @@ wManageWindow(WScreen *scr, Window window) if (flags & XFLAG_MULTIPLE) reposition = 2; } - + switch (reposition) { case 1: head = wGetHeadForPointerLocation(scr); rect = wGetRectForHead(scr, head); - + x = rect.pos.x + (x * rect.size.width)/scr->scr_width; y = rect.pos.y + (y * rect.size.height)/scr->scr_height; break; - + case 2: rect = wGetRectForHead(scr, head); - + if (x < rect.pos.x) x = rect.pos.x; else if (x + width > rect.pos.x + rect.size.width) x = rect.pos.x + rect.size.width - width; - + if (y < rect.pos.y) y = rect.pos.y; else if (y + height > rect.pos.y + rect.size.height) y = rect.pos.y + rect.size.height - height; - + break; - + default: break; } @@ -1213,6 +1314,10 @@ wManageWindow(WScreen *scr, Window window) wScreenBringInside(scr, &x, &y, width, height); } +#ifdef NETWM_HINTS + wNETWMPositionSplash(wwin, &x, &y, width, height); +#endif + if (wwin->flags.urgent) { if (!IS_OMNIPRESENT(wwin)) wwin->flags.omnipresent ^= 1; @@ -1220,7 +1325,7 @@ wManageWindow(WScreen *scr, Window window) /* *-------------------------------------------------- - * + * * Create frame, borders and do reparenting * *-------------------------------------------------- @@ -1230,14 +1335,14 @@ wManageWindow(WScreen *scr, Window window) if (wPreferences.modelock) foo |= WFF_LANGUAGE_BUTTON; #endif - if (!WFLAGP(wwin, no_titlebar)) + if (HAS_TITLEBAR(wwin)) foo |= WFF_TITLEBAR; - if (!WFLAGP(wwin, no_resizebar)) + if (HAS_RESIZEBAR(wwin)) foo |= WFF_RESIZEBAR; - if (!WFLAGP(wwin, no_border)) + if (HAS_BORDER(wwin)) foo |= WFF_BORDER; - wwin->frame = wFrameWindowCreate(scr, window_level, + wwin->frame = wFrameWindowCreate(scr, window_level, x, y, width, height, &wPreferences.window_title_clearance, foo, scr->window_title_texture, @@ -1312,7 +1417,7 @@ wManageWindow(WScreen *scr, Window window) y -= wwin->frame->top_width + wwin->frame->bottom_width; } - /* + /* * wWindowConfigure() will init the client window's size * (wwin->client.{width,height}) and all other geometry * related variables (frame_x,frame_y) @@ -1324,7 +1429,7 @@ wManageWindow(WScreen *scr, Window window) /* *-------------------------------------------------- - * + * * Setup descriptors and save window to internal * lists * @@ -1342,12 +1447,10 @@ wManageWindow(WScreen *scr, Window window) if (leader && leader->main_window==None) { leader->main_window = leader->client_win; } - app = wApplicationCreate(scr, wwin->main_window); + app = wApplicationCreate(wwin); if (app) { app->last_workspace = workspace; - app->main_window_desc->fake_group = wwin->fake_group; - /* * Do application specific stuff, like setting application * wide attributes. @@ -1416,10 +1519,10 @@ wManageWindow(WScreen *scr, Window window) if (wPreferences.superfluous && !wPreferences.no_animations && !scr->flags.startup && (wwin->transient_for==None || wwin->transient_for==scr->root_win) - /* + /* * The brain damaged idiotic non-click to focus modes will * have trouble with this because: - * + * * 1. window is created and mapped by the client * 2. window is mapped by wmaker in small size * 3. window is animated to grow to normal size @@ -1427,7 +1530,7 @@ wManageWindow(WScreen *scr, Window window) * 5. eventually, the EnterNotify event that would trigger * the window focusing (if the mouse is over that window) * will be processed by wmaker. - * But since this event will be rather delayed + * But since this event will be rather delayed * (step 3 has a large delay) the time when the event ocurred * and when it is processed, the client that owns that window * will reject the XSetInputFocus() for it. @@ -1474,7 +1577,7 @@ wManageWindow(WScreen *scr, Window window) /* Update name must come after WApplication stuff is done */ wWindowUpdateName(wwin, title); if (title) - XFree(title); + XFree(title); XUngrabServer(dpy); @@ -1507,7 +1610,7 @@ wManageWindow(WScreen *scr, Window window) wColormapInstallForWindow(scr, scr->cmap_window); - + #ifdef OLWM_HINTS if (wwin->client_flags.olwm_warp_to_pin && wwin->frame->titlebar != NULL && !WFLAGP(wwin, no_close_button) && !withdraw) { @@ -1526,10 +1629,10 @@ wManageWindow(WScreen *scr, Window window) WMAddNotificationObserver(appearanceObserver, wwin, WNWindowAppearanceSettingsChanged, wwin); - + /* *-------------------------------------------------- - * + * * Cleanup temporary stuff * *-------------------------------------------------- @@ -1574,21 +1677,21 @@ wManageInternalWindow(WScreen *scr, Window window, Window owner, WSETUFLAG(wwin, no_miniaturizable, 1); wwin->focus_mode = WFM_PASSIVE; - + wwin->client_win = window; wwin->screen_ptr = scr; wwin->transient_for = owner; - + wwin->client.x = x; wwin->client.y = y; wwin->client.width = width; wwin->client.height = height; - + wwin->frame_x = wwin->client.x; wwin->frame_y = wwin->client.y; - + foo = WFF_RIGHT_BUTTON|WFF_BORDER; foo |= WFF_TITLEBAR; #ifdef XKB_BUTTON_HINT @@ -1603,7 +1706,7 @@ wManageInternalWindow(WScreen *scr, Window window, Window owner, scr->resizebar_texture, scr->window_title_color, &scr->title_font); - + XSaveContext(dpy, window, wWinContext, (XPointer)&wwin->client_descriptor); wwin->frame->flags.is_client_window_frame = 1; @@ -1616,28 +1719,28 @@ wManageInternalWindow(WScreen *scr, Window window, Window owner, /* hide buttons */ wFrameWindowHideButton(wwin->frame, WFF_RIGHT_BUTTON); - + wwin->frame->child = wwin; - + wwin->frame->workspace = wwin->screen_ptr->current_workspace; - + #ifdef XKB_BUTTON_HINT if (wPreferences.modelock) wwin->frame->on_click_language = windowLanguageClick; #endif - + wwin->frame->on_click_right = windowCloseClick; - + wwin->frame->on_mousedown_titlebar = titlebarMouseDown; wwin->frame->on_dblclick_titlebar = titlebarDblClick; - + wwin->frame->on_mousedown_resizebar = resizebarMouseDown; wwin->client.y += wwin->frame->top_width; - XReparentWindow(dpy, wwin->client_win, wwin->frame->core->window, + XReparentWindow(dpy, wwin->client_win, wwin->frame->core->window, 0, wwin->frame->top_width); - wWindowConfigure(wwin, wwin->frame_x, wwin->frame_y, + wWindowConfigure(wwin, wwin->frame_x, wwin->frame_y, wwin->client.width, wwin->client.height); /* setup the frame descriptor */ @@ -1648,7 +1751,7 @@ wManageInternalWindow(WScreen *scr, Window window, Window owner, XLowerWindow(dpy, window); XMapSubwindows(dpy, wwin->frame->core->window); - + /* setup stacking descriptor */ if (wwin->transient_for!=None && wwin->transient_for!=scr->root_win) { WWindow *tmp; @@ -1658,7 +1761,7 @@ wManageInternalWindow(WScreen *scr, Window window, Window owner, } else { wwin->frame->core->stacking->child_of = NULL; } - + if (!scr->focused_window) { /* first window on the list */ @@ -1692,17 +1795,17 @@ wManageInternalWindow(WScreen *scr, Window window, Window owner, /* - *---------------------------------------------------------------------- + *---------------------------------------------------------------------- * wUnmanageWindow-- * Removes the frame window from a window and destroys all data * related to it. The window will be reparented back to the root window * if restore is True. - * + * * Side effects: * Everything related to the window is destroyed and the window * is removed from the window lists. Focus is set to the previous on the * window list. - *---------------------------------------------------------------------- + *---------------------------------------------------------------------- */ void wUnmanageWindow(WWindow *wwin, Bool restore, Bool destroyed) @@ -1740,10 +1843,10 @@ wUnmanageWindow(WWindow *wwin, Bool restore, Bool destroyed) /* deselect window */ wSelectWindow(wwin, False); - + /* remove all pending events on window */ /* I think this only matters for autoraise */ - if (wPreferences.raise_delay) + if (wPreferences.raise_delay) WMDeleteTimerWithClientData(wwin->frame->core); XFlush(dpy); @@ -1764,7 +1867,7 @@ wUnmanageWindow(WWindow *wwin, Bool restore, Bool destroyed) } wasFocused = wwin->flags.focused; - + /* remove from window focus list */ if (!wwin->prev && !wwin->next) { /* was the only window */ @@ -1785,7 +1888,7 @@ wUnmanageWindow(WWindow *wwin, Bool restore, Bool destroyed) if (wPreferences.focus_mode==WKF_CLICK) { /* if in click to focus mode and the window - * was a transient, focus the owner window + * was a transient, focus the owner window */ tmp = NULL; if (wPreferences.focus_mode==WKF_CLICK) { @@ -1864,7 +1967,7 @@ wWindowMap(WWindow *wwin) XMapWindow(dpy, wwin->frame->core->window); if (!wwin->flags.shaded) { /* window will be remapped when getting MapNotify */ - XSelectInput(dpy, wwin->client_win, + XSelectInput(dpy, wwin->client_win, wwin->event_mask & ~StructureNotifyMask); XMapWindow(dpy, wwin->client_win); XSelectInput(dpy, wwin->client_win, wwin->event_mask); @@ -1880,7 +1983,7 @@ wWindowUnmap(WWindow *wwin) wwin->flags.mapped = 0; /* prevent window withdrawal when getting UnmapNotify */ - XSelectInput(dpy, wwin->client_win, + XSelectInput(dpy, wwin->client_win, wwin->event_mask & ~StructureNotifyMask); XUnmapWindow(dpy, wwin->client_win); XSelectInput(dpy, wwin->client_win, wwin->event_mask); @@ -1961,10 +2064,10 @@ wWindowUnfocus(WWindow *wwin) CloseWindowMenu(wwin->screen_ptr); if (wwin->flags.is_gnustep == 0) - wFrameWindowChangeState(wwin->frame, wwin->flags.semi_focused + wFrameWindowChangeState(wwin->frame, wwin->flags.semi_focused ? WS_PFOCUSED : WS_UNFOCUSED); - if (wwin->transient_for!=None + if (wwin->transient_for!=None && wwin->transient_for!=wwin->screen_ptr->root_win) { WWindow *owner; owner = wWindowFor(wwin->transient_for); @@ -1988,12 +2091,12 @@ void wWindowUpdateName(WWindow *wwin, char *newTitle) { char *title; - + if (!wwin->frame) return; - + wwin->flags.wm_name_changed = 1; - + if (!newTitle) { /* the hint was removed */ title = DEF_WINDOW_TITLE; @@ -2010,16 +2113,16 @@ wWindowUpdateName(WWindow *wwin, char *newTitle) /* *---------------------------------------------------------------------- - * + * * wWindowConstrainSize-- * Constrains size for the client window, taking the maximal size, * window resize increments and other size hints into account. - * + * * Returns: - * The closest size to what was given that the client window can + * The closest size to what was given that the client window can * have. - * - *---------------------------------------------------------------------- + * + *---------------------------------------------------------------------- */ void wWindowConstrainSize(WWindow *wwin, int *nwidth, int *nheight) @@ -2049,7 +2152,7 @@ wWindowConstrainSize(WWindow *wwin, int *nwidth, int *nheight) maxAX = wwin->normal_hints->max_aspect.x; maxAY = wwin->normal_hints->max_aspect.y; } - + baseW = wwin->normal_hints->base_width; baseH = wwin->normal_hints->base_height; } @@ -2061,7 +2164,7 @@ wWindowConstrainSize(WWindow *wwin, int *nwidth, int *nheight) if (width > maxW) width = maxW; - if (height > maxH) + if (height > maxH) height = maxH; /* aspect ratio code borrowed from olwm */ @@ -2122,7 +2225,7 @@ wWindowConstrainSize(WWindow *wwin, int *nwidth, int *nheight) void -wWindowCropSize(WWindow *wwin, int maxW, int maxH, +wWindowCropSize(WWindow *wwin, int maxW, int maxH, int *width, int *height) { int baseW = 0, baseH = 0; @@ -2131,16 +2234,16 @@ wWindowCropSize(WWindow *wwin, int maxW, int maxH, if (wwin->normal_hints) { baseW = wwin->normal_hints->base_width; baseH = wwin->normal_hints->base_height; - + winc = wwin->normal_hints->width_inc; - hinc = wwin->normal_hints->height_inc; + hinc = wwin->normal_hints->height_inc; } if (*width > maxW) *width = maxW - (maxW - baseW) % winc; if (*height > maxH) - *height = maxH - (maxH - baseH) % hinc; + *height = maxH - (maxH - baseH) % hinc; } @@ -2151,7 +2254,7 @@ wWindowChangeWorkspace(WWindow *wwin, int workspace) WApplication *wapp; int unmap = 0; - if (workspace >= scr->workspace_count || workspace < 0 + if (workspace >= scr->workspace_count || workspace < 0 || workspace == wwin->frame->workspace) return; @@ -2183,14 +2286,14 @@ wWindowChangeWorkspace(WWindow *wwin, int workspace) XMapWindow(dpy, wwin->icon->core->window); wwin->icon->mapped = 1; } - } else if (!wwin->flags.mapped && + } else if (!wwin->flags.mapped && !(wwin->flags.miniaturized || wwin->flags.hidden)) { wWindowMap(wwin); } } if (!IS_OMNIPRESENT(wwin)) { int oldWorkspace = wwin->frame->workspace; - + wwin->frame->workspace = workspace; WMPostNotificationName(WMNChangedWorkspace, wwin, (void*)oldWorkspace); @@ -2218,7 +2321,7 @@ wWindowSynthConfigureNotify(WWindow *wwin) sevent.xconfigure.height = wwin->client.height; sevent.xconfigure.border_width = wwin->old_border_width; - if (WFLAGP(wwin, no_titlebar)) + if (!HAS_TITLEBAR(wwin)) sevent.xconfigure.above = None; else sevent.xconfigure.above = wwin->frame->titlebar->window; @@ -2235,23 +2338,23 @@ wWindowSynthConfigureNotify(WWindow *wwin) /* *---------------------------------------------------------------------- * wWindowConfigure-- - * Configures the frame, decorations and client window to the + * Configures the frame, decorations and client window to the * specified geometry. The geometry is not checked for validity, - * wWindowConstrainSize() must be used for that. + * wWindowConstrainSize() must be used for that. * The size parameters are for the client window, but the position is * for the frame. * The client window receives a ConfigureNotify event, according * to what ICCCM says. - * + * * Returns: * None - * + * * Side effects: * Window size and position are changed and client window receives * a ConfigureNotify event. - *---------------------------------------------------------------------- + *---------------------------------------------------------------------- */ -void +void wWindowConfigure(wwin, req_x, req_y, req_width, req_height) WWindow *wwin; int req_x, req_y; /* new position of the frame */ @@ -2259,29 +2362,29 @@ int req_width, req_height; /* new size of the client */ { int synth_notify = False; int resize; - + resize = (req_width!=wwin->client.width || req_height!=wwin->client.height); - /* + /* * if the window is being moved but not resized then * send a synthetic ConfigureNotify */ if ((req_x!=wwin->frame_x || req_y!=wwin->frame_y) && !resize) { synth_notify = True; } - + if (WFLAGP(wwin, dont_move_off)) - wScreenBringInside(wwin->screen_ptr, &req_x, &req_y, + wScreenBringInside(wwin->screen_ptr, &req_x, &req_y, req_width, req_height); if (resize) { if (req_width < MIN_WINDOW_SIZE) req_width = MIN_WINDOW_SIZE; if (req_height < MIN_WINDOW_SIZE) req_height = MIN_WINDOW_SIZE; - + /* If growing, resize inner part before frame, * if shrinking, resize frame before. - * This will prevent the frame (that can have a different color) + * This will prevent the frame (that can have a different color) * to be exposed, causing flicker */ if (req_height > wwin->frame->core->height || req_width > wwin->frame->core->width) @@ -2294,7 +2397,7 @@ int req_width, req_height; /* new size of the client */ } else { int h; - h = req_height + wwin->frame->top_width + h = req_height + wwin->frame->top_width + wwin->frame->bottom_width; wFrameWindowConfigure(wwin->frame, req_x, req_y, req_width, h); @@ -2316,7 +2419,7 @@ int req_width, req_height; /* new size of the client */ } wwin->frame_x = req_x; wwin->frame_y = req_y; - if (!WFLAGP(wwin, no_border)) { + if (HAS_BORDER(wwin)) { wwin->client.x += FRAME_BORDER_WIDTH; wwin->client.y += FRAME_BORDER_WIDTH; } @@ -2333,7 +2436,7 @@ int req_width, req_height; /* new size of the client */ } -void +void wWindowMove(wwin, req_x, req_y) WWindow *wwin; int req_x, req_y; /* new position of the frame */ @@ -2356,7 +2459,7 @@ int req_x, req_y; /* new position of the frame */ wwin->client.x = req_x; wwin->client.y = req_y + wwin->frame->top_width; - if (!WFLAGP(wwin, no_border)) { + if (HAS_BORDER(wwin)) { wwin->client.x += FRAME_BORDER_WIDTH; wwin->client.y += FRAME_BORDER_WIDTH; } @@ -2380,7 +2483,7 @@ wWindowUpdateButtonImages(WWindow *wwin) Pixmap pixmap, mask; WFrameWindow *fwin = wwin->frame; - if (WFLAGP(wwin, no_titlebar)) + if (!HAS_TITLEBAR(wwin)) return; /* miniaturize button */ @@ -2389,7 +2492,7 @@ wWindowUpdateButtonImages(WWindow *wwin) if (wwin->wm_gnustep_attr && wwin->wm_gnustep_attr->flags & GSMiniaturizePixmapAttr) { pixmap = wwin->wm_gnustep_attr->miniaturize_pixmap; - + if (wwin->wm_gnustep_attr->flags&GSMiniaturizeMaskAttr) { mask = wwin->wm_gnustep_attr->miniaturize_mask; } else { @@ -2402,7 +2505,7 @@ wWindowUpdateButtonImages(WWindow *wwin) wPixmapDestroy(fwin->lbutton_image); fwin->lbutton_image = NULL; } - + if (!fwin->lbutton_image) { fwin->lbutton_image = wPixmapCreate(scr, pixmap, mask); fwin->lbutton_image->client_owned = 1; @@ -2418,25 +2521,25 @@ wWindowUpdateButtonImages(WWindow *wwin) #ifdef XKB_BUTTON_HINT if (!WFLAGP(wwin, no_language_button)) { - if (fwin->languagebutton_image && - !fwin->languagebutton_image->shared) { - wPixmapDestroy(fwin->languagebutton_image); - } - fwin->languagebutton_image = - scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode]; + if (fwin->languagebutton_image && + !fwin->languagebutton_image->shared) { + wPixmapDestroy(fwin->languagebutton_image); + } + fwin->languagebutton_image = + scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode]; } #endif /* close button */ -/* redefine WFLAGP to MGFLAGP to allow broken close operation */ + /* redefine WFLAGP to MGFLAGP to allow broken close operation */ #define MGFLAGP(wwin, FLAG) (wwin)->client_flags.FLAG if (!WFLAGP(wwin, no_close_button)) { - if (wwin->wm_gnustep_attr + if (wwin->wm_gnustep_attr && wwin->wm_gnustep_attr->flags & GSClosePixmapAttr) { pixmap = wwin->wm_gnustep_attr->close_pixmap; - + if (wwin->wm_gnustep_attr->flags&GSCloseMaskAttr) mask = wwin->wm_gnustep_attr->close_mask; else @@ -2447,7 +2550,7 @@ wWindowUpdateButtonImages(WWindow *wwin) wPixmapDestroy(fwin->rbutton_image); fwin->rbutton_image = NULL; } - + if (!fwin->rbutton_image) { fwin->rbutton_image = wPixmapCreate(scr, pixmap, mask); fwin->rbutton_image->client_owned = 1; @@ -2460,17 +2563,17 @@ wWindowUpdateButtonImages(WWindow *wwin) wPixmapDestroy(fwin->rbutton_image); fwin->rbutton_image = scr->b_pixmaps[WBUT_KILL]; - + } else if (MGFLAGP(wwin, broken_close)) { - if (fwin->rbutton_image && !fwin->rbutton_image->shared) + if (fwin->rbutton_image && !fwin->rbutton_image->shared) wPixmapDestroy(fwin->rbutton_image); fwin->rbutton_image = scr->b_pixmaps[WBUT_BROKENCLOSE]; } else { - if (fwin->rbutton_image && !fwin->rbutton_image->shared) + if (fwin->rbutton_image && !fwin->rbutton_image->shared) wPixmapDestroy(fwin->rbutton_image); fwin->rbutton_image = scr->b_pixmaps[WBUT_CLOSE]; @@ -2487,10 +2590,10 @@ wWindowUpdateButtonImages(WWindow *wwin) *--------------------------------------------------------------------------- * wWindowConfigureBorders-- * Update window border configuration according to attribute flags. - * - *--------------------------------------------------------------------------- + * + *--------------------------------------------------------------------------- */ -void +void wWindowConfigureBorders(WWindow *wwin) { if (wwin->frame) { @@ -2498,14 +2601,16 @@ wWindowConfigureBorders(WWindow *wwin) int newy, oldh; flags = WFF_LEFT_BUTTON|WFF_RIGHT_BUTTON; + #ifdef XKB_BUTTON_HINT - flags |= WFF_LANGUAGE_BUTTON; + flags |= WFF_LANGUAGE_BUTTON; #endif - if (!WFLAGP(wwin, no_titlebar)) + + if (HAS_TITLEBAR(wwin)) flags |= WFF_TITLEBAR; - if (!WFLAGP(wwin, no_resizebar) && !WFLAGP(wwin, no_resizable)) + if (HAS_RESIZEBAR(wwin) && IS_RESIZABLE(wwin)) flags |= WFF_RESIZEBAR; - if (!WFLAGP(wwin, no_border)) + if (HAS_BORDER(wwin)) flags |= WFF_BORDER; if (wwin->flags.shaded) flags |= WFF_IS_SHADED; @@ -2526,9 +2631,10 @@ wWindowConfigureBorders(WWindow *wwin) flags |= WFF_LEFT_BUTTON; #ifdef XKB_BUTTON_HINT - if (!WFLAGP(wwin, no_language_button) - && wwin->frame->flags.hide_language_button) - flags |= WFF_LANGUAGE_BUTTON; + if (!WFLAGP(wwin, no_language_button) + && wwin->frame->flags.hide_language_button) { + flags |= WFF_LANGUAGE_BUTTON; + } #endif if (!WFLAGP(wwin, no_close_button) @@ -2610,7 +2716,7 @@ getSavedState(Window window, WSavedState **state) unsigned long nitems_ret; unsigned long bytes_after_ret; CARD32 *data; - + if (XGetWindowProperty(dpy, window, _XA_WINDOWMAKER_STATE, 0, 10, True, _XA_WINDOWMAKER_STATE, &type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret, @@ -2634,7 +2740,7 @@ getSavedState(Window window, WSavedState **state) if (*state && type_ret==_XA_WINDOWMAKER_STATE) return 1; - else + else return 0; } @@ -2648,7 +2754,7 @@ wWindowClearShape(WWindow *wwin) XFlush(dpy); } -void +void wWindowSetShape(WWindow *wwin) { XRectangle rect[2]; @@ -2659,10 +2765,10 @@ wWindowSetShape(WWindow *wwin) int ordering; /* only shape is the client's */ - if (WFLAGP(wwin, no_titlebar) && WFLAGP(wwin, no_resizebar)) { + if (!HAS_TITLEBAR(wwin) && !HAS_RESIZEBAR(wwin)) { goto alt_code; } - + /* Get array of rectangles describing the shape mask */ rects = XShapeGetRectangles(dpy, wwin->client_win, ShapeBounding, &count, &ordering); @@ -2680,16 +2786,16 @@ wWindowSetShape(WWindow *wwin) memcpy(urec, rects, sizeof(XRectangle)*count); XFree(rects); - if (!WFLAGP(wwin, no_titlebar)) { + if (HAS_TITLEBAR(wwin)) { urec[count].x = -1; urec[count].y = -1 - wwin->frame->top_width; urec[count].width = wwin->frame->core->width + 2; urec[count].height = wwin->frame->top_width + 1; count++; } - if (!WFLAGP(wwin, no_resizebar)) { + if (HAS_RESIZEBAR(wwin)) { urec[count].x = -1; - urec[count].y = wwin->frame->core->height + urec[count].y = wwin->frame->core->height - wwin->frame->bottom_width - wwin->frame->top_width; urec[count].width = wwin->frame->core->width + 2; urec[count].height = wwin->frame->bottom_width + 1; @@ -2707,14 +2813,14 @@ wWindowSetShape(WWindow *wwin) alt_code: #endif /* OPTIMIZE_SHAPE */ count = 0; - if (!WFLAGP(wwin, no_titlebar)) { + if (HAS_TITLEBAR(wwin)) { rect[count].x = -1; rect[count].y = -1; rect[count].width = wwin->frame->core->width + 2; rect[count].height = wwin->frame->top_width + 1; count++; } - if (!WFLAGP(wwin, no_resizebar)) { + if (HAS_RESIZEBAR(wwin)) { rect[count].x = -1; rect[count].y = wwin->frame->core->height - wwin->frame->bottom_width; rect[count].width = wwin->frame->core->width + 2; @@ -2778,7 +2884,7 @@ wWindowSetKeyGrabs(WWindow *wwin) * work even if the NumLock/ScrollLock key is on. */ wHackedGrabKey(key->keycode, key->modifier, - wwin->frame->core->window, True, GrabModeAsync, + wwin->frame->core->window, True, GrabModeAsync, GrabModeAsync); #endif } @@ -2798,7 +2904,7 @@ wWindowResetMouseGrabs(WWindow *wwin) { /* Mouse grabs can't be done on the client window because of * ICCCM and because clients that try to do the same will crash. - * + * * But there is a problem wich makes tbar buttons of unfocused * windows not usable as the click goes to the frame window instead * of the button itself. Must figure a way to fix that. @@ -2812,7 +2918,7 @@ wWindowResetMouseGrabs(WWindow *wwin) True, ButtonPressMask|ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, None); } - + if (!wwin->flags.focused && !WFLAGP(wwin, no_focusable) && !wwin->flags.is_gnustep) { /* the passive grabs to focus the window */ @@ -2829,7 +2935,7 @@ void wWindowUpdateGNUstepAttr(WWindow *wwin, GNUstepWMAttributes *attr) { if (attr->flags & GSExtraFlagsAttr) { - if (MGFLAGP(wwin, broken_close) != + if (MGFLAGP(wwin, broken_close) != (attr->extra_flags & GSDocumentEditedFlag)) { wwin->client_flags.broken_close = !MGFLAGP(wwin, broken_close); wWindowUpdateButtonImages(wwin); @@ -2878,17 +2984,11 @@ wWindowGetSavedState(Window win) { char *instance, *class, *command=NULL; WWindowState *wstate = windowState; - char **argv; - int argc; if (!wstate) return NULL; - if (XGetCommand(dpy, win, &argv, &argc)) { - if (argc > 0) - command = wtokenjoin(argv, argc); - XFreeStringList(argv); - } + command = GetCommandForWindow(win); if (!command) return NULL; @@ -2918,7 +3018,7 @@ wWindowGetSavedState(Window win) } -void +void wWindowDeleteSavedState(WMagicNumber id) { WWindowState *tmp, *wstate=(WWindowState*)id; @@ -2959,7 +3059,7 @@ wWindowDeleteSavedState(WMagicNumber id) } -void +void wWindowDeleteSavedStatesForPID(pid_t pid) { WWindowState *tmp, *wstate; @@ -2998,7 +3098,7 @@ wWindowDeleteSavedStatesForPID(pid_t pid) } tmp = tmp->next; } - } + } } @@ -3015,7 +3115,7 @@ wWindowSetOmnipresent(WWindow *wwin, Bool flag) /* ====================================================================== */ -static void +static void resizebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) { WWindow *wwin = data; @@ -3027,12 +3127,12 @@ resizebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) "Turn it off or some mouse actions and keyboard shortcuts will not work.")); } #endif - + event->xbutton.state &= ValidModMask; - + CloseWindowMenu(wwin->screen_ptr); - if (wPreferences.focus_mode==WKF_CLICK + if (wPreferences.focus_mode==WKF_CLICK && !(event->xbutton.state&ControlMask) && !WFLAGP(wwin, no_focusable)) { wSetFocusTo(wwin->screen_ptr, wwin); @@ -3044,7 +3144,7 @@ resizebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) if (event->xbutton.window != wwin->frame->resizebar->window) { if (XGrabPointer(dpy, wwin->frame->resizebar->window, True, ButtonMotionMask|ButtonReleaseMask|ButtonPressMask, - GrabModeAsync, GrabModeAsync, None, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime)!=GrabSuccess) { #ifdef DEBUG0 wwarning("pointer grab failed for window move"); @@ -3052,7 +3152,7 @@ resizebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) return; } } - + if (event->xbutton.state & MOD_MASK) { /* move the window */ wMouseMoveWindow(wwin, event); @@ -3065,7 +3165,7 @@ resizebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) -static void +static void titlebarDblClick(WCoreWindow *sender, void *data, XEvent *event) { WWindow *wwin = data; @@ -3086,7 +3186,7 @@ titlebarDblClick(WCoreWindow *sender, void *data, XEvent *event) if (event->xbutton.state & ControlMask) dir |= MAX_VERTICAL; - + if (event->xbutton.state & ShiftMask) { dir |= MAX_HORIZONTAL; if (!(event->xbutton.state & ControlMask)) @@ -3094,7 +3194,7 @@ titlebarDblClick(WCoreWindow *sender, void *data, XEvent *event) } /* maximize window */ - if (dir!=0 && !WFLAGP(wwin, no_resizable)) { + if (dir!=0 && IS_RESIZABLE(wwin)) { int ndir = dir ^ wwin->flags.maximized; if (ndir != 0) { @@ -3124,7 +3224,7 @@ frameMouseDown(WObjDescriptor *desc, XEvent *event) WWindow *wwin = desc->parent; event->xbutton.state &= ValidModMask; - + CloseWindowMenu(wwin->screen_ptr); if (/*wPreferences.focus_mode==WKF_CLICK @@ -3135,10 +3235,10 @@ frameMouseDown(WObjDescriptor *desc, XEvent *event) if (event->xbutton.button == Button1) { wRaiseFrame(wwin->frame->core); } - + if (event->xbutton.state & MOD_MASK) { /* move the window */ - if (XGrabPointer(dpy, wwin->client_win, False, + if (XGrabPointer(dpy, wwin->client_win, False, ButtonMotionMask|ButtonReleaseMask|ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime)!=GrabSuccess) { @@ -3147,7 +3247,7 @@ frameMouseDown(WObjDescriptor *desc, XEvent *event) #endif return; } - if (event->xbutton.button == Button3 && !WFLAGP(wwin, no_resizable)) + if (event->xbutton.button == Button3) wMouseResizeWindow(wwin, event); else if (event->xbutton.button==Button1 || event->xbutton.button==Button2) wMouseMoveWindow(wwin, event); @@ -3156,7 +3256,7 @@ frameMouseDown(WObjDescriptor *desc, XEvent *event) } -static void +static void titlebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) { WWindow *wwin = (WWindow*)data; @@ -3172,7 +3272,7 @@ titlebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) CloseWindowMenu(wwin->screen_ptr); - if (wPreferences.focus_mode==WKF_CLICK + if (wPreferences.focus_mode==WKF_CLICK && !(event->xbutton.state&ControlMask) && !WFLAGP(wwin, no_focusable)) { wSetFocusTo(wwin->screen_ptr, wwin); @@ -3180,7 +3280,7 @@ titlebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) if (event->xbutton.button == Button1 || event->xbutton.button == Button2) { - + if (event->xbutton.button == Button1) { if (event->xbutton.state & MOD_MASK) { wLowerFrame(wwin->frame->core); @@ -3196,7 +3296,7 @@ titlebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) if (event->xbutton.window != wwin->frame->titlebar->window && XGrabPointer(dpy, wwin->frame->titlebar->window, False, ButtonMotionMask|ButtonReleaseMask|ButtonPressMask, - GrabModeAsync, GrabModeAsync, None, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime)!=GrabSuccess) { #ifdef DEBUG0 wwarning("pointer grab failed for window move"); @@ -3216,7 +3316,7 @@ titlebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) if (event->xbutton.window != wwin->frame->titlebar->window && XGrabPointer(dpy, wwin->frame->titlebar->window, False, ButtonMotionMask|ButtonReleaseMask|ButtonPressMask, - GrabModeAsync, GrabModeAsync, None, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime)!=GrabSuccess) { #ifdef DEBUG0 wwarning("pointer grab failed for window move"); @@ -3224,14 +3324,14 @@ titlebarMouseDown(WCoreWindow *sender, void *data, XEvent *event) return; } - OpenWindowMenu(wwin, event->xbutton.x_root, + OpenWindowMenu(wwin, event->xbutton.x_root, wwin->frame_y+wwin->frame->top_width, False); /* allow drag select */ desc = &wwin->screen_ptr->window_menu->menu->descriptor; event->xany.send_event = True; (*desc->handle_mousedown)(desc, event); - + XUngrabPointer(dpy, CurrentTime); } } @@ -3309,8 +3409,8 @@ windowLanguageClick(WCoreWindow *sender, void *data, XEvent *event) wwin->frame->languagemode = wwin->frame->last_languagemode; wwin->frame->last_languagemode = tl; wSetFocusTo(scr, wwin); - wwin->frame->languagebutton_image = - wwin->frame->screen_ptr->b_pixmaps[WBUT_XKBGROUP1 + + wwin->frame->languagebutton_image = + wwin->frame->screen_ptr->b_pixmaps[WBUT_XKBGROUP1 + wwin->frame->languagemode]; wFrameWindowUpdateLanguageButton(wwin->frame); if (event->xbutton.button == Button3) @@ -3326,7 +3426,7 @@ windowIconifyClick(WCoreWindow *sender, void *data, XEvent *event) WWindow *wwin = data; event->xbutton.state &= ValidModMask; - + CloseWindowMenu(wwin->screen_ptr); if (event->xbutton.button < Button1 || event->xbutton.button > Button3) @@ -3339,7 +3439,7 @@ windowIconifyClick(WCoreWindow *sender, void *data, XEvent *event) WApplication *wapp; if ((event->xbutton.state & ControlMask) || (event->xbutton.button == Button3)) { - + wapp = wApplicationOf(wwin->main_window); if (wapp && !WFLAGP(wwin, no_appicon)) wHideApplication(wapp); diff --git a/src/window.h b/src/window.h index 74005745..a8b359db 100644 --- a/src/window.h +++ b/src/window.h @@ -95,6 +95,7 @@ typedef struct { #ifdef XKB_BUTTON_HINT unsigned int no_language_button:1; #endif + unsigned int no_movable:1; /* decorations */ unsigned int no_resizebar:1; /* draw the bottom handle? */ @@ -135,6 +136,10 @@ typedef struct { unsigned int full_maximize:1; +#ifdef VIRTUAL_DESKTOP + unsigned int virtual_stick:1; +#endif + /* * emulate_app_icon must be automatically disabled for apps that can * generate their own appicons and for apps that have no_appicon=1 @@ -201,6 +206,11 @@ typedef struct WWindow { unsigned int width, height; /* original geometry of the window */ } old_geometry; /* (before things like maximize) */ + struct { + int x, y; + unsigned int width, height; /* original geometry of the window */ + } bfs_geometry; /* (before fullscreen) */ + /* client window info */ short old_border_width; /* original border width of client_win*/ Window client_win; /* the window we're managing */ @@ -257,6 +267,7 @@ typedef struct WWindow { unsigned int hidden:1; unsigned int shaded:1; unsigned int maximized:2; + unsigned int fullscreen:1; unsigned int omnipresent:1; unsigned int semi_focused:1; @@ -307,19 +318,36 @@ typedef struct WWindow { unsigned int olwm_push_pin_out:1;/* emulate pushpin behaviour */ unsigned int olwm_limit_menu:1; #endif -#ifdef NET_HINTS +#ifdef NETWM_HINTS unsigned int net_state_from_client:1; /* state hint was set by client */ - unsigned int net_skip_taskbar:1; unsigned int net_skip_pager:1; + unsigned int net_handle_icon:1; + unsigned int net_show_desktop:1; #endif } flags; /* state of the window */ struct WIcon *icon; /* icon info for the window */ int icon_x, icon_y; /* position of the icon */ +#ifdef NETWM_HINTS + int icon_w, icon_h; + RImage *net_icon_image; + Atom type; +#endif } WWindow; -#define IS_OMNIPRESENT(w) ((w)->flags.omnipresent ^ WFLAGP(w, omnipresent)) +#define HAS_TITLEBAR(w) (!(WFLAGP((w), no_titlebar) || (w)->flags.fullscreen)) +#define HAS_RESIZEBAR(w) (!(WFLAGP((w), no_resizebar) || (w)->flags.fullscreen)) +#define HAS_BORDER(w) (!(WFLAGP((w), no_border) || (w)->flags.fullscreen)) +#define IS_MOVABLE(w) (!(WFLAGP((w), no_movable) || (w)->flags.fullscreen)) +#define IS_RESIZABLE(w) (!(WFLAGP((w), no_resizable) || (w)->flags.fullscreen)) + +#ifdef VIRTUAL_DESKTOP +# define IS_VSTUCK(w) (WFLAGP((w), virtual_stick) || (w)->flags.fullscreen) +#endif + +/* XXX: CHECK THIS,.. IT SEEMED WEIRD TO ME!!! */ +#define IS_OMNIPRESENT(w) ((w)->flags.omnipresent | WFLAGP(w, omnipresent)) #define WINDOW_LEVEL(w) ((w)->frame->core->stacking->window_level) diff --git a/src/winmenu.c b/src/winmenu.c index 84462d2e..fe8f7215 100644 --- a/src/winmenu.c +++ b/src/winmenu.c @@ -586,10 +586,10 @@ updateMenuForWindow(WMenu *menu, WWindow *wwin) menu->entries[MC_MAXIMIZE]->text = text; } - wMenuSetEnabled(menu, MC_MAXIMIZE, !WFLAGP(wwin, no_resizable)); + wMenuSetEnabled(menu, MC_MAXIMIZE, IS_RESIZABLE(wwin)); - wMenuSetEnabled(menu, MC_MOVERESIZE, !WFLAGP(wwin, no_resizable) + wMenuSetEnabled(menu, MC_MOVERESIZE, IS_RESIZABLE(wwin) && !wwin->flags.miniaturized); if (wwin->flags.shaded) { diff --git a/src/winspector.c b/src/winspector.c index 9cec2677..9e52df36 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -47,6 +47,11 @@ #include "dock.h" #include "client.h" +#ifdef NETWM_HINTS +#include "wmspec.h" +#endif + +#include "xinerama.h" #include @@ -540,7 +545,7 @@ saveSettings(WMButton *button, InspectorPanel *panel) return; if (!dict) { - dict = WMCreatePLDictionary(NULL, NULL, NULL); + dict = WMCreatePLDictionary(NULL, NULL); if (dict) { db->dictionary = dict; } else { @@ -555,8 +560,8 @@ saveSettings(WMButton *button, InspectorPanel *panel) WMPLSetCaseSensitive(True); - winDic = WMCreatePLDictionary(NULL, NULL, NULL); - appDic = WMCreatePLDictionary(NULL, NULL, NULL); + winDic = WMCreatePLDictionary(NULL, NULL); + appDic = WMCreatePLDictionary(NULL, NULL); /* Update icon for window */ icon_file = WMGetTextFieldText(panel->fileText); @@ -875,6 +880,9 @@ applySettings(WMButton *button, InspectorPanel *panel) wwin->frame->flags.need_texture_change = 1; wWindowConfigureBorders(wwin); wFrameWindowPaint(wwin->frame); +#ifdef NETWM_HINTS + wNETWMUpdateActions(wwin, False); +#endif /* * Can't apply emulate_appicon because it will probably cause problems. diff --git a/src/wmspec.c b/src/wmspec.c index 87df9e50..a96231ae 100644 --- a/src/wmspec.c +++ b/src/wmspec.c @@ -1,9 +1,9 @@ /* wmspec.c-- support for the wm-spec Hints - * + * * Window Maker window manager - * + * * Copyright (c) 1998-2003 Alfredo K. Kojima - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -16,23 +16,42 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "wconfig.h" +#ifdef NETWM_HINTS + #include #include +#include #include "WindowMaker.h" #include "window.h" #include "screen.h" +#include "workspace.h" #include "framewin.h" #include "actions.h" +#include "client.h" +#include "wmspec.h" +#include "icon.h" +#include "stacking.h" +#include "xinerama.h" +#ifdef DEBUG_WMSPEC +#include +#endif + +/* Global variables */ +extern Atom _XA_WM_DELETE_WINDOW; +extern Time LastTimestamp; +extern WPreferences wPreferences; + +/* Root Window Properties */ static Atom net_supported; static Atom net_client_list; static Atom net_client_list_stacking; @@ -40,156 +59,439 @@ static Atom net_number_of_desktops; static Atom net_desktop_geometry; static Atom net_desktop_viewport; static Atom net_current_desktop; +static Atom net_desktop_names; static Atom net_active_window; -static Atom net_workarea; +static Atom net_workarea; /* XXX: not xinerama compatible */ static Atom net_supporting_wm_check; -/* net_virtual_roots N/A */ -/* TODO - * _NET_WM_NAME - * _NET_WM_VISIBLE_NAME - * _NET_WM_ICON_NAME - * _NET_WM_VISIBLE_ICON_NAME - * _NET_WM_WINDOW_TYPE - */ +static Atom net_virtual_roots; /* N/A */ +static Atom net_desktop_layout; /* XXX */ +static Atom net_showing_desktop; + +/* Other Root Window Messages */ +static Atom net_close_window; +static Atom net_moveresize_window; /* TODO */ +static Atom net_wm_moveresize; /* TODO */ + +/* Application Window Properties */ +static Atom net_wm_name; /* TODO */ +static Atom net_wm_visible_name; /* TODO */ +static Atom net_wm_icon_name; /* TODO */ +static Atom net_wm_visible_icon_name; /* TODO */ static Atom net_wm_desktop; +static Atom net_wm_window_type; +static Atom net_wm_window_type_desktop; +static Atom net_wm_window_type_dock; +static Atom net_wm_window_type_toolbar; +static Atom net_wm_window_type_menu; +static Atom net_wm_window_type_utility; +static Atom net_wm_window_type_splash; +static Atom net_wm_window_type_dialog; +static Atom net_wm_window_type_normal; static Atom net_wm_state; - -static Atom net_wm_strut; -/* - * _NET_WM_ICON_GEOMETRY - * _NET_WM_ICON - * _NET_WM_PID - * _NET_WM_HANDLED_ICONS - * - */ - -static Atom net_wm_state_modal; +static Atom net_wm_state_modal; /* XXX: what is this?!? */ static Atom net_wm_state_sticky; static Atom net_wm_state_maximized_vert; static Atom net_wm_state_maximized_horz; static Atom net_wm_state_shaded; static Atom net_wm_state_skip_taskbar; static Atom net_wm_state_skip_pager; +static Atom net_wm_state_hidden; +static Atom net_wm_state_fullscreen; +static Atom net_wm_state_above; +static Atom net_wm_state_below; +static Atom net_wm_allowed_actions; +static Atom net_wm_action_move; +static Atom net_wm_action_resize; +static Atom net_wm_action_minimize; +static Atom net_wm_action_shade; +static Atom net_wm_action_stick; +static Atom net_wm_action_maximize_horz; +static Atom net_wm_action_maximize_vert; +static Atom net_wm_action_fullscreen; +static Atom net_wm_action_change_desktop; +static Atom net_wm_action_close; +static Atom net_wm_strut; /* XXX: see net_workarea */ +static Atom net_wm_strut_partial; /* TODO: doesn't really fit into the current strut scheme */ +static Atom net_wm_icon_geometry; /* FIXME: should work together with net_wm_handled_icons, gnome-panel-2.2.0.1 doesn't use _NET_WM_HANDLED_ICONS, thus present situation. */ +static Atom net_wm_icon; +static Atom net_wm_pid; /* TODO */ +static Atom net_wm_handled_icons; /* FIXME: see net_wm_icon_geometry */ +/* Window Manager Protocols */ +static Atom net_wm_ping; /* TODO */ +static Atom utf8_string; -/* states */ +typedef struct { + char * name; + Atom * atom; +} atomitem_t; +static atomitem_t atomNames[] = { + { "_NET_SUPPORTED", &net_supported }, + { "_NET_CLIENT_LIST", &net_client_list }, + { "_NET_CLIENT_LIST_STACKING", &net_client_list_stacking }, + { "_NET_NUMBER_OF_DESKTOPS", &net_number_of_desktops }, + { "_NET_DESKTOP_GEOMETRY", &net_desktop_geometry }, + { "_NET_DESKTOP_VIEWPORT", &net_desktop_viewport }, + { "_NET_CURRENT_DESKTOP", &net_current_desktop }, + { "_NET_DESKTOP_NAMES", &net_desktop_names }, + { "_NET_ACTIVE_WINDOW", &net_active_window }, + { "_NET_WORKAREA", &net_workarea }, + { "_NET_SUPPORTING_WM_CHECK", &net_supporting_wm_check }, + { "_NET_VIRTUAL_ROOTS", &net_virtual_roots }, + { "_NET_DESKTOP_LAYOUT", &net_desktop_layout }, + { "_NET_SHOWING_DESKTOP", &net_showing_desktop }, -static char *atomNames[] = { - "_NET_SUPPORTED", - "_NET_CLIENT_LIST", - "_NET_NUMBER_OF_DESKTOPS", - "_NET_DESKTOP_GEOMETRY", - "_NET_DESKTOP_VIEWPORT", - "_NET_CURRENT_DESKTOP", - "_NET_ACTIVE_WINDOW", - "_NET_WORKAREA", - "_NET_SUPPORTING_WM_CHECK", - "_NET_WM_DESKTOP", - "_NET_WM_STATE", - "_NET_WM_STRUT", - - - - "_NET_WM_STATE_MODAL", - "_NET_WM_STATE_STICKY", - "_NET_WM_STATE_MAXIMIZED_VERT", - "_NET_WM_STATE_MAXIMIZED_HORZ", - "_NET_WM_STATE_SHADED", - "_NET_WM_STATE_SKIP_TASKBAR", - "_NET_WM_STATE_SKIP_PAGER" + { "_NET_CLOSE_WINDOW", &net_close_window }, + { "_NET_MOVERESIZE_WINDOW", &net_moveresize_window }, + { "_NET_WM_MOVERESIZE", &net_wm_moveresize }, + + { "_NET_WM_NAME", &net_wm_name }, + { "_NET_WM_VISIBLE_NAME", &net_wm_visible_name }, + { "_NET_WM_ICON_NAME", &net_wm_icon_name }, + { "_NET_WM_VISIBLE_ICON_NAME", &net_wm_visible_icon_name }, + { "_NET_WM_DESKTOP", &net_wm_desktop }, + { "_NET_WM_WINDOW_TYPE", &net_wm_window_type }, + { "_NET_WM_WINDOW_TYPE_DESKTOP", &net_wm_window_type_desktop }, + { "_NET_WM_WINDOW_TYPE_DOCK", &net_wm_window_type_dock }, + { "_NET_WM_WINDOW_TYPE_TOOLBAR", &net_wm_window_type_toolbar }, + { "_NET_WM_WINDOW_TYPE_MENU", &net_wm_window_type_menu }, + { "_NET_WM_WINDOW_TYPE_UTILITY", &net_wm_window_type_utility }, + { "_NET_WM_WINDOW_TYPE_SPLASH", &net_wm_window_type_splash }, + { "_NET_WM_WINDOW_TYPE_DIALOG", &net_wm_window_type_dialog }, + { "_NET_WM_WINDOW_TYPE_NORMAL", &net_wm_window_type_normal }, + { "_NET_WM_STATE", &net_wm_state }, + { "_NET_WM_STATE_MODAL", &net_wm_state_modal }, + { "_NET_WM_STATE_STICKY", &net_wm_state_sticky }, + { "_NET_WM_STATE_MAXIMIZED_VERT", &net_wm_state_maximized_vert }, + { "_NET_WM_STATE_MAXIMIZED_HORZ", &net_wm_state_maximized_horz }, + { "_NET_WM_STATE_SHADED", &net_wm_state_shaded }, + { "_NET_WM_STATE_SKIP_TASKBAR", &net_wm_state_skip_taskbar }, + { "_NET_WM_STATE_SKIP_PAGER", &net_wm_state_skip_pager }, + { "_NET_WM_STATE_HIDDEN", &net_wm_state_hidden }, + { "_NET_WM_STATE_FULLSCREEN", &net_wm_state_fullscreen }, + { "_NET_WM_STATE_ABOVE", &net_wm_state_above }, + { "_NET_WM_STATE_BELOW", &net_wm_state_below }, + { "_NET_WM_ALLOWED_ACTIONS", &net_wm_allowed_actions }, + { "_NET_WM_ACTION_MOVE", &net_wm_action_move }, + { "_NET_WM_ACTION_RESIZE", &net_wm_action_resize }, + { "_NET_WM_ACTION_MINIMIZE", &net_wm_action_minimize }, + { "_NET_WM_ACTION_SHADE", &net_wm_action_shade }, + { "_NET_WM_ACTION_STICK", &net_wm_action_stick }, + { "_NET_WM_ACTION_MAXIMIZE_HORZ", &net_wm_action_maximize_horz }, + { "_NET_WM_ACTION_MAXIMIZE_VERT", &net_wm_action_maximize_vert }, + { "_NET_WM_ACTION_FULLSCREEN", &net_wm_action_fullscreen }, + { "_NET_WM_ACTION_CHANGE_DESKTOP", &net_wm_action_change_desktop }, + { "_NET_WM_ACTION_CLOSE", &net_wm_action_close }, + { "_NET_WM_STRUT", &net_wm_strut }, + { "_NET_WM_STRUT_PARTIAL", &net_wm_strut_partial }, + { "_NET_WM_ICON_GEOMETRY", &net_wm_icon_geometry }, + { "_NET_WM_ICON", &net_wm_icon }, + { "_NET_WM_PID", &net_wm_pid }, + { "_NET_WM_HANDLED_ICONS", &net_wm_handled_icons }, + + { "_NET_WM_PING", &net_wm_ping }, + + { "UTF8_STRING", &utf8_string }, }; +#define atomNr (sizeof(atomNames)/sizeof(atomitem_t)) + +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 +#define _NET_WM_STATE_TOGGLE 2 + +#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 +#define _NET_WM_MOVERESIZE_SIZE_TOP 1 +#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 +#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 +#define _NET_WM_MOVERESIZE_SIZE_LEFT 7 +#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */ +#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */ +#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */ + static void observer(void *self, WMNotification *notif); static void wsobserver(void *self, WMNotification *notif); +static void updateClientList(WScreen *scr); +static void updateClientListStacking(WScreen *scr, WWindow *); + +static void updateWorkspaceNames(WScreen *scr); +static void updateCurrentWorkspace(WScreen *scr); +static void updateWorkspaceCount(WScreen *scr); typedef struct NetData { WScreen *scr; - Window *client_windows; - int client_count; - int client_size; + WReservedArea *strut; + WWindow **show_desktop; } NetData; - - - -static void setSupportedHints(WScreen *scr) +static void +setSupportedHints(WScreen *scr) { - Atom atom[32]; + Atom atom[atomNr]; int i = 0; - unsigned int sizes[2]; - + /* set supported hints list */ - + /* XXX: extend this !!! */ + atom[i++] = net_client_list; + atom[i++] = net_client_list_stacking; + atom[i++] = net_number_of_desktops; + atom[i++] = net_desktop_geometry; + atom[i++] = net_desktop_viewport; + atom[i++] = net_current_desktop; + atom[i++] = net_desktop_names; + atom[i++] = net_active_window; + atom[i++] = net_workarea; + atom[i++] = net_supporting_wm_check; + atom[i++] = net_showing_desktop; +#if 0 + atom[i++] = net_wm_moveresize; +#endif + atom[i++] = net_wm_desktop; + atom[i++] = net_wm_window_type; + atom[i++] = net_wm_window_type_desktop; + atom[i++] = net_wm_window_type_dock; + atom[i++] = net_wm_window_type_toolbar; + atom[i++] = net_wm_window_type_menu; + atom[i++] = net_wm_window_type_utility; + atom[i++] = net_wm_window_type_splash; + atom[i++] = net_wm_window_type_dialog; + atom[i++] = net_wm_window_type_normal; + + atom[i++] = net_wm_state; + /* atom[i++] = net_wm_state_modal; */ /* XXX: not sure where/when to use it. */ + atom[i++] = net_wm_state_sticky; + atom[i++] = net_wm_state_shaded; + atom[i++] = net_wm_state_maximized_horz; + atom[i++] = net_wm_state_maximized_vert; + atom[i++] = net_wm_state_skip_taskbar; + atom[i++] = net_wm_state_skip_pager; + atom[i++] = net_wm_state_hidden; + atom[i++] = net_wm_state_fullscreen; + atom[i++] = net_wm_state_above; + atom[i++] = net_wm_state_below; + + atom[i++] = net_wm_allowed_actions; + atom[i++] = net_wm_action_move; + atom[i++] = net_wm_action_resize; + atom[i++] = net_wm_action_minimize; + atom[i++] = net_wm_action_shade; + atom[i++] = net_wm_action_stick; + atom[i++] = net_wm_action_maximize_horz; + atom[i++] = net_wm_action_maximize_vert; + atom[i++] = net_wm_action_fullscreen; + atom[i++] = net_wm_action_change_desktop; + atom[i++] = net_wm_action_close; + + atom[i++] = net_wm_strut; + atom[i++] = net_wm_icon_geometry; + atom[i++] = net_wm_icon; + atom[i++] = net_wm_handled_icons; + + XChangeProperty(dpy, scr->root_win, net_supported, XA_ATOM, 32, + PropModeReplace, (unsigned char*)atom, i); - - XChangeProperty(dpy, scr->root_win, - net_supported, XA_ATOM, 32, - PropModeReplace, (unsigned char*)atom, i); - /* set supporting wm hint */ - XChangeProperty(dpy, scr->root_win, - net_supporting_wm_check, XA_WINDOW, 32, - PropModeReplace, - (unsigned char*)&scr->info_window, 1); - - XChangeProperty(dpy, scr->info_window, - net_supporting_wm_check, XA_WINDOW, 32, - PropModeReplace, - (unsigned char*)&scr->info_window, 1); - - - /* set desktop geometry. dynamic change is not supported */ - sizes[0] = scr->scr_width; - sizes[1] = scr->scr_height; - - XChangeProperty(dpy, scr->root_win, - net_desktop_geometry, XA_CARDINAL, 32, - PropModeReplace, - (unsigned char*)&sizes, 2); - - /* set desktop viewport. dynamic change is not supported */ - sizes[0] = 0; - sizes[1] = 0; - - XChangeProperty(dpy, scr->root_win, - net_desktop_viewport, XA_CARDINAL, 32, - PropModeReplace, - (unsigned char*)&sizes, 2); + XChangeProperty(dpy, scr->root_win, net_supporting_wm_check, XA_WINDOW, 32, + PropModeReplace, (unsigned char*)&scr->info_window, 1); + XChangeProperty(dpy, scr->info_window, net_supporting_wm_check, XA_WINDOW, + 32, PropModeReplace, (unsigned char*)&scr->info_window, 1); } -void netwmInitialize(WScreen *scr) +void +wNETWMUpdateDesktop(WScreen *scr) +{ + CARD32 *views, sizes[2]; + int count, i; + + if (scr->workspace_count==0) + return; + + count = scr->workspace_count * 2; + views = wmalloc(sizeof(CARD32) * count); + /*memset(views, 0, sizeof(CARD32) * count);*/ + +#ifdef VIRTUAL_DESKTOP + sizes[0] = scr->workspaces[scr->current_workspace]->width; + sizes[1] = scr->workspaces[scr->current_workspace]->height; +#else + sizes[0] = scr->scr_width; + sizes[1] = scr->scr_height; +#endif + + for (i=0; iworkspace_count; i++) { +#ifdef VIRTUAL_DESKTOP + views[2*i + 0] = scr->workspaces[i]->view_x; + views[2*i + 1] = scr->workspaces[i]->view_y; +#else + views[2*i + 0] = 0; + views[2*i + 1] = 0; +#endif + } + + XChangeProperty(dpy, scr->root_win, net_desktop_geometry, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)sizes, 2); + + XChangeProperty(dpy, scr->root_win, net_desktop_viewport, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)views, count); + + wfree(views); +} + + +static void +updateIconImage(WScreen *scr, WWindow *wwin) +{ + Atom actual_type_return; + int actual_format_return; + unsigned long nitems_return, bytes_after_return; + unsigned char *prop_return; + int rc = XGetWindowProperty(dpy, wwin->client_win, net_wm_icon, 0, ~0, False, + XA_CARDINAL, &actual_type_return, &actual_format_return, + &nitems_return, &bytes_after_return, &prop_return); + + if (rc==Success && prop_return) { + unsigned int *data = (unsigned int *)prop_return; + unsigned int pos = 0, len = 0; + unsigned int best_pos = 0, best_tmp = ~0; + extern WPreferences wPreferences; + unsigned int pref_size = wPreferences.icon_size; + unsigned int pref_sq = pref_size*pref_size; + char *src, *dst; + RImage *new_rimage; + + do { + len = data[pos+0]*data[pos+1]; + unsigned int tmp = pref_sq-len; + if (tmp < best_tmp && tmp > 0) { + best_tmp = tmp; + best_pos = pos; + } + pos += 2+len; + } while (pos < nitems_return && len != 0); + + new_rimage = RCreateImage(data[best_pos+0], data[best_pos+1], True); + len = data[best_pos+0] * data[best_pos+1]; + src = (char*)&data[best_pos+2]; + dst = new_rimage->data; + for (pos=0; posnet_icon_image) + RReleaseImage(wwin->net_icon_image); + wwin->net_icon_image = new_rimage; + } + + XFree(prop_return); + } +} + + +static void +updateShowDesktop(WScreen * scr, Bool show) +{ + CARD32 foo; + + foo = (show == True); + XChangeProperty(dpy, scr->root_win, net_showing_desktop, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&foo, 1); +} + + +void +wNETWMShowingDesktop(WScreen *scr, Bool show) +{ + if (show && scr->netdata->show_desktop == NULL) { + WWindow *tmp, **wins; + int i=0; + + wins = (WWindow **)wmalloc(sizeof(WWindow *)*(scr->window_count+1)); + + tmp = scr->focused_window; + while (tmp) { + if (!tmp->flags.hidden && !tmp->flags.miniaturized && + !WFLAGP(tmp, skip_window_list)) { + + wins[i++] = tmp; + tmp->flags.skip_next_animation = 1; + tmp->flags.net_show_desktop = 1; + wIconifyWindow(tmp); + } + + tmp = tmp->prev; + } + wins[i++] = NULL; + + scr->netdata->show_desktop = wins; + updateShowDesktop(scr, True); + } else if (scr->netdata->show_desktop != NULL) { + /* FIXME: get rid of workspace flashing ! */ + int ws = scr->current_workspace; + WWindow **tmp; + for (tmp = scr->netdata->show_desktop; *tmp; ++tmp) { + wDeiconifyWindow(*tmp); + (*tmp)->flags.net_show_desktop = 0; + } + if (ws != scr->current_workspace) + wWorkspaceChange(scr, ws); + wfree(scr->netdata->show_desktop); + scr->netdata->show_desktop = NULL; + updateShowDesktop(scr, False); + } +} + + +void +wNETWMInitStuff(WScreen *scr) { NetData *data; - Atom atom[32]; + int i; + +#ifdef DEBUG_WMSPEC + printf( "wNETWMInitStuff\n"); +#endif #ifdef HAVE_XINTERNATOMS - XInternAtoms(dpy, atomNames, sizeof(atomNames)/sizeof(char*), - False, atom); -#else { - int i; - for (i = 0; i < sizeof(atomNames)/sizeof(char*); i++) { - atom[i] = XInternAtom(dpy, atomNames[i], False); - } + Atom atoms[atomNr]; + char * names[atomNr]; + + for (i = 0; i < atomNr; ++i) { + names[i] = atomNames[i].name; + } + XInternAtoms(dpy, &names[0], atomNr, False, atoms); + for (i = 0; i < atomNr; ++i) { + *atomNames[i].atom = atoms[i]; + } + } +#else + for (i = 0; i < atomNr; i++) { + *atomNames[i].atom = XInternAtom(dpy, atomNames[i].name, False); } #endif - net_supported = atom[0]; - net_client_list = atom[1]; - - setSupportedHints(scr); - + data = wmalloc(sizeof(NetData)); data->scr = scr; - data->client_windows = NULL; - data->client_count = 0; - data->client_size = 0; + data->strut = NULL; + data->show_desktop = NULL; + + scr->netdata = data; + + setSupportedHints(scr); WMAddNotificationObserver(observer, data, WMNManaged, NULL); WMAddNotificationObserver(observer, data, WMNUnmanaged, NULL); @@ -203,195 +505,1015 @@ void netwmInitialize(WScreen *scr) WMAddNotificationObserver(wsobserver, data, WMNWorkspaceDestroyed, NULL); WMAddNotificationObserver(wsobserver, data, WMNWorkspaceChanged, NULL); WMAddNotificationObserver(wsobserver, data, WMNWorkspaceNameChanged, NULL); + + updateClientList(scr); + updateClientListStacking(scr, NULL); + updateWorkspaceCount(scr); + updateCurrentWorkspace(scr); + updateWorkspaceNames(scr); + updateShowDesktop(scr, False); + + wScreenUpdateUsableArea(scr); } void -netwmUpdateWorkarea(WScreen *scr) +wNETWMUpdateActions(WWindow *wwin, Bool del) { - unsigned int area[4]; - - /* XXX */ + Atom action[10]; /* nr of actions atoms defined */ + int i = 0; - XChangeProperty(dpy, scr->root_win, net_workarea, XA_CARDINAL, 32, - PropModeReplace, - (unsigned char*)area, 4); + if (del) { + XDeleteProperty(dpy, wwin->client_win, net_wm_allowed_actions); + return; + } + + if (IS_MOVABLE(wwin)) + action[i++] = net_wm_action_move; + + if (IS_RESIZABLE(wwin)) + action[i++] = net_wm_action_resize; + + if (!WFLAGP(wwin, no_miniaturizable)) + action[i++] = net_wm_action_minimize; + + if (!WFLAGP(wwin, no_shadeable)) + action[i++] = net_wm_action_shade; + + /* if (!WFLAGP(wwin, no_stickable)) */ + action[i++] = net_wm_action_stick; + + /* if (!(WFLAGP(wwin, no_maximizeable) & MAX_HORIZONTAL)) */ + if (IS_RESIZABLE(wwin)) + action[i++] = net_wm_action_maximize_horz; + + /* if (!(WFLAGP(wwin, no_maximizeable) & MAX_VERTICAL)) */ + if (IS_RESIZABLE(wwin)) + action[i++] = net_wm_action_maximize_vert; + + /* if (!WFLAGP(wwin, no_fullscreen)) */ + action[i++] = net_wm_action_fullscreen; + + /* if (!WFLAGP(wwin, no_change_desktop)) */ + action[i++] = net_wm_action_change_desktop; + + if (!WFLAGP(wwin, no_closable)) + action[i++] = net_wm_action_close; + + XChangeProperty(dpy, wwin->client_win, net_wm_allowed_actions, + XA_ATOM, 32, PropModeReplace, (unsigned char *)action, i); } +void +wNETWMUpdateWorkarea(WScreen *scr, WArea usableArea) +{ + CARD32 *area; + int count, i; + + /* XXX: not Xinerama compatible, + xinerama gets the largest available */ + + if(!scr->netdata || scr->workspace_count==0) + return; + + count = scr->workspace_count * 4; + area = wmalloc(sizeof(CARD32) * count); + for (i=0; iworkspace_count; i++) { + area[4*i + 0] = usableArea.x1; + area[4*i + 1] = usableArea.y1; + area[4*i + 2] = usableArea.x2 - usableArea.x1; + area[4*i + 3] = usableArea.y2 - usableArea.y1; + } + + XChangeProperty(dpy, scr->root_win, net_workarea, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)area, count); + + wfree(area); +} + + +Bool +wNETWMGetUsableArea(WScreen *scr, int head, WArea *area) +{ + WReservedArea *cur; + WMRect rect; + + if(!scr->netdata || !scr->netdata->strut) + return False; + + area->x1 = area->y1 = area->x2 = area->y2 = 0; + + for(cur = scr->netdata->strut ; cur ; cur = cur->next) { + WWindow * wwin = wWindowFor(cur->window); + if (wWindowTouchesHead(wwin, head)) { + if(cur->area.x1 > area->x1) + area->x1 = cur->area.x1; + if(cur->area.y1 > area->y1) + area->y1 = cur->area.y1; + if(cur->area.x2 > area->x2) + area->x2 = cur->area.x2; + if(cur->area.y2 > area->y2) + area->y2 = cur->area.y2; + } + } + + if (area->x1==0 && area->x2==0 && + area->y1==0 && area->y2==0) return False; + + rect = wGetRectForHead(scr, head); + + area->x1 = rect.pos.x + area->x1; + area->x2 = rect.pos.x + rect.size.width - area->x2; + area->y1 = rect.pos.y + area->y1; + area->y2 = rect.pos.y + rect.size.height - area->y2; + + return True; +} + static void -updateClientList(WScreen *scr, WWindow *wwin, Bool added) +updateClientList(WScreen *scr) { - NetData *data = scr->netdata; + WWindow *wwin; + Window *windows; + int count; - if (added) { - if (data->client_count == data->client_size) { - data->client_size += 20; - data->client_windows = wrealloc(data->client_windows, - sizeof(Window)*data->client_size); - } + windows = (Window *)wmalloc(sizeof(Window)*(scr->window_count+1)); - data->client_windows[data->client_count++] = wwin->client_win; - - XChangeProperty(dpy, scr->root_win, net_client_list, XA_WINDOW, 32, - PropModeAppend, (unsigned char*)&wwin->client_win, 1); - } else { - int i; - for (i = 0; i < data->client_count; i++) { - if (data->client_windows[i] == wwin->client_win) { - if (data->client_count-1 > i) { - memmove(data->client_windows+i, - data->client_windows+i+1, - (data->client_count-i-1)*sizeof(Window)); - } - data->client_count--; - break; - } - } - - /* update client list */ - XChangeProperty(dpy, scr->root_win, net_client_list, XA_WINDOW, 32, - PropModeReplace, - (unsigned char *)data->client_windows, - data->client_count); + count = 0; + wwin = scr->focused_window; + while (wwin) { + windows[count++] = wwin->client_win; + wwin = wwin->prev; } + XChangeProperty(dpy, scr->root_win, net_client_list, XA_WINDOW, 32, + PropModeReplace, (unsigned char*)windows, count); + + wfree(windows); XFlush(dpy); } - static void -updateClientListStacking(WScreen *scr) +updateClientListStacking(WScreen *scr, WWindow *wwin_excl) { WWindow *wwin; Window *client_list; + Window *client_list_reverse; int client_count; WCoreWindow *tmp; WMBagIterator iter; + int i; /* update client list */ - - client_list = (Window*)malloc(sizeof(Window)*scr->window_count); - if (!client_list) { - wwarning(_("out of memory while updating wm hints")); - return; - } + i = scr->window_count + 1; + client_list = (Window*)wmalloc(sizeof(Window) * i); + client_list_reverse = (Window*)wmalloc(sizeof(Window) * i); + client_count = 0; WM_ETARETI_BAG(scr->stacking_list, tmp, iter) { - while (tmp) { - client_list[client_count++] = tmp->window; - tmp = tmp->stacking->under; - } + while (tmp) { + wwin = wWindowFor(tmp->window); + /* wwin_excl is a window to exclude from the list + (e.g. it's now unmanaged) */ + if(wwin && (wwin != wwin_excl)) + client_list[client_count++] = wwin->client_win; + tmp = tmp->stacking->under; + } } - XChangeProperty(dpy, scr->root_win, - net_client_list_stacking, XA_WINDOW, 32, - PropModeReplace, - (unsigned char *)client_list, client_count); + for(i = 0; i < client_count; i++) { + Window w = client_list[client_count - i - 1]; + client_list_reverse[i] = w; + } + + XChangeProperty(dpy, scr->root_win, net_client_list_stacking, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)client_list_reverse, client_count); wfree(client_list); + wfree(client_list_reverse); XFlush(dpy); } - static void updateWorkspaceCount(WScreen *scr) /* changeable */ { - unsigned int count = scr->workspace_count; - - XChangeProperty(dpy, scr->root_win, - net_number_of_desktops, XA_CARDINAL, 32, - PropModeReplace, - (unsigned char*)&count, 1); + CARD32 count; + + count = scr->workspace_count; + + XChangeProperty(dpy, scr->root_win, net_number_of_desktops, XA_CARDINAL, + 32, PropModeReplace, (unsigned char*)&count, 1); } static void updateCurrentWorkspace(WScreen *scr) /* changeable */ { - unsigned int count = scr->current_workspace; - - XChangeProperty(dpy, scr->root_win, - net_current_desktop, XA_CARDINAL, 32, - PropModeReplace, - (unsigned char*)&count, 1); + CARD32 count; + + count = scr->current_workspace; + + XChangeProperty(dpy, scr->root_win, net_current_desktop, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)&count, 1); } static void -updateWorkspaceNames(WScreen *scr, int workspace) +updateWorkspaceNames(WScreen *scr) { - /* XXX UTF 8 */ + char buf[1024], *pos; + unsigned int i, len, curr_size; + + pos = buf; + len = 0; + for(i = 0; i < scr->workspace_count; i++) { + curr_size = strlen(scr->workspaces[i]->name); + strcpy(pos, scr->workspaces[i]->name); + pos += (curr_size+1); + len += (curr_size+1); + } + + XChangeProperty(dpy, scr->root_win, net_desktop_names, utf8_string, 8, + PropModeReplace, (unsigned char *)buf, len); } static void updateFocusHint(WScreen *scr, WWindow *wwin) /* changeable */ { - Window window = None; - - if (wwin) - window = wwin->client_win; - - XChangeProperty(dpy, scr->root_win, - net_active_window, XA_WINDOW, 32, - PropModeReplace, - (unsigned char*)&window, 1); + Window window; + + if (!scr->focused_window || !scr->focused_window->flags.focused) + window = None; + else + window = scr->focused_window->client_win; + + XChangeProperty(dpy, scr->root_win, net_active_window, XA_WINDOW, 32, + PropModeReplace, (unsigned char*)&window, 1); } static void -updateWorkspaceHint(WWindow *wwin, Bool del) +updateWorkspaceHint(WWindow *wwin, Bool fake, Bool del) { + CARD32 l; + if (del) { - XDeleteProperty(dpy, wwin->client_win, net_wm_desktop); + XDeleteProperty(dpy, wwin->client_win, net_wm_desktop); } else { - XChangeProperty(dpy, wwin->screen_ptr->root_win, - net_wm_desktop, XA_CARDINAL, 32, - PropModeReplace, - (unsigned char*)&wwin->frame->workspace, 1); + l = ((fake || IS_OMNIPRESENT(wwin)) ? -1 : wwin->frame->workspace); + XChangeProperty(dpy, wwin->client_win, net_wm_desktop, XA_CARDINAL, + 32, PropModeReplace, (unsigned char*)&l, 1); } } static void -updateStateHint(WWindow *wwin, Bool del) /* changeable */ +updateStateHint(WWindow *wwin, Bool changedWorkspace, Bool del) /* changeable */ { if (del) { - if (!wwin->flags.net_state_from_client) - XDeleteProperty(dpy, wwin->client_win, net_wm_state); + if (!wwin->flags.net_state_from_client) { + XDeleteProperty(dpy, wwin->client_win, net_wm_state); + } } else { - Atom state[8]; - int i = 0; - - if (wwin->flags.omnipresent) - state[i++] = net_wm_state_sticky; - if (wwin->flags.maximized & MAX_HORIZONTAL) - state[i++] = net_wm_state_maximized_horz; - if (wwin->flags.maximized & MAX_VERTICAL) - state[i++] = net_wm_state_maximized_vert; - if (wwin->flags.shaded) - state[i++] = net_wm_state_shaded; - if (WFLAGP(wwin, skip_window_list) || wwin->flags.net_skip_taskbar) - state[i++] = net_wm_state_skip_taskbar; - if (wwin->flags.net_skip_pager) - state[i++] = net_wm_state_skip_pager; + Atom state[11]; /* nr of defined state atoms */ + int i = 0; + + if(changedWorkspace || (wPreferences.sticky_icons && !IS_OMNIPRESENT(wwin))) + updateWorkspaceHint(wwin, False, False); + + if (IS_OMNIPRESENT(wwin)) + state[i++] = net_wm_state_sticky; + if (wwin->flags.shaded) + state[i++] = net_wm_state_shaded; + if (wwin->flags.maximized & MAX_HORIZONTAL) + state[i++] = net_wm_state_maximized_horz; + if (wwin->flags.maximized & MAX_VERTICAL) + state[i++] = net_wm_state_maximized_vert; + if (WFLAGP(wwin, skip_window_list)) + state[i++] = net_wm_state_skip_taskbar; + if (wwin->flags.net_skip_pager) + state[i++] = net_wm_state_skip_pager; + if ((wwin->flags.hidden || wwin->flags.miniaturized) && !wwin->flags.net_show_desktop){ + state[i++] = net_wm_state_hidden; + state[i++] = net_wm_state_skip_pager; + + if (wwin->flags.miniaturized && wPreferences.sticky_icons) { + if( !IS_OMNIPRESENT(wwin)) + updateWorkspaceHint(wwin, True, False); + state[i++] = net_wm_state_sticky; + } + } + if (WFLAGP(wwin, sunken)) + state[i++] = net_wm_state_below; + if (WFLAGP(wwin, floating)) + state[i++] = net_wm_state_above; + if (wwin->flags.fullscreen) + state[i++] = net_wm_state_fullscreen; + + XChangeProperty(dpy, wwin->client_win, net_wm_state, XA_ATOM, 32, + PropModeReplace, (unsigned char *)state, i); } } -static void +static Bool updateStrut(WWindow *wwin, Bool adding) { - if (adding) { -// XGetWindowProperty(dpy, wwin->client_win, - - /* XXX add property observer */ + WScreen *scr; + WReservedArea *area; + Bool hasState = False; + + scr = wwin->screen_ptr; + + if (adding) { + Atom type_ret; + int fmt_ret; + unsigned long nitems_ret; + unsigned long bytes_after_ret; + long *data = 0; + + if (XGetWindowProperty(dpy, wwin->client_win, net_wm_strut, 0, 4, False, + XA_CARDINAL, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, + (unsigned char**)&data)==Success && data) { + + area = (WReservedArea *)wmalloc(sizeof(WReservedArea)); + area->area.x1 = data[0]; + area->area.x2 = data[1]; + area->area.y1 = data[2]; + area->area.y2 = data[3]; + + area->window = wwin->client_win; + + area->next = scr->netdata->strut; + scr->netdata->strut = area; + + XFree(data); + hasState = True; +#ifdef VIRTUAL_DESKTOP + /* just in case wm_window_type didn't set it already */ + wwin->client_flags.virtual_stick = 1; +#endif + } + } else { + /* deleting */ + area = scr->netdata->strut; + + if(area) { + if(area->window == wwin->client_win) { + scr->netdata->strut = area->next; + wfree(area); + hasState = True; + } else { + while(area->next && area->next->window != wwin->client_win) + area = area->next; + + if(area->next) { + WReservedArea *next; + + next = area->next->next; + wfree(area->next); + area->next = next; + + hasState = True; + } + } + } } + + return hasState; +} + + +static int +getWindowLayer(WWindow * wwin) +{ + int layer = WMNormalLevel; + + if (wwin->type == net_wm_window_type_desktop) { + layer = WMDesktopLevel; + } else if (wwin->type == net_wm_window_type_dock) { + layer = WMDockLevel; + } else if (wwin->type == net_wm_window_type_toolbar) { + layer = WMMainMenuLevel; + } else if (wwin->type == net_wm_window_type_menu) { + layer = WMSubmenuLevel; + } else if (wwin->type == net_wm_window_type_utility) { + } else if (wwin->type == net_wm_window_type_splash) { + } else if (wwin->type == net_wm_window_type_dialog) { + if (wwin->transient_for) { + WWindow *parent = wWindowFor(wwin->transient_for); + if (parent && parent->flags.fullscreen) { + layer = WMFullscreenLevel; + } + } + //layer = WMPopUpLevel; + } else if (wwin->type == net_wm_window_type_normal) { + } + + if (wwin->client_flags.sunken && WMSunkenLevel < layer) + layer = WMSunkenLevel; + if (wwin->client_flags.floating && WMFloatingLevel > layer) + layer = WMFloatingLevel; + + return layer; +} + + +static void +doStateAtom(WWindow *wwin, Atom state, int set, Bool init) +{ + + if (state == net_wm_state_sticky) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !IS_OMNIPRESENT(wwin); + } + if (set != wwin->flags.omnipresent) { + wWindowSetOmnipresent(wwin, set); + } + } else if (state == net_wm_state_shaded) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !wwin->flags.shaded; + } + if (init) { + wwin->flags.shaded = set; + } else { + if (set) { + wShadeWindow(wwin); + } else { + wUnshadeWindow(wwin); + } + } + } else if (state == net_wm_state_skip_taskbar) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !wwin->client_flags.skip_window_list; + } + wwin->client_flags.skip_window_list = set; + } else if (state == net_wm_state_skip_pager) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !wwin->flags.net_skip_pager; + } + wwin->flags.net_skip_pager = set; + } else if (state == net_wm_state_maximized_vert) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !(wwin->flags.maximized & MAX_VERTICAL); + } + if (init) { + wwin->flags.maximized = set; + } else { + if (set) { + wMaximizeWindow(wwin, wwin->flags.maximized | MAX_VERTICAL); + } else { + wMaximizeWindow(wwin, wwin->flags.maximized & ~MAX_VERTICAL); + } + } + } else if (state == net_wm_state_maximized_horz) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !(wwin->flags.maximized & MAX_HORIZONTAL); + } + if (init) { + wwin->flags.maximized = set; + } else { + if (set) { + wMaximizeWindow(wwin, wwin->flags.maximized | MAX_HORIZONTAL); + } else { + wMaximizeWindow(wwin, wwin->flags.maximized & ~MAX_HORIZONTAL); + } + } + } else if (state == net_wm_state_hidden) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !(wwin->flags.miniaturized); + } + if (init) { + wwin->flags.miniaturized = set; + } else { + if (set) { + wIconifyWindow(wwin); + } else { + wDeiconifyWindow(wwin); + } + } + } else if (state == net_wm_state_fullscreen) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !(wwin->flags.fullscreen); + } + if (init) { + wwin->flags.fullscreen = set; + } else { + if (set) { + wFullscreenWindow(wwin); + } else { + wUnfullscreenWindow(wwin); + } + } + } else if (state == net_wm_state_above) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !(wwin->client_flags.floating); + } + if (init) { + wwin->client_flags.floating = set; + } else { + wwin->client_flags.floating = set; + ChangeStackingLevel(wwin->frame->core, getWindowLayer(wwin)); + } + + } else if (state == net_wm_state_below) { + if (set == _NET_WM_STATE_TOGGLE) { + set = !(wwin->client_flags.sunken); + } + if (init) { + wwin->client_flags.sunken = set; + } else { + wwin->client_flags.sunken = set; + ChangeStackingLevel(wwin->frame->core, getWindowLayer(wwin)); + } + + } else { +#ifdef DEBUG_WMSPEC + printf("doStateAtom unknown atom %s set %d\n", XGetAtomName(dpy, state), set); +#endif + } +} + + +static void +removeIcon( WWindow * wwin) +{ + if (wwin->icon == NULL) + return; + if (wwin->flags.miniaturized && wwin->icon->mapped) { + XUnmapWindow(dpy, wwin->icon->core->window); + RemoveFromStackList(wwin->icon->core); + wIconDestroy(wwin->icon); + wwin->icon = NULL; + } +} + + +static Bool +handleWindowType(WWindow * wwin, Atom type, int *layer) +{ + Bool ret = True; + + if (type == net_wm_window_type_desktop) { + wwin->client_flags.no_titlebar = 1; + wwin->client_flags.no_resizable = 1; + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_border = 1; + wwin->client_flags.no_resizebar = 1; + wwin->client_flags.no_shadeable = 1; + wwin->client_flags.no_movable = 1; + wwin->client_flags.omnipresent = 1; + wwin->client_flags.skip_window_list = 1; + wwin->client_flags.dont_move_off = 1; + wwin->client_flags.no_appicon = 1; + wwin->flags.net_skip_pager = 1; + wwin->frame_x = 0; + wwin->frame_y = 0; +#ifdef VIRTUAL_DESKTOP + wwin->client_flags.virtual_stick = 1; +#endif + } else if (type == net_wm_window_type_dock) { + wwin->client_flags.no_titlebar = 1; + wwin->client_flags.no_resizable = 1; + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_border = 1; /* XXX: really not a single decoration. */ + wwin->client_flags.no_resizebar = 1; + wwin->client_flags.no_shadeable = 1; + wwin->client_flags.no_movable = 1; + wwin->client_flags.omnipresent = 1; + wwin->client_flags.skip_window_list = 1; + wwin->client_flags.dont_move_off = 1; + wwin->flags.net_skip_pager = 1; +#ifdef VIRTUAL_DESKTOP + wwin->client_flags.virtual_stick = 1; +#endif + } else if (type == net_wm_window_type_toolbar) { + wwin->client_flags.no_titlebar = 1; + wwin->client_flags.no_resizable = 1; + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_resizebar = 1; + wwin->client_flags.no_shadeable = 1; + wwin->client_flags.skip_window_list = 1; + wwin->client_flags.dont_move_off = 1; + wwin->client_flags.no_appicon = 1; + } else if (type == net_wm_window_type_menu) { + wwin->client_flags.no_titlebar = 1; + wwin->client_flags.no_resizable = 1; + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_resizebar = 1; + wwin->client_flags.no_shadeable = 1; + wwin->client_flags.skip_window_list = 1; + wwin->client_flags.dont_move_off = 1; + wwin->client_flags.no_appicon = 1; + } else if (type == net_wm_window_type_utility) { + wwin->client_flags.no_appicon = 1; + } else if (type == net_wm_window_type_splash) { + wwin->client_flags.no_titlebar = 1; + wwin->client_flags.no_resizable = 1; + wwin->client_flags.no_miniaturizable = 1; + wwin->client_flags.no_resizebar = 1; + wwin->client_flags.no_shadeable = 1; + wwin->client_flags.no_movable = 1; + wwin->client_flags.skip_window_list = 1; + wwin->client_flags.dont_move_off = 1; + wwin->client_flags.no_appicon = 1; + wwin->flags.net_skip_pager = 1; + } else if (type == net_wm_window_type_dialog) { + // wwin->client_flags.skip_window_list = 1; + // wwin->client_flags.no_appicon = 1; + } else if (type == net_wm_window_type_normal) { + } else { + ret = False; + } + + wwin->type = type; + *layer = getWindowLayer(wwin); + + return ret; +} + + +void +wNETWMPositionSplash(WWindow *wwin, int *x, int *y, int width, int height) +{ + if (wwin->type == net_wm_window_type_splash) { + WScreen * scr = wwin->screen_ptr; + WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr)); + *x = rect.pos.x + (rect.size.width - width)/2; + *y = rect.pos.y + (rect.size.height - height)/2; + } +} + + +static void +updateWindowType(WWindow * wwin) +{ + Atom type_ret; + int fmt_ret; + unsigned long nitems_ret; + unsigned long bytes_after_ret; + long *data = 0; + int layer; + if (XGetWindowProperty(dpy, wwin->client_win, net_wm_window_type, 0, 1, + False, XA_ATOM, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, (unsigned char **)&data)==Success + && data) { + + int i; + Atom * type = (Atom *)data; + for (i=0; iframe->core, layer); + wwin->frame->flags.need_texture_change = 1; + wWindowConfigureBorders(wwin); + wFrameWindowPaint(wwin->frame); + wNETWMUpdateActions(wwin, False); +} + + +Bool +wNETWMCheckClientHints(WWindow *wwin, int *layer, int *workspace) +{ + Atom type_ret; + int fmt_ret; + unsigned long nitems_ret; + unsigned long bytes_after_ret; + long *data = 0; + Bool hasState = False; + int i; + + if (XGetWindowProperty(dpy, wwin->client_win, net_wm_desktop, 0, 1, False, + XA_CARDINAL, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, + (unsigned char**)&data)==Success && data) { + + long desktop = *data; + XFree(data); + + if(desktop == -1) + wwin->client_flags.omnipresent = 1; + else + *workspace = desktop; + + hasState = True; + } + + if (XGetWindowProperty(dpy, wwin->client_win, net_wm_state, 0, 1, False, + XA_ATOM, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, + (unsigned char**)&data)==Success && data) { + + Atom * state = (Atom *)data; + for(i=0; iclient_win, net_wm_window_type, 0, 1, False, + XA_ATOM, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, + (unsigned char **)&data) == Success && data) { + + Atom * type = (Atom *)data; + for (i=0; iscreen_ptr); + + return hasState; +} + + +static Bool +updateNetIconInfo(WWindow *wwin) { + + Atom type_ret; + int fmt_ret; + unsigned long nitems_ret; + unsigned long bytes_after_ret; + long *data = 0; + Bool hasState = False; + Bool old_state = wwin->flags.net_handle_icon; + + if (XGetWindowProperty(dpy, wwin->client_win, net_wm_handled_icons, 0, 1, False, + XA_CARDINAL, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, (unsigned char **)&data) == Success && data) { + long handled = *data; + wwin->flags.net_handle_icon = (handled != 0); + XFree(data); + hasState = True; + + } else wwin->flags.net_handle_icon = False; + + if ( XGetWindowProperty(dpy, wwin->client_win, net_wm_icon_geometry, 0, 4, False, + XA_CARDINAL, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, (unsigned char **)&data) == Success && data) { + +#ifdef NETWM_PROPER + if (wwin->flags.net_handle_icon) +#else + wwin->flags.net_handle_icon = True; +#endif + { + wwin->icon_x = data[0]; + wwin->icon_y = data[1]; + wwin->icon_w = data[2]; + wwin->icon_h = data[3]; + } + + XFree(data); + hasState = True; + + } else wwin->flags.net_handle_icon = False; + + if (wwin->flags.miniaturized && + old_state != wwin->flags.net_handle_icon) { + if (wwin->flags.net_handle_icon) { + removeIcon(wwin); + } else { + wwin->flags.miniaturized = False; + wwin->flags.skip_next_animation = True; + wIconifyWindow(wwin); + } + } + + return hasState; +} + + +Bool +wNETWMCheckInitialClientState(WWindow *wwin) +{ + Bool hasState = False; + +#ifdef DEBUG_WMSPEC + printf("CheckInitialClientState\n"); +#endif + + wNETWMShowingDesktop(wwin->screen_ptr, False); + + hasState |= updateNetIconInfo(wwin); + + updateIconImage(wwin->screen_ptr, wwin); + + return hasState; +} + + +static void +handleDesktopNames(XClientMessageEvent *event, WScreen *scr) +{ + unsigned long nitems_ret, bytes_after_ret; + char *data, *names[32]; + int fmt_ret, i, n; + Atom type_ret; + + if (XGetWindowProperty(dpy, scr->root_win, net_desktop_names, 0, 1, False, + utf8_string, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, + (unsigned char**)&data)!=Success) { + return; + } + + if (data == 0) + return; + + if (type_ret != utf8_string || fmt_ret != 8) + return; + + n = 0; + names[n] = data; + for (i = 0; i < nitems_ret; i++) { + if (data[i] == 0) { + n++; + names[n] = &data[i]; + } else if (*names[n] == 0) { + names[n] = &data[i]; + wWorkspaceRename(scr, n, names[n]); + } + } +} + + +Bool +wNETWMProcessClientMessage(XClientMessageEvent *event) +{ + WScreen *scr; + WWindow *wwin; + Bool done = True; + +#ifdef DEBUG_WMSPEC + printf("processClientMessage type %s\n", XGetAtomName(dpy, event->message_type)); +#endif + + scr = wScreenForWindow(event->window); + if (scr) { + /* generic client messages */ + if (event->message_type == net_current_desktop) { + wWorkspaceChange(scr, event->data.l[0]); + } else if(event->message_type == net_number_of_desktops) { + long value; + + value = event->data.l[0]; + if(value > scr->workspace_count) { + wWorkspaceMake(scr, value - scr->workspace_count); + } else if(value < scr->workspace_count) { + int i; + Bool rebuild = False; + + for (i = scr->workspace_count-1; i >= value; i--) { + if (!wWorkspaceDelete(scr, i)) { + rebuild = True; + break; + } + } + + if(rebuild) { + updateWorkspaceCount(scr); + } + } + } else if (event->message_type == net_showing_desktop) { + wNETWMShowingDesktop(scr, event->data.l[0]); +#ifdef VIRTUAL_DESKTOP + } else if (event->message_type == net_desktop_viewport) { + wWorkspaceSetViewPort(scr, scr->current_workspace, + event->data.l[0], event->data.l[1]); +#endif + } else if (event->message_type == net_desktop_names) { + handleDesktopNames(event, scr); + } else { + done = False; + } + + if (done) + return True; + } + + /* window specific client messages */ + + wwin = wWindowFor(event->window); + if (!wwin) + return False; + + if (event->message_type == net_active_window) { + wNETWMShowingDesktop(scr, False); + wMakeWindowVisible(wwin); + } else if (event->message_type == net_close_window) { + if (!WFLAGP(wwin, no_closable)) { + if (wwin->protocols.DELETE_WINDOW) + wClientSendProtocol(wwin, _XA_WM_DELETE_WINDOW, LastTimestamp); + } + } else if (event->message_type == net_wm_state) { + int maximized = wwin->flags.maximized; + long set = event->data.l[0]; + +#ifdef DEBUG_WMSPEC + printf("net_wm_state set %d a1 %s a2 %s\n", set, + XGetAtomName(dpy, event->data.l[1]), + XGetAtomName(dpy, event->data.l[2])); +#endif + + doStateAtom(wwin, (Atom)event->data.l[1], set, False); + if(event->data.l[2]) + doStateAtom(wwin, (Atom)event->data.l[2], set, False); + + if(wwin->flags.maximized != maximized) { + if(!wwin->flags.maximized) { + wwin->flags.maximized = maximized; + wUnmaximizeWindow(wwin); + } else { + wMaximizeWindow(wwin, wwin->flags.maximized); + } + } + updateStateHint(wwin, False, False); + } else if (event->message_type == net_wm_handled_icons || + event->message_type == net_wm_icon_geometry) { + updateNetIconInfo(wwin); + } else if (event->message_type == net_wm_desktop) { + long desktop = event->data.l[0]; + if (desktop == -1) { + wWindowSetOmnipresent(wwin, True); + } else { + if (IS_OMNIPRESENT(wwin)) + wWindowSetOmnipresent(wwin, False); + wWindowChangeWorkspace(wwin, desktop); + } + } else if (event->message_type == net_wm_icon) { + updateIconImage(scr, wwin); + } else { + done = False; + } + + return done; +} + + +Bool +wNETWMCheckClientHintChange(WWindow *wwin, XPropertyEvent *event) +{ + Bool ret = True; + + if(event->atom == net_wm_strut) { + updateStrut(wwin, False); + updateStrut(wwin, True); + wScreenUpdateUsableArea(wwin->screen_ptr); + } else if (event->atom == net_wm_handled_icons || + event->atom == net_wm_icon_geometry) { + updateNetIconInfo(wwin); + } else if (event->atom == net_wm_window_type) { + updateWindowType(wwin); + } else { + ret = False; + } + + return ret; +} + + +int +wNETWMGetPidForWindow(Window window) +{ + Atom type_ret; + int fmt_ret; + unsigned long nitems_ret; + unsigned long bytes_after_ret; + long *data = 0; + int pid; + + if (XGetWindowProperty(dpy, window, net_wm_pid, 0, 1, False, + XA_CARDINAL, &type_ret, &fmt_ret, &nitems_ret, + &bytes_after_ret, + (unsigned char**)&data)==Success && data) { + + pid = *data; + XFree(data); + } else { + pid = 0; + } + + return pid; } @@ -402,34 +1524,38 @@ observer(void *self, WMNotification *notif) const char *name = WMGetNotificationName(notif); void *data = WMGetNotificationClientData(notif); NetData *ndata = (NetData*)self; - - - if (strcmp(name, WMNManaged) == 0 && wwin) { - updateClientList(wwin->screen_ptr, wwin, True); - - updateStrut(wwin, True); + + if (strcmp(name, WMNManaged) == 0 && wwin) { + updateClientList(wwin->screen_ptr); + updateClientListStacking(wwin->screen_ptr, NULL); + updateStateHint(wwin, True, False); + + updateStrut(wwin, False); + updateStrut(wwin, True); + wScreenUpdateUsableArea(wwin->screen_ptr); } else if (strcmp(name, WMNUnmanaged) == 0 && wwin) { - updateClientList(wwin->screen_ptr, wwin, False); - updateWorkspaceHint(wwin, True); - updateStateHint(wwin, True); - - updateStrut(wwin, False); - + updateClientList(wwin->screen_ptr); + updateClientListStacking(wwin->screen_ptr, wwin); + updateWorkspaceHint(wwin, False, True); + updateStateHint(wwin, False, True); + wNETWMUpdateActions(wwin, True); + + updateStrut(wwin, False); + wScreenUpdateUsableArea(wwin->screen_ptr); } else if (strcmp(name, WMNResetStacking) == 0 && wwin) { - updateClientListStacking(wwin->screen_ptr); - + updateClientListStacking(wwin->screen_ptr, NULL); + updateStateHint(wwin, False, False); } else if (strcmp(name, WMNChangedStacking) == 0 && wwin) { - updateClientListStacking(wwin->screen_ptr); - + updateClientListStacking(wwin->screen_ptr, NULL); + updateStateHint(wwin, False, False); } else if (strcmp(name, WMNChangedFocus) == 0) { - updateFocusHint(ndata->scr, wwin); - + updateFocusHint(ndata->scr, wwin); } else if (strcmp(name, WMNChangedWorkspace) == 0 && wwin) { - updateWorkspaceHint(wwin, False); - + updateWorkspaceHint(wwin, False, False); + updateStateHint(wwin, True, False); } else if (strcmp(name, WMNChangedState) == 0 && wwin) { - updateStateHint(wwin, False); + updateStateHint(wwin, !strcmp(data, "omnipresent"), False); } } @@ -439,18 +1565,21 @@ wsobserver(void *self, WMNotification *notif) { WScreen *scr = (WScreen*)WMGetNotificationObject(notif); const char *name = WMGetNotificationName(notif); - void *data = WMGetNotificationClientData(notif); + //void *data = WMGetNotificationClientData(notif); if (strcmp(name, WMNWorkspaceCreated) == 0) { - updateWorkspaceCount(scr); + updateWorkspaceCount(scr); + updateWorkspaceNames(scr); } else if (strcmp(name, WMNWorkspaceDestroyed) == 0) { - updateWorkspaceCount(scr); + updateWorkspaceCount(scr); + updateWorkspaceNames(scr); } else if (strcmp(name, WMNWorkspaceChanged) == 0) { - updateCurrentWorkspace(scr); + updateCurrentWorkspace(scr); } else if (strcmp(name, WMNWorkspaceNameChanged) == 0) { - updateWorkspaceNames(scr, (int)data); + updateWorkspaceNames(scr); } } +#endif /* NETWM_HINTS */ diff --git a/src/wmspec.h b/src/wmspec.h index b4294fe9..39890875 100644 --- a/src/wmspec.h +++ b/src/wmspec.h @@ -25,6 +25,21 @@ #ifndef _WMSPEC_H_ #define _WMSPEC_H_ +#include +#include +#include +void wNETWMInitStuff(WScreen *scr); +void wNETWMUpdateWorkarea(WScreen *scr, WArea usableArea); +Bool wNETWMGetUsableArea(WScreen *scr, int head, WArea *area); +Bool wNETWMCheckInitialClientState(WWindow *wwin); +Bool wNETWMProcessClientMessage(XClientMessageEvent *event); +Bool wNETWMCheckClientHints(WWindow *wwin, int *layer, int *workspace); +Bool wNETWMCheckClientHintChange(WWindow *wwin, XPropertyEvent *event); +void wNETWMShowingDesktop(WScreen *scr, Bool show); +void wNETWMUpdateActions(WWindow *wwin, Bool del); +void wNETWMUpdateDesktop(WScreen *scr); +void wNETWMPositionSplash(WWindow *wwin, int *x, int *y, int width, int height); +int wNETWMGetPidForWindow(Window window); #endif diff --git a/src/workspace.c b/src/workspace.c index 2e1387bf..85cb2281 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "wconfig.h" @@ -33,6 +33,7 @@ #include #include #include +#include #include "WindowMaker.h" #include "wcore.h" @@ -49,11 +50,18 @@ #ifdef KWM_HINTS #include "kwm.h" #endif +#ifdef NETWM_HINTS +#include "wmspec.h" +#endif + +#include "xinerama.h" extern WPreferences wPreferences; extern XContext wWinContext; +extern XContext wVEdgeContext; +extern void ProcessPendingEvents(); static WMPropList *dWorkspaces=NULL; static WMPropList *dClip, *dName; @@ -62,6 +70,7 @@ static WMPropList *dClip, *dName; static BOOL initVDesk = False; #endif + static void make_keys() { @@ -91,55 +100,59 @@ wWorkspaceNew(WScreen *scr) int i; if (scr->workspace_count < MAX_WORKSPACES) { - scr->workspace_count++; + scr->workspace_count++; - wspace = wmalloc(sizeof(WWorkspace)); - wspace->name = NULL; + wspace = wmalloc(sizeof(WWorkspace)); + wspace->name = NULL; #ifdef KWM_HINTS - if (scr->flags.kwm_syncing_count) { - wspace->name = wKWMGetWorkspaceName(scr, scr->workspace_count-1); - } + if (scr->flags.kwm_syncing_count) { + wspace->name = wKWMGetWorkspaceName(scr, scr->workspace_count-1); + } #endif - if (!wspace->name) { - wspace->name = wmalloc(strlen(_("Workspace %i"))+8); - sprintf(wspace->name, _("Workspace %i"), scr->workspace_count); - } + if (!wspace->name) { + wspace->name = wmalloc(strlen(_("Workspace %i"))+8); + sprintf(wspace->name, _("Workspace %i"), scr->workspace_count); + } - if (!wPreferences.flags.noclip) { - wspace->clip = wDockCreate(scr, WM_CLIP); - } else - wspace->clip = NULL; + if (!wPreferences.flags.noclip) { + wspace->clip = wDockCreate(scr, WM_CLIP); + } else + wspace->clip = NULL; - list = wmalloc(sizeof(WWorkspace*)*scr->workspace_count); + list = wmalloc(sizeof(WWorkspace*)*scr->workspace_count); - for (i=0; iworkspace_count-1; i++) { - list[i] = scr->workspaces[i]; - } - list[i] = wspace; - if (scr->workspaces) - wfree(scr->workspaces); - scr->workspaces = list; + for (i=0; iworkspace_count-1; i++) { + list[i] = scr->workspaces[i]; + } + list[i] = wspace; + if (scr->workspaces) + wfree(scr->workspaces); + scr->workspaces = list; - wWorkspaceMenuUpdate(scr, scr->workspace_menu); - wWorkspaceMenuUpdate(scr, scr->clip_ws_menu); + wWorkspaceMenuUpdate(scr, scr->workspace_menu); + wWorkspaceMenuUpdate(scr, scr->clip_ws_menu); #ifdef VIRTUAL_DESKTOP - wspace->view_x = wspace->view_y = 0; - wspace->height = scr->scr_height; - wspace->width = scr->scr_width; + wspace->view_x = wspace->view_y = 0; + wspace->height = scr->scr_height; + wspace->width = scr->scr_width; +#endif +#ifdef NETWM_HINTS + wNETWMUpdateDesktop(scr); #endif - WMPostNotificationName(WMNWorkspaceCreated, scr, - (void*)(scr->workspace_count-1)); - XFlush(dpy); - return scr->workspace_count-1; + WMPostNotificationName(WMNWorkspaceCreated, scr, + (void*)(scr->workspace_count-1)); + XFlush(dpy); + + return scr->workspace_count-1; } + return -1; } - Bool wWorkspaceDelete(WScreen *scr, int workspace) { @@ -147,7 +160,6 @@ wWorkspaceDelete(WScreen *scr, int workspace) WWorkspace **list; int i, j; - if (workspace<=0) return False; @@ -167,9 +179,9 @@ wWorkspaceDelete(WScreen *scr, int workspace) list = wmalloc(sizeof(WWorkspace*)*(scr->workspace_count-1)); j = 0; for (i=0; iworkspace_count; i++) { - if (i!=workspace) + if (i!=workspace) { list[j++] = scr->workspaces[i]; - else { + } else { if (scr->workspaces[i]->name) wfree(scr->workspaces[i]->name); wfree(scr->workspaces[i]); @@ -205,6 +217,10 @@ wWorkspaceDelete(WScreen *scr, int workspace) wMenuRealize(menu); } +#ifdef NETWM_HINTS + wNETWMUpdateDesktop(scr); +#endif + WMPostNotificationName(WMNWorkspaceDestroyed, scr, (void*)(scr->workspace_count-1)); @@ -223,7 +239,6 @@ typedef struct WorkspaceNameData { } WorkspaceNameData; - static void hideWorkspaceName(void *data) { @@ -246,8 +261,7 @@ hideWorkspaceName(void *data) Pixmap pix; scr->workspace_name_timer = - WMAddTimerHandler(WORKSPACE_NAME_FADE_DELAY, hideWorkspaceName, - scr); + WMAddTimerHandler(WORKSPACE_NAME_FADE_DELAY, hideWorkspaceName, scr); RCombineImagesWithOpaqueness(img, scr->workspace_name_data->text, scr->workspace_name_data->count*255/10); @@ -266,7 +280,6 @@ hideWorkspaceName(void *data) } - static void showWorkspaceName(WScreen *scr, int workspace) { @@ -279,9 +292,10 @@ showWorkspaceName(WScreen *scr, int workspace) int len = strlen(name); int x, y; - if (wPreferences.workspace_name_display_position == WD_NONE - || scr->workspace_count < 2) - return; + if (wPreferences.workspace_name_display_position == WD_NONE || + scr->workspace_count < 2) { + return; + } if (scr->workspace_name_timer) { WMDeleteTimerHandler(scr->workspace_name_timer); @@ -298,6 +312,7 @@ showWorkspaceName(WScreen *scr, int workspace) } data = wmalloc(sizeof(WorkspaceNameData)); + data->back = NULL; w = WMWidthOfString(scr->workspace_name_font, name, len); h = WMFontHeight(scr->workspace_name_font); @@ -347,7 +362,7 @@ showWorkspaceName(WScreen *scr, int workspace) for (x = 0; x <= 4; x++) { for (y = 0; y <= 4; y++) { WMDrawString(scr->wmscreen, text, scr->white, - scr->workspace_name_font, x, y, name, len); + scr->workspace_name_font, x, y, name, len); } } @@ -404,7 +419,7 @@ showWorkspaceName(WScreen *scr, int workspace) /* set a timeout for the effect */ data->timeout = time(NULL) + 2 + - (WORKSPACE_NAME_DELAY + WORKSPACE_NAME_FADE_DELAY*data->count)/1000; + (WORKSPACE_NAME_DELAY + WORKSPACE_NAME_FADE_DELAY*data->count)/1000; scr->workspace_name_data = data; @@ -452,25 +467,23 @@ wWorkspaceRelativeChange(WScreen *scr, int amount) w = scr->current_workspace + amount; if (amount < 0) { - - if (w >= 0) + if (w >= 0) { wWorkspaceChange(scr, w); - else if (wPreferences.ws_cycle) + } else if (wPreferences.ws_cycle) { wWorkspaceChange(scr, scr->workspace_count + w); - + } } else if (amount > 0) { - - if (w < scr->workspace_count) + if (w < scr->workspace_count) { wWorkspaceChange(scr, w); - else if (wPreferences.ws_advance) + } else if (wPreferences.ws_advance) { wWorkspaceChange(scr, WMIN(w, MAX_WORKSPACES-1)); - else if (wPreferences.ws_cycle) - wWorkspaceChange(scr, w % scr->workspace_count); + } else if (wPreferences.ws_cycle) { + wWorkspaceChange(scr, w % scr->workspace_count); + } } } - void wWorkspaceForceChange(WScreen *scr, int workspace) { @@ -494,29 +507,24 @@ wWorkspaceForceChange(WScreen *scr, int workspace) wWorkspaceMenuUpdate(scr, scr->clip_ws_menu); if ((tmp = scr->focused_window)!= NULL) { - if ((IS_OMNIPRESENT(tmp) && (tmp->flags.mapped || tmp->flags.shaded) - && !WFLAGP(tmp, no_focusable)) - || tmp->flags.changing_workspace) { + if ((IS_OMNIPRESENT(tmp) && (tmp->flags.mapped || tmp->flags.shaded) && + !WFLAGP(tmp, no_focusable)) || tmp->flags.changing_workspace) { foc = tmp; } /* foc2 = tmp; will fix annoyance with gnome panel * but will create annoyance for every other application */ - while (tmp) { if (tmp->frame->workspace!=workspace && !tmp->flags.selected) { /* unmap windows not on this workspace */ - if ((tmp->flags.mapped||tmp->flags.shaded) - && !IS_OMNIPRESENT(tmp) - && !tmp->flags.changing_workspace) { - + if ((tmp->flags.mapped||tmp->flags.shaded) && + !IS_OMNIPRESENT(tmp) && !tmp->flags.changing_workspace) { wWindowUnmap(tmp); } /* also unmap miniwindows not on this workspace */ if (!wPreferences.sticky_icons && tmp->flags.miniaturized && tmp->icon && !IS_OMNIPRESENT(tmp)) { - XUnmapWindow(dpy, tmp->icon->core->window); tmp->icon->mapped = 0; } @@ -529,8 +537,9 @@ wWorkspaceForceChange(WScreen *scr, int workspace) if (wapp) { wapp->last_workspace = workspace; } - if (!foc2 && (tmp->flags.mapped || tmp->flags.shaded)) - foc2 = tmp; + if (!foc2 && (tmp->flags.mapped || tmp->flags.shaded)) { + foc2 = tmp; + } } } else { /* change selected windows' workspace */ @@ -544,8 +553,9 @@ wWorkspaceForceChange(WScreen *scr, int workspace) if (!(tmp->flags.mapped || tmp->flags.miniaturized)) { /* remap windows that are on this workspace */ wWindowMap(tmp); - if (!foc && !WFLAGP(tmp, no_focusable)) - foc = tmp; + if (!foc && !WFLAGP(tmp, no_focusable)) { + foc = tmp; + } } /* Also map miniwindow if not omnipresent */ if (!wPreferences.sticky_icons && @@ -560,6 +570,16 @@ wWorkspaceForceChange(WScreen *scr, int workspace) tmp = tmp->prev; } + /* Gobble up events unleashed by our mapping & unmapping. + * These may trigger various grab-initiated focus & + * crossing events. However, we don't care about them, + * and ignore their focus implications altogether to avoid + * flicker. + */ + scr->flags.ignore_focus_events = 1; + ProcessPendingEvents(); + scr->flags.ignore_focus_events = 0; + if (!foc) foc = foc2; @@ -577,13 +597,19 @@ wWorkspaceForceChange(WScreen *scr, int workspace) tmp = NULL; if (XQueryPointer(dpy, scr->root_win, &bar, &win, &foo, &foo, &foo, &foo, &mask)) { - tmp = wWindowFor(win); - } - if (!tmp && wPreferences.focus_mode == WKF_SLOPPY) { - wSetFocusTo(scr, foc); - } else { - wSetFocusTo(scr, tmp); - } + tmp = wWindowFor(win); + } + + /* If there's a window under the pointer, focus it. + * (we ate all other focus events above, so it's + * certainly not focused). Otherwise focus last + * focused, or the root (depending on sloppiness) + */ + if (!tmp && wPreferences.focus_mode == WKF_SLOPPY) { + wSetFocusTo(scr, foc); + } else { + wSetFocusTo(scr, tmp); + } } } @@ -609,9 +635,12 @@ wWorkspaceForceChange(WScreen *scr, int workspace) } } -#ifdef KWM_HINTS +#if defined KWM_HINTS || defined NETWM_HINTS wScreenUpdateUsableArea(scr); #endif +#ifdef NETWM_HINTS + wNETWMUpdateDesktop(scr); +#endif showWorkspaceName(scr, workspace); @@ -620,23 +649,320 @@ wWorkspaceForceChange(WScreen *scr, int workspace) /* XSync(dpy, False); */ } + #ifdef VIRTUAL_DESKTOP + /* TODO: -* 1) Allow border around each window so the scrolling -* won't just stop at the border. -* 2) Make pager. -*/ + * + * 1) Allow border around each window so the scrolling + * won't just stop at the border. + * 2) Make pager. + * + */ + +#define vec_sub(a, b) wmkpoint((a).x-(b).x, (a).y-(b).y) +#define vec_add(a, b) wmkpoint((a).x+(b).x, (a).y+(b).y) +#define vec_inc(a, b) do { (a).x+=(b).x; (a).y+=(b).y; } while(0) +#define vec_dot(a, b) ((a).x*(b).x + (a).y*(b).y) +#define vec_scale(a, s) wmkpoint((a).x*s, (a).y*s) +#define vec_scale2(a, s, t) wmkpoint((a).x*s, (a).y*t) + +#ifndef HAS_BORDER +#define HAS_BORDER(w) (!(WFLAGP((w), no_border))) +#endif + +#ifndef IS_VSTUCK +#define IS_VSTUCK(w) (WFLAGP((w), virtual_stick)) +#endif + +#define updateMinimum(l,p,ml,mp) do { if (cmp(l) && (l)<(ml)) { (ml)=(l); (mp)=(p); }; } while(0) + +static Bool cmp_gez(int i) { return (i >= 0); } + +static Bool cmp_gz(int i) { return (i > 0); } + + +static WMPoint +getClosestEdge(WScreen * scr, WMPoint direction, Bool (*cmp)(int)) +{ + WMPoint closest = wmkpoint(0, 0); + int closest_len = INT_MAX; + WWindow * wwin; + + for (wwin=scr->focused_window; wwin; wwin=wwin->prev) { + if (wwin->frame->workspace == scr->current_workspace) { + if (!wwin->flags.miniaturized && + !IS_VSTUCK(wwin) && + !wwin->flags.hidden) { + int border = 2*HAS_BORDER(wwin); + int len; + int x1,x2,y1,y2; + int head = wGetHeadForWindow(wwin); + WArea area = wGetUsableAreaForHead(scr, head, NULL, False); + WMPoint p; + + x1 = wwin->frame_x - area.x1; + y1 = wwin->frame_y - area.y1; + x2 = wwin->frame_x + wwin->frame->core->width + border - area.x2; + y2 = wwin->frame_y + wwin->frame->core->height + border - area.y2; + + p = wmkpoint(x1,y1); + len = vec_dot(direction, p); + updateMinimum(len, p, closest_len, closest); + + p = wmkpoint(x1,y2); + len = vec_dot(direction, p); + updateMinimum(len, p, closest_len, closest); + + p = wmkpoint(x2,y1); + len = vec_dot(direction, p); + updateMinimum(len, p, closest_len, closest); + + p = wmkpoint(x2,y2); + len = vec_dot(direction, p); + updateMinimum(len, p, closest_len, closest); + } + } + } + + return closest; +} + + +void +wWorkspaceKeyboardMoveDesktop(WScreen *scr, WMPoint direction) +{ + int x, y; + WMPoint edge = getClosestEdge(scr, direction, cmp_gz); + int len = vec_dot(edge, direction); + WMPoint step = vec_scale(direction, len); + wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); + wWorkspaceSetViewPort(scr, scr->current_workspace, x+step.x, y+step.y); +} + + +extern Cursor wCursor[WCUR_LAST]; + + +static void +vdMouseMoveDesktop(XEvent *event, WMPoint direction) +{ + static int lock = False; + if (lock) return; + lock = True; + + Bool done = False; + Bool moved = True; + WScreen *scr = wScreenForRootWindow(event->xcrossing.root); + WMPoint old_pos = wmkpoint(event->xcrossing.x_root, event->xcrossing.y_root); + WMPoint step; + int x, y; + int resisted = 0; + + if (XGrabPointer(dpy, event->xcrossing.window, False, + PointerMotionMask, GrabModeAsync, GrabModeAsync, + scr->root_win, wCursor[WCUR_EMPTY], + CurrentTime) != GrabSuccess) { + + /* if the grab fails, do it the old fashioned way */ + step = vec_scale2(direction, wPreferences.vedge_hscrollspeed, + wPreferences.vedge_vscrollspeed); + wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); + if (wWorkspaceSetViewPort(scr, scr->current_workspace, + x+step.x, y+step.y)) { + step = vec_scale(direction, wPreferences.vedge_thickness + 1); + XWarpPointer(dpy, None, scr->root_win, 0,0,0,0, + event->xcrossing.x_root - step.x, + event->xcrossing.y_root - step.y); + } + goto exit; + } + XSync(dpy, True); + + if (old_pos.x < 0) + old_pos.x = 0; + if (old_pos.y < 0) + old_pos.y = 0; + if (old_pos.x > scr->scr_width) + old_pos.x = scr->scr_width; + if (old_pos.y > scr->scr_height) + old_pos.y = scr->scr_height; + + while (!done) { + XEvent ev; + if (moved) { + XWarpPointer(dpy, None, scr->root_win, 0, 0, 0, 0, + scr->scr_width/2, scr->scr_height/2); + moved = False; + } + WMMaskEvent(dpy, PointerMotionMask, &ev); + + switch (ev.type) { + case MotionNotify: + { + int step_len; + step = wmkpoint(ev.xmotion.x_root-scr->scr_width/2, + ev.xmotion.y_root-scr->scr_height/2); + step_len = vec_dot(step, direction); + if (step_len < 0) { + done = True; + break; + } + + if (step_len > 0) { + Bool do_move = True; + int resist = wPreferences.vedge_resistance; + WMPoint closest; + int closest_len = INT_MAX; + if (resist) { + closest = getClosestEdge(scr, direction, cmp_gez); + closest_len = vec_dot(direction, closest); + } + + if (!closest_len) { + resisted += step_len; + do_move = resisted >= resist; + if (do_move) { + closest_len = INT_MAX; + step_len = resisted - resist; + resisted = 0; + } + } + if (do_move) { + if (closest_len <= wPreferences.vedge_attraction) { + step = vec_scale(direction, closest_len); + } else { + step = vec_scale(direction, step_len); + } + + wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); + wWorkspaceSetViewPort(scr, scr->current_workspace, + x+step.x, y+step.y); + moved = True; + } + } + } + break; + } + } + + step = vec_add(old_pos, vec_scale(direction, -1)); + XWarpPointer(dpy, None, scr->root_win, 0,0,0,0, step.x, step.y); + XUngrabPointer(dpy, CurrentTime); + +exit: + lock = False; +} + + +static void +vdHandleEnter_u(XEvent *event) { + vdMouseMoveDesktop(event, VEC_UP); +} + + +static void +vdHandleEnter_d(XEvent *event) { + vdMouseMoveDesktop(event, VEC_DOWN); +} + + +static void +vdHandleEnter_l(XEvent *event) { + vdMouseMoveDesktop(event, VEC_LEFT); +} + + +static void +vdHandleEnter_r(XEvent *event) { + vdMouseMoveDesktop(event, VEC_RIGHT); +} + + +static void +wWorkspaceMapEdge(WScreen *scr) +{ + int i; + if (wPreferences.vedge_thickness && initVDesk) { + for (i=0; ivirtual_nr_edges; ++i) { + XMapWindow(dpy, scr->virtual_edges[i]); + } + } +} + + +static void +wWorkspaceUnmapEdge(WScreen *scr) +{ + int i; + if (wPreferences.vedge_thickness && initVDesk) { + for (i=0; ivirtual_nr_edges; ++i) { + XUnmapWindow(dpy, scr->virtual_edges[i]); + } + } +} + + +#define LEFT_EDGE 0x01 +#define RIGHT_EDGE 0x02 +#define TOP_EDGE 0x04 +#define BOTTOM_EDGE 0x08 +#define ALL_EDGES 0x0F void wWorkspaceManageEdge(WScreen *scr) { - int w; - int vmask; - XSetWindowAttributes attribs; + if (!initVDesk && wPreferences.vedge_thickness) { + int i, j, w; + int vmask; + XSetWindowAttributes attribs; + + int heads = wXineramaHeads(scr); + int *hasEdges = (int*)wmalloc(sizeof(int)*heads); + + int thickness = wPreferences.vedge_thickness; + int nr_edges = 0; + int max_edges = 4*heads; + int head; + Window * edges = (Window *)wmalloc(sizeof(Window)*max_edges); - /* puts("wWorkspaceManageEdge()"); */ - if (wPreferences.vedge_thickness) { initVDesk = True; + + for (i=0; i 0 && hlen == 0) { /* horz alignment, vert edges touch */ + if (i_rect.pos.x < j_rect.pos.x) { /* i left of j */ + hasEdges[i] &= ~RIGHT_EDGE; + hasEdges[j] &= ~LEFT_EDGE; + } else { /* j left of i */ + hasEdges[j] &= ~RIGHT_EDGE; + hasEdges[i] &= ~LEFT_EDGE; + } + } else if (vlen == 0 && hlen > 0) { /* vert alignment, horz edges touch */ + if (i_rect.pos.y < j_rect.pos.y) { /* i top of j */ + hasEdges[i] &= ~BOTTOM_EDGE; + hasEdges[j] &= ~TOP_EDGE; + } else { /* j top of i */ + hasEdges[j] &= ~BOTTOM_EDGE; + hasEdges[i] &= ~TOP_EDGE; + } + } + } + } + for (w = 0; w < scr->workspace_count; w++) { /* puts("reset workspace"); */ wWorkspaceSetViewPort(scr, w, 0, 0); @@ -645,93 +971,202 @@ wWorkspaceManageEdge(WScreen *scr) vmask = CWEventMask|CWOverrideRedirect; attribs.event_mask = (EnterWindowMask | LeaveWindowMask | VisibilityChangeMask); attribs.override_redirect = True; - scr->virtual_edge_u = - XCreateWindow(dpy, scr->root_win, 0, 0, - scr->scr_width, wPreferences.vedge_thickness, 0, - CopyFromParent, InputOnly, CopyFromParent, vmask, &attribs); - scr->virtual_edge_d = - XCreateWindow(dpy, scr->root_win, 0, scr->scr_height-wPreferences.vedge_thickness, - scr->scr_width, wPreferences.vedge_thickness, 0, - CopyFromParent, InputOnly, CopyFromParent, vmask, &attribs); - scr->virtual_edge_l = - XCreateWindow(dpy, scr->root_win, 0, 0, - wPreferences.vedge_thickness, scr->scr_height, 0, - CopyFromParent, InputOnly, CopyFromParent, vmask, &attribs); - scr->virtual_edge_r = - XCreateWindow(dpy, scr->root_win, scr->scr_width-wPreferences.vedge_thickness, 0, - wPreferences.vedge_thickness, scr->scr_height, 0, - CopyFromParent, InputOnly, CopyFromParent, vmask, &attribs); - XMapWindow(dpy, scr->virtual_edge_u); - XMapWindow(dpy, scr->virtual_edge_d); - XMapWindow(dpy, scr->virtual_edge_l); - XMapWindow(dpy, scr->virtual_edge_r); + + for (head=0; headroot_win, rect.pos.x, rect.pos.y, + rect.size.width, thickness, 0, + CopyFromParent, InputOnly, CopyFromParent, + vmask, &attribs); + XSaveContext(dpy, edges[nr_edges], wVEdgeContext, + (XPointer)vdHandleEnter_u); + ++nr_edges; + } + + if (hasEdges[head] & BOTTOM_EDGE) { + edges[nr_edges] = + XCreateWindow(dpy, scr->root_win, rect.pos.x, + rect.pos.y+rect.size.height-thickness, + rect.size.width, thickness, 0, + CopyFromParent, InputOnly, CopyFromParent, + vmask, &attribs); + XSaveContext(dpy, edges[nr_edges], wVEdgeContext, + (XPointer)vdHandleEnter_d); + ++nr_edges; + } + + if (hasEdges[head] & LEFT_EDGE) { + edges[nr_edges] = + XCreateWindow(dpy, scr->root_win, rect.pos.x, rect.pos.y, + thickness, rect.pos.y+rect.size.height, 0, + CopyFromParent, InputOnly, CopyFromParent, + vmask, &attribs); + XSaveContext(dpy, edges[nr_edges], wVEdgeContext, + (XPointer)vdHandleEnter_l); + ++nr_edges; + } + + if (hasEdges[head] & RIGHT_EDGE) { + edges[nr_edges] = + XCreateWindow(dpy, scr->root_win, + rect.pos.x + rect.size.width - thickness, rect.pos.y, + thickness, rect.size.height, 0, + CopyFromParent, InputOnly, CopyFromParent, vmask, + &attribs); + XSaveContext(dpy, edges[nr_edges], wVEdgeContext, + (XPointer)vdHandleEnter_r); + ++nr_edges; + } + } + + scr->virtual_nr_edges = nr_edges; + scr->virtual_edges = edges; + + wWorkspaceMapEdge(scr); wWorkspaceRaiseEdge(scr); + + wfree(hasEdges); } } + +void +wWorkspaceUpdateEdge(WScreen *scr) +{ + if (!initVDesk && wPreferences.vedge_thickness) { + wWorkspaceManageEdge(scr); + } else if (initVDesk) { + if (wPreferences.vedge_thickness) { + wWorkspaceMapEdge(scr); + } else { + wWorkspaceUnmapEdge(scr); + } + } +} + + +void +wWorkspaceDestroyEdge(WScreen *scr) +{ + if (!initVDesk) { + int i; + + for (i=0; ivirtual_nr_edges; ++i) { + XDeleteContext(dpy, scr->virtual_edges[i], wVEdgeContext); + XDestroyWindow(dpy, scr->virtual_edges[i]); + } + + wfree(scr->virtual_edges); + scr->virtual_edges = NULL; + scr->virtual_nr_edges = 0; + + initVDesk = False; + } +} + + void wWorkspaceRaiseEdge(WScreen *scr) { - puts("raise edge"); + static int toggle = 0; + int i; + if (wPreferences.vedge_thickness && initVDesk) { - XRaiseWindow(dpy, scr->virtual_edge_u); - XRaiseWindow(dpy, scr->virtual_edge_d); - XRaiseWindow(dpy, scr->virtual_edge_l); - XRaiseWindow(dpy, scr->virtual_edge_r); + if (toggle) { + for (i=0; ivirtual_nr_edges; ++i) { + XRaiseWindow(dpy, scr->virtual_edges[i]); + } + } else { + for (i=scr->virtual_nr_edges-1; i>=0; --i) { + XRaiseWindow(dpy, scr->virtual_edges[i]); + } + } + + toggle ^= 1; } } void wWorkspaceLowerEdge(WScreen *scr) { - puts("lower edge"); + int i; if (wPreferences.vedge_thickness && initVDesk) { - XLowerWindow(dpy, scr->virtual_edge_u); - XLowerWindow(dpy, scr->virtual_edge_d); - XLowerWindow(dpy, scr->virtual_edge_l); - XLowerWindow(dpy, scr->virtual_edge_r); + for (i=0; ivirtual_nr_edges; ++i) { + XLowerWindow(dpy, scr->virtual_edges[i]); + } } } + void -wWorkspaceResizeViewPort(WScreen *scr, int workspace, int width, int height) +wWorkspaceResizeViewPort(WScreen *scr, int workspace) { - scr->workspaces[workspace]->width = WMAX(width,scr->scr_width); - scr->workspaces[workspace]->height = WMAX(height,scr->scr_height); + int x, y; + wWorkspaceGetViewPosition(scr, scr->current_workspace, &x, &y); + wWorkspaceSetViewPort(scr, scr->current_workspace, x, y); } + void updateWorkspaceGeometry(WScreen *scr, int workspace, int *view_x, int *view_y) { int most_left, most_right, most_top, most_bottom; WWindow *wwin; + int heads = wXineramaHeads(scr); + typedef int strut_t[4]; + strut_t * strut = (strut_t*)wmalloc(heads*sizeof(strut_t)); + int head, i; + + for (head=0; headfocused_window; - most_right = scr->scr_width; - most_bottom = scr->scr_height; - most_left = 0; - most_top = 0; + most_right = 0; + most_bottom = 0; + most_left = scr->scr_width; + most_top = scr->scr_height; for(;wwin; wwin = wwin->prev) { if (wwin->frame->workspace == workspace) { - if (!wwin->flags.miniaturized - && !wwin->flags.hidden) { - if (wwin->frame_x < most_left) { /* record positions, should this be cached? */ - most_left = wwin->frame_x; - } - if ((int)wwin->frame_x + (int)wwin->frame->core->width > most_right) { - most_right = wwin->frame_x + wwin->frame->core->width; - } - if (wwin->frame_y < most_top) { - most_top = wwin->frame_y; - } - if (wwin->frame_y + wwin->frame->core->height > most_bottom) { - most_bottom = wwin->frame_y + wwin->frame->core->height; + if (!wwin->flags.miniaturized && !IS_VSTUCK(wwin) && + !wwin->flags.hidden) { + + head = wGetHeadForWindow(wwin); + + i = wwin->frame_x - strut[head][0]; + if (i < most_left) /* record positions, should this be cached? */ + most_left = i; + i = wwin->frame_x + wwin->frame->core->width + strut[head][1]; + if (HAS_BORDER(wwin)) + i+=2; + if (i > most_right) + most_right = i; + i = wwin->frame_y - strut[head][2]; + if (i < most_top) + most_top = i; + i = wwin->frame_y + wwin->frame->core->height + strut[head][3]; + if (HAS_BORDER(wwin)) + i+=2; + if (i > most_bottom) { + most_bottom = i; } } } } + if (most_left > 0) most_left = 0; + if (most_top > 0) most_top = 0; + scr->workspaces[workspace]->width = WMAX(most_right, scr->scr_width) - WMIN(most_left, 0); scr->workspaces[workspace]->height = WMAX(most_bottom, scr->scr_height) - WMIN(most_top, 0); @@ -741,6 +1176,7 @@ updateWorkspaceGeometry(WScreen *scr, int workspace, int *view_x, int *view_y) *view_y += -most_top - scr->workspaces[workspace]->view_y; scr->workspaces[workspace]->view_y = -most_top; + wfree(strut); } @@ -770,41 +1206,48 @@ wWorkspaceSetViewPort(WScreen *scr, int workspace, int view_x, int view_y) Bool adjust_flag = False; int diff_x, diff_y; static _delay_configure delay_configure = {NULL, 0}; + WWorkspace *wptr; WWindow *wwin; + wptr = scr->workspaces[workspace]; + /*printf("wWorkspaceSetViewPort %d %d\n", view_x, view_y);*/ updateWorkspaceGeometry(scr, workspace, &view_x, &view_y); - if (view_x + scr->scr_width > scr->workspaces[workspace]->width) { + if (view_x + scr->scr_width > wptr->width) { /* puts("right edge of vdesk"); */ - view_x = scr->workspaces[workspace]->width - scr->scr_width; + view_x = wptr->width - scr->scr_width; } if (view_x < 0) { /* puts("left edge of vdesk"); */ view_x = 0; } - if (view_y + scr->scr_height > scr->workspaces[workspace]->height) { + if (view_y + scr->scr_height > wptr->height) { /* puts("right edge of vdesk"); */ - view_y = scr->workspaces[workspace]->height - scr->scr_height; + view_y = wptr->height - scr->scr_height; } if (view_y < 0) { /* puts("left edge of vdesk"); */ view_y = 0; } - diff_x = scr->workspaces[workspace]->view_x - view_x; - diff_y = scr->workspaces[workspace]->view_y - view_y; + diff_x = wptr->view_x - view_x; + diff_y = wptr->view_y - view_y; if (!diff_x && !diff_y) return False; - scr->workspaces[workspace]->view_x = view_x; - scr->workspaces[workspace]->view_y = view_y; + wptr->view_x = view_x; + wptr->view_y = view_y; +#ifdef NETWM_HINTS + wNETWMUpdateDesktop(scr); +#endif for (wwin = scr->focused_window; wwin; wwin = wwin->prev) { - if (wwin->frame->workspace == workspace) { + if (wwin->frame->workspace == workspace && !IS_VSTUCK(wwin)) { wWindowMove(wwin, wwin->frame_x + diff_x, wwin->frame_y + diff_y); + adjust_flag = True; } } if (1) { /* if delay*/ @@ -818,15 +1261,14 @@ wWorkspaceSetViewPort(WScreen *scr, int workspace, int view_x, int view_y) void -wWorkspaceGetViewPosition(WScreen *scr, int workspace, int *view_x, int *view_y) +wWorkspaceGetViewPosition(WScreen *scr, int workspace, int *x, int *y) { - if (view_x) *view_x = scr->workspaces[workspace]->view_x; - if (view_y) *view_y = scr->workspaces[workspace]->view_y; + *x = scr->workspaces[workspace]->view_x; + *y = scr->workspaces[workspace]->view_y; } #endif - static void switchWSCommand(WMenu *menu, WMenuEntry *entry) { @@ -834,16 +1276,14 @@ switchWSCommand(WMenu *menu, WMenuEntry *entry) } - static void deleteWSCommand(WMenu *menu, WMenuEntry *entry) { wWorkspaceDelete(menu->frame->screen_ptr, - menu->frame->screen_ptr->workspace_count-1); + menu->frame->screen_ptr->workspace_count-1); } - static void newWSCommand(WMenu *menu, WMenuEntry *foo) { diff --git a/src/workspace.h b/src/workspace.h index 6f3cdcdd..7d0760de 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -41,12 +41,21 @@ void wWorkspaceChange(WScreen *scr, int workspace); void wWorkspaceForceChange(WScreen *scr, int workspace); #ifdef VIRTUAL_DESKTOP void wWorkspaceManageEdge(WScreen *scr); +void wWorkspaceUpdateEdge(WScreen *scr); +void wWorkspaceDestroyEdge(WScreen *scr); void wWorkspaceRaiseEdge(WScreen *scr); void wWorkspaceLowerEdge(WScreen *scr); -void wWorkspaceResizeViewPort(WScreen *scr, int workspace, int width, int height); +void wWorkspaceResizeViewPort(WScreen *scr, int workspace); +void wWorkspaceKeyboardMoveDesktop(WScreen *scr, WMPoint direction); Bool wWorkspaceSetViewPort(WScreen *scr, int workspace, int view_x, int view_y); Bool wWorkspaceAdjustViewPort(WScreen *scr, int workspace, int view_x, int view_y); void wWorkspaceGetViewPosition(WScreen *scr, int workspace, int *view_x, int *view_y); + +#define VEC_LEFT wmkpoint(-1,0) +#define VEC_RIGHT wmkpoint(1,0) +#define VEC_UP wmkpoint(0,-1) +#define VEC_DOWN wmkpoint(0,1) + #endif diff --git a/src/xdnd.c b/src/xdnd.c index 35085db7..b9a11dff 100644 --- a/src/xdnd.c +++ b/src/xdnd.c @@ -86,7 +86,7 @@ void wXDNDMakeAwareness(Window window) { } void wXDNDClearAwareness(Window window) { - long int xdnd_version = 3; + //long int xdnd_version = 3; XDeleteProperty (dpy, window, _XA_XdndAware); } diff --git a/src/xutil.c b/src/xutil.c index 71c9f981..964d602e 100644 --- a/src/xutil.c +++ b/src/xutil.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "wconfig.h" diff --git a/test/wtest.c b/test/wtest.c index 563dbe85..692a5341 100644 --- a/test/wtest.c +++ b/test/wtest.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include diff --git a/util/Makefile.am b/util/Makefile.am index d42a0a58..1346f994 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -3,9 +3,10 @@ AUTOMAKE_OPTIONS = no-dependencies pkgdatadir = $(datadir)/@PACKAGE@ -bin_PROGRAMS = wxcopy wxpaste wdwrite wdread getstyle setstyle seticons geticonset wmsetbg wmsetup wmagnify +bin_PROGRAMS = wxcopy wxpaste wdwrite wdread getstyle setstyle convertfonts \ + seticons geticonset wmsetbg wmsetup wmagnify -bin_SCRIPTS = wmaker.inst wm-oldmenu2new wsetfont wmchlocale wkdemenu.pl\ +bin_SCRIPTS = wmaker.inst wm-oldmenu2new wsetfont wmchlocale wkdemenu.pl \ wcopy wpaste EXTRA_DIST = wmaker.inst.in bughint wm-oldmenu2new wsetfont directjpeg.c \ @@ -31,6 +32,8 @@ setstyle_LDADD = \ $(top_builddir)/WINGs/libWUtil.a \ @XLFLAGS@ @XLIBS@ $(liblist) +convertfonts_LDADD = $(top_builddir)/WINGs/libWUtil.a $(liblist) + seticons_LDADD= $(top_builddir)/WINGs/libWUtil.a $(liblist) geticonset_LDADD= $(top_builddir)/WINGs/libWUtil.a $(liblist) diff --git a/util/convertfonts.c b/util/convertfonts.c new file mode 100644 index 00000000..2ed83a8a --- /dev/null +++ b/util/convertfonts.c @@ -0,0 +1,317 @@ +/* convertfonts.c - converts fonts in a style file to fontconfig format + * + * WindowMaker window manager + * + * Copyright (c) 2004 Dan Pascu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + + +#define PROG_VERSION "convertfonts (Window Maker) 1.0" + +#include +#include +#include +#include +#include + +#include "../src/wconfig.h" + +#define DEFAULT_FONT "sans-serif:pixelsize=12" + +char *FontOptions[] = { + "IconTitleFont", + "ClipTitleFont", + "DisplayFont", + "LargeDisplayFont", + "MenuTextFont", + "MenuTitleFont", + "WindowTitleFont", + "SystemFont", + "BoldSystemFont", + NULL +}; + + +char *ProgName; + + +static int +countChar(char *str, char c) +{ + int count = 0; + + if (!str) + return 0; + + for (; *str!=0; str++) { + if (*str == c) { + count++; + } + } + + return count; +} + + +typedef struct str { + char *str; + int len; +} str; + +#define XLFD_TOKENS 14 + + +static str* +getXLFDTokens(char *xlfd) +{ + static str tokens[XLFD_TOKENS]; + int i, len, size; + char *ptr; + + if (!xlfd || *xlfd!='-' || countChar(xlfd, '-')0; i++) { + /* skip one '-' */ + ptr++; + len--; + if (len <= 0) + break; + size = strcspn(ptr, "-"); + tokens[i].str = ptr; + tokens[i].len = size; + ptr += size; + len -= size; + } + + return tokens; +} + + +static int +strToInt(str *token) +{ + int res=0, pos, c; + + if (token->len==0 || token->str[0]=='*') { + return -1; + } else { + for (res=0, pos=0; poslen; pos++) { + c = token->str[pos] - '0'; + if (c<0 || c>9) + break; + res = res*10 + c; + } + } + return res; +} + + +static char* +mapSlantToName(str *slant) +{ + if (slant->len==0 || slant->str[0]=='*') + return "roman"; + + switch(slant->str[0]) { + case 'i': + return "italic"; + case 'o': + return "oblique"; + case 'r': + default: + return "roman"; + } +} + + +char* +xlfdToFc(char *xlfd, char *useFamily, Bool keepXLFD) +{ + str *tokens, *family, *weight, *slant; + char *name, buf[512]; + int size, pixelsize; + + tokens = getXLFDTokens(xlfd); + if (!tokens) + return wstrdup(DEFAULT_FONT); + + family = &(tokens[1]); + weight = &(tokens[2]); + slant = &(tokens[3]); + + if (useFamily) { + name = wstrdup(useFamily); + } else { + if (family->len==0 || family->str[0]=='*') + return wstrdup(DEFAULT_FONT); + + sprintf(buf, "%.*s", family->len, family->str); + name = wstrdup(buf); + } + + pixelsize = strToInt(&tokens[6]); + size = strToInt(&tokens[7]); + + if (size<=0 && pixelsize<=0) { + name = wstrappend(name, ":pixelsize=12"); + } else if (pixelsize>0) { + /* if pixelsize is present size will be ignored so we skip it */ + sprintf(buf, ":pixelsize=%d", pixelsize); + name = wstrappend(name, buf); + } else { + sprintf(buf, "-%d", size/10); + name = wstrappend(name, buf); + } + + if (weight->len>0 && weight->str[0]!='*') { + sprintf(buf, ":weight=%.*s", weight->len, weight->str); + name = wstrappend(name, buf); + } + + if (slant->len>0 && slant->str[0]!='*') { + sprintf(buf, ":slant=%s", mapSlantToName(slant)); + name = wstrappend(name, buf); + } + + if (keepXLFD) { + name = wstrappend(name, ":xlfd="); + name = wstrappend(name, xlfd); + } + + return name; +} + + +/* return converted font (if conversion is needed) else the original font */ +static char* +convertFont(char *font, Bool keepXLFD) +{ + if (font[0]=='-') { + if (!strchr(font, ',')) { + return xlfdToFc(font, NULL, keepXLFD); + } else { + return xlfdToFc(font, "sans-serif", keepXLFD); + } + } else { + return font; + } +} + + +void +print_help() +{ + printf("\nUsage: %s \n\n", ProgName); + puts("Converts fonts in a style file into fontconfig format"); + puts(""); + puts(" --help display this help and exit"); + puts(" --version output version information and exit"); + puts(" --keep-xlfd preserve the original xlfd by appending a ':xlfd=' hint"); + puts(" to the font name. This property is not used by the fontconfig"); + puts(" matching engine to find the font, but it is useful as a hint"); + puts(" about what the original font was to allow hand tuning the"); + puts(" result or restoring the xlfd. The default is to not add it"); + puts(" as it results in long, unreadable and confusing names."); + puts(" --sets-too try to approximate fontsets by using their first complete xlfd."); + puts(" This only works for singlebyte languages. The default is to"); + puts(" replace the fontset with the default: 'sans-serif:pixelsize=12'"); + puts(" which should display properly for any language."); + puts(""); +} + +// replace --sets-too with something better +int +main(int argc, char **argv) +{ + WMPropList *style, *key, *val; + char *file = NULL, *oldfont, *newfont; + struct stat statbuf; + Bool keepXLFD = False; + int i; + + ProgName = argv[0]; + + if (argc<2) { + print_help(); + exit(0); + } + + for (i=1; i < argc; i++) { + if (strcmp("--version", argv[i])==0) { + puts(PROG_VERSION); + exit(0); + } else if (strcmp("--help", argv[i])==0) { + print_help(); + exit(0); + } else if (strcmp("--keep-xlfd", argv[i])==0) { + keepXLFD = True;; + } else if (argv[i][0]=='-') { + printf("%s: invalid argument '%s'\n", ProgName, argv[i]); + printf("Try '%s --help' for more information\n", ProgName); + exit(1); + } else { + file = argv[i]; + } + } + + WMPLSetCaseSensitive(False); + + if (stat(file, &statbuf) < 0) { + perror(file); + exit(1); + } + + style = WMReadPropListFromFile(file); + if (!style) { + perror(file); + printf("%s: could not load style file.\n", ProgName); + exit(1); + } + + if (!WMIsPLDictionary(style)) { + printf("%s: '%s' is not a well formatted style file\n", ProgName, file); + exit(1); + } + + for (i=0; FontOptions[i]!=NULL; i++) { + key = WMCreatePLString(FontOptions[i]); + val = WMGetFromPLDictionary(style, key); + if (val) { + oldfont = WMGetFromPLString(val); + newfont = convertFont(oldfont, keepXLFD); + if (oldfont != newfont) { + val = WMCreatePLString(newfont); + WMPutInPLDictionary(style, key, val); + WMReleasePropList(val); + wfree(newfont); + } + } + WMReleasePropList(key); + } + + WMWritePropListToFile(style, file, True); + + exit(0); +} + + diff --git a/util/geticonset.c b/util/geticonset.c index 4853d4ca..a1387f58 100644 --- a/util/geticonset.c +++ b/util/geticonset.c @@ -106,7 +106,7 @@ main(int argc, char **argv) exit(1); } - iconset = WMCreatePLDictionary(NULL, NULL, NULL); + iconset = WMCreatePLDictionary(NULL, NULL); keylist = WMGetPLDictionaryKeys(all_windows); icon_key = WMCreatePLString("Icon"); @@ -122,10 +122,7 @@ main(int argc, char **argv) if (window_attrs && WMIsPLDictionary(window_attrs)) { icon_value = WMGetFromPLDictionary(window_attrs, icon_key); if (icon_value) { - - icondic = WMCreatePLDictionary(icon_key, icon_value, - NULL); - + icondic = WMCreatePLDictionary(icon_key, icon_value, NULL); WMPutInPLDictionary(iconset, window_name, icondic); } } diff --git a/util/getstyle.c b/util/getstyle.c index e0c54625..9cfdd908 100644 --- a/util/getstyle.c +++ b/util/getstyle.c @@ -467,7 +467,7 @@ strToInt(str *token) int res=0, pos, c; if (token->len==0 || token->str[0]=='*') { - return -1; + return -1; } else { for (res=0, pos=0; poslen; pos++) { c = token->str[pos] - '0'; @@ -589,7 +589,7 @@ findCopyFile(char *dir, char *file) if (!fullPath) { char buffer[4000]; - sprintf(buffer, "coould not find file %s", file); + sprintf(buffer, "could not find file %s", file); abortar(buffer); } copyFile(dir, fullPath); @@ -763,7 +763,7 @@ main(int argc, char **argv) prop = val; } - style = WMCreatePLDictionary(NULL, NULL, NULL); + style = WMCreatePLDictionary(NULL, NULL); for (i=0; options[i]!=NULL; i++) { key = WMCreatePLString(options[i]); @@ -776,7 +776,7 @@ main(int argc, char **argv) oldfont = WMGetFromPLString(val); newfont = convertFont(oldfont); - /* font is a reference to old if conversion is not needed */ + /* newfont is a reference to old if conversion is not needed */ if (newfont != oldfont) { WMReleasePropList(val); val = WMCreatePLString(newfont); diff --git a/util/wmagnify.c b/util/wmagnify.c index 0ab49b79..9d6703d9 100644 --- a/util/wmagnify.c +++ b/util/wmagnify.c @@ -10,6 +10,7 @@ #include #include +#include #include /* diff --git a/util/wmsetbg.c b/util/wmsetbg.c index 31592cb0..ba7c56fa 100644 --- a/util/wmsetbg.c +++ b/util/wmsetbg.c @@ -495,7 +495,7 @@ parseTexture(RContext *rc, char *text) XColor color; Pixmap pixmap = None; RImage *image = NULL; - int w, h; + //int w, h; int iwidth, iheight; RColor rcolor; diff --git a/wmlib/app.c b/wmlib/app.c index 96e11a75..6a7f5769 100644 --- a/wmlib/app.c +++ b/wmlib/app.c @@ -21,6 +21,7 @@ #include #include +#include #include "WMaker.h" #include "app.h" diff --git a/wrlib/convert.c b/wrlib/convert.c index ba96643e..95689bba 100644 --- a/wrlib/convert.c +++ b/wrlib/convert.c @@ -678,7 +678,8 @@ image2StandardPseudoColor(RContext *ctx, RImage *image) int x1, ofs; #ifdef DEBUG - printf("pseudo color dithering with %d colors per channel\n", cpc); + printf("pseudo color dithering with %d colors per channel\n", + ctx->attribs->colors_per_channel); #endif err = (short*)malloc(3*(image->width+2)*sizeof(short)); nerr = (short*)malloc(3*(image->width+2)*sizeof(short)); diff --git a/wrlib/draw.c b/wrlib/draw.c index e8a7e3f6..777f37d3 100644 --- a/wrlib/draw.c +++ b/wrlib/draw.c @@ -279,7 +279,7 @@ clipLineInRectangle(int xmin, int ymin, int xmax, int ymax, } else if (ocode & RIG) { y = *y1 + (*y2 - *y1) * (xmax - *x1) / (*x2 - *x1); x = xmax; - } else if (ocode & LEF) { + } else { //if (ocode & LEF) { y = *y1 + (*y2 - *y1) * (xmax - *x1) / (*x2 - *x1); x = xmin; } diff --git a/wrlib/x86_specific.c b/wrlib/x86_specific.c index 10bd5b6f..5f41cd06 100644 --- a/wrlib/x86_specific.c +++ b/wrlib/x86_specific.c @@ -37,33 +37,33 @@ x86_check_mmx() result = 0; asm volatile - ("pushal \n" // please dont forget this in any asm - "pushfl \n" // check whether cpuid supported - "pop %%eax \n" - "movl %%eax, %%ebx \n" - "xorl $(1<<21), %%eax \n" - "pushl %%eax \n" - "popfl \n" - "pushfl \n" - "popl %%eax \n" - "xorl %%ebx, %%eax \n" - "andl $(1<<21), %%eax \n" - "jz .NotPentium \n" - "xorl %%eax, %%eax \n" // no eax effect because of the movl below - // except reseting flags. is it needed? - "movl $1, %%eax \n" - "cpuid \n" - "test $(1<<23), %%edx \n" - "jz .NotMMX \n" + ("pushal \n\t" // please dont forget this in any asm + "pushfl \n\t" // check whether cpuid supported + "pop %%eax \n\t" + "movl %%eax, %%ebx \n\t" + "xorl $(1<<21), %%eax \n\t" + "pushl %%eax \n\t" + "popfl \n\t" + "pushfl \n\t" + "popl %%eax \n\t" + "xorl %%ebx, %%eax \n\t" + "andl $(1<<21), %%eax \n\t" + "jz .NotPentium \n\t" + "xorl %%eax, %%eax \n\t" // no eax effect because of the movl below + // except reseting flags. is it needed? + "movl $1, %%eax \n\t" + "cpuid \n\t" + "test $(1<<23), %%edx \n\t" + "jz .NotMMX \n\t" - "popal \n" // popal needed because the address of - "movl $1, %0 \n" // variable %0 may be kept in a register + "popal \n\t" // popal needed because the address of + "movl $1, %0 \n\t" // variable %0 may be kept in a register "jmp .noPop \n" - ".NotMMX: \n" - ".NotPentium: \n" +".NotMMX: \n" +".NotPentium: \n\t" "popal \n" - ".noPop: \n" +".noPop: \n\t" : "=m" (result)); @@ -80,341 +80,382 @@ x86_check_mmx() * * - try to align stack (local variable space) into quadword boundary */ - - - void -x86_mmx_TrueColor_32_to_16(unsigned char *image, // 8 - unsigned short *ximage, // 12 - short *err, // 16 - short *nerr, // 20 - short *rtable, // 24 - short *gtable, // 28 - short *btable, // 32 - int dr, // 36 - int dg, // 40 - int db, // 44 - unsigned int roffs, // 48 - unsigned int goffs, // 52 - unsigned int boffs, // 56 - int width, // 60 - int height, // 64 - int line_offset) // 68 +x86_mmx_TrueColor_32_to_16(unsigned char *image, + unsigned short *ximage, + short *err, + short *nerr, + short *rtable, + short *gtable, + short *btable, + int dr, + int dg, + int db, + unsigned int roffs, + unsigned int goffs, + unsigned int boffs, + int width, + int height, + int line_offset) { - /* - int x; //-4 - long long rrggbbaa;// -16 - long long pixel; //-24 - short *tmp_err; //-32 - short *tmp_nerr; //-36 - */ + long long rrggbbaa; + long long pixel; + short *tmp_err; + short *tmp_nerr; + int x; asm volatile - ( - "subl $128, %esp \n" // alloc some more stack - - "pushal \n" + ( + "pushal \n\t" // pack dr, dg and db into mm6 - "movl 36(%ebp), %eax \n" - "movl 40(%ebp), %ebx \n" - "movw %ax, -16(%ebp) \n" - - "movw %bx, -14(%ebp) \n" - "movl 44(%ebp), %eax \n" - "movw $0, -10(%ebp) \n" - "movw %ax, -12(%ebp) \n" + "movl %7, %%eax \n\t" + "movl %8, %%ebx \n\t" + "movl %9, %%ecx \n\t" + "movw %%ax, %16 \n\t" + "movw %%bx, %17 \n\t" + "movw %%cx, %18 \n\t" + "movw $0, %19 \n\t" - "movq -16(%ebp), %mm6 \n" // dr dg db 0 + "movq %16, %%mm6 \n\t" // dr dg db 0 // pack 4|4|4|4 into mm7, for shifting (/16) - "movl $0x00040004, -16(%ebp) \n" - "movl $0x00040004, -12(%ebp) \n" - "movq -16(%ebp), %mm7 \n" + "movl $0x00040004, %16 \n\t" + "movl $0x00040004, %18 \n\t" + "movq %16, %%mm7 \n\t" // store constant values for using with mmx when dithering - "movl $0x00070007, -16(%ebp) \n" - "movl $0x00070007, -12(%ebp) \n" - "movq -16(%ebp), %mm5 \n" + "movl $0x00070007, %16 \n\t" + "movl $0x00070007, %18 \n\t" + "movq %16, %%mm5 \n\t" - "movl $0x00050005, -16(%ebp) \n" - "movl $0x00050005, -12(%ebp) \n" - "movq -16(%ebp), %mm4 \n" + "movl $0x00050005, %16 \n\t" + "movl $0x00050005, %18 \n\t" + "movq %16, %%mm4 \n\t" - "movl $0x00030003, -16(%ebp) \n" - "movl $0x00030003, -12(%ebp) \n" - "movq -16(%ebp), %mm3 \n" + "movl $0x00030003, %16 \n\t" + "movl $0x00030003, %18 \n\t" + "movq %16, %%mm3 \n\t" // process 1 pixel / cycle, each component treated as 16bit - "movl 8(%ebp), %esi \n" // esi = image->data + "movl %0, %%esi \n" // esi = image->data -".LoopYa: \n" - "movl 60(%ebp), %eax \n" - "movl %eax, -4(%ebp) \n" // x = width +".LoopYa: \n\t" + "movl %13, %%eax \n\t" + "movl %%eax, %26 \n\t" // x = width - "movl 64(%ebp), %eax \n" - "decl %eax \n" // y-- - "movl %eax, 64(%ebp) \n" - "js .Enda \n" // if y < 0, goto end - "andl $1, %eax \n" - "jz .LoopY_1a \n" // if (y&1) goto LoopY_1 + "movl %14, %%eax \n\t" + "decl %%eax \n\t" // y-- + "movl %%eax, %14 \n\t" + "js .Enda \n\t" // if y < 0, goto end + "andl $1, %%eax \n\t" + "jz .LoopY_1a \n" // if (y&1) goto LoopY_1 -".LoopY_0a: \n" +".LoopY_0a: \n\t" - "movl 16(%ebp), %ebx \n" // ebx = err - "movl %ebx, -36(%ebp) \n" // [-36] = err - "movl 20(%ebp), %eax \n" // - "movl %eax, -32(%ebp) \n" // [-32] = nerr + "movl %2, %%ebx \n\t" // ebx = err + "movl %%ebx, %25 \n\t" // [-36] = err + "movl %3, %%eax \n\t" // + "movl %%eax, %24 \n\t" // [-32] = nerr "jmp .LoopXa \n" -".LoopY_1a: \n" +".LoopY_1a: \n\t" - "movl 20(%ebp), %ebx \n" // ebx = nerr - "movl %ebx, -36(%ebp) \n" // [-36] = nerr - "movl 16(%ebp), %eax \n" // - "movl %eax, -32(%ebp) \n" // [-32] = eerr + "movl %3, %%ebx \n\t" // ebx = nerr + "movl %%ebx, %25 \n\t" // [-36] = nerr + "movl %2, %%eax \n\t" // + "movl %%eax, %24 \n\t" // [-32] = eerr ".align 16 \n" -".LoopXa: \n" +".LoopXa: \n\t" // calculate errors and pixel components // depend on ebx, esi, mm6 - "movq (%ebx), %mm1 \n" // mm1 = error[0..3] - "punpcklbw (%esi), %mm0 \n" // mm0 = image->data[0..3] - "psrlw $8, %mm0 \n" // fixup mm0 - "paddusb %mm1, %mm0 \n" // mm0 = mm0 + mm1 (sat. to 255) - "movq %mm0, -24(%ebp) \n" // save the pixel + "movq (%%ebx), %%mm1 \n\t" // mm1 = error[0..3] + "punpcklbw (%%esi), %%mm0 \n\t" // mm0 = image->data[0..3] + "psrlw $8, %%mm0 \n\t" // fixup mm0 + "paddusb %%mm1, %%mm0 \n\t" // mm0 = mm0 + mm1 (sat. to 255) + "movq %%mm0, %20 \n\t" // save the pixel - "movzwl -24(%ebp), %ecx \n" // ecx = pixel.red - "movl 24(%ebp), %edi \n" // edi = rtable + "movzwl %20, %%ecx \n\t" // ecx = pixel.red + "movl %4, %%edi \n\t" // edi = rtable //agi - "leal (%edi, %ecx, 2), %eax \n" // eax = &rtable[pixel.red] + "leal (%%edi, %%ecx, 2), %%eax \n\t" // eax = &rtable[pixel.red] // agi - "movw (%eax), %dx \n" // dx = rtable[pixel.red] - "movw %dx, -16(%ebp) \n" // save rr + "movw (%%eax), %%dx \n\t" // dx = rtable[pixel.red] + "movw %%dx, %16 \n\t" // save rr - "movzwl -22(%ebp), %ecx \n" // ecx = pixel.green - "movl 28(%ebp), %edi \n" // edi = gtable + "movzwl %21, %%ecx \n\t" // ecx = pixel.green + "movl %5, %%edi \n\t" // edi = gtable //agi - "leal (%edi, %ecx, 2), %eax \n" // eax = >able[pixel.green] + "leal (%%edi, %%ecx, 2), %%eax \n\t" // eax = >able[pixel.green] //agi - "movw (%eax), %dx \n" // dx = gtable[pixel.green] - "movw %dx, -14(%ebp) \n" // save gg + "movw (%%eax), %%dx \n\t" // dx = gtable[pixel.green] + "movw %%dx, %17 \n\t" // save gg - "movzwl -20(%ebp), %ecx \n" // ecx = pixel.blue - "movl 32(%ebp), %edi \n" // ebx = btable + "movzwl %22, %%ecx \n\t" // ecx = pixel.blue + "movl %6, %%edi \n\t" // ebx = btable //agi - "leal (%edi, %ecx, 2), %eax \n" // eax = &btable[pixel.blue] + "leal (%%edi, %%ecx, 2), %%eax \n\t" // eax = &btable[pixel.blue] //agi - "movw (%eax), %dx \n" // dx = btable[pixel.blue] - "movw %dx, -12(%ebp) \n" // save bb + "movw (%%eax), %%dx \n\t" // dx = btable[pixel.blue] + "movw %%dx, %18 \n\t" // save bb - "movw $0, -10(%ebp) \n" // save dummy aa + "movw $0, %19 \n\t" // save dummy aa - "movq -16(%ebp), %mm1 \n" // load mm1 with rrggbbaa - "pmullw %mm6, %mm1 \n" // mm1 = rr*dr|... - "psubsw %mm1, %mm0 \n" // error = pixel - mm1 + "movq %16, %%mm1 \n\t" // load mm1 with rrggbbaa + "pmullw %%mm6, %%mm1 \n\t" // mm1 = rr*dr|... + "psubsw %%mm1, %%mm0 \n\t" // error = pixel - mm1 // distribute the error // depend on mm0, mm7, mm3, mm4, mm5 - "movl -36(%ebp), %ebx \n" + "movl %25, %%ebx \n\t" - "movq %mm0, %mm1 \n" - "pmullw %mm5, %mm1 \n" // mm1 = mm1*7 - "psrlw %mm7, %mm1 \n" // mm1 = mm1/16 - "paddw 8(%ebx), %mm1 \n" - "movq %mm1, 8(%ebx) \n" // err[x+1,y] = rer*7/16 + "movq %%mm0, %%mm1 \n\t" + "pmullw %%mm5, %%mm1 \n\t" // mm1 = mm1*7 + "psrlw %%mm7, %%mm1 \n\t" // mm1 = mm1/16 + "paddw 8(%%ebx), %%mm1 \n\t" + "movq %%mm1, 8(%%ebx) \n\t" // err[x+1,y] = rer*7/16 - "movl -32(%ebp), %ebx \n" + "movl %24, %%ebx \n\t" - "movq %mm0, %mm1 \n" - "pmullw %mm4, %mm1 \n" // mm1 = mm1*5 - "psrlw %mm7, %mm1 \n" // mm1 = mm1/16 - "paddw -8(%ebx), %mm1 \n" - "movq %mm1, -8(%ebx) \n" // err[x-1,y+1] += rer*3/16 + "movq %%mm0, %%mm1 \n\t" + "pmullw %%mm4, %%mm1 \n\t" // mm1 = mm1*5 + "psrlw %%mm7, %%mm1 \n\t" // mm1 = mm1/16 + "paddw -8(%%ebx), %%mm1 \n\t" + "movq %%mm1, -8(%%ebx) \n\t" // err[x-1,y+1] += rer*3/16 - "movq %mm0, %mm1 \n" - "pmullw %mm3, %mm1 \n" // mm1 = mm1*3 - "psrlw %mm7, %mm1 \n" // mm1 = mm1/16 - "paddw 8(%ebx), %mm1 \n" - "movq %mm1, (%ebx) \n" // err[x,y+1] += rer*5/16 + "movq %%mm0, %%mm1 \n\t" + "pmullw %%mm3, %%mm1 \n\t" // mm1 = mm1*3 + "psrlw %%mm7, %%mm1 \n\t" // mm1 = mm1/16 + "paddw 8(%%ebx), %%mm1 \n\t" + "movq %%mm1, (%%ebx) \n\t" // err[x,y+1] += rer*5/16 - "psrlw %mm7, %mm0 \n" // mm0 = mm0/16 - "movq %mm0, 8(%ebx) \n" // err[x+1,y+1] = rer/16 + "psrlw %%mm7, %%mm0 \n\t" // mm0 = mm0/16 + "movq %%mm0, 8(%%ebx) \n\t" // err[x+1,y+1] = rer/16 // calculate final pixel value and store - "movl 48(%ebp), %ecx \n" - "movw -16(%ebp), %ax \n" - "shlw %cl, %ax \n" //NP* ax = r<data += 4 + "addl $4, %%esi \n\t" // image->data += 4 - "decl -4(%ebp) \n" // x-- - "jnz .LoopXa \n" // if x>0, goto .LoopX + "decl %26 \n\t" // x-- + "jnz .LoopXa \n\t" // if x>0, goto .LoopX // depend on edx - "addl 68(%ebp), %edx \n" // add extra offset to ximage - "movl %edx, 12(%ebp) \n" + "addl %15, %%edx \n\t" // add extra offset to ximage + "movl %%edx, %1 \n\t" "jmp .LoopYa \n" -".Enda: \n" // THE END - - "emms \n" - - "popal \n" +".Enda: \n\t" // THE END + "emms \n\t" + "popal \n\t" + : + : + "m" (image), // %0 + "m" (ximage), // %1 + "m" (err), // %2 + "m" (nerr), // %3 + "m" (rtable), // %4 + "m" (gtable), // %5 + "m" (btable), // %6 + "m" (dr), // %7 + "m" (dg), // %8 + "m" (db), // %9 + "m" (roffs), // %10 + "m" (goffs), // %11 + "m" (boffs), // %12 + "m" (width), // %13 + "m" (height), // %14 + "m" (line_offset), // %15 + "m" (rrggbbaa), // %16 (access to rr) + "m" ((*((short*)(&rrggbbaa)+1))), // %17 (access to gg) + "m" ((*((short*)(&rrggbbaa)+2))), // %18 (access to bb) + "m" ((*((short*)(&rrggbbaa)+3))), // %19 (access to aa) + "m" (pixel), // %20 (access to pixel.r) + "m" ((*((short*)(&pixel)+1))), // %21 (access to pixel.g) + "m" ((*((short*)(&pixel)+2))), // %22 (access to pixel.b) + "m" ((*((short*)(&pixel)+3))), // %23 (access to pixel.a) + "m" (tmp_err), // %24 + "m" (tmp_nerr), // %25 + "m" (x) // %26 ); } - - - - void -x86_mmx_TrueColor_24_to_16(unsigned char *image, // 8 - unsigned short *ximage, // 12 - short *err, // 16 - short *nerr, // 20 - short *rtable, // 24 - short *gtable, // 28 - short *btable, // 32 - int dr, // 36 - int dg, // 40 - int db, // 44 - unsigned int roffs, // 48 - unsigned int goffs, // 52 - unsigned int boffs, // 56 - int width, // 60 - int height, // 64 - int line_offset) // 68 +x86_mmx_TrueColor_24_to_16(unsigned char *image, + unsigned short *ximage, + short *err, + short *nerr, + short *rtable, + short *gtable, + short *btable, + int dr, + int dg, + int db, + unsigned int roffs, + unsigned int goffs, + unsigned int boffs, + int width, + int height, + int line_offset) { - /* - int x; //-4 - long long rrggbbaa;// -16 - long long pixel; //-24 - short *tmp_err; //-32 - short *tmp_nerr; //-36 - * - int w1; // -64 - int w2; // -68 - */ + long long rrggbbaa; + long long pixel; + + short *tmp_err; + short *tmp_nerr; + + int x; + int w1; + int w2; asm volatile ( - "subl $128, %esp \n" // alloc some more stack - - "pushal \n" + "pushal \n\t" - "movl 60(%ebp), %eax \n" // eax = width - "movl %eax, %ebx \n" - "shrl $2, %eax \n" - "movl %eax, -64(%ebp) \n" // w1 = width / 4 - "andl $3, %ebx \n" - "movl %ebx, -68(%ebp) \n" // w2 = width % 4 + "movl %13, %%eax \n\t" // eax = width + "movl %%eax, %%ebx \n\t" + "shrl $2, %%eax \n\t" + "movl %%eax, %27 \n\t" // w1 = width / 4 + "andl $3, %%ebx \n\t" + "movl %%ebx, %28 \n" // w2 = width %% 4 -".LoopYc: \n" - "movl 60(%ebp), %eax \n" - "movl %eax, -4(%ebp) \n" // x = width +".LoopYc: \n\t" + "movl %13, %%eax \n\t" + "movl %%eax, %26 \n\t" // x = width - "decl 64(%ebp) \n" // height-- - "js .Endc \n" // if height < 0 then end + "decl %14 \n\t" // height-- + "js .Endc \n\t" // if height < 0 then end - "movl 64(%ebp), %eax \n" - "decl %eax \n" // y-- - "movl %eax, 64(%ebp) \n" - "js .Endc \n" // if y < 0, goto end - "andl $1, %eax \n" - "jz .LoopY_1c \n" // if (y&1) goto LoopY_1 + "movl %14, %%eax \n\t" + "decl %%eax \n\t" // y-- + "movl %%eax, %14 \n\t" + "js .Endc \n\t" // if y < 0, goto end + "andl $1, %%eax \n\t" + "jz .LoopY_1c \n" // if (y&1) goto LoopY_1 -".LoopY_0c: \n" +".LoopY_0c: \n\t" - "movl 16(%ebp), %ebx \n" // ebx = err - "movl %ebx, -36(%ebp) \n" // [-36] = err - "movl 20(%ebp), %eax \n" // - "movl %eax, -32(%ebp) \n" // [-32] = nerr + "movl %2, %%ebx \n\t" // ebx = err + "movl %%ebx, %25 \n\t" // [-36] = err + "movl %3, %%eax \n\t" // + "movl %%eax, %24 \n\t" // [-32] = nerr "jmp .LoopX_1c \n" -".LoopY_1c: \n" +".LoopY_1c: \n\t" - "movl 20(%ebp), %ebx \n" // ebx = nerr - "movl %ebx, -36(%ebp) \n" // [-36] = nerr - "movl 16(%ebp), %eax \n" // - "movl %eax, -32(%ebp) \n" // [-32] = eerr + "movl %3, %%ebx \n\t" // ebx = nerr + "movl %%ebx, %25 \n\t" // [-36] = nerr + "movl %2, %%eax \n\t" // + "movl %%eax, %24 \n\t" // [-32] = eerr - ".align 16 \n" + ".align 16 \n\t" - "movl %eax, -4(%ebp) \n" // x = w1 -".LoopX_1c: \n" - "decl -4(%ebp) \n" // x-- - "js .Xend1_c \n" // if x < 0 then end + "movl %%eax, %26 \n" // x = w1 +".LoopX_1c: \n\t" + "decl %26 \n\t" // x-- + "js .Xend1_c \n\t" // if x < 0 then end // do conversion of 4 pixels - "movq 16(%ebp), %mm0 \n" // mm0 = err + "movq %2, %%mm0 \n\t" // mm0 = err "jmp .LoopX_1c \n" -".Xend1_c: \n" +".Xend1_c: \n\t" - "movl -68(%ebp), %eax \n" - "movl %eax, -4(%ebp) \n" // x = w2 -".LoopX_2c: \n" - "decl -4(%ebp) \n" // x-- - "js .Xend2_c \n" // + "movl %28, %%eax \n\t" + "movl %%eax, %26 \n" // x = w2 +".LoopX_2c: \n\t" + "decl %26 \n\t" // x-- + "js .Xend2_c \n\t" // // do conversion "jmp .LoopX_2c \n" -".Xend2_c: \n" +".Xend2_c: \n\t" - "movl -64(%ebp), %eax \n" + "movl %27, %%eax \n\t" "jmp .LoopYc \n" -".Endc: \n" // THE END - - "emms \n" - - "popal \n" +".Endc: \n\t" // THE END + "emms \n\t" + "popal \n\t" + : + : + "m" (image), // %0 + "m" (ximage), // %1 + "m" (err), // %2 + "m" (nerr), // %3 + "m" (rtable), // %4 + "m" (gtable), // %5 + "m" (btable), // %6 + "m" (dr), // %7 + "m" (dg), // %8 + "m" (db), // %9 + "m" (roffs), // %10 + "m" (goffs), // %11 + "m" (boffs), // %12 + "m" (width), // %13 + "m" (height), // %14 + "m" (line_offset), // %15 + "m" (rrggbbaa), // %16 (access to rr) + "m" ((*((short*)(&rrggbbaa)+1))), // %17 (access to gg) + "m" ((*((short*)(&rrggbbaa)+2))), // %18 (access to bb) + "m" ((*((short*)(&rrggbbaa)+3))), // %19 (access to aa) + "m" (pixel), // %20 (access to pixel.r) + "m" ((*((short*)(&pixel)+1))), // %21 (access to pixel.g) + "m" ((*((short*)(&pixel)+2))), // %22 (access to pixel.b) + "m" ((*((short*)(&pixel)+3))), // %23 (access to pixel.a) + "m" (tmp_err), // %24 + "m" (tmp_nerr), // %25 + "m" (x), // %26 + "m" (w1), // %27 + "m" (w2) // %28 ); } @@ -425,272 +466,293 @@ x86_mmx_TrueColor_24_to_16(unsigned char *image, // 8 void -x86_PseudoColor_32_to_8(unsigned char *image, // 8 - unsigned char *ximage, // 12 - char *err, // 16 - char *nerr, // 20 - short *ctable, // 24 - int dr, // 28 - int dg, // 32 - int db, // 36 - unsigned long *pixels, // 40 - int cpc, // 44 - int width, // 48 - int height, // 52 - int bytesPerPixel, // 56 - int line_offset) // 60 +x86_PseudoColor_32_to_8(unsigned char *image, + unsigned char *ximage, + char *err, + char *nerr, + short *ctable, + int dr, + int dg, + int db, + unsigned long *pixels, + int cpc, + int width, + int height, + int bytesPerPixel, + int line_offset) { - /* - * int x; -4 - * int cpcpc; -8 - * - * int rr; -12 - * int gg; -16 - * int bb; -20 - * - * char ndr; -21 - * char ndg; -22 - * char ndb; -23 - * - * char *err; -32 - * char *nerr; -36 - * - */ + int x; + int cpcpc; + + int rr; + int gg; + int bb; + + char *tmp_err; + char *tmp_nerr; + + char ndr; // aparently not used + char ndg; // aparently not used + char ndb; // aparently not used + asm volatile ( - "subl $128, %esp \n" // alloc some stack space - "pushal \n" + "pushal \n\t" - "movl 44(%ebp), %eax \n" - "mulb 44(%ebp) \n" - "movl %eax, -8(%ebp) \n" // cpcpc = cpc*cpc + "movl %9, %%eax \n\t" + "mulb %9 \n\t" + "movl %%eax, %15 \n\t" // cpcpc = cpc*cpc // eax will always be <= 0xffff // process 1 pixel / cycle, each component treated as 16bit - "movl 8(%ebp), %esi \n" // esi = image->data + "movl %0, %%esi \n" // esi = image->data -".LoopYb: \n" - "movl 48(%ebp), %ecx \n" - "movl %ecx, -4(%ebp) \n" // x = width +".LoopYb: \n\t" + "movl %10, %%ecx \n\t" + "movl %%ecx, %14 \n\t" // x = width - "movl 52(%ebp), %ecx \n" - "decl %ecx \n" // y-- - "movl %ecx, 52(%ebp) \n" - "js .Endb \n" // if y < 0, goto end - "andl $1, %ecx \n" - "jz .LoopY_1b \n" // if (y&1) goto LoopY_1 + "movl %11, %%ecx \n\t" + "decl %%ecx \n\t" // y-- + "movl %%ecx, %11 \n\t" + "js .Endb \n\t" // if y < 0, goto end + "andl $1, %%ecx \n\t" + "jz .LoopY_1b \n" // if (y&1) goto LoopY_1 -".LoopY_0b: \n" +".LoopY_0b: \n\t" - "movl 16(%ebp), %ebx \n" // ebx = err -//useless "movl %ebx, -36(%ebp) \n" // [-36] = err - "movl 20(%ebp), %ecx \n" // - "movl %ecx, -32(%ebp) \n" // [-32] = nerr + "movl %2, %%ebx \n\t" // ebx = err +//useless "movl %%ebx, %20 \n\t" // [-36] = err + "movl %3, %%ecx \n\t" // + "movl %%ecx, %19 \n\t" // [-32] = nerr - "movl $0, (%ecx) \n" // init error of nerr[0] to 0 + "movl $0, (%%ecx) \n\t" // init error of nerr[0] to 0 "jmp .LoopXb \n" -".LoopY_1b: \n" +".LoopY_1b: \n\t" - "movl 20(%ebp), %ebx \n" // ebx = nerr -//useless "movl %ebx, -36(%ebp) \n" // [-36] = nerr - "movl 16(%ebp), %ecx \n" // - "movl %ecx, -32(%ebp) \n" // [-32] = err + "movl %3, %%ebx \n\t" // ebx = nerr +//useless "movl %%ebx, %20 \n\t" // [-36] = nerr + "movl %2, %%ecx \n\t" // + "movl %%ecx, %19 \n\t" // [-32] = err - "movl $0, (%ecx) \n" // init error of nerr[0] to 0 + "movl $0, (%%ecx) \n\t" // init error of nerr[0] to 0 ".align 16 \n" -".LoopXb: \n" +".LoopXb: \n\t" - "movl 24(%ebp), %edi \n" // edi = ctable - "xorl %edx, %edx \n" // zero the upper word on edx + "movl %4, %%edi \n\t" // edi = ctable + "xorl %%edx, %%edx \n\t" // zero the upper word on edx // RED // depends on ebx==err, esi==image->data, edi - "movzbw (%esi), %dx \n" // dx = image->data[0] - "movsbw (%ebx), %ax \n" // ax = error[0] - "addw %ax, %dx \n" // pixel.red = data[0] + error[0] + "movzbw (%%esi), %%dx \n\t" // dx = image->data[0] + "movsbw (%%ebx), %%ax \n\t" // ax = error[0] + "addw %%ax, %%dx \n\t" // pixel.red = data[0] + error[0] - "testb %dh, %dh \n" // test if pixel.red < 0 or > 255 - "jz .OKRb \n" // 0 <= pixel.red <= 255 - "js .NEGRb \n" // pixel.red < 0 - "movw $0xff, %dx \n" // pixel.red > 255 + "testb %%dh, %%dh \n\t" // test if pixel.red < 0 or > 255 + "jz .OKRb \n\t" // 0 <= pixel.red <= 255 + "js .NEGRb \n\t" // pixel.red < 0 + "movw $0xff, %%dx \n\t" // pixel.red > 255 "jmp .OKRb \n" -".NEGRb: \n" - "xorw %dx, %dx \n" -".OKRb: \n" +".NEGRb: \n\t" + "xorw %%dx, %%dx \n" +".OKRb: \n\t" //partial reg - "leal (%edi, %edx, 2), %ecx \n" // ecx = &ctable[pixel.red] + "leal (%%edi, %%edx, 2), %%ecx \n\t" // ecx = &ctable[pixel.red] //agi - "movl (%ecx), %eax \n" // ax = ctable[pixel.red] - "movw %ax, -12(%ebp) \n" // save rr + "movl (%%ecx), %%eax \n\t" // ax = ctable[pixel.red] + "movw %%ax, %16 \n\t" // save rr - "mulb 28(%ebp) \n" // ax = rr*dr - "subw %ax, %dx \n" // rer = dx = dx - rr*dr + "mulb %5 \n\t" // ax = rr*dr + "subw %%ax, %%dx \n\t" // rer = dx = dx - rr*dr - "movswl %dx, %eax \n" // save rer + "movswl %%dx, %%eax \n\t" // save rer // distribute error - "leal (, %eax, 8), %ecx \n" - "subw %dx, %cx \n" // cx = rer * 7 - "sarw $4, %cx \n" // cx = rer * 7 / 16 - "addb %cl, 4(%ebx) \n" // err[x+1] += rer * 7 / 16 + "leal (, %%eax, 8), %%ecx \n\t" + "subw %%dx, %%cx \n\t" // cx = rer * 7 + "sarw $4, %%cx \n\t" // cx = rer * 7 / 16 + "addb %%cl, 4(%%ebx) \n\t" // err[x+1] += rer * 7 / 16 - "movl -32(%ebp), %ecx \n" // ecx = nerr + "movl %19, %%ecx \n\t" // ecx = nerr - "leaw (%eax, %eax, 4), %dx \n" // dx = rer * 5 - "sarw $4, %dx \n" // dx = rer * 5 / 16 - "addb %dl, (%ecx) \n" // nerr[x] += rer * 5 / 16 + "leaw (%%eax, %%eax, 4), %%dx \n\t" // dx = rer * 5 + "sarw $4, %%dx \n\t" // dx = rer * 5 / 16 + "addb %%dl, (%%ecx) \n\t" // nerr[x] += rer * 5 / 16 - "leaw (%eax, %eax, 2), %dx \n" // dx = rer * 3 - "sarw $4, %dx \n" // dx = rer * 3 / 16 - "addb %dl, -4(%ecx) \n" // nerr[x-1] += rer * 3 / 16 + "leaw (%%eax, %%eax, 2), %%dx \n\t" // dx = rer * 3 + "sarw $4, %%dx \n\t" // dx = rer * 3 / 16 + "addb %%dl, -4(%%ecx) \n\t" // nerr[x-1] += rer * 3 / 16 - "sarw $4, %ax \n" // ax = rer / 16 - "movb %al, 4(%ecx) \n" // nerr[x+1] = rer / 16 + "sarw $4, %%ax \n\t" // ax = rer / 16 + "movb %%al, 4(%%ecx) \n\t" // nerr[x+1] = rer / 16 // GREEN // depends on ebx, esi, edi - "movzbw 1(%esi), %dx \n" // dx = image->data[1] - "movsbw 1(%ebx), %ax \n" // ax = error[1] - "addw %ax, %dx \n" // pixel.grn = data[1] + error[1] + "movzbw 1(%%esi), %%dx \n\t" // dx = image->data[1] + "movsbw 1(%%ebx), %%ax \n\t" // ax = error[1] + "addw %%ax, %%dx \n\t" // pixel.grn = data[1] + error[1] - "testb %dh, %dh \n" // test if pixel.grn < 0 or > 255 - "jz .OKGb \n" // 0 <= pixel.grn <= 255 - "js .NEGGb \n" // pixel.grn < 0 - "movw $0xff, %dx \n" // pixel.grn > 255 + "testb %%dh, %%dh \n\t" // test if pixel.grn < 0 or > 255 + "jz .OKGb \n\t" // 0 <= pixel.grn <= 255 + "js .NEGGb \n\t" // pixel.grn < 0 + "movw $0xff, %%dx \n\t" // pixel.grn > 255 "jmp .OKGb \n" -".NEGGb: \n" - "xorw %dx, %dx \n" -".OKGb: \n" +".NEGGb: \n\t" + "xorw %%dx, %%dx \n" +".OKGb: \n\t" // partial reg - "leal (%edi, %edx, 2), %ecx \n" // ecx = &ctable[pixel.grn] + "leal (%%edi, %%edx, 2), %%ecx \n\t" // ecx = &ctable[pixel.grn] //agi - "movw (%ecx), %ax \n" // ax = ctable[pixel.grn] - "movw %ax, -16(%ebp) \n" // save gg + "movw (%%ecx), %%ax \n\t" // ax = ctable[pixel.grn] + "movw %%ax, %17 \n\t" // save gg - "mulb 28(%ebp) \n" // ax = gg*dg - "subw %ax, %dx \n" // ger = dx = dx - gg*dg + "mulb %6 \n\t" // ax = gg*dg + "subw %%ax, %%dx \n\t" // ger = dx = dx - gg*dg - "movswl %dx, %eax \n" // save ger + "movswl %%dx, %%eax \n\t" // save ger // distribute error - "leal (, %eax, 8), %ecx \n" - "subw %dx, %cx \n" // cx = ger * 7 - "sarw $4, %cx \n" // cx = ger * 7 / 16 - "addb %cl, 5(%ebx) \n" // err[x+1] += ger * 7 / 16 + "leal (, %%eax, 8), %%ecx \n\t" + "subw %%dx, %%cx \n\t" // cx = ger * 7 + "sarw $4, %%cx \n\t" // cx = ger * 7 / 16 + "addb %%cl, 5(%%ebx) \n\t" // err[x+1] += ger * 7 / 16 - "movl -32(%ebp), %ecx \n" // ecx = nerr + "movl %19, %%ecx \n\t" // ecx = nerr - "leaw (%eax, %eax, 4), %dx \n" // dx = ger * 5 - "sarw $4, %dx \n" // dx = ger * 5 / 16 - "addb %dl, 1(%ecx) \n" // nerr[x] += ger * 5 / 16 + "leaw (%%eax, %%eax, 4), %%dx \n\t" // dx = ger * 5 + "sarw $4, %%dx \n\t" // dx = ger * 5 / 16 + "addb %%dl, 1(%%ecx) \n\t" // nerr[x] += ger * 5 / 16 - "leaw (%eax, %eax, 2), %dx \n" // dx = ger * 3 - "sarw $4, %dx \n" // dx = ger * 3 / 16 - "addb %dl, -3(%ecx) \n" // nerr[x-1] += ger * 3 / 16 + "leaw (%%eax, %%eax, 2), %%dx \n\t" // dx = ger * 3 + "sarw $4, %%dx \n\t" // dx = ger * 3 / 16 + "addb %%dl, -3(%%ecx) \n\t" // nerr[x-1] += ger * 3 / 16 - "sarw $4, %ax \n" // ax = ger / 16 - "movb %al, 5(%ecx) \n" // nerr[x+1] = ger / 16 + "sarw $4, %%ax \n\t" // ax = ger / 16 + "movb %%al, 5(%%ecx) \n\t" // nerr[x+1] = ger / 16 // BLUE // depends on ebx, esi - "movzbw 2(%esi), %dx \n" // dx = image->data[2] - "movsbw 2(%ebx), %ax \n" // ax = error[2] - "addw %ax, %dx \n" // pixel.grn = data[2] + error[2] + "movzbw 2(%%esi), %%dx \n\t" // dx = image->data[2] + "movsbw 2(%%ebx), %%ax \n\t" // ax = error[2] + "addw %%ax, %%dx \n\t" // pixel.grn = data[2] + error[2] - "testb %dh, %dh \n" // test if pixel.blu < 0 or > 255 - "jz .OKBb \n" // 0 <= pixel.blu <= 255 - "js .NEGBb \n" // pixel.blu < 0 - "movw $0xff, %dx \n" // pixel.blu > 255 + "testb %%dh, %%dh \n\t" // test if pixel.blu < 0 or > 255 + "jz .OKBb \n\t" // 0 <= pixel.blu <= 255 + "js .NEGBb \n\t" // pixel.blu < 0 + "movw $0xff, %%dx \n\t" // pixel.blu > 255 "jmp .OKBb \n" -".NEGBb: \n" - "xorw %dx, %dx \n" -".OKBb: \n" +".NEGBb: \n\t" + "xorw %%dx, %%dx \n" +".OKBb: \n\t" //partial reg - "leal (%edi, %edx, 2), %ecx \n" // ecx = &ctable[pixel.blu] + "leal (%%edi, %%edx, 2), %%ecx \n\t" // ecx = &ctable[pixel.blu] //agi - "movw (%ecx), %ax \n" // ax = ctable[pixel.blu] - "movw %ax, -20(%ebp) \n" // save bb + "movw (%%ecx), %%ax \n\t" // ax = ctable[pixel.blu] + "movw %%ax, %18 \n\t" // save bb - "mulb 28(%ebp) \n" // ax = bb*db - "subw %ax, %dx \n" // ber = dx = dx - bb*db - "movswl %dx, %eax \n" // save ber + "mulb %7 \n\t" // ax = bb*db + "subw %%ax, %%dx \n\t" // ber = dx = dx - bb*db + "movswl %%dx, %%eax \n\t" // save ber // distribute error - "leal (, %eax, 8), %ecx \n" - "subw %dx, %cx \n" // cx = ber * 7 - "sarw $4, %cx \n" // cx = ber * 7 / 16 - "addb %cl, 6(%ebx) \n" // err[x+1] += ber * 7 / 16 + "leal (, %%eax, 8), %%ecx \n\t" + "subw %%dx, %%cx \n\t" // cx = ber * 7 + "sarw $4, %%cx \n\t" // cx = ber * 7 / 16 + "addb %%cl, 6(%%ebx) \n\t" // err[x+1] += ber * 7 / 16 - "movl -32(%ebp), %ecx \n" // ecx = nerr + "movl %19, %%ecx \n\t" // ecx = nerr - "leaw (%eax, %eax, 4), %dx \n" // dx = ber * 5 - "sarw $4, %dx \n" // dx = ber * 5 / 16 - "addb %dl, 2(%ecx) \n" // nerr[x] += ber * 5 / 16 + "leaw (%%eax, %%eax, 4), %%dx \n\t" // dx = ber * 5 + "sarw $4, %%dx \n\t" // dx = ber * 5 / 16 + "addb %%dl, 2(%%ecx) \n\t" // nerr[x] += ber * 5 / 16 - "leaw (%eax, %eax, 2), %dx \n" // dx = ber * 3 - "sarw $4, %dx \n" // dx = ber * 3 / 16 - "addb %dl, -4(%ecx) \n" // nerr[x-1] += ber * 3 / 16 + "leaw (%%eax, %%eax, 2), %%dx \n\t" // dx = ber * 3 + "sarw $4, %%dx \n\t" // dx = ber * 3 / 16 + "addb %%dl, -4(%%ecx) \n\t" // nerr[x-1] += ber * 3 / 16 - "sarw $4, %ax \n" // ax = ber / 16 - "movb %al, 6(%ecx) \n" // nerr[x+1] = ber / 16 + "sarw $4, %%ax \n\t" // ax = ber / 16 + "movb %%al, 6(%%ecx) \n\t" // nerr[x+1] = ber / 16 - "andl $0xffff, %eax \n" + "andl $0xffff, %%eax \n\t" // depends on eax & 0xffff0000 == 0 // calculate the index of the value of the pixel - "movw -12(%ebp), %ax \n" // ax = rr - "mulb -8(%ebp) \n" // ax = cpcpc*rr - "movw %ax, %cx \n" - "movw -16(%ebp), %ax \n" // ax = gg - "mulb 44(%ebp) \n" // ax = cpc*gg - "addw %cx, %ax \n" // ax = cpc*gg + cpcpc*rr - "addw -20(%ebp), %ax \n" // ax = cpcpc*rr + cpc*gg + bb + "movw %16, %%ax \n\t" // ax = rr + "mulb %15 \n\t" // ax = cpcpc*rr + "movw %%ax, %%cx \n\t" + "movw %17, %%ax \n\t" // ax = gg + "mulb %9 \n\t" // ax = cpc*gg + "addw %%cx, %%ax \n\t" // ax = cpc*gg + cpcpc*rr + "addw %18, %%ax \n\t" // ax = cpcpc*rr + cpc*gg + bb - "movl 40(%ebp), %ecx \n" + "movl %8, %%ecx \n\t" //agi - "leal (%ecx, %eax, 4), %edx \n" + "leal (%%ecx, %%eax, 4), %%edx \n\t" //agi - "movb (%edx), %cl \n" // cl = pixels[ax] + "movb (%%edx), %%cl \n\t" // cl = pixels[ax] // store the pixel - "movl 12(%ebp), %eax \n" - "movb %cl, (%eax) \n" // *ximage = cl - "incl 12(%ebp) \n" // ximage++ + "movl %1, %%eax \n\t" + "movb %%cl, (%%eax) \n\t" // *ximage = cl + "incl %1 \n\t" // ximage++ // prepare for next iteration on X - "addl $4, -32(%ebp) \n" // nerr += 4 - "addl $4, %ebx \n" // err += 4 + "addl $4, %19 \n\t" // nerr += 4 + "addl $4, %%ebx \n\t" // err += 4 - "addl 56(%ebp), %esi \n" // image->data += bpp + "addl %12, %%esi \n\t" // image->data += bpp - "decl -4(%ebp) \n" // x-- - "jnz .LoopXb \n" // if x>0, goto .LoopX + "decl %14 \n\t" // x-- + "jnz .LoopXb \n\t" // if x>0, goto .LoopX - "movl 60(%ebp), %eax \n" - "addl %eax, 12(%ebp) \n" // add extra offset to ximage + "movl %13, %%eax \n\t" + "addl %%eax, %1 \n\t" // add extra offset to ximage "jmp .LoopYb \n" -".Endb: \n" - - "emms \n" - "popal \n" +".Endb: \n\t" + "emms \n\t" + "popal \n\t" + : + : + "m" (image), // %0 + "m" (ximage), // %1 + "m" (err), // %2 + "m" (nerr), // %3 + "m" (ctable), // %4 + "m" (dr), // %5 + "m" (dg), // %6 + "m" (db), // %7 + "m" (pixels), // %8 + "m" (cpc), // %9 + "m" (width), // %10 + "m" (height), // %11 + "m" (bytesPerPixel), // %12 + "m" (line_offset), // %13 + "m" (x), // %14 + "m" (cpcpc), // %15 + "m" (rr), // %16 + "m" (gg), // %17 + "m" (bb), // %18 + "m" (tmp_err), // %19 + "m" (tmp_nerr), // %20 + "m" (ndr), // %21 + "m" (ndg), // %22 + "m" (ndb) // %23 ); - - } #endif /* ASM_X86 */ +