diff --git a/dlls/x11drv/.cvsignore b/dlls/x11drv/.cvsignore index 1c6078cb8d9..eb19f3afc61 100644 --- a/dlls/x11drv/.cvsignore +++ b/dlls/x11drv/.cvsignore @@ -1,4 +1,3 @@ Makefile -wineclipsrv x11drv.dll.dbg.c x11drv.spec.def diff --git a/dlls/x11drv/Makefile.in b/dlls/x11drv/Makefile.in index 933577f7a80..c2a45d7904a 100644 --- a/dlls/x11drv/Makefile.in +++ b/dlls/x11drv/Makefile.in @@ -1,4 +1,3 @@ -EXTRADEFS = -DBINDIR="\"$(bindir)\"" TOPSRCDIR = @top_srcdir@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ @@ -44,20 +43,8 @@ C_SRCS = \ xrender.c \ xvidmode.c -PROGRAMS = wineclipsrv - @MAKE_DLL_RULES@ all: $(PROGRAMS) -wineclipsrv: wineclipsrv.c - $(CC) $(ALLCFLAGS) -o wineclipsrv $(SRCDIR)/wineclipsrv.c $(EXTRALIBS) $(LDFLAGS) $(LIBS) - -install:: $(PROGRAMS) - $(MKINSTALLDIRS) $(bindir) - $(INSTALL_PROGRAM) wineclipsrv $(bindir)/wineclipsrv - -uninstall:: - $(RM) $(bindir)/wineclipsrv - ### Dependencies: diff --git a/dlls/x11drv/wineclipsrv.c b/dlls/x11drv/wineclipsrv.c deleted file mode 100644 index 9e6e835cadf..00000000000 --- a/dlls/x11drv/wineclipsrv.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* - * Wine Clipboard Server - * - * Copyright 1999 Noel Borthwick - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * USAGE: - * wineclipsrv [selection_mask] [debugClass_mask] [clearAllSelections] - * - * The optional selection-mask argument is a bit mask of the selection - * types to be acquired. Currently two selections are supported: - * 1. PRIMARY (mask value 1) - * 2. CLIPBOARD (mask value 2). - * - * debugClass_mask is a bit mask of all debugging classes for which messages - * are to be output. The standard Wine debug class set FIXME(1), ERR(2), - * WARN(4) and TRACE(8) are supported. - * - * If clearAllSelections == 1 *all* selections are lost whenever a SelectionClear - * event is received. - * - * If no arguments are supplied the server aquires all selections. (mask value 3) - * and defaults to output of only FIXME(1) and ERR(2) messages. The default for - * clearAllSelections is 0. - * - * NOTES: - * - * The Wine Clipboard Server is a standalone XLib application whose - * purpose is to manage the X selection when Wine exits. - * The server itself is started automatically with the appropriate - * selection masks, whenever Wine exits after acquiring the PRIMARY and/or - * CLIPBOARD selection. (See X11DRV_CLIPBOARD_ResetOwner) - * When the server starts, it first proceeds to capture the selection data from - * Wine and then takes over the selection ownership. It does this by querying - * the current selection owner(of the specified selections) for the TARGETS - * selection target. It then proceeds to cache all the formats exposed by - * TARGETS. If the selection does not support the TARGETS target, or if no - * target formats are exposed, the server simply exits. - * Once the cache has been filled, the server then actually acquires ownership - * of the respective selection and begins fielding selection requests. - * Selection requests are serviced from the cache. If a selection is lost the - * server flushes its internal cache, destroying all data previously saved. - * Once ALL selections have been lost the server terminates. - * - * TODO: - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -/* - * Lightweight debug definitions for Wine Clipboard Server. - * The standard FIXME, ERR, WARN & TRACE classes are supported - * without debug channels. - * The standard defines NO_TRACE_MSGS and NO_DEBUG_MSGS will compile out - * TRACE, WARN and ERR and FIXME message displays. - */ - -/* Internal definitions (do not use these directly) */ - -#ifdef __SUNPRO_C -#define __FUNCTION__ __func__ -#endif - -enum __DEBUG_CLASS { __DBCL_FIXME, __DBCL_ERR, __DBCL_WARN, __DBCL_TRACE, __DBCL_COUNT }; - -extern char __debug_msg_enabled[__DBCL_COUNT]; - -extern const char * const debug_cl_name[__DBCL_COUNT]; - -#define DEBUG_CLASS_COUNT __DBCL_COUNT - -#define __GET_DEBUGGING(dbcl) (__debug_msg_enabled[(dbcl)]) -#define __SET_DEBUGGING(dbcl,on) (__debug_msg_enabled[(dbcl)] = (on)) - - -#define __DPRINTF(dbcl) \ - (!__GET_DEBUGGING(dbcl) || \ - (printf("%s:%s:%s ", debug_cl_name[(dbcl)], progname, __FUNCTION__),0)) \ - ? 0 : printf - -#define __DUMMY_DPRINTF 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL) - -/* use configure to allow user to compile out debugging messages */ -#ifndef NO_TRACE_MSGS - #define TRACE __DPRINTF(__DBCL_TRACE) -#else - #define TRACE __DUMMY_DPRINTF -#endif /* NO_TRACE_MSGS */ - -#ifndef NO_DEBUG_MSGS - #define WARN __DPRINTF(__DBCL_WARN) - #define FIXME __DPRINTF(__DBCL_FIXME) -#else - #define WARN __DUMMY_DPRINTF - #define FIXME __DUMMY_DPRINTF -#endif /* NO_DEBUG_MSGS */ - -/* define error macro regardless of what is configured */ -#define ERR __DPRINTF(__DBCL_ERR) - - -#define TRUE 1 -#define FALSE 0 -typedef int BOOL; - -/* Internal definitions for debugging messages(do not use these directly) */ -const char * const debug_cl_name[] = { "fixme", "err", "warn", "trace" }; -char __debug_msg_enabled[DEBUG_CLASS_COUNT] = {1, 1, 0, 0}; - - -/* Selection masks */ - -#define S_NOSELECTION 0 -#define S_PRIMARY 1 -#define S_CLIPBOARD 2 - -/* Debugging class masks */ - -#define C_FIXME 1 -#define C_ERR 2 -#define C_WARN 4 -#define C_TRACE 8 - -/* - * Global variables - */ - -static Display *g_display = NULL; -static int screen_num; -static char *progname; /* name this program was invoked by */ -static Window g_win = 0; /* the hidden clipboard server window */ -static GC g_gc = 0; - -static const char g_szOutOfMemory[] = "Insufficient memory!\n"; - -/* X selection context info */ -static const char _CLIPBOARD[] = "CLIPBOARD"; /* CLIPBOARD atom name */ -static int g_selectionToAcquire = 0; /* Masks for the selection to be acquired */ -static int g_selectionAcquired = 0; /* Contains the current selection masks */ -static int g_clearAllSelections = 0; /* If TRUE *all* selections are lost on SelectionClear */ - -/* Selection cache */ -typedef struct tag_CACHEENTRY -{ - Atom target; - Atom type; - int nFormat; - int nElements; - void *pData; -} CACHEENTRY, *PCACHEENTRY; - -static PCACHEENTRY g_pPrimaryCache = NULL; /* Primary selection cache */ -static PCACHEENTRY g_pClipboardCache = NULL; /* Clipboard selection cache */ -static unsigned long g_cPrimaryTargets = 0; /* Number of TARGETS reported by PRIMARY selection */ -static unsigned long g_cClipboardTargets = 0; /* Number of TARGETS reported by CLIPBOARD selection */ - -/* - * Prototypes - */ - -int RunAsDaemon( void ); -BOOL Init(int argc, char **argv); -void TerminateServer( int ret ); -int AcquireSelection(); -int CacheDataFormats( Atom SelectionSrc, PCACHEENTRY *ppCache ); -void EmptyCache(PCACHEENTRY pCache, int nItems); -BOOL FillCacheEntry( Atom SelectionSrc, Atom target, PCACHEENTRY pCacheEntry ); -BOOL LookupCacheItem( Atom selection, Atom target, PCACHEENTRY *ppCacheEntry ); -void EVENT_ProcessEvent( XEvent *event ); -Atom EVENT_SelectionRequest_MULTIPLE( XSelectionRequestEvent *pevent ); -void EVENT_SelectionRequest( XSelectionRequestEvent *event, BOOL bIsMultiple ); -void EVENT_SelectionClear( XSelectionClearEvent *event ); -void EVENT_PropertyNotify( XPropertyEvent *event ); -Pixmap DuplicatePixmap(Pixmap pixmap); -void TextOut(Window win, GC gc, char *pStr); -void getGC(Window win, GC *gc); - - -int main(int argc, char **argv) -{ - XEvent event; - - if ( RunAsDaemon() == -1 ) - { - ERR("could not run as daemon\n"); - exit(1); - } - - if ( !Init(argc, argv) ) - exit(0); - - /* Acquire the selection after retrieving all clipboard data - * owned by the current selection owner. If we were unable to - * Acquire any selection, terminate right away. - */ - if ( AcquireSelection() == S_NOSELECTION ) - TerminateServer(0); - - TRACE("Clipboard server running...\n"); - - /* Start an X event loop */ - while (1) - { - XNextEvent(g_display, &event); - - EVENT_ProcessEvent( &event ); - } -} - - -/************************************************************************** - * RunAsDaemon() - */ -int RunAsDaemon( void ) -{ - int i; - - /* fork child process and let parent exit ; gets rid of original PID */ - switch( fork() ) - { - case -1: - ERR("fork failed\n"); - return(-1); - case 0: - exit(0); - break; - } - - /* below is child process w/ new PID, set as session leader */ - setsid(); - - /* close stdin,stdout,stderr and file descriptors (overkill method) */ - for ( i = 0; i < 256 ; i++ ) - close(i); - - TRACE("now running as daemon...\n"); - return 0; -} - - -/************************************************************************** - * Init() - * Initialize the clipboard server - */ -BOOL Init(int argc, char **argv) -{ - unsigned int width, height; /* window size */ - unsigned int border_width = 4; /* four pixels */ - unsigned int display_width, display_height; - char *window_name = "Wine Clipboard Server"; - XSizeHints *size_hints = NULL; - XWMHints *wm_hints = NULL; - XClassHint *class_hints = NULL; - XTextProperty windowName; - char *display_name = NULL; - - progname = argv[0]; - - if (!(size_hints = XAllocSizeHints())) - { - ERR(g_szOutOfMemory); - return 0; - } - if (!(wm_hints = XAllocWMHints())) - { - ERR(g_szOutOfMemory); - return 0; - } - if (!(class_hints = XAllocClassHint())) - { - ERR(g_szOutOfMemory); - return 0; - } - - /* connect to X server */ - if ( (g_display=XOpenDisplay(display_name)) == NULL ) - { - ERR( "cannot connect to X server %s\n", XDisplayName(display_name)); - return 0; - } - - /* get screen size from display structure macro */ - screen_num = DefaultScreen(g_display); - display_width = DisplayWidth(g_display, screen_num); - display_height = DisplayHeight(g_display, screen_num); - - /* size window with enough room for text */ - width = display_width/3, height = display_height/4; - - /* create opaque window */ - g_win = XCreateSimpleWindow(g_display, RootWindow(g_display,screen_num), - 0, 0, width, height, border_width, BlackPixel(g_display, - screen_num), WhitePixel(g_display,screen_num)); - - - /* Set size hints for window manager. The window manager may - * override these settings. */ - - /* x, y, width, and height hints are now taken from - * the actual settings of the window when mapped. Note - * that PPosition and PSize must be specified anyway. */ - - size_hints->flags = PPosition | PSize | PMinSize; - size_hints->min_width = 300; - size_hints->min_height = 200; - - /* These calls store window_name into XTextProperty structures - * and sets the other fields properly. */ - if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) - { - ERR( "structure allocation for windowName failed.\n"); - TerminateServer(-1); - } - - wm_hints->initial_state = NormalState; - wm_hints->input = True; - wm_hints->flags = StateHint | InputHint; - - class_hints->res_name = progname; - class_hints->res_class = "WineClipSrv"; - - XSetWMProperties(g_display, g_win, &windowName, NULL, - argv, argc, size_hints, wm_hints, - class_hints); - - /* Select event types wanted */ - XSelectInput(g_display, g_win, ExposureMask | KeyPressMask | - ButtonPressMask | StructureNotifyMask | PropertyChangeMask ); - - /* create GC for text and drawing */ - getGC(g_win, &g_gc); - - /* Display window */ - /* XMapWindow(g_display, g_win); */ - - /* Set the selections to be acquired from the command line argument. - * If none specified, default to all selections we understand. - */ - if (argc > 1) - g_selectionToAcquire = atoi(argv[1]); - else - g_selectionToAcquire = S_PRIMARY | S_CLIPBOARD; - - /* Set the debugging class state from the command line argument */ - if (argc > 2) - { - int dbgClasses = atoi(argv[2]); - - __SET_DEBUGGING(__DBCL_FIXME, dbgClasses & C_FIXME); - __SET_DEBUGGING(__DBCL_ERR, dbgClasses & C_ERR); - __SET_DEBUGGING(__DBCL_WARN, dbgClasses & C_WARN); - __SET_DEBUGGING(__DBCL_TRACE, dbgClasses & C_TRACE); - } - - /* Set the "ClearSelections" state from the command line argument */ - if (argc > 3) - g_clearAllSelections = atoi(argv[3]); - - return TRUE; -} - - -/************************************************************************** - * TerminateServer() - */ -void TerminateServer( int ret ) -{ - TRACE("Terminating Wine clipboard server...\n"); - - /* Free Primary and Clipboard selection caches */ - EmptyCache(g_pPrimaryCache, g_cPrimaryTargets); - EmptyCache(g_pClipboardCache, g_cClipboardTargets); - - if (g_gc) - XFreeGC(g_display, g_gc); - - if (g_display) - XCloseDisplay(g_display); - - exit(ret); -} - - -/************************************************************************** - * AcquireSelection() - * - * Acquire the selection after retrieving all clipboard data owned by - * the current selection owner. - */ -int AcquireSelection() -{ - Atom xaClipboard = XInternAtom(g_display, _CLIPBOARD, False); - - /* - * For all selections we need to acquire, get a list of all targets - * supplied by the current selection owner. - */ - if (g_selectionToAcquire & S_PRIMARY) - { - TRACE("Acquiring PRIMARY selection...\n"); - g_cPrimaryTargets = CacheDataFormats( XA_PRIMARY, &g_pPrimaryCache ); - TRACE("Cached %ld formats...\n", g_cPrimaryTargets); - } - if (g_selectionToAcquire & S_CLIPBOARD) - { - TRACE("Acquiring CLIPBOARD selection...\n"); - g_cClipboardTargets = CacheDataFormats( xaClipboard, &g_pClipboardCache ); - TRACE("Cached %ld formats...\n", g_cClipboardTargets); - } - - /* - * Now that we have cached the data, we proceed to acquire the selections - */ - if (g_cPrimaryTargets) - { - /* Acquire the PRIMARY selection */ - while (XGetSelectionOwner(g_display,XA_PRIMARY) != g_win) - XSetSelectionOwner(g_display, XA_PRIMARY, g_win, CurrentTime); - - g_selectionAcquired |= S_PRIMARY; - } - else - TRACE("No PRIMARY targets - ownership not acquired.\n"); - - if (g_cClipboardTargets) - { - /* Acquire the CLIPBOARD selection */ - while (XGetSelectionOwner(g_display,xaClipboard) != g_win) - XSetSelectionOwner(g_display, xaClipboard, g_win, CurrentTime); - - g_selectionAcquired |= S_CLIPBOARD; - } - else - TRACE("No CLIPBOARD targets - ownership not acquired.\n"); - - return g_selectionAcquired; -} - -BOOL GetSelectionEvent(Atom SelectionSrc, XEvent *xe) -{ - time_t end_time; - - /* Set up a 10 second time out */ - end_time=time(NULL)+10; - - do - { - struct timeval nap; - - if (XCheckTypedWindowEvent(g_display, g_win, SelectionNotify, xe)) - { - if( xe->xselection.selection == SelectionSrc ) - return TRUE; - } - - if (time(NULL)>end_time) - break; - - /* Sleep a bit to make this busy wait less brutal */ - nap.tv_sec = 0; - nap.tv_usec = 10; - select(0, NULL, NULL, NULL, &nap); - } - while (TRUE); - - return FALSE; -} - -/************************************************************************** - * CacheDataFormats - * - * Allocates and caches the list of data formats available from the current selection. - * This queries the selection owner for the TARGETS property and saves all - * reported property types. - */ -int CacheDataFormats( Atom SelectionSrc, PCACHEENTRY *ppCache ) -{ - XEvent xe; - Atom aTargets; - Atom atype=AnyPropertyType; - int aformat; - unsigned long remain; - unsigned long cSelectionTargets = 0; - Atom* targetList=NULL; - Window ownerSelection = 0; - - if (!ppCache) - return 0; - *ppCache = NULL; - - /* Get the selection owner */ - ownerSelection = XGetSelectionOwner(g_display, SelectionSrc); - if ( ownerSelection == None ) - return cSelectionTargets; - - /* - * Query the selection owner for the TARGETS property - */ - aTargets = XInternAtom(g_display, "TARGETS", False); - - TRACE("Requesting TARGETS selection for '%s' (owner=%08x)...\n", - XGetAtomName(g_display, SelectionSrc), (unsigned)ownerSelection ); - - XConvertSelection(g_display, SelectionSrc, aTargets, - XInternAtom(g_display, "SELECTION_DATA", False), - g_win, CurrentTime); - - /* - * Wait until SelectionNotify is received - */ - if (!GetSelectionEvent(SelectionSrc, &xe)) - return 0; - - /* Verify that the selection returned a valid TARGETS property */ - if ( (xe.xselection.target != aTargets) - || (xe.xselection.property == None) ) - { - TRACE("\tCould not retrieve TARGETS\n"); - return cSelectionTargets; - } - - /* Read the TARGETS property contents */ - if(XGetWindowProperty(g_display, xe.xselection.requestor, xe.xselection.property, - 0, 0x3FFF, True, AnyPropertyType/*XA_ATOM*/, &atype, &aformat, - &cSelectionTargets, &remain, (unsigned char**)&targetList) != Success) - TRACE("\tCouldn't read TARGETS property\n"); - else - { - TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n", - XGetAtomName(g_display,atype),aformat,cSelectionTargets, remain); - /* - * The TARGETS property should have returned us a list of atoms - * corresponding to each selection target format supported. - */ - if( (atype == XA_ATOM || atype == aTargets) && aformat == 32 ) - { - int i; - - /* Allocate the selection cache */ - *ppCache = (PCACHEENTRY)calloc(cSelectionTargets, sizeof(CACHEENTRY)); - - /* Cache these formats in the selection cache */ - for (i = 0; i < cSelectionTargets; i++) - { - char *itemFmtName = XGetAtomName(g_display, targetList[i]); - - TRACE("\tAtom# %d: '%s'\n", i, itemFmtName); - - /* Populate the cache entry */ - if (!FillCacheEntry( SelectionSrc, targetList[i], &((*ppCache)[i]))) - ERR("Failed to fill cache entry!\n"); - - XFree(itemFmtName); - } - } - - /* Free the list of targets */ - XFree(targetList); - } - - return cSelectionTargets; -} - -/*********************************************************************** - * FillCacheEntry - * - * Populates the specified cache entry - */ -BOOL FillCacheEntry( Atom SelectionSrc, Atom target, PCACHEENTRY pCacheEntry ) -{ - XEvent xe; - Window w; - Atom prop, reqType; - Atom atype=AnyPropertyType; - int aformat; - unsigned long nitems,remain,itemSize; - long lRequestLength; - unsigned char* val=NULL; - BOOL bRet = FALSE; - - TRACE("Requesting %s selection from %s...\n", - XGetAtomName(g_display, target), - XGetAtomName(g_display, SelectionSrc) ); - - /* Ask the selection owner to convert the selection to the target format */ - XConvertSelection(g_display, SelectionSrc, target, - XInternAtom(g_display, "SELECTION_DATA", False), - g_win, CurrentTime); - - /* wait until SelectionNotify is received */ - if (!GetSelectionEvent(SelectionSrc,&xe)) - return bRet; - - /* Now proceed to retrieve the actual converted property from - * the SELECTION_DATA atom */ - - w = xe.xselection.requestor; - prop = xe.xselection.property; - reqType = xe.xselection.target; - - if(prop == None) - { - TRACE("\tOwner failed to convert selection!\n"); - return bRet; - } - - TRACE("\tretrieving property %s from window %ld into %s\n", - XGetAtomName(g_display,reqType), (long)w, XGetAtomName(g_display,prop) ); - - /* - * First request a zero length in order to figure out the request size. - */ - if(XGetWindowProperty(g_display,w,prop,0,0,False, AnyPropertyType/*reqType*/, - &atype, &aformat, &nitems, &itemSize, &val) != Success) - { - WARN("\tcouldn't get property size\n"); - return bRet; - } - - /* Free zero length return data if any */ - if ( val ) - { - XFree(val); - val = NULL; - } - - TRACE("\tretrieving %ld bytes...\n", itemSize * aformat/8); - lRequestLength = (itemSize * aformat/8)/4 + 1; - - /* - * Retrieve the actual property in the required X format. - */ - if(XGetWindowProperty(g_display,w,prop,0,lRequestLength,False,AnyPropertyType/*reqType*/, - &atype, &aformat, &nitems, &remain, &val) != Success) - { - WARN("\tcouldn't read property\n"); - return bRet; - } - - TRACE("\tType %s,Format %d,nitems %ld,remain %ld,value %s\n", - atype ? XGetAtomName(g_display,atype) : NULL, aformat,nitems,remain,val); - - if (remain) - { - WARN("\tCouldn't read entire property- selection may be too large! Remain=%ld\n", remain); - goto END; - } - - /* - * Populate the cache entry - */ - pCacheEntry->target = target; - pCacheEntry->type = atype; - pCacheEntry->nFormat = aformat; - pCacheEntry->nElements = nitems; - - if (atype == XA_PIXMAP) - { - Pixmap *pPixmap = (Pixmap *)val; - Pixmap newPixmap = DuplicatePixmap( *pPixmap ); - pPixmap = (Pixmap*)calloc(1, sizeof(Pixmap)); - *pPixmap = newPixmap; - pCacheEntry->pData = pPixmap; - } - else - pCacheEntry->pData = val; - -END: - /* Delete the property on the window now that we are done - * This will send a PropertyNotify event to the selection owner. */ - XDeleteProperty(g_display,w,prop); - - return TRUE; -} - - -/*********************************************************************** - * LookupCacheItem - * - * Lookup a target atom in the cache and get the matching cache entry - */ -BOOL LookupCacheItem( Atom selection, Atom target, PCACHEENTRY *ppCacheEntry ) -{ - int i; - int nCachetargets = 0; - PCACHEENTRY pCache = NULL; - Atom xaClipboard = XInternAtom(g_display, _CLIPBOARD, False); - - /* Locate the cache to be used based on the selection type */ - if ( selection == XA_PRIMARY ) - { - pCache = g_pPrimaryCache; - nCachetargets = g_cPrimaryTargets; - } - else if ( selection == xaClipboard ) - { - pCache = g_pClipboardCache; - nCachetargets = g_cClipboardTargets; - } - - if (!pCache || !ppCacheEntry) - return FALSE; - - *ppCacheEntry = NULL; - - /* Look for the target item in the cache */ - for (i = 0; i < nCachetargets; i++) - { - if (pCache[i].target == target) - { - *ppCacheEntry = &pCache[i]; - return TRUE; - } - } - - return FALSE; -} - - -/*********************************************************************** - * EmptyCache - * - * Empties the specified cache - */ -void EmptyCache(PCACHEENTRY pCache, int nItems) -{ - int i; - - if (!pCache) - return; - - /* Release all items in the cache */ - for (i = 0; i < nItems; i++) - { - if (pCache[i].target && pCache[i].pData) - { - /* If we have a Pixmap, free it first */ - if (pCache[i].target == XA_PIXMAP || pCache[i].target == XA_BITMAP) - { - Pixmap *pPixmap = (Pixmap *)pCache[i].pData; - - TRACE("Freeing %s (handle=%ld)...\n", - XGetAtomName(g_display, pCache[i].target), *pPixmap); - - XFreePixmap(g_display, *pPixmap); - - /* Free the cached data item (allocated by us) */ - free(pCache[i].pData); - } - else - { - TRACE("Freeing %s (%p)...\n", - XGetAtomName(g_display, pCache[i].target), pCache[i].pData); - - /* Free the cached data item (allocated by X) */ - XFree(pCache[i].pData); - } - } - } - - /* Destroy the cache */ - free(pCache); -} - - -/*********************************************************************** - * EVENT_ProcessEvent - * - * Process an X event. - */ -void EVENT_ProcessEvent( XEvent *event ) -{ - /* - static const char * const event_names[] = - { - "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", - "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", - "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", - "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", - "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", - "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", - "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", - "ClientMessage", "MappingNotify" - }; - - TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window ); - */ - - switch (event->type) - { - case Expose: - /* don't draw the window */ - if (event->xexpose.count != 0) - break; - - /* Output something */ - TextOut(g_win, g_gc, "Click here to terminate"); - break; - - case ConfigureNotify: - break; - - case ButtonPress: - /* fall into KeyPress (no break) */ - case KeyPress: - TerminateServer(1); - break; - - case SelectionRequest: - EVENT_SelectionRequest( (XSelectionRequestEvent *)event, FALSE ); - break; - - case SelectionClear: - EVENT_SelectionClear( (XSelectionClearEvent*)event ); - break; - - case PropertyNotify: -#if 0 - EVENT_PropertyNotify( (XPropertyEvent *)event ); -#endif - break; - - default: /* ignore all other events */ - break; - - } /* end switch */ - -} - - -/*********************************************************************** - * EVENT_SelectionRequest_MULTIPLE - * Service a MULTIPLE selection request event - * rprop contains a list of (target,property) atom pairs. - * The first atom names a target and the second names a property. - * The effect is as if we have received a sequence of SelectionRequest events - * (one for each atom pair) except that: - * 1. We reply with a SelectionNotify only when all the requested conversions - * have been performed. - * 2. If we fail to convert the target named by an atom in the MULTIPLE property, - * we replace the atom in the property by None. - */ -Atom EVENT_SelectionRequest_MULTIPLE( XSelectionRequestEvent *pevent ) -{ - Atom rprop; - Atom atype=AnyPropertyType; - int aformat; - unsigned long remain; - Atom* targetPropList=NULL; - unsigned long cTargetPropList = 0; -/* Atom xAtomPair = XInternAtom(g_display, "ATOM_PAIR", False); */ - - /* If the specified property is None the requestor is an obsolete client. - * We support these by using the specified target atom as the reply property. - */ - rprop = pevent->property; - if( rprop == None ) - rprop = pevent->target; - if (!rprop) - goto END; - - /* Read the MULTIPLE property contents. This should contain a list of - * (target,property) atom pairs. - */ - if(XGetWindowProperty(g_display, pevent->requestor, rprop, - 0, 0x3FFF, False, AnyPropertyType, &atype, &aformat, - &cTargetPropList, &remain, (unsigned char**)&targetPropList) != Success) - TRACE("\tCouldn't read MULTIPLE property\n"); - else - { - TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n", - XGetAtomName(g_display,atype),aformat,cTargetPropList,remain); - - /* - * Make sure we got what we expect. - * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent - * in a MULTIPLE selection request should be of type ATOM_PAIR. - * However some X apps(such as XPaint) are not compliant with this and return - * a user defined atom in atype when XGetWindowProperty is called. - * The data *is* an atom pair but is not denoted as such. - */ - if(aformat == 32 /* atype == xAtomPair */ ) - { - int i; - - /* Iterate through the ATOM_PAIR list and execute a SelectionRequest - * for each (target,property) pair */ - - for (i = 0; i < cTargetPropList; i+=2) - { - char *targetName = XGetAtomName(g_display, targetPropList[i]); - char *propName = XGetAtomName(g_display, targetPropList[i+1]); - XSelectionRequestEvent event; - - TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n", i/2, targetName, propName); - XFree(targetName); - XFree(propName); - - /* We must have a non "None" property to service a MULTIPLE target atom */ - if ( !targetPropList[i+1] ) - { - TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i); - continue; - } - - /* Set up an XSelectionRequestEvent for this (target,property) pair */ - memcpy( &event, pevent, sizeof(XSelectionRequestEvent) ); - event.target = targetPropList[i]; - event.property = targetPropList[i+1]; - - /* Fire a SelectionRequest, informing the handler that we are processing - * a MULTIPLE selection request event. - */ - EVENT_SelectionRequest( &event, TRUE ); - } - } - - /* Free the list of targets/properties */ - XFree(targetPropList); - } - -END: - return rprop; -} - - -/*********************************************************************** - * EVENT_SelectionRequest - * Process an event selection request event. - * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called - * recursively while servicing a "MULTIPLE" selection target. - * - */ -void EVENT_SelectionRequest( XSelectionRequestEvent *event, BOOL bIsMultiple ) -{ - XSelectionEvent result; - Atom rprop = None; - Window request = event->requestor; - Atom xaMultiple = XInternAtom(g_display, "MULTIPLE", False); - PCACHEENTRY pCacheEntry = NULL; - void *pData = NULL; - Pixmap pixmap; - - /* If the specified property is None the requestor is an obsolete client. - * We support these by using the specified target atom as the reply property. - */ - rprop = event->property; - if( rprop == None ) - rprop = event->target; - - TRACE("Request for %s in selection %s\n", - XGetAtomName(g_display, event->target), XGetAtomName(g_display, event->selection)); - - /* Handle MULTIPLE requests - rprop contains a list of (target, property) atom pairs */ - if(event->target == xaMultiple) - { - /* MULTIPLE selection request - will call us back recursively */ - rprop = EVENT_SelectionRequest_MULTIPLE( event ); - goto END; - } - - /* Lookup the requested target property in the cache */ - if ( !LookupCacheItem(event->selection, event->target, &pCacheEntry) ) - { - TRACE("Item not available in cache!\n"); - goto END; - } - - /* Update the X property */ - TRACE("\tUpdating property %s...\n", XGetAtomName(g_display, rprop)); - - /* If we have a request for a pixmap, return a duplicate */ - - if(event->target == XA_PIXMAP || event->target == XA_BITMAP) - { - Pixmap *pPixmap = (Pixmap *)pCacheEntry->pData; - pixmap = DuplicatePixmap( *pPixmap ); - pData = &pixmap; - } - else - pData = pCacheEntry->pData; - - XChangeProperty(g_display, request, rprop, - pCacheEntry->type, pCacheEntry->nFormat, PropModeReplace, - (unsigned char *)pData, pCacheEntry->nElements); - -END: - if( rprop == None) - TRACE("\tRequest ignored\n"); - - /* reply to sender - * SelectionNotify should be sent only at the end of a MULTIPLE request - */ - if ( !bIsMultiple ) - { - result.type = SelectionNotify; - result.display = g_display; - result.requestor = request; - result.selection = event->selection; - result.property = rprop; - result.target = event->target; - result.time = event->time; - TRACE("Sending SelectionNotify event...\n"); - XSendEvent(g_display,event->requestor,False,NoEventMask,(XEvent*)&result); - } -} - - -/*********************************************************************** - * EVENT_SelectionClear - * We receive this event when another client grabs the X selection. - * If we lost both PRIMARY and CLIPBOARD we must terminate. - */ -void EVENT_SelectionClear( XSelectionClearEvent *event ) -{ - Atom xaClipboard = XInternAtom(g_display, _CLIPBOARD, False); - - TRACE("()\n"); - - /* If we're losing the CLIPBOARD selection, or if the preferences in .winerc - * dictate that *all* selections should be cleared on loss of a selection, - * we must give up all the selections we own. - */ - if ( g_clearAllSelections || (event->selection == xaClipboard) ) - { - TRACE("Lost CLIPBOARD (+PRIMARY) selection\n"); - - /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */ - if ( (event->selection == xaClipboard) - && (g_selectionAcquired & S_PRIMARY) ) - { - XSetSelectionOwner(g_display, XA_PRIMARY, None, CurrentTime); - } - - /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */ - if ( (event->selection == XA_PRIMARY) - && (g_selectionAcquired & S_CLIPBOARD) ) - { - XSetSelectionOwner(g_display, xaClipboard, None, CurrentTime); - } - - g_selectionAcquired = S_NOSELECTION; /* Clear the selection masks */ - } - else if (event->selection == XA_PRIMARY) - { - TRACE("Lost PRIMARY selection...\n"); - g_selectionAcquired &= ~S_PRIMARY; /* Clear the PRIMARY flag */ - } - - /* Once we lose all our selections we have nothing more to do */ - if (g_selectionAcquired == S_NOSELECTION) - TerminateServer(1); -} - -/*********************************************************************** - * EVENT_PropertyNotify - * We use this to release resources like Pixmaps when a selection - * client no longer needs them. - */ -void EVENT_PropertyNotify( XPropertyEvent *event ) -{ - TRACE("()\n"); - - /* Check if we have any resources to free */ - - switch(event->state) - { - case PropertyDelete: - { - TRACE("\tPropertyDelete for atom %s on window %ld\n", - XGetAtomName(event->display, event->atom), (long)event->window); - - /* FreeResources( event->atom ); */ - break; - } - - case PropertyNewValue: - { - TRACE("\tPropertyNewValue for atom %s on window %ld\n\n", - XGetAtomName(event->display, event->atom), (long)event->window); - break; - } - - default: - break; - } -} - -/*********************************************************************** - * DuplicatePixmap - */ -Pixmap DuplicatePixmap(Pixmap pixmap) -{ - Pixmap newPixmap; - XImage *xi; - Window root; - int x,y; /* Unused */ - unsigned border_width; /* Unused */ - unsigned int depth, width, height; - - TRACE("\t() Pixmap=%ld\n", (long)pixmap); - - /* Get the Pixmap dimensions and bit depth */ - if ( 0 == XGetGeometry(g_display, pixmap, &root, &x, &y, &width, &height, - &border_width, &depth) ) - return 0; - - TRACE("\tPixmap properties: width=%d, height=%d, depth=%d\n", - width, height, depth); - - newPixmap = XCreatePixmap(g_display, g_win, width, height, depth); - - xi = XGetImage(g_display, pixmap, 0, 0, width, height, AllPlanes, XYPixmap); - - XPutImage(g_display, newPixmap, g_gc, xi, 0, 0, 0, 0, width, height); - - XDestroyImage(xi); - - TRACE("\t() New Pixmap=%ld\n", (long)newPixmap); - return newPixmap; -} - -/*********************************************************************** - * getGC - * Get a GC to use for drawing - */ -void getGC(Window win, GC *gc) -{ - unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */ - XGCValues values; - unsigned int line_width = 6; - int line_style = LineOnOffDash; - int cap_style = CapRound; - int join_style = JoinRound; - int dash_offset = 0; - static char dash_list[] = {12, 24}; - int list_length = 2; - - /* Create default Graphics Context */ - *gc = XCreateGC(g_display, win, valuemask, &values); - - /* specify black foreground since default window background is - * white and default foreground is undefined. */ - XSetForeground(g_display, *gc, BlackPixel(g_display,screen_num)); - - /* set line attributes */ - XSetLineAttributes(g_display, *gc, line_width, line_style, - cap_style, join_style); - - /* set dashes */ - XSetDashes(g_display, *gc, dash_offset, dash_list, list_length); -} - - -/*********************************************************************** - * TextOut - */ -void TextOut(Window win, GC gc, char *pStr) -{ - int y_offset, x_offset; - - y_offset = 10; - x_offset = 2; - - /* output text, centered on each line */ - XDrawString(g_display, win, gc, x_offset, y_offset, pStr, - strlen(pStr)); -} diff --git a/documentation/PACKAGING b/documentation/PACKAGING index ba4d4f4ecba..a1eb1ef6104 100644 --- a/documentation/PACKAGING +++ b/documentation/PACKAGING @@ -178,8 +178,6 @@ WINE COMPONENTS - winebuild : Winebuild is a tool used for building Winelib applications (and by Wine itself) to allow a developer to compile a .spec file into a .spec.c file. - - wineclipserv : The Wine Clipboard Server is a standalone XLib application - whose purpose is to manage the X selection when Wine exits. - wineconsole : Render the output of CUI programs. - winedbg : A application making use of the debugging API to allow debugging of Wine or Winelib applications as well as Wine itself @@ -462,9 +460,6 @@ Example (split this into %build and %install section for rpm: install -d $BR/usr/X11R6/lib/wine mv $BR/usr/X11R6/lib/lib* $BR/usr/X11R6/lib/wine/ - # the clipboard server is started on demand. - install -m 755 dlls/x11drv/wineclipsrv $BR/usr/X11R6/bin/ - # The Wine server is needed. install -m 755 server/wineserver $BR/usr/X11R6/bin/ @@ -477,9 +472,9 @@ separate library directory should be used. You will need to package the files: - $prefix/bin/wine, $prefix/bin/dosmod, $prefix/lib/wine/* + $prefix/bin/wine, $prefix/lib/wine/* $prefix/man/man1/wine.1, $prefix/include/wine/*, - $prefix/bin/wineserver, $prefix/bin/wineclipsrv + $prefix/bin/wineserver %config /etc/wine/* %doc ... choose from the toplevel directory and documentation/ diff --git a/documentation/samples/config b/documentation/samples/config index 827e72aac3a..70b8cbac9ea 100644 --- a/documentation/samples/config +++ b/documentation/samples/config @@ -159,7 +159,6 @@ WINE REGISTRY Version 2 [Clipboard] "ClearAllSelections" = "0" -"PersistentSelection" = "1" "UsePrimary" = "0" ; List of all directories directly contain .AFM files diff --git a/documentation/wine.man.in b/documentation/wine.man.in index ef6d08245f4..e5c2240db5f 100644 --- a/documentation/wine.man.in +++ b/documentation/wine.man.in @@ -233,11 +233,6 @@ The .B wine debugger .TP -.I @bindir@/wineclipsrv -The -.B wine -clipboard server -.TP .I @dlldir@ Directory containing .B wine's