Removes obsolete clipboard, replaces by platform-agnostic SDL2`s APIs. Refs D2476.
Patch By: linkmauve Tested By: bb, elexis, Stan This was SVN commit r23624.
This commit is contained in:
parent
f558dbbd6f
commit
76909984b2
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -24,7 +24,6 @@
|
||||
#include "graphics/TextRenderer.h"
|
||||
#include "gui/CGUI.h"
|
||||
#include "gui/CGUIScrollBarVertical.h"
|
||||
#include "lib/sysdep/clipboard.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/utf8.h"
|
||||
#include "ps/ConfigDB.h"
|
||||
@ -600,29 +599,30 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev)
|
||||
|
||||
m_WantedX = 0.0f;
|
||||
|
||||
wchar_t* text = sys_clipboard_get();
|
||||
if (text)
|
||||
{
|
||||
if (SelectingText())
|
||||
DeleteCurSelection();
|
||||
char* utf8_text = SDL_GetClipboardText();
|
||||
if (!utf8_text)
|
||||
return IN_HANDLED;
|
||||
|
||||
if (m_iBufferPos == static_cast<int>(m_Caption.length()))
|
||||
m_Caption += text;
|
||||
else
|
||||
m_Caption =
|
||||
m_Caption.Left(m_iBufferPos) + text +
|
||||
m_Caption.Right(static_cast<long>(m_Caption.length()) - m_iBufferPos);
|
||||
std::wstring text = wstring_from_utf8(utf8_text);
|
||||
SDL_free(utf8_text);
|
||||
|
||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1);
|
||||
if (SelectingText())
|
||||
DeleteCurSelection();
|
||||
|
||||
m_iBufferPos += (int)wcslen(text);
|
||||
UpdateAutoScroll();
|
||||
UpdateBufferPositionSetting();
|
||||
if (m_iBufferPos == static_cast<int>(m_Caption.length()))
|
||||
m_Caption += text;
|
||||
else
|
||||
m_Caption =
|
||||
m_Caption.Left(m_iBufferPos) + text +
|
||||
m_Caption.Right(static_cast<long>(m_Caption.length()) - m_iBufferPos);
|
||||
|
||||
sys_clipboard_free(text);
|
||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1);
|
||||
|
||||
SendEvent(GUIM_TEXTEDIT, EventNameTextEdit);
|
||||
}
|
||||
m_iBufferPos += static_cast<int>(text.size());
|
||||
UpdateAutoScroll();
|
||||
UpdateBufferPositionSetting();
|
||||
|
||||
SendEvent(GUIM_TEXTEDIT, EventNameTextEdit);
|
||||
|
||||
return IN_HANDLED;
|
||||
}
|
||||
@ -651,7 +651,7 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev)
|
||||
|
||||
CStrW text = m_Caption.Left(virtualTo).Right(virtualTo - virtualFrom);
|
||||
|
||||
sys_clipboard_set(&text[0]);
|
||||
SDL_SetClipboardText(text.ToUTF8().c_str());
|
||||
|
||||
if (hotkey == "cut")
|
||||
{
|
||||
|
@ -1,38 +0,0 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_SYSDEP_CLIPBOARD
|
||||
#define INCLUDED_SYSDEP_CLIPBOARD
|
||||
|
||||
// "copy" text into the clipboard. replaces previous contents.
|
||||
extern Status sys_clipboard_set(const wchar_t* text);
|
||||
|
||||
// allow "pasting" from clipboard.
|
||||
// @return current clipboard text or 0 if not representable as text.
|
||||
// callers are responsible for passing this pointer to sys_clipboard_free.
|
||||
extern wchar_t* sys_clipboard_get();
|
||||
|
||||
// free memory returned by sys_clipboard_get.
|
||||
// @param copy is ignored if 0.
|
||||
extern Status sys_clipboard_free(wchar_t* copy);
|
||||
|
||||
#endif // #ifndef INCLUDED_SYSDEP_CLIPBOARD
|
@ -26,21 +26,6 @@
|
||||
|
||||
#include "lib/external_libraries/libsdl.h"
|
||||
|
||||
Status sys_clipboard_set(const wchar_t* UNUSED(text))
|
||||
{
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
wchar_t* sys_clipboard_get()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status sys_clipboard_free(wchar_t* UNUSED(copy))
|
||||
{
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
namespace gfx {
|
||||
|
||||
Status GetVideoMode(int* xres, int* yres, int* bpp, int* freq)
|
||||
|
@ -38,42 +38,6 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
Status sys_clipboard_set(const wchar_t* text)
|
||||
{
|
||||
Status ret = INFO::OK;
|
||||
|
||||
std::string str = utf8_from_wstring(text);
|
||||
bool ok = osx_SendStringToPasteboard(str);
|
||||
if (!ok)
|
||||
ret = ERR::FAIL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
wchar_t* sys_clipboard_get()
|
||||
{
|
||||
wchar_t* ret = NULL;
|
||||
std::string str;
|
||||
bool ok = osx_GetStringFromPasteboard(str);
|
||||
if (ok)
|
||||
{
|
||||
// TODO: this is yucky, why are we passing around wchar_t*?
|
||||
std::wstring wstr = wstring_from_utf8(str);
|
||||
size_t len = wcslen(wstr.c_str());
|
||||
ret = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
|
||||
std::copy(wstr.c_str(), wstr.c_str()+len, ret);
|
||||
ret[len] = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Status sys_clipboard_free(wchar_t* copy)
|
||||
{
|
||||
free(copy);
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
namespace gfx {
|
||||
|
||||
Status GetVideoMode(int* xres, int* yres, int* bpp, int* freq)
|
||||
@ -143,7 +107,6 @@ Status GetVideoMode(int* xres, int* yres, int* bpp, int* freq)
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
|
||||
OsPath sys_ExecutablePathname()
|
||||
{
|
||||
OsPath path;
|
||||
|
@ -1,47 +0,0 @@
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OSX_PASTEBOARD_H
|
||||
#define OSX_PASTEBOARD_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* C++ interface to Cocoa implementation for pasteboards
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get a string from the pasteboard
|
||||
*
|
||||
* @param[out] out pasteboard string in UTF-8 encoding, if found
|
||||
* @return true if string was found on pasteboard and successfully retrieved, false otherwise
|
||||
*/
|
||||
bool osx_GetStringFromPasteboard(std::string& out);
|
||||
|
||||
/**
|
||||
* Store a string on the pasteboard
|
||||
*
|
||||
* @param[in] string string to store in UTF-8 encoding
|
||||
* @return true if string was successfully sent to pasteboard, false on error
|
||||
*/
|
||||
bool osx_SendStringToPasteboard(const std::string& string);
|
||||
|
||||
#endif // OSX_PASTEBOARD_H
|
@ -1,95 +0,0 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <AvailabilityMacros.h> // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <string>
|
||||
|
||||
#import "osx_pasteboard.h"
|
||||
|
||||
bool osx_GetStringFromPasteboard(std::string& out)
|
||||
{
|
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSString* string = nil;
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
||||
// As of 10.6, pasteboards can hold multiple items
|
||||
if ([pasteboard respondsToSelector: @selector(readObjectsForClasses:)])
|
||||
{
|
||||
NSArray* classes = [NSArray arrayWithObjects:[NSString class], nil];
|
||||
NSDictionary* options = [NSDictionary dictionary];
|
||||
NSArray* copiedItems = [pasteboard readObjectsForClasses:classes options:options];
|
||||
// We only need to support a single item, so grab the first string
|
||||
if (copiedItems != nil && [copiedItems count] > 0)
|
||||
string = [copiedItems objectAtIndex:0];
|
||||
else
|
||||
return false; // No strings found on pasteboard
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif // fallback to 10.5 API
|
||||
// Verify that there is a string available for us
|
||||
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
|
||||
if ([pasteboard availableTypeFromArray:types] != nil)
|
||||
string = [pasteboard stringForType:NSStringPboardType];
|
||||
else
|
||||
return false; // No strings found on pasteboard
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
||||
}
|
||||
#endif
|
||||
|
||||
if (string != nil)
|
||||
out = std::string([string UTF8String]);
|
||||
else
|
||||
return false; // fail
|
||||
|
||||
return true; // success
|
||||
}
|
||||
|
||||
bool osx_SendStringToPasteboard(const std::string& string)
|
||||
{
|
||||
// We're only working with strings, so we don't need to lazily write
|
||||
// anything (otherwise we'd need to set up an owner and data provider)
|
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSString* type;
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
||||
if ([pasteboard respondsToSelector: @selector(clearContents)])
|
||||
{
|
||||
type = NSPasteboardTypeString;
|
||||
[pasteboard clearContents];
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif // fallback to 10.5 API
|
||||
type = NSStringPboardType;
|
||||
NSArray* types = [NSArray arrayWithObjects: type, nil];
|
||||
// Roughly equivalent to clearContents followed by addTypes:owner
|
||||
[pasteboard declareTypes:types owner:nil];
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// May raise a NSPasteboardCommunicationException
|
||||
BOOL ok = [pasteboard setString:[NSString stringWithUTF8String:string.c_str()] forType:type];
|
||||
return ok == YES;
|
||||
}
|
@ -113,242 +113,4 @@ static bool get_wminfo(SDL_SysWMinfo& wminfo)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Oh, boy, this is heavy stuff...
|
||||
|
||||
<User-End Stuff - Definitions and Conventions>
|
||||
http://www.freedesktop.org/standards/clipboards-spec/clipboards.txt
|
||||
<Technical, API stuff>
|
||||
http://www.mail-archive.com/xfree86@xfree86.org/msg15594.html
|
||||
http://michael.toren.net/mirrors/doc/X-copy+paste.txt
|
||||
http://devdocs.wesnoth.org/clipboard_8cpp-source.html
|
||||
http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html
|
||||
http://www.jwz.org/doc/x-cut-and-paste.html
|
||||
|
||||
The basic run-down on X Selection Handling:
|
||||
* One window owns the "current selection" at any one time
|
||||
* Accessing the Selection (i.e. "paste"), Step-by-step
|
||||
* Ask the X server for the current selection owner
|
||||
* Ask the selection owner window to convert the selection into a format
|
||||
we can understand (XA_STRING - Latin-1 string - for now)
|
||||
* The converted result is stored as a property of the *selection owner*
|
||||
window. It is possible to specify the current application window as the
|
||||
target - but that'd require some X message handling... easier to skip that..
|
||||
* The final step is to acquire the property value of the selection owner
|
||||
window
|
||||
|
||||
Notes:
|
||||
An "Atom" is a server-side object that represents a string by an index into some
|
||||
kind of table or something. Pretty much like a handle that refers to one unique
|
||||
string. Atoms are used here to refer to property names and value formats.
|
||||
|
||||
Expansions:
|
||||
* Implement UTF-8 format support (should be interresting for international users)
|
||||
|
||||
*/
|
||||
wchar_t *sys_clipboard_get()
|
||||
{
|
||||
Display *disp=XOpenDisplay(NULL);
|
||||
if(!disp)
|
||||
return NULL;
|
||||
|
||||
// We use CLIPBOARD as the default, since the CLIPBOARD semantics are much
|
||||
// closer to windows semantics.
|
||||
Atom selSource=XInternAtom(disp, "CLIPBOARD", False);
|
||||
|
||||
Window selOwner=XGetSelectionOwner(disp, selSource);
|
||||
if(selOwner == None)
|
||||
{
|
||||
// However, since many apps don't use CLIPBOARD, but use PRIMARY instead
|
||||
// we use XA_PRIMARY as a fallback clipboard. This is true for xterm,
|
||||
// for example.
|
||||
selSource=XA_PRIMARY;
|
||||
selOwner=XGetSelectionOwner(disp, selSource);
|
||||
}
|
||||
if(selOwner != None) {
|
||||
Atom pty=XInternAtom(disp, "SelectionPropertyTemp", False);
|
||||
XConvertSelection(disp, selSource, XA_STRING, pty, selOwner, CurrentTime);
|
||||
XFlush(disp);
|
||||
|
||||
Atom type;
|
||||
int format=0, result=0;
|
||||
unsigned long len=0, bytes_left=0, dummy=0;
|
||||
u8 *data=NULL;
|
||||
|
||||
// Get the length of the property and some attributes
|
||||
// bytes_left will contain the length of the selection
|
||||
result = XGetWindowProperty (disp, selOwner, pty,
|
||||
0, 0, // offset - len
|
||||
0, // Delete 0==FALSE
|
||||
AnyPropertyType,//flag
|
||||
&type, // return type
|
||||
&format, // return format
|
||||
&len, &bytes_left,
|
||||
&data);
|
||||
if(result != Success)
|
||||
debug_printf("clipboard_get: XGetWindowProperty failed! result: %d type:%lu len:%lu format:%d bytes_left:%lu\n",
|
||||
result, type, len, format, bytes_left);
|
||||
if(result == Success && bytes_left > 0)
|
||||
{
|
||||
result = XGetWindowProperty (disp, selOwner,
|
||||
pty, 0, bytes_left, 0,
|
||||
AnyPropertyType, &type, &format,
|
||||
&len, &dummy, &data);
|
||||
|
||||
if(result == Success)
|
||||
{
|
||||
if(type == XA_STRING) //Latin-1: Just copy into low byte of wchar_t
|
||||
{
|
||||
wchar_t *ret=(wchar_t *)malloc((bytes_left+1)*sizeof(wchar_t));
|
||||
std::copy(data, data+bytes_left, ret);
|
||||
ret[bytes_left]=0;
|
||||
return ret;
|
||||
}
|
||||
// TODO: Handle UTF8 strings
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("clipboard_get: XGetWindowProperty failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status sys_clipboard_free(wchar_t *clip_buf)
|
||||
{
|
||||
free(clip_buf);
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* An SDL Event filter that intercepts other applications' requests for the
|
||||
* X selection buffer.
|
||||
*
|
||||
* @see x11_clipboard_init
|
||||
* @see sys_clipboard_set
|
||||
*/
|
||||
int clipboard_filter(void* UNUSED(userdata), SDL_Event* event)
|
||||
{
|
||||
/* Pass on all non-window manager specific events immediately */
|
||||
/* And do nothing if we don't actually have a clip-out to send out */
|
||||
if(event->type != SDL_SYSWMEVENT || !selection_data)
|
||||
return 1;
|
||||
|
||||
/* Handle window-manager specific clipboard events */
|
||||
/* (Note: libsdl must be compiled with X11 support (SDL_VIDEO_DRIVER_X11 in SDL_config.h) -
|
||||
else you'll get errors like "'struct SDL_SysWMmsg' has no member named 'xevent'") */
|
||||
XEvent* xevent = &event->syswm.msg->msg.x11.event;
|
||||
switch(xevent->type) {
|
||||
/* Copy the selection from our buffer to the requested property, and
|
||||
convert to the requested target format */
|
||||
case SelectionRequest: {
|
||||
XSelectionRequestEvent *req;
|
||||
XEvent sevent;
|
||||
|
||||
req = &xevent->xselectionrequest;
|
||||
sevent.xselection.type = SelectionNotify;
|
||||
sevent.xselection.display = req->display;
|
||||
sevent.xselection.selection = req->selection;
|
||||
sevent.xselection.target = req->target;
|
||||
sevent.xselection.property = None;
|
||||
sevent.xselection.requestor = req->requestor;
|
||||
sevent.xselection.time = req->time;
|
||||
// Simply strip all non-Latin1 characters and replace with '?'
|
||||
// We should support XA_UTF8
|
||||
if(req->target == XA_STRING)
|
||||
{
|
||||
size_t size = wcslen(selection_data);
|
||||
u8* buf = (u8*)alloca(size);
|
||||
|
||||
for(size_t i = 0; i < size; i++)
|
||||
{
|
||||
buf[i] = selection_data[i] < 0x100 ? selection_data[i] : '?';
|
||||
}
|
||||
|
||||
XChangeProperty(g_SDL_Display, req->requestor, req->property,
|
||||
sevent.xselection.target, 8, PropModeReplace,
|
||||
buf, size);
|
||||
sevent.xselection.property = req->property;
|
||||
}
|
||||
// TODO Add more target formats
|
||||
XSendEvent(g_SDL_Display, req->requestor, False, 0, &sevent);
|
||||
XSync(g_SDL_Display, False);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization for X clipboard handling, called on-demand by
|
||||
* sys_clipboard_set.
|
||||
*/
|
||||
Status x11_clipboard_init()
|
||||
{
|
||||
SDL_SysWMinfo info;
|
||||
|
||||
if(get_wminfo(info))
|
||||
{
|
||||
/* Save the information for later use */
|
||||
if(info.subsystem == SDL_SYSWM_X11)
|
||||
{
|
||||
g_SDL_Display = info.info.x11.display;
|
||||
g_SDL_Window = info.info.x11.window;
|
||||
|
||||
/* Enable the special window hook events */
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
|
||||
SDL_SetEventFilter(clipboard_filter, NULL);
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ERR::FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Selection (i.e. "copy")
|
||||
*
|
||||
* Step-by-step (X11)
|
||||
* <ul>
|
||||
* <li>Store the selection text in a local buffer
|
||||
* <li>Tell the X server that we want to own the selection
|
||||
* <li>Listen for Selection events and respond to them as appropriate
|
||||
* </ul>
|
||||
*/
|
||||
Status sys_clipboard_set(const wchar_t *str)
|
||||
{
|
||||
ONCE(x11_clipboard_init());
|
||||
|
||||
if(selection_data)
|
||||
{
|
||||
free(selection_data);
|
||||
selection_data = NULL;
|
||||
}
|
||||
|
||||
selection_size = (wcslen(str)+1)*sizeof(wchar_t);
|
||||
selection_data = (wchar_t *)malloc(selection_size);
|
||||
wcscpy(selection_data, str);
|
||||
|
||||
// Like for the clipboard_get code above, we rather use CLIPBOARD than
|
||||
// PRIMARY - more windows'y behaviour there.
|
||||
Atom clipboard_atom = XInternAtom(g_SDL_Display, "CLIPBOARD", False);
|
||||
XSetSelectionOwner(g_SDL_Display, clipboard_atom, g_SDL_Window, CurrentTime);
|
||||
XSetSelectionOwner(g_SDL_Display, XA_PRIMARY, g_SDL_Window, CurrentTime);
|
||||
|
||||
// SDL2 doesn't have a lockable event thread, so it just uses
|
||||
// XSync directly instead of lock_func/unlock_func
|
||||
XSync(g_SDL_Display, False);
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
#endif // #if HAVE_X
|
||||
|
@ -1,123 +0,0 @@
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "lib/sysdep/clipboard.h"
|
||||
|
||||
#include "lib/sysdep/os/win/win.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
|
||||
|
||||
// caller is responsible for freeing hMem.
|
||||
static Status SetClipboardText(const wchar_t* text, HGLOBAL& hMem)
|
||||
{
|
||||
const size_t numChars = wcslen(text);
|
||||
hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, (numChars + 1) * sizeof(wchar_t));
|
||||
if(!hMem)
|
||||
WARN_RETURN(ERR::NO_MEM);
|
||||
|
||||
wchar_t* lockedText = (wchar_t*)GlobalLock(hMem);
|
||||
if(!lockedText)
|
||||
WARN_RETURN(ERR::NO_MEM);
|
||||
wcscpy_s(lockedText, numChars+1, text);
|
||||
GlobalUnlock(hMem);
|
||||
|
||||
HANDLE hData = SetClipboardData(CF_UNICODETEXT, hMem);
|
||||
if(!hData) // failed
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
// @return INFO::OK iff text has been assigned a pointer (which the
|
||||
// caller must free via sys_clipboard_free) to the clipboard text.
|
||||
static Status GetClipboardText(wchar_t*& text)
|
||||
{
|
||||
// NB: Windows NT/2000+ auto convert CF_UNICODETEXT <-> CF_TEXT.
|
||||
|
||||
if(!IsClipboardFormatAvailable(CF_UNICODETEXT))
|
||||
return INFO::CANNOT_HANDLE;
|
||||
|
||||
HGLOBAL hMem = GetClipboardData(CF_UNICODETEXT);
|
||||
if(!hMem)
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
|
||||
const wchar_t* lockedText = (const wchar_t*)GlobalLock(hMem);
|
||||
if(!lockedText)
|
||||
WARN_RETURN(ERR::NO_MEM);
|
||||
|
||||
const size_t size = GlobalSize(hMem);
|
||||
text = (wchar_t*)malloc(size);
|
||||
if(!text)
|
||||
WARN_RETURN(ERR::NO_MEM);
|
||||
wcscpy_s(text, size/sizeof(wchar_t), lockedText);
|
||||
|
||||
(void)GlobalUnlock(hMem);
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
// OpenClipboard parameter.
|
||||
// NB: using wutil_AppWindow() causes GlobalLock to fail.
|
||||
static const HWND hWndNewOwner = 0; // MSDN: associate with "current task"
|
||||
|
||||
Status sys_clipboard_set(const wchar_t* text)
|
||||
{
|
||||
if(!OpenClipboard(hWndNewOwner))
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
|
||||
WARN_IF_FALSE(EmptyClipboard());
|
||||
|
||||
// NB: to enable copy/pasting something other than text, add
|
||||
// message handlers for WM_RENDERFORMAT and WM_RENDERALLFORMATS.
|
||||
HGLOBAL hMem;
|
||||
Status ret = SetClipboardText(text, hMem);
|
||||
|
||||
WARN_IF_FALSE(CloseClipboard()); // must happen before GlobalFree
|
||||
|
||||
ENSURE(GlobalFree(hMem) == 0); // (0 indicates success)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
wchar_t* sys_clipboard_get()
|
||||
{
|
||||
if(!OpenClipboard(hWndNewOwner))
|
||||
return 0;
|
||||
|
||||
wchar_t* text;
|
||||
Status ret = GetClipboardText(text);
|
||||
|
||||
WARN_IF_FALSE(CloseClipboard());
|
||||
|
||||
return (ret == INFO::OK)? text : 0;
|
||||
}
|
||||
|
||||
|
||||
Status sys_clipboard_free(wchar_t* text)
|
||||
{
|
||||
free(text);
|
||||
return INFO::OK;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -29,13 +29,13 @@
|
||||
|
||||
#include "lib/alignment.h"
|
||||
#include "lib/sysdep/os/win/win.h" // includes windows.h; must come before shlobj
|
||||
#include <SDL_clipboard.h> // SDL_SetClipboardText
|
||||
#include <shlobj.h> // pick_dir
|
||||
#include <shellapi.h> // open_url
|
||||
#include <Wincrypt.h>
|
||||
#include <WindowsX.h> // message crackers
|
||||
#include <winhttp.h>
|
||||
|
||||
#include "lib/sysdep/clipboard.h"
|
||||
#include "lib/sysdep/os/win/error_dialog.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
|
||||
@ -214,7 +214,8 @@ static void dlg_OnCommand(HWND hDlg, int id, HWND UNUSED(hWndCtl), UINT UNUSED(c
|
||||
{
|
||||
std::vector<wchar_t> buf(128*KiB); // (too big for stack)
|
||||
GetDlgItemTextW(hDlg, IDC_EDIT1, &buf[0], (int)buf.size());
|
||||
sys_clipboard_set(&buf[0]);
|
||||
std::string string = utf8_from_wstring(&buf[0]);
|
||||
SDL_SetClipboardText(string.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -31,7 +31,6 @@
|
||||
#include "gui/GUIManager.h"
|
||||
#include "gui/GUIMatrix.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "lib/sysdep/clipboard.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/utf8.h"
|
||||
#include "maths/MathUtil.h"
|
||||
@ -531,7 +530,7 @@ void CConsole::SetBuffer(const wchar_t* szMessage)
|
||||
|
||||
wcsncpy(m_szBuffer, szMessage, CONSOLE_BUFFER_SIZE);
|
||||
m_szBuffer[CONSOLE_BUFFER_SIZE-1] = 0;
|
||||
m_iBufferLength = (int)wcslen(m_szBuffer);
|
||||
m_iBufferLength = static_cast<int>(wcslen(m_szBuffer));
|
||||
m_iBufferPos = std::min(oldBufferPos, m_iBufferLength);
|
||||
}
|
||||
|
||||
@ -649,19 +648,22 @@ InReaction conInputHandler(const SDL_Event_* ev)
|
||||
}
|
||||
else if (g_Console->IsActive() && hotkey == "copy")
|
||||
{
|
||||
sys_clipboard_set(g_Console->GetBuffer());
|
||||
std::string text = utf8_from_wstring(g_Console->GetBuffer());
|
||||
SDL_SetClipboardText(text.c_str());
|
||||
return IN_HANDLED;
|
||||
}
|
||||
else if (g_Console->IsActive() && hotkey == "paste")
|
||||
{
|
||||
wchar_t* text = sys_clipboard_get();
|
||||
if (text)
|
||||
{
|
||||
for (wchar_t* c = text; *c; c++)
|
||||
g_Console->InsertChar(0, *c);
|
||||
char* utf8_text = SDL_GetClipboardText();
|
||||
if (!utf8_text)
|
||||
return IN_HANDLED;
|
||||
|
||||
std::wstring text = wstring_from_utf8(utf8_text);
|
||||
SDL_free(utf8_text);
|
||||
|
||||
for (wchar_t c : text)
|
||||
g_Console->InsertChar(0, c);
|
||||
|
||||
sys_clipboard_free(text);
|
||||
}
|
||||
return IN_HANDLED;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user