Fix the drag-and-drop of terminals/text back to pre-port functionality - a real pain this one (gtk2->gtk3)

This commit is contained in:
Stephen Boddy 2015-07-12 22:06:36 +02:00
parent 8b566b9859
commit d56da596b3
2 changed files with 71 additions and 42 deletions

View File

@ -8,7 +8,7 @@ import sys
import os import os
import signal import signal
import gi import gi
from gi.repository import GLib, GObject, Pango, Gtk, Gdk from gi.repository import GLib, GObject, Pango, Gtk, Gdk, cairo
gi.require_version('Vte', '2.91') # vte-0.38 (gnome-3.14) gi.require_version('Vte', '2.91') # vte-0.38 (gnome-3.14)
from gi.repository import Vte from gi.repository import Vte
import subprocess import subprocess
@ -128,7 +128,7 @@ class Terminal(Gtk.VBox):
self.pending_on_vte_size_allocate = False self.pending_on_vte_size_allocate = False
self.vte = Vte.Terminal() self.vte = Vte.Terminal()
self.vte._expose_data = None self.vte._draw_data = None
if not hasattr(self.vte, "set_opacity") or \ if not hasattr(self.vte, "set_opacity") or \
not hasattr(self.vte, "is_composited"): not hasattr(self.vte, "is_composited"):
self.composite_support = False self.composite_support = False
@ -363,18 +363,40 @@ class Terminal(Gtk.VBox):
dsttargets = [("vte", Gtk.TargetFlags.SAME_APP, self.TARGET_TYPE_VTE), dsttargets = [("vte", Gtk.TargetFlags.SAME_APP, self.TARGET_TYPE_VTE),
('text/x-moz-url', 0, 0), ('text/x-moz-url', 0, 0),
('_NETSCAPE_URL', 0, 0)] ('_NETSCAPE_URL', 0, 0)]
# dsttargets = Gtk.target_list_add_text_targets(dsttargets) # FIXME FOR GTK3 '''
# dsttargets = Gtk.target_list_add_uri_targets(dsttargets) The following should work, but on my system it corrupts the returned
TargetEntry's in the newdstargets with binary crap, causing "Segmentation
fault (core dumped)" when the later drag_dest_set gets called.
dsttargetlist = Gtk.TargetList.new([])
dsttargetlist.add_text_targets(0)
dsttargetlist.add_uri_targets(0)
dsttargetlist.add_table(dsttargets)
newdsttargets = Gtk.target_table_new_from_list(dsttargetlist)
'''
# FIXME: Temporary workaround for the problems with the correct way of doing things
dsttargets.extend([('text/plain', 0, 0),
('text/plain;charset=utf-8', 0, 0),
('TEXT', 0, 0),
('STRING', 0, 0),
('UTF8_STRING', 0, 0),
('COMPOUND_TEXT', 0, 0),
('text/uri-list', 0, 0)])
# Convert to target entries
srcvtetargets = [Gtk.TargetEntry.new(*tgt) for tgt in srcvtetargets]
dsttargets = [Gtk.TargetEntry.new(*tgt) for tgt in dsttargets]
dbg('Finalised drag targets: %s' % dsttargets) dbg('Finalised drag targets: %s' % dsttargets)
# for (widget, mask) in [ for (widget, mask) in [
# (self.vte, Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.BUTTON3_MASK), (self.vte, Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.BUTTON3_MASK),
# (self.titlebar, Gdk.ModifierType.BUTTON1_MASK)]: (self.titlebar, Gdk.ModifierType.BUTTON1_MASK)]:
# widget.drag_source_set(mask, srcvtetargets, Gdk.DragAction.MOVE) # FIXME FOR GTK3 widget.drag_source_set(mask, srcvtetargets, Gdk.DragAction.MOVE)
#
# self.vte.drag_dest_set(Gtk.DestDefaults.MOTION | self.vte.drag_dest_set(Gtk.DestDefaults.MOTION |
# Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP, Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP,
# dsttargets, Gdk.DragAction.COPY | Gdk.DragAction.MOVE) # FIXME FOR GTK3 dsttargets, Gdk.DragAction.COPY | Gdk.DragAction.MOVE)
for widget in [self.vte, self.titlebar]: for widget in [self.vte, self.titlebar]:
widget.connect('drag-begin', self.on_drag_begin, self) widget.connect('drag-begin', self.on_drag_begin, self)
@ -919,29 +941,28 @@ class Terminal(Gtk.VBox):
def on_drag_begin(self, widget, drag_context, _data): def on_drag_begin(self, widget, drag_context, _data):
"""Handle the start of a drag event""" """Handle the start of a drag event"""
widget.drag_source_set_icon_pixbuf(util.widget_pixbuf(self, 512)) Gtk.drag_set_icon_pixbuf(drag_context, util.widget_pixbuf(self, 512), 0, 0)
def on_drag_data_get(self, _widget, _drag_context, selection_data, info, def on_drag_data_get(self, _widget, _drag_context, selection_data, info,
_time, data): _time, data):
"""I have no idea what this does, drag and drop is a mystery. sorry.""" """I have no idea what this does, drag and drop is a mystery. sorry."""
selection_data.set('vte', info, selection_data.set(Gdk.atom_intern('vte', False), info,
str(data.terminator.terminals.index(self))) str(data.terminator.terminals.index(self)))
def on_drag_motion(self, widget, drag_context, x, y, _time, _data): def on_drag_motion(self, widget, drag_context, x, y, _time, _data):
"""*shrug*""" """*shrug*"""
if not drag_context.targets == ['vte'] and \ if not drag_context.list_targets() == [Gdk.atom_intern('vte', False)] and \
(Gtk.targets_include_text(drag_context.targets) or \ (Gtk.targets_include_text(drag_context.list_targets()) or \
Gtk.targets_include_uri(drag_context.targets)): Gtk.targets_include_uri(drag_context.list_targets())):
# copy text from another widget # copy text from another widget
return return
srcwidget = drag_context.get_source_widget() srcwidget = Gtk.drag_get_source_widget(drag_context)
if(isinstance(srcwidget, Gtk.EventBox) and if(isinstance(srcwidget, Gtk.EventBox) and
srcwidget == self.titlebar) or widget == srcwidget: srcwidget == self.titlebar) or widget == srcwidget:
# on self # on self
return return
alloc = widget.get_allocation() alloc = widget.get_allocation()
rect = (0, 0, alloc.width, alloc.height)
if self.config['use_theme_colors']: if self.config['use_theme_colors']:
color = self.vte.get_style_context().get_color(Gtk.StateType.NORMAL) # VERIFY FOR GTK3 as above color = self.vte.get_style_context().get_color(Gtk.StateType.NORMAL) # VERIFY FOR GTK3 as above
@ -970,24 +991,23 @@ class Terminal(Gtk.VBox):
coord = (bottomleft, bottomright, middleright , middleleft) coord = (bottomleft, bottomright, middleright , middleleft)
#here, we define some widget internal values #here, we define some widget internal values
widget._expose_data = { 'color': color, 'coord' : coord } widget._draw_data = { 'color': color, 'coord' : coord }
#redraw by forcing an event #redraw by forcing an event
connec = widget.connect_after('expose-event', self.on_expose_event) connec = widget.connect_after('draw', self.on_draw)
widget.window.invalidate_rect(rect, True) widget.queue_draw_area(0, 0, alloc.width, alloc.height)
widget.window.process_updates(True) widget.get_window().process_updates(True)
#finaly reset the values #finaly reset the values
widget.disconnect(connec) widget.disconnect(connec)
widget._expose_data = None widget._draw_data = None
def on_expose_event(self, widget, _event): def on_draw(self, widget, context):
"""Handle an expose event while dragging""" """Handle an expose event while dragging"""
if not widget._expose_data: if not widget._draw_data:
return(False) return(False)
color = widget._expose_data['color'] color = widget._draw_data['color']
coord = widget._expose_data['coord'] coord = widget._draw_data['coord']
context = widget.window.cairo_create()
context.set_source_rgba(color.red, color.green, color.blue, 0.5) context.set_source_rgba(color.red, color.green, color.blue, 0.5)
if len(coord) > 0 : if len(coord) > 0 :
context.move_to(coord[len(coord)-1][0], coord[len(coord)-1][1]) context.move_to(coord[len(coord)-1][0], coord[len(coord)-1][1])
@ -1001,11 +1021,11 @@ class Terminal(Gtk.VBox):
_info, _time, data): _info, _time, data):
"""Something has been dragged into the terminal. Handle it as either a """Something has been dragged into the terminal. Handle it as either a
URL or another terminal.""" URL or another terminal."""
dbg('drag data received of type: %s' % selection_data.type) dbg('drag data received of type: %s' % (selection_data.get_data_type()))
if Gtk.targets_include_text(drag_context.targets) or \ if Gtk.targets_include_text(drag_context.list_targets()) or \
Gtk.targets_include_uri(drag_context.targets): Gtk.targets_include_uri(drag_context.list_targets()):
# copy text to destination # copy text to destination
txt = selection_data.data.strip(' ') txt = selection_data.get_data().strip(' ')
if txt[0:7] == 'file://': if txt[0:7] == 'file://':
txt = "'%s'" % urllib.unquote(txt[7:]) txt = "'%s'" % urllib.unquote(txt[7:])
else: else:
@ -1014,8 +1034,8 @@ class Terminal(Gtk.VBox):
term.feed(txt) term.feed(txt)
return return
widgetsrc = data.terminator.terminals[int(selection_data.data)] widgetsrc = data.terminator.terminals[int(selection_data.get_data())]
srcvte = drag_context.get_source_widget() srcvte = Gtk.drag_get_source_widget(drag_context)
#check if computation requireds #check if computation requireds
if (isinstance(srcvte, Gtk.EventBox) and if (isinstance(srcvte, Gtk.EventBox) and
srcvte == self.titlebar) or srcvte == widget: srcvte == self.titlebar) or srcvte == widget:

View File

@ -24,7 +24,8 @@
""" """
import sys import sys
from gi.repository import Gtk from gi.repository import Gtk, Gdk
import cairo
import os import os
import pwd import pwd
import inspect import inspect
@ -142,11 +143,9 @@ def shell_lookup():
def widget_pixbuf(widget, maxsize=None): def widget_pixbuf(widget, maxsize=None):
"""Generate a pixbuf of a widget""" """Generate a pixbuf of a widget"""
pixmap = widget.get_snapshot() # FIXME: Can this be changed from using "import cairo" to "from gi.repository import cairo"?
(width, height) = pixmap.get_size() window = widget.get_window()
pixbuf = GdkPixbuf.Pixbuf(GdkPixbuf.Colorspace.RGB, False, 8, width, height) width, height = window.get_width(), window.get_height()
pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, width,
height)
longest = max(width, height) longest = max(width, height)
@ -156,8 +155,18 @@ def widget_pixbuf(widget, maxsize=None):
if not maxsize or (width * factor) > width or (height * factor) > height: if not maxsize or (width * factor) > width or (height * factor) > height:
factor = 1 factor = 1
scaledpixbuf = pixbuf.scale_simple(int(width * factor), int(height * factor), GdkPixbuf.InterpType.BILINEAR) preview_width, preview_height = int(width * factor), int(height * factor)
preview_surface = Gdk.Window.create_similar_surface(window,
cairo.CONTENT_COLOR, preview_width, preview_height)
cairo_context = cairo.Context(preview_surface)
cairo_context.scale(factor, factor)
Gdk.cairo_set_source_window(cairo_context, window, 0, 0)
cairo_context.paint()
scaledpixbuf = Gdk.pixbuf_get_from_surface(preview_surface, 0, 0, preview_width, preview_height);
return(scaledpixbuf) return(scaledpixbuf)
def get_config_dir(): def get_config_dir():