1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 04:20:27 +01:00

Finished the libWUtil library.

This commit is contained in:
dan
1999-09-10 20:13:44 +00:00
parent d214a2ca98
commit f2f71a1f09
6 changed files with 188 additions and 95 deletions

View File

@@ -3,6 +3,50 @@ changes since wmaker 0.60.0:
- added WMScreenWidth() and WMScreenHeight() functions.
- fixed some problems when compiling with non gcc compilers.
- added libWUtil, a library that is a subset of libWINGs. It contains utils
that can be used in writing non-GUI programs. They include: hashes,
notifications, input/idle/timer handlers, user defaults database handling,
memory handling, application resource handling, etc.
All the non-GUI stuff from libWINGs is present.
Still linWINGs contain all this stuff so if you use libWINGs, you don't
need to link against libWUtil too.
One notable aspect of libWUtil is that it has a modified version of the
event handling function. It is named WHandleEvents() and will handle all
input/idle/timer events the app has.
If your app has a permanent input handler (as for example a socket a server
is listening on), then the main loop of the app can be:
while(1) {
WHandleEvents();
}
but if there is no permanent input handler, you need to add some delay to
avoid a too high cpu load by your program:
while(1) {
WHandleEvents();
wusleep(5000);
}
A permanent input handler is one that is established when the program starts
and is present until the program exits.
One that is deleted and later reinstalled, is not considered permanent.
This difference is because if there is some input handler, the function will
block until some event appears, while if there is no input handler the
function will return almost immediately (after handling the timer/idle
stuff).
Except the stuff declared in WUtil.h, the following functions declared in
WINGs.h are also present in libWUtil (you will need to #include <WINGs.h>
if you use one of these):
WMInitializeApplication(char *applicationName, int *argc, char **argv);
WMSetResourcePath(char *path);
WMGetApplicationName();
WMPathForResourceOfType(char *resource, char *ext);
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata);
WMDeleteTimerWithClientData(void *cdata);
WMDeleteTimerHandler(WMHandlerID handlerID);
WMAddIdleHandler(WMCallback *callback, void *cdata);
WMDeleteIdleHandler(WMHandlerID handlerID);
WMAddInputHandler(int fd, int condition, WMInputProc *proc,
void *clientData);
WMDeleteInputHandler(WMHandlerID handlerID);
changes since wmaker 0.53.0:

View File

@@ -12,7 +12,7 @@ LIBLIST= $(top_builddir)/wrlib/libwraster.la\
#lib_LTLIBRARIES = libWINGs.la
lib_LIBRARIES = libWINGs.a
lib_LIBRARIES = libWINGs.a libWUtil.a
#libWINGs_la_LDFLAGS = -version-info 1:1:0
@@ -101,6 +101,23 @@ libWINGs_a_SOURCES = \
usleep.c
libWUtil_a_SOURCES = \
WINGs.h \
WINGsP.h \
llist.h \
llist.c \
international.c \
notification.c \
userdefaults.c \
wapplication.c \
wutil.c \
error.c \
findfile.c \
hashtable.c \
memory.c \
usleep.c
INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/src \
-DRESOURCE_PATH=\"$(datadir)/WINGs\" @HEADER_SEARCH_PATH@ -DDEBUG

View File

@@ -101,7 +101,7 @@ LIBLIST = $(top_builddir)/wrlib/libwraster.la @LIBRARY_SEARCH_PATH@ @GFXLIBS@
#lib_LTLIBRARIES = libWINGs.la
lib_LIBRARIES = libWINGs.a
lib_LIBRARIES = libWINGs.a libWUtil.a
#libWINGs_la_LDFLAGS = -version-info 1:1:0
@@ -146,6 +146,9 @@ EXTRA_DIST = logo.xpm BUGS
libWINGs_a_SOURCES = WINGs.h WINGsP.h configuration.c llist.h llist.c international.c notification.c selection.c userdefaults.c wapplication.c wappresource.c wballoon.c wbrowser.c wbutton.c wcolor.c wcolorpanel.c wcolorwell.c wevent.c wfilepanel.c wframe.c wfont.c wfontpanel.c widgets.c wlabel.c wlist.c wmisc.c wpanel.c wpixmap.c wpopupbutton.c wscroller.c wscrollview.c wslider.c wsplitview.c wtabview.c wtextfield.c wwindow.c wview.c error.c findfile.c hashtable.c memory.c usleep.c
libWUtil_a_SOURCES = WINGs.h WINGsP.h llist.h llist.c international.c notification.c userdefaults.c wapplication.c wutil.c error.c findfile.c hashtable.c memory.c usleep.c
INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/src -DRESOURCE_PATH=\"$(datadir)/WINGs\" @HEADER_SEARCH_PATH@ -DDEBUG
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -169,6 +172,10 @@ wevent.o wfilepanel.o wframe.o wfont.o wfontpanel.o widgets.o wlabel.o \
wlist.o wmisc.o wpanel.o wpixmap.o wpopupbutton.o wscroller.o \
wscrollview.o wslider.o wsplitview.o wtabview.o wtextfield.o wwindow.o \
wview.o error.o findfile.o hashtable.o memory.o usleep.o
libWUtil_a_LIBADD =
libWUtil_a_OBJECTS = llist.o international.o notification.o \
userdefaults.o wapplication.o wutil.o error.o findfile.o hashtable.o \
memory.o usleep.o
AR = ar
PROGRAMS = $(noinst_PROGRAMS)
@@ -208,8 +215,8 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
SOURCES = $(libWINGs_a_SOURCES) $(wtest_SOURCES) $(wmquery_SOURCES) $(wmfile_SOURCES) $(fontl_SOURCES) $(testmywidget_SOURCES) $(testcolorpanel_SOURCES) $(testnot_SOURCES)
OBJECTS = $(libWINGs_a_OBJECTS) $(wtest_OBJECTS) $(wmquery_OBJECTS) $(wmfile_OBJECTS) $(fontl_OBJECTS) $(testmywidget_OBJECTS) $(testcolorpanel_OBJECTS) $(testnot_OBJECTS)
SOURCES = $(libWINGs_a_SOURCES) $(libWUtil_a_SOURCES) $(wtest_SOURCES) $(wmquery_SOURCES) $(wmfile_SOURCES) $(fontl_SOURCES) $(testmywidget_SOURCES) $(testcolorpanel_SOURCES) $(testnot_SOURCES)
OBJECTS = $(libWINGs_a_OBJECTS) $(libWUtil_a_OBJECTS) $(wtest_OBJECTS) $(wmquery_OBJECTS) $(wmfile_OBJECTS) $(fontl_OBJECTS) $(testmywidget_OBJECTS) $(testcolorpanel_OBJECTS) $(testnot_OBJECTS)
all: all-redirect
.SUFFIXES:
@@ -297,6 +304,11 @@ libWINGs.a: $(libWINGs_a_OBJECTS) $(libWINGs_a_DEPENDENCIES)
$(AR) cru libWINGs.a $(libWINGs_a_OBJECTS) $(libWINGs_a_LIBADD)
$(RANLIB) libWINGs.a
libWUtil.a: $(libWUtil_a_OBJECTS) $(libWUtil_a_DEPENDENCIES)
-rm -f libWUtil.a
$(AR) cru libWUtil.a $(libWUtil_a_OBJECTS) $(libWUtil_a_LIBADD)
$(RANLIB) libWUtil.a
mostlyclean-noinstPROGRAMS:
clean-noinstPROGRAMS:

View File

@@ -477,7 +477,7 @@ typedef struct WMTabViewDelegate {
void WMInitializeApplication(char *applicationName, int *argc, char **argv);
void WMSetApplicationDataPath(char *path);
void WMSetResourcePath(char *path);
/* don't free the returned string */
char *WMGetApplicationName();

View File

@@ -174,6 +174,16 @@ void wusleep(unsigned int microsec);
int wsprintesc(char *buffer, int length, char *format, WMSEscapes **escapes,
int count);
#endif
/*......................................................................*/
/* This function is used _only_ if you create a NON-GUI program.
* For GUI based programs use WMNextEvent()/WMHandleEvent() instead.
* This function will handle all input/timer/idle events, then return.
*/
void WHandleEvents();
/*......................................................................*/

View File

@@ -2,6 +2,7 @@
/*
* This event handling stuff was based on Tk.
* adapted from wevent.c
*/
#include "WINGsP.h"
@@ -16,7 +17,7 @@
#endif
//#include <X11/Xos.h>
#include <X11/Xos.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
@@ -94,11 +95,11 @@ WMHandlerID
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
{
TimerHandler *handler, *tmp;
handler = malloc(sizeof(TimerHandler));
if (!handler)
return NULL;
rightNow(&handler->when);
addmillisecs(&handler->when, milliseconds);
handler->callback = callback;
@@ -153,7 +154,7 @@ WMDeleteTimerHandler(WMHandlerID handlerID)
{
TimerHandler *tmp, *handler=(TimerHandler*)handlerID;
if (!handler || !timerHandler)
if (!handler || !timerHandler)
return;
tmp = timerHandler;
@@ -178,7 +179,7 @@ WMHandlerID
WMAddIdleHandler(WMCallback *callback, void *cdata)
{
IdleHandler *handler, *tmp;
handler = malloc(sizeof(IdleHandler));
if (!handler)
return NULL;
@@ -232,16 +233,16 @@ WMHandlerID
WMAddInputHandler(int fd, int condition, WMInputProc *proc, void *clientData)
{
InputHandler *handler;
handler = wmalloc(sizeof(InputHandler));
handler->fd = fd;
handler->mask = condition;
handler->callback = proc;
handler->clientData = clientData;
handler->next = inputHandler;
inputHandler = handler;
return handler;
@@ -269,7 +270,7 @@ WMDeleteInputHandler(WMHandlerID handlerID)
}
tmp = tmp->next;
}
}
}
}
@@ -284,7 +285,7 @@ checkIdleHandlers()
}
handler = idleHandler;
/* we will process all idleHandlers so, empty the handler list */
idleHandler = NULL;
@@ -293,7 +294,7 @@ checkIdleHandlers()
(*handler->callback)(handler->clientData);
/* remove the handler */
free(handler);
handler = tmp;
}
W_FlushIdleNotificationQueue();
@@ -350,23 +351,46 @@ delayUntilNextTimerEvent(struct timeval *delay)
}
Bool
W_WaitForEvent(Display *dpy, unsigned long xeventmask)
/*
* This functions will handle input events on all registered file descriptors.
* Input:
* - waitForInput - True if we want the function to wait until an event
* appears on a file descriptor we watch, False if we
* want the function to immediately return if there is
* no data available on the file descriptors we watch.
* Output:
* if waitForInput is False, the function will return False if there are no
* input handlers registered, or if there is no data
* available on the registered ones, and will return True
* if there is at least one input handler that has data
* available.
* if waitForInput is True, the function will return False if there are no
* input handlers registered, else it will block until an
* event appears on one of the file descriptors it watches
* and then it will return True.
*
* If the retured value is True, the input handlers for the corresponding file
* descriptors are also called.
*
*/
static Bool
handleInputEvents(Bool waitForInput)
{
#if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT)
struct pollfd *fds;
InputHandler *handler;
int count, timeout, nfds, k, retval;
int count, timeout, nfds, k;
for (nfds = 1, handler = inputHandler;
if (!inputHandler)
return False;
for (nfds = 0, handler = inputHandler;
handler != 0; handler = handler->next) nfds++;
fds = wmalloc(nfds * sizeof(struct pollfd));
fds[0].fd = ConnectionNumber(dpy);
fds[0].events = POLLIN;
for (k = 1, handler = inputHandler;
handler;
fds = wmalloc(nfds * sizeof(struct pollfd));
for (k = 0, handler = inputHandler;
handler;
handler = handler->next, k++) {
fds[k].fd = handler->fd;
fds[k].events = 0;
@@ -383,10 +407,13 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
}
/*
* Setup the select() timeout to the estimated time until the
* next timer expires.
* If we don't wait for input, set timeout to return immediately,
* else setup the timeout to the estimated time until the
* next timer expires or if no timer is pending to infinite.
*/
if (timerPending()) {
if (!waitForInput) {
timeout = 0;
} else if (timerPending()) {
struct timeval tv;
delayUntilNextTimerEvent(&tv);
timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
@@ -394,22 +421,11 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
timeout = -1;
}
if (xeventmask==0) {
if (XPending(dpy))
return True;
} else {
XEvent ev;
if (XCheckMaskEvent(dpy, xeventmask, &ev)) {
XPutBackEvent(dpy, &ev);
return True;
}
}
count = poll(fds, nfds, timeout);
if (count > 0) {
handler = inputHandler;
k = 1;
k = 0;
while (handler) {
int mask;
InputHandler *next;
@@ -418,17 +434,17 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
if (fds[k].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI))
mask |= WIReadMask;
if (fds[k].revents & (POLLOUT | POLLWRBAND))
mask |= WIWriteMask;
if (fds[k].revents & (POLLHUP | POLLNVAL | POLLERR))
mask |= WIExceptMask;
next = handler->next;
if (mask!=0 && handler->callback) {
(*handler->callback)(handler->fd, mask,
(*handler->callback)(handler->fd, mask,
handler->clientData);
}
@@ -437,12 +453,11 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
}
}
retval = fds[0].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI);
free(fds);
W_FlushASAPNotificationQueue();
return retval;
return (count > 0);
#else /* not HAVE_POLL */
#ifdef HAVE_SELECT
struct timeval timeout;
@@ -452,12 +467,14 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
int count;
InputHandler *handler = inputHandler;
if (!inputHandler)
return False;
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_ZERO(&eset);
FD_SET(ConnectionNumber(dpy), &rset);
maxfd = ConnectionNumber(dpy);
maxfd = 0;
while (handler) {
if (handler->mask & WIReadMask)
@@ -475,30 +492,22 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
handler = handler->next;
}
/*
* Setup the select() timeout to the estimated time until the
* next timer expires.
* If we don't wait for input, set timeout to return immediately,
* else setup the timeout to the estimated time until the
* next timer expires or if no timer is pending to infinite.
*/
if (timerPending()) {
if (!waitForInput) {
timeout.tv_sec = 0;
timeout.tv_usec = 0;
timeoutPtr = &timeout;
} else if (timerPending()) {
delayUntilNextTimerEvent(&timeout);
timeoutPtr = &timeout;
} else {
timeoutPtr = (struct timeval*)0;
}
XSync(dpy, False);
if (xeventmask==0) {
if (XPending(dpy))
return True;
} else {
XEvent ev;
if (XCheckMaskEvent(dpy, xeventmask, &ev)) {
XPutBackEvent(dpy, &ev);
return True;
}
}
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
if (count > 0) {
@@ -512,17 +521,17 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
if (FD_ISSET(handler->fd, &rset))
mask |= WIReadMask;
if (FD_ISSET(handler->fd, &wset))
mask |= WIWriteMask;
if (FD_ISSET(handler->fd, &eset))
mask |= WIExceptMask;
next = handler->next;
if (mask!=0 && handler->callback) {
(*handler->callback)(handler->fd, mask,
(*handler->callback)(handler->fd, mask,
handler->clientData);
}
@@ -532,7 +541,7 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
W_FlushASAPNotificationQueue();
return FD_ISSET(ConnectionNumber(dpy), &rset);
return (count > 0);
#else /* not HAVE_SELECT, not HAVE_POLL */
Neither select nor poll. You lose.
#endif /* HAVE_SELECT */
@@ -541,39 +550,40 @@ Neither select nor poll. You lose.
void
WMNextEvent(Display *dpy, XEvent *event)
{
WHandleEvents()
{
/* Check any expired timers */
if (timerPending()) {
checkTimerHandlers();
checkTimerHandlers();
}
while (XPending(dpy) == 0) {
/* Do idle stuff */
/* Do idle and timer stuff while there are no timer or X events */
while (!XPending(dpy) && idlePending()) {
if (idlePending())
checkIdleHandlers();
/* dispatch timer events */
if (timerPending())
checkTimerHandlers();
}
/*
* Make sure that new events did not arrive while we were doing
* timer/idle stuff. Or we might block forever waiting for
* an event that already arrived.
*/
/* wait to something happen */
W_WaitForEvent(dpy, 0);
/* Check any expired timers */
if (timerPending()) {
checkTimerHandlers();
/* We need to make sure that we have some input handler before calling
* checkIdleHandlers() in a while loop, because else the while loop
* can run forever (if some idle handler reinitiates itself).
*/
if (inputHandler) {
/* Do idle and timer stuff while there are no input events */
while (idlePending() && inputHandler && !handleInputEvents(False)) {
if (idlePending())
checkIdleHandlers();
/* dispatch timer events */
if (timerPending())
checkTimerHandlers();
}
} else {
if (idlePending())
checkIdleHandlers();
/* dispatch timer events */
if (timerPending())
checkTimerHandlers();
}
XNextEvent(dpy, event);
handleInputEvents(True);
/* Check any expired timers */
if (timerPending()) {
checkTimerHandlers();
}
}