SDL/x11 : make Copy/Paste and Drag&Drop work
This commit is contained in:
		
							parent
							
								
									8ec57abf88
								
							
						
					
					
						commit
						d7c6193c21
					
				@ -511,9 +511,11 @@ endif
 | 
				
			|||||||
        LOPT = -lm
 | 
					        LOPT = -lm
 | 
				
			||||||
        ifeq ($(API),sdl)
 | 
					        ifeq ($(API),sdl)
 | 
				
			||||||
          LOPT += $(shell sdl-config --libs) -lSDL_image
 | 
					          LOPT += $(shell sdl-config --libs) -lSDL_image
 | 
				
			||||||
 | 
					          LOPT += -lX11
 | 
				
			||||||
        endif
 | 
					        endif
 | 
				
			||||||
        ifeq ($(API),sdl2)
 | 
					        ifeq ($(API),sdl2)
 | 
				
			||||||
          LOPT += $(shell sdl2-config --libs) -lSDL2_image
 | 
					          LOPT += $(shell sdl2-config --libs) -lSDL2_image
 | 
				
			||||||
 | 
					          LOPT += -lX11
 | 
				
			||||||
        endif
 | 
					        endif
 | 
				
			||||||
        LOPT += $(TTFLOPT)
 | 
					        LOPT += $(TTFLOPT)
 | 
				
			||||||
        LOPT += $(shell pkg-config --libs libpng)
 | 
					        LOPT += $(shell pkg-config --libs libpng)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										356
									
								
								src/input.c
									
									
									
									
									
								
							
							
						
						
									
										356
									
								
								src/input.c
									
									
									
									
									
								
							@ -83,7 +83,7 @@ int Snap_axis_origin_Y;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
char * Drop_file_name = NULL;
 | 
					char * Drop_file_name = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(USE_X11)
 | 
					#if defined(USE_X11) || defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
char * X11_clipboard = NULL;
 | 
					char * X11_clipboard = NULL;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -319,6 +319,182 @@ int Move_cursor_with_constraints()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// WM events management
 | 
					// WM events management
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(USE_X11) || defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					static int xdnd_version = 5;
 | 
				
			||||||
 | 
					static Window xdnd_source = None;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void Handle_ClientMessage(const XClientMessageEvent * xclient)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					  Display * X11_display;
 | 
				
			||||||
 | 
					  Window X11_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!GFX2_Get_X11_Display_Window(&X11_display, &X11_window))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_ERROR, "Failed to get X11 display and window\n");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (xclient->message_type == XInternAtom(X11_display, "XdndEnter", False))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    //int list = xclient->data.l[1] & 1;
 | 
				
			||||||
 | 
					    xdnd_version = xclient->data.l[1] >> 24;
 | 
				
			||||||
 | 
					    xdnd_source = xclient->data.l[0];
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_DEBUG, "XdndEnter version=%d source=%lu\n", xdnd_version, xdnd_source);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (xclient->message_type == XInternAtom(X11_display, "XdndLeave", False))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_DEBUG, "XdndLeave\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (xclient->message_type == XInternAtom(X11_display, "XdndPosition", False))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    XEvent reply;
 | 
				
			||||||
 | 
					    int x_abs, y_abs;
 | 
				
			||||||
 | 
					    int x_pos, y_pos;
 | 
				
			||||||
 | 
					    Window root_window, child;
 | 
				
			||||||
 | 
					    unsigned int width, height;
 | 
				
			||||||
 | 
					    unsigned int border_width, depth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    x_abs = (xclient->data.l[2] >> 16) & 0xffff;
 | 
				
			||||||
 | 
					    y_abs = xclient->data.l[2] & 0xffff;
 | 
				
			||||||
 | 
					    // reply with XdndStatus
 | 
				
			||||||
 | 
					    // see https://github.com/glfw/glfw/blob/a9a5a0b016215b4e40a19acb69577d91cf21a563/src/x11_window.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(&reply, 0, sizeof(reply));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reply.type = ClientMessage;
 | 
				
			||||||
 | 
					    reply.xclient.window = xclient->data.l[0]; // drag & drop source window
 | 
				
			||||||
 | 
					    reply.xclient.message_type = XInternAtom(X11_display, "XdndStatus", False);
 | 
				
			||||||
 | 
					    reply.xclient.format = 32;
 | 
				
			||||||
 | 
					    reply.xclient.data.l[0] = xclient->window;
 | 
				
			||||||
 | 
					    if (XGetGeometry(X11_display, X11_window, &root_window, &x_pos, &y_pos, &width, &height, &border_width, &depth)
 | 
				
			||||||
 | 
					        && XTranslateCoordinates(X11_display, X11_window, root_window, 0, 0, &x_abs, &y_abs, &child))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      reply.xclient.data.l[2] = (x_abs & 0xffff) << 16 | (y_abs & 0xffff);
 | 
				
			||||||
 | 
					      reply.xclient.data.l[3] = (width & 0xffff) << 16 | (height & 0xffff);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reply that we are ready to copy the dragged data
 | 
				
			||||||
 | 
					    reply.xclient.data.l[1] = 1; // Accept with no rectangle
 | 
				
			||||||
 | 
					    if (xdnd_version >= 2)
 | 
				
			||||||
 | 
					      reply.xclient.data.l[4] = XInternAtom(X11_display, "XdndActionCopy", False);
 | 
				
			||||||
 | 
					    XSendEvent(X11_display, xclient->data.l[0], False, NoEventMask, &reply);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (xclient->message_type == XInternAtom(X11_display, "XdndDrop", False))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    Atom selection = XInternAtom(X11_display, "XdndSelection", False);
 | 
				
			||||||
 | 
					    Time time = CurrentTime;
 | 
				
			||||||
 | 
					    if (xdnd_version >= 1)
 | 
				
			||||||
 | 
					      time = xclient->data.l[2];
 | 
				
			||||||
 | 
					    XConvertSelection(X11_display,
 | 
				
			||||||
 | 
					        selection,
 | 
				
			||||||
 | 
					        XInternAtom(X11_display, "text/uri-list", False),
 | 
				
			||||||
 | 
					        selection,
 | 
				
			||||||
 | 
					        xclient->window,
 | 
				
			||||||
 | 
					        time);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_INFO, "Unhandled ClientMessage message_type=\"%s\"\n", XGetAtomName(X11_display, xclient->message_type));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int Handle_SelectionNotify(const XSelectionEvent* xselection)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int user_feedback_required = 0;
 | 
				
			||||||
 | 
					  Atom type = 0;
 | 
				
			||||||
 | 
					  int format = 0;
 | 
				
			||||||
 | 
					#if defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					  Display * X11_display;
 | 
				
			||||||
 | 
					  Window X11_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!GFX2_Get_X11_Display_Window(&X11_display, &X11_window))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_ERROR, "Failed to get X11 display and window\n");
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (xselection->property == XInternAtom(X11_display, "XdndSelection", False))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    int r;
 | 
				
			||||||
 | 
					    unsigned long count = 0, bytesAfter = 0;
 | 
				
			||||||
 | 
					    unsigned char * value = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    r = XGetWindowProperty(X11_display, xselection->requestor, xselection->property, 0, LONG_MAX,
 | 
				
			||||||
 | 
					                           False, xselection->target /* type */, &type, &format,
 | 
				
			||||||
 | 
					                           &count, &bytesAfter, &value);
 | 
				
			||||||
 | 
					    if (r == Success && value != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (format == 8)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        int i, j;
 | 
				
			||||||
 | 
					        Drop_file_name = malloc(count + 1);
 | 
				
			||||||
 | 
					        i = 0; j = 0;
 | 
				
			||||||
 | 
					        if (count > 7 && 0 == memcmp(value, "file://", 7))
 | 
				
			||||||
 | 
					          i = 7;
 | 
				
			||||||
 | 
					        while (i < (int)count && value[i] != 0 && value[i] != '\n' && value[i] != '\r')
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          if (i < ((int)count + 2) && value[i] == '%')
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            // URI-Decode : "%NN" to char of value 0xNN
 | 
				
			||||||
 | 
					            i++;
 | 
				
			||||||
 | 
					            Drop_file_name[j] = (value[i] - ((value[i] >= 'A') ? 'A' - 10 : '0')) << 4;
 | 
				
			||||||
 | 
					            i++;
 | 
				
			||||||
 | 
					            Drop_file_name[j++] |= (value[i] - ((value[i] >= 'A') ? 'A' - 10 : '0'));
 | 
				
			||||||
 | 
					            i++;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          else
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            Drop_file_name[j++] = (char)value[i++];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Drop_file_name[j++] = '\0';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      XFree(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (xdnd_version >= 2)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      XEvent reply;
 | 
				
			||||||
 | 
					      memset(&reply, 0, sizeof(reply));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      reply.type = ClientMessage;
 | 
				
			||||||
 | 
					      reply.xclient.window = xdnd_source;
 | 
				
			||||||
 | 
					      reply.xclient.message_type = XInternAtom(X11_display, "XdndFinished", False);
 | 
				
			||||||
 | 
					      reply.xclient.format = 32;
 | 
				
			||||||
 | 
					      reply.xclient.data.l[0] = X11_window;
 | 
				
			||||||
 | 
					      reply.xclient.data.l[1] = 1;  // success
 | 
				
			||||||
 | 
					      reply.xclient.data.l[2] = XInternAtom(X11_display, "XdndActionCopy", False);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      XSendEvent(X11_display, xdnd_source, False, NoEventMask, &reply);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (xselection->selection == XInternAtom(X11_display, "CLIPBOARD", False)
 | 
				
			||||||
 | 
					      || xselection->selection == XInternAtom(X11_display, "PRIMARY", False))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    int r;
 | 
				
			||||||
 | 
					    unsigned long count = 0, bytesAfter = 0;
 | 
				
			||||||
 | 
					    unsigned char * value = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    r = XGetWindowProperty(X11_display, X11_window, xselection->property, 0, LONG_MAX,
 | 
				
			||||||
 | 
					        False, xselection->target /* type */, &type, &format,
 | 
				
			||||||
 | 
					        &count, &bytesAfter, &value);
 | 
				
			||||||
 | 
					    if (r == Success && value != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      X11_clipboard = strdup((char *)value);
 | 
				
			||||||
 | 
					      XFree(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    user_feedback_required = 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    GFX2_Log(GFX2_INFO, "Unhandled SelectNotify selection=%s\n", XGetAtomName(X11_display, xselection->selection));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return user_feedback_required;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(USE_SDL)
 | 
					#if defined(USE_SDL)
 | 
				
			||||||
void Handle_window_resize(SDL_ResizeEvent event)
 | 
					void Handle_window_resize(SDL_ResizeEvent event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -945,6 +1121,10 @@ int Get_input(int sleep_time)
 | 
				
			|||||||
      switch(event.type)
 | 
					      switch(event.type)
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
#if defined(USE_SDL)
 | 
					#if defined(USE_SDL)
 | 
				
			||||||
 | 
					          case SDL_ACTIVEEVENT:
 | 
				
			||||||
 | 
					              GFX2_Log(GFX2_DEBUG, "SDL_ACTIVEEVENT gain=%d state=%d\n", event.active.gain, event.active.state);
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          case SDL_VIDEORESIZE:
 | 
					          case SDL_VIDEORESIZE:
 | 
				
			||||||
              Handle_window_resize(event.resize);
 | 
					              Handle_window_resize(event.resize);
 | 
				
			||||||
              user_feedback_required = 1;
 | 
					              user_feedback_required = 1;
 | 
				
			||||||
@ -1111,8 +1291,38 @@ int Get_input(int sleep_time)
 | 
				
			|||||||
                  // Drop of zero files. Thanks for the information, Bill.
 | 
					                  // Drop of zero files. Thanks for the information, Bill.
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
 | 
					#elif defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					#if defined(USE_SDL)
 | 
				
			||||||
 | 
					#define xevent event.syswm.msg->event.xevent
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
              GFX2_Log(GFX2_DEBUG, "Unhandled SDL_SYSWMEVENT\n");
 | 
					#define xevent event.syswm.msg->msg.x11.event
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					              switch (xevent.type)
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                case ClientMessage:
 | 
				
			||||||
 | 
					                  Handle_ClientMessage(&(xevent.xclient));
 | 
				
			||||||
 | 
					                  break;
 | 
				
			||||||
 | 
					                case SelectionNotify:
 | 
				
			||||||
 | 
					                  if (Handle_SelectionNotify(&(xevent.xselection)))
 | 
				
			||||||
 | 
					                    user_feedback_required = 1;
 | 
				
			||||||
 | 
					                  break;
 | 
				
			||||||
 | 
					                case ButtonPress:
 | 
				
			||||||
 | 
					                case ButtonRelease:
 | 
				
			||||||
 | 
					                case MotionNotify:
 | 
				
			||||||
 | 
					                  // ignore
 | 
				
			||||||
 | 
					                  break;
 | 
				
			||||||
 | 
					                case GenericEvent:
 | 
				
			||||||
 | 
					                  GFX2_Log(GFX2_DEBUG, "SDL_SYSWMEVENT x11 GenericEvent extension=%d evtype=%d\n",
 | 
				
			||||||
 | 
					                           xevent.xgeneric.extension,
 | 
				
			||||||
 | 
					                           xevent.xgeneric.evtype);
 | 
				
			||||||
 | 
					                  break;
 | 
				
			||||||
 | 
					                case PropertyNotify:
 | 
				
			||||||
 | 
					                  GFX2_Log(GFX2_DEBUG, "SDL_SYSWMEVENT x11 PropertyNotify\n");
 | 
				
			||||||
 | 
					                  break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                  GFX2_Log(GFX2_DEBUG, "Unhandled SDL_SYSWMEVENT x11 event type=%d\n", xevent.type);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					#undef xevent
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
              break;
 | 
					              break;
 | 
				
			||||||
          
 | 
					          
 | 
				
			||||||
@ -1255,8 +1465,6 @@ int Get_input(int sleep_time)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
#elif defined(USE_X11)
 | 
					#elif defined(USE_X11)
 | 
				
			||||||
    int user_feedback_required = 0; // Flag qui indique si on doit arrêter de traiter les évènements ou si on peut enchainer
 | 
					    int user_feedback_required = 0; // Flag qui indique si on doit arrêter de traiter les évènements ou si on peut enchainer
 | 
				
			||||||
    static int xdnd_version = 5;
 | 
					 | 
				
			||||||
    static Window xdnd_source = None;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Color_cycling();
 | 
					    Color_cycling();
 | 
				
			||||||
    // Commit any pending screen update.
 | 
					    // Commit any pending screen update.
 | 
				
			||||||
@ -1415,145 +1623,15 @@ int Get_input(int sleep_time)
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              // unrecognized WM event.
 | 
					              GFX2_Log(GFX2_INFO, "unrecognized WM event : %s\n", XGetAtomName(X11_display, (Atom)event.xclient.data.l[0]));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          else if (event.xclient.message_type == XInternAtom(X11_display, "XdndEnter", False))
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            //int list = event.xclient.data.l[1] & 1;
 | 
					 | 
				
			||||||
            xdnd_version = event.xclient.data.l[1] >> 24;
 | 
					 | 
				
			||||||
            xdnd_source = event.xclient.data.l[0];
 | 
					 | 
				
			||||||
            GFX2_Log(GFX2_DEBUG, "XdndEnter version=%d source=%lu\n", xdnd_version, xdnd_source);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          else if (event.xclient.message_type == XInternAtom(X11_display, "XdndLeave", False))
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            GFX2_Log(GFX2_DEBUG, "XdndLeave\n");
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          else if (event.xclient.message_type == XInternAtom(X11_display, "XdndPosition", False))
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            XEvent reply;
 | 
					 | 
				
			||||||
            int x_abs, y_abs;
 | 
					 | 
				
			||||||
            int x_pos, y_pos;
 | 
					 | 
				
			||||||
            Window root_window, child;
 | 
					 | 
				
			||||||
            unsigned int width, height;
 | 
					 | 
				
			||||||
            unsigned int border_width, depth;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            x_abs = (event.xclient.data.l[2] >> 16) & 0xffff;
 | 
					 | 
				
			||||||
            y_abs = event.xclient.data.l[2] & 0xffff;
 | 
					 | 
				
			||||||
            // reply with XdndStatus
 | 
					 | 
				
			||||||
            // see https://github.com/glfw/glfw/blob/a9a5a0b016215b4e40a19acb69577d91cf21a563/src/x11_window.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            memset(&reply, 0, sizeof(reply));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            reply.type = ClientMessage;
 | 
					 | 
				
			||||||
            reply.xclient.window = event.xclient.data.l[0]; // drag & drop source window
 | 
					 | 
				
			||||||
            reply.xclient.message_type = XInternAtom(X11_display, "XdndStatus", False);
 | 
					 | 
				
			||||||
            reply.xclient.format = 32;
 | 
					 | 
				
			||||||
            reply.xclient.data.l[0] = event.xclient.window;
 | 
					 | 
				
			||||||
            if (XGetGeometry(X11_display, X11_window, &root_window, &x_pos, &y_pos, &width, &height, &border_width, &depth)
 | 
					 | 
				
			||||||
              && XTranslateCoordinates(X11_display, X11_window, root_window, 0, 0, &x_abs, &y_abs, &child))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              reply.xclient.data.l[2] = (x_abs & 0xffff) << 16 | (y_abs & 0xffff);
 | 
					 | 
				
			||||||
              reply.xclient.data.l[3] = (width & 0xffff) << 16 | (height & 0xffff);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Reply that we are ready to copy the dragged data
 | 
					 | 
				
			||||||
            reply.xclient.data.l[1] = 1; // Accept with no rectangle
 | 
					 | 
				
			||||||
            if (xdnd_version >= 2)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              reply.xclient.data.l[4] = XInternAtom(X11_display, "XdndActionCopy", False);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            XSendEvent(X11_display, event.xclient.data.l[0], False, NoEventMask, &reply);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          else if (event.xclient.message_type == XInternAtom(X11_display, "XdndDrop", False))
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            Time time = CurrentTime;
 | 
					 | 
				
			||||||
            if (xdnd_version >= 1)
 | 
					 | 
				
			||||||
              time = event.xclient.data.l[2];
 | 
					 | 
				
			||||||
            XConvertSelection(X11_display,
 | 
					 | 
				
			||||||
                              XInternAtom(X11_display, "XdndSelection", False),
 | 
					 | 
				
			||||||
                              XInternAtom(X11_display, "text/uri-list", False),
 | 
					 | 
				
			||||||
                              XInternAtom(X11_display, "XdndSelection", False),
 | 
					 | 
				
			||||||
                              event.xclient.window,
 | 
					 | 
				
			||||||
                              time);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        case SelectionNotify:
 | 
					 | 
				
			||||||
          if (event.xselection.property == XInternAtom(X11_display, "XdndSelection", False))
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            Atom type = 0;
 | 
					 | 
				
			||||||
            int format = 0;
 | 
					 | 
				
			||||||
            int r;
 | 
					 | 
				
			||||||
            unsigned long count = 0, bytesAfter = 0;
 | 
					 | 
				
			||||||
            unsigned char * value = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            r = XGetWindowProperty(X11_display, event.xselection.requestor, event.xselection.property, 0, LONG_MAX,
 | 
					 | 
				
			||||||
                                   False, event.xselection.target /* type */, &type, &format,
 | 
					 | 
				
			||||||
                                   &count, &bytesAfter, &value);
 | 
					 | 
				
			||||||
            if (r == Success && value != NULL)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              if (format == 8)
 | 
					 | 
				
			||||||
              {
 | 
					 | 
				
			||||||
                int i, j;
 | 
					 | 
				
			||||||
                Drop_file_name = malloc(count + 1);
 | 
					 | 
				
			||||||
                i = 0; j = 0;
 | 
					 | 
				
			||||||
                if (count > 7 && 0 == memcmp(value, "file://", 7))
 | 
					 | 
				
			||||||
                  i = 7;
 | 
					 | 
				
			||||||
                while (i < (int)count && value[i] != 0 && value[i] != '\n' && value[i] != '\r')
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                  if (i < ((int)count + 2) && value[i] == '%')
 | 
					 | 
				
			||||||
                  {
 | 
					 | 
				
			||||||
                    // URI-Decode : "%NN" to char of value 0xNN
 | 
					 | 
				
			||||||
                    i++;
 | 
					 | 
				
			||||||
                    Drop_file_name[j] = (value[i] - ((value[i] >= 'A') ? 'A' - 10 : '0')) << 4;
 | 
					 | 
				
			||||||
                    i++;
 | 
					 | 
				
			||||||
                    Drop_file_name[j++] |= (value[i] - ((value[i] >= 'A') ? 'A' - 10 : '0'));
 | 
					 | 
				
			||||||
                    i++;
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
          else
 | 
					          else
 | 
				
			||||||
                  {
 | 
					            Handle_ClientMessage(&event.xclient);
 | 
				
			||||||
                    Drop_file_name[j++] = (char)value[i++];
 | 
					          break;
 | 
				
			||||||
                  }
 | 
					        case SelectionNotify:
 | 
				
			||||||
                }
 | 
					          if (Handle_SelectionNotify(&event.xselection))
 | 
				
			||||||
                Drop_file_name[j++] = '\0';
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
              XFree(value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (xdnd_version >= 2)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              XEvent reply;
 | 
					 | 
				
			||||||
              memset(&reply, 0, sizeof(reply));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              reply.type = ClientMessage;
 | 
					 | 
				
			||||||
              reply.xclient.window = xdnd_source;
 | 
					 | 
				
			||||||
              reply.xclient.message_type = XInternAtom(X11_display, "XdndFinished", False);
 | 
					 | 
				
			||||||
              reply.xclient.format = 32;
 | 
					 | 
				
			||||||
              reply.xclient.data.l[0] = X11_window;
 | 
					 | 
				
			||||||
              reply.xclient.data.l[1] = 1;  // success
 | 
					 | 
				
			||||||
              reply.xclient.data.l[2] = XInternAtom(X11_display, "XdndActionCopy", False);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              XSendEvent(X11_display, xdnd_source, False, NoEventMask, &reply);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          else if (event.xselection.selection == XInternAtom(X11_display, "CLIPBOARD", False)
 | 
					 | 
				
			||||||
                || event.xselection.selection == XInternAtom(X11_display, "PRIMARY", False))
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            Atom type = 0;
 | 
					 | 
				
			||||||
            int format = 0;
 | 
					 | 
				
			||||||
            int r;
 | 
					 | 
				
			||||||
            unsigned long count = 0, bytesAfter = 0;
 | 
					 | 
				
			||||||
            unsigned char * value = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            r = XGetWindowProperty(X11_display, X11_window, event.xselection.property, 0, LONG_MAX,
 | 
					 | 
				
			||||||
                                   False, event.xselection.target /* type */, &type, &format,
 | 
					 | 
				
			||||||
                                   &count, &bytesAfter, &value);
 | 
					 | 
				
			||||||
            if (r == Success && value != NULL)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              X11_clipboard = strdup((char *)value);
 | 
					 | 
				
			||||||
              XFree(value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            user_feedback_required = 1;
 | 
					            user_feedback_required = 1;
 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
          GFX2_Log(GFX2_INFO, "X11 event.type = %d not handled\n", event.type);
 | 
					          GFX2_Log(GFX2_INFO, "X11 event.type = %d not handled\n", event.type);
 | 
				
			||||||
 | 
				
			|||||||
@ -70,10 +70,12 @@
 | 
				
			|||||||
#include <X11/Xlib.h>
 | 
					#include <X11/Xlib.h>
 | 
				
			||||||
extern Display * X11_display;
 | 
					extern Display * X11_display;
 | 
				
			||||||
extern Window X11_window;
 | 
					extern Window X11_window;
 | 
				
			||||||
extern char * X11_clipboard;
 | 
					 | 
				
			||||||
#elif defined(__macosx__)
 | 
					#elif defined(__macosx__)
 | 
				
			||||||
const char * get_paste_board(void);
 | 
					const char * get_paste_board(void);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(USE_X11) || defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					extern char * X11_clipboard;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Virtual keyboard is ON by default on these platforms:
 | 
					// Virtual keyboard is ON by default on these platforms:
 | 
				
			||||||
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(GCWZERO)
 | 
					#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(GCWZERO)
 | 
				
			||||||
@ -407,7 +409,7 @@ bye:
 | 
				
			|||||||
  if (unicode)
 | 
					  if (unicode)
 | 
				
			||||||
    *unicode = NULL;
 | 
					    *unicode = NULL;
 | 
				
			||||||
  return haiku_get_clipboard();
 | 
					  return haiku_get_clipboard();
 | 
				
			||||||
  #elif defined(USE_X11) || defined(__macosx__) || defined(USE_SDL2)
 | 
					  #elif defined(USE_X11) || defined(__macosx__) || defined(USE_SDL2) || (defined(USE_SDL) && defined(SDL_VIDEO_DRIVER_X11))
 | 
				
			||||||
  if (unicode)
 | 
					  if (unicode)
 | 
				
			||||||
    *unicode = NULL;
 | 
					    *unicode = NULL;
 | 
				
			||||||
    #if defined(USE_SDL2)
 | 
					    #if defined(USE_SDL2)
 | 
				
			||||||
@ -420,11 +422,24 @@ bye:
 | 
				
			|||||||
    char * utf8_str = SDL_GetClipboardText();
 | 
					    char * utf8_str = SDL_GetClipboardText();
 | 
				
			||||||
    if (utf8_str != NULL)
 | 
					    if (utf8_str != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    #elif defined(USE_X11)
 | 
					    #elif defined(USE_X11) || (defined(USE_SDL) && defined(SDL_VIDEO_DRIVER_X11))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    Atom selection = XInternAtom(X11_display, "CLIPBOARD", False);
 | 
					    Atom selection;
 | 
				
			||||||
    Window selection_owner = XGetSelectionOwner(X11_display, selection);
 | 
					    Window selection_owner;
 | 
				
			||||||
 | 
					#if defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					    Display * X11_display;
 | 
				
			||||||
 | 
					    Window X11_window;
 | 
				
			||||||
 | 
					    int old_wmevent_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!GFX2_Get_X11_Display_Window(&X11_display, &X11_window))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      GFX2_Log(GFX2_ERROR, "Failed to get X11 display and window\n");
 | 
				
			||||||
 | 
					      return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    selection = XInternAtom(X11_display, "CLIPBOARD", False);
 | 
				
			||||||
 | 
					    selection_owner = XGetSelectionOwner(X11_display, selection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (selection_owner == None)
 | 
					    if (selection_owner == None)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -433,6 +448,10 @@ bye:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if (selection_owner == None)
 | 
					    if (selection_owner == None)
 | 
				
			||||||
      return NULL;
 | 
					      return NULL;
 | 
				
			||||||
 | 
					#if defined(USE_SDL)
 | 
				
			||||||
 | 
					    old_wmevent_state = SDL_EventState(SDL_SYSWMEVENT, SDL_QUERY);
 | 
				
			||||||
 | 
					    SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    XConvertSelection(X11_display, selection, XInternAtom(X11_display, "UTF8_STRING", False),
 | 
					    XConvertSelection(X11_display, selection, XInternAtom(X11_display, "UTF8_STRING", False),
 | 
				
			||||||
                      XInternAtom(X11_display, "GFX2_CLIP", False), /* Property */
 | 
					                      XInternAtom(X11_display, "GFX2_CLIP", False), /* Property */
 | 
				
			||||||
@ -442,6 +461,9 @@ bye:
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
      Get_input(20);
 | 
					      Get_input(20);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					#if defined(USE_SDL)
 | 
				
			||||||
 | 
					    SDL_EventState(SDL_SYSWMEVENT, old_wmevent_state);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    if (X11_clipboard != NULL)
 | 
					    if (X11_clipboard != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      char * utf8_str = X11_clipboard;
 | 
					      char * utf8_str = X11_clipboard;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/screen.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/screen.h
									
									
									
									
									
								
							@ -32,6 +32,12 @@
 | 
				
			|||||||
#ifdef WIN32
 | 
					#ifdef WIN32
 | 
				
			||||||
#include <windows.h>  // for HWND
 | 
					#include <windows.h>  // for HWND
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(USE_SDL) || defined(USE_SDL2)
 | 
				
			||||||
 | 
					#include <SDL_syswm.h> // for Display, Window
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(USE_X11)
 | 
				
			||||||
 | 
					#include <X11/Xlib.h> // for Display, Window
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#include "struct.h"
 | 
					#include "struct.h"
 | 
				
			||||||
#include "global.h"
 | 
					#include "global.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -70,6 +76,10 @@ void GFX2_UpdateScreen(void);
 | 
				
			|||||||
HWND GFX2_Get_Window_Handle(void);
 | 
					HWND GFX2_Get_Window_Handle(void);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(USE_X11) || defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					int GFX2_Get_X11_Display_Window(Display * * display, Window * window);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Set application icon(s)
 | 
					/// Set application icon(s)
 | 
				
			||||||
void Define_icon(void);
 | 
					void Define_icon(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -530,8 +530,42 @@ HWND GFX2_Get_Window_Handle(void)
 | 
				
			|||||||
  SDL_SysWMinfo wminfo;
 | 
					  SDL_SysWMinfo wminfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SDL_VERSION(&wminfo.version);
 | 
					  SDL_VERSION(&wminfo.version);
 | 
				
			||||||
  SDL_GetWMInfo(&wminfo);
 | 
					#if defined(USE_SDL)
 | 
				
			||||||
 | 
					  if (SDL_GetWMInfo(&wminfo) <= 0)
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
  return wminfo.window;
 | 
					  return wminfo.window;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  if (Window_SDL == NULL)
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  if (!SDL_GetWindowWMInfo(Window_SDL, &wminfo))
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  return wminfo.info.win.window;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SDL_VIDEO_DRIVER_X11
 | 
				
			||||||
 | 
					int GFX2_Get_X11_Display_Window(Display * * display, Window * window)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SDL_SysWMinfo wminfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SDL_VERSION(&wminfo.version);
 | 
				
			||||||
 | 
					#if defined(USE_SDL)
 | 
				
			||||||
 | 
					  // SDL 1.x
 | 
				
			||||||
 | 
					  if (SDL_GetWMInfo(&wminfo) <= 0)
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  *display = wminfo.info.x11.display;
 | 
				
			||||||
 | 
					  *window = wminfo.info.x11.wmwindow;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  // SDL 2.x
 | 
				
			||||||
 | 
					  if (Window_SDL == NULL)
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  if (!SDL_GetWindowWMInfo(Window_SDL, &wminfo))
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  *display = wminfo.info.x11.display;
 | 
				
			||||||
 | 
					  *window = wminfo.info.x11.window;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -547,6 +581,18 @@ void Allow_drag_and_drop(int flag)
 | 
				
			|||||||
#ifdef __WIN32__
 | 
					#ifdef __WIN32__
 | 
				
			||||||
  DragAcceptFiles(GFX2_Get_Window_Handle(), flag?TRUE:FALSE);
 | 
					  DragAcceptFiles(GFX2_Get_Window_Handle(), flag?TRUE:FALSE);
 | 
				
			||||||
  SDL_EventState (SDL_SYSWMEVENT, flag?SDL_ENABLE:SDL_DISABLE);
 | 
					  SDL_EventState (SDL_SYSWMEVENT, flag?SDL_ENABLE:SDL_DISABLE);
 | 
				
			||||||
 | 
					#elif defined(SDL_VIDEO_DRIVER_X11)
 | 
				
			||||||
 | 
					  Atom version = flag ? 5 : 0;
 | 
				
			||||||
 | 
					  Display * display;
 | 
				
			||||||
 | 
					  Window window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (GFX2_Get_X11_Display_Window(&display, &window))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    XChangeProperty(display, window,
 | 
				
			||||||
 | 
					                    XInternAtom(display, "XdndAware", False),
 | 
				
			||||||
 | 
					                    XA_ATOM, 32, PropModeReplace, (unsigned char *)&version, 1);
 | 
				
			||||||
 | 
					    SDL_EventState (SDL_SYSWMEVENT, flag?SDL_ENABLE:SDL_DISABLE);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  (void)flag; // unused
 | 
					  (void)flag; // unused
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user