Exemplo n.º 1
0
 def serve():
     while True:
         xevent = self.requests.get()
         self.requests.task_done()
         if xevent is None:
             break
         elif xevent.type == X.SelectionRequest:
             client_prop = process_request(xevent.requestor,
                                           xevent.property,
                                           xevent.target)
             selection_notify = event.SelectionNotify(
                 time=xevent.time,
                 requestor=xevent.requestor,
                 selection=xevent.selection,
                 target=xevent.target,
                 property=client_prop,
             )
             xevent.requestor.send_event(selection_notify,
                                         onerror=errHandler)
             try:
                 self.display.flush()
             except Exception as e:
                 ErrorReporter.print(e)
                 self.reset()
                 break
         elif xevent.type == X.SelectionClear:
             while not self.requests.empty():
                 try:
                     self.requests.get_nowait()
                     self.requests.task_done()
                 except Empty:
                     break
             self.content_set = False
             break
         elif xevent.type == X.SelectionNotify and xevent.property == X.NONE:
             print('Failed to transfer ownership to Clipboard Manager',
                   file=sys.stderr)
             break
Exemplo n.º 2
0
    def process_outgoing(self):
        def process_request(client, property, target):

            prop_set = True
            if property == X.NONE:
                client_prop = target
            else:
                client_prop = property
            if target == self.TARGETS:
                prop_value = [self.TARGETS, self.SAVE_TARGETS]
                prop_value += [
                    target for target, data in content.items() if data
                ]
                prop_type = Xatom.ATOM
                prop_format = 32
            elif target in content:
                data = content[target]
                if isinstance(data, str):
                    prop_value = data.encode()
                elif isinstance(data, ByteString):
                    prop_value = data
                else:
                    client_prop = X.NONE
                prop_type = target
                prop_format = 8
            elif target == self.MULTIPLE:
                wanted_prop = client.get_full_property(client_prop,
                                                       X.AnyPropertyType)
                if wanted_prop:
                    wanted = [
                        wanted_prop.value[i:i + 2]
                        for i in range(0, len(wanted_prop.value), 2)
                    ]
                    for target, prop in wanted:
                        process_request(client, prop, target)
                    prop_set = False
                else:
                    client_prop = X.NONE
            else:
                client_prop = X.NONE
            if client_prop != X.NONE and prop_set:
                client.change_property(client_prop, prop_type, prop_format,
                                       prop_value)
            return client_prop

        while True:
            content = self.outbox.get()
            self.outbox.task_done()
            self.setter_window.set_selection_owner(self.SELECTION,
                                                   X.CurrentTime)
            self.display.flush()
            current_owner = self.display.get_selection_owner(self.SELECTION)
            if current_owner == self.setter_window:
                while True:
                    xevent = self.requests.get()
                    self.requests.task_done()
                    if xevent.type == X.SelectionRequest:
                        client_prop = process_request(xevent.requestor,
                                                      xevent.property,
                                                      xevent.target)
                        selection_notify = event.SelectionNotify(
                            time=xevent.time,
                            requestor=xevent.requestor,
                            selection=xevent.selection,
                            target=xevent.target,
                            property=client_prop)
                        xevent.requestor.send_event(selection_notify)
                        self.display.flush()
                    elif xevent.type == X.SelectionClear:
                        while not self.requests.empty():
                            try:
                                self.requests.get_nowait()
                                self.requests.task_done()
                            except Empty:
                                break
                        self.content_set = False
                        break
                    elif xevent.type == X.SelectionNotify:
                        if xevent.property == X.NONE:
                            print('Failed to transfer ownership to ' +
                                  'Clipboard Manager')
Exemplo n.º 3
0
def main():
    if len(sys.argv) < 3:
        sys.exit('usage: {0} SELECTION TYPE [FILE [TYPE [FILE...]]]\n\n'
                 'SELECTION is typically PRIMARY, SECONDARY or CLIPBOARD.\n'
                 'If FILE is omitted, stdin is read.\n'
                 'Multiple type/file combos can be specified.\n'
                 .format(sys.argv[0]))

    args = sys.argv[1:]

    d = display.Display()

    sel_name = args[0]
    del args[0]
    sel_atom = d.get_atom(sel_name)

    # map type atom -> data
    types = {}

    while args:
        type_atom = d.get_atom(args[0])
        del args[0]

        if args:
            f = open(args[0], 'rb')
            del args[0]
        else:
            f = sys.stdin

        # Limit selection size to avoid implementing INCR
        data = f.read(MAX_SIZE)
        f.close()

        if len(data) >= MAX_SIZE:
            log('too much data: {0} bytes, max is {1} bytes', len(data), MAX_SIZE)
            error('INCR support not implemented to put larger files')

        types[type_atom] = data


    targets_atom = d.get_atom('TARGETS')


    # We must have a window to own a selection
    w = d.screen().root.create_window(
        0, 0, 10, 10, 0, X.CopyFromParent)

    # And to grab the selection we must have a timestamp, get one with
    # a property notify when we're anyway setting wm_name
    w.change_attributes(event_mask = X.PropertyChangeMask)
    w.set_wm_name(os.path.basename(sys.argv[0]))

    e = d.next_event()
    sel_time = e.time
    w.change_attributes(event_mask = 0)

    # Grab the selection and make sure we actually got it
    w.set_selection_owner(sel_atom, sel_time)
    if d.get_selection_owner(sel_atom) != w:
        log('could not take ownership of {0}', sel_name)
        return

    log('took ownership of selection {0}', sel_name)

    # The event loop, waiting for and processing requests
    while True:
        e = d.next_event()

        if (e.type == X.SelectionRequest
            and e.owner == w
            and e.selection == sel_atom):

            client = e.requestor

            if e.property == X.NONE:
                log('request from obsolete client!')
                client_prop = e.target # per ICCCM recommendation
            else:
                client_prop = e.property

            target_name = d.get_atom_name(e.target)

            log('got request for {0}, dest {1} on 0x{2:08x} {3}',
                target_name, d.get_atom_name(client_prop),
                client.id, client.get_wm_name())

            # Is the client asking for which types we support?
            if e.target == targets_atom:
                # Then respond with TARGETS and the type
                prop_value = [targets_atom] + types.keys()
                prop_type = Xatom.ATOM
                prop_format = 32

            # Request for the offered type
            elif e.target in types:
                prop_value = types[e.target]
                prop_type = e.target
                prop_format = 8

            # Something else, tell client they can't get it
            else:
                log('refusing conversion to {0}', target_name)
                client_prop = X.NONE

            # Put the data on the dest window, if possible
            if client_prop != X.NONE:
                client.change_property(
                    client_prop, prop_type, prop_format, prop_value)

            # And always send a selection notification
            ev = event.SelectionNotify(
                time = e.time,
                requestor = e.requestor,
                selection = e.selection,
                target = e.target,
                property = client_prop)

            client.send_event(ev)

            # Done!

        elif (e.type == X.SelectionClear
              and e.window == w
              and e.atom == sel_atom):
            log('lost ownership of selection {0}', sel_name)
            return