예제 #1
0
 def make_cursor(self, cursor_data):
     #if present, try cursor ny name:
     display = display_get_default()
     if len(cursor_data)>=9 and cursor_types:
         cursor_name = bytestostr(cursor_data[8])
         if cursor_name:
             gdk_cursor = cursor_types.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_for_display(display, 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))
     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))
     fw, fh = get_fixed_cursor_size()
     if fw>0 and fh>0 and (w!=fw or h!=fh):
         #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us)
         if w<=fw and h<=fh:
             cursorlog("pasting cursor of size %ix%i onto clear pixbuf of size %ix%i", w, h, fw, fh)
             cursor_pixbuf = get_pixbuf_from_data("\0"*fw*fh*4, True, fw, fh, fw*4)
             pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0)
         else:
             cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i", w, h, fw, fh)
             cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR)
             xratio, yratio = float(w)/fw, float(h)/fh
             x, y = int(x/xratio), int(y/yratio)
     elif 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)
         x, y, w, h = int(x/ratio), int(y/ratio), int(w/ratio), int(h/ratio)
         cursorlog("downscaling cursor %s by %.2f: %sx%s", pixbuf, ratio, w, h)
         cursor_pixbuf = pixbuf.scale_simple(w, h, INTERP_BILINEAR)
     else:
         cursor_pixbuf = pixbuf
     #clamp to pixbuf size:
     w = cursor_pixbuf.get_width()
     h = cursor_pixbuf.get_height()
     x = max(0, min(x, w-1))
     y = max(0, min(y, h-1))
     return new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y)
예제 #2
0
 def set_command(self, command):
     if not HAS_X11_BINDINGS:
         return
     v = command
     if type(command)!=unicode:
         v = bytestostr(command)
         try:
             v = v.decode("utf8")
         except:
             pass
     def do_set_command():
         metalog("do_set_command() str(%s)=%s (type=%s)", command, v, type(command))
         prop_set(self.get_window(), "WM_COMMAND", "latin1", v)
     self.when_realized("command", do_set_command)
예제 #3
0
 def update_icon(self, width, height, coding, data):
     log("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height, coding, len(data))
     coding = bytestostr(coding)
     if coding == "premult_argb32":
         if unpremultiply_argb is None:
             #we could use PIL here with mode 'RGBa'
             log.warn("cannot process premult_argb32 icon without the argb module")
             return
         #we usually cannot do in-place and this is not performance critical
         data = byte_buffer_to_buffer(unpremultiply_argb(data))
         pixbuf = pixbuf_new_from_data(data, COLORSPACE_RGB, True, 8, width, height, width*4)
     else:
         loader = PixbufLoader()
         loader.write(data)
         loader.close()
         pixbuf = loader.get_pixbuf()
     log("%s.set_icon(%s)", self, pixbuf)
     self.set_icon(pixbuf)
예제 #4
0
파일: net_util.py 프로젝트: ljmljz/xpra
		def pver(v):
			if type(v) in (tuple, list):
				s = ""
				for i in range(len(v)):
					if i>0:
						#dot seperated numbers
						if type(v[i-1])==int:
							s += "."
						else:
							s += ", "
					s += str(v[i])
				return s
			if type(v)==bytes:
				from xpra.util import bytestostr
				v = bytestostr(v)
			if type(v)==str and v.startswith("v"):
				return v[1:]
			return str(v)
예제 #5
0
 def pver(v):
     if type(v) in (tuple, list):
         s = ""
         for i in range(len(v)):
             if i > 0:
                 #dot seperated numbers
                 if type(v[i - 1]) == int:
                     s += "."
                 else:
                     s += ", "
             s += str(v[i])
         return s
     if type(v) == bytes:
         from xpra.util import bytestostr
         v = bytestostr(v)
     if type(v) == str and v.startswith("v"):
         return v[1:]
     return str(v)
예제 #6
0
 def update_icon(self, width, height, coding, data):
     coding = bytestostr(coding)
     iconlog("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height, coding, len(data))
     if PYTHON3 and WIN32:
         iconlog("not setting icon to prevent crashes..")
         return
     if coding == "premult_argb32":            #we usually cannot do in-place and this is not performance critical
         data = unpremultiply_argb(data)
         rgba = memoryview_to_bytes(bgra_to_rgba(data))
         pixbuf = get_pixbuf_from_data(rgba, True, width, height, width*4)
     else:
         loader = PixbufLoader()
         loader.write(data)
         loader.close()
         pixbuf = loader.get_pixbuf()
     #for debugging, save to a file so we can see it:
     #pixbuf.save("C-%s-%s.png" % (self._id, int(time.time())), "png")
     iconlog("%s.set_icon(%s)", self, pixbuf)
     self.set_icon(pixbuf)
예제 #7
0
 def update_icon(self, width, height, coding, data):
     coding = bytestostr(coding)
     iconlog("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height,
             coding, len(data))
     if PYTHON3 and WIN32:
         iconlog("not setting icon to prevent crashes..")
         return
     if coding == "premult_argb32":  #we usually cannot do in-place and this is not performance critical
         data = unpremultiply_argb(data)
         rgba = memoryview_to_bytes(bgra_to_rgba(data))
         pixbuf = get_pixbuf_from_data(rgba, True, width, height, width * 4)
     else:
         loader = PixbufLoader()
         loader.write(data)
         loader.close()
         pixbuf = loader.get_pixbuf()
     #for debugging, save to a file so we can see it:
     #pixbuf.save("C-%s-%s.png" % (self._id, int(time.time())), "png")
     iconlog("%s.set_icon(%s)", self, pixbuf)
     self.set_icon(pixbuf)
예제 #8
0
 def update_icon(self, width, height, coding, data):
     log("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height,
         coding, len(data))
     coding = bytestostr(coding)
     if coding == "premult_argb32":
         if unpremultiply_argb is None:
             #we could use PIL here with mode 'RGBa'
             log.warn(
                 "cannot process premult_argb32 icon without the argb module"
             )
             return
         #we usually cannot do in-place and this is not performance critical
         data = unpremultiply_argb(data)
         rgba = byte_buffer_to_buffer(bgra_to_rgba(data))
         pixbuf = get_pixbuf_from_data(rgba, True, width, height, width * 4)
     else:
         loader = PixbufLoader()
         loader.write(data)
         loader.close()
         pixbuf = loader.get_pixbuf()
     log("%s.set_icon(%s)", self, pixbuf)
     self.set_icon(pixbuf)
예제 #9
0
 def make_cursor(self, cursor_data):
     #if present, try cursor ny name:
     display = display_get_default()
     cursorlog(
         "make_cursor: has-name=%s, has-cursor-types=%s, xscale=%s, yscale=%s, USE_LOCAL_CURSORS=%s",
         len(cursor_data) >= 9, bool(cursor_types), self.xscale,
         self.yscale, USE_LOCAL_CURSORS)
     #named cursors cannot be scaled (round to 10 to compare so 0.95 and 1.05 are considered the same as 1.0, no scaling):
     if len(cursor_data) >= 9 and cursor_types and iround(
             self.xscale * 10) == 10 and iround(self.yscale * 10) == 10:
         cursor_name = bytestostr(cursor_data[8])
         if cursor_name and USE_LOCAL_CURSORS:
             gdk_cursor = cursor_types.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_for_display(display, 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))
     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))
     fw, fh = get_fixed_cursor_size()
     if fw > 0 and fh > 0 and (w != fw or h != fh):
         #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us)
         if w <= fw and h <= fh:
             cursorlog(
                 "pasting cursor of size %ix%i onto clear pixbuf of size %ix%i",
                 w, h, fw, fh)
             cursor_pixbuf = get_pixbuf_from_data("\0" * fw * fh * 4, True,
                                                  fw, fh, fw * 4)
             pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0)
         else:
             cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i",
                       w, h, fw, fh)
             cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR)
             xratio, yratio = float(w) / fw, float(h) / fh
             x, y = iround(x / xratio), iround(y / yratio)
     else:
         sx, sy, sw, sh = x, y, w, h
         #scale the cursors:
         if self.xscale != 1 or self.yscale != 1:
             sx, sy, sw, sh = self.srect(x, y, w, h)
         sw = max(1, sw)
         sh = max(1, sh)
         #ensure we honour the max size if there is one:
         if (cmaxw > 0 and sw > cmaxw) or (cmaxh > 0 and sh > cmaxh):
             ratio = 1.0
             if cmaxw > 0:
                 ratio = max(ratio, float(w) / cmaxw)
             if cmaxh > 0:
                 ratio = max(ratio, float(h) / cmaxh)
             cursorlog("clamping cursor size to %ix%i using ratio=%s",
                       cmaxw, cmaxh, ratio)
             sx, sy, sw, sh = iround(x / ratio), iround(y / ratio), min(
                 cmaxw, iround(w / ratio)), min(cmaxh, iround(h / ratio))
         if sw != w or sh != h:
             cursorlog(
                 "scaling cursor from %ix%i hotspot at %ix%i to %ix%i hotspot at %ix%i",
                 w, h, x, y, sw, sh, sx, sy)
             cursor_pixbuf = pixbuf.scale_simple(sw, sh, INTERP_BILINEAR)
             x, y = sx, sy
         else:
             cursor_pixbuf = pixbuf
     #clamp to pixbuf size:
     w = cursor_pixbuf.get_width()
     h = cursor_pixbuf.get_height()
     x = max(0, min(x, w - 1))
     y = max(0, min(y, h - 1))
     try:
         c = new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y)
     except RuntimeError as e:
         log.error("Error: failed to create cursor:")
         log.error(" %s", e)
         log.error(" using %s of size %ix%i with hotspot at %ix%i",
                   cursor_pixbuf, w, h, x, y)
         c = None
     return c
예제 #10
0
파일: menu.py 프로젝트: ljmljz/xpra
def setup_dbus_window_menu(add, wid, menus, application_action_callback=None, window_action_callback=None):
    def nomenu():
        #tell caller to clear all properties if they exist:
        return {
                "_GTK_APP_MENU_OBJECT_PATH"     : None,
                "_GTK_WINDOW_OBJECT_PATH"       : None,
                "_GTK_APPLICATION_OBJECT_PATH"  : None,
                "_GTK_UNIQUE_BUS_NAME"          : None,
                "_GTK_APPLICATION_ID"           : None
                }
    if add is False:
        return nomenu()
    global window_menu_services, window_menus, fallback_menus
    if len(menus)==0 and fallback_menus:
        menus = fallback_menus
    #ie: menu = {
    #         'enabled': True,
    #         'application-id':         'org.xpra.ExampleMenu',
    #         'application-actions':    {'quit': (True, '', ()), 'about': (True, '', ()), 'help': (True, '', ()), 'custom': (True, '', ()), 'activate-tab': (True, 's', ()), 'preferences': (True, '', ())},
    #         'window-actions':         {'edit-profile': (True, 's', ()), 'reset': (True, 'b', ()), 'about': (True, '', ()), 'help': (True, '', ()), 'fullscreen': (True, '', (0,)), 'detach-tab': (True, '', ()), 'save-contents': (True, '', ()), 'zoom': (True, 'i', ()), 'move-tab': (True, 'i', ()), 'new-terminal': (True, '(ss)', ()), 'switch-tab': (True, 'i', ()), 'new-profile': (True, '', ()), 'close': (True, 's', ()), 'show-menubar': (True, '', (1,)), 'select-all': (True, '', ()), 'copy': (True, '', ()), 'paste': (True, 's', ()), 'find': (True, 's', ()), 'preferences': (True, '', ())},
    #         'window-menu':            {0:
    #               {0: ({':section': (0, 1)}, {':section': (0, 2)}, {':section': (0, 3)}),
    #                1: ({'action': 'win.new-terminal', 'target': ('default', 'default'), 'label': '_New Terminal'},),
    #                2: ({'action': 'app.preferences', 'label': '_Preferences'},),
    #                3: ({'action': 'app.help', 'label': '_Help'}, {'action': 'app.about', 'label': '_About'}, {'action': 'app.quit', 'label': '_Quit'}),
    #                }
    #             }
    #           }
    enabled = menus.get("enabled", False)
    app_actions_service, window_actions_service, window_menu_service = None, None, None
    def remove_services(*args):
        """ removes all the services if they are not longer used by any windows """
        for x in (app_actions_service, window_actions_service, window_menu_service):
            if x:
                if x not in window_menu_services.values():
                    try:
                        x.remove_from_connection()
                    except Exception as e:
                        log.warn("Error removing %s: %s", x, e)
        try:
            del window_menus[wid]
        except:
            pass
    if enabled:
        m = typedict(menus)
        app_id          = bytestostr(m.strget("application-id", b"org.xpra.Window%i" % wid)).decode()
        app_actions     = m.dictget("application-actions")
        window_actions  = m.dictget("window-actions")
        window_menu     = m.dictget("window-menu")
    if wid in window_menus:
        #update, destroy or re-create the services:
        app_actions_service, window_actions_service, window_menu_service, cur_app_id = window_menus[wid]
        if not enabled or cur_app_id!=app_id:
            remove_services()   #falls through to re-create them if enabled is True
            app_actions_service, window_actions_service, window_menu_service = None, None, None
        else:
            #update them:
            app_actions_service.set_actions(app_actions)
            window_actions_service.set_actions(window_actions)
            window_menu_service.set_menus(window_menu)
            return
    if not enabled:
        #tell caller to clear all properties if they exist:
        return nomenu()
    #make or re-use services:
    try:
        NAME_PREFIX = "org.xpra."
        from xpra.util import strtobytes
        from xpra.dbus.common import init_session_bus
        from xpra.dbus.gtk_menuactions import Menus, Actions
        session_bus = init_session_bus()
        bus_name = session_bus.get_unique_name().decode()
        name = app_id
        for strip in ("org.", "gtk.", "xpra.", "gnome."):
            if name.startswith(strip):
                name = name[len(strip):]
        name = NAME_PREFIX + name
        log("normalized named(%s)=%s", app_id, name)

        def get_service(service_class, name, path, *args):
            """ find the service by name and path, or create one """
            service = window_menu_services.get((service_class, name, path))
            if service is None:
                service = service_class(name, path, session_bus, *args)
                window_menu_services[(service_class, name, path)] = service
            return service

        app_path = strtobytes("/"+name.replace(".", "/")).decode()
        app_actions_service = get_service(Actions, name, app_path, app_actions, application_action_callback)

        #this one should be unique and therefore not re-used? (only one "window_action_callback"..)
        window_path = u"%s/window/%s" % (app_path, wid)
        window_actions_service = get_service(Actions, name, window_path, window_actions, window_action_callback)

        menu_path = u"%s/menus/appmenu" % app_path
        window_menu_service = get_service(Menus, app_id, menu_path, window_menu)
        window_menus[wid] = app_actions_service, window_actions_service, window_menu_service, app_id

        return {
                "_GTK_APP_MENU_OBJECT_PATH"     : ("utf8", menu_path),
                "_GTK_WINDOW_OBJECT_PATH"       : ("utf8", window_path),
                "_GTK_APPLICATION_OBJECT_PATH"  : ("utf8", app_path),
                "_GTK_UNIQUE_BUS_NAME"          : ("utf8", bus_name),
                "_GTK_APPLICATION_ID"           : ("utf8", app_id),
               }
    except Exception:
        log.error("Error: cannot parse or apply menu:", exc_info=True)
        remove_services()
        return nomenu()
예제 #11
0
    def set_metadata(self, metadata):
        metalog("set_metadata(%s)", metadata)
        #WARNING: "class-instance" needs to go first because others may realize the window
        #(and GTK doesn't set the "class-instance" once the window is realized)
        if b"class-instance" in metadata:
            self.set_class_instance(
                *self._metadata.strlistget("class-instance", ("xpra", "Xpra")))

        if b"title" in metadata:
            try:
                title = bytestostr(self._client.title).replace("\0", "")
                if title.find("@") >= 0:
                    #perform metadata variable substitutions:
                    #full of py3k unicode headaches that don't need to be
                    default_values = {
                        "title": "<untitled window>",
                        "client-machine": "<unknown machine>"
                    }

                    def metadata_replace(match):
                        atvar = match.group(0)  #ie: '@title@'
                        var = atvar[1:len(atvar) - 1]  #ie: 'title'
                        default_value = default_values.get(
                            var, "<unknown %s>" % var)
                        value = self._metadata.strget(var, default_value)
                        if sys.version < '3':
                            value = value.decode("utf-8")
                        return value

                    title = re.sub("@[\w\-]*@", metadata_replace, title)
                    if sys.version < '3':
                        utf8_title = title.encode("utf-8")
                    else:
                        utf8_title = title
            except Exception as e:
                log.error("error parsing window title: %s", e)
                utf8_title = b""
            self.set_title(utf8_title)

        if b"icon-title" in metadata:
            icon_title = metadata.strget("icon-title")
            self.set_icon_name(icon_title)

        if b"size-constraints" in metadata:
            self.size_constraints = typedict(
                metadata.dictget("size-constraints"))
            self.set_size_constraints(self.size_constraints,
                                      self.max_window_size)

        if b"transient-for" in metadata:
            wid = metadata.intget("transient-for", -1)
            self.apply_transient_for(wid)

        if b"modal" in metadata:
            modal = metadata.boolget("modal")
            self.set_modal(modal)

        #apply window-type hint if window has not been mapped yet:
        if b"window-type" in metadata and not self.is_mapped():
            window_types = metadata.strlistget("window-type")
            self.set_window_type(window_types)

        if b"role" in metadata:
            role = metadata.strget("role")
            self.set_role(role)

        if b"xid" in metadata:
            xid = metadata.strget("xid")
            self.set_xid(xid)

        if b"opacity" in metadata:
            opacity = metadata.intget("opacity", -1)
            if opacity < 0:
                opacity = 1
            else:
                opacity = min(1, opacity / float(0xffffffff))
            #requires gtk>=2.12!
            if hasattr(self, "set_opacity"):
                self.set_opacity(opacity)

        if b"has-alpha" in metadata:
            new_alpha = metadata.boolget("has-alpha")
            if new_alpha != self._has_alpha:
                log.warn(
                    "window %s changed its alpha flag from %s to %s (unsupported)",
                    self._id, self._has_alpha, new_alpha)
                self._has_alpha = new_alpha

        if b"maximized" in metadata:
            maximized = metadata.boolget("maximized")
            if maximized != self._maximized:
                self._maximized = maximized
                if maximized:
                    self.maximize()
                else:
                    self.unmaximize()

        if b"fullscreen" in metadata:
            fullscreen = metadata.boolget("fullscreen")
            if self._fullscreen is None or self._fullscreen != fullscreen:
                self._fullscreen = fullscreen
                self.set_fullscreen(fullscreen)

        if b"iconic" in metadata:
            iconified = metadata.boolget("iconic")
            if self._iconified != iconified:
                self._iconified = iconified
                if iconified:
                    self.iconify()
                else:
                    self.deiconify()

        if b"decorations" in metadata:
            self.set_decorated(metadata.boolget("decorations"))
            self.apply_geometry_hints(self.geometry_hints)

        if b"above" in metadata:
            above = metadata.boolget("above")
            if self._above != above:
                self._above = above
                self.set_keep_above(above)

        if b"below" in metadata:
            below = metadata.boolget("below")
            if self._below != below:
                self._below = below
                self.set_keep_below(below)

        if b"shaded" in metadata:
            shaded = metadata.boolget("shaded")
            if self._shaded != shaded:
                self._shaded = shaded
                self.set_shaded(shaded)

        if b"sticky" in metadata:
            sticky = metadata.boolget("sticky")
            if self._sticky != sticky:
                self._sticky = sticky
                if sticky:
                    self.stick()
                else:
                    self.unstick()

        if b"skip-taskbar" in metadata:
            skip_taskbar = metadata.boolget("skip-taskbar")
            if self._skip_taskbar != skip_taskbar:
                self._skip_taskbar = skip_taskbar
                self.set_skip_taskbar_hint(skip_taskbar)

        if b"skip-pager" in metadata:
            skip_pager = metadata.boolget("skip-pager")
            if self._skip_pager != skip_pager:
                self._skip_pager = skip_pager
                self.set_skip_taskbar_hint(skip_pager)

        if b"workspace" in metadata:
            self.set_workspace(metadata.intget("workspace"))

        if b"bypass-compositor" in metadata:
            self.set_bypass_compositor(metadata.intget("bypass-compositor"))

        if b"strut" in metadata:
            self.set_strut(metadata.dictget("strut"))

        if b"fullscreen-monitors" in metadata:
            self.set_fullscreen_monitors(
                metadata.intlistget("fullscreen-monitors"))

        if b"shape" in metadata:
            self.set_shape(metadata.dictget("shape"))

        if b"command" in metadata:
            self.set_command(metadata.strget("command"))

        if b"menu" in metadata:
            self.set_menu(metadata.dictget("menu"))
예제 #12
0
    def set_metadata(self, metadata):
        metalog("set_metadata(%s)", metadata)
        #WARNING: "class-instance" needs to go first because others may realize the window
        #(and GTK doesn't set the "class-instance" once the window is realized)
        if b"class-instance" in metadata:
            self.set_class_instance(*self._metadata.strlistget("class-instance", ("xpra", "Xpra")))

        if b"title" in metadata:
            try:
                title = bytestostr(self._client.title).replace("\0", "")
                if title.find("@")>=0:
                    #perform metadata variable substitutions:
                    #full of py3k unicode headaches that don't need to be
                    default_values = {"title"           : "<untitled window>",
                                      "client-machine"  : "<unknown machine>"}
                    def metadata_replace(match):
                        atvar = match.group(0)          #ie: '@title@'
                        var = atvar[1:len(atvar)-1]     #ie: 'title'
                        default_value = default_values.get(var, "<unknown %s>" % var)
                        value = self._metadata.strget(var, default_value)
                        if sys.version<'3':
                            value = value.decode("utf-8")
                        return value
                    title = re.sub("@[\w\-]*@", metadata_replace, title)
                    if sys.version<'3':
                        utf8_title = title.encode("utf-8")
                    else:
                        utf8_title = title
            except Exception as e:
                log.error("error parsing window title: %s", e)
                utf8_title = b""
            self.set_title(utf8_title)

        if b"icon-title" in metadata:
            icon_title = metadata.strget("icon-title")
            self.set_icon_name(icon_title)

        if b"size-constraints" in metadata:
            self.size_constraints = typedict(metadata.dictget("size-constraints"))
            self.set_size_constraints(self.size_constraints, self.max_window_size)

        if b"transient-for" in metadata:
            wid = metadata.intget("transient-for", -1)
            self.apply_transient_for(wid)

        if b"modal" in metadata:
            modal = metadata.boolget("modal")
            self.set_modal(modal)

        #apply window-type hint if window has not been mapped yet:
        if b"window-type" in metadata and not self.is_mapped():
            window_types = metadata.strlistget("window-type")
            self.set_window_type(window_types)

        if b"role" in metadata:
            role = metadata.strget("role")
            self.set_role(role)

        if b"xid" in metadata:
            xid = metadata.strget("xid")
            self.set_xid(xid)

        if b"opacity" in metadata:
            opacity = metadata.intget("opacity", -1)
            if opacity<0:
                opacity = 1
            else:
                opacity = min(1, opacity/float(0xffffffff))
            #requires gtk>=2.12!
            if hasattr(self, "set_opacity"):
                self.set_opacity(opacity)

        if b"has-alpha" in metadata:
            new_alpha = metadata.boolget("has-alpha")
            if new_alpha!=self._has_alpha:
                log.warn("window %s changed its alpha flag from %s to %s (unsupported)", self._id, self._has_alpha, new_alpha)
                self._has_alpha = new_alpha

        if b"maximized" in metadata:
            maximized = metadata.boolget("maximized")
            if maximized!=self._maximized:
                self._maximized = maximized
                if maximized:
                    self.maximize()
                else:
                    self.unmaximize()

        if b"fullscreen" in metadata:
            fullscreen = metadata.boolget("fullscreen")
            if self._fullscreen is None or self._fullscreen!=fullscreen:
                self._fullscreen = fullscreen
                self.set_fullscreen(fullscreen)

        if b"iconic" in metadata:
            iconified = metadata.boolget("iconic")
            if self._iconified!=iconified:
                self._iconified = iconified
                if iconified:
                    self.iconify()
                else:
                    self.deiconify()

        if b"decorations" in metadata:
            self.set_decorated(metadata.boolget("decorations"))
            self.apply_geometry_hints(self.geometry_hints)

        if b"above" in metadata:
            above = metadata.boolget("above")
            if self._above!=above:
                self._above = above
                self.set_keep_above(above)

        if b"below" in metadata:
            below = metadata.boolget("below")
            if self._below!=below:
                self._below = below
                self.set_keep_below(below)

        if b"shaded" in metadata:
            shaded = metadata.boolget("shaded")
            if self._shaded!=shaded:
                self._shaded = shaded
                self.set_shaded(shaded)

        if b"sticky" in metadata:
            sticky = metadata.boolget("sticky")
            if self._sticky!=sticky:
                self._sticky = sticky
                if sticky:
                    self.stick()
                else:
                    self.unstick()

        if b"skip-taskbar" in metadata:
            skip_taskbar = metadata.boolget("skip-taskbar")
            if self._skip_taskbar!=skip_taskbar:
                self._skip_taskbar = skip_taskbar
                self.set_skip_taskbar_hint(skip_taskbar)

        if b"skip-pager" in metadata:
            skip_pager = metadata.boolget("skip-pager")
            if self._skip_pager!=skip_pager:
                self._skip_pager = skip_pager
                self.set_skip_taskbar_hint(skip_pager)

        if b"workspace" in metadata:
            self.set_workspace(metadata.intget("workspace"))

        if b"bypass-compositor" in metadata:
            self.set_bypass_compositor(metadata.intget("bypass-compositor"))

        if b"strut" in metadata:
            self.set_strut(metadata.dictget("strut"))

        if b"fullscreen-monitors" in metadata:
            self.set_fullscreen_monitors(metadata.intlistget("fullscreen-monitors"))

        if b"shape" in metadata:
            self.set_shape(metadata.dictget("shape"))

        if b"command" in metadata:
            self.set_command(metadata.strget("command"))

        if b"menu" in metadata:
            self.set_menu(metadata.dictget("menu"))
예제 #13
0
 def make_cursor(self, cursor_data):
     #if present, try cursor ny name:
     display = display_get_default()
     cursorlog("make_cursor: has-name=%s, has-cursor-types=%s, xscale=%s, yscale=%s, USE_LOCAL_CURSORS=%s", len(cursor_data)>=9, bool(cursor_types), self.xscale, self.yscale, USE_LOCAL_CURSORS)
     #named cursors cannot be scaled (round to 10 to compare so 0.95 and 1.05 are considered the same as 1.0, no scaling):
     if len(cursor_data)>=9 and cursor_types and iround(self.xscale*10)==10 and iround(self.yscale*10)==10:
         cursor_name = bytestostr(cursor_data[8])
         if cursor_name and USE_LOCAL_CURSORS:
             gdk_cursor = cursor_types.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_for_display(display, 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))
     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))
     fw, fh = get_fixed_cursor_size()
     if fw>0 and fh>0 and (w!=fw or h!=fh):
         #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us)
         if w<=fw and h<=fh:
             cursorlog("pasting cursor of size %ix%i onto clear pixbuf of size %ix%i", w, h, fw, fh)
             cursor_pixbuf = get_pixbuf_from_data("\0"*fw*fh*4, True, fw, fh, fw*4)
             pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0)
         else:
             cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i", w, h, fw, fh)
             cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR)
             xratio, yratio = float(w)/fw, float(h)/fh
             x, y = iround(x/xratio), iround(y/yratio)
     else:
         sx, sy, sw, sh = x, y, w, h
         #scale the cursors:
         if self.xscale!=1 or self.yscale!=1:
             sx, sy, sw, sh = self.srect(x, y, w, h)
         sw = max(1, sw)
         sh = max(1, sh)
         #ensure we honour the max size if there is one:
         if (cmaxw>0 and sw>cmaxw) or (cmaxh>0 and sh>cmaxh):
             ratio = 1.0
             if cmaxw>0:
                 ratio = max(ratio, float(w)/cmaxw)
             if cmaxh>0:
                 ratio = max(ratio, float(h)/cmaxh)
             cursorlog("clamping cursor size to %ix%i using ratio=%s", cmaxw, cmaxh, ratio)
             sx, sy, sw, sh = iround(x/ratio), iround(y/ratio), min(cmaxw, iround(w/ratio)), min(cmaxh, iround(h/ratio))
         if sw!=w or sh!=h:
             cursorlog("scaling cursor from %ix%i hotspot at %ix%i to %ix%i hotspot at %ix%i", w, h, x, y, sw, sh, sx, sy)
             cursor_pixbuf = pixbuf.scale_simple(sw, sh, INTERP_BILINEAR)
             x, y = sx, sy
         else:
             cursor_pixbuf = pixbuf
     #clamp to pixbuf size:
     w = cursor_pixbuf.get_width()
     h = cursor_pixbuf.get_height()
     x = max(0, min(x, w-1))
     y = max(0, min(y, h-1))
     try:
         c = new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y)
     except RuntimeError as e:
         log.error("Error: failed to create cursor:")
         log.error(" %s", e)
         log.error(" using %s of size %ix%i with hotspot at %ix%i", cursor_pixbuf, w, h, x, y)
         c = None
     return c
예제 #14
0
 def make_cursor(self, cursor_data):
     #if present, try cursor ny name:
     display = display_get_default()
     if len(cursor_data) >= 9 and cursor_types:
         cursor_name = bytestostr(cursor_data[8])
         if cursor_name:
             gdk_cursor = cursor_types.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_for_display(display, 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))
     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))
     fw, fh = get_fixed_cursor_size()
     if fw > 0 and fh > 0 and (w != fw or h != fh):
         #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us)
         if w <= fw and h <= fh:
             cursorlog(
                 "pasting cursor of size %ix%i onto clear pixbuf of size %ix%i",
                 w, h, fw, fh)
             cursor_pixbuf = get_pixbuf_from_data("\0" * fw * fh * 4, True,
                                                  fw, fh, fw * 4)
             pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0)
         else:
             cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i",
                       w, h, fw, fh)
             cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR)
             xratio, yratio = float(w) / fw, float(h) / fh
             x, y = int(x / xratio), int(y / yratio)
     elif 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)
         x, y, w, h = int(x / ratio), int(y / ratio), int(w / ratio), int(
             h / ratio)
         cursorlog("downscaling cursor %s by %.2f: %sx%s", pixbuf, ratio, w,
                   h)
         cursor_pixbuf = pixbuf.scale_simple(w, h, INTERP_BILINEAR)
     else:
         cursor_pixbuf = pixbuf
     #clamp to pixbuf size:
     w = cursor_pixbuf.get_width()
     h = cursor_pixbuf.get_height()
     x = max(0, min(x, w - 1))
     y = max(0, min(y, h - 1))
     return new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y)
예제 #15
0
파일: menu.py 프로젝트: rudresh2319/Xpra
def setup_dbus_window_menu(add,
                           wid,
                           menus,
                           application_action_callback=None,
                           window_action_callback=None):
    def nomenu():
        #tell caller to clear all properties if they exist:
        return {
            "_GTK_APP_MENU_OBJECT_PATH": None,
            "_GTK_WINDOW_OBJECT_PATH": None,
            "_GTK_APPLICATION_OBJECT_PATH": None,
            "_GTK_UNIQUE_BUS_NAME": None,
            "_GTK_APPLICATION_ID": None
        }

    if add is False:
        return nomenu()
    global window_menu_services, window_menus, fallback_menus
    if len(menus) == 0 and fallback_menus:
        menus = fallback_menus
    #ie: menu = {
    #         'enabled': True,
    #         'application-id':         'org.xpra.ExampleMenu',
    #         'application-actions':    {'quit': (True, '', ()), 'about': (True, '', ()), 'help': (True, '', ()), 'custom': (True, '', ()), 'activate-tab': (True, 's', ()), 'preferences': (True, '', ())},
    #         'window-actions':         {'edit-profile': (True, 's', ()), 'reset': (True, 'b', ()), 'about': (True, '', ()), 'help': (True, '', ()), 'fullscreen': (True, '', (0,)), 'detach-tab': (True, '', ()), 'save-contents': (True, '', ()), 'zoom': (True, 'i', ()), 'move-tab': (True, 'i', ()), 'new-terminal': (True, '(ss)', ()), 'switch-tab': (True, 'i', ()), 'new-profile': (True, '', ()), 'close': (True, 's', ()), 'show-menubar': (True, '', (1,)), 'select-all': (True, '', ()), 'copy': (True, '', ()), 'paste': (True, 's', ()), 'find': (True, 's', ()), 'preferences': (True, '', ())},
    #         'window-menu':            {0:
    #               {0: ({':section': (0, 1)}, {':section': (0, 2)}, {':section': (0, 3)}),
    #                1: ({'action': 'win.new-terminal', 'target': ('default', 'default'), 'label': '_New Terminal'},),
    #                2: ({'action': 'app.preferences', 'label': '_Preferences'},),
    #                3: ({'action': 'app.help', 'label': '_Help'}, {'action': 'app.about', 'label': '_About'}, {'action': 'app.quit', 'label': '_Quit'}),
    #                }
    #             }
    #           }
    enabled = menus.get("enabled", False)
    app_actions_service, window_actions_service, window_menu_service = None, None, None

    def remove_services(*args):
        """ removes all the services if they are not longer used by any windows """
        for x in (app_actions_service, window_actions_service,
                  window_menu_service):
            if x:
                if x not in window_menu_services.values():
                    try:
                        x.remove_from_connection()
                    except Exception as e:
                        log.warn("Error removing %s: %s", x, e)
        try:
            del window_menus[wid]
        except:
            pass

    if enabled:
        m = typedict(menus)
        app_id = bytestostr(
            m.strget("application-id", b"org.xpra.Window%i" % wid)).decode()
        app_actions = m.dictget("application-actions")
        window_actions = m.dictget("window-actions")
        window_menu = m.dictget("window-menu")
    if wid in window_menus:
        #update, destroy or re-create the services:
        app_actions_service, window_actions_service, window_menu_service, cur_app_id = window_menus[
            wid]
        if not enabled or cur_app_id != app_id:
            remove_services(
            )  #falls through to re-create them if enabled is True
            app_actions_service, window_actions_service, window_menu_service = None, None, None
        else:
            #update them:
            app_actions_service.set_actions(app_actions)
            window_actions_service.set_actions(window_actions)
            window_menu_service.set_menus(window_menu)
            return
    if not enabled:
        #tell caller to clear all properties if they exist:
        return nomenu()
    #make or re-use services:
    try:
        NAME_PREFIX = "org.xpra."
        from xpra.util import strtobytes
        from xpra.dbus.common import init_session_bus
        from xpra.dbus.gtk_menuactions import Menus, Actions
        session_bus = init_session_bus()
        bus_name = session_bus.get_unique_name().decode()
        name = app_id
        for strip in ("org.", "gtk.", "xpra.", "gnome."):
            if name.startswith(strip):
                name = name[len(strip):]
        name = NAME_PREFIX + name
        log("normalized named(%s)=%s", app_id, name)

        def get_service(service_class, name, path, *args):
            """ find the service by name and path, or create one """
            service = window_menu_services.get((service_class, name, path))
            if service is None:
                service = service_class(name, path, session_bus, *args)
                window_menu_services[(service_class, name, path)] = service
            return service

        app_path = strtobytes("/" + name.replace(".", "/")).decode()
        app_actions_service = get_service(Actions, name, app_path, app_actions,
                                          application_action_callback)

        #this one should be unique and therefore not re-used? (only one "window_action_callback"..)
        window_path = u"%s/window/%s" % (app_path, wid)
        window_actions_service = get_service(Actions, name, window_path,
                                             window_actions,
                                             window_action_callback)

        menu_path = u"%s/menus/appmenu" % app_path
        window_menu_service = get_service(Menus, app_id, menu_path,
                                          window_menu)
        window_menus[
            wid] = app_actions_service, window_actions_service, window_menu_service, app_id

        return {
            "_GTK_APP_MENU_OBJECT_PATH": ("utf8", menu_path),
            "_GTK_WINDOW_OBJECT_PATH": ("utf8", window_path),
            "_GTK_APPLICATION_OBJECT_PATH": ("utf8", app_path),
            "_GTK_UNIQUE_BUS_NAME": ("utf8", bus_name),
            "_GTK_APPLICATION_ID": ("utf8", app_id),
        }
    except Exception:
        log.error("Error: cannot parse or apply menu:", exc_info=True)
        remove_services()
        return nomenu()