def _nativeSetMousePos(self, px, py): result = Qz.CGWarpMouseCursorPosition( Qz.CGPointMake(float(px), float(py)))
def position(self): loc = NSEvent.mouseLocation() return loc.x, Quartz.CGDisplayPixelsHigh(0) - loc.y
def run(self): tap = Quartz.CGEventTapCreate( Quartz.kCGSessionEventTap, Quartz.kCGHeadInsertEventTap, Quartz.kCGEventTapOptionDefault, Quartz.CGEventMaskBit(Quartz.kCGEventMouseMoved) | Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDown) | Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseUp) | Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseDown) | Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseUp) | Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseDown) | Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseUp), self.handler, None) loopsource = Quartz.CFMachPortCreateRunLoopSource(None, tap, 0) loop = Quartz.CFRunLoopGetCurrent() Quartz.CFRunLoopAddSource(loop, loopsource, Quartz.kCFRunLoopDefaultMode) Quartz.CGEventTapEnable(tap, True) while self.state: Quartz.CFRunLoopRunInMode(Quartz.kCFRunLoopDefaultMode, 5, False)
def press(self, x, y, button=1): event = Quartz.CGEventCreateMouseEvent(None, pressID[button], (x, y), button - 1) Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
def move(self, x, y): move = Quartz.CGEventCreateMouseEvent(None, Quartz.kCGEventMouseMoved, (x, y), 0) Quartz.CGEventPost(Quartz.kCGHIDEventTap, move)
def rclick(x, y, button=2): theEvent = Quartz.CGEventCreateMouseEvent(None, pressID[button], (x, y), button - 1) Quartz.CGEventPost(Quartz.kCGHIDEventTap, theEvent) Quartz.CGEventSetType(theEvent, releaseID[button]) Quartz.CGEventPost(Quartz.kCGHIDEventTap, theEvent)
def drawQuartzRomanText(context): text = b"Quartz" textlen = len(text) fontSize = 60 opaqueBlack = [0.0, 0.0, 0.0, 1.0] opaqueRed = [0.663, 0.0, 0.031, 1.0] # Set the fill color space. This sets the # fill painting color to opaque black. Quartz.CGContextSetFillColorSpace( context, Utilities.getTheCalibratedRGBColorSpace() ) # The Cocoa framework calls the draw method with an undefined # value of the text matrix. It's best to set it to what is needed by # this code: the identity transform. Quartz.CGContextSetTextMatrix(context, Quartz.CGAffineTransformIdentity) # Set the font with the PostScript name "Times-Roman", at # fontSize points, with the MacRoman encoding. Quartz.CGContextSelectFont( context, b"Times-Roman", fontSize, Quartz.kCGEncodingMacRoman ) # The default text drawing mode is fill. Draw the text at (70, 400). Quartz.CGContextShowTextAtPoint(context, 70, 400, text, textlen) # Set the fill color to red. Quartz.CGContextSetFillColor(context, opaqueRed) # Draw the next piece of text where the previous one left off. Quartz.CGContextShowText(context, text, textlen) for i in range(3): # Get the current text pen position. p = Quartz.CGContextGetTextPosition(context) # Translate to the current text pen position. Quartz.CGContextTranslateCTM(context, p.x, p.y) # Rotate clockwise by 90 degrees for the next # piece of text. Quartz.CGContextRotateCTM(context, Utilities.DEGREES_TO_RADIANS(-90)) # Draw the next piece of text in blac at the origin. Quartz.CGContextSetFillColor(context, opaqueBlack) Quartz.CGContextShowTextAtPoint(context, 0, 0, text, textlen) # Draw the next piece of text where the previous piece # left off and paint it with red. Quartz.CGContextSetFillColor(context, opaqueRed) Quartz.CGContextShowText(context, text, textlen)
def _blendMode(self, operation): value = self._blendModeMap[operation] Quartz.CGContextSetBlendMode(self._pdfContext, value)
def _clipPath(self): if self._state.path: self._pdfPath(self._state.path) Quartz.CGContextClip(self._pdfContext)
def _nativeEventCallback(self, *args): try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time = currentSec() if etype == Qz.kCGEventTapDisabledByTimeout: print2err( "** WARNING: Mouse Tap Disabled due to timeout. Re-enabling....: ", etype) Qz.CGEventTapEnable(self._tap, True) return event else: confidence_interval = 0.0 delay = 0.0 iohub_time = logged_time device_time = Qz.CGEventGetTimestamp( event) * self.DEVICE_TIME_TO_SECONDS ioe_type = EventConstants.UNDEFINED px, py = Qz.CGEventGetLocation(event) multi_click_count = Qz.CGEventGetIntegerValueField( event, Qz.kCGMouseEventClickState) mouse_event = NSEvent.eventWithCGEvent_(event) window_handle = mouse_event.windowNumber() # TO DO: Implement multimonitor location based on mouse location support. # Currently always uses monitor index 0 display_index = self.getDisplayIndexForMousePosition( (px, py)) if display_index == -1: if self._last_display_index is not None: display_index = self._last_display_index else: #print2err("!!! _nativeEventCallback error: mouse event pos {0} not in any display bounds!!!".format(event.Position)) #print2err("!!! -> SKIPPING EVENT") #print2err("===============") return event # result=self._validateMousePosition((px,py),display_index) # if result != True: # #print2err("!!! _validateMousePosition made ajustment: {0} to {1}".format((px,py),result)) # nx,ny=result # display_index=self.getDisplayIndexForMousePosition((nx,ny)) # #print2err("Going to Update mousePosition: {0} => {1} on D {2}".format((px,py),(ny,ny),display_index)) # px,py=nx,ny # self._nativeSetMousePos(px,py) px, py = self._display_device._pixel2DisplayCoord( px, py, display_index) self._lastPosition = self._position self._position = px, py self._last_display_index = self._display_index self._display_index = display_index # TO DO: Supported reporting scroll x info for OSX. # This also suggests not having scoll up and down events and # just having the one scroll event type, regardless of direction / dimension scroll_dx = 0 scroll_dy = 0 button_state = 0 if etype in pressID: button_state = MouseConstants.MOUSE_BUTTON_STATE_PRESSED if multi_click_count > 1: ioe_type = EventConstants.MOUSE_MULTI_CLICK else: ioe_type = EventConstants.MOUSE_BUTTON_PRESS elif etype in releaseID: button_state = MouseConstants.MOUSE_BUTTON_STATE_RELEASED ioe_type = EventConstants.MOUSE_BUTTON_RELEASE elif etype in dragID: ioe_type = EventConstants.MOUSE_DRAG elif etype == Qz.kCGEventMouseMoved: ioe_type = EventConstants.MOUSE_MOVE elif etype == Qz.kCGEventScrollWheel: ioe_type = EventConstants.MOUSE_SCROLL scroll_dy = Qz.CGEventGetIntegerValueField( event, Qz.kCGScrollWheelEventPointDeltaAxis1) scroll_dx = Qz.CGEventGetIntegerValueField( event, Qz.kCGScrollWheelEventPointDeltaAxis2) self._scrollPositionX += scroll_dx self._scrollPositionY += scroll_dy iohub_button_id = self._IOHUB_BUTTON_ID_MAPPINGS.get( etype, 0) if iohub_button_id in self.activeButtons: self.activeButtons[iohub_button_id] = int( button_state == MouseConstants.MOUSE_BUTTON_STATE_PRESSED) pressed_buttons = 0 for k, v in self.activeButtons.items(): pressed_buttons += k * v # Create Event List # index 0 and 1 are session and exp. ID's # index 2 is (yet to be used) device_id ioe = self._EVENT_TEMPLATE_LIST ioe[3] = Computer._getNextEventID() ioe[4] = ioe_type #event type code ioe[5] = device_time ioe[6] = logged_time ioe[7] = iohub_time ioe[8] = confidence_interval ioe[9] = delay # index 10 is filter id, not used at this time ioe[11] = display_index ioe[12] = button_state ioe[13] = iohub_button_id ioe[14] = pressed_buttons ioe[15] = px ioe[16] = py ioe[17] = int(scroll_dx) ioe[18] = int(self._scrollPositionX) ioe[19] = int(scroll_dy) ioe[20] = int(self._scrollPositionY) ioe[21] = Keyboard._modifier_value ioe[22] = window_handle self._addNativeEventToBuffer(copy(ioe)) self._last_callback_time = logged_time except Exception: printExceptionDetailsToStdErr() Qz.CGEventTapEnable(self._tap, False) # Must return original event or no mouse events will get to OSX! return event
def __init__(self, *args, **kwargs): MouseDevice.__init__(self, *args, **kwargs['dconfig']) self._tap = Qz.CGEventTapCreate( Qz.kCGSessionEventTap, Qz.kCGHeadInsertEventTap, Qz.kCGEventTapOptionDefault, Qz.CGEventMaskBit(Qz.kCGEventMouseMoved) | Qz.CGEventMaskBit(Qz.kCGEventLeftMouseDown) | Qz.CGEventMaskBit(Qz.kCGEventLeftMouseUp) | Qz.CGEventMaskBit(Qz.kCGEventRightMouseDown) | Qz.CGEventMaskBit(Qz.kCGEventRightMouseUp) | Qz.CGEventMaskBit(Qz.kCGEventLeftMouseDragged) | Qz.CGEventMaskBit(Qz.kCGEventRightMouseDragged) | Qz.CGEventMaskBit(Qz.kCGEventOtherMouseDragged) | Qz.CGEventMaskBit(Qz.kCGEventOtherMouseDown) | Qz.CGEventMaskBit(Qz.kCGEventScrollWheel) | Qz.CGEventMaskBit(Qz.kCGEventOtherMouseUp), self._nativeEventCallback, None) self._scrollPositionX = 0 self._CGEventTapEnable = Qz.CGEventTapEnable self._loop_source = Qz.CFMachPortCreateRunLoopSource( None, self._tap, 0) self._device_loop = Qz.CFRunLoopGetCurrent() self._loop_mode = Qz.kCFRunLoopDefaultMode Qz.CFRunLoopAddSource(self._device_loop, self._loop_source, self._loop_mode)
def _poll(self): self._last_poll_time = currentSec() while Qz.CFRunLoopRunInMode(self._loop_mode, 0.0, True) == Qz.kCFRunLoopRunHandledSource: pass
def _nativeSetSystemCursorVisibility(self, v): if v and not Qz.CGCursorIsVisible(): Qz.CGDisplayShowCursor(Qz.CGMainDisplayID()) elif not v and Qz.CGCursorIsVisible(): Qz.CGDisplayHideCursor(Qz.CGMainDisplayID())
def _nativeGetSystemCursorVisibility(self): return Qz.CGCursorIsVisible()
#!/usr/bin/env python import Quartz #wl = Quartz.CGWindowListCopyWindowInfo( Quartz.kCGWindowListOptionOnScreenOnly | Quartz.kCGWindowListExcludeDesktopElements, Quartz.kCGNullWindowID) wl = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionAll, Quartz.kCGNullWindowID) wl = sorted(wl, key=lambda k: k.valueForKey_('kCGWindowOwnerPID')) #print wl print 'PID'.rjust(7) + ' ' + 'WinID'.rjust(5) + ' ' + 'x,y,w,h'.ljust( 21) + ' ' + '\t[Title] SubTitle' print '-'.rjust(7, '-') + ' ' + '-'.rjust(5, '-') + ' ' + '-'.ljust( 21, '-') + ' ' + '\t-------------------------------------------' for v in wl: print ( \ str(v.valueForKey_('kCGWindowOwnerPID') or '?').rjust(7) + \ ' ' + str(v.valueForKey_('kCGWindowNumber') or '?').rjust(5) + \ ' {' + ('' if v.valueForKey_('kCGWindowBounds') is None else \ ( \ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('X'))) + ',' + \ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Y'))) + ',' + \ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Width'))) + ',' + \ str(int(v.valueForKey_('kCGWindowBounds').valueForKey_('Height'))) \ ) \ ).ljust(21) + \ '}' + \ '\t[' + ((v.valueForKey_('kCGWindowOwnerName') or '') + ']') + \
def _textBox(self, txt, box, align): path, (x, y) = self._getPathForFrameSetter(box) canDoGradients = not isinstance(txt, FormattedString) attrString = self.attributedString(txt, align=align) if self._state.hyphenation: attrString = self.hyphenateAttributedString(attrString, path) setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) frame = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None) ctLines = CoreText.CTFrameGetLines(frame) origins = CoreText.CTFrameGetLineOrigins(frame, (0, len(ctLines)), None) for i, (originX, originY) in enumerate(origins): ctLine = ctLines[i] bounds = CoreText.CTLineGetImageBounds(ctLine, self._pdfContext) if bounds.size.width == 0: continue ctRuns = CoreText.CTLineGetGlyphRuns(ctLine) for ctRun in ctRuns: attributes = CoreText.CTRunGetAttributes(ctRun) fillColor = attributes.get( AppKit.NSForegroundColorAttributeName) strokeColor = attributes.get(AppKit.NSStrokeColorAttributeName) strokeWidth = attributes.get(AppKit.NSStrokeWidthAttributeName, self._state.strokeWidth) baselineShift = attributes.get( AppKit.NSBaselineOffsetAttributeName, 0) self._save() drawingMode = None if self._state.shadow is not None: self._pdfShadow(self._state.shadow) if canDoGradients and self._state.gradient is not None: self._save() self._state.fillColor = self._state.shadow.color self._state.cmykColor = self._state.shadow.cmykColor self._pdfFillColor() self._state.fillColor = None self._state.cmykColor = None Quartz.CGContextSetTextDrawingMode( self._pdfContext, Quartz.kCGTextFill) Quartz.CGContextSetTextPosition( self._pdfContext, x + originX, y + originY + baselineShift) CoreText.CTRunDraw(ctRun, self._pdfContext, (0, 0)) self._restore() if canDoGradients and self._state.gradient is not None: self._save() Quartz.CGContextSetTextDrawingMode(self._pdfContext, Quartz.kCGTextClip) Quartz.CGContextSetTextPosition( self._pdfContext, x + originX, y + originY + baselineShift) CoreText.CTRunDraw(ctRun, self._pdfContext, (0, 0)) self._pdfGradient(self._state.gradient) self._restore() drawingMode = None elif fillColor is not None: drawingMode = Quartz.kCGTextFill self._pdfFillColor(fillColor) if strokeColor is not None: drawingMode = Quartz.kCGTextStroke self._pdfStrokeColor(strokeColor) Quartz.CGContextSetLineWidth(self._pdfContext, abs(strokeWidth)) if self._state.lineDash is not None: Quartz.CGContextSetLineDash(self._pdfContext, 0, self._state.lineDash, len(self._state.lineDash)) if self._state.miterLimit is not None: Quartz.CGContextSetMiterLimit(self._pdfContext, self._state.miterLimit) if self._state.lineCap is not None: Quartz.CGContextSetLineCap(self._pdfContext, self._state.lineCap) if self._state.lineJoin is not None: Quartz.CGContextSetLineJoin(self._pdfContext, self._state.lineJoin) if fillColor is not None and strokeColor is not None: drawingMode = Quartz.kCGTextFillStroke if macOSVersion >= "10.11" and macOSVersion < "10.13": # solve bug in OSX where the stroke color is the same as the fill color # simple solution: draw it twice... drawingMode = Quartz.kCGTextFill Quartz.CGContextSetTextDrawingMode( self._pdfContext, drawingMode) Quartz.CGContextSetTextPosition( self._pdfContext, x + originX, y + originY + baselineShift) CoreText.CTRunDraw(ctRun, self._pdfContext, (0, 0)) drawingMode = Quartz.kCGTextStroke if drawingMode is not None: Quartz.CGContextSetTextDrawingMode(self._pdfContext, drawingMode) Quartz.CGContextSetTextPosition( self._pdfContext, x + originX, y + originY + baselineShift) CoreText.CTRunDraw(ctRun, self._pdfContext, (0, 0)) self._restore()
def click(x, y, button=1): theEvent = Quartz.CGEventCreateMouseEvent(None, pressID[button], (x, y), button - 1) Quartz.CGEventPost(Quartz.kCGHIDEventTap, theEvent) Quartz.CGEventSetType(theEvent, Quartz.kCGEventLeftMouseUp) Quartz.CGEventPost(Quartz.kCGHIDEventTap, theEvent)
def _transform(self, transform): Quartz.CGContextConcatCTM(self._pdfContext, transform)
def drawQuartzTextWithTextMatrix(context): fontSize = 60.0 extraLeading = 10.0 text = b"Quartz " textlen = len(text) # The Cocoa framework calls the draw method with an undefined # value of the text matrix. It's best to set it to what is needed by # this code. Initially that is the identity transform. Quartz.CGContextSetTextMatrix(context, Quartz.CGAffineTransformIdentity) # Set the font with the PostScript name "Times-Roman", at # fontSize points, with the MacRoman encoding. Quartz.CGContextSelectFont( context, b"Times-Roman", fontSize, Quartz.kCGEncodingMacRoman ) # ---- Text Line 1 ---- # Draw the text at (10, 600). Quartz.CGContextShowTextAtPoint(context, 10, 600, text, textlen) # Get the current text position. The text pen is at the trailing # point from the text just drawn. textPosition = Quartz.CGContextGetTextPosition(context) # Set the text matrix to one that flips text in y and sets # the text position to the user space coordinate (0,0). t = Quartz.CGAffineTransformMake(1, 0, 0, -1, 0, 0) Quartz.CGContextSetTextMatrix(context, t) # Set the text position to the point where the previous text ended. Quartz.CGContextSetTextPosition(context, textPosition.x, textPosition.y) # Draw the text at the current text position. It will be drawn # flipped in y, relative to the text drawn previously. Quartz.CGContextShowText(context, text, textlen) # ---- Text Line 2 ---- # Translate down for the next piece of text. Quartz.CGContextTranslateCTM(context, 0, -(3 * fontSize + extraLeading)) Quartz.CGContextSaveGState(context) if 1: # Change the text matrix to {1, 0, 0, 3, 0, 0}, which # scales text by a factor of 1 in x and 3 in y. # This scaling doesn't affect any drawing other than text # drawing since only text drawing is transformed by # the text matrix. t = Quartz.CGAffineTransformMake(1, 0, 0, 3, 0, 0) Quartz.CGContextSetTextMatrix(context, t) # This text is scaled relative to the previous text # because of the text matrix scaling. Quartz.CGContextShowTextAtPoint(context, 10, 600, text, textlen) # This restores the graphics state to what it was at the time # of the last Quartz.CGContextSaveGState, but since the text matrix # isn't part of the Quartz graphics state, it isn't affected. Quartz.CGContextRestoreGState(context) # The text matrix isn't affected by Quartz.CGContextSaveGState and # Quartz.CGContextRestoreGState. You can see this by observing that # the next text piece appears immediately after the first piece # and with the same text scaling as that text drawn with the # text matrix established before we did CGContextRestoreGState. Quartz.CGContextShowText(context, text, textlen) # ---- Text Line 3 ---- # Translate down for the next piece of text. Quartz.CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) # Reset the text matrix to the identity matrix. Quartz.CGContextSetTextMatrix(context, Quartz.CGAffineTransformIdentity) # Now draw text in a flipped coordinate system. Quartz.CGContextSaveGState(context) if 1: # Flip the coordinate system to mimic a coordinate system with the origin # at the top-left corner of a window. The new origin is at 600 units in # +y from the old origin and the y axis now increases with positive y # going down the window. Quartz.CGContextConcatCTM( context, Quartz.CGAffineTransformMake(1, 0, 0, -1, 0, 600) ) # This text will be flipped along with the CTM. Quartz.CGContextShowTextAtPoint(context, 10, 10, text, textlen) # Obtain the user space coordinates of the current text position. textPosition = Quartz.CGContextGetTextPosition(context) # Draw text at that point but flipped in y. showFlippedTextAtPoint(context, textPosition.x, textPosition.y, text, textlen) Quartz.CGContextRestoreGState(context)
def _cmykNSColorToCGColor(self, c): return Quartz.CGColorCreateGenericCMYK(c.cyanComponent(), c.magentaComponent(), c.yellowComponent(), c.blackComponent(), c.alphaComponent())
def drawQuartzTextWithTextModes(context): fillText = b"Fill " strokeText = b"Stroke " fillAndStrokeText = b"FillStroke " invisibleText = b"Invisible " clipText = b"ClipText " fillStrokeClipText = b"FillStrokeClip " fontSize = 40.0 extraLeading = 5.0 dash = (1, 1) opaqueRed = (1.0, 0.0, 0.0, 1.0) # Set the fill and stroke color space. This sets the # fill and stroke painting color to opaque black. Quartz.CGContextSetFillColorSpace( context, Utilities.getTheCalibratedRGBColorSpace() ) Quartz.CGContextSetStrokeColorSpace( context, Utilities.getTheCalibratedRGBColorSpace() ) # The Cocoa framework calls the draw method with an undefined # value of the text matrix. It's best to set it to what is needed by # this code: the identity transform. Quartz.CGContextSetTextMatrix(context, Quartz.CGAffineTransformIdentity) # Set the font with the PostScript name "Times-Roman", at # fontSize points, with the MacRoman encoding. Quartz.CGContextSelectFont( context, b"Times-Roman", fontSize, Quartz.kCGEncodingMacRoman ) # ---- Text Line 1 ---- # Default text drawing mode is fill. Draw the text at (10, 400). Quartz.CGContextShowTextAtPoint(context, 10, 400, fillText, len(fillText)) # Set the fill color to red. Quartz.CGContextSetFillColor(context, opaqueRed) Quartz.CGContextSetTextPosition(context, 180, 400) Quartz.CGContextShowText(context, fillText, len(fillText)) # Translate down for the next line of text. Quartz.CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) # ---- Text Line 2 ---- # Now stroke the text by setting the text drawing mode # to kCGTextStroke. When stroking text, Quartz uses the stroke # color in the graphics state. Quartz.CGContextSetTextDrawingMode(context, Quartz.kCGTextStroke) Quartz.CGContextShowTextAtPoint(context, 10, 400, strokeText, len(strokeText)) # When stroking text, the line width and other gstate parameters # that affect stroking affect text stroking as well. Quartz.CGContextSetLineWidth(context, 2) Quartz.CGContextSetLineDash(context, 0, dash, 2) Quartz.CGContextSetTextPosition(context, 180, 400) Quartz.CGContextShowText(context, strokeText, len(strokeText)) # Reset the line dash and line width to their defaults. Quartz.CGContextSetLineDash(context, 0, None, 0) Quartz.CGContextSetLineWidth(context, 1) # Translate down for the next line of text. Quartz.CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) # ---- Text Line 3 ---- # Set the text drawing mode so that text is both filled and # stroked. This produces text that is filled with the fill # color and stroked with the stroke color. Quartz.CGContextSetTextDrawingMode(context, Quartz.kCGTextFillStroke) Quartz.CGContextShowTextAtPoint( context, 10, 400, fillAndStrokeText, len(fillAndStrokeText) ) # Now draw again with a thicker stroke width. Quartz.CGContextSetLineWidth(context, 2) Quartz.CGContextSetTextPosition(context, 180, 400) Quartz.CGContextShowText(context, fillAndStrokeText, len(fillAndStrokeText)) Quartz.CGContextSetLineWidth(context, 1) Quartz.CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) # ---- Text Line 4 ---- # Set the text drawing mode to invisible so that the next piece of # text does not appear. Quartz updates the text position as # if it had been drawn. Quartz.CGContextSetTextDrawingMode(context, Quartz.kCGTextInvisible) Quartz.CGContextShowTextAtPoint(context, 10, 400, invisibleText, len(invisibleText)) Quartz.CGContextSetTextDrawingMode(context, Quartz.kCGTextFill) Quartz.CGContextSetTextPosition(context, 180, 400) Quartz.CGContextShowText(context, fillText, len(fillText)) Quartz.CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) # ---- Text Line 5 ---- Quartz.CGContextSaveGState(context) if 1: # Use the text as a clipping path. Quartz.CGContextSetTextDrawingMode(context, Quartz.kCGTextClip) Quartz.CGContextShowTextAtPoint(context, 10, 400, clipText, len(clipText)) # Position and draw a grid of lines. Quartz.CGContextTranslateCTM(context, 10, 400) drawGridLines(context) Quartz.CGContextRestoreGState(context) Quartz.CGContextSaveGState(context) if 1: # The current text position is that after the last piece # of text has been drawn. Since CGContextSaveGState/ # CGContextRestoreGState do not affect the text position or # the text matrix, the text position is that after the last # text was "drawn", that drawn with the kCGTextClip mode # above. This is where the next text drawn will go if it # isn't explicitly positioned. nextTextPosition = Quartz.CGContextGetTextPosition(context) # Draw so that the text is filled, stroked, and then used # the clip subsequent drawing. Quartz.CGContextSetTextDrawingMode(context, Quartz.kCGTextFillStrokeClip) # Explicitly set the text position. Quartz.CGContextSetTextPosition(context, 180, 400) nextTextPosition = Quartz.CGContextGetTextPosition(context) Quartz.CGContextShowText(context, fillStrokeClipText, len(fillStrokeClipText)) # Adjust the location of the grid lines so that they overlap the # text just drawn. Quartz.CGContextTranslateCTM(context, nextTextPosition.x, nextTextPosition.y) # Draw the grid lines clipped by the text. drawGridLines(context) Quartz.CGContextRestoreGState(context)
def _linkRect(self, name, xywh): x, y, w, h = xywh rectBox = Quartz.CGRectMake(x, y, w, h) Quartz.CGPDFContextSetDestinationForRect(self._pdfContext, name, rectBox)
def release(self, x, y, button=1): event = Quartz.CGEventCreateMouseEvent(None, releaseID[button], (x, y), button - 1) Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
def _closeContext(self): Quartz.CGContextEndPage(self._pdfContext) Quartz.CGPDFContextClose(self._pdfContext) self._hasContext = False
def drag(self, x, y): drag = Quartz.CGEventCreateMouseEvent(None, Quartz.kCGEventLeftMouseDragged, (x, y), 0) Quartz.CGEventPost(Quartz.kCGHIDEventTap, drag)
def _save(self): Quartz.CGContextSaveGState(self._pdfContext)
def screen_size(self): return Quartz.CGDisplayPixelsWide(0), Quartz.CGDisplayPixelsHigh(0)
def _restore(self): Quartz.CGContextRestoreGState(self._pdfContext)
def PressKey(keycode): event = Quartz.CGEventCreateKeyboardEvent(None, keycode, 1) Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
def event_handler(self, proxy, event_type, event, *args): if event_type in [Quartz.kCGEventKeyDown, Quartz.kCGEventKeyUp]: scan_code = Quartz.CGEventGetIntegerValueField( event, Quartz.kCGKeyboardEventKeycode) keyboard_key = keyboard_scan_code_mapping.get(scan_code) if keyboard_key is None: return event keyboard_event = KeyboardEvents.UP if event_type == Quartz.kCGEventKeyUp else KeyboardEvents.DOWN self.callback(KeyboardEvent(keyboard_event, keyboard_key)) elif event_type == Quartz.kCGEventFlagsChanged: scan_code = Quartz.CGEventGetIntegerValueField( event, Quartz.kCGKeyboardEventKeycode) keyboard_key = keyboard_scan_code_mapping.get(scan_code) if keyboard_key is None: return event flags = Quartz.CGEventGetFlags(event) if scan_code in [56, 60 ] and (flags & Quartz.kCGEventFlagMaskShift): keyboard_event = KeyboardEvents.DOWN elif scan_code == 57 and (flags & Quartz.kCGEventFlagMaskAlphaShift): keyboard_event = KeyboardEvents.DOWN elif scan_code in [ 58, 61 ] and (flags & Quartz.kCGEventFlagMaskAlternate): keyboard_event = KeyboardEvents.DOWN elif scan_code in [59, 62 ] and (flags & Quartz.kCGEventFlagMaskControl): keyboard_event = KeyboardEvents.DOWN elif scan_code in [54, 55 ] and (flags & Quartz.kCGEventFlagMaskCommand): keyboard_event = KeyboardEvents.DOWN else: keyboard_event = KeyboardEvents.UP self.callback(KeyboardEvent(keyboard_event, keyboard_key)) elif event_type in (mouse_click_down_events + mouse_click_up_events): direction = "DOWN" if event_type in mouse_click_down_events else "UP" x, y = [int(i) for i in Quartz.CGEventGetLocation(event)] if event_type in mouse_button_mapping: button = mouse_button_mapping[event_type] else: button_number = Quartz.CGEventGetIntegerValueField( event, Quartz.kCGMouseEventButtonNumber) if (button_number + 1024) in mouse_button_mapping: button = mouse_button_mapping[button_number + 1024] else: return event self.callback( MouseEvent(MouseEvents.CLICK, button=button, direction=direction, x=x, y=y)) elif event_type == Quartz.kCGEventScrollWheel: x, y = [int(i) for i in Quartz.CGEventGetLocation(event)] velocity = Quartz.CGEventGetIntegerValueField( event, Quartz.kCGScrollWheelEventDeltaAxis1) direction = "UP" if velocity > 0 else "DOWN" self.callback( MouseEvent(MouseEvents.SCROLL, direction=direction, velocity=abs(velocity), x=x, y=y)) elif event_type == Quartz.kCGEventMouseMoved: x, y = [int(i) for i in Quartz.CGEventGetLocation(event)] self.callback(MouseEvent(MouseEvents.MOVE, x=x, y=y)) else: return event return event