diff options
author | Kevin Walzer <kw@codebykevin.com> | 2020-10-20 02:12:21 (GMT) |
---|---|---|
committer | Kevin Walzer <kw@codebykevin.com> | 2020-10-20 02:12:21 (GMT) |
commit | 1752aa31f611b6517d2f99596bc97cf9cdab0671 (patch) | |
tree | b80242b6b2d0392f6545beff9dbebe86e2899440 | |
parent | e602f49377f47a8ea74ea71dd0de9fd79158aa79 (diff) | |
download | tk-1752aa31f611b6517d2f99596bc97cf9cdab0671.zip tk-1752aa31f611b6517d2f99596bc97cf9cdab0671.tar.gz tk-1752aa31f611b6517d2f99596bc97cf9cdab0671.tar.bz2 |
Tentative implementation of button-1 and button-2 bindings; still need to test on Win and X11
-rw-r--r-- | library/systray.tcl | 77 | ||||
-rw-r--r-- | macosx/tkMacOSXSysTray.c | 153 |
2 files changed, 148 insertions, 82 deletions
diff --git a/library/systray.tcl b/library/systray.tcl index b7a5ac0..4e9aab8 100644 --- a/library/systray.tcl +++ b/library/systray.tcl @@ -37,9 +37,15 @@ proc _balloon_show {w arg} { # Additional infrastructure for Windows callbacks. proc _win_callback {msg icn script} { + global _cb_1 + global _cb_2 + switch -exact -- $msg { WM_LBUTTONDOWN { - eval $script + eval $_cb2 + } + WM_RBUTTONDOWN { + eval $cb_1 } } } @@ -110,6 +116,10 @@ global _ico set _ico "" global _iconlist set _iconlist {} +global _cb_1 +set _cb_1 "" +global _cb_2 +set _cb_2 "" # systray -- # This procedure creates an icon display in the platform-specific system tray. @@ -120,12 +130,15 @@ set _iconlist {} # Arguments: # image - Tk image to display. # text - string to display in tooltip over image. -# callback - Tcl proc to invoke on <Button-1> event. +# b1_callback - Tcl proc to invoke on <Button-1> event. +# b2_callback - Tcl proc to invoke on <Button-2> event. + # modify - change one of the systray properties. # Arguments (only one required): # image - Tk image to update. # text - string to update. -# callback - Tcl proc to change. +# b1_callback - Tcl proc to change. +# b2_callback - Tcl proc to change. # destroy - destroy systray icon. # Arguments: # none. @@ -142,11 +155,14 @@ proc ::tk::systray {args} { #Set variables for icon properties. global _ico - global _iconlist + global _iconlist + global _cb_1 + global _cb_2 set _img "" set _txt "" - set _cb "" + set _cb_1 "" + set _cb_2 "" #Remove the systray icon. if {[lindex $args 0] eq "destroy" && [llength $args] == 1} { @@ -170,12 +186,13 @@ proc ::tk::systray {args} { #Create the system tray icon. if {[lindex $args 0] eq "create"} { - if {[llength $args] != 4} { - error "wrong # args: should be \"tk systray create image ?text? ?callback?\"" + if {[llength $args] != 5} { + error "wrong # args: should be \"tk systray create image ?text? ?b1_callback? b2_callback?\"" } set _img [lindex $args 1] set _txt [lindex $args 2] - set _cb [lindex $args 3] + set _cb_1 [lindex $args 3] + set _cb_2 [lindex $args 4] switch -- [tk windowingsystem] { "win32" { if {[llength $_iconlist] > 0} { @@ -183,7 +200,7 @@ proc ::tk::systray {args} { icon supported per interpeter" } set _ico [_systray createfrom $_img] - _systray taskbar add $_ico -text $_txt -callback [list _win_callback %m %i $_cb] + _systray taskbar add $_ico -text $_txt -callback [list _win_callback %m %i] lappend _iconlist "ico#[llength _iconlist]" } "x11" { @@ -194,17 +211,18 @@ proc ::tk::systray {args} { set _ico $_img _systray ._tray -image $_img -visible true _balloon ._tray $_txt - bind ._tray <Button-1> $_cb + bind ._tray <Button-1> $_cb_1 + bind ._tray <Button-2> $_cb_2 } "aqua" { - _systray create $_img $_txt $_cb + _systray create $_img $_txt $_cb_1 $_cb_2 } } } #Modify the system tray icon properties. if {[lindex $args 0] eq "modify"} { if {[llength $args] != 3} { - error "wrong # args: \"tk systray modify image | text | callback option?\"" + error "wrong # args: \"tk systray modify image | text | b1_callback | b2_callback option?\"" } switch -- [tk windowingsystem] { "win32" { @@ -212,16 +230,21 @@ proc ::tk::systray {args} { set _img [lindex $args 2] _systray taskbar delete $_ico set _ico [_systray createfrom $_img] - _systray taskbar add $_ico -text $_txt -callback [list _win_callback %m %i $_cb] + _systray taskbar add $_ico -text $_txt -callback [list _win_callback %m %i] } if {[lindex $args 1] eq "text"} { set _txt [lindex $args 2] _systray taskbar modify $_ico -text $_txt } - if {[lindex $args 1 ] eq "callback"} { - set _cb [lindex $args 2] - _systray taskbar modify $_ico -callback [list _win_callback %m %i $_cb] + if {[lindex $args 1 ] eq "b1_callback"} { + set _cb_1 [lindex $args 2] + _systray taskbar modify $_ico -callback [list _win_callback %m %i] } + if {[lindex $args 1 ] eq "b2_callback"} { + set _cb_2 [lindex $args 2] + _systray taskbar modify $_ico -callback [list _win_callback %m %i] + } + } "x11" { if {[lindex $args 1] eq "image"} { @@ -235,11 +258,17 @@ proc ::tk::systray {args} { set _txt [lindex $args 2] _balloon ._tray $_txt } - if {[lindex $args 1 ] eq "callback"} { - set _cb "" + if {[lindex $args 1 ] eq "b1_callback"} { + set _cb_1 "" bind ._tray <Button-1> "" - set _cb [lindex $args 2] - bind ._tray <Button-1> $_cb + set _cb_1 [lindex $args 2] + bind ._tray <Button-1> $_cb_1 + } + if {[lindex $args 1 ] eq "b2_callback"} { + set _cb_2 "" + bind ._tray <Button-1> "" + set _cb_2 [lindex $args 2] + bind ._tray <Button-1> $_cb_2 } } "aqua" { @@ -251,9 +280,13 @@ proc ::tk::systray {args} { set _txt [lindex $args 2] _systray modify text $_txt } - if {[lindex $args 1 ] eq "callback"} { + if {[lindex $args 1 ] eq "b1_callback"} { + set _cb [lindex $args 2] + _systray modify callback $_cb_1 + } + if {[lindex $args 1 ] eq "b2_callback"} { set _cb [lindex $args 2] - _systray modify callback $_cb + _systray modify callback $_cb_2 } } } diff --git a/macosx/tkMacOSXSysTray.c b/macosx/tkMacOSXSysTray.c index 63e9b6c..7b9a897 100644 --- a/macosx/tkMacOSXSysTray.c +++ b/macosx/tkMacOSXSysTray.c @@ -27,13 +27,15 @@ static const char ASSOC_KEY[] = "tk::tktray"; NSImage * icon; NSString * tooltip; Tcl_Interp * interp; - Tcl_Obj * callback; + Tcl_Obj * b1_callback; + Tcl_Obj * b2_callback; } - (id) init : (Tcl_Interp *) interp; - (void) setImagewithImage : (NSImage *) image; - (void) setTextwithString : (NSString *) string; -- (void) setCallback : (Tcl_Obj *) callback; +- (void) setB1Callback : (Tcl_Obj *) callback; +- (void) setB2Callback : (Tcl_Obj *) callback; - (void) clickOnStatusItem: (id) sender; - (void) dealloc; @@ -48,9 +50,11 @@ static const char ASSOC_KEY[] = "tk::tktray"; statusItem = [[statusBar statusItemWithLength:NSVariableStatusItemLength] retain]; statusItem.button.target = self; statusItem.button.action = @selector(clickOnStatusItem: ); + [statusItem.button sendActionOn : NSEventMaskLeftMouseUp | NSEventMaskRightMouseUp]; statusItem.visible = YES; interp = interpreter; - callback = NULL; + b1_callback = NULL; + b2_callback = NULL; return self; } @@ -68,30 +72,48 @@ static const char ASSOC_KEY[] = "tk::tktray"; statusItem.button.toolTip = tooltip; } -- (void) setCallback : (Tcl_Obj *) obj +- (void) setB1Callback : (Tcl_Obj *) obj { if (obj != NULL) { Tcl_IncrRefCount(obj); } - if (callback != NULL) { - Tcl_DecrRefCount(callback); + if (b1_callback != NULL) { + Tcl_DecrRefCount(b1_callback); } - callback = obj; + b1_callback = obj; +} + +- (void) setB2Callback : (Tcl_Obj *) obj +{ + if (obj != NULL) { + Tcl_IncrRefCount(obj); + } + if (b2_callback != NULL) { + Tcl_DecrRefCount(b1_callback); + } + b2_callback = obj; } - (void) clickOnStatusItem: (id) sender { - if ((NSApp.currentEvent.clickCount == 1) && (callback != NULL)) { - int result = Tcl_EvalObjEx(interp, callback, TCL_EVAL_GLOBAL); + NSEvent *event = [NSApp currentEvent]; + if (([event type] == NSEventTypeLeftMouseUp) && (b1_callback != NULL)) { + int result = Tcl_EvalObjEx(interp, b1_callback, TCL_EVAL_GLOBAL); if (result != TCL_OK) { Tcl_BackgroundException(interp, result); } - } + } else { + if (([event type] == NSEventTypeRightMouseUp) && (b2_callback != NULL)) { + int result = Tcl_EvalObjEx(interp, b2_callback, TCL_EVAL_GLOBAL); + if (result != TCL_OK) { + Tcl_BackgroundException(interp, result); + } + } +} } - - (void) dealloc { - /* + /* * We are only doing the minimal amount of deallocation that * the superclass cannot handle when it is deallocated, per * https://developer.apple.com/documentation/objectivec/nsobject/ @@ -100,8 +122,11 @@ static const char ASSOC_KEY[] = "tk::tktray"; * in the Tk test suite. */ [statusBar removeStatusItem: statusItem]; - if (callback != NULL) { - Tcl_DecrRefCount(callback); + if (b1_callback != NULL) { + Tcl_DecrRefCount(b1_callback); + } + if (b2_callback != NULL) { + Tcl_DecrRefCount(b2_callback); } } @@ -121,7 +146,7 @@ static const char ASSOC_KEY[] = "tk::tktray"; - (id) init; - (void) postNotificationWithTitle : (NSString *) title message: (NSString *) detail; - (BOOL) userNotificationCenter:(NSUserNotificationCenter *)center - shouldPresentNotification:(NSUserNotification *)notification; + shouldPresentNotification:(NSUserNotification *)notification; - (void) dealloc; @@ -206,28 +231,21 @@ typedef struct { static int MacSystrayObjCmd( - void *clientData, - Tcl_Interp * interp, - int objc, - Tcl_Obj *const *objv) + void *clientData, + Tcl_Interp * interp, + int objc, + Tcl_Obj *const *objv) { Tk_Image tk_image; TrayInfo *info = (TrayInfo *)clientData; int result, idx; static const char *options[] = - {"create", "modify", "destroy", NULL}; + {"create", "modify", "destroy", NULL}; typedef enum {TRAY_CREATE, TRAY_MODIFY, TRAY_DESTROY} optionsEnum; static const char *modifyOptions[] = - {"image", "text", "callback", NULL}; - typedef enum {TRAY_IMAGE, TRAY_TEXT, TRAY_CALLBACK} modifyOptionsEnum; - - if (info->tk_item == NULL) { - info->tk_item = [[TkStatusItem alloc] init: interp]; - } else { - Tcl_AppendResult(interp, "Only one system tray icon supported per interpeter", NULL); - return TCL_ERROR; - } + {"image", "text", "b1_callback", "b2_callback", NULL}; + typedef enum {TRAY_IMAGE, TRAY_TEXT, TRAY_B1_CALLBACK, TRAY_B2_CALLBACK} modifyOptionsEnum; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "create | modify | destroy"); @@ -243,8 +261,15 @@ MacSystrayObjCmd( switch((optionsEnum)idx) { case TRAY_CREATE: { - if (objc < 5) { - Tcl_WrongNumArgs(interp, 1, objv, "create image ?text? ?callback?"); + if (objc < 6) { + Tcl_WrongNumArgs(interp, 1, objv, "create image ?text? ?b1_callback? b2_callback?"); + return TCL_ERROR; + } + + if (info->tk_item == NULL) { + info->tk_item = [[TkStatusItem alloc] init: interp]; + } else { + Tcl_AppendResult(interp, "Only one system tray icon supported per interpeter", NULL); return TCL_ERROR; } @@ -287,12 +312,13 @@ MacSystrayObjCmd( * Set the proc for the callback. */ - [info->tk_item setCallback : objv[4]]; + [info->tk_item setB1Callback : objv[4]]; + [info->tk_item setB2Callback : objv[5]]; break; } case TRAY_MODIFY: { - if (objc < 4) { + if (objc < 5) { Tcl_WrongNumArgs(interp, 1, objv, "modify object item"); return TCL_ERROR; } @@ -350,24 +376,30 @@ MacSystrayObjCmd( * Modify the proc for the callback. */ - case TRAY_CALLBACK: { - [info->tk_item setCallback : objv[3]]; + case TRAY_B1_CALLBACK: { + [info->tk_item setB1Callback : objv[3]]; + break; + } + case TRAY_B2_CALLBACK: { + [info->tk_item setB2Callback : objv[4]]; + break; } break; } - break; - } - case TRAY_DESTROY: { - /* we don't really distroy, just reset the image, text and callback */ - [info->tk_item setImagewithImage: nil]; - [info->tk_item setTextwithString: nil]; - [info->tk_item setCallback : NULL]; - /* do nothing */ - break; + + case TRAY_DESTROY: { + /* we don't really distroy, just reset the image, text and callback */ + [info->tk_item setImagewithImage: nil]; + [info->tk_item setTextwithString: nil]; + [info->tk_item setB1Callback : NULL]; + [info->tk_item setB2Callback : NULL]; + // /* do nothing */ + break; + } + break; } + return TCL_OK; } - - return TCL_OK; } @@ -389,18 +421,18 @@ MacSystrayObjCmd( static void MacSystrayDestroy( - void *clientData, - TCL_UNUSED(Tcl_Interp *)) + void *clientData, + TCL_UNUSED(Tcl_Interp *)) { TrayInfo *info = (TrayInfo *)clientData; if (info->tk_item != NULL) { - [info->tk_item dealloc]; - info->tk_item = NULL; + [info->tk_item dealloc]; + info->tk_item = NULL; } if (info->notify_item != NULL) { - [info->notify_item dealloc]; - info->notify_item = NULL; + [info->notify_item dealloc]; + info->notify_item = NULL; } ckfree(info); } @@ -424,12 +456,12 @@ MacSystrayDestroy( static int SysNotifyObjCmd( - void *clientData, - Tcl_Interp * interp, - int objc, - Tcl_Obj *const *objv) + void *clientData, + Tcl_Interp * interp, + int objc, + Tcl_Obj *const *objv) { - TrayInfo *info = (TrayInfo *) clientData; + TrayInfo *info = (TrayInfo *) clientData; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "title message"); @@ -465,16 +497,17 @@ static int SysNotifyObjCmd( */ int -MacSystrayInit(Tcl_Interp *interp) { +MacSystrayInit(Tcl_Interp *interp) +{ /* * Initialize TkStatusItem and TkNotifyItem. */ - TrayInfo *info = (TrayInfo *)ckalloc(sizeof(TrayInfo)); + TrayInfo *info = (TrayInfo *)ckalloc(sizeof(TrayInfo)); memset(info, 0, sizeof(TrayInfo)); - Tcl_SetAssocData(interp, ASSOC_KEY, MacSystrayDestroy, info); + Tcl_SetAssocData(interp, ASSOC_KEY, MacSystrayDestroy, info); if ([NSApp macOSVersion] < 101000) { Tcl_AppendResult(interp, "Statusitem icons not supported on versions of macOS lower than 10.10", NULL); |