void appIconMouseDown(WObjDescriptor *desc, XEvent *event) { WAppIcon *aicon = desc->parent; WIcon *icon = aicon->icon; XEvent ev; int x=aicon->x_pos, y=aicon->y_pos; int dx=event->xbutton.x, dy=event->xbutton.y; int grabbed=0; int done=0; int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ WScreen *scr = icon->core->screen_ptr; WWorkspace *workspace = scr->workspaces[scr->current_workspace]; int shad_x = 0, shad_y = 0, docking=0, dockable, collapsed = 0; int ix, iy; int clickButton = event->xbutton.button; Pixmap ghost = None; Window wins[2]; Bool movingSingle = False; int oldX = x; int oldY = y; Bool hasMoved = False; if (aicon->editing || WCHECK_STATE(WSTATE_MODAL)) return; if (IsDoubleClick(scr, event)) { iconDblClick(desc, event); return; } if (event->xbutton.button == Button3) { WObjDescriptor *desc; WApplication *wapp = wApplicationOf(aicon->icon->owner->main_window); if (!wapp) return; if (event->xbutton.send_event && XGrabPointer(dpy, aicon->icon->core->window, True, ButtonMotionMask |ButtonReleaseMask|ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) { wwarning("pointer grab failed for appicon menu"); return; } openApplicationMenu(wapp, event->xbutton.x_root, event->xbutton.y_root); /* allow drag select of menu */ desc = &scr->icon_menu->menu->descriptor; event->xbutton.send_event = True; (*desc->handle_mousedown)(desc, event); return; } #ifdef DEBUG puts("Moving icon"); #endif if (event->xbutton.state & MOD_MASK) wLowerFrame(icon->core); else wRaiseFrame(icon->core); if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask |ButtonReleaseMask|ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) { wwarning("pointer grab failed for appicon move"); } if (wPreferences.flags.nodock && wPreferences.flags.noclip) dockable = 0; else dockable = canBeDocked(icon->owner); wins[0] = icon->core->window; wins[1] = scr->dock_shadow; XRestackWindows(dpy, wins, 2); if (superfluous) { if (icon->pixmap!=None) ghost = MakeGhostIcon(scr, icon->pixmap); else ghost = MakeGhostIcon(scr, icon->core->window); XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); XClearWindow(dpy, scr->dock_shadow); } while (!done) { WMMaskEvent(dpy, PointerMotionMask|ButtonReleaseMask|ButtonPressMask |ButtonMotionMask|ExposureMask, &ev); switch (ev.type) { case Expose: WMHandleEvent(&ev); break; case MotionNotify: hasMoved = True; if (!grabbed) { if (abs(dx-ev.xmotion.x)>=MOVE_THRESHOLD || abs(dy-ev.xmotion.y)>=MOVE_THRESHOLD) { XChangeActivePointerGrab(dpy, ButtonMotionMask |ButtonReleaseMask|ButtonPressMask, wCursor[WCUR_MOVE], CurrentTime); grabbed=1; } else { break; } } x = ev.xmotion.x_root - dx; y = ev.xmotion.y_root - dy; if (movingSingle) { XMoveWindow(dpy, icon->core->window, x, y); } else { wAppIconMove(aicon, x, y); } if (dockable) { if (scr->dock && wDockSnapIcon(scr->dock, aicon, x, y, &ix, &iy, False)) { shad_x = scr->dock->x_pos + ix*wPreferences.icon_size; shad_y = scr->dock->y_pos + iy*wPreferences.icon_size; if (scr->last_dock != scr->dock && collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (!collapsed && (collapsed = scr->dock->collapsed)) { scr->dock->collapsed = 0; wDockShowIcons(scr->dock); } if (scr->dock->auto_raise_lower) wDockRaise(scr->dock); scr->last_dock = scr->dock; XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); if (!docking) { XMapWindow(dpy, scr->dock_shadow); } docking = 1; } else if (workspace->clip && wDockSnapIcon(workspace->clip, aicon, x, y, &ix, &iy, False)) { shad_x = workspace->clip->x_pos + ix*wPreferences.icon_size; shad_y = workspace->clip->y_pos + iy*wPreferences.icon_size; if (scr->last_dock != workspace->clip && collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (!collapsed && (collapsed = workspace->clip->collapsed)) { workspace->clip->collapsed = 0; wDockShowIcons(workspace->clip); } if (workspace->clip->auto_raise_lower) wDockRaise(workspace->clip); scr->last_dock = workspace->clip; XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); if (!docking) { XMapWindow(dpy, scr->dock_shadow); } docking = 1; } else if (docking) { XUnmapWindow(dpy, scr->dock_shadow); docking = 0; } } break; case ButtonPress: break; case ButtonRelease: if (ev.xbutton.button != clickButton) break; XUngrabPointer(dpy, CurrentTime); if (docking) { Bool docked; /* icon is trying to be docked */ SlideWindow(icon->core->window, x, y, shad_x, shad_y); XUnmapWindow(dpy, scr->dock_shadow); docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy); if (scr->last_dock->auto_collapse) { collapsed = 0; } if (workspace->clip && workspace->clip != scr->last_dock && workspace->clip->auto_raise_lower) wDockLower(workspace->clip); if (!docked) { /* If icon could not be docked, slide it back to the old * position */ SlideWindow(icon->core->window, x, y, oldX, oldY); } wSoundPlay(WSOUND_DOCK); } else { if (movingSingle) { /* move back to its place */ SlideWindow(icon->core->window, x, y, oldX, oldY); wAppIconMove(aicon, oldX, oldY); } else { XMoveWindow(dpy, icon->core->window, x, y); aicon->x_pos = x; aicon->y_pos = y; } if (workspace->clip && workspace->clip->auto_raise_lower) wDockLower(workspace->clip); } if (collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (superfluous) { if (ghost!=None) XFreePixmap(dpy, ghost); XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel); } if (wPreferences.auto_arrange_icons) wArrangeIcons(scr, True); if (wPreferences.single_click && !hasMoved) iconDblClick(desc, event); done = 1; break; } } #ifdef DEBUG puts("End icon move"); #endif }
static void appicon_move_motion(virtual_screen *vscr, WScreen *scr, XEvent ev, WDock **lastDock, WDock **originalDock, WAppIcon *aicon, WDock **allDocks, Bool *collapsed, Bool *dockable, Bool *ondock, int *x, int *y, int *ix, int *iy, int *shad_x, int *shad_y, int *ofs_x, int *ofs_y, Bool *grabbed, int omnipresent, Bool *showed_all_clips) { WDock *theNewDock = NULL; int i, j; if (!(*grabbed)) { if (abs(*ofs_x - ev.xmotion.x) < MOVE_THRESHOLD && abs(*ofs_y - ev.xmotion.y) < MOVE_THRESHOLD) return; XChangeActivePointerGrab(dpy, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, wPreferences.cursor[WCUR_MOVE], CurrentTime); *grabbed = True; } if (omnipresent && !(*showed_all_clips)) { for (j = 0; j < vscr->workspace.count; j++) { if (j == vscr->workspace.current) continue; wDockShowIcons(vscr->workspace.array[j]->clip); /* * Note: if dock is collapsed (for instance, because it * auto-collapses), its icons still won't show up */ } *showed_all_clips = True; /* To prevent flickering */ } *x = ev.xmotion.x_root - *ofs_x; *y = ev.xmotion.y_root - *ofs_y; wAppIconMove(aicon, *x, *y); if (!(ev.xmotion.state & MOD_MASK) || aicon->launching || aicon->lock || *originalDock == NULL) { for (i = 0; *dockable && i < vscr->drawer.drawer_count + 2; i++) { WDock *theDock = allDocks[i]; if (theDock == NULL) break; if (wDockSnapIcon(theDock, aicon, *x, *y, ix, iy, (theDock == *originalDock))) { theNewDock = theDock; break; } } /* Stay in lastDock if no dock really wants us */ if (*originalDock != NULL && theNewDock == NULL && (aicon->launching || aicon->lock || aicon->running)) theNewDock = *lastDock; } if (*lastDock != NULL && *lastDock != theNewDock) { /* Leave lastDock in the state we found it */ if ((*lastDock)->type == WM_DRAWER) wDrawerFillTheGap(*lastDock, aicon, (*lastDock == *originalDock)); if (*collapsed) { (*lastDock)->collapsed = 1; wDockHideIcons(*lastDock); *collapsed = False; } if ((*lastDock)->auto_raise_lower) wDockLower(*lastDock); } if (theNewDock != NULL) { if (*lastDock != theNewDock) { *collapsed = theNewDock->collapsed; if (*collapsed) { theNewDock->collapsed = 0; wDockShowIcons(theNewDock); } if (theNewDock->auto_raise_lower) { wDockRaise(theNewDock); /* And raise the moving tile above it */ wRaiseFrame(aicon->icon->vscr, aicon->icon->core); } *lastDock = theNewDock; } *shad_x = (*lastDock)->x_pos + *ix * wPreferences.icon_size; *shad_y = (*lastDock)->y_pos + *iy * wPreferences.icon_size; XMoveWindow(dpy, scr->dock_shadow, *shad_x, *shad_y); if (!(*ondock)) XMapWindow(dpy, scr->dock_shadow); *ondock = 1; } else { *lastDock = NULL; if (*ondock) XUnmapWindow(dpy, scr->dock_shadow); *ondock = 0; } }
void StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next, Bool class_only) { WShortKey binding; WSwitchPanel *swpanel = NULL; WScreen *scr = wScreenForRootWindow(event->xkey.root); KeyCode leftKey = XKeysymToKeycode(dpy, XK_Left); KeyCode rightKey = XKeysymToKeycode(dpy, XK_Right); KeyCode homeKey = XKeysymToKeycode(dpy, XK_Home); KeyCode endKey = XKeysymToKeycode(dpy, XK_End); KeyCode shiftLKey = XKeysymToKeycode(dpy, XK_Shift_L); KeyCode shiftRKey = XKeysymToKeycode(dpy, XK_Shift_R); KeyCode escapeKey = XKeysymToKeycode(dpy, XK_Escape); KeyCode returnKey = XKeysymToKeycode(dpy, XK_Return); Bool esc_cancel = False; Bool somethingElse = False; Bool done = False; Bool hasModifier; int modifiers; WWindow *newFocused; WWindow *oldFocused; XEvent ev; if (!wwin) return; if (next) { if (class_only) binding = wKeyBindings[WKBD_GROUPNEXT]; else binding = wKeyBindings[WKBD_FOCUSNEXT]; } else { if (class_only) binding = wKeyBindings[WKBD_GROUPPREV]; else binding = wKeyBindings[WKBD_FOCUSPREV]; } hasModifier = (binding.modifier != 0); if (hasModifier) XGrabKeyboard(dpy, scr->root_win, False, GrabModeAsync, GrabModeAsync, CurrentTime); scr->flags.doing_alt_tab = 1; swpanel = wInitSwitchPanel(scr, wwin, class_only); oldFocused = wwin; if (swpanel) { if (wwin->flags.mapped && !wPreferences.panel_only_open) newFocused = wSwitchPanelSelectNext(swpanel, !next, True, False); else newFocused = wSwitchPanelSelectFirst(swpanel, False); oldFocused = change_focus_and_raise(newFocused, oldFocused, swpanel, scr, False); } else { if (wwin->frame->workspace == w_global.workspace.current) newFocused = wwin; else newFocused = NULL; } while (hasModifier && !done) { WMMaskEvent(dpy, KeyPressMask | KeyReleaseMask | ExposureMask | PointerMotionMask | ButtonReleaseMask | EnterWindowMask, &ev); /* ignore CapsLock */ modifiers = ev.xkey.state & w_global.shortcut.modifiers_mask; if (!swpanel) break; switch (ev.type) { case KeyPress: if ((wKeyBindings[WKBD_FOCUSNEXT].keycode == ev.xkey.keycode && wKeyBindings[WKBD_FOCUSNEXT].modifier == modifiers) || (wKeyBindings[WKBD_GROUPNEXT].keycode == ev.xkey.keycode && wKeyBindings[WKBD_GROUPNEXT].modifier == modifiers) || ev.xkey.keycode == rightKey) { newFocused = wSwitchPanelSelectNext(swpanel, False, ev.xkey.keycode != rightKey, (!class_only && wKeyBindings[WKBD_GROUPNEXT].keycode == ev.xkey.keycode && wKeyBindings[WKBD_GROUPNEXT].modifier == modifiers)); oldFocused = change_focus_and_raise(newFocused, oldFocused, swpanel, scr, False); } else if ((wKeyBindings[WKBD_FOCUSPREV].keycode == ev.xkey.keycode && wKeyBindings[WKBD_FOCUSPREV].modifier == modifiers) || (wKeyBindings[WKBD_GROUPPREV].keycode == ev.xkey.keycode && wKeyBindings[WKBD_GROUPPREV].modifier == modifiers) || ev.xkey.keycode == leftKey) { newFocused = wSwitchPanelSelectNext(swpanel, True, ev.xkey.keycode != leftKey, (!class_only && wKeyBindings[WKBD_GROUPPREV].keycode == ev.xkey.keycode && wKeyBindings[WKBD_GROUPPREV].modifier == modifiers)); oldFocused = change_focus_and_raise(newFocused, oldFocused, swpanel, scr, False); } else if (ev.xkey.keycode == homeKey || ev.xkey.keycode == endKey) { newFocused = wSwitchPanelSelectFirst(swpanel, ev.xkey.keycode != homeKey); oldFocused = change_focus_and_raise(newFocused, oldFocused, swpanel, scr, False); } else if (ev.xkey.keycode == escapeKey) { /* Focus the first window of the swpanel, despite the 'False' */ newFocused = wSwitchPanelSelectFirst(swpanel, False); oldFocused = change_focus_and_raise(newFocused, oldFocused, swpanel, scr, True); esc_cancel = True; done = True; } else if (ev.xkey.keycode == returnKey) { /* Close the switchpanel without eating the keypress */ done = True; } else if (ev.xkey.keycode != shiftLKey && ev.xkey.keycode != shiftRKey) { somethingElse = True; done = True; } break; case KeyRelease: if (ev.xkey.keycode == shiftLKey || ev.xkey.keycode == shiftRKey) if (wPreferences.strict_windoze_cycle) break; if (ev.xkey.keycode == leftKey || ev.xkey.keycode == rightKey) break; if (ev.xkey.keycode == XK_Return) break; if (ev.xkey.keycode != binding.keycode) done = True; break; case EnterNotify: /* ignore unwanted EnterNotify's */ break; case LeaveNotify: case MotionNotify: case ButtonRelease: { WWindow *tmp; tmp = wSwitchPanelHandleEvent(swpanel, &ev); if (tmp) { newFocused = tmp; oldFocused = change_focus_and_raise(newFocused, oldFocused, swpanel, scr, False); if (ev.type == ButtonRelease) done = True; } } break; default: WMHandleEvent(&ev); break; } } if (hasModifier) XUngrabKeyboard(dpy, CurrentTime); if (swpanel) wSwitchPanelDestroy(swpanel); if (newFocused && !esc_cancel) { wRaiseFrame(newFocused->frame->core); CommitStacking(scr); if (!newFocused->flags.mapped) wMakeWindowVisible(newFocused); wSetFocusTo(scr, newFocused); } scr->flags.doing_alt_tab = 0; if (somethingElse) WMHandleEvent(&ev); }
Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) { WIcon *icon = aicon->icon; virtual_screen *vscr = aicon->icon->vscr; WScreen *scr = vscr->screen_ptr; WDock *originalDock = aicon->dock; /* can be NULL */ WDock *lastDock = originalDock; WDock *allDocks[vscr->drawer.drawer_count + 2]; /* clip, dock and drawers (order determined at runtime) */ WDrawerChain *dc; Bool dockable = True; Bool ondock = True; Bool grabbed = False; Bool collapsed = False; /* Stores the collapsed state of lastDock, before the moving appicon entered it */ int superfluous = wPreferences.superfluous; /* we cache it to avoid problems */ int omnipresent = aicon->omnipresent; /* this must be cached */ Bool showed_all_clips = False; int clickButton = event->xbutton.button; Pixmap ghost = None; Window wins[2]; /* Managing shadow window */ XEvent ev; int x = aicon->x_pos, y = aicon->y_pos; int ofs_x = event->xbutton.x, ofs_y = event->xbutton.y; int shad_x = x, shad_y = y; int ix = aicon->xindex, iy = aicon->yindex; int i; int oldX = x; int oldY = y; Bool hasMoved = False; if (wPreferences.flags.noupdates && originalDock != NULL) return False; if (event->xbutton.state & MOD_MASK) { /* * If Mod is pressed for an docked appicon, * assume it is to undock it,so don't lower it */ if (originalDock == NULL) wLowerFrame(icon->vscr, icon->core); } else { wRaiseFrame(icon->vscr, icon->core); } if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) != GrabSuccess) wwarning("Pointer grab failed in wHandleAppIconMove"); if (originalDock == NULL) { ondock = False; if (wPreferences.flags.nodock && wPreferences.flags.noclip && wPreferences.flags.nodrawer) dockable = False; else dockable = canBeDocked(icon->owner); } /* * We try the various docks in that order: * - First, the dock the appicon comes from, if any * - Then, the drawers * - Then, the "dock" (WM_DOCK) * - Finally, the clip */ i = 0; if (originalDock != NULL) allDocks[i++] = originalDock; /* Testing vscr->drawers is enough, no need to test wPreferences.flags.nodrawer */ for (dc = vscr->drawer.drawers; dc != NULL; dc = dc->next) if (dc->adrawer != originalDock) allDocks[i++] = dc->adrawer; if (!wPreferences.flags.nodock && vscr->dock.dock != originalDock) allDocks[i++] = vscr->dock.dock; if (!wPreferences.flags.noclip && originalDock != vscr->workspace.array[vscr->workspace.current]->clip) allDocks[i++] = vscr->workspace.array[vscr->workspace.current]->clip; /* In case the clip, the dock, or both, are disabled */ for ( ; i < vscr->drawer.drawer_count + 2; i++) allDocks[i] = NULL; wins[0] = icon->core->window; wins[1] = scr->dock_shadow; XRestackWindows(dpy, wins, 2); XMoveResizeWindow(dpy, scr->dock_shadow, aicon->x_pos, aicon->y_pos, ICON_SIZE, ICON_SIZE); if (superfluous) { if (icon->pixmap != None) ghost = MakeGhostIcon(vscr, icon->pixmap); else ghost = MakeGhostIcon(vscr, icon->core->window); XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); XClearWindow(dpy, scr->dock_shadow); } if (ondock) XMapWindow(dpy, scr->dock_shadow); while (1) { WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask | ButtonMotionMask | ExposureMask | EnterWindowMask, &ev); switch (ev.type) { case Expose: WMHandleEvent(&ev); break; case EnterNotify: /* * It means the cursor moved so fast that it entered * something else (if moving slowly, it would have * stayed in the appIcon that is being moved. Ignore * such "spurious" EnterNotifiy's */ break; case MotionNotify: hasMoved = True; appicon_move_motion(vscr, scr, ev, &lastDock, &originalDock, aicon, allDocks, &collapsed, &dockable, &ondock, &x, &y, &ix, &iy, &shad_x, &shad_y, &ofs_x, &ofs_y, &grabbed, omnipresent, &showed_all_clips); break; case ButtonPress: break; case ButtonRelease: if (ev.xbutton.button != clickButton) break; appicon_move_button_release(originalDock, lastDock, aicon, icon, x, y, oldX, oldY, shad_x, shad_y, ix, iy, &collapsed, ondock, ghost, showed_all_clips); return hasMoved; } } }