X11 clipboard paste : support several formats
This commit is contained in:
		
							parent
							
								
									d24dd3e1a9
								
							
						
					
					
						commit
						583d646b26
					
				
							
								
								
									
										94
									
								
								src/input.c
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								src/input.c
									
									
									
									
									
								
							@ -88,6 +88,7 @@ word * Drop_file_name_unicode = NULL;
 | 
			
		||||
#if defined(USE_X11) || (defined(SDL_VIDEO_DRIVER_X11) && !defined(NO_X11))
 | 
			
		||||
char * X11_clipboard = NULL;
 | 
			
		||||
unsigned long X11_clipboard_size = 0;
 | 
			
		||||
enum X11_CLIPBOARD_TYPES X11_clipboard_type = X11_CLIPBOARD_NONE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// --
 | 
			
		||||
@ -598,24 +599,86 @@ static int Handle_SelectionNotify(const XSelectionEvent* xselection)
 | 
			
		||||
      XFree(target_name);
 | 
			
		||||
 | 
			
		||||
      r = XGetWindowProperty(X11_display, X11_window, xselection->property, 0, LONG_MAX,
 | 
			
		||||
          False, xselection->target /* type */, &type, &format,
 | 
			
		||||
          False, AnyPropertyType/*xselection->target*/ /* type */, &type, &format,
 | 
			
		||||
          &count, &bytesAfter, &value);
 | 
			
		||||
      if (r == Success && value != NULL)
 | 
			
		||||
      {
 | 
			
		||||
#ifndef __no_pnglib__
 | 
			
		||||
        Atom png = XInternAtom(X11_display, "image/png", False);
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef __no_tifflib__
 | 
			
		||||
        Atom tiff = XInternAtom(X11_display, "image/tiff", False);
 | 
			
		||||
#endif
 | 
			
		||||
        Atom urilist = XInternAtom(X11_display, "text/uri-list", False);
 | 
			
		||||
        Atom utf8string = XInternAtom(X11_display, "UTF8_STRING", False);
 | 
			
		||||
        // by order of preference
 | 
			
		||||
        const struct { Atom a; enum X11_CLIPBOARD_TYPES t; } supported[] = {
 | 
			
		||||
#ifndef __no_pnglib__
 | 
			
		||||
          { png, X11_CLIPBOARD_PNG },
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef __no_tifflib__
 | 
			
		||||
          { tiff, X11_CLIPBOARD_TIFF },
 | 
			
		||||
#endif
 | 
			
		||||
          { urilist, X11_CLIPBOARD_URILIST },
 | 
			
		||||
          { utf8string, X11_CLIPBOARD_UTF8STRING },
 | 
			
		||||
          { None, X11_CLIPBOARD_NONE }
 | 
			
		||||
        };
 | 
			
		||||
        char * type_name = XGetAtomName(X11_display, type);
 | 
			
		||||
        GFX2_Log(GFX2_DEBUG, "Clipboard value=%p %lu bytes format=%d type=%s\n",
 | 
			
		||||
                 value, count, format, type_name);
 | 
			
		||||
        XFree(type_name);
 | 
			
		||||
        if (count > 0)
 | 
			
		||||
        if (xselection->target == XInternAtom(X11_display, "TARGETS", False))
 | 
			
		||||
        {
 | 
			
		||||
          X11_clipboard_size = count;
 | 
			
		||||
          if (xselection->target == XInternAtom(X11_display, "UTF8_STRING", False))
 | 
			
		||||
            X11_clipboard = strdup((char *)value); // Text Clipboard
 | 
			
		||||
          else if (xselection->target == XInternAtom(X11_display, "image/png", False))
 | 
			
		||||
          { // Picture clipboard (PNG)
 | 
			
		||||
            X11_clipboard = malloc(count);
 | 
			
		||||
            if (X11_clipboard != NULL)
 | 
			
		||||
              memcpy(X11_clipboard, value, count);
 | 
			
		||||
          unsigned long i;
 | 
			
		||||
          Atom * atoms = (Atom *)value;
 | 
			
		||||
          Atom prefered = None;
 | 
			
		||||
          for (i = 0; i < count; i++)
 | 
			
		||||
          {
 | 
			
		||||
            int j;
 | 
			
		||||
            char * atom_name = XGetAtomName(X11_display, atoms[i]);
 | 
			
		||||
            GFX2_Log(GFX2_DEBUG, "  %d %s\n", atoms[i], atom_name);
 | 
			
		||||
            XFree(atom_name);
 | 
			
		||||
            if (prefered == None)
 | 
			
		||||
            {
 | 
			
		||||
              for (j = 0; supported[j].a != None; j++)
 | 
			
		||||
              {
 | 
			
		||||
                if (atoms[i] == supported[j].a)
 | 
			
		||||
                {
 | 
			
		||||
                  prefered = atoms[i];
 | 
			
		||||
                  break;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          if (prefered != None)
 | 
			
		||||
          {
 | 
			
		||||
            XConvertSelection(X11_display, xselection->selection, prefered,
 | 
			
		||||
                    xselection->property, X11_window, CurrentTime);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        else if (count > 0)
 | 
			
		||||
        {
 | 
			
		||||
          X11_clipboard = malloc(count+1);
 | 
			
		||||
          if (X11_clipboard != NULL)
 | 
			
		||||
          {
 | 
			
		||||
            int i;
 | 
			
		||||
            X11_clipboard_size = count;
 | 
			
		||||
            X11_clipboard_type = X11_CLIPBOARD_UNKNOWN;
 | 
			
		||||
            for (i = 0; supported[i].a != None; i++)
 | 
			
		||||
            {
 | 
			
		||||
              if (supported[i].a == xselection->target)
 | 
			
		||||
              {
 | 
			
		||||
                X11_clipboard_type = supported[i].t;
 | 
			
		||||
                break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            memcpy(X11_clipboard, value, count);
 | 
			
		||||
            X11_clipboard[count] = '\0';
 | 
			
		||||
          }
 | 
			
		||||
          else
 | 
			
		||||
          {
 | 
			
		||||
            X11_clipboard_type = X11_CLIPBOARD_NONE;
 | 
			
		||||
            X11_clipboard_size = 0;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        XFree(value);
 | 
			
		||||
@ -632,8 +695,13 @@ static int Handle_SelectionNotify(const XSelectionEvent* xselection)
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    char * selection_name = XGetAtomName(X11_display, xselection->selection);
 | 
			
		||||
    GFX2_Log(GFX2_INFO, "Unhandled SelectNotify selection=%s\n", selection_name);
 | 
			
		||||
    char * property_name = "None";
 | 
			
		||||
    if (xselection->property != None)
 | 
			
		||||
      XGetAtomName(X11_display, xselection->property);
 | 
			
		||||
    GFX2_Log(GFX2_INFO, "Unhandled SelectNotify selection=%s property=%s\n", selection_name, property_name);
 | 
			
		||||
    XFree(selection_name);
 | 
			
		||||
    if (xselection->property != None)
 | 
			
		||||
      XFree(property_name);
 | 
			
		||||
  }
 | 
			
		||||
  return user_feedback_required;
 | 
			
		||||
}
 | 
			
		||||
@ -1570,7 +1638,9 @@ int Get_input(int sleep_time)
 | 
			
		||||
                  if (X11_clipboard)
 | 
			
		||||
                  {
 | 
			
		||||
                    free(X11_clipboard);
 | 
			
		||||
                    X11_clipboard = NULL;
 | 
			
		||||
                    X11_clipboard_size = 0;
 | 
			
		||||
                    X11_clipboard_type = X11_CLIPBOARD_NONE;
 | 
			
		||||
                  }
 | 
			
		||||
                  SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 | 
			
		||||
                  break;
 | 
			
		||||
@ -1965,7 +2035,9 @@ int Get_input(int sleep_time)
 | 
			
		||||
          if (X11_clipboard)
 | 
			
		||||
          {
 | 
			
		||||
            free(X11_clipboard);
 | 
			
		||||
            X11_clipboard = NULL;
 | 
			
		||||
            X11_clipboard_size = 0;
 | 
			
		||||
            X11_clipboard_type = X11_CLIPBOARD_NONE;
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case SelectionRequest:
 | 
			
		||||
 | 
			
		||||
@ -77,10 +77,19 @@ extern char * Drop_file_name;
 | 
			
		||||
extern word * Drop_file_name_unicode;
 | 
			
		||||
 | 
			
		||||
#if defined(USE_X11) || (defined(SDL_VIDEO_DRIVER_X11) && !defined(NO_X11))
 | 
			
		||||
enum X11_CLIPBOARD_TYPES {
 | 
			
		||||
  X11_CLIPBOARD_NONE,
 | 
			
		||||
  X11_CLIPBOARD_UNKNOWN,
 | 
			
		||||
  X11_CLIPBOARD_PNG,
 | 
			
		||||
  X11_CLIPBOARD_TIFF,
 | 
			
		||||
  X11_CLIPBOARD_URILIST,
 | 
			
		||||
  X11_CLIPBOARD_UTF8STRING
 | 
			
		||||
};
 | 
			
		||||
///
 | 
			
		||||
/// malloc'ed copy of the X11 clipboard
 | 
			
		||||
extern char * X11_clipboard;
 | 
			
		||||
extern unsigned long X11_clipboard_size;
 | 
			
		||||
extern enum X11_CLIPBOARD_TYPES X11_clipboard_type;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1485,18 +1485,27 @@ static void Load_ClipBoard_Image(T_IO_Context * context)
 | 
			
		||||
  selection = XInternAtom(X11_display, "CLIPBOARD", False);
 | 
			
		||||
  selection_owner = XGetSelectionOwner(X11_display, selection);
 | 
			
		||||
  if (selection_owner == None)
 | 
			
		||||
  {
 | 
			
		||||
    GFX2_Log(GFX2_INFO, "No owner for the X11 \"CLIPBOARD\" selection\n");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
#if defined(USE_SDL) || defined(USE_SDL2)
 | 
			
		||||
  // Enable processing of X11 events
 | 
			
		||||
  old_wmevent_state = SDL_EventState(SDL_SYSWMEVENT, SDL_QUERY);
 | 
			
		||||
  SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef __no_pnglib__
 | 
			
		||||
  XConvertSelection(X11_display, selection, XInternAtom(X11_display, "image/png"/*"PIXMAP"*/, False),
 | 
			
		||||
  // "TARGETS" is a special content type. The selection owner will
 | 
			
		||||
  // respond with a list of supported type. We will then choose our
 | 
			
		||||
  // prefered type and ask for it.
 | 
			
		||||
  // see Handle_SelectionNotify()
 | 
			
		||||
  // We could ask directly for "image/png" or "image/tiff" but that is
 | 
			
		||||
  // not sure this is supported by the selection owner.
 | 
			
		||||
  XConvertSelection(X11_display, selection, XInternAtom(X11_display, "TARGETS", False),
 | 
			
		||||
                    XInternAtom(X11_display, "GFX2_CLIP", False), /* Property */
 | 
			
		||||
                    X11_window, CurrentTime);
 | 
			
		||||
  // wait for the event to be received
 | 
			
		||||
  for(i = 0; X11_clipboard == NULL && i < 10; i++)
 | 
			
		||||
  // wait for the event to be received. 500ms maximum
 | 
			
		||||
  for(i = 0; X11_clipboard == NULL && i < 25; i++)
 | 
			
		||||
  {
 | 
			
		||||
    Get_input(20);
 | 
			
		||||
  }
 | 
			
		||||
@ -1504,24 +1513,39 @@ static void Load_ClipBoard_Image(T_IO_Context * context)
 | 
			
		||||
  SDL_EventState(SDL_SYSWMEVENT, old_wmevent_state);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (X11_clipboard != NULL)
 | 
			
		||||
  switch(X11_clipboard_type)
 | 
			
		||||
  {
 | 
			
		||||
    if (png_sig_cmp((byte *)X11_clipboard, 0, 8) == 0)
 | 
			
		||||
    {
 | 
			
		||||
      File_error = 0;
 | 
			
		||||
      Load_PNG_Sub(context, NULL, X11_clipboard, X11_clipboard_size);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      GFX2_Log(GFX2_WARNING, "Clipboard content not in PNG format\n");
 | 
			
		||||
    }
 | 
			
		||||
    free(X11_clipboard);
 | 
			
		||||
    X11_clipboard = NULL;
 | 
			
		||||
    X11_clipboard_size = 0;
 | 
			
		||||
  }
 | 
			
		||||
#else
 | 
			
		||||
  GFX2_Log(GFX2_ERROR, "Need PNG support for X11 image copy/paste\n");
 | 
			
		||||
    case X11_CLIPBOARD_NONE:
 | 
			
		||||
      GFX2_Log(GFX2_INFO, "Unable to retrieve X11 \"CLIPBOARD\" selection in a supported format. X11_clipboard=%p\n", X11_clipboard);
 | 
			
		||||
      break;
 | 
			
		||||
#ifndef __no_pnglib__
 | 
			
		||||
    case X11_CLIPBOARD_PNG:
 | 
			
		||||
      if (png_sig_cmp((byte *)X11_clipboard, 0, 8) == 0)
 | 
			
		||||
      {
 | 
			
		||||
        File_error = 0;
 | 
			
		||||
        Load_PNG_Sub(context, NULL, X11_clipboard, X11_clipboard_size);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
        GFX2_Log(GFX2_WARNING, "Failed to load PNG Clipboard\n");
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef __no_tifflib__
 | 
			
		||||
    case X11_CLIPBOARD_TIFF:
 | 
			
		||||
      Load_TIFF_from_memory(context, X11_clipboard, X11_clipboard_size);
 | 
			
		||||
      if (File_error != 0)
 | 
			
		||||
        GFX2_Log(GFX2_WARNING, "Failed to load TIFF Clipboard\n");
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
    // TODO
 | 
			
		||||
    case X11_CLIPBOARD_UTF8STRING:
 | 
			
		||||
    case X11_CLIPBOARD_URILIST:
 | 
			
		||||
    default:
 | 
			
		||||
      GFX2_Log(GFX2_WARNING, "Unsupported Clipboard format %d\n", (int)X11_clipboard_type);
 | 
			
		||||
  }
 | 
			
		||||
  free(X11_clipboard);
 | 
			
		||||
  X11_clipboard = NULL;
 | 
			
		||||
  X11_clipboard_size = 0;
 | 
			
		||||
  X11_clipboard_type = X11_CLIPBOARD_NONE;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
  GFX2_Log(GFX2_ERROR, "Load_ClipBoard_Image() not implemented on this platform yet\n");
 | 
			
		||||
 | 
			
		||||
@ -488,6 +488,7 @@ bye:
 | 
			
		||||
      char * utf8_str = X11_clipboard;
 | 
			
		||||
      X11_clipboard = NULL;
 | 
			
		||||
      X11_clipboard_size = 0;
 | 
			
		||||
      X11_clipboard_type = X11_CLIPBOARD_NONE;
 | 
			
		||||
  #else
 | 
			
		||||
  {
 | 
			
		||||
    // mac OS without X11
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user