void EvtMouseVScrollBar(struct XObj *xobj, XButtonEvent *EvtButton) { static XEvent event; int oldy = 0; int oldvalue = -1; int newvalue; int x1,y1,x2,y2; Window Win1,Win2; unsigned int modif; fd_set in_fdset; do { /* On suit les mouvements de la souris */ FQueryPointer(dpy, *xobj->ParentWin, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif); y2 = y2 - xobj->y; if (y2 < 15) y2 = 15; if (y2 > xobj->height - 21) y2 = xobj->height - 21; if (oldy != y2) { oldy = y2; /* calcule de xobj->value */ newvalue = (y2-15)*xobj->height/(xobj->height - 36) * (xobj->value2 - xobj->value3) / (xobj->height) + xobj->value3; if (newvalue!=oldvalue) { HideThumbV(xobj); xobj->value = newvalue; DrawThumbV(xobj, NULL); oldvalue = newvalue; SendMsg(xobj,SingleClic); XSync(dpy,0); usleep(10000); } } FD_ZERO(&in_fdset); FD_SET(x_fd, &in_fdset); select(32, SELECT_FD_SET_CAST &in_fdset, NULL, NULL, NULL); } while (!FCheckTypedEvent(dpy, ButtonRelease, &event) && EvtButton != NULL); }
/* same as above, but forces to regrab buttons on the window under the pointer * if necessary */ void focus_grab_buttons_on_pointer_window(void) { Window w; FvwmWindow *fw; if (!FQueryPointer( dpy, Scr.Root, &JunkRoot, &w, &JunkX, &JunkY, &JunkX, &JunkY, &JunkMask)) { /* pointer is not on this screen */ return; } if (XFindContext(dpy, w, FvwmContext, (caddr_t *) &fw) == XCNOENT) { /* pointer is not over a window */ return; } focus_grab_buttons(fw); return; }
void EvtMousePopupMenu(struct XObj *xobj, XButtonEvent *EvtButton) { static XEvent event; int x,y,hOpt,yMenu,hMenu; int x1,y1,x2,y2,oldy; int oldvalue = 0; int newvalue = 0; Window Win1,Win2,WinPop; unsigned int modif; unsigned long mask; unsigned long while_mask; XSetWindowAttributes Attr; Time start_time = 0; KeySym ks; unsigned char buf[10]; Bool End = 1; int asc = xobj->Ffont->ascent; hOpt = xobj->Ffont->height + 10; xobj->value3 = CountOption(xobj->title); yMenu = xobj->y - ((xobj->value-1) * hOpt); hMenu = xobj->value3 * hOpt; /* Creation de la fenetre menu */ XTranslateCoordinates(dpy, *xobj->ParentWin, Root, xobj->x, yMenu, &x, &y, &Win1); if (x < 0) x = 0; if (y < 0) y = 0; if (x+xobj->width > XDisplayWidth(dpy, screen)) x = XDisplayWidth(dpy, screen) - xobj->width; if (y+hMenu > XDisplayHeight(dpy, screen)) y = XDisplayHeight(dpy, screen) - hMenu; mask = 0; Attr.background_pixel = xobj->TabColor[back]; mask |= CWBackPixel; Attr.border_pixel = 0; mask |= CWBorderPixel; Attr.colormap = Pcmap; mask |= CWColormap; Attr.cursor = XCreateFontCursor(dpy, XC_hand2); mask |= CWCursor; /* Curseur pour la fenetre / Window cursor */ Attr.override_redirect = True; mask |= CWOverrideRedirect; WinPop = XCreateWindow(dpy, Root, x, y, xobj->width, hMenu, 0, Pdepth, InputOutput, Pvisual, mask, &Attr); if (xobj->colorset >= 0) SetWindowBackground(dpy, WinPop, xobj->width, hMenu, &Colorset[xobj->colorset], Pdepth, xobj->gc, True); XMapRaised(dpy, WinPop); /* Dessin du menu / Drawing the menu */ DrawPMenu(xobj, WinPop, hOpt, 0); XGrabPointer(dpy, WinPop, True, GRAB_EVMASK, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); if (EvtButton == NULL) { while_mask = ButtonPress; } else { start_time = EvtButton->time; while_mask = ButtonRelease; } while (End) { FQueryPointer(dpy, Root, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif); /* Determiner l'option courante / Current option */ y2 = y2 - y; x2 = x2 - x; oldy = y2; /* calcule de xobj->value / compute xobj->value */ if ((x2 > 0) && (x2 < xobj->width) && (y2 > 0) && (y2 < hMenu)) newvalue = y2 / hOpt+1; else newvalue = 0; if (newvalue != oldvalue) { UnselectMenu(xobj, WinPop, hOpt, oldvalue, xobj->width, asc, 0); SelectMenu(xobj, WinPop, hOpt, newvalue); oldvalue = newvalue; } FNextEvent(dpy, &event); switch (event.type) { case KeyPress: XLookupString(&event.xkey, (char *)buf, sizeof(buf), &ks, NULL); if (ks == XK_Escape) { newvalue = 0; End = 0; } else if (ks == XK_Return) { End = 0; } else if (ks == XK_Up && y2 >= hOpt) { FWarpPointer(dpy, None, None, 0, 0, 0, 0, 0, -hOpt); } else if (ks == XK_Down && y2 + hOpt <= hMenu) { FWarpPointer(dpy, None, None, 0, 0, 0, 0, 0, hOpt); } break; case ButtonPress: if (while_mask == ButtonPress) End = 0; break; case ButtonRelease: if (start_time != 0 && event.xbutton.time - start_time < MENU_DRAG_TIME) { while_mask = ButtonPress; start_time = 0; } if (while_mask == ButtonRelease) End = 0; break; } } #if 0 do { FQueryPointer(dpy, Root, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif); /* Determiner l'option courante / Current option */ y2 = y2 - y; x2 = x2 - x; { oldy = y2; /* calcule de xobj->value / compute xobj->value */ if ((x2 > 0) && (x2 < xobj->width) && (y2 > 0) && (y2 < hMenu)) newvalue = y2 / hOpt+1; else newvalue = 0; if (newvalue != oldvalue) { UnselectMenu(xobj, WinPop, hOpt, oldvalue, xobj->width, asc, 0); SelectMenu(xobj, WinPop, hOpt, newvalue); oldvalue = newvalue; } } FD_ZERO(&in_fdset); FD_SET(x_fd, &in_fdset); select(32, SELECT_FD_SET_CAST &in_fdset, NULL, NULL, NULL); } while (!FCheckTypedEvent(dpy, while_mask, &event)); #endif XUngrabPointer(dpy, CurrentTime); XSync(dpy,0); XDestroyWindow(dpy, WinPop); if (newvalue != 0) { xobj->value = newvalue; SendMsg(xobj, SingleClic); } }
static void execute_complex_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, Bool *desperate, Bool has_ref_window_moved) { cond_rc_t tmp_rc; cfunc_action_t type = CF_MOTION; char c; FunctionItem *fi; Bool Persist = False; Bool HaveDoubleClick = False; Bool HaveHold = False; Bool NeedsTarget = False; Bool ImmediateNeedsTarget = False; int do_allow_unmanaged = FUNC_ALLOW_UNMANAGED; int do_allow_unmanaged_immediate = FUNC_ALLOW_UNMANAGED; char *arguments[11], *taction; char *func_name; int x, y ,i; XEvent d; FvwmFunction *func; static int depth = 0; const exec_context_t *exc2; exec_context_changes_t ecc; exec_context_change_mask_t mask; int trigger_evtype; int button; XEvent *te; if (cond_rc == NULL) { condrc_init(&tmp_rc); cond_rc = &tmp_rc; } cond_rc->rc = COND_RC_OK; mask = 0; d.type = 0; ecc.w.fw = exc->w.fw; ecc.w.w = exc->w.w; ecc.w.wcontext = exc->w.wcontext; /* find_complex_function expects a token, not just a quoted string */ func_name = PeekToken(action, &taction); if (!func_name) { return; } func = find_complex_function(func_name); if (func == NULL) { if (*desperate == 0) { fvwm_msg( ERR, "ComplexFunction", "No such function %s", action); } return; } if (!depth) { Scr.flags.is_executing_complex_function = 1; } depth++; *desperate = 0; /* duplicate the whole argument list for use as '$*' */ if (taction) { arguments[0] = safestrdup(taction); /* strip trailing newline */ if (arguments[0][0]) { int l= strlen(arguments[0]); if (arguments[0][l - 1] == '\n') { arguments[0][l - 1] = 0; } } /* Get the argument list */ for (i = 1; i < 11; i++) { taction = GetNextToken(taction, &arguments[i]); } } else { for (i = 0; i < 11; i++) { arguments[i] = NULL; } } /* In case we want to perform an action on a button press, we * need to fool other routines */ te = exc->x.elast; if (te->type == ButtonPress) { trigger_evtype = ButtonRelease; } else { trigger_evtype = te->type; } func->use_depth++; for (fi = func->first_item; fi != NULL; fi = fi->next_item) { if (fi->flags & FUNC_NEEDS_WINDOW) { NeedsTarget = True; do_allow_unmanaged &= fi->flags; if (fi->condition == CF_IMMEDIATE) { do_allow_unmanaged_immediate &= fi->flags; ImmediateNeedsTarget = True; break; } } } if (ImmediateNeedsTarget) { if (DeferExecution( &ecc, &mask, CRS_SELECT, trigger_evtype, do_allow_unmanaged_immediate)) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); return; } NeedsTarget = False; } else { ecc.w.w = (ecc.w.fw) ? FW_W_FRAME(ecc.w.fw) : None; mask |= ECC_W; } /* we have to grab buttons before executing immediate actions because * these actions can move the window away from the pointer so that a * button release would go to the application below. */ if (!GrabEm(CRS_NONE, GRAB_NORMAL)) { func->use_depth--; fvwm_msg( ERR, "ComplexFunction", "Grab failed in function %s," " unable to execute immediate action", action); __cf_cleanup(&depth, arguments, cond_rc); return; } exc2 = exc_clone_context(exc, &ecc, mask); __run_complex_function_items( cond_rc, CF_IMMEDIATE, func, exc2, arguments, has_ref_window_moved); exc_destroy_context(exc2); for (fi = func->first_item; fi != NULL && cond_rc->break_levels == 0; fi = fi->next_item) { /* c is already lowercase here */ c = fi->condition; switch (c) { case CF_IMMEDIATE: break; case CF_DOUBLE_CLICK: HaveDoubleClick = True; Persist = True; break; case CF_HOLD: HaveHold = True; Persist = True; break; default: Persist = True; break; } } if (!Persist || cond_rc->break_levels != 0) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); UngrabEm(GRAB_NORMAL); return; } /* Only defer execution if there is a possibility of needing * a window to operate on */ if (NeedsTarget) { if (DeferExecution( &ecc, &mask, CRS_SELECT, trigger_evtype, do_allow_unmanaged)) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); UngrabEm(GRAB_NORMAL); return; } } te = (mask & ECC_ETRIGGER) ? ecc.x.etrigger : exc->x.elast; switch (te->xany.type) { case ButtonPress: case ButtonRelease: x = te->xbutton.x_root; y = te->xbutton.y_root; button = te->xbutton.button; /* Take the click which started this fuction off the * Event queue. -DDN- Dan D Niles [email protected] */ FCheckMaskEvent(dpy, ButtonPressMask, &d); break; default: if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ x = 0; y = 0; } button = 0; break; } /* Wait and see if we have a click, or a move */ /* wait forever, see if the user releases the button */ type = CheckActionType(x, y, &d, HaveHold, True, &button); if (type == CF_CLICK) { int button2; /* If it was a click, wait to see if its a double click */ if (HaveDoubleClick) { type = CheckActionType( x, y, &d, True, False, &button2); switch (type) { case CF_HOLD: case CF_MOTION: case CF_CLICK: if (button == button2) { type = CF_DOUBLE_CLICK; } else { type = CF_CLICK; } break; case CF_TIMEOUT: type = CF_CLICK; break; default: /* can't happen */ break; } } } else if (type == CF_TIMEOUT) { type = CF_HOLD; } /* some functions operate on button release instead of presses. These * gets really weird for complex functions ... */ if (d.type == ButtonPress) { d.type = ButtonRelease; if (d.xbutton.button > 0 && d.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS) { d.xbutton.state &= (~(Button1Mask >> (d.xbutton.button - 1))); }
void menu_shortcuts( struct MenuRoot *mr, struct MenuParameters *pmp, struct MenuReturn *pmret, XEvent *event, struct MenuItem **pmi_current, double_keypress *pdkp, int *ret_menu_x, int *ret_menu_y) { int with_control; int with_shift; int with_meta; KeySym keysym; char ckeychar; int ikeychar; MenuItem *new_item; MenuItem *mi_current; int index; int mx; int my; int menu_x; int menu_y; int menu_width; int menu_height; int items_to_move; int do_skip_section; menu_shortcut_action saction; Binding *binding; int context; int is_geometry_known; char *command; ckeychar = 0; new_item = NULL; mi_current = pmi_current ? *pmi_current : NULL; do_skip_section = 0; saction = SA_NONE; context = C_MENU; is_geometry_known = 0; context = C_MENU; command = 0; if (mi_current) { if (MI_IS_TITLE(mi_current)) { context |= C_TITLE; } else { /* menu item context, use I (icon) for it */ context |= C_MENU_ITEM; } } else { if ( menu_get_geometry( mr, &JunkRoot, &menu_x, &menu_y, &menu_width, &menu_height, &JunkBW, &JunkDepth)) { is_geometry_known = 1; if ( FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &mx, &my, &JunkX, &JunkY, &JunkMask) == 0) { /* pointer is on a different screen */ mx = 0; my = 0; } else if ( mx >= menu_x && mx < menu_x + menu_width && my >= menu_y && my < menu_y + menu_height) { /* pointer is on the meny somewhere not over * an item */ if (my < menu_y + MST_BORDER_WIDTH(mr)) { /* upper border context (-)*/ context |= C_SB_TOP; } else if ( my >= menu_y + menu_height - MST_BORDER_WIDTH(mr)) { /* lower border context (_) */ context |= C_SB_BOTTOM; } else if (mx < menu_x + MR_ITEM_X_OFFSET(mr)) { /* left border or left sidepic */ context |= C_SB_LEFT; } else if (mx < menu_x + MST_BORDER_WIDTH(mr)) { /* left border context ([)*/ context |= C_SB_LEFT; } else if ( mx >= menu_x + MR_ITEM_X_OFFSET(mr) + MR_ITEM_WIDTH(mr)) { /* right sidepic or right border */ context |= C_SB_RIGHT; } else if ( mx >= menu_x + menu_width - MST_BORDER_WIDTH(mr)) { /* right border context (])*/ context |= C_SB_RIGHT; } } } else { mvwm_msg( ERR, "menu_shortcuts", "can't get geometry of" " menu %s", MR_NAME(mr)); } } if (event->type == KeyRelease) { /* This function is only called with a KeyRelease event if the * user released the 'select' key (s)he configured. */ pmret->rc = MENU_SELECTED; return; } items_to_move = 0; pmret->rc = MENU_NOP; /*** handle mouse events ***/ if (event->type == ButtonRelease) { /*** Read the control keys stats ***/ with_control = event->xbutton.state & ControlMask ? 1 : 0; with_shift = event->xbutton.state & ShiftMask ? 1: 0; with_meta = event->xbutton.state & Mod1Mask ? 1: 0; /** handle menu bindings **/ binding = menu_binding_is_mouse(event, context); if (binding != NULL) { parse_menu_action( mr, binding->Action, &saction, &items_to_move, &do_skip_section, &command); } index = 0; ikeychar = 0; } else /* Should be KeyPressed */ { /*** Read the control keys stats ***/ with_control = event->xkey.state & ControlMask? 1 : 0; with_shift = event->xkey.state & ShiftMask? 1: 0; with_meta = event->xkey.state & Mod1Mask? 1: 0; /*** handle double-keypress ***/ if (pdkp->timestamp && fev_get_evtime() - pdkp->timestamp < MST_DOUBLE_CLICK_TIME(pmp->menu) && event->xkey.state == pdkp->keystate && event->xkey.keycode == pdkp->keycode) { *pmi_current = NULL; pmret->rc = MENU_DOUBLE_CLICKED; return; } pdkp->timestamp = 0; /*** find out the key ***/ /* Is it okay to treat keysym-s as Ascii? * No, because the keypad numbers don't work. * Use XlookupString */ index = XLookupString(&(event->xkey), &ckeychar, 1, &keysym, NULL); ikeychar = (int)ckeychar; } /*** Try to match hot keys ***/ /* Need isascii here - isgraph might coredump! */ if (index == 1 && isascii(ikeychar) && isgraph(ikeychar) && with_control == 0 && with_meta == 0) { /* allow any printable character to be a keysym, but be sure * control isn't pressed */ MenuItem *mi; MenuItem *mi1; int key; int countHotkey = 0; /* if this is a letter set it to lower case */ if (isupper(ikeychar)) { ikeychar = tolower(ikeychar) ; } /* MMH [email protected] 2/7/99 * Multiple hotkeys per menu * Search menu for matching hotkey; * remember how many we found and where we found it */ mi = (mi_current == NULL || mi_current == MR_LAST_ITEM(mr)) ? MR_FIRST_ITEM(mr) : MI_NEXT_ITEM(mi_current); mi1 = mi; do { if (MI_HAS_HOTKEY(mi) && !MI_IS_TITLE(mi) && (!MI_IS_HOTKEY_AUTOMATIC(mi) || MST_USE_AUTOMATIC_HOTKEYS(mr))) { key = (MI_LABEL(mi)[(int)MI_HOTKEY_COLUMN(mi)]) [MI_HOTKEY_COFFSET(mi)]; key = tolower(key); if (ikeychar == key) { if (++countHotkey == 1) { new_item = mi; } } } mi = (mi == MR_LAST_ITEM(mr)) ? MR_FIRST_ITEM(mr) : MI_NEXT_ITEM(mi); } while (mi != mi1); /* For multiple instances of a single hotkey, just move the * selection */ /* TA: 2011-07-24: But if the user has turned off * "UniqueHotkeyActivatedImmediate", keep the menu open until * the user has asked for that entry to be enacted. This also * implies the style "TitleWarpOff" and we're not over a popup * item, in which case the pointer is warped to the submenu in * the usual way. */ if ((countHotkey > 1) || (countHotkey >=1 && ( (!MST_DO_WARP_TO_TITLE(mr) || !MI_IS_POPUP(new_item)) ) && !MST_HOTKEY_ACTIVATES_IMMEDIATE(mr))) { *pmi_current = new_item; pmret->rc = MENU_NEWITEM; return; } /* Do things the old way for unique hotkeys in the menu */ else if (countHotkey == 1) { *pmi_current = new_item; if (new_item && MI_IS_POPUP(new_item)) { pmret->rc = MENU_POPUP; } else { pmret->rc = MENU_SELECTED; } return; } /* MMH [email protected] 2/7/99 */ } /*** now determine the action to take ***/ /** handle menu key bindings **/ if ( event->type == KeyPress && keysym == XK_Escape && with_control == 0 && with_shift == 0 && with_meta == 0) { /* Don't allow override of Escape with no modifiers */ saction = SA_ABORT; } else if (event->type == KeyPress) { binding = menu_binding_is_key(event, context); if (binding != NULL) { parse_menu_action( mr, binding->Action, &saction, &items_to_move, &do_skip_section, &command); } } if ( !mi_current && (saction == SA_ENTER || saction == SA_MOVE_ITEMS || saction == SA_SELECT || saction == SA_SCROLL)) { if (is_geometry_known) { if (my < menu_y + MST_BORDER_WIDTH(mr)) { saction = SA_FIRST; } else if (my > menu_y + menu_height - MST_BORDER_WIDTH(mr)) { saction = SA_LAST; } else { saction = SA_WARPBACK; } } else { saction = SA_FIRST; } } /*** execute the necessary actions ***/ switch (saction) { case SA_ENTER: if (mi_current && MI_IS_POPUP(mi_current)) { pmret->rc = MENU_POPUP; } else { pmret->rc = MENU_NOP; } break; case SA_LEAVE: pmret->rc = (MR_IS_TEAR_OFF_MENU(mr)) ? MENU_NOP : MENU_POPDOWN; break; case SA_FIRST: if (do_skip_section) { *pmi_current = get_selectable_item_from_section( mr, items_to_move); } else { *pmi_current = get_selectable_item_from_index( mr, items_to_move); } if (*pmi_current != NULL) { pmret->rc = MENU_NEWITEM; } else { pmret->rc = MENU_NOP; } break; case SA_LAST: if (do_skip_section) { get_selectable_item_count(mr, &index); index += items_to_move; if (index < 0) { index = 0; } *pmi_current = get_selectable_item_from_section( mr, index); if (*pmi_current != NULL) { pmret->rc = MENU_NEWITEM; } else { pmret->rc = MENU_NOP; } } else { index = get_selectable_item_count(mr, NULL); if (index > 0) { index += items_to_move; if (index < 0) { index = 0; } *pmi_current = get_selectable_item_from_index( mr, index); pmret->rc = (*pmi_current) ? MENU_NEWITEM : MENU_NOP; } else { pmret->rc = MENU_NOP; } } break; case SA_MOVE_ITEMS: if (do_skip_section) { int section; int count; get_selectable_item_count(mr, &count); get_selectable_item_index(mr, mi_current, §ion); section += items_to_move; if (section < 0) section = count; else if (section > count) section = 0; index = section; } else if (items_to_move < 0) { index = get_selectable_item_index( mr, mi_current, NULL); if (index == 0) /* wraparound */ index = get_selectable_item_count(mr, NULL); else { index += items_to_move; } } else { index = get_selectable_item_index( mr, mi_current, NULL) + items_to_move; /* correct for the case that we're between items */ if (!MI_IS_SELECTABLE(mi_current)) { index--; } } if (do_skip_section) { new_item = get_selectable_item_from_section(mr, index); } else { new_item = get_selectable_item_from_index(mr, index); if (items_to_move > 0 && new_item == mi_current) { new_item = get_selectable_item_from_index(mr, 0); } } if (new_item) { *pmi_current = new_item; pmret->rc = MENU_NEWITEM; } else { pmret->rc = MENU_NOP; } break; case SA_CONTINUE: *pmi_current = MR_LAST_ITEM(mr); if (*pmi_current && MI_IS_POPUP(*pmi_current)) { /* enter the submenu */ pmret->rc = MENU_POPUP; } else { /* do nothing */ *pmi_current = mi_current; pmret->rc = MENU_NOP; } break; case SA_WARPBACK: /* Warp the pointer back into the menu. */ FWarpPointer( dpy, 0, MR_WINDOW(mr), 0, 0, 0, 0, menudim_middle_x_offset(&MR_DIM(mr)), my - menu_y); pmret->rc = MENU_NEWITEM_FIND; break; case SA_SELECT: pmret->rc = MENU_SELECTED; return; case SA_ABORT: pmret->rc = (MR_IS_TEAR_OFF_MENU(mr)) ? MENU_KILL_TEAR_OFF_MENU : MENU_ABORTED; return; case SA_TEAROFF: pmret->rc = (MR_IS_TEAR_OFF_MENU(mr)) ? MENU_NOP : MENU_TEAR_OFF; return; case SA_SCROLL: if (MST_MOUSE_WHEEL(mr) == MMW_MENU) { items_to_move *= -1; } if ( !menu_get_outer_geometry( mr, pmp, &JunkRoot, &menu_x, &menu_y, &JunkWidth, &menu_height, &JunkBW, &JunkDepth)) { mvwm_msg( ERR, "menu_shortcuts", "can't get geometry of menu %s", MR_NAME(mr)); return; } if (do_skip_section) { int count; get_selectable_item_count(mr, &count); get_selectable_item_index(mr, mi_current, &index); index += items_to_move; if (index < 0) { index = 0; } else if (index > count) { index = count; } new_item = get_selectable_item_from_section(mr, index); } else { index = get_selectable_item_index( mr, mi_current, NULL); if (items_to_move > 0 && !MI_IS_SELECTABLE(mi_current)) { index--; } index += items_to_move; new_item = get_selectable_item_from_index(mr, index); } if ( new_item && ((items_to_move < 0 && MI_Y_OFFSET(new_item) > MI_Y_OFFSET(mi_current)) || (items_to_move > 0 && MI_Y_OFFSET(new_item) < MI_Y_OFFSET(mi_current)))) { /* never scroll in the "wrong" direction */ new_item = NULL; } if (new_item) { *pmi_current = new_item; pmret->rc = MENU_NEWITEM; /* Have to work with relative positions or tear off * menus will be hard to reposition */ if ( FQueryPointer( dpy, MR_WINDOW(mr), &JunkRoot, &JunkChild, &JunkX, &JunkY, &mx, &my, &JunkMask) == 0) { /* This should not happen */ mx = 0; my = 0; } if (MST_MOUSE_WHEEL(mr) == MMW_POINTER) { if (event->type == ButtonRelease) { FWarpPointer( dpy, 0, 0, 0, 0, 0, 0, 0, -my + menuitem_middle_y_offset( new_item, MR_STYLE(mr))); } /* pointer wrapped elsewhere for key events */ } else { int old_y = menu_y; menu_y += my - menuitem_middle_y_offset( new_item, MR_STYLE(mr)); if ( !MST_SCROLL_OFF_PAGE(mr) && menu_height < MR_SCREEN_HEIGHT(mr)) { if (menu_y < 0) { FWarpPointer(dpy, 0, 0, 0, 0, 0, 0, 0,-menu_y); menu_y=0; } if ( menu_y + menu_height > MR_SCREEN_HEIGHT(mr)) { FWarpPointer( dpy, 0, 0, 0, 0, 0, 0, 0, MR_SCREEN_HEIGHT(mr) - menu_y - menu_height); menu_y = MR_SCREEN_HEIGHT(mr) - menu_height; } } if (old_y != menu_y) { pmret->rc = MENU_NEWITEM_MOVEMENU; *ret_menu_x = menu_x; *ret_menu_y = menu_y; } else { pmret->rc = MENU_NEWITEM; } } } else { pmret->rc = MENU_NOP; } break; case SA_EXEC_CMD: pmret->rc = MENU_EXEC_CMD; *pmp->ret_paction = command; break; case SA_NONE: default: pmret->rc = MENU_NOP; break; } if (saction != SA_SCROLL && pmret->rc == MENU_NEWITEM) { if (!menu_get_outer_geometry( mr, pmp, &JunkRoot, &menu_x, &menu_y, &JunkWidth, &menu_height, &JunkBW, &JunkDepth)) { mvwm_msg( ERR, "menu_shortcuts", "can't get geometry of menu %s", MR_NAME(mr)); return; } if (menu_y < 0 || menu_y + menu_height > MR_SCREEN_HEIGHT(mr)) { menu_y = (menu_y < 0) ? 0 : MR_SCREEN_HEIGHT(mr) - menu_height; pmret->rc = MENU_NEWITEM_MOVEMENU; *ret_menu_x = menu_x; *ret_menu_y = menu_y; } } return; }
void EvtMouseTextField(struct XObj *xobj,XButtonEvent *EvtButton) { unsigned int modif; int x1,x2,y1,y2,i; Window Win1,Win2; int PosCurs=0; int SizeBuf; char *str; int NewPos; Atom type; XEvent event; int ButPress=1; int format; unsigned long longueur,octets_restant; unsigned char *donnees=(unsigned char *)""; XRectangle rect; int start_pos, selection_pos, curs_pos; /* On deplace le curseur a la position de la souris */ /* On recupere la position de la souris */ /* We move the cursor at mouse position and we get the mouse position */ switch (EvtButton->button) { case Button1: FQueryPointer( dpy,*xobj->ParentWin,&Win1,&Win2,&x1,&y1,&x2,&y2, &modif); x2=x2-xobj->x; /* see where we clicked */ PosCurs=0; /* byte position of first visible character */ start_pos = getByteOffsetBoundsCheck(xobj->Ffont, xobj->title, xobj->value3); /* cursor offset in bytes */ curs_pos = 0; while ((curs_pos < strlen(xobj->title + start_pos)) && (x2 > FlocaleTextWidth( xobj->Ffont,xobj->title + start_pos, curs_pos) + 8)) { curs_pos += FlocaleStringNumberOfBytes( xobj->Ffont, xobj->title + start_pos + curs_pos); PosCurs++; } DrawPointTxt(xobj,xobj->TabColor[back]); /* set selection start and end where clicked */ /* first visible char + position clicked */ xobj->value = PosCurs + xobj->value3; xobj->value2 = PosCurs + xobj->value3; /* byte offset corresponding to the above */ start_pos = getByteOffsetBoundsCheck(xobj->Ffont, xobj->title, xobj->value3); selection_pos = getByteOffsetBoundsCheck(xobj->Ffont, xobj->title, xobj->value3); DrawPointTxt(xobj,xobj->TabColor[fore]); DrawTextField(xobj,NULL); while (ButPress) { FNextEvent(dpy, &event); switch (event.type) { case MotionNotify: FQueryPointer( dpy,*xobj->ParentWin,&Win1,&Win2,&x1, &y1,&x2,&y2,&modif); x2=x2-xobj->x; PosCurs=0; curs_pos = 0; /* determine how far in the mouse is now */ while ((curs_pos < strlen( xobj->title + start_pos)) && (x2 > FlocaleTextWidth( xobj->Ffont,xobj->title+ start_pos, curs_pos) + 8)) { curs_pos += FlocaleStringNumberOfBytes( xobj->Ffont, xobj->title + start_pos + curs_pos); PosCurs++; } /* Limitation de la zone de dessin */ /* limitation of the drawing zone */ /* these 2 if-statements updates current cursor position of the widget if needed */ if (PosCurs > (xobj->value2 - xobj->value3)) { /* select made "forward" */ rect.x= FlocaleTextWidth( xobj->Ffont, xobj->title+ start_pos, selection_pos - start_pos); rect.y=0; rect.width= FlocaleTextWidth( xobj->Ffont, xobj->title+ start_pos, curs_pos) -rect.x+1; rect.height=xobj->height; xobj->value2 = PosCurs + xobj->value3; DrawTextField(xobj,NULL); } else if (PosCurs < (xobj->value2 - xobj->value3)) { /* selection made "backwards" */ rect.x=FlocaleTextWidth( xobj->Ffont, xobj->title+ start_pos, curs_pos) - 1; rect.y=0; rect.width=FlocaleTextWidth( xobj->Ffont, xobj->title+ start_pos, selection_pos - start_pos) - rect.x+2; rect.height=xobj->height; xobj->value2= PosCurs + xobj->value3; DrawTextField(xobj,NULL); } break; case ButtonRelease: ButPress=0; break; } } /* Enregistrement de la selection dans le presse papier */ /* Le programme devient proprietaire de la selection */ /* selection stuff: get the selection */ if (xobj->value != xobj->value2) { str=(char*)GetText(xobj, xobj->value2); for (i=0;i<=7;i++) XStoreBuffer(dpy,str,strlen(str),i); Scrapt = (char*)realloc( (void*)Scrapt, (strlen(str)+2)*sizeof(char)); Scrapt = strcpy(Scrapt,str); free(str); x11base->HaveXSelection=True; XSetSelectionOwner( dpy,XA_PRIMARY,x11base->win,EvtButton->time); SelectOneTextField(xobj); } break; case Button2: /* Colle le texte */ /* Si l'application possede pas la selection, elle la demande */ /* sinon elle lit son presse papier */ /* read the selection */ if (!x11base->HaveXSelection) { /* Demande de la selection */ /* ask for the selection */ XConvertSelection( dpy,XA_PRIMARY,XA_STRING,propriete, *xobj->ParentWin, EvtButton->time); while (!(FCheckTypedEvent(dpy,SelectionNotify,&event))) ; if (event.xselection.property!=None) if (event.xselection.selection==XA_PRIMARY) { XGetWindowProperty( dpy,event.xselection.requestor, event.xselection.property,0L, 8192L,False, event.xselection.target,&type, &format, &longueur, &octets_restant,&donnees); if (longueur>0) { Scrapt=(char*)realloc( (void*)Scrapt, (longueur+1)* sizeof(char)); Scrapt=strcpy( Scrapt,(char *)donnees); XDeleteProperty( dpy, event.xselection. requestor, event.xselection. property); XFree(donnees); } } } SizeBuf=strlen(Scrapt); if (SizeBuf>0) { NewPos=InsertText(xobj,Scrapt,SizeBuf); DrawPointTxt(xobj,xobj->TabColor[back]); xobj->value=NewPos; xobj->value2=NewPos; DrawPointTxt(xobj,xobj->TabColor[fore]); DrawTextField(xobj,NULL); SendMsg(xobj,SingleClic); } break; case Button3: /* Appuie sur le troisieme bouton */ FQueryPointer( dpy,*xobj->ParentWin,&Win1,&Win2,&x1,&y1,&x2,&y2, &modif); x2=x2-xobj->x; PosCurs=0; while ((PosCurs<strlen(xobj->title))&& (x2>FlocaleTextWidth( xobj->Ffont,xobj->title+xobj->value3, PosCurs)+8)) PosCurs++; if ((PosCurs<xobj->value) && (xobj->value<xobj->value2)) xobj->value=xobj->value2; if ((PosCurs>xobj->value) && (xobj->value>xobj->value2)) xobj->value=xobj->value2; xobj->value2=PosCurs+xobj->value3; DrawTextField(xobj,NULL); while (ButPress) { FNextEvent(dpy, &event); switch (event.type) { case MotionNotify: FQueryPointer( dpy,*xobj->ParentWin,&Win1,&Win2,&x1, &y1,&x2,&y2,&modif); x2=x2-xobj->x; while ((PosCurs<strlen(xobj->title))&& (x2 > FlocaleTextWidth( xobj->Ffont, xobj->title+xobj->value3, PosCurs)+8)) PosCurs++; if (PosCurs>xobj->value2) { rect.x= FlocaleTextWidth( xobj->Ffont, xobj->title+ xobj->value3, xobj->value2); rect.y=0; rect.width= FlocaleTextWidth( xobj->Ffont, xobj->title+ xobj->value3,PosCurs+1) -rect.x+1; rect.height=xobj->height; xobj->value2=PosCurs; DrawTextField(xobj,NULL); } else if (PosCurs<xobj->value2) { rect.x=FlocaleTextWidth( xobj->Ffont, xobj->title+ xobj->value3, PosCurs)-1; rect.y=0; rect.width=FlocaleTextWidth( xobj->Ffont, xobj->title+xobj-> value3, xobj->value2+1)- rect.x+2; rect.height=xobj->height; xobj->value2= PosCurs+xobj->value3; DrawTextField(xobj,NULL); } PosCurs=0; break; case ButtonRelease: ButPress=0; break; } } if (xobj->value!=xobj->value2) { str=(char*)GetText(xobj,xobj->value2); for (i=0;i<=7;i++) XStoreBuffer(dpy,str,strlen(str),i); Scrapt=(char*)realloc( (void*)Scrapt,(strlen(str)+2)*sizeof(char)); Scrapt=strcpy(Scrapt,str); free(str); x11base->HaveXSelection=True; XSetSelectionOwner( dpy,XA_PRIMARY,x11base->win,EvtButton->time); } break; } }
void EvtMousePushButton(struct XObj *xobj, XButtonEvent *EvtButton) { static XEvent event; int End = 1; unsigned int modif; int x1,x2,y1,y2,i; Window Win1,Win2,WinPop; Window WinBut = 0; int In = 0; char *str; int x,y,hOpt,yMenu,hMenu,wMenu; int oldvalue = 0,newvalue; unsigned long mask; XSetWindowAttributes Attr; if (EvtButton->button == Button1) { i = (xobj->width - FlocaleTextWidth( xobj->Ffont, xobj->title, strlen(xobj->title)))/2; while (End) { FNextEvent(dpy, &event); switch (event.type) { case EnterNotify: FQueryPointer( dpy, *xobj->ParentWin, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif); if (WinBut == 0) { WinBut = Win2; DrawReliefRect( 0, 0, xobj->width, xobj->height, xobj, shad, hili); DrawIconStr( 0,xobj, True, PUSH_BUTTON_LCR_OFFSETS, NULL, NULL, NULL); In = 1; } else { if (Win2 == WinBut) { DrawReliefRect( 0, 0, xobj->width, xobj->height, xobj, shad, hili); DrawIconStr( 1, xobj, True, PUSH_BUTTON_LCR_OFFSETS, NULL, NULL, NULL); In = 1; } else if (In) { In = 0; DrawReliefRect( 0, 0, xobj->width, xobj->height, xobj, hili, shad); DrawIconStr( 0, xobj, True, PUSH_BUTTON_LCR_OFFSETS, NULL, NULL, NULL); } } break; case LeaveNotify: FQueryPointer( dpy, *xobj->ParentWin, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif); if (Win2 == WinBut) { In = 1; DrawReliefRect( 0, 0, xobj->width, xobj->height, xobj, shad, hili); DrawIconStr( 1, xobj, True, PUSH_BUTTON_LCR_OFFSETS, NULL, NULL, NULL); } else if (In) { DrawReliefRect( 0, 0, xobj->width, xobj->height, xobj, hili, shad); DrawIconStr( 0, xobj, True, PUSH_BUTTON_LCR_OFFSETS, NULL, NULL, NULL); In = 0; } break; case ButtonRelease: End = 0; DrawReliefRect( 0, 0, xobj->width, xobj->height, xobj, hili, shad); DrawIconStr( 0, xobj, True, PUSH_BUTTON_LCR_OFFSETS, NULL, NULL, NULL); if (In) { /* Envoie d'un message vide de type * SingleClic pour un clique souris */ xobj->value = 1; SendMsg(xobj, SingleClic); xobj->value = 0; } break; } } } /* affichage du popup menu / Drawing the popup menu */ else if (EvtButton->button == Button3) { if (xobj->value3 > 1) { hOpt = xobj->Ffont->height + 10; /* Hauteur totale du menu / Total height of the menu */ hMenu = (xobj->value3 - 1) * hOpt; yMenu = xobj->y + xobj->height; wMenu = 0; for (i = 2 ; i <= xobj->value3; i++) { str = (char*)GetMenuTitle(xobj->title, i); if (wMenu < FlocaleTextWidth( xobj->Ffont, str, strlen(str))+34) wMenu = FlocaleTextWidth( xobj->Ffont, str, strlen(str))+34; free(str); } /* Creation de la fenetre menu / create the menu * window */ XTranslateCoordinates(dpy, *xobj->ParentWin, Root, xobj->x, yMenu, &x, &y, &Win1); if (x<0) x = 0; if (y<0) y = 0; if (x + wMenu > XDisplayWidth(dpy, screen)) { x = XDisplayWidth(dpy, screen) - wMenu; } if (y + hMenu > XDisplayHeight(dpy, screen)) { y = y-hMenu-xobj->height; } mask = 0; Attr.background_pixel = xobj->TabColor[back]; mask |= CWBackPixel; Attr.border_pixel = 0; mask |= CWBorderPixel; Attr.colormap = Pcmap; mask |= CWColormap; Attr.cursor = XCreateFontCursor(dpy, XC_hand2); mask |= CWCursor; /* Curseur pour la fenetre */ Attr.override_redirect = True; mask |= CWOverrideRedirect; WinPop = XCreateWindow( dpy, Root, x, y, wMenu-5, hMenu, 0, Pdepth, InputOutput, Pvisual, mask, &Attr); if (xobj->colorset >= 0) SetWindowBackground( dpy, WinPop, wMenu - 5, hMenu, &Colorset[xobj->colorset], Pdepth, xobj->gc, True); XMapRaised(dpy, WinPop); /* Dessin du menu */ DrawPMenu(xobj, WinPop, hOpt, 1); do { FQueryPointer( dpy, Root, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif); /* Determiner l'option courante / Current * option */ y2 = y2 - y; x2 = x2 - x; { /* calcule de xobj->value / Compute * xobj->value */ if ((x2 > 0) && (x2 < wMenu) && (y2 > 0) && (y2 < hMenu)) newvalue = y2 / hOpt+1; else newvalue = 0; if (newvalue!=oldvalue) { UnselectMenu( xobj, WinPop, hOpt, oldvalue, wMenu-5, xobj->Ffont->ascent, 1); SelectMenu( xobj, WinPop, hOpt, newvalue); oldvalue = newvalue; } } } while (!FCheckTypedEvent(dpy, ButtonRelease, &event)); XDestroyWindow(dpy, WinPop); if (newvalue != 0) { xobj->value = newvalue; SendMsg(xobj, SingleClic); xobj->value = 0; } xobj->DrawObj(xobj, NULL); } /* xobj->value3 > 1 */ } /* EvtButton->button == Button3 */ }