Skip to content

Commit

Permalink
#640: cursor support for gtk3:
Browse files Browse the repository at this point in the history
* move gtk2 cursor code to gtk client base superclass
* add compat code to gtk_util

git-svn-id: https://xpra.org/svn/Xpra/trunk@7573 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Sep 11, 2014
1 parent f28f0ce commit 5ca46cb
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 69 deletions.
60 changes: 0 additions & 60 deletions src/xpra/client/gtk2/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@
from xpra.gtk_common.gtk_util import gtk_main
from xpra.client.gtk_base.gtk_client_base import GTKXpraClient
from xpra.client.gtk2.tray_menu import GTK2TrayMenu
from xpra.gtk_common.cursor_names import cursor_names
from xpra.client.window_border import WindowBorder
from xpra.net.compression import Uncompressed
from xpra.log import Logger

log = Logger("gtk", "client")
cursorlog = Logger("gtk", "client", "cursor")
clipboardlog = Logger("gtk", "client", "clipboard")
grablog = Logger("gtk", "client", "grab")

Expand All @@ -45,8 +43,6 @@

FAKE_UI_LOCKUPS = int(os.environ.get("XPRA_FAKE_UI_LOCKUPS", "0"))

missing_cursor_names = set()


class XpraClient(GTKXpraClient):

Expand Down Expand Up @@ -331,62 +327,6 @@ def get_root_window(self):
def get_root_size(self):
return gdk.get_default_root_window().get_size()

def make_cursor(self, cursor_data):
#if present, try cursor ny name:
if len(cursor_data)>=9 and cursor_names:
cursor_name = cursor_data[8]
if cursor_name:
gdk_cursor = cursor_names.get(cursor_name.upper())
if gdk_cursor is not None:
cursorlog("setting new cursor by name: %s=%s", cursor_name, gdk_cursor)
return gdk.Cursor(gdk_cursor)
else:
global missing_cursor_names
if cursor_name not in missing_cursor_names:
cursorlog("cursor name '%s' not found", cursor_name)
missing_cursor_names.add(cursor_name)
#create cursor from the pixel data:
w, h, xhot, yhot, serial, pixels = cursor_data[2:8]
if len(pixels)<w*h*4:
import binascii
cursorlog.warn("not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w*h*4, len(pixels), binascii.hexlify(pixels)[:100])
return
pixbuf = gdk.pixbuf_new_from_data(pixels, gdk.COLORSPACE_RGB, True, 8, w, h, w * 4)
x = max(0, min(xhot, w-1))
y = max(0, min(yhot, h-1))
display = gdk.display_get_default()
csize = display.get_default_cursor_size()
cmaxw, cmaxh = display.get_maximal_cursor_size()
if len(cursor_data)>=11:
ssize = cursor_data[9]
smax = cursor_data[10]
cursorlog("server cursor sizes: default=%s, max=%s", ssize, smax)
cursorlog("new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot,yhot, serial, w,h, len(pixels), csize, (cmaxw, cmaxh))
ratio = 1
if w>cmaxw or h>cmaxh or (csize>0 and (csize<w or csize<h)):
ratio = max(float(w)/cmaxw, float(h)/cmaxh, float(max(w,h))/csize)
cursorlog("downscaling cursor by %.2f", ratio)
pixbuf = pixbuf.scale_simple(int(w/ratio), int(h/ratio), gdk.INTERP_BILINEAR)
x = int(x/ratio)
y = int(y/ratio)
return gdk.Cursor(gdk.display_get_default(), pixbuf, x, y)

def set_windows_cursor(self, windows, cursor_data):
cursor = None
if cursor_data:
try:
cursor = self.make_cursor(cursor_data)
except Exception as e:
cursorlog.warn("error creating cursor: %s (using default)", e, exc_info=True)
if cursor is None:
#use default:
cursor = gdk.Cursor(gtk.gdk.X_CURSOR)
for w in windows:
gdkwin = w.get_window()
#trays don't have a gdk window
if gdkwin:
gdkwin.set_cursor(cursor)


def _process_raise_window(self, packet):
wid = packet[1]
Expand Down
1 change: 0 additions & 1 deletion src/xpra/client/gtk3/cairo_workaround.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ CAIRO_FORMAT = {
}

def set_image_surface_data(object image_surface, rgb_format, object pixel_data, int width, int height, int stride):
print("set_image_surface_data%s" % str((image_surface, rgb_format, len(pixel_data), width, height, stride)))
#convert pixel_data to a C buffer:
cdef const unsigned char * cbuf = <unsigned char *> 0
cdef Py_ssize_t cbuf_len = 0
Expand Down
3 changes: 0 additions & 3 deletions src/xpra/client/gtk3/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,6 @@ def get_root_size(self):
w, h = 1920, 1080
return w, h

def set_windows_cursor(self, gtkwindows, new_cursor):
pass

def init_opengl(self, enable_opengl):
self.opengl_enabled = False
self.opengl_props = {"info" : "GTK3 does not support OpenGL"}
Expand Down
67 changes: 63 additions & 4 deletions src/xpra/client/gtk_base/gtk_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@

from xpra.log import Logger
log = Logger("gtk", "main")
cursorlog = Logger("gtk", "client", "cursor")

from xpra.gtk_common.quit import (gtk_main_quit_really,
gtk_main_quit_on_fatal_exceptions_enable)
from xpra.gtk_common.cursor_names import cursor_names
from xpra.gtk_common.gtk_util import get_gtk_version_info, scaled_image, pixbuf_new_from_file, display_get_default, screen_get_default
from xpra.gtk_common.gtk_util import get_gtk_version_info, scaled_image, default_Cursor, new_Cursor, new_Cursor_from_pixbuf, \
pixbuf_new_from_file, display_get_default, screen_get_default, get_pixbuf_from_data, INTERP_BILINEAR
from xpra.client.ui_client_base import UIXpraClient
from xpra.client.gobject_client_base import GObjectXpraClient
from xpra.client.gtk_base.gtk_keyboard_helper import GTKKeyboardHelper
from xpra.client.gtk_base.session_info import SessionInfo
from xpra.platform.paths import get_icon_filename
from xpra.platform.gui import system_bell

missing_cursor_names = set()


class GTKXpraClient(UIXpraClient, GObjectXpraClient):
__gsignals__ = UIXpraClient.__gsignals__
Expand Down Expand Up @@ -161,9 +165,6 @@ def supports_system_tray(self):
#always True: we can always use gtk.StatusIcon as fallback
return True

def set_windows_cursor(self, gtkwindows, new_cursor):
raise Exception("override me!")


def get_root_window(self):
raise Exception("override me!")
Expand Down Expand Up @@ -229,6 +230,64 @@ def get_screen_sizes(self):
i += 1
return screen_sizes

def set_windows_cursor(self, windows, cursor_data):
cursorlog("set_windows_cursor(%s, ..)", windows)
cursor = None
if cursor_data:
try:
cursor = self.make_cursor(cursor_data)
cursorlog("make_cursor(..)=%s", cursor)
except Exception as e:
log.warn("error creating cursor: %s (using default)", e, exc_info=True)
if cursor is None:
#use default:
cursor = default_Cursor
for w in windows:
gdkwin = w.get_window()
#trays don't have a gdk window
if gdkwin:
gdkwin.set_cursor(cursor)

def make_cursor(self, cursor_data):
#if present, try cursor ny name:
if len(cursor_data)>=9 and cursor_names:
cursor_name = cursor_data[8]
if cursor_name:
gdk_cursor = cursor_names.get(cursor_name.upper())
if gdk_cursor is not None:
cursorlog("setting new cursor by name: %s=%s", cursor_name, gdk_cursor)
return new_Cursor(gdk_cursor)
else:
global missing_cursor_names
if cursor_name not in missing_cursor_names:
cursorlog("cursor name '%s' not found", cursor_name)
missing_cursor_names.add(cursor_name)
#create cursor from the pixel data:
w, h, xhot, yhot, serial, pixels = cursor_data[2:8]
if len(pixels)<w*h*4:
import binascii
cursorlog.warn("not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w*h*4, len(pixels), binascii.hexlify(pixels)[:100])
return
pixbuf = get_pixbuf_from_data(pixels, True, w, h, w*4)
x = max(0, min(xhot, w-1))
y = max(0, min(yhot, h-1))
display = display_get_default()
csize = display.get_default_cursor_size()
cmaxw, cmaxh = display.get_maximal_cursor_size()
if len(cursor_data)>=11:
ssize = cursor_data[9]
smax = cursor_data[10]
cursorlog("server cursor sizes: default=%s, max=%s", ssize, smax)
cursorlog("new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot,yhot, serial, w,h, len(pixels), csize, (cmaxw, cmaxh))
ratio = 1
if w>cmaxw or h>cmaxh or (csize>0 and (csize<w or csize<h)):
ratio = max(float(w)/cmaxw, float(h)/cmaxh, float(max(w,h))/csize)
cursorlog("downscaling cursor by %.2f", ratio)
pixbuf = pixbuf.scale_simple(int(w/ratio), int(h/ratio), INTERP_BILINEAR)
x = int(x/ratio)
y = int(y/ratio)
return new_Cursor_from_pixbuf(display_get_default(), pixbuf, x, y)


def process_ui_capabilities(self):
UIXpraClient.process_ui_capabilities(self)
Expand Down
7 changes: 6 additions & 1 deletion src/xpra/gtk_common/gtk_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
pass

if is_gtk3():
#where is this gone now?
default_Cursor = gdk.Cursor.new(gdk.CursorType.X_CURSOR)
new_Cursor = gdk.Cursor.new
new_Cursor_from_pixbuf = gdk.Cursor.new_from_pixbuf
from gi.repository import GdkPixbuf #@UnresolvedImport
image_new_from_pixbuf = gtk.Image.new_from_pixbuf
pixbuf_new_from_file = GdkPixbuf.Pixbuf.new_from_file
Expand Down Expand Up @@ -146,6 +148,9 @@ def gtk_main():
if gtk.gtk_version<(2,18):
raise Exception("your version of PyGTK is too old: %s" % str(gtk.pygtk_version))

default_Cursor = gdk.Cursor(gdk.X_CURSOR)
new_Cursor = gdk.Cursor
new_Cursor_from_pixbuf = gdk.Cursor
image_new_from_pixbuf = gtk.image_new_from_pixbuf
pixbuf_new_from_file = gdk.pixbuf_new_from_file
pixbuf_new_from_data = gdk.pixbuf_new_from_data
Expand Down

0 comments on commit 5ca46cb

Please sign in to comment.