Copy selection to x clipboard.
Review URL: http://codereview.chromium.org/55052 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13044 0039d316-1c4b-4281-b951-d872f2087c98
Esse commit está contido em:
@@ -772,8 +772,10 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
|
||||
OnRemoveAutofillEntry)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFeedList, OnMsgUpdateFeedList)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionRequest, OnExtensionRequest)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnMsgSelectionChanged)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectionText, OnMsgSetSelectionText)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_PasteFromSelectionClipboard,
|
||||
OnPasteFromSelectionClipboard)
|
||||
OnMsgPasteFromSelectionClipboard)
|
||||
// Have the super handle all other messages.
|
||||
IPC_MESSAGE_UNHANDLED(RenderWidgetHost::OnMessageReceived(msg))
|
||||
IPC_END_MESSAGE_MAP_EX()
|
||||
@@ -1094,6 +1096,21 @@ void RenderViewHost::OnMsgSetTooltipText(const std::wstring& tooltip_text) {
|
||||
view()->SetTooltipText(tooltip_text);
|
||||
}
|
||||
|
||||
void RenderViewHost::OnMsgSelectionChanged() {
|
||||
if (view())
|
||||
view()->SelectionChanged();
|
||||
}
|
||||
|
||||
void RenderViewHost::OnMsgSetSelectionText(const std::string& text) {
|
||||
if (view())
|
||||
view()->SetSelectionText(text);
|
||||
}
|
||||
|
||||
void RenderViewHost::OnMsgPasteFromSelectionClipboard() {
|
||||
if (view())
|
||||
view()->PasteFromSelectionClipboard();
|
||||
}
|
||||
|
||||
void RenderViewHost::OnMsgRunFileChooser(bool multiple_files,
|
||||
const std::wstring& title,
|
||||
const std::wstring& default_file,
|
||||
@@ -1366,8 +1383,3 @@ void RenderViewHost::SendExtensionResponse(int callback_id,
|
||||
const std::string& response) {
|
||||
Send(new ViewMsg_ExtensionResponse(routing_id(), callback_id, response));
|
||||
}
|
||||
|
||||
void RenderViewHost::OnPasteFromSelectionClipboard() {
|
||||
if (view())
|
||||
view()->PasteFromSelectionClipboard();
|
||||
}
|
||||
|
||||
@@ -506,6 +506,9 @@ class RenderViewHost : public RenderWidgetHost {
|
||||
#endif
|
||||
void OnMsgGoToEntryAtOffset(int offset);
|
||||
void OnMsgSetTooltipText(const std::wstring& tooltip_text);
|
||||
void OnMsgSelectionChanged();
|
||||
void OnMsgSetSelectionText(const std::string& text);
|
||||
void OnMsgPasteFromSelectionClipboard();
|
||||
void OnMsgRunFileChooser(bool multiple_files,
|
||||
const std::wstring& title,
|
||||
const std::wstring& default_file,
|
||||
@@ -565,8 +568,6 @@ class RenderViewHost : public RenderWidgetHost {
|
||||
void OnExtensionRequest(const std::string& name, const std::string& args,
|
||||
int callback_id);
|
||||
|
||||
void OnPasteFromSelectionClipboard();
|
||||
|
||||
// Helper function to send a navigation message. If a cross-site request is
|
||||
// in progress, we may be suspended while waiting for the onbeforeunload
|
||||
// handler, so this function might buffer the message rather than sending it.
|
||||
|
||||
@@ -112,6 +112,12 @@ class RenderWidgetHostView {
|
||||
// the page has changed.
|
||||
virtual void SetTooltipText(const std::wstring& tooltip_text) = 0;
|
||||
|
||||
// Notifies the View that the renderer text selection has changed.
|
||||
virtual void SelectionChanged() { };
|
||||
|
||||
// Notifies the View what the current selection text is.
|
||||
virtual void SetSelectionText(const std::string& text) { };
|
||||
|
||||
// Tells the View to get the text from the selection clipboard and send it
|
||||
// back to the renderer asynchronously.
|
||||
virtual void PasteFromSelectionClipboard() { }
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
@@ -16,13 +17,10 @@
|
||||
#include "chrome/browser/renderer_host/backing_store.h"
|
||||
#include "chrome/browser/renderer_host/render_widget_host.h"
|
||||
#include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h"
|
||||
#include "webkit/glue/webcursor_gtk_data.h"
|
||||
|
||||
using WebKit::WebInputEventFactory;
|
||||
|
||||
namespace {
|
||||
|
||||
#include "webkit/glue/webcursor_gtk_data.h"
|
||||
|
||||
// This class is a simple convenience wrapper for Gtk functions. It has only
|
||||
// static methods.
|
||||
class RenderWidgetHostViewGtkWidget {
|
||||
@@ -48,9 +46,9 @@ class RenderWidgetHostViewGtkWidget {
|
||||
g_signal_connect(widget, "key-release-event",
|
||||
G_CALLBACK(KeyPressReleaseEvent), host_view);
|
||||
g_signal_connect(widget, "focus-in-event",
|
||||
G_CALLBACK(FocusIn), host_view);
|
||||
G_CALLBACK(OnFocusIn), host_view);
|
||||
g_signal_connect(widget, "focus-out-event",
|
||||
G_CALLBACK(FocusOut), host_view);
|
||||
G_CALLBACK(OnFocusOut), host_view);
|
||||
g_signal_connect(widget, "button-press-event",
|
||||
G_CALLBACK(ButtonPressReleaseEvent), host_view);
|
||||
g_signal_connect(widget, "button-release-event",
|
||||
@@ -60,6 +58,34 @@ class RenderWidgetHostViewGtkWidget {
|
||||
g_signal_connect(widget, "scroll-event",
|
||||
G_CALLBACK(MouseScrollEvent), host_view);
|
||||
|
||||
GtkTargetList* target_list = gtk_target_list_new(NULL, 0);
|
||||
gtk_target_list_add_text_targets(target_list, 0);
|
||||
gint num_targets = 0;
|
||||
GtkTargetEntry* targets = gtk_target_table_new_from_list(target_list,
|
||||
&num_targets);
|
||||
gtk_selection_clear_targets(widget, GDK_SELECTION_PRIMARY);
|
||||
gtk_selection_add_targets(widget, GDK_SELECTION_PRIMARY, targets,
|
||||
num_targets);
|
||||
gtk_target_table_free(targets, num_targets);
|
||||
|
||||
// When X requests the contents of the clipboard, GTK will emit the
|
||||
// selection_request_event signal. The default handler would then
|
||||
// synchronously emit the selection_get signal. However, we want to
|
||||
// respond to the selection_request_event asynchronously, so we intercept
|
||||
// the signal in OnSelectionRequest, request the selection text from the
|
||||
// render view, and return TRUE so the default handler won't be called. Then
|
||||
// when we get the selection text back from the renderer in
|
||||
// SetSelectionText() we will call manually the selection_request_event
|
||||
// default handler.
|
||||
g_signal_connect(widget, "selection_request_event",
|
||||
G_CALLBACK(OnSelectionRequest), host_view);
|
||||
g_signal_connect(widget, "selection_get",
|
||||
G_CALLBACK(OnSelectionGet), host_view);
|
||||
|
||||
// In OnSelectionGet, we need to access |host_view| to get the selection
|
||||
// text.
|
||||
g_object_set_data(G_OBJECT(widget), "render-widget-host-view-gtk",
|
||||
host_view);
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -87,13 +113,13 @@ class RenderWidgetHostViewGtkWidget {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean FocusIn(GtkWidget* widget, GdkEventFocus* focus,
|
||||
static gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* focus,
|
||||
RenderWidgetHostViewGtk* host_view) {
|
||||
host_view->GetRenderWidgetHost()->Focus();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean FocusOut(GtkWidget* widget, GdkEventFocus* focus,
|
||||
static gboolean OnFocusOut(GtkWidget* widget, GdkEventFocus* focus,
|
||||
RenderWidgetHostViewGtk* host_view) {
|
||||
// Whenever we lose focus, set the cursor back to that of our parent window,
|
||||
// which should be the default arrow.
|
||||
@@ -130,17 +156,49 @@ class RenderWidgetHostViewGtkWidget {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean OnSelectionRequest(GtkWidget* widget,
|
||||
GdkEventSelection* event) {
|
||||
RenderWidgetHostViewGtk* host_view =
|
||||
reinterpret_cast<RenderWidgetHostViewGtk*>(
|
||||
g_object_get_data(G_OBJECT(widget), "render-widget-host-view-gtk"));
|
||||
|
||||
// If we already know the selection text, return FALSE to let the default
|
||||
// handler run. Also, don't try to handle two events simultaneously,
|
||||
// because we might end up sending the wrong |event_selection_| back to GTK.
|
||||
if (!host_view->selection_text_.empty() ||
|
||||
host_view->event_selection_active_)
|
||||
return FALSE;
|
||||
|
||||
host_view->event_selection_ = *event;
|
||||
host_view->event_selection_active_ = true;
|
||||
if (host_view->selection_text_.empty())
|
||||
host_view->RequestSelectionText();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void OnSelectionGet(GtkWidget* widget,
|
||||
GtkSelectionData* data,
|
||||
guint info, guint time,
|
||||
RenderWidgetHostViewGtk* host_view) {
|
||||
DCHECK(!host_view->selection_text_.empty() ||
|
||||
host_view->event_selection_active_);
|
||||
|
||||
gtk_selection_data_set(data, data->target, 8,
|
||||
reinterpret_cast<const guchar*>(host_view->selection_text_.c_str()),
|
||||
host_view->selection_text_.length());
|
||||
}
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWidgetHostViewGtkWidget);
|
||||
};
|
||||
|
||||
gboolean OnPopupParentFocusOut(GtkWidget* parent, GdkEventFocus* focus,
|
||||
RenderWidgetHost* host) {
|
||||
static gboolean OnPopupParentFocusOut(GtkWidget* parent, GdkEventFocus* focus,
|
||||
RenderWidgetHost* host) {
|
||||
host->Shutdown();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
|
||||
RenderWidgetHost* widget) {
|
||||
@@ -153,7 +211,8 @@ RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host)
|
||||
parent_(NULL),
|
||||
popup_signal_id_(0),
|
||||
activatable_(true),
|
||||
is_loading_(false) {
|
||||
is_loading_(false),
|
||||
event_selection_active_(false) {
|
||||
host_->set_view(this);
|
||||
}
|
||||
|
||||
@@ -308,6 +367,22 @@ void RenderWidgetHostViewGtk::SetTooltipText(const std::wstring& tooltip_text) {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewGtk::SelectionChanged() {
|
||||
selection_text_.clear();
|
||||
|
||||
guint32 timestamp = gdk_x11_get_server_time(view_.get()->window);
|
||||
gtk_selection_owner_set(view_.get(), GDK_SELECTION_PRIMARY, timestamp);
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewGtk::SetSelectionText(const std::string& text) {
|
||||
selection_text_ = text;
|
||||
DCHECK(event_selection_active_);
|
||||
event_selection_active_ = false;
|
||||
// Resume normal handling of the active selection_request_event.
|
||||
GtkWidgetClass* klass = GTK_WIDGET_CLASS(gtk_type_class(GTK_TYPE_WIDGET));
|
||||
klass->selection_request_event(view_.get(), &event_selection_);
|
||||
}
|
||||
|
||||
BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
|
||||
const gfx::Size& size) {
|
||||
Display* display = x11_util::GetXDisplay();
|
||||
@@ -387,6 +462,10 @@ void RenderWidgetHostViewGtk::ShowCurrentCursor() {
|
||||
gdk_cursor_unref(gdk_cursor);
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewGtk::RequestSelectionText() {
|
||||
host_->Send(new ViewMsg_RequestSelectionText(host_->routing_id()));
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewGtk::ReceivedSelectionText(GtkClipboard* clipboard,
|
||||
const gchar* text, gpointer userdata) {
|
||||
RenderWidgetHostViewGtk* host_view =
|
||||
|
||||
@@ -5,16 +5,19 @@
|
||||
#ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_GTK_H_
|
||||
#define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_GTK_H_
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <vector>
|
||||
|
||||
#include "base/gfx/native_widget_types.h"
|
||||
#include "chrome/browser/renderer_host/render_widget_host_view.h"
|
||||
#include "chrome/common/owned_widget_gtk.h"
|
||||
#include "chrome/common/render_messages.h"
|
||||
#include "webkit/glue/webcursor.h"
|
||||
|
||||
class RenderWidgetHost;
|
||||
|
||||
typedef struct _GtkClipboard GtkClipboard;
|
||||
typedef struct _GtkSelectionData GtkSelectionData;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// See comments in render_widget_host_view.h about this class and its members.
|
||||
@@ -58,6 +61,8 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
|
||||
void RenderViewGone();
|
||||
void Destroy();
|
||||
void SetTooltipText(const std::wstring& tooltip_text);
|
||||
void SelectionChanged();
|
||||
void SetSelectionText(const std::string& text);
|
||||
void PasteFromSelectionClipboard();
|
||||
BackingStore* AllocBackingStore(const gfx::Size& size);
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -67,9 +72,20 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
|
||||
void Paint(const gfx::Rect&);
|
||||
|
||||
private:
|
||||
friend class RenderWidgetHostViewGtkWidget;
|
||||
|
||||
void set_event_selection(GdkEventSelection* event_selection) {
|
||||
event_selection_ = *event_selection;
|
||||
event_selection_active_ = true;
|
||||
}
|
||||
|
||||
// Update the display cursor for the render view.
|
||||
void ShowCurrentCursor();
|
||||
|
||||
void RequestSelectionText();
|
||||
|
||||
// When we've requested the text from the X clipboard, GTK returns it to us
|
||||
// through this callback.
|
||||
static void ReceivedSelectionText(GtkClipboard* clipboard,
|
||||
const gchar* text,
|
||||
gpointer userdata);
|
||||
@@ -99,6 +115,17 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
|
||||
|
||||
// The cursor for the page. This is passed up from the renderer.
|
||||
WebCursor current_cursor_;
|
||||
|
||||
// We cache the text that is selected on the page. This is used for copying to
|
||||
// the X clipboard. We update |selection_text_| whenever X asks us for it and
|
||||
// the cache is empty. We invalidate it (set it to empty) whenever the
|
||||
// renderer sends a SelectionChanged message.
|
||||
std::string selection_text_;
|
||||
|
||||
// A struct that keeps state for the XSelectionEvent we are handling (if any).
|
||||
GdkEventSelection event_selection_;
|
||||
// Tracks whether we are currently handling an XSelectionEvent.
|
||||
bool event_selection_active_;
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_GTK_H_
|
||||
|
||||
@@ -108,6 +108,10 @@ IPC_BEGIN_MESSAGES(View)
|
||||
// node.
|
||||
IPC_MESSAGE_ROUTED1(ViewMsg_SetInitialFocus, bool /* reverse */)
|
||||
|
||||
// Ask the renderer to send us the selection text via the SetSelectionText
|
||||
// message.
|
||||
IPC_MESSAGE_ROUTED0(ViewMsg_RequestSelectionText)
|
||||
|
||||
// Tells the renderer to perform the specified navigation, interrupting any
|
||||
// existing navigation.
|
||||
IPC_MESSAGE_ROUTED1(ViewMsg_Navigate, ViewMsg_Navigate_Params)
|
||||
@@ -900,6 +904,13 @@ IPC_BEGIN_MESSAGES(ViewHost)
|
||||
IPC_MESSAGE_ROUTED1(ViewHostMsg_SetTooltipText,
|
||||
std::wstring /* tooltip text string */)
|
||||
|
||||
// Notification that the text selection has changed.
|
||||
IPC_MESSAGE_ROUTED0(ViewHostMsg_SelectionChanged)
|
||||
|
||||
// Send the current text selection.
|
||||
IPC_MESSAGE_ROUTED1(ViewHostMsg_SetSelectionText,
|
||||
std::string /* currently selected text */)
|
||||
|
||||
// Asks the browser to display the file chooser. The result is returned in a
|
||||
// ViewHost_RunFileChooserResponse message.
|
||||
IPC_MESSAGE_ROUTED4(ViewHostMsg_RunFileChooser,
|
||||
@@ -1063,7 +1074,7 @@ IPC_BEGIN_MESSAGES(ViewHost)
|
||||
IPC_MESSAGE_ROUTED1(ViewHostMsg_CrashedPlugin,
|
||||
FilePath /* plugin_path */)
|
||||
|
||||
// Dsiplays a JavaScript out-of-memory message in the infobar.
|
||||
// Displays a JavaScript out-of-memory message in the infobar.
|
||||
IPC_MESSAGE_ROUTED0(ViewHostMsg_JSOutOfMemory)
|
||||
|
||||
// Displays a box to confirm that the user wants to navigate away from the
|
||||
|
||||
@@ -297,6 +297,12 @@ void RenderView::Init(gfx::NativeViewId parent_hwnd,
|
||||
MessageLoop::current());
|
||||
webwidget_ = WebView::Create(this, webkit_prefs);
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
// We have to enable ourselves as the editor delegate on linux so we can copy
|
||||
// text selections to the X clipboard.
|
||||
webview()->SetUseEditorDelegate(true);
|
||||
#endif
|
||||
|
||||
// Don't let WebCore keep a B/F list - we have our own.
|
||||
// We let it keep 1 entry because FrameLoader::goToItem expects an item in the
|
||||
// backForwardList, which is used only in ASSERTs.
|
||||
@@ -425,6 +431,7 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_HandleExtensionMessage,
|
||||
OnHandleExtensionMessage)
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse)
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_RequestSelectionText, OnRequestSelectionText)
|
||||
|
||||
// Have the super handle all other messages.
|
||||
IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
|
||||
@@ -454,6 +461,10 @@ void RenderView::SendThumbnail() {
|
||||
Send(new ViewHostMsg_Thumbnail(routing_id_, url, score, thumbnail));
|
||||
}
|
||||
|
||||
void RenderView::OnRequestSelectionText() {
|
||||
Send(new ViewHostMsg_SetSelectionText(routing_id_, selection_text_));
|
||||
}
|
||||
|
||||
void RenderView::PrintPage(const ViewMsg_PrintPage_Params& params,
|
||||
const gfx::Size& canvas_size,
|
||||
WebFrame* frame) {
|
||||
@@ -2422,6 +2433,17 @@ void RenderView::SetTooltipText(WebView* webview,
|
||||
Send(new ViewHostMsg_SetTooltipText(routing_id_, tooltip_text));
|
||||
}
|
||||
|
||||
void RenderView::DidChangeSelection(bool is_empty_selection) {
|
||||
#if defined(OS_LINUX)
|
||||
if (!is_empty_selection) {
|
||||
// TODO(estade): find a way to incrementally update the selection text.
|
||||
selection_text_ = webview()->GetMainFrame()->GetSelection(false);
|
||||
Send(new ViewHostMsg_SelectionChanged(routing_id_));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void RenderView::DownloadUrl(const GURL& url, const GURL& referrer) {
|
||||
Send(new ViewHostMsg_DownloadUrl(routing_id_, url, referrer));
|
||||
}
|
||||
|
||||
@@ -280,6 +280,9 @@ class RenderView : public RenderWidget,
|
||||
virtual void OnNavStateChanged(WebView* webview);
|
||||
virtual void SetTooltipText(WebView* webview,
|
||||
const std::wstring& tooltip_text);
|
||||
// Called when the text selection changed. This is only called on linux since
|
||||
// on other platforms the RenderView doesn't act as an editor client delegate.
|
||||
virtual void DidChangeSelection(bool is_empty_selection);
|
||||
|
||||
virtual void DownloadUrl(const GURL& url, const GURL& referrer);
|
||||
|
||||
@@ -593,6 +596,9 @@ class RenderView : public RenderWidget,
|
||||
|
||||
void OnHandleExtensionMessage(const std::string& message, int channel_id);
|
||||
|
||||
// Sends the selection text to the browser.
|
||||
void OnRequestSelectionText();
|
||||
|
||||
// Prints the page listed in |params|.
|
||||
void PrintPage(const ViewMsg_PrintPage_Params& params,
|
||||
const gfx::Size& canvas_size,
|
||||
@@ -815,6 +821,10 @@ class RenderView : public RenderWidget,
|
||||
// Maps pending callback IDs to their frames.
|
||||
IDMap<WebFrame> pending_extension_callbacks_;
|
||||
|
||||
// The currently selected text. This is currently only updated on Linux, where
|
||||
// it's for the selection clipboard.
|
||||
std::string selection_text_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RenderView);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,17 +6,11 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Small program to dump the contents of GTK's clipboard to the terminal.
|
||||
* Feel free to add to it or improve formatting or whatnot.
|
||||
*/
|
||||
int main(int argc, char* argv[]) {
|
||||
gtk_init(&argc, &argv);
|
||||
namespace {
|
||||
|
||||
void PrintClipboardContents(GtkClipboard* clip) {
|
||||
GdkAtom* targets;
|
||||
int num_targets = 0;
|
||||
// For now only look at GDK_SELECTION_CLIPBOARD. This could be extended
|
||||
// to look at GDK_SELECTION_PRIMARY (the X clipboard).
|
||||
GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||
|
||||
gtk_clipboard_wait_for_targets(clip, &targets, &num_targets);
|
||||
|
||||
printf("Available targets:\n---------------\n");
|
||||
@@ -34,6 +28,10 @@ int main(int argc, char* argv[]) {
|
||||
if (strstr(gdk_atom_name(targets[i]), "image")) {
|
||||
printf("(image omitted)\n\n");
|
||||
continue;
|
||||
} else if (strstr(gdk_atom_name(targets[i]), "TIMESTAMP")) {
|
||||
// TODO(estade): Print the time stamp in human readable format.
|
||||
printf("(time omitted)\n\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < data->length; j++) {
|
||||
@@ -44,3 +42,18 @@ int main(int argc, char* argv[]) {
|
||||
printf("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Small program to dump the contents of GTK's clipboards to the terminal.
|
||||
* Feel free to add to it or improve formatting or whatnot.
|
||||
*/
|
||||
int main(int argc, char* argv[]) {
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
printf("Desktop clipboard\n");
|
||||
PrintClipboardContents(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
|
||||
|
||||
printf("X clipboard\n");
|
||||
PrintClipboardContents(gtk_clipboard_get(GDK_SELECTION_PRIMARY));
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário