mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-30 03:21:29 +02:00
Draw inverted monochrome cursor pixels so the text caret is visible
This commit is contained in:
@@ -43,6 +43,7 @@ var (
|
||||
procCreateJobObjectW = kernel32.NewProc("CreateJobObjectW")
|
||||
procSetInformationJobObject = kernel32.NewProc("SetInformationJobObject")
|
||||
procAssignProcessToJobObject = kernel32.NewProc("AssignProcessToJobObject")
|
||||
procIsProcessInJob = kernel32.NewProc("IsProcessInJob")
|
||||
procSetTokenInformation = advapi32.NewProc("SetTokenInformation")
|
||||
procCreateEnvironmentBlock = userenv.NewProc("CreateEnvironmentBlock")
|
||||
procDestroyEnvironmentBlock = userenv.NewProc("DestroyEnvironmentBlock")
|
||||
@@ -323,7 +324,13 @@ func spawnAgentInSession(sessionID uint32, socketPath, authToken string, jobHand
|
||||
if jobHandle != 0 {
|
||||
r, _, e := procAssignProcessToJobObject.Call(uintptr(jobHandle), uintptr(pi.Process))
|
||||
if r == 0 {
|
||||
log.Warnf("assign agent to job object: %v (orphan possible on service crash)", e)
|
||||
// Report the job state of both ends: assignment is refused when the
|
||||
// child already belongs to a job that will not accept ours, which is
|
||||
// the difference between a breakaway that did not happen and a
|
||||
// rights problem on the handles.
|
||||
log.Warnf("assign agent to job object: %v (orphan possible on service crash); "+
|
||||
"daemon in a job: %s, agent in a job: %s",
|
||||
e, describeInJob(windows.CurrentProcess()), describeInJob(pi.Process))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,6 +411,21 @@ func newSessionManager() *sessionManager {
|
||||
return m
|
||||
}
|
||||
|
||||
// describeInJob reports whether a process belongs to any job object, for the
|
||||
// diagnostic on a failed assignment. Returns the error text when the query
|
||||
// itself fails, since that is equally informative there.
|
||||
func describeInJob(h windows.Handle) string {
|
||||
var inJob int32
|
||||
r, _, e := procIsProcessInJob.Call(uintptr(h), 0, uintptr(unsafe.Pointer(&inJob)))
|
||||
if r == 0 {
|
||||
return fmt.Sprintf("unknown (%v)", e)
|
||||
}
|
||||
if inJob != 0 {
|
||||
return "yes"
|
||||
}
|
||||
return "no"
|
||||
}
|
||||
|
||||
// createKillOnCloseJob returns a Job Object configured so that closing its
|
||||
// handle (process exit or explicit Close) terminates every process assigned
|
||||
// to it. Used to keep orphaned vnc-agent processes from outliving the service.
|
||||
|
||||
@@ -337,15 +337,30 @@ func decodeMonoCursor(hbmMask windows.Handle) (*image.RGBA, error) {
|
||||
img := image.NewRGBA(image.Rect(0, 0, int(w), int(h)))
|
||||
for y := int32(0); y < h; y++ {
|
||||
for x := int32(0); x < w; x++ {
|
||||
and := data[(y*w+x)*4]
|
||||
xor := data[((y+h)*w+x)*4]
|
||||
and := data[(y*w+x)*4] != 0
|
||||
xor := data[((y+h)*w+x)*4] != 0
|
||||
di := (y*w + x) * 4
|
||||
if and != 0 {
|
||||
|
||||
// The two halves of the mask encode four states:
|
||||
//
|
||||
// AND=0 XOR=0 black
|
||||
// AND=0 XOR=1 white
|
||||
// AND=1 XOR=0 transparent
|
||||
// AND=1 XOR=1 inverts whatever is on screen
|
||||
//
|
||||
// The cursor pseudo-encoding has no inversion, and the text
|
||||
// caret (IDC_IBEAM) is drawn almost entirely from inverted
|
||||
// pixels, which is how it stays legible over both light and dark
|
||||
// text. Reading them as transparent left it invisible while
|
||||
// every other stock cursor rendered, so they are drawn black
|
||||
// here: that is what the other VNC servers settle on, and text
|
||||
// fields are light far more often than not.
|
||||
if and && !xor {
|
||||
img.Pix[di+3] = 0
|
||||
continue
|
||||
}
|
||||
c := byte(0)
|
||||
if xor != 0 {
|
||||
if !and && xor {
|
||||
c = 255
|
||||
}
|
||||
img.Pix[di+0] = c
|
||||
|
||||
Reference in New Issue
Block a user