Example #1
0
func (i *imagelist) apply(hwnd C.HWND, uMsg C.UINT) {
	width := C.GetSystemMetrics(C.SM_CXSMICON)
	height := C.GetSystemMetrics(C.SM_CYSMICON)
	il := C.newImageList(width, height)
	for index := range i.list {
		C.addImage(il, hwnd, i.list[index], C.int(i.width[index]), C.int(i.height[index]), width, height)
	}
	C.SendMessageW(hwnd, uMsg, 0, C.LPARAM(uintptr(unsafe.Pointer(il))))
}
Example #2
0
//export finishAreaMouseEvent
func finishAreaMouseEvent(data unsafe.Pointer, cbutton C.DWORD, up C.BOOL, heldButtons C.uintptr_t, xpos C.int, ypos C.int) {
	var me MouseEvent

	a := (*area)(data)
	button := uint(cbutton)
	me.Pos = image.Pt(int(xpos), int(ypos))
	if !me.Pos.In(image.Rect(0, 0, a.width, a.height)) { // outside the actual Area; no event
		return
	}
	if up != C.FALSE {
		me.Up = button
	} else if button != 0 { // don't run the click counter if the mouse was only moved
		me.Down = button
		// this returns a LONG, which is int32, but we don't need to worry about the signedness because for the same bit widths and two's complement arithmetic, s1-s2 == u1-u2 if bits(s1)==bits(s2) and bits(u1)==bits(u2) (and Windows requires two's complement: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/27/422551.aspx)
		// signedness isn't much of an issue for these calls anyway because http://stackoverflow.com/questions/24022225/what-are-the-sign-extension-rules-for-calling-windows-api-functions-stdcall-t and that we're only using unsigned values (think back to how you (didn't) handle signedness in assembly language) AND because of the above AND because the statistics below (time interval and width/height) really don't make sense if negative
		time := C.GetMessageTime()
		maxTime := C.GetDoubleClickTime()
		// ignore zero returns and errors; MSDN says zero will be returned on error but that GetLastError() is meaningless
		xdist := C.GetSystemMetrics(C.SM_CXDOUBLECLK)
		ydist := C.GetSystemMetrics(C.SM_CYDOUBLECLK)
		me.Count = a.clickCounter.click(button, me.Pos.X, me.Pos.Y,
			uintptr(time), uintptr(maxTime), int(xdist/2), int(ydist/2))
	}
	// though wparam will contain control and shift state, let's use just one function to get modifiers for both keyboard and mouse events; it'll work the same anyway since we have to do this for alt and windows key (super)
	me.Modifiers = getModifiers()
	if button != 1 && (heldButtons&C.MK_LBUTTON) != 0 {
		me.Held = append(me.Held, 1)
	}
	if button != 2 && (heldButtons&C.MK_MBUTTON) != 0 {
		me.Held = append(me.Held, 2)
	}
	if button != 3 && (heldButtons&C.MK_RBUTTON) != 0 {
		me.Held = append(me.Held, 3)
	}
	if button != 4 && (heldButtons&C.MK_XBUTTON1) != 0 {
		me.Held = append(me.Held, 4)
	}
	if button != 5 && (heldButtons&C.MK_XBUTTON2) != 0 {
		me.Held = append(me.Held, 5)
	}
	a.handler.Mouse(me)
}
Example #3
0
func (b *button) preferredSize(d *sizing) (width, height int) {
	// comctl32.dll version 6 thankfully provides a method to grab this...
	var size C.SIZE

	size.cx = 0 // explicitly ask for ideal size
	size.cy = 0
	if C.SendMessageW(b._hwnd, C.BCM_GETIDEALSIZE, 0, C.LPARAM(uintptr(unsafe.Pointer(&size)))) != C.FALSE {
		return int(size.cx), int(size.cy)
	}
	// that failed, fall back
	println("message failed; falling back")
	// don't worry about the error return from GetSystemMetrics(); there's no way to tell (explicitly documented as such)
	xmargins := 2 * int(C.GetSystemMetrics(C.SM_CXEDGE))
	return xmargins + int(b._textlen), fromdlgunitsY(buttonHeight, d)
}
Example #4
0
func mouseIsLeft() bool {
	return C.GetSystemMetrics(C.SM_SWAPBUTTON) == C.TRUE
}
Example #5
0
func (wi *windowInternal) processEvent(message C.UINT, wParam C.WPARAM, lParam C.LPARAM) (events []Event, eventErrors []ThreadError) {
	// Don't process any message until window is created
	if wi.window.Handle == nil {
		return
	}

	switch message {
	case C.WM_DESTROY: // Destroy event
		// Here we must cleanup resources !
		wi.cleanup()
	case C.WM_ACTIVATE:
		// TODO fullscreen handling
		if wi.monitor == nil || !wi.monitor.IsValid() {
			break
		}

		// Were we deactivated/iconified?
		wi.inactive = C.__LOWORD(C.DWORD(wParam)) == C.WA_INACTIVE
		minimized := C.__HIWORD(C.DWORD(wParam)) != 0

		if (wi.inactive || minimized) && !wi.minimized {
			// _glfwInputDeactivation();

			// If we are in fullscreen mode we need to iconify
			if wi.monitor != nil && wi.monitor.IsValid() {
				// Do we need to manually iconify?
				if err := ChangeDisplaySettingsExW(&wi.monitor.internal.info.szDevice[0], nil, nil, 0, nil); err != nil {
					// TODO: Error handling
					panic(err)
				}

				if !minimized {
					// Minimize window
					// C.SetWindowULong(wi.window.Handle, C.GWL_STYLE, C.WS_POPUP)
					// C.SetWindowLong(wi.window.Handle, C.GWL_EXSTYLE, 0)
					// C.SetWindowPos(wi.window.Handle, HWND_BOTTOM, 1, 1, 10, 10, C.SWP_HIDEWINDOW)
					C.ShowWindow(wi.window.Handle, C.SW_MINIMIZE)
					minimized = true
				}

				// Restore the original desktop resolution
				if err := ChangeDisplaySettingsExW(&wi.monitor.internal.info.szDevice[0], nil, nil, 0, nil); err != nil {
					// TODO: Error handling
					panic(err)
				}

			}

			// Unlock mouse if locked
			// if !_glfwWin.oldMouseLockValid {
			// 	_glfwWin.oldMouseLock = _glfwWin.mouseLock;
			// 	_glfwWin.oldMouseLockValid = GL_TRUE;
			// 	glfwEnable( GLFW_MOUSE_CURSOR );
			// }
		} else if !wi.inactive || !minimized {
			// If we are in fullscreen mode we need to maximize
			if wi.monitor != nil && wi.monitor.IsValid() && wi.minimized {
				// Change display settings to the user selected mode
				if err := ChangeDisplaySettingsExW(&wi.monitor.internal.info.szDevice[0], wi.devMode, nil, C.CDS_FULLSCREEN, nil); err != nil {
					// TODO error handling
					panic(err)
				}

				// Do we need to manually restore window?
				if minimized {
					// Restore window
					C.ShowWindow(wi.window.Handle, C.SW_RESTORE)
					minimized = false

					// Activate window
					C.ShowWindow(wi.window.Handle, C.SW_SHOW)
					// setForegroundWindow( _glfwWin.window );
					C.SetFocus(wi.window.Handle)
				}

				// Lock mouse, if necessary
				// if _glfwWin.oldMouseLockValid && _glfwWin.oldMouseLock {
				// 	glfwDisable( GLFW_MOUSE_CURSOR );
				// }
				// _glfwWin.oldMouseLockValid = GL_FALSE;
			}
		}

		wi.minimized = minimized

	case C.WM_SETCURSOR: // Set cursor event
		// The mouse has moved, if the cursor is in our window we must refresh the cursor
		if C.__LOWORD(C.DWORD(lParam)) == C.HTCLIENT {
			C.SetCursor(wi.cursor)
		}

	case C.WM_CLOSE: // Close event
		events = append(events, WindowClosedEvent{})

	case C.WM_SIZE: // Resize event
		// Consider only events triggered by a maximize or a un-maximize
		if wParam == C.SIZE_MINIMIZED || wi.resizing {
			break
		}

		// Ignore cases where the window has only been moved
		if x, y := wi.getSize(); wi.lastSizeX == x && wi.lastSizeY == y {
			break
		}

		events = append(events, WindowResizeEvent{
			Width:  wi.lastSizeX,
			Height: wi.lastSizeY,
		})

	case C.WM_ENTERSIZEMOVE: // Start resizing
		wi.resizing = true

	case C.WM_EXITSIZEMOVE: // Stop resizing
		wi.resizing = false
		// Ignore cases where the window has only been moved
		if x, y := wi.getSize(); wi.lastSizeX == x && wi.lastSizeY == y {
			break
		} else {
			wi.lastSizeX, wi.lastSizeY = x, y
		}

		events = append(events, WindowResizeEvent{
			Width:  wi.lastSizeX,
			Height: wi.lastSizeY,
		})

	case C.WM_KILLFOCUS: // Lost focus event
		events = append(events, WindowGainedFocusEvent{})

	case C.WM_SETFOCUS: // Gain focus event
		events = append(events, WindowLostFocusEvent{})

	case C.WM_CHAR: // Text event
		if !wi.keyRepeatEnabled && lParam&(1<<30) != 0 {
			break
		}

		events = append(events, TextEnteredEvent{
			Character: rune(wParam),
		})

	case C.WM_KEYDOWN, C.WM_SYSKEYDOWN: // Keydown event
		if !wi.keyRepeatEnabled && C.__HIWORD(C.DWORD(lParam))&C.KF_REPEAT != 0 {
			break
		}

		events = append(events, KeyPressedEvent{
			Code:    virtualKeyCodeToSF(wParam, lParam),
			Alt:     C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_MENU))) != 0,
			Control: C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_CONTROL))) != 0,
			Shift:   C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_SHIFT))) != 0,
			System:  C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_LWIN))) != 0 || C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_RWIN))) != 0,
		})

	case C.WM_KEYUP, C.WM_SYSKEYUP: // Keyup event
		events = append(events, KeyReleasedEvent{
			Code:    virtualKeyCodeToSF(wParam, lParam),
			Alt:     C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_MENU))) != 0,
			Control: C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_CONTROL))) != 0,
			Shift:   C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_SHIFT))) != 0,
			System:  C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_LWIN))) != 0 || C.__HIWORD(C.DWORD(C.GetAsyncKeyState(C.VK_RWIN))) != 0,
		})

	case C.WM_MOUSEWHEEL: // Mouse wheel event
		// Mouse position is in screen coordinates, convert it to window coordinates
		position := C.POINT{
			x: C.LONG(C.__LOWORD(C.DWORD(lParam))),
			y: C.LONG(C.__HIWORD(C.DWORD(lParam))),
		}
		C.__ScreenToClient(wi.window.Handle, &position)

		events = append(events, MouseWheelEvent{
			Delta: int(int16(C.__HIWORD(C.DWORD(wParam))) / 120),
			X:     int(position.x),
			Y:     int(position.y),
		})

	case C.WM_LBUTTONDOWN, C.WM_RBUTTONDOWN: // Mouse left/right button down event
		button := mouse_vkeys_handed_map[mouseKey{message, C.GetSystemMetrics(C.SM_SWAPBUTTON) == C.TRUE}]
		events = append(events, MouseButtonPressedEvent{
			Button: button,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_LBUTTONUP, C.WM_RBUTTONUP: // Mouse left/right button up event
		button := mouse_vkeys_handed_map[mouseKey{message, C.GetSystemMetrics(C.SM_SWAPBUTTON) == C.TRUE}]
		events = append(events, MouseButtonReleasedEvent{
			Button: button,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_MBUTTONDOWN: // Mouse wheel button down event
		events = append(events, MouseButtonPressedEvent{
			Button: MouseMiddle,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_MBUTTONUP: // Mouse wheel button up event
		events = append(events, MouseButtonReleasedEvent{
			Button: MouseMiddle,
			X:      int(C.__LOWORD(C.DWORD(lParam))),
			Y:      int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_XBUTTONDOWN: // Mouse X button down event
		event := MouseButtonPressedEvent{
			X: int(C.__LOWORD(C.DWORD(lParam))),
			Y: int(C.__HIWORD(C.DWORD(lParam))),
		}

		switch C.__HIWORD(C.DWORD(wParam)) {
		default:
			fallthrough
		case C.XBUTTON1:
			event.Button = MouseXButton1
		case C.XBUTTON2:
			event.Button = MouseXButton2

		}
		events = append(events, event)

	case C.WM_XBUTTONUP: // Mouse X button up event
		event := MouseButtonPressedEvent{
			X: int(C.__LOWORD(C.DWORD(lParam))),
			Y: int(C.__HIWORD(C.DWORD(lParam))),
		}

		switch C.__HIWORD(C.DWORD(wParam)) {
		default:
			fallthrough
		case C.XBUTTON1:
			event.Button = MouseXButton1
		case C.XBUTTON2:
			event.Button = MouseXButton2

		}
		events = append(events, event)

	case C.WM_MOUSEMOVE: // Mouse move event
		// Check if we need to generate a MouseEntered event
		if !wi.isCursorIn {
			mouseEvent := C.TRACKMOUSEEVENT{
				cbSize:    C.TRACKMOUSEEVENT_size,
				hwndTrack: wi.window.Handle,
				dwFlags:   C.TME_LEAVE,
			}
			C.__TrackMouseEvent(&mouseEvent)

			wi.isCursorIn = true

			events = append(events, MouseEnteredEvent{})
		}

		events = append(events, MouseMoveEvent{
			X: int(C.__LOWORD(C.DWORD(lParam))),
			Y: int(C.__HIWORD(C.DWORD(lParam))),
		})

	case C.WM_MOUSELEAVE: // Mouse leave event
		wi.isCursorIn = false
		events = append(events, MouseLeftEvent{})

	}

	return
}