github.com/jmigpin/editor@v1.6.0/driver/xdriver/xcursors/cursors.go (about) 1 package xcursors 2 3 import ( 4 "image/color" 5 6 "github.com/BurntSushi/xgb" 7 "github.com/BurntSushi/xgb/xproto" 8 "github.com/jmigpin/editor/util/imageutil" 9 ) 10 11 // https://tronche.com/gui/x/xlib/appendix/b/ 12 13 type Cursors struct { 14 conn *xgb.Conn 15 win xproto.Window 16 m map[Cursor]xproto.Cursor 17 } 18 19 func NewCursors(conn *xgb.Conn, win xproto.Window) (*Cursors, error) { 20 cs := &Cursors{ 21 conn: conn, 22 win: win, 23 m: make(map[Cursor]xproto.Cursor), 24 } 25 return cs, nil 26 } 27 func (cs *Cursors) SetCursor(c Cursor) error { 28 xc, ok := cs.m[c] 29 if !ok { 30 xc2, err := cs.loadCursor(c) 31 if err != nil { 32 return err 33 } 34 cs.m[c] = xc2 35 xc = xc2 36 } 37 mask := uint32(xproto.CwCursor) 38 values := []uint32{uint32(xc)} 39 _ = xproto.ChangeWindowAttributes(cs.conn, cs.win, mask, values) 40 return nil 41 } 42 func (cs *Cursors) loadCursor(c Cursor) (xproto.Cursor, error) { 43 return cs.loadCursor2(c, color.Black, color.White) 44 } 45 func (cs *Cursors) loadCursor2(c Cursor, fg, bg color.Color) (xproto.Cursor, error) { 46 if c == XCNone { 47 return 0, nil 48 } 49 fontId, err := xproto.NewFontId(cs.conn) 50 if err != nil { 51 return 0, err 52 } 53 cursor, err := xproto.NewCursorId(cs.conn) 54 if err != nil { 55 return 0, err 56 } 57 name := "cursor" 58 err = xproto.OpenFontChecked(cs.conn, fontId, uint16(len(name)), name).Check() 59 if err != nil { 60 return 0, err 61 } 62 63 // colors 64 ur, ug, ub, _ := imageutil.ColorUint16s(fg) 65 vr, vg, vb, _ := imageutil.ColorUint16s(bg) 66 67 err = xproto.CreateGlyphCursorChecked( 68 cs.conn, cursor, 69 fontId, fontId, 70 uint16(c), uint16(c)+1, 71 ur, ug, ub, 72 vr, vg, vb).Check() 73 if err != nil { 74 return 0, err 75 } 76 77 err = xproto.CloseFontChecked(cs.conn, fontId).Check() 78 if err != nil { 79 return 0, err 80 } 81 82 return cursor, nil 83 } 84 85 type Cursor uint16 86 87 // Just to distinguish from the other cursors (uint16) to reset to parent window cursor. Value after last x cursor at 152. 88 const XCNone = 200 89 90 const ( 91 XCursor = 0 92 Arrow = 2 93 BasedArrowDown = 4 94 BasedArrowUp = 6 95 Boat = 8 96 Bogosity = 10 97 BottomLeftCorner = 12 98 BottomRightCorner = 14 99 BottomSide = 16 100 BottomTee = 18 101 BoxSpiral = 20 102 CenterPtr = 22 103 Circle = 24 104 Clock = 26 105 CoffeeMug = 28 106 Cross = 30 107 CrossReverse = 32 108 Crosshair = 34 109 DiamondCross = 36 110 Dot = 38 111 DotBoxMask = 40 112 DoubleArrow = 42 113 DraftLarge = 44 114 DraftSmall = 46 115 DrapedBox = 48 116 Exchange = 50 117 Fleur = 52 118 Gobbler = 54 119 Gumby = 56 120 Hand1 = 58 121 Hand2 = 60 122 Heart = 62 123 Icon = 64 124 IronCross = 66 125 LeftPtr = 68 126 LeftSide = 70 127 LeftTee = 72 128 LeftButton = 74 129 LLAngle = 76 130 LRAngle = 78 131 Man = 80 132 MiddleButton = 82 133 Mouse = 84 134 Pencil = 86 135 Pirate = 88 136 Plus = 90 137 QuestionArrow = 92 138 RightPtr = 94 139 RightSide = 96 140 RightTee = 98 141 RightButton = 100 142 RtlLogo = 102 143 Sailboat = 104 144 SBDownArrow = 106 145 SBHDoubleArrow = 108 146 SBLeftArrow = 110 147 SBRightArrow = 112 148 SBUpArrow = 114 149 SBVDoubleArrow = 116 150 Shuttle = 118 151 Sizing = 120 152 Spider = 122 153 Spraycan = 124 154 Star = 126 155 Target = 128 156 TCross = 130 157 TopLeftArrow = 132 158 TopLeftCorner = 134 159 TopRightCorner = 136 160 TopSide = 138 161 TopTee = 140 162 Trek = 142 163 ULAngle = 144 164 Umbrella = 146 165 URAngle = 148 166 Watch = 150 167 XTerm = 152 168 )