Skip to content

Commit

Permalink
Implement mouse enter and mouse leave events
Browse files Browse the repository at this point in the history
  • Loading branch information
simonkrauter committed May 8, 2024
1 parent 4c0ae23 commit 00ebab3
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 4 deletions.
28 changes: 28 additions & 0 deletions src/nigui.nim
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ type
fOnMouseButtonUp: MouseButtonProc
fOnClick: ClickProc
fOnMouseMove: MouseMoveProc
fOnMouseEnter: MouseMoveProc
fOnMouseLeave: MouseMoveProc
fOnKeyDown: KeyboardProc
tag*: string

Expand Down Expand Up @@ -344,6 +346,8 @@ type
y*: int
MouseButtonProc* = proc(event: MouseEvent)
MouseMoveProc* = proc(event: MouseEvent)
MouseEnterProc* = proc(event: MouseEvent)
MouseLeaveProc* = proc(event: MouseEvent)

ClickEvent* = ref object
control*: Control
Expand Down Expand Up @@ -899,6 +903,12 @@ method `onMouseButtonUp=`*(control: Control, callback: MouseButtonProc) {.base.}
method onMouseMove*(control: Control): MouseMoveProc {.base.}
method `onMouseMove=`*(control: Control, callback: MouseMoveProc) {.base.}

method onMouseEnter*(control: Control): MouseEnterProc {.base.}
method `onMouseEnter=`*(control: Control, callback: MouseEnterProc) {.base.}

method onMouseLeave*(control: Control): MouseLeaveProc {.base.}
method `onMouseLeave=`*(control: Control, callback: MouseLeaveProc) {.base.}

method onClick*(control: Control): ClickProc {.base.}
method `onClick=`*(control: Control, callback: ClickProc) {.base.}

Expand Down Expand Up @@ -2014,6 +2024,18 @@ method handleMouseMoveEvent(control: Control, event: MouseEvent) =
if callback != nil:
callback(event)

method handleMouseEnterEvent(control: Control, event: MouseEvent) =
# can be overridden by custom control
let callback = control.onMouseEnter
if callback != nil:
callback(event)

method handleMouseLeaveEvent(control: Control, event: MouseEvent) =
# can be overridden by custom control
let callback = control.onMouseLeave
if callback != nil:
callback(event)

method handleClickEvent(control: Control, event: ClickEvent) =
# can be overridden by custom button
let callback = control.onClick
Expand Down Expand Up @@ -2041,6 +2063,12 @@ method `onMouseButtonUp=`(control: Control, callback: MouseButtonProc) = control
method onMouseMove(control: Control): MouseMoveProc = control.fOnMouseMove
method `onMouseMove=`(control: Control, callback: MouseMoveProc) = control.fOnMouseMove = callback

method onMouseEnter(control: Control): MouseEnterProc = control.fOnMouseEnter
method `onMouseEnter=`(control: Control, callback: MouseEnterProc) = control.fOnMouseEnter = callback

method onMouseLeave(control: Control): MouseLeaveProc = control.fOnMouseLeave
method `onMouseLeave=`(control: Control, callback: MouseLeaveProc) = control.fOnMouseLeave = callback

method onClick(control: Control): ClickProc = control.fOnClick
method `onClick=`(control: Control, callback: ClickProc) = control.fOnClick = callback

Expand Down
24 changes: 20 additions & 4 deletions src/nigui/private/gtk3/gtk3.nim
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ type
device*: pointer
x_root*, y_root*: cdouble

GdkEventCrossing* {.bycopy.} = object
event_type*: cint
window*: pointer
send_event*: int8
subwindow*: pointer
time*: cint
x*, y*: cdouble
x_root*, y_root*: cdouble
mode*: cint
detail*: cint
focus*: bool
device*: pointer
state*: cint

GdkEventKey* {.bycopy.} = object
event_type*: cint
window*: pointer
Expand Down Expand Up @@ -196,10 +210,12 @@ const
# [..]

# GdkEventMask:
GDK_POINTER_MOTION_MASK* = 4
GDK_BUTTON_PRESS_MASK* = 256
GDK_BUTTON_RELEASE_MASK* = 512
GDK_KEY_PRESS_MASK* = 1024
GDK_POINTER_MOTION_MASK* = 1 shl 4
GDK_BUTTON_PRESS_MASK* = 1 shl 8
GDK_BUTTON_RELEASE_MASK* = 1 shl 9
GDK_KEY_PRESS_MASK* = 1 shl 10
GDK_ENTER_NOTIFY_MASK* = 1 shl 12
GDK_LEAVE_NOTIFY_MASK* = 1 shl 13
# [..]

# cairo_format_t:
Expand Down
18 changes: 18 additions & 0 deletions src/nigui/private/gtk3/platform_impl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,18 @@ proc pControlMotionNotifySignal(widget: pointer, event: var GdkEventMotion, data
evt.y = event.y.int
control.handleMouseMoveEvent(evt)

proc pControlEnterNotifySignal(widget: pointer, event: var GdkEventCrossing, data: pointer): Gboolean {.cdecl.} =
let control = cast[ControlImpl](data)
var evt = new MouseEvent
evt.control = control
control.handleMouseEnterEvent(evt)

proc pControlLeaveNotifySignal(widget: pointer, event: var GdkEventCrossing, data: pointer): Gboolean {.cdecl.} =
let control = cast[ControlImpl](data)
var evt = new MouseEvent
evt.control = control
control.handleMouseLeaveEvent(evt)

proc pControlChangedSignal(widget: pointer, data: pointer): Gboolean {.cdecl.} =
let control = cast[TextBox](data)
var evt = new TextChangeEvent
Expand Down Expand Up @@ -1040,6 +1052,12 @@ proc init(control: ControlImpl) =
gtk_widget_add_events(control.fHandle, GDK_POINTER_MOTION_MASK)
discard g_signal_connect_data(control.fHandle, "motion-notify-event", cast[pointer](pControlMotionNotifySignal), cast[pointer](control))

gtk_widget_add_events(control.fHandle, GDK_ENTER_NOTIFY_MASK)
discard g_signal_connect_data(control.fHandle, "enter-notify-event", cast[pointer](pControlEnterNotifySignal), cast[pointer](control))

gtk_widget_add_events(control.fHandle, GDK_LEAVE_NOTIFY_MASK)
discard g_signal_connect_data(control.fHandle, "leave-notify-event", cast[pointer](pControlLeaveNotifySignal), cast[pointer](control))

control.fIMContext = gtk_im_multicontext_new()
discard g_signal_connect_data(control.fIMContext, "commit", cast[pointer](pControlIMContextCommitSignal), cast[pointer](control))

Expand Down
18 changes: 18 additions & 0 deletions src/nigui/private/windows/platform_impl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var pLastMouseButtonDownControlX: int
var pLastMouseButtonDownControlY: int
var pLastMouseMoveX: int
var pLastMouseMoveY: int
var pLastMouseEnterControl: Control

var appRunning: bool

Expand Down Expand Up @@ -1293,11 +1294,28 @@ proc pCommonControlWndProc(hWnd: pointer, uMsg: int32, wParam, lParam: pointer):
pLastMouseMoveY = y
let control = cast[Control](pGetWindowLongPtr(hWnd, GWLP_USERDATA))
if control != nil:
if control != pLastMouseEnterControl:
pLastMouseEnterControl = control
var event = new MouseEvent
event.control = control
control.handleMouseEnterEvent(event)
var tme: TTrackMouseEvent
tme.cbSize = TTrackMouseEvent.sizeof.int32
tme.dwFlags = TME_LEAVE
tme.hwndTrack = hWnd
discard TrackMouseEvent(tme)
var event = new MouseEvent
event.control = control
event.x = x
event.y = y
control.handleMouseMoveEvent(event)
of WM_MOUSELEAVE:
let control = cast[Control](pGetWindowLongPtr(hWnd, GWLP_USERDATA))
if control != nil:
pLastMouseEnterControl = nil
var event = new MouseEvent
event.control = control
control.handleMouseLeaveEvent(event)
of WM_HSCROLL, WM_VSCROLL:
pCommonControlWndProc_Scroll(hWnd, uMsg, wParam, lParam)

Expand Down
8 changes: 8 additions & 0 deletions src/nigui/private/windows/windows.nim
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ const
# WM_NCLBUTTONDOWN* = 161
# WM_NCLBUTTONUP* = 162
WM_MOUSEWHEEL* = 0x020A
WM_MOUSELEAVE* = 0x02A3
WM_MOVE* = 3
WM_NEXTDLGCTL* = 0x0028
WM_PAINT* = 15
Expand Down Expand Up @@ -243,6 +244,7 @@ const
FontStyleRegular* = 0
FontStyleBold* = 1
TextRenderingHint_AntiAlias* = 4
TME_LEAVE* = 0x00000002


# ----------------------------------------------------------------------------------------
Expand Down Expand Up @@ -396,6 +398,11 @@ type
ptMinTrackSize*: Point
ptMaxTrackSize*: Point

TTrackMouseEvent* {.pure.} = object
cbSize*: int32
dwFlags*: int32
hwndTrack*: pointer
dwHoverTime*: int32


# ----------------------------------------------------------------------------------------
Expand Down Expand Up @@ -498,6 +505,7 @@ proc ScreenToClient*(hWnd: pointer, lpPoint: var Point): bool {.importc, libUser
proc MonitorFromPoint*(pt: Point, dwFlags: int32): pointer {.importc, libUser32.}
proc GetScrollPos*(hWnd: pointer, nBar: int32): int32 {.importc, libUser32.}
proc LockWindowUpdate*(hWndLock: pointer): bool {.importc, libUser32.}
proc TrackMouseEvent*(lpEventTrack: var TTrackMouseEvent): bool {.importc, libUser32.}

type GetDpiForWindowType* = proc(hWnd: pointer): int32 {.gcsafe, stdcall.} # not available on Windows 7

Expand Down

0 comments on commit 00ebab3

Please sign in to comment.