Beispiel #1
0
Datei: hint.c Projekt: Miteam/jwm
/** Determine the title to display for a client. */
void ReadWMName(ClientNode *np)
{

   unsigned long count;
   int status;
   unsigned long extra;
   Atom realType;
   int realFormat;
   unsigned char *name;

   if(np->name) {
      Release(np->name);
   }

   status = JXGetWindowProperty(display, np->window,
                                atoms[ATOM_NET_WM_NAME], 0, 1024, False,
                                atoms[ATOM_UTF8_STRING], &realType,
                                &realFormat, &count, &extra, &name);
   if(status != Success || realFormat == 0) {
      np->name = NULL;
   } else {
      const size_t size = strlen((char*)name) + 1;
      np->name = Allocate(size);
      memcpy(np->name, name, size);
      JXFree(name);
      np->name = ConvertFromUTF8(np->name);
   }

#ifdef USE_XUTF8
   if(!np->name) {
      status = JXGetWindowProperty(display, np->window,
                                   XA_WM_NAME, 0, 1024, False,
                                   atoms[ATOM_COMPOUND_TEXT],
                                   &realType, &realFormat, &count,
                                   &extra, &name);
      if(status == Success && realFormat == 8) {
         char **tlist;
         XTextProperty tprop;
         int tcount;
         tprop.value = name;
         tprop.encoding = atoms[ATOM_COMPOUND_TEXT];
         tprop.format = realFormat;
         tprop.nitems = strlen((char*)name);
         if(XmbTextPropertyToTextList(display, &tprop, &tlist, &tcount)
            == Success && tcount > 0) {
            const size_t len = strlen(tlist[0]) + 1;
            np->name = Allocate(len);
            memcpy(np->name, tlist[0], len);
            XFreeStringList(tlist);
         }
         JXFree(name);
      }
   }
#endif

   if(!np->name) {
      char *temp = NULL;
      if(JXFetchName(display, np->window, &temp)) {
         const size_t len = strlen(temp) + 1;
         np->name = Allocate(len);
         memcpy(np->name, temp, len);
         JXFree(temp);
      }
   }

}
Beispiel #2
0
std::string XWindowManager::GetStringProperty(Window window_id, Atom atom) const
{
  Atom type;
  int result, format;
  unsigned long n_items, bytes_after;
  char *val = nullptr;

  result = XGetWindowProperty(screen->dpy(), window_id, atom, 0L, 65536, False,
                              AnyPropertyType, &type, &format, &n_items,
                              &bytes_after, reinterpret_cast<unsigned char **>(&val));

  if (result != Success)
  {
    LOG_DEBUG(logger) << "Impossible to get the property " << gdk_x11_get_xatom_name(atom)
                      << " for window " << window_id;
    return std::string();
  }

  if (!val || n_items == 0)
  {
    LOG_DEBUG(logger) << "Impossible to get the property " << gdk_x11_get_xatom_name(atom)
                      << " for window " << window_id << ": empty value";
    return std::string();
  }

  std::unique_ptr<char[], int(*)(void*)> string(val, XFree);

  if (format != 8)
  {
    LOG_ERROR(logger) << "Impossible to get the property " << gdk_x11_get_xatom_name(atom)
                      << " for window " << window_id << ": invalid format " << format;
    return std::string();
  }

  if (type != XA_STRING && type != atom::XA_COMPOUND_TEXT && type != Atoms::utf8String)
  {
    LOG_ERROR(logger) << "Impossible to get the property " << gdk_x11_get_xatom_name(atom)
                      << " for window " << window_id << ": invalid string type: "
                      << gdk_x11_get_xatom_name(type);
    return std::string();
  }

  if (type == atom::XA_COMPOUND_TEXT || (type == XA_STRING && !g_utf8_validate(val, n_items, nullptr)))
  {
    // In case we have compound text, we need to convert it to utf-8
    XTextProperty text_property;
    text_property.value = reinterpret_cast<unsigned char*>(val);
    text_property.encoding = type;
    text_property.format = format;
    text_property.nitems = n_items;

    char **list = nullptr;
    int count = 0;
    result = XmbTextPropertyToTextList(screen->dpy(), &text_property, &list, &count);

    if (result != Success || count == 0)
    {
      LOG_WARN(logger) << "Impossible to get the property " << gdk_x11_get_xatom_name(atom)
                       << "for window " << window_id << " properly: impossible to convert to current locale";
      return std::string(val, n_items);
    }

    std::unique_ptr<char*[], void(*)(char**)> list_ptr(list, XFreeStringList);

    if (count != 1)
    {
      LOG_WARN(logger) << "Impossible to get the property " << gdk_x11_get_xatom_name(atom)
                       << "for window " << window_id << " properly: invalid number of parsed values";
    }

    return list_ptr[0];
  }

  return std::string(val, n_items);
}
/*ARGSUSED*/
static void 
InsertClipboard(Widget w, XtPointer client_data, Atom *selection, 
		Atom *type, XtPointer value, unsigned long *length, 
		int *format)
{
    Display *d = XtDisplay(w);
    Atom target = (Atom)client_data;
    Boolean convert_failed = (*type == XT_CONVERT_FAIL);

    if (!convert_failed)
    {
	char **list;
	int i, ret, count;

	XTextProperty prop;
	prop.value = value;
	prop.nitems = *length;
	prop.format = *format;
	prop.encoding = *type;
	ret = XmbTextPropertyToTextList(d, &prop, &list, &count);
	if (ret >= Success)
	{
	    /* manuals say something about multiple strings in a disjoint
	    text selection (?), it should be harmless to get them all */
	    for (i = 0; i < count; i++)
		NewCurrentClipContents(list[i], strlen(list[i]));
	    XFreeStringList(list);
	} else
	    convert_failed = True;
	XFree(value);
    }

    if (convert_failed) {
	/* if UTF8_STRING failed try COMPOUND_TEXT */
	if (target == XA_UTF8_STRING(d))
	{
	    XtGetSelectionValue(w, *selection, XA_COMPOUND_TEXT(d),
				InsertClipboard,
				(XtPointer)(XA_COMPOUND_TEXT(d)),
				CurrentTime);
	    return;
	}
	/* if COMPOUND_TEXT failed try STRING */
	else if (target == XA_COMPOUND_TEXT(d))
	{
	    XtGetSelectionValue(w, *selection, XA_STRING,
				InsertClipboard,
				NULL,
				CurrentTime);
	    return;
	}
	/* all conversions failed */
	else
	{
	    Arg arg;
	    XtSetArg (arg, XtNlabel, "CLIPBOARD selection conversion failed");
	    XtSetValues (failDialog, &arg, 1);
	    CenterWidgetOnWidget (failDialogShell, text);
	    XtPopup (failDialogShell, XtGrabNone);
#ifdef XKB
	    XkbStdBell (d, XtWindow(w), 0, XkbBI_MinorError);
#else
	    XBell (d, 0);
#endif
	}
    }
    
    XtOwnSelection(top, ClipboardAtom, CurrentTime,
		   ConvertSelection, LoseSelection, NULL);
}
int
winClipboardFlushXEvents (HWND hwnd,
			  int iWindow,
			  Display *pDisplay,
			  Bool fUseUnicode)
{
  static Atom atomLocalProperty;
  static Atom atomCompoundText;
  static Atom atomUTF8String;
  static Atom atomTargets;
  static int generation;

  if (generation != serverGeneration)
    {
      generation = serverGeneration;
      atomLocalProperty = XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False);
      atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
      atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
      atomTargets = XInternAtom (pDisplay, "TARGETS", False);
    }

  /* Process all pending events */
  while (XPending (pDisplay))
    {
      XTextProperty		xtpText = {0};
      XEvent			event;
      XSelectionEvent		eventSelection;
      unsigned long		ulReturnBytesLeft;
      char			*pszReturnData = NULL;
      char			*pszGlobalData = NULL;
      int			iReturn;
      HGLOBAL			hGlobal = NULL;
      XICCEncodingStyle		xiccesStyle;
      int			iConvertDataLen = 0;
      char			*pszConvertData = NULL;
      char			*pszTextList[2] = {NULL};
      int			iCount;
      char			**ppszTextList = NULL;
      wchar_t			*pwszUnicodeStr = NULL;
      int			iUnicodeLen = 0;
      int			iReturnDataLen = 0;
      int			i;
      Bool			fAbort = FALSE;
      Bool			fCloseClipboard = FALSE;
      Bool			fSetClipboardData = TRUE;

      /* Get the next event - will not block because one is ready */
      XNextEvent (pDisplay, &event);

      /* Branch on the event type */
      switch (event.type)
	{
	  /*
	   * SelectionRequest
	   */

	case SelectionRequest:
	  {
	    char			*pszAtomName = NULL;
	    winDebug("SelectionRequest - target %d\n",
                     event.xselectionrequest.target);

	    pszAtomName = XGetAtomName (pDisplay,
					event.xselectionrequest.target);
	    winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
	    XFree (pszAtomName);
	    pszAtomName = NULL;
	  }

	  /* Abort if invalid target type */
	  if (event.xselectionrequest.target != XA_STRING
	      && event.xselectionrequest.target != atomUTF8String
	      && event.xselectionrequest.target != atomCompoundText
	      && event.xselectionrequest.target != atomTargets)
	    {
	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Handle targets type of request */
	  if (event.xselectionrequest.target == atomTargets)
	    {
	      Atom atomTargetArr[] = {atomTargets,
				      atomCompoundText,
				      atomUTF8String,
				      XA_STRING};

	      /* Try to change the property */
	      iReturn = XChangeProperty (pDisplay,
					 event.xselectionrequest.requestor,
					 event.xselectionrequest.property,
					 XA_ATOM,
					 32,
					 PropModeReplace,
					 (unsigned char *) atomTargetArr,
					 (sizeof (atomTargetArr)
					  / sizeof (atomTargetArr[0])));
	      if (iReturn == BadAlloc
		  || iReturn == BadAtom
		  || iReturn == BadMatch
		  || iReturn == BadValue
		  || iReturn == BadWindow)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XChangeProperty failed: %d\n",
			  iReturn);
		}

	      /* Setup selection notify xevent */
	      eventSelection.type	= SelectionNotify;
	      eventSelection.send_event	= True;
	      eventSelection.display	= pDisplay;
	      eventSelection.requestor	= event.xselectionrequest.requestor;
	      eventSelection.selection	= event.xselectionrequest.selection;
	      eventSelection.target	= event.xselectionrequest.target;
	      eventSelection.property	= event.xselectionrequest.property;
	      eventSelection.time	= event.xselectionrequest.time;

	      /*
	       * Notify the requesting window that
	       * the operation has completed
	       */
	      iReturn = XSendEvent (pDisplay,
				    eventSelection.requestor,
				    False,
				    0L,
				    (XEvent *) &eventSelection);
	      if (iReturn == BadValue || iReturn == BadWindow)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XSendEvent () failed\n");
		}
	      break;
	    }

	  /* Check that clipboard format is available */
	  if (fUseUnicode
	      && !IsClipboardFormatAvailable (CF_UNICODETEXT))
	    {
	      static int count; /* Hack to stop acroread spamming the log */
	      static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
	      if (hwnd != lasthwnd) count = 0;
	      count++;
	      if (count < 6) ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
		      "available from Win32 clipboard.  Aborting %d.\n", count);
	      lasthwnd = hwnd;

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  else if (!fUseUnicode
		   && !IsClipboardFormatAvailable (CF_TEXT))
	    {
	      ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
		      "available from Win32 clipboard.  Aborting.\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Close clipboard if we have it open already */
	  if (GetOpenClipboardWindow () == hwnd)
	    {
	      CloseClipboard ();
	    }

	  /* Access the clipboard */
	  if (!OpenClipboard (hwnd))
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "OpenClipboard () failed: %08lx\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  
	  /* Indicate that clipboard was opened */
	  fCloseClipboard = TRUE;

	  /* Setup the string style */
	  if (event.xselectionrequest.target == XA_STRING)
	    xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
	  else if (event.xselectionrequest.target == atomUTF8String)
	    xiccesStyle = XUTF8StringStyle;
#endif
	  else if (event.xselectionrequest.target == atomCompoundText)
	    xiccesStyle = XCompoundTextStyle;
	  else
	    xiccesStyle = XStringStyle;

	  /*
	   * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me
	   */
	  
	  /* Get a pointer to the clipboard text, in desired format */
	  if (fUseUnicode)
	    {
	      /* Retrieve clipboard data */
	      hGlobal = GetClipboardData (CF_UNICODETEXT);
	    }
	  else
	    {
	      /* Retrieve clipboard data */
	      hGlobal = GetClipboardData (CF_TEXT);
	    }
	  if (!hGlobal)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "GetClipboardData () failed: %08lx\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  pszGlobalData = (char *) GlobalLock (hGlobal);

	  /* Convert the Unicode string to UTF8 (MBCS) */
	  if (fUseUnicode)
	    {
	      iConvertDataLen = WideCharToMultiByte (CP_UTF8,
						     0,
						     (LPCWSTR)pszGlobalData,
						     -1,
						     NULL,
						     0,
						     NULL,
						     NULL);
	      /* NOTE: iConvertDataLen includes space for null terminator */
	      pszConvertData = (char *) malloc (iConvertDataLen);
	      WideCharToMultiByte (CP_UTF8,
				   0,
				   (LPCWSTR)pszGlobalData,
				   -1,
				   pszConvertData,
				   iConvertDataLen,
				   NULL,
				   NULL);
	    }
	  else
	    {
	      pszConvertData = strdup (pszGlobalData);
	      iConvertDataLen = strlen (pszConvertData) + 1;
	    }

	  /* Convert DOS string to UNIX string */
	  winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData));

	  /* Setup our text list */
	  pszTextList[0] = pszConvertData;
	  pszTextList[1] = NULL;

	  /* Initialize the text property */
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Create the text property from the text list */
	  if (fUseUnicode)
	    {
#ifdef X_HAVE_UTF8_STRING
	      iReturn = Xutf8TextListToTextProperty (pDisplay,
						     pszTextList,
						     1,
						     xiccesStyle,
						     &xtpText);
#endif
	    }
	  else
	    {
	      iReturn = XmbTextListToTextProperty (pDisplay,
						   pszTextList,
						   1,
						   xiccesStyle,
						   &xtpText);
	    }
	  if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "X*TextListToTextProperty failed: %d\n",
		      iReturn);

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  
	  /* Free the converted string */
	  free (pszConvertData);
	  pszConvertData = NULL;

	  /* Copy the clipboard text to the requesting window */
	  iReturn = XChangeProperty (pDisplay,
				     event.xselectionrequest.requestor,
				     event.xselectionrequest.property,
				     event.xselectionrequest.target,
				     8,
				     PropModeReplace,
				     xtpText.value,
				     xtpText.nitems);
	  if (iReturn == BadAlloc || iReturn == BadAtom
	      || iReturn == BadMatch || iReturn == BadValue
	      || iReturn == BadWindow)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "XChangeProperty failed: %d\n",
		      iReturn);

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Release the clipboard data */
	  GlobalUnlock (hGlobal);
	  pszGlobalData = NULL;
	  fCloseClipboard = FALSE;
	  CloseClipboard ();

	  /* Clean up */
	  XFree (xtpText.value);
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Setup selection notify event */
	  eventSelection.type = SelectionNotify;
	  eventSelection.send_event = True;
	  eventSelection.display = pDisplay;
	  eventSelection.requestor = event.xselectionrequest.requestor;
	  eventSelection.selection = event.xselectionrequest.selection;
	  eventSelection.target = event.xselectionrequest.target;
	  eventSelection.property = event.xselectionrequest.property;
	  eventSelection.time = event.xselectionrequest.time;

	  /* Notify the requesting window that the operation has completed */
	  iReturn = XSendEvent (pDisplay,
				eventSelection.requestor,
				False,
				0L,
				(XEvent *) &eventSelection);
	  if (iReturn == BadValue || iReturn == BadWindow)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "XSendEvent () failed\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	winClipboardFlushXEvents_SelectionRequest_Done:
	  /* Free allocated resources */
	  if (xtpText.value)
	  {
	    XFree (xtpText.value);
	    xtpText.value = NULL;
	    xtpText.nitems = 0;
	  }
	  free(pszConvertData);
	  if (hGlobal && pszGlobalData)
	    GlobalUnlock (hGlobal);
	  
	  /*
	   * Send a SelectionNotify event to the requesting
	   * client when we abort.
	   */
	  if (fAbort)
	    {
	      /* Setup selection notify event */
	      eventSelection.type = SelectionNotify;
	      eventSelection.send_event = True;
	      eventSelection.display = pDisplay;
	      eventSelection.requestor = event.xselectionrequest.requestor;
	      eventSelection.selection = event.xselectionrequest.selection;
	      eventSelection.target = event.xselectionrequest.target;
	      eventSelection.property = None;
	      eventSelection.time = event.xselectionrequest.time;

	      /* Notify the requesting window that the operation is complete */
	      iReturn = XSendEvent (pDisplay,
				    eventSelection.requestor,
				    False,
				    0L,
				    (XEvent *) &eventSelection);
	      if (iReturn == BadValue || iReturn == BadWindow)
		{
		  /*
		   * Should not be a problem if XSendEvent fails because
		   * the client may simply have exited.
		   */
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XSendEvent () failed for abort event.\n");
		}
	    }

	  /* Close clipboard if it was opened */
	  if (fCloseClipboard)
	  {
	    fCloseClipboard = FALSE;
	    CloseClipboard ();
	  }
	  break;


	  /*
	   * SelectionNotify
	   */ 

	case SelectionNotify:

	  winDebug ("winClipboardFlushXEvents - SelectionNotify\n");
	  {
	    char		*pszAtomName;
	    pszAtomName = XGetAtomName (pDisplay,
					event.xselection.selection);

	    winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
                     pszAtomName);
	    XFree (pszAtomName);
	  }

	  /*
	   * Request conversion of UTF8 and CompoundText targets.
	   */
	  if (event.xselection.property == None)
	    {
	      if (event.xselection.target == XA_STRING)
		{
		  winDebug ("winClipboardFlushXEvents - SelectionNotify - "
                            "XA_STRING\n");

		  return WIN_XEVENTS_CONVERT;
		}
	      else if (event.xselection.target == atomUTF8String)
		{
		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
                           "Requesting conversion of UTF8 target.\n");

		  XConvertSelection (pDisplay,
				     event.xselection.selection,
				     XA_STRING,
				     atomLocalProperty,
				     iWindow,
				     CurrentTime);

		  /* Process the ConvertSelection event */
		  XFlush (pDisplay);
		  return WIN_XEVENTS_CONVERT;
		}
#ifdef X_HAVE_UTF8_STRING
	      else if (event.xselection.target == atomCompoundText)
		{
		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
                           "Requesting conversion of CompoundText target.\n");

		  XConvertSelection (pDisplay,
				     event.xselection.selection,
				     atomUTF8String,
				     atomLocalProperty,
				     iWindow,
				     CurrentTime);

		  /* Process the ConvertSelection event */
		  XFlush (pDisplay);
		  return WIN_XEVENTS_CONVERT;
		}
#endif
	      else
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
			  "Unknown format.  Cannot request conversion, "
			  "aborting.\n");
		  break;
		}
	    }

	  /* Retrieve the size of the stored data */
	  iReturn = XGetWindowProperty (pDisplay,
					iWindow,
					atomLocalProperty,
					0,
					0, /* Don't get data, just size */
					False,
					AnyPropertyType,
					&xtpText.encoding,
					&xtpText.format,
					&xtpText.nitems,
					&ulReturnBytesLeft,
					&xtpText.value);
	  if (iReturn != Success)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "XGetWindowProperty () failed, aborting: %d\n",
		      iReturn);
	      break;
	    }

	  winDebug("SelectionNotify - returned data %d left %d\n",
                   xtpText.nitems, ulReturnBytesLeft);

	  /* Request the selection data */
	  iReturn = XGetWindowProperty (pDisplay,
					iWindow,
					atomLocalProperty,
					0,
					ulReturnBytesLeft,
					False,
					AnyPropertyType,
					&xtpText.encoding,
					&xtpText.format,
					&xtpText.nitems,
					&ulReturnBytesLeft,
					&xtpText.value);
	  if (iReturn != Success)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "XGetWindowProperty () failed, aborting: %d\n",
		      iReturn);
	      break;
	    }

	    {
	      char		*pszAtomName = NULL;

	      winDebug("SelectionNotify - returned data %d left %d\n",
                       xtpText.nitems, ulReturnBytesLeft);
	      pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
	      winDebug("Notify atom name %s\n", pszAtomName);
	      XFree (pszAtomName);
	      pszAtomName = NULL;
	    }

	  if (fUseUnicode)
	    {
#ifdef X_HAVE_UTF8_STRING
	      /* Convert the text property to a text list */
	      iReturn = Xutf8TextPropertyToTextList (pDisplay,
						     &xtpText,
						     &ppszTextList,
						     &iCount);
#endif
	    }
	  else
	    {
	      iReturn = XmbTextPropertyToTextList (pDisplay,
						   &xtpText,
						   &ppszTextList,
						   &iCount);
	    }
	  if (iReturn == Success || iReturn > 0)
	    {
	      /* Conversion succeeded or some unconvertible characters */
	      if (ppszTextList != NULL)
		{
		  iReturnDataLen = 0;
		  for (i = 0; i < iCount; i++)
		    {
		      iReturnDataLen += strlen(ppszTextList[i]);
		    }
		  pszReturnData = malloc (iReturnDataLen + 1);
		  pszReturnData[0] = '\0';
		  for (i = 0; i < iCount; i++)
		    {
		      strcat (pszReturnData, ppszTextList[i]);
		    }
		}
	      else
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
			  "X*TextPropertyToTextList list_return is NULL.\n");
		  pszReturnData = malloc (1);
		  pszReturnData[0] = '\0';
		}
	    }
	  else
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "X*TextPropertyToTextList returned: ");
	      switch (iReturn)
		{
		case XNoMemory:
		  ErrorF ("XNoMemory\n");
		  break;
		case XConverterNotFound:
		  ErrorF ("XConverterNotFound\n");
		  break;
		default:
		  ErrorF ("%d", iReturn);
		  break;
		}
	      pszReturnData = malloc (1);
	      pszReturnData[0] = '\0';
	    }

	  /* Free the data returned from XGetWindowProperty */
	  if (ppszTextList)
	    XFreeStringList (ppszTextList);
	  ppszTextList = NULL;
	  XFree (xtpText.value);
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Convert the X clipboard string to DOS format */
	  winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));

	  if (fUseUnicode)
	    {
	      /* Find out how much space needed to convert MBCS to Unicode */
	      iUnicodeLen = MultiByteToWideChar (CP_UTF8,
						 0,
						 pszReturnData,
						 -1,
						 NULL,
						 0);

	      /* Allocate memory for the Unicode string */
	      pwszUnicodeStr
		= (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
	      if (!pwszUnicodeStr)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify "
			  "malloc failed for pwszUnicodeStr, aborting.\n");

		  /* Abort */
		  fAbort = TRUE;
		  goto winClipboardFlushXEvents_SelectionNotify_Done;
		}

	      /* Do the actual conversion */
	      MultiByteToWideChar (CP_UTF8,
				   0,
				   pszReturnData,
				   -1,
				   pwszUnicodeStr,
				   iUnicodeLen);
	      
	      /* Allocate global memory for the X clipboard data */
	      hGlobal = GlobalAlloc (GMEM_MOVEABLE,
				     sizeof (wchar_t) * (iUnicodeLen + 1));
	    }
	  else
	    {
	      pszConvertData = strdup (pszReturnData);
	      iConvertDataLen = strlen (pszConvertData) + 1;

	      /* Allocate global memory for the X clipboard data */
	      hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
	    }

	  free (pszReturnData);

	  /* Check that global memory was allocated */
	  if (!hGlobal)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify "
		      "GlobalAlloc failed, aborting: %ld\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionNotify_Done;
	    }

	  /* Obtain a pointer to the global memory */
	  pszGlobalData = GlobalLock (hGlobal);
	  if (pszGlobalData == NULL)
	    {
	      ErrorF ("winClipboardFlushXEvents - Could not lock global "
		      "memory for clipboard transfer\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionNotify_Done;
	    }

	  /* Copy the returned string into the global memory */
	  if (fUseUnicode)
	    {
	      memcpy (pszGlobalData,
		      pwszUnicodeStr,
		      sizeof (wchar_t) * (iUnicodeLen + 1));
	      free (pwszUnicodeStr);
	      pwszUnicodeStr = NULL;
	    }
	  else
	    {
	      strcpy (pszGlobalData, pszConvertData);
	      free (pszConvertData);
	      pszConvertData = NULL;
	    }

	  /* Release the pointer to the global memory */
	  GlobalUnlock (hGlobal);
	  pszGlobalData = NULL;

	  /* Push the selection data to the Windows clipboard */
	  if (fUseUnicode)
	    SetClipboardData (CF_UNICODETEXT, hGlobal);
	  else
	    SetClipboardData (CF_TEXT, hGlobal);

	  /* Flag that SetClipboardData has been called */
	  fSetClipboardData = FALSE;

	  /*
	   * NOTE: Do not try to free pszGlobalData, it is owned by
	   * Windows after the call to SetClipboardData ().
	   */

	winClipboardFlushXEvents_SelectionNotify_Done:
	  /* Free allocated resources */
	  if (ppszTextList)
	    XFreeStringList (ppszTextList);
	  if (xtpText.value)
	  {
	    XFree (xtpText.value);
	    xtpText.value = NULL;
	    xtpText.nitems = 0;
	  }
	  free(pszConvertData);
	  free(pwszUnicodeStr);
	  if (hGlobal && pszGlobalData)
	    GlobalUnlock (hGlobal);
	  if (fSetClipboardData && g_fUnicodeSupport)
	    SetClipboardData (CF_UNICODETEXT, NULL);
	  if (fSetClipboardData)
	    SetClipboardData (CF_TEXT, NULL);
	  return WIN_XEVENTS_NOTIFY;

        case SelectionClear:
          winDebug("SelectionClear - doing nothing\n");
          break;

	case PropertyNotify:
	  break;

	case MappingNotify:
	  break;

	default:
          ErrorF ("winClipboardFlushXEvents - unexpected event type %d\n", event.type);
	  break;
	}
    }

  return WIN_XEVENTS_SUCCESS;
}
Beispiel #5
0
QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
{
    QString title;

    Atom type;
    int format;
    unsigned long nitems;
    unsigned long after;
    unsigned char* data = nullptr;

    // the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME

    int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, false, m_atomUtf8String,
                                    &type, &format, &nitems, &after, &data);

    if ((retVal == 0) && data) {
        title = QString::fromUtf8(reinterpret_cast<char*>(data));
    }
    else {
        XTextProperty textProp;
        retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
        if ((retVal != 0) && textProp.value) {
            char** textList = nullptr;
            int count;

            if (textProp.encoding == m_atomUtf8String) {
                title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value));
            }
            else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0)
                     && textList && (count > 0)) {
                title = QString::fromLocal8Bit(textList[0]);
            }
            else if (textProp.encoding == m_atomString) {
                title = QString::fromLocal8Bit(reinterpret_cast<char*>(textProp.value));
            }

            if (textList) {
                XFreeStringList(textList);
            }
        }

        if (textProp.value) {
            XFree(textProp.value);
        }
    }

    if (data) {
        XFree(data);
    }

    if (useBlacklist && !title.isEmpty()) {
        if (window == m_rootWindow) {
            return QString();
        }

        QString className = windowClassName(window);
        if (m_classBlacklist.contains(className)) {
            return QString();
        }

        QList<Window> keepassxWindows = widgetsToX11Windows(QApplication::topLevelWidgets());
        if (keepassxWindows.contains(window)) {
            return QString();
        }
    }

    return title;
}
Beispiel #6
0
bool QX11Data::clipboardReadProperty(Window win, Atom property, bool deleteProperty,
                                     QByteArray *buffer, int *size, Atom *type, int *format)
{
    int           maxsize = maxSelectionIncr(display);
    ulong  bytes_left; // bytes_after
    ulong  length;     // nitems
    uchar *data;
    Atom   dummy_type;
    int    dummy_format;
    int    r;

    if (!type)                                // allow null args
        type = &dummy_type;
    if (!format)
        format = &dummy_format;

    // Don't read anything, just get the size of the property data
    r = XGetWindowProperty(display, win, property, 0, 0, False,
                            AnyPropertyType, type, format,
                            &length, &bytes_left, &data);
    if (r != Success || (type && *type == XNone)) {
        buffer->resize(0);
        return false;
    }
    XFree((char*)data);

    int  offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left;

    VDEBUG("QClipboard: read_property(): initial property length: %d", proplen);

    switch (*format) {
    case 8:
    default:
        format_inc = sizeof(char) / 1;
        break;

    case 16:
        format_inc = sizeof(short) / 2;
        proplen *= sizeof(short) / 2;
        break;

    case 32:
        format_inc = sizeof(long) / 4;
        proplen *= sizeof(long) / 4;
        break;
    }

    int newSize = proplen;
    buffer->resize(newSize);

    bool ok = (buffer->size() == newSize);
    VDEBUG("QClipboard: read_property(): buffer resized to %d", buffer->size());

    if (ok && newSize) {
        // could allocate buffer

        while (bytes_left) {
            // more to read...

            r = XGetWindowProperty(display, win, property, offset, maxsize/4,
                                   False, AnyPropertyType, type, format,
                                   &length, &bytes_left, &data);
            if (r != Success || (type && *type == XNone))
                break;

            offset += length / (32 / *format);
            length *= format_inc * (*format) / 8;

            // Here we check if we get a buffer overflow and tries to
            // recover -- this shouldn't normally happen, but it doesn't
            // hurt to be defensive
            if ((int)(buffer_offset + length) > buffer->size()) {
                length = buffer->size() - buffer_offset;

                // escape loop
                bytes_left = 0;
            }

            memcpy(buffer->data() + buffer_offset, data, length);
            buffer_offset += length;

            XFree((char*)data);
        }

        if (*format == 8 && *type == ATOM(COMPOUND_TEXT)) {
            // convert COMPOUND_TEXT to a multibyte string
            XTextProperty textprop;
            textprop.encoding = *type;
            textprop.format = *format;
            textprop.nitems = buffer_offset;
            textprop.value = (unsigned char *) buffer->data();

            char **list_ret = 0;
            int count;
            if (XmbTextPropertyToTextList(display, &textprop, &list_ret,
                         &count) == Success && count && list_ret) {
                offset = buffer_offset = strlen(list_ret[0]);
                buffer->resize(offset);
                memcpy(buffer->data(), list_ret[0], offset);
            }
            if (list_ret) XFreeStringList(list_ret);
        }
    }

    // correct size, not 0-term.
    if (size)
        *size = buffer_offset;

    VDEBUG("QClipboard: read_property(): buffer size %d, buffer offset %d, offset %d",
           buffer->size(), buffer_offset, offset);

    if (deleteProperty)
        XDeleteProperty(display, win, property);

    XFlush(display);

    return ok;
}
Beispiel #7
0
int
winClipboardFlushXEvents(HWND hwnd,
                         Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
{
    Atom atomClipboard = atoms->atomClipboard;
    Atom atomLocalProperty = atoms->atomLocalProperty;
    Atom atomUTF8String = atoms->atomUTF8String;
    Atom atomCompoundText = atoms->atomCompoundText;
    Atom atomTargets = atoms->atomTargets;

    /* Process all pending events */
    while (XPending(pDisplay)) {
        XTextProperty xtpText = { 0 };
        XEvent event;
        XSelectionEvent eventSelection;
        unsigned long ulReturnBytesLeft;
        char *pszReturnData = NULL;
        char *pszGlobalData = NULL;
        int iReturn;
        HGLOBAL hGlobal = NULL;
        XICCEncodingStyle xiccesStyle;
        char *pszConvertData = NULL;
        char *pszTextList[2] = { NULL };
        int iCount;
        char **ppszTextList = NULL;
        wchar_t *pwszUnicodeStr = NULL;
        Bool fAbort = FALSE;
        Bool fCloseClipboard = FALSE;
        Bool fSetClipboardData = TRUE;

        /* Get the next event - will not block because one is ready */
        XNextEvent(pDisplay, &event);

        /* Branch on the event type */
        switch (event.type) {
            /*
             * SelectionRequest
             */

        case SelectionRequest:
        {
            char *pszAtomName = NULL;

            winDebug("SelectionRequest - target %ld\n",
                     event.xselectionrequest.target);

            pszAtomName = XGetAtomName(pDisplay,
                                       event.xselectionrequest.target);
            winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
            XFree(pszAtomName);
            pszAtomName = NULL;
        }

            /* Abort if invalid target type */
            if (event.xselectionrequest.target != XA_STRING
                && event.xselectionrequest.target != atomUTF8String
                && event.xselectionrequest.target != atomCompoundText
                && event.xselectionrequest.target != atomTargets) {
                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Handle targets type of request */
            if (event.xselectionrequest.target == atomTargets) {
                Atom atomTargetArr[] = { atomTargets,
                    atomCompoundText,
                    atomUTF8String,
                    XA_STRING
                };

                /* Try to change the property */
                iReturn = XChangeProperty(pDisplay,
                                          event.xselectionrequest.requestor,
                                          event.xselectionrequest.property,
                                          XA_ATOM,
                                          32,
                                          PropModeReplace,
                                          (unsigned char *) atomTargetArr,
                                          ARRAY_SIZE(atomTargetArr));
                if (iReturn == BadAlloc
                    || iReturn == BadAtom
                    || iReturn == BadMatch
                    || iReturn == BadValue || iReturn == BadWindow) {
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XChangeProperty failed: %d\n", iReturn);
                }

                /* Setup selection notify xevent */
                eventSelection.type = SelectionNotify;
                eventSelection.send_event = True;
                eventSelection.display = pDisplay;
                eventSelection.requestor = event.xselectionrequest.requestor;
                eventSelection.selection = event.xselectionrequest.selection;
                eventSelection.target = event.xselectionrequest.target;
                eventSelection.property = event.xselectionrequest.property;
                eventSelection.time = event.xselectionrequest.time;

                /*
                 * Notify the requesting window that
                 * the operation has completed
                 */
                iReturn = XSendEvent(pDisplay,
                                     eventSelection.requestor,
                                     False, 0L, (XEvent *) &eventSelection);
                if (iReturn == BadValue || iReturn == BadWindow) {
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XSendEvent () failed\n");
                }
                break;
            }

            /* Close clipboard if we have it open already */
            if (GetOpenClipboardWindow() == hwnd) {
                CloseClipboard();
            }

            /* Access the clipboard */
            if (!OpenClipboard(hwnd)) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "OpenClipboard () failed: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Indicate that clipboard was opened */
            fCloseClipboard = TRUE;

            /* Check that clipboard format is available */
            if (data->fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
                static int count;       /* Hack to stop acroread spamming the log */
                static HWND lasthwnd;   /* I've not seen any other client get here repeatedly? */

                if (hwnd != lasthwnd)
                    count = 0;
                count++;
                if (count < 6)
                    ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
                           "available from Win32 clipboard.  Aborting %d.\n",
                           count);
                lasthwnd = hwnd;

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }
            else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
                ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
                       "available from Win32 clipboard.  Aborting.\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Setup the string style */
            if (event.xselectionrequest.target == XA_STRING)
                xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
            else if (event.xselectionrequest.target == atomUTF8String)
                xiccesStyle = XUTF8StringStyle;
#endif
            else if (event.xselectionrequest.target == atomCompoundText)
                xiccesStyle = XCompoundTextStyle;
            else
                xiccesStyle = XStringStyle;

            /* Get a pointer to the clipboard text, in desired format */
            if (data->fUseUnicode) {
                /* Retrieve clipboard data */
                hGlobal = GetClipboardData(CF_UNICODETEXT);
            }
            else {
                /* Retrieve clipboard data */
                hGlobal = GetClipboardData(CF_TEXT);
            }
            if (!hGlobal) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "GetClipboardData () failed: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }
            pszGlobalData = (char *) GlobalLock(hGlobal);

            /* Convert the Unicode string to UTF8 (MBCS) */
            if (data->fUseUnicode) {
                int iConvertDataLen = WideCharToMultiByte(CP_UTF8,
                                                      0,
                                                      (LPCWSTR) pszGlobalData,
                                                      -1, NULL, 0, NULL, NULL);
                /* NOTE: iConvertDataLen includes space for null terminator */
                pszConvertData = malloc(iConvertDataLen);
                WideCharToMultiByte(CP_UTF8,
                                    0,
                                    (LPCWSTR) pszGlobalData,
                                    -1,
                                    pszConvertData,
                                    iConvertDataLen, NULL, NULL);
            }
            else {
                pszConvertData = strdup(pszGlobalData);
            }

            /* Convert DOS string to UNIX string */
            winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));

            /* Setup our text list */
            pszTextList[0] = pszConvertData;
            pszTextList[1] = NULL;

            /* Initialize the text property */
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Create the text property from the text list */
            if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
                iReturn = Xutf8TextListToTextProperty(pDisplay,
                                                      pszTextList,
                                                      1, xiccesStyle, &xtpText);
#endif
            }
            else {
                iReturn = XmbTextListToTextProperty(pDisplay,
                                                    pszTextList,
                                                    1, xiccesStyle, &xtpText);
            }
            if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "X*TextListToTextProperty failed: %d\n", iReturn);

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Free the converted string */
            free(pszConvertData);
            pszConvertData = NULL;

            /* Copy the clipboard text to the requesting window */
            iReturn = XChangeProperty(pDisplay,
                                      event.xselectionrequest.requestor,
                                      event.xselectionrequest.property,
                                      event.xselectionrequest.target,
                                      8,
                                      PropModeReplace,
                                      xtpText.value, xtpText.nitems);
            if (iReturn == BadAlloc || iReturn == BadAtom
                || iReturn == BadMatch || iReturn == BadValue
                || iReturn == BadWindow) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "XChangeProperty failed: %d\n", iReturn);

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Release the clipboard data */
            GlobalUnlock(hGlobal);
            pszGlobalData = NULL;
            fCloseClipboard = FALSE;
            CloseClipboard();

            /* Clean up */
            XFree(xtpText.value);
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Setup selection notify event */
            eventSelection.type = SelectionNotify;
            eventSelection.send_event = True;
            eventSelection.display = pDisplay;
            eventSelection.requestor = event.xselectionrequest.requestor;
            eventSelection.selection = event.xselectionrequest.selection;
            eventSelection.target = event.xselectionrequest.target;
            eventSelection.property = event.xselectionrequest.property;
            eventSelection.time = event.xselectionrequest.time;

            /* Notify the requesting window that the operation has completed */
            iReturn = XSendEvent(pDisplay,
                                 eventSelection.requestor,
                                 False, 0L, (XEvent *) &eventSelection);
            if (iReturn == BadValue || iReturn == BadWindow) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "XSendEvent () failed\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

 winClipboardFlushXEvents_SelectionRequest_Done:
            /* Free allocated resources */
            if (xtpText.value) {
                XFree(xtpText.value);
                xtpText.value = NULL;
                xtpText.nitems = 0;
            }
            free(pszConvertData);
            if (hGlobal && pszGlobalData)
                GlobalUnlock(hGlobal);

            /*
             * Send a SelectionNotify event to the requesting
             * client when we abort.
             */
            if (fAbort) {
                /* Setup selection notify event */
                eventSelection.type = SelectionNotify;
                eventSelection.send_event = True;
                eventSelection.display = pDisplay;
                eventSelection.requestor = event.xselectionrequest.requestor;
                eventSelection.selection = event.xselectionrequest.selection;
                eventSelection.target = event.xselectionrequest.target;
                eventSelection.property = None;
                eventSelection.time = event.xselectionrequest.time;

                /* Notify the requesting window that the operation is complete */
                iReturn = XSendEvent(pDisplay,
                                     eventSelection.requestor,
                                     False, 0L, (XEvent *) &eventSelection);
                if (iReturn == BadValue || iReturn == BadWindow) {
                    /*
                     * Should not be a problem if XSendEvent fails because
                     * the client may simply have exited.
                     */
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XSendEvent () failed for abort event.\n");
                }
            }

            /* Close clipboard if it was opened */
            if (fCloseClipboard) {
                fCloseClipboard = FALSE;
                CloseClipboard();
            }
            break;

            /*
             * SelectionNotify
             */

        case SelectionNotify:
            winDebug("winClipboardFlushXEvents - SelectionNotify\n");
            {
                char *pszAtomName;

                pszAtomName = XGetAtomName(pDisplay,
                                           event.xselection.selection);

                winDebug
                    ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
                     pszAtomName);
                XFree(pszAtomName);
            }

            /*
              SelectionNotify with property of None indicates either:

              (i) Generated by the X server if no owner for the specified selection exists
                  (perhaps it's disappeared on us mid-transaction), or
              (ii) Sent by the selection owner when the requested selection conversion could
                   not be performed or server errors prevented the conversion data being returned
            */
            if (event.xselection.property == None) {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                           "Conversion to format %ld refused.\n",
                           event.xselection.target);
                    return WIN_XEVENTS_FAILED;
                }

            if (event.xselection.target == atomTargets) {
              return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms);
            }

            /* Retrieve the selection data and delete the property */
            iReturn = XGetWindowProperty(pDisplay,
                                         iWindow,
                                         atomLocalProperty,
                                         0,
                                         INT_MAX,
                                         True,
                                         AnyPropertyType,
                                         &xtpText.encoding,
                                         &xtpText.format,
                                         &xtpText.nitems,
                                         &ulReturnBytesLeft, &xtpText.value);
            if (iReturn != Success) {
                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                       "XGetWindowProperty () failed, aborting: %d\n", iReturn);
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            {
                char *pszAtomName = NULL;

                winDebug("SelectionNotify - returned data %lu left %lu\n",
                         xtpText.nitems, ulReturnBytesLeft);
                pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
                winDebug("Notify atom name %s\n", pszAtomName);
                XFree(pszAtomName);
                pszAtomName = NULL;
            }

            if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
                /* Convert the text property to a text list */
                iReturn = Xutf8TextPropertyToTextList(pDisplay,
                                                      &xtpText,
                                                      &ppszTextList, &iCount);
#endif
            }
            else {
                iReturn = XmbTextPropertyToTextList(pDisplay,
                                                    &xtpText,
                                                    &ppszTextList, &iCount);
            }
            if (iReturn == Success || iReturn > 0) {
                /* Conversion succeeded or some unconvertible characters */
                if (ppszTextList != NULL) {
                    int i;
                    int iReturnDataLen = 0;
                    for (i = 0; i < iCount; i++) {
                        iReturnDataLen += strlen(ppszTextList[i]);
                    }
                    pszReturnData = malloc(iReturnDataLen + 1);
                    pszReturnData[0] = '\0';
                    for (i = 0; i < iCount; i++) {
                        strcat(pszReturnData, ppszTextList[i]);
                    }
                }
                else {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                           "X*TextPropertyToTextList list_return is NULL.\n");
                    pszReturnData = malloc(1);
                    pszReturnData[0] = '\0';
                }
            }
            else {
                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                       "X*TextPropertyToTextList returned: ");
                switch (iReturn) {
                case XNoMemory:
                    ErrorF("XNoMemory\n");
                    break;
                case XLocaleNotSupported:
                    ErrorF("XLocaleNotSupported\n");
                    break;
                case XConverterNotFound:
                    ErrorF("XConverterNotFound\n");
                    break;
                default:
                    ErrorF("%d\n", iReturn);
                    break;
                }
                pszReturnData = malloc(1);
                pszReturnData[0] = '\0';
            }

            /* Free the data returned from XGetWindowProperty */
            if (ppszTextList)
                XFreeStringList(ppszTextList);
            ppszTextList = NULL;
            XFree(xtpText.value);
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Convert the X clipboard string to DOS format */
            winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));

            if (data->fUseUnicode) {
                /* Find out how much space needed to convert MBCS to Unicode */
                int iUnicodeLen = MultiByteToWideChar(CP_UTF8,
                                                  0,
                                                  pszReturnData, -1, NULL, 0);

                /* NOTE: iUnicodeLen includes space for null terminator */
                pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen);
                if (!pwszUnicodeStr) {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify "
                           "malloc failed for pwszUnicodeStr, aborting.\n");

                    /* Abort */
                    fAbort = TRUE;
                    goto winClipboardFlushXEvents_SelectionNotify_Done;
                }

                /* Do the actual conversion */
                MultiByteToWideChar(CP_UTF8,
                                    0,
                                    pszReturnData,
                                    -1, pwszUnicodeStr, iUnicodeLen);

                /* Allocate global memory for the X clipboard data */
                hGlobal = GlobalAlloc(GMEM_MOVEABLE,
                                      sizeof(wchar_t) * iUnicodeLen);
            }
            else {
                int iConvertDataLen = 0;
                pszConvertData = strdup(pszReturnData);
                iConvertDataLen = strlen(pszConvertData) + 1;

                /* Allocate global memory for the X clipboard data */
                hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
            }

            free(pszReturnData);

            /* Check that global memory was allocated */
            if (!hGlobal) {
                ErrorF("winClipboardFlushXEvents - SelectionNotify "
                       "GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            /* Obtain a pointer to the global memory */
            pszGlobalData = GlobalLock(hGlobal);
            if (pszGlobalData == NULL) {
                ErrorF("winClipboardFlushXEvents - Could not lock global "
                       "memory for clipboard transfer\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            /* Copy the returned string into the global memory */
            if (data->fUseUnicode) {
                wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr);
                free(pwszUnicodeStr);
                pwszUnicodeStr = NULL;
            }
            else {
                strcpy(pszGlobalData, pszConvertData);
                free(pszConvertData);
                pszConvertData = NULL;
            }

            /* Release the pointer to the global memory */
            GlobalUnlock(hGlobal);
            pszGlobalData = NULL;

            /* Push the selection data to the Windows clipboard */
            if (data->fUseUnicode)
                SetClipboardData(CF_UNICODETEXT, hGlobal);
            else
                SetClipboardData(CF_TEXT, hGlobal);

            /* Flag that SetClipboardData has been called */
            fSetClipboardData = FALSE;

            /*
             * NOTE: Do not try to free pszGlobalData, it is owned by
             * Windows after the call to SetClipboardData ().
             */

 winClipboardFlushXEvents_SelectionNotify_Done:
            /* Free allocated resources */
            if (ppszTextList)
                XFreeStringList(ppszTextList);
            if (xtpText.value) {
                XFree(xtpText.value);
                xtpText.value = NULL;
                xtpText.nitems = 0;
            }
            free(pszConvertData);
            free(pwszUnicodeStr);
            if (hGlobal && pszGlobalData)
                GlobalUnlock(hGlobal);
            if (fSetClipboardData) {
                SetClipboardData(CF_UNICODETEXT, NULL);
                SetClipboardData(CF_TEXT, NULL);
            }
            return WIN_XEVENTS_NOTIFY_DATA;

        case SelectionClear:
            winDebug("SelectionClear - doing nothing\n");
            break;

        case PropertyNotify:
            break;

        case MappingNotify:
            break;

        default:
            if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
                XFixesSelectionNotifyEvent *e =
                    (XFixesSelectionNotifyEvent *) & event;

                winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");

                /* Save selection owners for monitored selections, ignore other selections */
                if ((e->selection == XA_PRIMARY) && fPrimarySelection) {
                    MonitorSelection(e, CLIP_OWN_PRIMARY);
                }
                else if (e->selection == atomClipboard) {
                    MonitorSelection(e, CLIP_OWN_CLIPBOARD);
                }
                else
                    break;

                /* Selection is being disowned */
                if (e->owner == None) {
                    winDebug
                        ("winClipboardFlushXEvents - No window, returning.\n");
                    break;
                }

                /*
                   XXX: there are all kinds of wacky edge cases we might need here:
                   - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
                   - root window is taking ownership?
                 */

                /* If we are the owner of the most recently owned selection, don't go all recursive :) */
                if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
                    (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
                    winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
                    break;
                }

                /* Close clipboard if we have it open already (possible? correct??) */
                if (GetOpenClipboardWindow() == hwnd) {
                    CloseClipboard();
                }

                /* Access the Windows clipboard */
                if (!OpenClipboard(hwnd)) {
                    ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }

                /* Take ownership of the Windows clipboard */
                if (!EmptyClipboard()) {
                    ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }

                /* Advertise regular text and unicode */
                SetClipboardData(CF_UNICODETEXT, NULL);
                SetClipboardData(CF_TEXT, NULL);

                /* Release the clipboard */
                if (!CloseClipboard()) {
                    ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }
            }
            /* XFixesSelectionWindowDestroyNotifyMask */
            /* XFixesSelectionClientCloseNotifyMask */
            else {
                ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
                       event.type);
            }
            break;
        }
    }

    return WIN_XEVENTS_SUCCESS;
}
Beispiel #8
0
/**
 * Retrieves the data from a certain source Atom using a specific
 * format.
 *
 * \param source The currently active clipboard Atom to get the data from.
 * \param format The format of the data to get.
 * \param length Out parameter that contains the length of the returned
 * buffer.
 * \return The requested content or NULL in case no content exists or an
 * error occured.
 */
static int
_get_data_as (Atom source, Atom format, char **data, unsigned int *size)
{
    Window owner;
    time_t start;
    Atom sel_type;
    int sel_format;
    unsigned long nbytes, overflow;
    *size = 0;
    unsigned char *src;
    unsigned long offset = 0;
    unsigned long chunk = 0;
    int step = 1;
    XEvent ev;
    Time timestamp;

    /* If we are the owner, simply return the clip buffer, if it matches
     * the request type.
     */
    if (!scrap_lost_x11 ())
    {
        char *fmt;

        fmt = _atom_to_string (format);
        /* TODO */
        free (fmt);

        return 1;
    }

    Lock_Display ();
    
    /* Find a selection owner. */
    owner = _get_scrap_owner (&source);
    if (owner == None)
    {
        Unlock_Display ();
        SDL_SetError ("no clipboard owner found");
        return 0;
    }

    timestamp = (source == XA_PRIMARY) ?  _selectiontime : _cliptime;

    /* Copy and convert the selection into our SDL_SELECTION atom of the
     * window. 
     * Flush afterwards, so we have an immediate effect and do not receive
     * the old buffer anymore.
     */
    XConvertSelection (_sdldisplay, source, format, _atom_SDL, _sdlwindow,
        timestamp);
    XSync (_sdldisplay, False);

    /* Let's wait for the SelectionNotify event from the callee and
     * react upon it as soon as it is received.
     */
    for (start = time (0);;)
    {
        if (XCheckTypedWindowEvent (_sdldisplay, _sdlwindow,
                SelectionNotify, &ev))
            break;
        if (time (0) - start >= 5)
        {
            /* Timeout, damn. */
            Unlock_Display ();
            SDL_SetError ("timeout on retrieving the clipboard data");
            return 0;
        }
    }
    /* Get any property type and check the sel_type afterwards to decide
     * what to do.
     */
    if (XGetWindowProperty (_sdldisplay, ev.xselection.requestor, _atom_SDL,
            0, 0, True, AnyPropertyType, &sel_type, &sel_format, &nbytes,
            &overflow, &src) != Success)
    {
        XFree (src);
        Unlock_Display ();
        SDL_SetError ("could not receive clipboard buffer");
        return 0;
    }

    /* In case we requested a SCRAP_TEXT, any property type of
     * XA_STRING, XA_COMPOUND_TEXT, UTF8_STRING and TEXT is valid.
     */
    if (format == _atom_MIME_PLAIN &&
        (sel_type != _atom_UTF8 && sel_type != _atom_TEXT
            && sel_type != _atom_COMPOUND && sel_type != XA_STRING))
    {
        /* No matching text type found. Return nothing then. */
        XFree (src);
        Unlock_Display ();
        SDL_SetError ("text format not found");
        return 0;
    }

    /* Anything is fine, so copy the buffer and return it. */
    switch (sel_format)
    {
    case 16:
        step = sizeof (short) / 2;
        break;
    case 32:
        step = sizeof (long) / 4;
        break;
    case 8:
    default:
        step = sizeof (char);
        *size = overflow; /* 8 bit size is already correctly set in nbytes.*/
        break;
    }

    /* X11 guarantees NULL termination, add an extra byte. */
    *size = step * overflow;
    *data = malloc (*size + 1);
    if (*data)
    {
        unsigned long boffset = 0;
        chunk = MAX_CHUNK_SIZE(_sdldisplay);
        memset (*data, 0, (size_t) (*size + 1));

        /* Read as long as there is data. */
        while (overflow)
        {
            if (XGetWindowProperty (_sdldisplay, ev.xselection.requestor,
                    _atom_SDL, offset, chunk, True, AnyPropertyType, &sel_type,
                    &sel_format, &nbytes, &overflow, &src) != Success)
            {
                break;
            }
            
            offset += nbytes / (32 / sel_format);
            nbytes *= step * sel_format / 8;
            memcpy ((*data) + boffset, src, nbytes);
            boffset += nbytes;
            XFree (src);
        }
    }
    else
    {
        /* ENOMEM */
        SDL_SetError ("could not allocate memory");
        return 0;
    }
    /* In case we've got a COMPOUND_TEXT, convert it to the current
     * multibyte locale.
     */
    if (sel_type == _atom_COMPOUND && sel_format == 8)
    {
        char **list = NULL;
        int count, status = 0;
        XTextProperty p;

        p.encoding = sel_type;
        p.format = sel_format;
        p.nitems = nbytes;
        p.value = (unsigned char*)(*data);

        status = XmbTextPropertyToTextList (_sdldisplay, &p, &list, &count);
        if (status == XLocaleNotSupported || status == XConverterNotFound)
        {
            free (*data);
            SDL_SetError ("current locale is not supported for conversion.");
            return 0;
        }
        else if (status == XNoMemory)
        {
            free (*data);
            SDL_SetError ("could not allocate memory");
            return 0;
        }
        else if (status == Success)
        {
            if (count && list)
            {
                int i = 0;
                int ioffset = 0;
                char *tmp;

                free (*data);
                *data = NULL;
                for (i = 0; i < count; i++)
                {
                    *size = strlen (list[i]);
                    tmp = *data;
                    *data = realloc (*data, (*size) + 1);
                    if (!(*data))
                    {
                        free (tmp);
                        SDL_SetError ("could not allocate memory");
                        return 0;
                    }
                    ioffset += *size;

                    memcpy (*data, list[i], *size);
                    memset ((*data) + ioffset, '\n', 1);
                }
                memset ((*data) + ioffset, 0, 1);
            }
        }

        if (list)
            XFreeStringList (list);
    }

    Unlock_Display ();
    return 1;
}
Beispiel #9
0
/********************************************************************
 *
 * Setup a child service record per the selection request.
 */
void mgr_initialize( XEvent *report, XpPdmServiceRec *rec )
{
    Display *testdpy;
    char    buf[1024];

    Display *selection_display;
    Window   requestor;
    Atom     prop_atom;
    unsigned long tafter;

    XTextProperty  text_prop;
    char           **list;
    int            list_cnt;

    /*
     * Grab the PDM_CLIENT_PROP from which all the juicy
     * information is retrieved.
     */
    selection_display = report->xselectionrequest.display;
    requestor = report->xselectionrequest.requestor;
    prop_atom = report->xselectionrequest.property;

    if ( XGetWindowProperty( selection_display, requestor, prop_atom,
			0, 100000, True, AnyPropertyType,
                        &text_prop.encoding,
			&text_prop.format,
			&text_prop.nitems,
			&tafter,
                        &text_prop.value ) != Success ) {
	/*
	 * Error
	 */
	rec->pdm_exec_errorcode = g.pdm_start_error;

	sprintf( buf, PDMD_MSG_5, g.prog_name );
	rec->pdm_exec_errormessage = xpstrdup( buf );

	return;
    }

    if ( text_prop.format != 8 ) {
	/*
	 * Error
	 */
	rec->pdm_exec_errorcode = g.pdm_start_error;

	sprintf( buf, PDMD_MSG_6, g.prog_name );
	rec->pdm_exec_errormessage = xpstrdup( buf );

	return;
    }

    if ( XmbTextPropertyToTextList( selection_display, &text_prop,
				     &list, &list_cnt ) < 0 ) {
	/*
	 * Error
	 */
	rec->pdm_exec_errorcode = g.pdm_start_error;

	sprintf( buf, PDMD_MSG_7, g.prog_name );
	rec->pdm_exec_errormessage = xpstrdup( buf );

	return;
    }

    /*
     * Fill in the PDM_MANAGER portion of the client record.
     */
    rec->video_display_str  = xpstrdup( list[0] );
    rec->video_window       = strtol(list[1], (char **)NULL, 16);
    rec->print_display_str  = xpstrdup( list[2] );
    rec->print_window       = strtol(list[3], (char **)NULL, 16);
#if 0 && defined(PRINTING_SUPPORTED)
    rec->print_context      = strtol(list[4], (char **)NULL, 16);
#endif /* PRINTING_SUPPORTED */
    rec->locale_hint        = xpstrdup( list[5] );
    XFreeStringList( list );

    rec->selection_display  = selection_display;
    rec->requestor          = requestor;
    rec->prop_atom          = prop_atom;
    rec->selection          = report->xselectionrequest.selection;
    rec->time               = report->xselectionrequest.time;

    rec->mgr_flag           = True;	/* mgr portion of rec now valid */

    /*
     * Optimization.  The only live display connection, for which we
     * need to trap XIO errors, is "selection display".  For the
     * "video" and "print" displays, we have the display strings and
     * can establish connections as we need them.  Since they are rarely
     * used, and opening them up here would create XIO liability problems
     * and a startup performance hit, we won't establish connections now.
     *
     * One optimization however is to see if the "print" display would
     * just happen to be the same at the "selection display" currently
     * open.
     */
    if ( !strcmp( XDisplayString(rec->selection_display),
		  rec->print_display_str ) ) {
	rec->seldpy_as_printdpy = True;
    }
    else {
	rec->seldpy_as_printdpy = False;

#ifdef OPTIONAL_PXAUTH_PRETEST
	/*
	 * Verify connectability to the Print Server.
	 *
	 * Note: once beyond the selection phase, all communication
	 *       will be by way of the Print Server.  If we cannot
	 *       connect later, then we will have no way to deliver
	 *       EXIT_PXAUTH, EXIT_VXAUTH, EXIT_ERROR, EXIT_OK or
         *       EXIT_CANCEL.  Real bad news!
	 *
	 * It is better to discover now that we don't have
	 * connection authorization for the print display since
	 * we can still let the user know of PXAUTH problems
	 * via the selection display currently open.
	 *
	 * Unfortunately, this pre-test is a performance hit in the
	 * startup phase.
	 */
	if ( ! (testdpy = XOpenDisplay(rec->print_display_str)) ) {
	    rec->pdm_exec_errorcode = g.pdm_start_pxauth;
	    return;
	}
	XCloseDisplay( testdpy );
#endif /* OPTIONAL_PXAUTH_PRETEST */
    }

#ifdef OPTIONAL_VXAUTH_PRETEST
    /*
     * Verify connectability to the Video Server.
     *
     * It is better to discover now that we don't have
     * connection authorization for the video display since
     * we can still let the user know of VXAUTH problems
     * via the selection display currently open.
     *
     * Unfortunately, this pre-test is a performance hit in the
     * startup phase.
     */
    if ( ! (testdpy = XOpenDisplay(rec->video_display_str)) ) {
	rec->pdm_exec_errorcode = g.pdm_start_vxauth;
	return;
    }
    XCloseDisplay( testdpy );
#endif /* OPTIONAL_VXAUTH_PRETEST */

}
Beispiel #10
0
Client *createclient(Window w)
{
  extern void checkstyle(Client *c);

  XWindowAttributes attr;
  Client *c;

  if(w==0) return 0;
  if(!XFindContext(dpy, w, client_context, (XPointer*)&c)) return c;

  XGetWindowAttributes(dpy, w, &attr);

  c = (Client *)calloc(1, sizeof(Client));
  c->scr = scr;
  c->window = w;
  c->parent = scr->root;
  c->old_bw = attr.border_width;
  c->next = clients;
  c->state = WithdrawnState;
  c->gravity = NorthWestGravity;
  c->reparenting = 0;
  XSelectInput(dpy, c->window, PropertyChangeMask);
#ifdef USE_FONTSETS
  {
    XTextProperty prop;
    c->title = NULL;
    if(XGetWMName(dpy, c->window, &prop) && prop.value) {
      char **list;
      int n;
      if(XmbTextPropertyToTextList(dpy, &prop, &list, &n) >= Success) {
	if(n > 0)
	  c->title = strdup(list[0]);
	XFreeStringList(list);
      }
      XFree(prop.value);
    }
  }
#else
  XGetWMName(dpy, c->window, &c->title);
#endif
  c->style = NULL;
  checkstyle(c);
  checksizehints(c);
  c->zoomx=0;
  c->zoomy=scr->bh;
  if(c->sizehints.width_inc) {
    c->zoomw=scr->width-c->sizehints.base_width-22;
    c->zoomw-=c->zoomw%c->sizehints.width_inc;
    c->zoomw+=c->sizehints.base_width;
    if(c->zoomw>c->sizehints.max_width)
      c->zoomw=c->sizehints.max_width;
    if(c->zoomw<c->sizehints.min_width)
      c->zoomw=c->sizehints.min_width;
  } else
    c->zoomw=attr.width;
  if(c->sizehints.height_inc) {
    c->zoomh=scr->height-c->sizehints.base_height-scr->bh-c->zoomy-2;
    c->zoomh-=c->zoomh%c->sizehints.height_inc;
    c->zoomh+=c->sizehints.base_height;
    if(c->zoomh>c->sizehints.max_height)
      c->zoomh=c->sizehints.max_height;
    if(c->zoomh<c->sizehints.min_height)
      c->zoomh=c->sizehints.min_height;
  } else
    c->zoomh=attr.height;
  XSaveContext(dpy, w, client_context, (XPointer)c);
  return clients = c;
}