Copy support for X11
This commit is contained in:
parent
cd74f5da8d
commit
3e1d6b165d
@ -6236,7 +6236,7 @@ static int PNG_read_unknown_chunk(png_structp ptr, png_unknown_chunkp chunk)
|
|||||||
|
|
||||||
|
|
||||||
struct PNG_memory_buffer {
|
struct PNG_memory_buffer {
|
||||||
const char * buffer;
|
char * buffer;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
};
|
};
|
||||||
@ -6294,7 +6294,7 @@ void Load_PNG_Sub(T_IO_Context * context, FILE * file, const char * memory_buffe
|
|||||||
png_init_io(png_ptr, file);
|
png_init_io(png_ptr, file);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer.buffer = memory_buffer;
|
buffer.buffer = (char *)memory_buffer;
|
||||||
buffer.offset = 8; // skip header
|
buffer.offset = 8; // skip header
|
||||||
buffer.size = memory_buffer_size;
|
buffer.size = memory_buffer_size;
|
||||||
png_set_read_fn(png_ptr, &buffer, PNG_memory_read);
|
png_set_read_fn(png_ptr, &buffer, PNG_memory_read);
|
||||||
@ -6623,34 +6623,57 @@ void Load_PNG(T_IO_Context * context)
|
|||||||
File_error=1;
|
File_error=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save a PNG file
|
|
||||||
void Save_PNG(T_IO_Context * context)
|
static void PNG_memory_write(png_structp png_ptr, png_bytep p, png_size_t count)
|
||||||
{
|
{
|
||||||
FILE *file;
|
struct PNG_memory_buffer * buffer = (struct PNG_memory_buffer *)png_get_io_ptr(png_ptr);
|
||||||
|
GFX2_Log(GFX2_DEBUG, "PNG_memory_write(%p, %p, %u) (io_ptr=%p)\n", png_ptr, p, count, buffer);
|
||||||
|
if (buffer->size < buffer->offset + count)
|
||||||
|
{
|
||||||
|
char * tmp = realloc(buffer->buffer, buffer->offset + count + 1024);
|
||||||
|
if (tmp == NULL)
|
||||||
|
{
|
||||||
|
GFX2_Log(GFX2_ERROR, "PNG_memory_write() Failed to allocate %u bytes of memory\n", buffer->offset + count + 1024);
|
||||||
|
File_error = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer->buffer = tmp;
|
||||||
|
buffer->size = buffer->offset + count + 1024;
|
||||||
|
}
|
||||||
|
memcpy(buffer->buffer + buffer->offset, p, count);
|
||||||
|
buffer->offset += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PNG_memory_flush(png_structp png_ptr)
|
||||||
|
{
|
||||||
|
struct PNG_memory_buffer * buffer = (struct PNG_memory_buffer *)png_get_io_ptr(png_ptr);
|
||||||
|
GFX2_Log(GFX2_DEBUG, "PNG_memory_flush(%p) (io_ptr=%p)\n", png_ptr, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Save_PNG_Sub(T_IO_Context * context, FILE * file, char * * buffer, unsigned long * buffer_size)
|
||||||
|
{
|
||||||
|
static png_bytep * Row_pointers = NULL;
|
||||||
int y;
|
int y;
|
||||||
byte * pixel_ptr;
|
byte * pixel_ptr;
|
||||||
png_structp png_ptr;
|
png_structp png_ptr;
|
||||||
png_infop info_ptr;
|
png_infop info_ptr;
|
||||||
png_unknown_chunk crng_chunk;
|
png_unknown_chunk crng_chunk;
|
||||||
byte cycle_data[16*6]; // Storage for color-cycling data, referenced by crng_chunk
|
byte cycle_data[16*6]; // Storage for color-cycling data, referenced by crng_chunk
|
||||||
static png_bytep * Row_pointers;
|
struct PNG_memory_buffer memory_buffer;
|
||||||
|
|
||||||
File_error=0;
|
|
||||||
Row_pointers = NULL;
|
|
||||||
|
|
||||||
// Ouverture du fichier
|
|
||||||
if ((file=Open_file_write(context)))
|
|
||||||
{
|
|
||||||
setvbuf(file, NULL, _IOFBF, 64*1024);
|
|
||||||
|
|
||||||
/* initialisation */
|
/* initialisation */
|
||||||
if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))
|
if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))
|
||||||
&& (info_ptr = png_create_info_struct(png_ptr)))
|
&& (info_ptr = png_create_info_struct(png_ptr)))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!setjmp(png_jmpbuf(png_ptr)))
|
if (!setjmp(png_jmpbuf(png_ptr)))
|
||||||
{
|
{
|
||||||
|
if (file != NULL)
|
||||||
png_init_io(png_ptr, file);
|
png_init_io(png_ptr, file);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&memory_buffer, 0, sizeof(memory_buffer));
|
||||||
|
png_set_write_fn(png_ptr, &memory_buffer, PNG_memory_write, PNG_memory_flush);
|
||||||
|
}
|
||||||
|
|
||||||
/* en-tete */
|
/* en-tete */
|
||||||
if (!setjmp(png_jmpbuf(png_ptr)))
|
if (!setjmp(png_jmpbuf(png_ptr)))
|
||||||
@ -6663,15 +6686,14 @@ void Save_PNG(T_IO_Context * context)
|
|||||||
{
|
{
|
||||||
// Commentaires texte PNG
|
// Commentaires texte PNG
|
||||||
// Cette partie est optionnelle
|
// Cette partie est optionnelle
|
||||||
#ifdef PNG_iTXt_SUPPORTED
|
|
||||||
png_text text_ptr[2] = {
|
png_text text_ptr[2] = {
|
||||||
|
#ifdef PNG_iTXt_SUPPORTED
|
||||||
{-1, "Software", "Grafx2", 6, 0, NULL, NULL},
|
{-1, "Software", "Grafx2", 6, 0, NULL, NULL},
|
||||||
{-1, "Title", NULL, 0, 0, NULL, NULL}
|
{-1, "Title", NULL, 0, 0, NULL, NULL}
|
||||||
#else
|
#else
|
||||||
png_text text_ptr[2] = {
|
|
||||||
{-1, "Software", "Grafx2", 6},
|
{-1, "Software", "Grafx2", 6},
|
||||||
{-1, "Title", NULL, 0}
|
{-1, "Title", NULL, 0}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
int nb_text_chunks=1;
|
int nb_text_chunks=1;
|
||||||
if (context->Comment[0])
|
if (context->Comment[0])
|
||||||
@ -6797,20 +6819,34 @@ void Save_PNG(T_IO_Context * context)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
File_error=1;
|
File_error=1;
|
||||||
// fermeture du fichier
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser
|
|
||||||
// ce fichier pourri trainait... Ca fait pas propre.
|
|
||||||
if (File_error)
|
|
||||||
Remove_file(context);
|
|
||||||
|
|
||||||
if (Row_pointers)
|
if (Row_pointers)
|
||||||
{
|
|
||||||
free(Row_pointers);
|
free(Row_pointers);
|
||||||
Row_pointers=NULL;
|
if (memory_buffer.buffer)
|
||||||
|
{
|
||||||
|
*buffer = memory_buffer.buffer;
|
||||||
|
*buffer_size = memory_buffer.offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Save a PNG file
|
||||||
|
void Save_PNG(T_IO_Context * context)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
File_error = 0;
|
||||||
|
|
||||||
|
file = Open_file_write(context);
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
Save_PNG_Sub(context, file, NULL, NULL);
|
||||||
|
fclose(file);
|
||||||
|
// remove the file if there was an error
|
||||||
|
if (File_error)
|
||||||
|
Remove_file(context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
File_error = 1;
|
||||||
|
}
|
||||||
#endif // __no_pnglib__
|
#endif // __no_pnglib__
|
||||||
|
|
||||||
|
|||||||
@ -141,6 +141,7 @@ void Test_PNG(T_IO_Context *, FILE *);
|
|||||||
void Load_PNG(T_IO_Context *);
|
void Load_PNG(T_IO_Context *);
|
||||||
void Save_PNG(T_IO_Context *);
|
void Save_PNG(T_IO_Context *);
|
||||||
void Load_PNG_Sub(T_IO_Context * context, FILE * file, const char * memory_buffer, unsigned long memory_buffer_size);
|
void Load_PNG_Sub(T_IO_Context * context, FILE * file, const char * memory_buffer, unsigned long memory_buffer_size);
|
||||||
|
void Save_PNG_Sub(T_IO_Context * context, FILE * file, char * * buffer, unsigned long * buffer_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -- INFO (Amiga ICONS) ----------------------------------------------------
|
// -- INFO (Amiga ICONS) ----------------------------------------------------
|
||||||
|
|||||||
84
src/input.c
84
src/input.c
@ -38,6 +38,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "gfx2log.h"
|
#include "gfx2log.h"
|
||||||
@ -522,6 +523,60 @@ static int Handle_SelectionNotify(const XSelectionEvent* xselection)
|
|||||||
}
|
}
|
||||||
return user_feedback_required;
|
return user_feedback_required;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Handle_SelectionRequest(const XSelectionRequestEvent* xselectionrequest)
|
||||||
|
{
|
||||||
|
XSelectionEvent xselection;
|
||||||
|
char * target_name;
|
||||||
|
char * property_name;
|
||||||
|
Atom png;
|
||||||
|
#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
|
||||||
|
|
||||||
|
png = XInternAtom(X11_display, "image/png", False);
|
||||||
|
|
||||||
|
target_name = XGetAtomName(X11_display, xselectionrequest->target);
|
||||||
|
property_name = XGetAtomName(X11_display, xselectionrequest->property);
|
||||||
|
GFX2_Log(GFX2_DEBUG, "Handle_SelectionRequest target=%s property=%s\n", target_name, property_name);
|
||||||
|
XFree(target_name);
|
||||||
|
XFree(property_name);
|
||||||
|
|
||||||
|
xselection.type = SelectionNotify;
|
||||||
|
xselection.requestor = xselectionrequest->requestor;
|
||||||
|
xselection.selection = xselectionrequest->selection;
|
||||||
|
xselection.target = xselectionrequest->target;
|
||||||
|
xselection.property = xselectionrequest->property;
|
||||||
|
xselection.time = xselectionrequest->time;
|
||||||
|
|
||||||
|
if (xselectionrequest->target == XInternAtom(X11_display, "TARGETS", False))
|
||||||
|
{
|
||||||
|
Atom targets[1];
|
||||||
|
targets[0] = png;
|
||||||
|
XChangeProperty(X11_display, xselectionrequest->requestor, xselectionrequest->property,
|
||||||
|
XA_ATOM, 32, PropModeReplace,
|
||||||
|
(unsigned char *)targets, 1);
|
||||||
|
}
|
||||||
|
else if (xselectionrequest->target == png)
|
||||||
|
{
|
||||||
|
XChangeProperty(X11_display, xselectionrequest->requestor, xselectionrequest->property,
|
||||||
|
png, 8, PropModeReplace,
|
||||||
|
(unsigned char *)X11_clipboard, X11_clipboard_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xselection.property = None; // refuse
|
||||||
|
}
|
||||||
|
|
||||||
|
XSendEvent(X11_display, xselectionrequest->requestor, True, NoEventMask, (XEvent *)&xselection);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_SDL)
|
#if defined(USE_SDL)
|
||||||
@ -1351,6 +1406,18 @@ int Get_input(int sleep_time)
|
|||||||
if (Handle_SelectionNotify(&(xevent.xselection)))
|
if (Handle_SelectionNotify(&(xevent.xselection)))
|
||||||
user_feedback_required = 1;
|
user_feedback_required = 1;
|
||||||
break;
|
break;
|
||||||
|
case SelectionRequest:
|
||||||
|
Handle_SelectionRequest(&(xevent.xselectionrequest));
|
||||||
|
break;
|
||||||
|
case SelectionClear:
|
||||||
|
GFX2_Log(GFX2_DEBUG, "X11 SelectionClear\n");
|
||||||
|
if (X11_clipboard)
|
||||||
|
{
|
||||||
|
free(X11_clipboard);
|
||||||
|
X11_clipboard_size = 0;
|
||||||
|
}
|
||||||
|
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
||||||
|
break;
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
@ -1687,6 +1754,23 @@ int Get_input(int sleep_time)
|
|||||||
if (Handle_SelectionNotify(&event.xselection))
|
if (Handle_SelectionNotify(&event.xselection))
|
||||||
user_feedback_required = 1;
|
user_feedback_required = 1;
|
||||||
break;
|
break;
|
||||||
|
case SelectionClear:
|
||||||
|
GFX2_Log(GFX2_DEBUG, "X11 SelectionClear\n");
|
||||||
|
if (X11_clipboard)
|
||||||
|
{
|
||||||
|
free(X11_clipboard);
|
||||||
|
X11_clipboard_size = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SelectionRequest:
|
||||||
|
Handle_SelectionRequest(&event.xselectionrequest);
|
||||||
|
break;
|
||||||
|
case ReparentNotify:
|
||||||
|
GFX2_Log(GFX2_DEBUG, "X11 ReparentNotify\n");
|
||||||
|
break;
|
||||||
|
case MapNotify:
|
||||||
|
GFX2_Log(GFX2_DEBUG, "X11 MapNotify\n");
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1566,6 +1566,46 @@ static void Save_ClipBoard_Image(T_IO_Context * context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
#elif defined(USE_X11) || (defined(SDL_VIDEO_DRIVER_X11) && !defined(NO_X11))
|
||||||
|
Atom selection;
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
if (X11_display == NULL)
|
||||||
|
{
|
||||||
|
#if defined(USE_SDL)
|
||||||
|
char video_driver_name[32];
|
||||||
|
GFX2_Log(GFX2_WARNING, "X11 display is NULL. X11 is needed for Copy/Paste. SDL video driver is currently %s\n", SDL_VideoDriverName(video_driver_name, sizeof(video_driver_name)));
|
||||||
|
#elif defined(USE_SDL2)
|
||||||
|
GFX2_Log(GFX2_WARNING, "X11 display is NULL. X11 is needed for Copy/Paste. SDL video driver is currently %s\n", SDL_GetCurrentVideoDriver());
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
File_error = 0;
|
||||||
|
if (X11_clipboard != NULL)
|
||||||
|
{
|
||||||
|
free(X11_clipboard);
|
||||||
|
X11_clipboard = NULL;
|
||||||
|
X11_clipboard_size = 0;
|
||||||
|
}
|
||||||
|
Save_PNG_Sub(context, NULL, &X11_clipboard, &X11_clipboard_size);
|
||||||
|
if (!File_error)
|
||||||
|
{
|
||||||
|
#if defined(USE_SDL) || defined(USE_SDL2)
|
||||||
|
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
|
||||||
|
#endif
|
||||||
|
selection = XInternAtom(X11_display, "CLIPBOARD", False);
|
||||||
|
XSetSelectionOwner(X11_display, selection, X11_window, CurrentTime);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
GFX2_Log(GFX2_ERROR, "Save_ClipBoard_Image() not implemented on this platform yet\n");
|
GFX2_Log(GFX2_ERROR, "Save_ClipBoard_Image() not implemented on this platform yet\n");
|
||||||
File_error = 1;
|
File_error = 1;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user