// sendApp sends an event to the applet matching the icon. // func (o *AppManager) sendApp(icon gldi.Icon, event string, data ...interface{}) bool { app := o.actives[unsafe.Pointer(icon.ToNative())] if app == nil { return notif.AnswerLetPass } o.log.Debug(event, data...) app.OnEvent(event, data...) return notif.AnswerIntercept // an app received the event (even if unused). intercept it. }
// ShowTemporaryWithIcon opens a simple dialog with a timeout. // func ShowTemporaryWithIcon(str string, icon gldi.Icon, container *gldi.Container, duration float64, iconPath string) { cstr := (*C.gchar)(C.CString(str)) defer C.free(unsafe.Pointer((*C.char)(cstr))) cpath := (*C.gchar)(C.CString(iconPath)) defer C.free(unsafe.Pointer((*C.char)(cpath))) cicon := (*C.Icon)(unsafe.Pointer(icon.ToNative())) ccontainer := (*C.GldiContainer)(unsafe.Pointer(container.Ptr)) C.gldi_dialog_show_temporary_with_icon(cstr, cicon, ccontainer, C.double(duration), cpath) }
func iconWindowActive(icon gldi.Icon) ([]gldi.Icon, int) { found := -1 if icon.GetSubDock() == nil { return nil, found } apps := icon.GetSubDock().Icons() for i, app := range apps { if app.Window().IsActive() { found = i } } return apps, found }
// ShowWithQuestion opens a dialog with a question to answer. // func ShowWithQuestion(str string, icon gldi.Icon, container *gldi.Container, iconPath string, onAnswer func(int, *gtk.Widget)) { cstr := (*C.gchar)(C.CString(str)) defer C.free(unsafe.Pointer((*C.char)(cstr))) cpath := (*C.gchar)(C.CString(iconPath)) defer C.free(unsafe.Pointer((*C.char)(cpath))) cicon := (*C.Icon)(unsafe.Pointer(icon.ToNative())) ccontainer := (*C.GldiContainer)(unsafe.Pointer(container.Ptr)) dialogCall = onAnswer removeDialog() c := C.gldi_dialog_show_with_question(cstr, cicon, ccontainer, cpath, C.CairoDockActionOnAnswerFunc(C.onDialogAnswer), nil, nil) dialogPtr = NewDialogFromNative(unsafe.Pointer(c)) }
// ShowItems opens the GUI and displays the given item icon config. // func (gc *Bridge) ShowItems(icon gldi.Icon, container *gldi.Container, moduleInstance *gldi.ModuleInstance, showPage int) { confpath := "" if icon != nil { confpath = icon.ConfigPath() } else if container != nil { // A main dock that is not the first one. Use the dedicated conf file. confpath = globals.CurrentThemePath(container.ToCairoDock().GetDockName() + ".conf") } if confpath == "" { gc.Log.Info("ShowGui unmatched", "icon", icon != nil, "- container", container != nil, "- moduleInstance", moduleInstance != nil, "- page", showPage) } else { gc.Create() if gc.Widget != nil { gc.Widget.SelectIcons(confpath) } } // cairo_dock_items_widget_select_item (ITEMS_WIDGET (pCategory->pCdWidget), pIcon, pContainer, pModuleInstance, iShowPage); }
// sendIconOrSub sends an event to the applet matching the icon or subicon. // func (o *AppManager) sendIconOrSub(icon gldi.Icon, container *gldi.Container, mainEvent, subEvent string, data ...interface{}) bool { var appIcon gldi.Icon switch { // Find the base icon of the icon that was clicked on (for subdock or desklets). case container.IsDesklet(): appIcon = container.ToDesklet().GetIcon() case gldi.ObjectIsDock(container) && container.ToCairoDock().GetRefCount() != 0 && !icon.IsApplet(): appIcon = container.ToCairoDock().SearchIconPointingOnDock(nil) default: appIcon = icon } if appIcon == nil || icon == nil || icon.ToNative() == nil { // TODO: need to check why. return notif.AnswerLetPass } if appIcon.ToNative() == icon.ToNative() { return o.sendApp(appIcon, mainEvent, data...) // Main Icon event. } data = append(data, icon.GetCommand()) // add reference to subicon key. return o.sendApp(appIcon, subEvent, data...) // SubIcon event. }
func onIconAddRemove(icon gldi.Icon, _ *gldi.CairoDock) { if icon.IsApplet() || ((icon.IsLauncher() || icon.IsStackIcon() || icon.IsSeparator()) && icon.GetDesktopFileName() != "") { ReloadItems() } }
// NewDialog creates a custom dialog. // func NewDialog(icon gldi.Icon, container *gldi.Container, dialog cdtype.DialogData) *Dialog { dialogCall = nil // Common dialog attributes. attr := new(C.CairoDialogAttr) if icon != nil { attr.pIcon = (*C.Icon)(unsafe.Pointer(icon.ToNative())) } attr.pContainer = (*C.GldiContainer)(unsafe.Pointer(container.Ptr)) if dialog.Icon != "" { // w,h := // cairo_dock_get_icon_extent (pIcon, &w, &h); // cImageFilePath = cairo_dock_search_icon_s_path (g_value_get_string (v), MAX (w, h)); attr.cImageFilePath = gchar(dialog.Icon) } else { attr.cImageFilePath = gchar("same icon") } if dialog.Message != "" { attr.cText = gchar(dialog.Message) } if dialog.Buttons != "" { cstr := gchar(dialog.Buttons) csep := gchar(";") clist := C.g_strsplit(cstr, csep, -1) // NULL-terminated C.free(unsafe.Pointer((*C.char)(cstr))) C.free(unsafe.Pointer((*C.char)(csep))) defer C.g_strfreev(clist) attr.cButtonsImage = C.constListString(clist) // Set the common C callback for all methods. attr.pActionFunc = C.CairoDockActionOnAnswerFunc(C.onDialogAnswer) } attr.iTimeLength = C.gint(1000 * dialog.TimeLength) attr.bForceAbove = cbool(dialog.ForceAbove) attr.bUseMarkup = cbool(dialog.UseMarkup) attr.pUserData = C.intToPointer(1) // unused, but it seems it must be set so the onDialogDestroyed can be called. attr.pFreeDataFunc = C.GFreeFunc(C.onDialogDestroyed) var widget *gtk.Widget var getValue = func() interface{} { return nil } switch typed := dialog.Widget.(type) { case cdtype.DialogWidgetText: widget, getValue = dialogWidgetText(typed) case cdtype.DialogWidgetScale: widget, getValue = dialogWidgetScale(typed) case cdtype.DialogWidgetList: widget, getValue = dialogWidgetList(typed) // default: // return errors.New("PopupDialog: invalid widget type") } if widget != nil { attr.pInteractiveWidget = (*C.GtkWidget)(unsafe.Pointer(widget.Native())) } if dialog.Buttons != "" && dialog.Callback != nil { dialogCall = func(clickedButton int, _ *gtk.Widget) { // No special widget, return button ID. dialog.Callback(clickedButton, getValue()) } } removeDialog() c := C.gldi_dialog_new(attr) dialogPtr = NewDialogFromNative(unsafe.Pointer(c)) return dialogPtr }
// nextOrder calculates an order position for a new icon, based on the mouse // position on current icon, and the order of the current icon and the next one. // func nextOrder(icon gldi.Icon, dock *gldi.CairoDock) float64 { if icon == nil { return gldi.IconLastOrder } if float64(dock.Container().MouseX()) < icon.DrawX()+icon.Width()*icon.Scale()/2 { // on the left. prev := dock.GetPreviousIcon(icon) if prev == nil { return icon.Order() - 1 } return (icon.Order() + prev.Order()) / 2 } next := dock.GetNextIcon(icon) // on the right. if next == nil { return icon.Order() + 1 } return (icon.Order() + next.Order()) / 2 }
// actionMiddleClick returns the middle-click string to add to the action button // if it's matching the action ID provided. // func actionMiddleClick(icon gldi.Icon, id int) string { if current.Taskbar.ActionOnMiddleClick() != id || icon.IsApplet() { return "" } return " (" + tran.Slate("middle-click") + ")" }
// OnMiddleClick triggers a dock liddle click action on the icon. // func OnMiddleClick(icon gldi.Icon, container *gldi.Container) bool { if icon == nil || !gldi.ObjectIsDock(container) { log.Debug("notifMiddleClick", "ignored: no icon or dock target") return notif.AnswerLetPass } actmid := current.Taskbar.ActionOnMiddleClick() simple := icon.IsAppli() && !icon.IsApplet() multi := icon.IsMultiAppli() switch { case (simple || multi) && actmid == 3: // Launch new. if icon.GetCommand() != "" { // if (! gldi_class_is_starting (icon->cClass) && ! gldi_icon_is_launching (icon)) // do not launch it twice icon.LaunchCommand(log) } return notif.AnswerIntercept case simple && actmid == 1: // Close one. icon.Window().Close() return notif.AnswerIntercept case simple && actmid == 2: // Minimise one. if !icon.Window().IsHidden() { icon.Window().Minimize() } return notif.AnswerIntercept case multi && actmid == 1: // Close all. icon.CallbackActionSubWindows((cdglobal.Window).Close)() return notif.AnswerIntercept case multi && actmid == 2: // Minimise all. hideShowInClassSubdock(icon) return notif.AnswerIntercept } return notif.AnswerLetPass }
// OnLeftClick triggers a dock left click action on the icon. // func OnLeftClick(icon gldi.Icon, container *gldi.Container, btnState uint) bool { switch { case icon == nil || !gldi.ObjectIsDock(container): log.Debug("notifClickIcon", "ignored: no icon or dock target") return notif.AnswerLetPass // With shift or ctrl on an icon that is linked to a program => re-launch this program. case gdk.ModifierType(btnState)&(gdk.GDK_SHIFT_MASK|gdk.GDK_CONTROL_MASK) > 0: if icon.IsLauncher() || icon.IsAppli() || icon.IsStackIcon() { icon.LaunchCommand(log) } return notif.AnswerLetPass // scale on an icon holding a class sub-dock (fallback: show all windows). case icon.IsMultiAppli() && current.Taskbar.PresentClassOnClick() && // if we want to use this feature (!current.Docks.ShowSubDockOnClick() || // if sub-docks are shown on mouse over icon.SubDockIsVisible() && // or this sub-dock is already visible icon.DesktopPresentClass()): // we use the scale plugin if it's possible icon.CallbackActionSubWindows((cdglobal.Window).Show)() // in case the dock is visible or about to be visible, hide it, as it would confuse the user to have both. // cairo_dock_emit_leave_signal (CAIRO_CONTAINER (icon->pSubDock)); return notif.AnswerIntercept // // else handle sub-docks showing on click, applis and launchers (not applets). // icon pointing to a sub-dock with either "sub-dock activation on click" option enabled, // or sub-dock not visible -> open the sub-dock case icon.GetSubDock() != nil && (current.Docks.ShowSubDockOnClick() || !icon.SubDockIsVisible()): icon.ShowSubdock(container.ToCairoDock()) return notif.AnswerIntercept // icon holding an appli, but not being an applet -> show/hide the window. case icon.IsAppli() && !icon.IsApplet(): // ne marche que si le dock est une fenêtre de type 'dock', sinon il prend le focus. if icon.Window().IsActive() && current.Taskbar.MinimizeOnClick() && !icon.Window().IsHidden() && icon.Window().IsOnCurrentDesktop() { icon.Window().Minimize() } else { icon.Window().Show() } return notif.AnswerIntercept // icon holding a class sub-dock -> show/hide the windows of the class. case icon.IsMultiAppli(): if current.Docks.ShowSubDockOnClick() { hideShowInClassSubdock(icon) } return notif.AnswerIntercept // finally, launcher being none of the previous cases -> launch the command case icon.IsLauncher(): // if (! gldi_class_is_starting (icon->cClass) && ! gldi_icon_is_launching (icon)) {// do not launch it twice (avoid wrong double click) => if we want to launch it 2 times in a row, we have to use Shift + Click icon.LaunchCommand(log) return notif.AnswerIntercept // wasn't there in real dock. } // for applets and their sub-icons, let the module-instance handles the click; for separators, no action. // cd_debug ("no action here"); return notif.AnswerLetPass }
// OnDropData triggers a dock drop data action on the icon. // func OnDropData(icon gldi.Icon, container *gldi.Container, data string, order float64) bool { if !gldi.ObjectIsDock(container) { log.Debug("notifDropData", "ignored: container is not a dock") return notif.AnswerLetPass } receivingDock := container.ToCairoDock() switch { case strings.HasSuffix(data, ".desktop"): // -> add a new launcher if dropped on or amongst launchers. if !current.Taskbar.MixLauncherAppli() && icon.IsAppli() { log.Debug("notifDropData", "ignored: desktop file found but maybe bad location in dock (or need mix launchers)") return notif.AnswerLetPass } // drop onto a container icon. if order == gldi.IconLastOrder && icon.IsStackIcon() && icon.GetSubDock() != nil { // add into the pointed sub-dock. receivingDock = icon.GetSubDock() } // else, still try to consider it a file? case icon == nil || order != gldi.IconLastOrder: // dropped between 2 icons -> try to add it (for instance a script). case icon.IsStackIcon(): // sub-dock -> propagate to the sub-dock. receivingDock = icon.GetSubDock() // dropped on an icon case icon.IsLauncher() || icon.IsAppli() || icon.IsClassIcon(): // launcher/appli -> fire the command with this file. cmd := icon.GetCommand() if cmd == "" { log.Debug("notifDropData", "ignored: no command to trigger") return notif.AnswerLetPass } // Some programs doesn't handle URI. Convert it to local path. if strings.HasPrefix(data, "file://") { // gchar *cPath = g_filename_from_uri (cReceivedData, NULL, NULL); // data = bouine(data) } ok := icon.LaunchCommand(log, data) if ok { icon.RequestAnimation("blink", 2) log.Debug("notifDropData", "opened with", icon.GetName(), "::", data) } return notif.AnswerIntercept default: // skip any other case. log.Debug("notifDropData", "ignored: nothing to do with icon type", icon.GetName()) return notif.AnswerLetPass } if current.DockIsLocked() || current.Docks.LockAll() { log.Debug("notifDropData", "ignored: dock is locked, can't add icon") return notif.AnswerLetPass } // Still here ? Try to add to target dock. newicon := gldi.LauncherAddNew(data, receivingDock, order) if newicon == nil { log.Debug("notifDropData", "add icon failed ::", data) return notif.AnswerIntercept } log.Debug("notifDropData", "icon added:", icon.GetName()) return notif.AnswerLetPass }
// OnMouseScroll triggers a dock mouse scroll action on the icon. // func OnMouseScroll(icon gldi.Icon, _ *gldi.Container, scrollUp bool) bool { switch { case icon == nil: case icon.IsSeparator(): // Cycle between desktops. log.Debug("SeparatorWheelChangeDesktop", confown.Settings.SeparatorWheelChangeDesktop) switch confown.Settings.SeparatorWheelChangeDesktop { case confown.SeparatorWheelChangeRange: desktops.Cycle(scrollUp, false) case confown.SeparatorWheelChangeLoop: desktops.Cycle(scrollUp, true) } // SeparatorDesktopLoop bool case icon.IsMultiAppli() || icon.IsStackIcon(): // Cycle between subdock applets list. showPrevNextInSubdock(icon, scrollUp) case icon.IsAppli() && icon.HasClass(): next := icon.GetPrevNextClassMateIcon(!scrollUp) if next != nil { next.Window().Show() } } return notif.AnswerLetPass }