def PressKeyOSX(hexKeyCode): global lastKey lastKey = hexKeyCode print("prepush") event = CoreGraphics.CGEventCreateKeyboardEvent(None, hexKeyCode, True) CoreGraphics.CGEventPost(CoreGraphics.kCGHIDEventTap, event) print("push")
def screenshot(*args): if len(args) == 4: x, y, w, h = args elif len(args) == 3 and isinstance(args[0], Point): x, y = args[0] w, h = args[1:] else: raise Exception('Error! Bad input to screenshot.') norm_w = SCREENSHOT_WIDTHS[np.searchsorted(SCREENSHOT_WIDTHS, w)] region = CG.CGRectMake(x, y, norm_w, h) image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) provider = CG.CGImageGetDataProvider(image) bin_data = CG.CGDataProviderCopyData(provider) data_format = "%dB" % norm_w * h * 4 unpacked = struct.unpack_from(data_format, bin_data) if norm_w == w: return np.array(unpacked, dtype=np.uint8).reshape(h, w, 4) else: return np.array(unpacked, dtype=np.uint8).reshape(h, norm_w, 4)[:, :w]
def button_action(self, pointer, button, pressed, _deviceid=-1, *args): if button <= 3: #we should be using CGEventCreateMouseEvent #instead we clear previous clicks when a "higher" button is pressed... oh well args = [] for i in range(button): args.append(i == (button - 1) and pressed) log("CG.CGPostMouseEvent(%s, %s, %s, %s)", pointer[:2], 1, button, args) CG.CGPostMouseEvent(pointer[:2], 1, button, *args) else: if not pressed: #we don't simulate press/unpress #so just ignore unpressed events return wheel = (button - 2) // 2 direction = 1 - (((button - 2) % 2) * 2) args = [] for i in range(wheel): if i != (wheel - 1): args.append(0) else: args.append(direction) log("CG.CGPostScrollWheelEvent(%s, %s)", wheel, args) CG.CGPostScrollWheelEvent(wheel, *args)
def cgimage_screen_capture(self, region=None): """ inputs region: Quartz.CoreGraphics CGRect """ if region is None: region = CG.CGRectInfinite elif region.size.width % 2 > 0: raise ValueError( "Capture region width: %s should be even to avoid warp" % region.size.width) image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) image_get_data_provider = CG.CGImageGetDataProvider(image) self.screen_capture_byte_data = CG.CGDataProviderCopyData( image_get_data_provider) # Get width/height of image self.screen_capture_width = CG.CGImageGetWidth(image) self.screen_capture_height = CG.CGImageGetHeight(image)
def _process_button_action(self, proto, packet): wid, button, pressed, pointer, modifiers = packet[1:6] log("process_button_action(%s, %s)", proto, packet) self._update_modifiers(proto, wid, modifiers) self._process_mouse_common(proto, wid, pointer) pointer = self._adjust_pointer(pointer) if button <= 3: #we should be using CGEventCreateMouseEvent #instead we clear previous clicks when a "higher" button is pressed... oh well args = [] for i in range(button): args.append(i == (button - 1) and pressed) log("CG.CGPostMouseEvent(%s, %s, %s, %s)", pointer, 1, button, args) CG.CGPostMouseEvent(pointer, 1, button, *args) else: if not pressed: #we don't simulate press/unpress #so just ignore unpressed events return wheel = (button - 2) // 2 direction = 1 - (((button - 2) % 2) * 2) args = [] for i in range(wheel): if i != (wheel - 1): args.append(0) else: args.append(direction) log("CG.CGPostScrollWheelEvent(%s, %s)", wheel, args) CG.CGPostScrollWheelEvent(wheel, *args)
def screenshot(region=None, dpi=72, cv2_format=False): if region is None: region = CG.CGRectInfinite else: region = CG.CGRectMake(*region) image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) file_name = '.screenshot-{0}.png'.format( datetime.datetime.now().strftime('%Y-%m%d_%H-%M-%S-%f')) file_type = LaunchServices.kUTTypePNG file_url = NSURL.fileURLWithPath_(file_name) dest = Quartz.CGImageDestinationCreateWithURL(file_url, file_type, 1, None) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, } Quartz.CGImageDestinationAddImage(dest, image, properties) Quartz.CGImageDestinationFinalize(dest) if cv2_format: image = cv2.imread(file_name) else: image = Image.open(file_name) os.unlink(file_name) return image
def update(self, _): region = CG.CGRectInfinite # Create screenshot as CGImage t = time.time() image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) bytesperrow = CG.CGImageGetBytesPerRow(image) pixeldata = CG.CGDataProviderCopyData(CG.CGImageGetDataProvider(image)) image = numpy.frombuffer(pixeldata, dtype=numpy.uint8) image = image.reshape((2400, bytesperrow // 4, 4)) # image = image[:, :width, :] im_rgb = cv2.cvtColor(image, cv2.COLOR_RGBA2BGR) image = cv2.flip(im_rgb, 0) image = cv2.resize(image, (1920, 1200)) # pilimage = Image.fromarray(image) # print(pilimage.size) # cv2.imwrite("CG.png",image) fgmask = self.fgbg.apply(image) # dst = cv2.bitwise_or(image, image, mask=fgmask) # image = Image.frombytes("RGB", sct_img.size, sct_img.bgra, "raw", "BGRX") # imgdata=numpy.fromstring(_data,dtype=numpy.uint8).tobytes() # image = image.resize((int(image.width / 2), int(image.height / 2))) self.texture.blit_buffer(dst.tobytes(), colorfmt='rgb') with self.widget.canvas: Rectangle(texture=self.texture, pos=(0, 0), size=Window.size) print(time.time() - t)
def fake_key(self, keycode, press): log.info("fake_key(%s, %s)", keycode, press) e = CG.CGEventCreateKeyboardEvent(None, keycode, press) #CGEventSetFlags(keyPress, modifierFlags) #modifierFlags: kCGEventFlagMaskShift, ... CG.CGEventPost(CG.kCGSessionEventTap, e) CG.CFRelease(e)
def get_CG_imagewrapper(rect=None): from xpra.codecs.image_wrapper import ImageWrapper assert CG, "cannot capture without Quartz.CoreGraphics" if rect is None: x = 0 y = 0 region = CG.CGRectInfinite else: x, y, w, h = rect region = CG.CGRectMake(x, y, roundup(w, 2), roundup(h, 2)) image = CG.CGWindowListCreateImage( region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageNominalResolution) #CG.kCGWindowImageDefault) width = CG.CGImageGetWidth(image) height = CG.CGImageGetHeight(image) bpc = CG.CGImageGetBitsPerComponent(image) bpp = CG.CGImageGetBitsPerPixel(image) rowstride = CG.CGImageGetBytesPerRow(image) alpha = CG.CGImageGetAlphaInfo(image) alpha_str = ALPHA.get(alpha, alpha) log( "get_CG_imagewrapper(..) image size: %sx%s, bpc=%s, bpp=%s, rowstride=%s, alpha=%s", width, height, bpc, bpp, rowstride, alpha_str) prov = CG.CGImageGetDataProvider(image) argb = CG.CGDataProviderCopyData(prov) return ImageWrapper(x, y, width, height, argb, "BGRX", 24, rowstride)
def createPDFDocumentFromPath(path): global verbose if verbose: print "Creating PDF document from file %s" % (path) return CG.CGPDFDocumentCreateWithURL( CG.CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False))
def capture_osx(self): region = CG.CGRectInfinite # [Create screenshot as CGImage]: image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) # [Intermediate step, get pixel data as CGDataProvider]: prov = CG.CGImageGetDataProvider(image) # [Copy data out of CGDataProvider, becomes string of bytes]: self._data = CG.CGDataProviderCopyData(prov) # [Get width/height of image]: self._width = CG.CGImageGetWidth(image) self._height = CG.CGImageGetHeight(image) # [Get raw pixels from the screen, save it to a Numpy array as RGB]: imgdata = numpy.frombuffer(self._data, dtype=numpy.uint8).reshape( int(len(self._data) / 4), 4) _numpy_bgr = imgdata[:self._width * self._height, :-1].reshape( self._height, self._width, 3) _numpy_rgb = _numpy_bgr[..., ::-1] self._numpy = _numpy_rgb
def capture(self, region=None): """region should be a CGRect, something like: >>> import Quartz.CoreGraphics as CG >>> region = CG.CGRectMake(0, 0, 100, 100) >>> sp = ScreenPixel() >>> sp.capture(region=region) The default region is CG.CGRectInfinite (captures the full screen) """ if region is None: region = CG.CGRectInfinite else: # TODO: Odd widths cause the image to warp. This is likely # caused by offset calculation in ScreenPixel.pixel, and # could could modified to allow odd-widths if region.size.width % 2 > 0: emsg = "Capture region width should be even (was %s)" % ( region.size.width) raise ValueError(emsg) # Create screenshot as CGImage image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) # Intermediate step, get pixel data as CGDataProvider prov = CG.CGImageGetDataProvider(image) # Copy data out of CGDataProvider, becomes string of bytes self._data = CG.CGDataProviderCopyData(prov) # Get width/height of image self.width = CG.CGImageGetWidth(image) self.height = CG.CGImageGetHeight(image)
def __enter__(self): if self.rect is None: result = CG.CGContextBeginTransparencyLayer(self.context, self.info) else: result = CG.CGContextBeginTransparencyLayerWithRect( self.context, self.rect, self.info ) return result
def createOutputContextWithPath(path): global verbose if verbose: print "Setting %s as the destination." % (path) return CG.CGPDFContextCreateWithURL( CG.CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False), None, None)
def move_mouse(self): x = random.randint(0, self.width) y = random.randint(0, self.height) #create the event move = CG.CGEventCreateMouseEvent(None, CG.kCGEventMouseMoved, CG.CGPointMake(x, y), CG.kCGMouseButtonLeft) #send the event CG.CGEventPost(CG.kCGHIDEventTap, move)
def get_icc_info(): #maybe we shouldn't return anything if there's more than one display? info = {} try: did = CG.CGMainDisplayID() info = get_colorspace_info(CG.CGDisplayCopyColorSpace(did)) except Exception as e: log("failed to query colorspace for main display: %s", e) return info
def release_key(self, hex_key_code): """ Releases key specified by a hex code. :param int hex_key_code: hexadecimal code for a key to be pressed. """ CG.CGEventPost( CG.kCGHIDEventTap, CG.CGEventCreateKeyboardEvent(None, hex_key_code, False))
def press_key_and_hold(self, hex_key_code): """ Presses (and holds) key specified by a hex code. :param int hex_key_code: hexadecimal code for a key to be pressed. """ CG.CGEventPost( CG.kCGHIDEventTap, CG.CGEventCreateKeyboardEvent(None, hex_key_code, True))
def get_display_icc_info(): info = {} try: err, active_displays, no = CG.CGGetActiveDisplayList(99, None, None) if err == 0 and no > 0: for i, adid in enumerate(active_displays): info[i] = get_colorspace_info(CG.CGDisplayCopyColorSpace(adid)) except Exception as e: log("failed to query colorspace for active displays: %s", e) return info
def get_icc_info(): #maybe we shouldn't return anything if there's more than one display? info = {} try: from Quartz import CoreGraphics as CG #@UnresolvedImport did = CG.CGMainDisplayID() info = get_colorspace_info(CG.CGDisplayCopyColorSpace(did)) except Exception as e: log("failed to query colorspace for main display: %s", e) return info
def double_click(self, x, y, button_name=LEFT_BUTTON, click_interval=0.5): MacUtils.verify_xy_coordinates(x, y) MacUtils.verify_mouse_button_name(button_name, self._SUPPORTED_BUTTON_NAMES) if button_name == self.LEFT_BUTTON: button = CG.kCGMouseButtonLeft down = CG.kCGEventLeftMouseDown up = CG.kCGEventLeftMouseUp if button_name == self.RIGHT_BUTTON: button = CG.kCGMouseButtonRight down = CG.kCGEventRightMouseDown up = CG.kCGEventRightMouseUp # http://www.codeitive.com/0iJqgkejVj/performing-a-double-click-using-cgeventcreatemouseevent.html event = CG.CGEventCreateMouseEvent(None, down, (x, y), button) CG.CGEventPost(CG.kCGSessionEventTap, event) CG.CGEventSetType(event, up) CG.CGEventPost(CG.kCGSessionEventTap, event) CG.CGEventSetIntegerValueField(event, CG.kCGMouseEventClickState, 2) # https://msdn.microsoft.com/en-us/library/windows/desktop/ms646263%28v=vs.85%29.aspx sleep(click_interval) CG.CGEventSetType(event, down) CG.CGEventPost(CG.kCGSessionEventTap, event) CG.CGEventSetType(event, up) CG.CGEventPost(CG.kCGSessionEventTap, event)
def double_click(self, x, y, button_name=LEFT_BUTTON): MacUtils.verify_xy_coordinates(x, y) MacUtils.verify_mouse_button_name(button_name, self._SUPPORTED_BUTTON_NAMES) if button_name == self.LEFT_BUTTON: button = CG.kCGMouseButtonLeft down = CG.kCGEventLeftMouseDown up = CG.kCGEventLeftMouseUp if button_name == self.RIGHT_BUTTON: button = CG.kCGMouseButtonRight down = CG.kCGEventRightMouseDown up = CG.kCGEventRightMouseUp # http://www.codeitive.com/0iJqgkejVj/performing-a-double-click-using-cgeventcreatemouseevent.html event = CG.CGEventCreateMouseEvent(None, down, (x, y), button) CG.CGEventPost(CG.kCGHIDEventTap, event) CG.CGEventSetType(event, up) CG.CGEventPost(CG.kCGHIDEventTap, event) CG.CGEventSetIntegerValueField(event, CG.kCGMouseEventClickState, 2) CG.CGEventSetType(event, down) CG.CGEventPost(CG.kCGHIDEventTap, event) CG.CGEventSetType(event, up) CG.CGEventPost(CG.kCGHIDEventTap, event)
def _mouse_event(self, event_type, x, y, mouse_button=CG.kCGMouseButtonLeft): if mouse_button not in [CG.kCGMouseButtonLeft, CG.kCGMouseButtonRight]: raise TypeError('Pikuli.MacMouse: incorrect mouse button type') evt = CG.CGEventCreateMouseEvent(None, event_type, (x, y), mouse_button) CG.CGEventPost(CG.kCGHIDEventTap, evt) return evt
def capture(): global screenshot_width global screenshot_data region = CG.CGRectInfinite # Create screenshot as CGImage image = CG.CGWindowListCreateImage(region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) prov = CG.CGImageGetDataProvider(image) screenshot_data = CG.CGDataProviderCopyData(prov) screenshot_width = CG.CGImageGetWidth(image)
def press_key_and_hold(self, hex_key_code): """Presses (and holds) key specified by a hex code. Arguments: - hex_key_code: integer value holding hexadecimal code for a key to be pressed. Returns: - None """ CG.CGEventPost(CG.kCGHIDEventTap, CG.CGEventCreateKeyboardEvent(None, hex_key_code, True))
def event(self, key: str, down: bool): """ Create a Core Graphics keyboard event and post it for macOS to process """ try: event = CG.CGEventCreateKeyboardEvent(None, self.KeyMap[key.lower()], down) if key.isupper(): CG.CGEventSetFlags( event, CG.kCGEventFlagMaskShift | CG.CGEventGetFlags(event)) CG.CGEventPost(CG.kCGHIDEventTap, event) except KeyError: raise NotImplementedError(f"Key '{key}' is not implemented")
def release_key(self, hex_key_code): """Releases key specified by a hex code. Arguments: - hex_key_code: integer value holding hexadecimal code for a key to be pressed. Returns: - None """ CG.CGEventPost( CG.kCGHIDEventTap, CG.CGEventCreateKeyboardEvent(None, hex_key_code, False))
def get_pixel_data(region: Optional[Region] = None): region = (CoreGraphics.CGRectInfinite if region is None else CoreGraphics.CGRectMake(region.x1, region.y1, region.x2 - region.x1, region.y2 - region.y1)) image = CoreGraphics.CGWindowListCreateImage( region, CoreGraphics.kCGWindowListOptionOnScreenOnly, CoreGraphics.kCGNullWindowID, CoreGraphics.kCGWindowImageDefault, ) pixel_data = CoreGraphics.CGDataProviderCopyData( CoreGraphics.CGImageGetDataProvider(image)) bytes_per_row = CoreGraphics.CGImageGetBytesPerRow(image) // 4 return pixel_data, bytes_per_row
def get_displays_info(): did = CG.CGMainDisplayID() info = { "main": get_display_info(did), } err, active_displays, no = CG.CGGetActiveDisplayList(99, None, None) if err == 0 and no > 0: for i, adid in enumerate(active_displays): info.setdefault("active", {})[i] = get_display_info(adid) err, online_displays, no = CG.CGGetOnlineDisplayList(99, None, None) if err == 0 and no > 0: for i, odid in enumerate(online_displays): info.setdefault("online", {})[i] = get_display_info(odid) return info
def takeScreenshot(self): image = CG.CGWindowListCreateImage(CG.CGRectInfinite, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault) prov = CG.CGImageGetDataProvider(image) _data = CG.CGDataProviderCopyData(prov) width = CG.CGImageGetWidth(image) height = CG.CGImageGetHeight(image) imgdata = np.frombuffer(_data, dtype=np.uint8).reshape(int(len(_data) / 4.0), 4) numpy_img = imgdata[:width * height, :-1].reshape(height, width, 3) return numpy_img