mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 20:38:08 +01:00
Merging appicon.c:appIconMouseDown and dock.c:handleIconMove into appicon.c:wHandleAppIconMove
Behaves essentially the same, only a bit more consistently. Known differences: 1. An AppIcon will now always end up undocked if moved while Mod1 is pressed. 2. Moving a docked AppIcon with Mod1 pressed (undocking it) used to auto-expand the clip, as clip expansion happened first, while looking for a snapping position, and the test on Mod1 being pressed happened only later
This commit is contained in:
committed by
Carlos R. Mafra
parent
8b6ff01d39
commit
9fae35fbc4
320
src/appicon.c
320
src/appicon.c
@@ -63,6 +63,7 @@ extern WDDomain *WDWindowAttributes;
|
|||||||
extern XContext wWinContext;
|
extern XContext wWinContext;
|
||||||
|
|
||||||
#define MOD_MASK wPreferences.modifier_mask
|
#define MOD_MASK wPreferences.modifier_mask
|
||||||
|
#define ICON_SIZE wPreferences.icon_size
|
||||||
|
|
||||||
void appIconMouseDown(WObjDescriptor * desc, XEvent * event);
|
void appIconMouseDown(WObjDescriptor * desc, XEvent * event);
|
||||||
static void iconDblClick(WObjDescriptor * desc, XEvent * event);
|
static void iconDblClick(WObjDescriptor * desc, XEvent * event);
|
||||||
@@ -667,24 +668,8 @@ static void iconDblClick(WObjDescriptor *desc, XEvent *event)
|
|||||||
void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||||
{
|
{
|
||||||
WAppIcon *aicon = desc->parent;
|
WAppIcon *aicon = desc->parent;
|
||||||
WIcon *icon = aicon->icon;
|
WScreen *scr = aicon->icon->core->screen_ptr;
|
||||||
XEvent ev;
|
Bool hasMoved;
|
||||||
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))
|
if (aicon->editing || WCHECK_STATE(WSTATE_MODAL))
|
||||||
return;
|
return;
|
||||||
@@ -729,24 +714,92 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->xbutton.state & MOD_MASK)
|
hasMoved = wHandleAppIconMove(aicon, event);
|
||||||
wLowerFrame(icon->core);
|
if (wPreferences.single_click && !hasMoved && aicon->dock != NULL)
|
||||||
else
|
{
|
||||||
|
iconDblClick(desc, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event)
|
||||||
|
{
|
||||||
|
WDock *originalDock = aicon->dock; /* can be NULL */
|
||||||
|
WDock *lastDock = originalDock;
|
||||||
|
WDock *allDocks[2]; /* clip and dock (order to be determined at runtime) */
|
||||||
|
Bool done = False, dockable, ondock;
|
||||||
|
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;
|
||||||
|
|
||||||
|
WIcon *icon = aicon->icon;
|
||||||
|
WScreen *scr = icon->core->screen_ptr;
|
||||||
|
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))
|
||||||
wRaiseFrame(icon->core);
|
wRaiseFrame(icon->core);
|
||||||
|
else {
|
||||||
|
/* If Mod is pressed for an docked appicon, assume it is to undock it,
|
||||||
|
* so don't lower it */
|
||||||
|
if (originalDock == NULL)
|
||||||
|
wLowerFrame(icon->core);
|
||||||
|
}
|
||||||
|
|
||||||
if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask
|
if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask
|
||||||
| ButtonReleaseMask | ButtonPressMask, GrabModeAsync,
|
| ButtonReleaseMask | ButtonPressMask, GrabModeAsync,
|
||||||
GrabModeAsync, None, None, CurrentTime) != GrabSuccess)
|
GrabModeAsync, None, None, CurrentTime) != GrabSuccess) {
|
||||||
wwarning("pointer grab failed for appicon move");
|
wwarning("Pointer grab failed in wHandleAppIconMove");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalDock != NULL) {
|
||||||
|
dockable = True;
|
||||||
|
ondock = True;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ondock = False;
|
||||||
if (wPreferences.flags.nodock && wPreferences.flags.noclip)
|
if (wPreferences.flags.nodock && wPreferences.flags.noclip)
|
||||||
dockable = 0;
|
dockable = 0;
|
||||||
else
|
else
|
||||||
dockable = canBeDocked(icon->owner);
|
dockable = canBeDocked(icon->owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We try the various docks in that order:
|
||||||
|
* - First, the dock the appicon comes from, if any
|
||||||
|
* - Then, the "dock" (WM_DOCK)
|
||||||
|
* - Finally, the clip
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
if (originalDock != NULL)
|
||||||
|
allDocks[ i++ ] = originalDock;
|
||||||
|
if (!wPreferences.flags.nodock && scr->dock != originalDock)
|
||||||
|
allDocks[ i++ ] = scr->dock;
|
||||||
|
if (!wPreferences.flags.noclip &&
|
||||||
|
originalDock != scr->workspaces[scr->current_workspace]->clip)
|
||||||
|
allDocks[ i++ ] = scr->workspaces[scr->current_workspace]->clip;
|
||||||
|
for ( ; i < 2; i++) /* In case the clip, the dock, or both, are disabled */
|
||||||
|
allDocks[ i ] = NULL;
|
||||||
|
|
||||||
|
|
||||||
wins[0] = icon->core->window;
|
wins[0] = icon->core->window;
|
||||||
wins[1] = scr->dock_shadow;
|
wins[1] = scr->dock_shadow;
|
||||||
XRestackWindows(dpy, wins, 2);
|
XRestackWindows(dpy, wins, 2);
|
||||||
|
XMoveResizeWindow(dpy, scr->dock_shadow, aicon->x_pos, aicon->y_pos, ICON_SIZE, ICON_SIZE);
|
||||||
if (superfluous) {
|
if (superfluous) {
|
||||||
if (icon->pixmap != None)
|
if (icon->pixmap != None)
|
||||||
ghost = MakeGhostIcon(scr, icon->pixmap);
|
ghost = MakeGhostIcon(scr, icon->pixmap);
|
||||||
@@ -755,6 +808,8 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
|||||||
XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost);
|
XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost);
|
||||||
XClearWindow(dpy, scr->dock_shadow);
|
XClearWindow(dpy, scr->dock_shadow);
|
||||||
}
|
}
|
||||||
|
if (ondock)
|
||||||
|
XMapWindow(dpy, scr->dock_shadow);
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask
|
WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask
|
||||||
@@ -774,8 +829,8 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
|||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
hasMoved = True;
|
hasMoved = True;
|
||||||
if (!grabbed) {
|
if (!grabbed) {
|
||||||
if (abs(dx - ev.xmotion.x) >= MOVE_THRESHOLD
|
if (abs(ofs_x - ev.xmotion.x) >= MOVE_THRESHOLD
|
||||||
|| abs(dy - ev.xmotion.y) >= MOVE_THRESHOLD) {
|
|| abs(ofs_y - ev.xmotion.y) >= MOVE_THRESHOLD) {
|
||||||
XChangeActivePointerGrab(dpy, ButtonMotionMask
|
XChangeActivePointerGrab(dpy, ButtonMotionMask
|
||||||
| ButtonReleaseMask | ButtonPressMask,
|
| ButtonReleaseMask | ButtonPressMask,
|
||||||
wCursor[WCUR_MOVE], CurrentTime);
|
wCursor[WCUR_MOVE], CurrentTime);
|
||||||
@@ -784,68 +839,87 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x = ev.xmotion.x_root - dx;
|
|
||||||
y = ev.xmotion.y_root - dy;
|
|
||||||
|
|
||||||
if (movingSingle)
|
if (omnipresent && !showed_all_clips) {
|
||||||
XMoveWindow(dpy, icon->core->window, x, y);
|
int i;
|
||||||
else
|
for (i = 0; i < scr->workspace_count; i++) {
|
||||||
|
if (i == scr->current_workspace)
|
||||||
|
continue;
|
||||||
|
wDockShowIcons(scr->workspaces[i]->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);
|
wAppIconMove(aicon, x, y);
|
||||||
|
|
||||||
if (dockable) {
|
/* At a high level, this if-block is about setting theNewDock to
|
||||||
if (scr->dock && wDockSnapIcon(scr->dock, aicon, x, y, &ix, &iy, False)) {
|
* the first dock that could snap the appicon at the current
|
||||||
shad_x = scr->dock->x_pos + ix * wPreferences.icon_size;
|
* position, and the next if-block uses that and other info to
|
||||||
shad_y = scr->dock->y_pos + iy * wPreferences.icon_size;
|
* determine whether to dock/undock.
|
||||||
|
*/
|
||||||
if (scr->last_dock != scr->dock && collapsed) {
|
WDock *theNewDock = NULL;
|
||||||
scr->last_dock->collapsed = 1;
|
for (i = 0; dockable && i < 2; i++) {
|
||||||
wDockHideIcons(scr->last_dock);
|
WDock *theDock = allDocks[i];
|
||||||
collapsed = 0;
|
if (theDock == NULL)
|
||||||
|
break;
|
||||||
|
if (wDockSnapIcon(theDock, aicon, x, y, &ix, &iy, (theDock == originalDock))) {
|
||||||
|
theNewDock = theDock;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!collapsed && (collapsed = scr->dock->collapsed)) {
|
}
|
||||||
scr->dock->collapsed = 0;
|
if (originalDock != NULL && theNewDock == NULL &&
|
||||||
wDockShowIcons(scr->dock);
|
(aicon->launching || aicon->lock || aicon->running)) {
|
||||||
|
/* In those cases, stay in lastDock if no dock really wants us */
|
||||||
|
theNewDock = lastDock;
|
||||||
|
}
|
||||||
|
if (theNewDock != NULL && !aicon->launching && !aicon->lock && ev.xmotion.state & MOD_MASK)
|
||||||
|
/* Mod is pressed: do not dock */
|
||||||
|
theNewDock = NULL;
|
||||||
|
if (lastDock != NULL && lastDock != theNewDock) {
|
||||||
|
/* Leave lastDock in the state we found it */
|
||||||
|
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->core);
|
||||||
|
}
|
||||||
|
lastDock = theNewDock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scr->dock->auto_raise_lower)
|
shad_x = lastDock->x_pos + ix*wPreferences.icon_size;
|
||||||
wDockRaise(scr->dock);
|
shad_y = lastDock->y_pos + iy*wPreferences.icon_size;
|
||||||
|
|
||||||
scr->last_dock = scr->dock;
|
|
||||||
|
|
||||||
XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y);
|
XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y);
|
||||||
if (!docking)
|
|
||||||
|
if (!ondock) {
|
||||||
XMapWindow(dpy, scr->dock_shadow);
|
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)) {
|
ondock = 1;
|
||||||
workspace->clip->collapsed = 0;
|
} else {
|
||||||
wDockShowIcons(workspace->clip);
|
lastDock = theNewDock; // i.e., NULL
|
||||||
}
|
if (ondock) {
|
||||||
|
|
||||||
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);
|
XUnmapWindow(dpy, scr->dock_shadow);
|
||||||
docking = 0;
|
|
||||||
}
|
}
|
||||||
|
ondock = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -857,41 +931,63 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
|||||||
break;
|
break;
|
||||||
XUngrabPointer(dpy, CurrentTime);
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
|
||||||
if (docking) {
|
Bool docked = False;
|
||||||
Bool docked;
|
if (ondock) {
|
||||||
|
|
||||||
/* icon is trying to be docked */
|
|
||||||
SlideWindow(icon->core->window, x, y, shad_x, shad_y);
|
SlideWindow(icon->core->window, x, y, shad_x, shad_y);
|
||||||
XUnmapWindow(dpy, scr->dock_shadow);
|
XUnmapWindow(dpy, scr->dock_shadow);
|
||||||
docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy, False);
|
if (originalDock == NULL) { // docking an undocked appicon
|
||||||
if (scr->last_dock->auto_collapse)
|
docked = wDockAttachIcon(lastDock, aicon, ix, iy, False);
|
||||||
collapsed = 0;
|
|
||||||
|
|
||||||
if (workspace->clip &&
|
|
||||||
workspace->clip != scr->last_dock && workspace->clip->auto_raise_lower)
|
|
||||||
wDockLower(workspace->clip);
|
|
||||||
|
|
||||||
if (!docked) {
|
if (!docked) {
|
||||||
/* If icon could not be docked, slide it back to the old
|
/* AppIcon got rejected (happens only when we can't get the
|
||||||
* position */
|
command for that appicon, and the user cancels the
|
||||||
|
wInputDialog asking for one). Make the rejection obvious by
|
||||||
|
sliding the icon to its old position */
|
||||||
SlideWindow(icon->core->window, x, y, oldX, oldY);
|
SlideWindow(icon->core->window, x, y, oldX, oldY);
|
||||||
}
|
}
|
||||||
} 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)
|
else { // moving a docked appicon to a dock
|
||||||
wDockLower(workspace->clip);
|
if (originalDock == lastDock) {
|
||||||
|
docked = True;
|
||||||
|
wDockReattachIcon(originalDock, aicon, ix, iy);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
docked = wDockMoveIconBetweenDocks(originalDock, lastDock, aicon, ix, iy);
|
||||||
|
if (!docked) {
|
||||||
|
/* Possible scenario: user moved an auto-attracted appicon
|
||||||
|
from the clip to the dock, and cancelled the wInputDialog
|
||||||
|
asking for a command */
|
||||||
|
SlideWindow(icon->core->window, x, y, oldX, oldY);
|
||||||
|
wDockReattachIcon(originalDock, aicon, aicon->xindex, aicon->yindex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No matter what happened above, check to lower lastDock
|
||||||
|
if (lastDock->auto_raise_lower)
|
||||||
|
wDockLower(lastDock);
|
||||||
|
/* If docked (or tried to dock) to a auto_collapsing dock, unset
|
||||||
|
* collapsed, so that wHandleAppIconMove doesn't collapse it
|
||||||
|
* right away (the timer will take care of it) */
|
||||||
|
if (lastDock->auto_collapse)
|
||||||
|
collapsed = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (originalDock != NULL) { /* Detaching a docked appicon */
|
||||||
|
if (superfluous) {
|
||||||
|
if (!aicon->running && !wPreferences.no_animations) {
|
||||||
|
/* We need to deselect it, even if is deselected in
|
||||||
|
* wDockDetach(), because else DoKaboom() will fail.
|
||||||
|
*/
|
||||||
|
if (aicon->icon->selected)
|
||||||
|
wIconSelect(aicon->icon);
|
||||||
|
DoKaboom(scr, aicon->icon->core->window, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wDockDetach(originalDock, aicon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (collapsed) {
|
if (collapsed) {
|
||||||
scr->last_dock->collapsed = 1;
|
lastDock->collapsed = 1;
|
||||||
wDockHideIcons(scr->last_dock);
|
wDockHideIcons(lastDock);
|
||||||
collapsed = 0;
|
collapsed = 0;
|
||||||
}
|
}
|
||||||
if (superfluous) {
|
if (superfluous) {
|
||||||
@@ -899,17 +995,21 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event)
|
|||||||
XFreePixmap(dpy, ghost);
|
XFreePixmap(dpy, ghost);
|
||||||
XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel);
|
XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel);
|
||||||
}
|
}
|
||||||
|
if (showed_all_clips) {
|
||||||
if (wPreferences.auto_arrange_icons)
|
int i;
|
||||||
|
for (i = 0; i < scr->workspace_count; i++) {
|
||||||
|
if (i == scr->current_workspace)
|
||||||
|
continue;
|
||||||
|
wDockHideIcons(scr->workspaces[i]->clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wPreferences.auto_arrange_icons && !(originalDock != NULL && docked))
|
||||||
|
/* Need to rearrange unless moving from dock to dock */
|
||||||
wArrangeIcons(scr, True);
|
wArrangeIcons(scr, True);
|
||||||
|
return hasMoved;
|
||||||
if (wPreferences.single_click && !hasMoved)
|
|
||||||
iconDblClick(desc, event);
|
|
||||||
|
|
||||||
done = 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return False; /* Never reached */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function save the application icon and store the path in the Dictionary */
|
/* This function save the application icon and store the path in the Dictionary */
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ typedef struct WAppIcon {
|
|||||||
|
|
||||||
WAppIcon *wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance,
|
WAppIcon *wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance,
|
||||||
char *wm_class, int tile);
|
char *wm_class, int tile);
|
||||||
|
Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event);
|
||||||
|
|
||||||
void wAppIconDestroy(WAppIcon *aicon);
|
void wAppIconDestroy(WAppIcon *aicon);
|
||||||
void wAppIconPaint(WAppIcon *aicon);
|
void wAppIconPaint(WAppIcon *aicon);
|
||||||
|
|||||||
226
src/dock.c
226
src/dock.c
@@ -105,8 +105,6 @@ static void clipLeave(WDock *dock);
|
|||||||
|
|
||||||
static void handleClipChangeWorkspace(WScreen *scr, XEvent *event);
|
static void handleClipChangeWorkspace(WScreen *scr, XEvent *event);
|
||||||
|
|
||||||
static Bool moveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y);
|
|
||||||
|
|
||||||
static void clipEnterNotify(WObjDescriptor *desc, XEvent *event);
|
static void clipEnterNotify(WObjDescriptor *desc, XEvent *event);
|
||||||
static void clipLeaveNotify(WObjDescriptor *desc, XEvent *event);
|
static void clipLeaveNotify(WObjDescriptor *desc, XEvent *event);
|
||||||
static void clipAutoCollapse(void *cdata);
|
static void clipAutoCollapse(void *cdata);
|
||||||
@@ -115,7 +113,6 @@ static void launchDockedApplication(WAppIcon *btn, Bool withSelection);
|
|||||||
|
|
||||||
static void clipAutoLower(void *cdata);
|
static void clipAutoLower(void *cdata);
|
||||||
static void clipAutoRaise(void *cdata);
|
static void clipAutoRaise(void *cdata);
|
||||||
static void reattachIcon(WDock *dock, WAppIcon *icon, int x, int y);
|
|
||||||
static WAppIcon *mainIconCreate(WScreen *scr, int type);
|
static WAppIcon *mainIconCreate(WScreen *scr, int type);
|
||||||
|
|
||||||
static int onScreen(WScreen *scr, int x, int y);
|
static int onScreen(WScreen *scr, int x, int y);
|
||||||
@@ -781,13 +778,13 @@ static void switchWSCommand(WMenu *menu, WMenuEntry *entry)
|
|||||||
|
|
||||||
WM_ITERATE_ARRAY(selectedIcons, btn, iter) {
|
WM_ITERATE_ARRAY(selectedIcons, btn, iter) {
|
||||||
if (wDockFindFreeSlot(dest, &x, &y)) {
|
if (wDockFindFreeSlot(dest, &x, &y)) {
|
||||||
moveIconBetweenDocks(src, dest, btn, x, y);
|
wDockMoveIconBetweenDocks(src, dest, btn, x, y);
|
||||||
XUnmapWindow(dpy, btn->icon->core->window);
|
XUnmapWindow(dpy, btn->icon->core->window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (icon != scr->clip_icon) {
|
} else if (icon != scr->clip_icon) {
|
||||||
if (wDockFindFreeSlot(dest, &x, &y)) {
|
if (wDockFindFreeSlot(dest, &x, &y)) {
|
||||||
moveIconBetweenDocks(src, dest, icon, x, y);
|
wDockMoveIconBetweenDocks(src, dest, icon, x, y);
|
||||||
XUnmapWindow(dpy, icon->icon->core->window);
|
XUnmapWindow(dpy, icon->icon->core->window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1961,7 +1958,7 @@ Bool wDockAttachIcon(WDock *dock, WAppIcon *icon, int x, int y, Bool update_icon
|
|||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reattachIcon(WDock *dock, WAppIcon *icon, int x, int y)
|
void wDockReattachIcon(WDock *dock, WAppIcon *icon, int x, int y)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -1978,7 +1975,7 @@ static void reattachIcon(WDock *dock, WAppIcon *icon, int x, int y)
|
|||||||
icon->y_pos = dock->y_pos + y * ICON_SIZE;
|
icon->y_pos = dock->y_pos + y * ICON_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool moveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y)
|
Bool wDockMoveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y)
|
||||||
{
|
{
|
||||||
WWindow *wwin;
|
WWindow *wwin;
|
||||||
char *command = NULL;
|
char *command = NULL;
|
||||||
@@ -2941,7 +2938,7 @@ void wClipUpdateForWorkspaceChange(WScreen *scr, int workspace)
|
|||||||
WAppIconChain *chain = scr->global_icons;
|
WAppIconChain *chain = scr->global_icons;
|
||||||
|
|
||||||
while (chain) {
|
while (chain) {
|
||||||
moveIconBetweenDocks(chain->aicon->dock,
|
wDockMoveIconBetweenDocks(chain->aicon->dock,
|
||||||
scr->workspaces[workspace]->clip,
|
scr->workspaces[workspace]->clip,
|
||||||
chain->aicon, chain->aicon->xindex, chain->aicon->yindex);
|
chain->aicon, chain->aicon->xindex, chain->aicon->yindex);
|
||||||
if (scr->workspaces[workspace]->clip->collapsed)
|
if (scr->workspaces[workspace]->clip->collapsed)
|
||||||
@@ -3400,217 +3397,6 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool handleIconMove(WDock *dock, WAppIcon *aicon, XEvent *event)
|
|
||||||
{
|
|
||||||
WScreen *scr = dock->screen_ptr;
|
|
||||||
Window wins[2];
|
|
||||||
WIcon *icon = aicon->icon;
|
|
||||||
WDock *dock2 = NULL, *last_dock = dock, *clip = NULL;
|
|
||||||
int ondock, grabbed = 0, change_dock = 0, collapsed = 0;
|
|
||||||
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 tmp;
|
|
||||||
Pixmap ghost = None;
|
|
||||||
Bool docked;
|
|
||||||
int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */
|
|
||||||
int omnipresent = aicon->omnipresent; /* this must be cached!!! */
|
|
||||||
Bool showed_all_clips = False;
|
|
||||||
Bool hasMoved = False;
|
|
||||||
|
|
||||||
if (wPreferences.flags.noupdates)
|
|
||||||
return hasMoved;
|
|
||||||
|
|
||||||
if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask
|
|
||||||
| ButtonReleaseMask | ButtonPressMask, GrabModeAsync,
|
|
||||||
GrabModeAsync, None, None, CurrentTime) != GrabSuccess) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(event->xbutton.state & MOD_MASK))
|
|
||||||
wRaiseFrame(icon->core);
|
|
||||||
|
|
||||||
if (!wPreferences.flags.noclip)
|
|
||||||
clip = scr->workspaces[scr->current_workspace]->clip;
|
|
||||||
|
|
||||||
if (dock == scr->dock && !wPreferences.flags.noclip)
|
|
||||||
dock2 = clip;
|
|
||||||
else if (dock != scr->dock && !wPreferences.flags.nodock)
|
|
||||||
dock2 = scr->dock;
|
|
||||||
|
|
||||||
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(scr, icon->pixmap);
|
|
||||||
else
|
|
||||||
ghost = MakeGhostIcon(scr, icon->core->window);
|
|
||||||
|
|
||||||
XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost);
|
|
||||||
XClearWindow(dpy, scr->dock_shadow);
|
|
||||||
}
|
|
||||||
XMapWindow(dpy, scr->dock_shadow);
|
|
||||||
|
|
||||||
ondock = 1;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
XMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask
|
|
||||||
| ButtonMotionMask | ExposureMask, &ev);
|
|
||||||
switch (ev.type) {
|
|
||||||
case Expose:
|
|
||||||
WMHandleEvent(&ev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionNotify:
|
|
||||||
hasMoved = True;
|
|
||||||
if (!grabbed) {
|
|
||||||
if (abs(ofs_x - ev.xmotion.x) >= MOVE_THRESHOLD
|
|
||||||
|| abs(ofs_y - ev.xmotion.y) >= MOVE_THRESHOLD) {
|
|
||||||
XChangeActivePointerGrab(dpy, ButtonMotionMask
|
|
||||||
| ButtonReleaseMask | ButtonPressMask,
|
|
||||||
wCursor[WCUR_MOVE], CurrentTime);
|
|
||||||
grabbed = 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (omnipresent && !showed_all_clips) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < scr->workspace_count; i++) {
|
|
||||||
if (i == scr->current_workspace)
|
|
||||||
continue;
|
|
||||||
wDockShowIcons(scr->workspaces[i]->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;
|
|
||||||
tmp = wDockSnapIcon(dock, aicon, x, y, &ix, &iy, True);
|
|
||||||
if (tmp && dock2) {
|
|
||||||
change_dock = 0;
|
|
||||||
if (last_dock != dock && collapsed) {
|
|
||||||
last_dock->collapsed = 1;
|
|
||||||
wDockHideIcons(last_dock);
|
|
||||||
collapsed = 0;
|
|
||||||
}
|
|
||||||
if (!collapsed && (collapsed = dock->collapsed)) {
|
|
||||||
dock->collapsed = 0;
|
|
||||||
wDockShowIcons(dock);
|
|
||||||
}
|
|
||||||
if (dock->auto_raise_lower)
|
|
||||||
wDockRaise(dock);
|
|
||||||
last_dock = dock;
|
|
||||||
} else if (dock2) {
|
|
||||||
tmp = wDockSnapIcon(dock2, aicon, x, y, &ix, &iy, False);
|
|
||||||
if (tmp) {
|
|
||||||
change_dock = 1;
|
|
||||||
if (last_dock != dock2 && collapsed) {
|
|
||||||
last_dock->collapsed = 1;
|
|
||||||
wDockHideIcons(last_dock);
|
|
||||||
collapsed = 0;
|
|
||||||
}
|
|
||||||
if (!collapsed && (collapsed = dock2->collapsed)) {
|
|
||||||
dock2->collapsed = 0;
|
|
||||||
wDockShowIcons(dock2);
|
|
||||||
}
|
|
||||||
if (dock2->auto_raise_lower)
|
|
||||||
wDockRaise(dock2);
|
|
||||||
last_dock = dock2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (aicon->launching || aicon->lock || (aicon->running && !(ev.xmotion.state & MOD_MASK))
|
|
||||||
|| (!aicon->running && tmp)) {
|
|
||||||
shad_x = last_dock->x_pos + ix * wPreferences.icon_size;
|
|
||||||
shad_y = last_dock->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 {
|
|
||||||
if (ondock)
|
|
||||||
XUnmapWindow(dpy, scr->dock_shadow);
|
|
||||||
|
|
||||||
ondock = 0;
|
|
||||||
}
|
|
||||||
XMoveWindow(dpy, icon->core->window, x, y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ButtonPress:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ButtonRelease:
|
|
||||||
if (ev.xbutton.button != event->xbutton.button)
|
|
||||||
break;
|
|
||||||
XUngrabPointer(dpy, CurrentTime);
|
|
||||||
if (ondock) {
|
|
||||||
SlideWindow(icon->core->window, x, y, shad_x, shad_y);
|
|
||||||
XUnmapWindow(dpy, scr->dock_shadow);
|
|
||||||
if (!change_dock) {
|
|
||||||
reattachIcon(dock, aicon, ix, iy);
|
|
||||||
if (clip && dock != clip && clip->auto_raise_lower)
|
|
||||||
wDockLower(clip);
|
|
||||||
} else {
|
|
||||||
docked = moveIconBetweenDocks(dock, dock2, aicon, ix, iy);
|
|
||||||
if (!docked) {
|
|
||||||
/* Slide it back if dock rejected it */
|
|
||||||
SlideWindow(icon->core->window, x, y, aicon->x_pos, aicon->y_pos);
|
|
||||||
reattachIcon(dock, aicon, aicon->xindex, aicon->yindex);
|
|
||||||
}
|
|
||||||
if (last_dock->type == WM_CLIP && last_dock->auto_collapse)
|
|
||||||
collapsed = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
aicon->x_pos = x;
|
|
||||||
aicon->y_pos = y;
|
|
||||||
if (superfluous) {
|
|
||||||
if (!aicon->running && !wPreferences.no_animations) {
|
|
||||||
/* We need to deselect it, even if is deselected in
|
|
||||||
* wDockDetach(), because else DoKaboom() will fail.
|
|
||||||
*/
|
|
||||||
if (aicon->icon->selected)
|
|
||||||
wIconSelect(aicon->icon);
|
|
||||||
|
|
||||||
DoKaboom(scr, aicon->icon->core->window, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (clip && clip->auto_raise_lower)
|
|
||||||
wDockLower(clip);
|
|
||||||
wDockDetach(dock, aicon);
|
|
||||||
}
|
|
||||||
if (collapsed) {
|
|
||||||
last_dock->collapsed = 1;
|
|
||||||
wDockHideIcons(last_dock);
|
|
||||||
collapsed = 0;
|
|
||||||
}
|
|
||||||
if (superfluous) {
|
|
||||||
if (ghost != None)
|
|
||||||
XFreePixmap(dpy, ghost);
|
|
||||||
XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel);
|
|
||||||
}
|
|
||||||
if (showed_all_clips) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < scr->workspace_count; i++) {
|
|
||||||
if (i == scr->current_workspace)
|
|
||||||
continue;
|
|
||||||
wDockHideIcons(scr->workspaces[i]->clip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hasMoved;;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return False; /* never reached */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getClipButton(int px, int py)
|
static int getClipButton(int px, int py)
|
||||||
{
|
{
|
||||||
@@ -3730,7 +3516,7 @@ static void iconMouseDown(WObjDescriptor *desc, XEvent *event)
|
|||||||
else
|
else
|
||||||
handleDockMove(dock, aicon, event);
|
handleDockMove(dock, aicon, event);
|
||||||
} else {
|
} else {
|
||||||
Bool hasMoved = handleIconMove(dock, aicon, event);
|
Bool hasMoved = wHandleAppIconMove(aicon, event);
|
||||||
if (wPreferences.single_click && !hasMoved)
|
if (wPreferences.single_click && !hasMoved)
|
||||||
iconDblClick(desc, event);
|
iconDblClick(desc, event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y,
|
|||||||
int *ret_x, int *ret_y, int redocking);
|
int *ret_x, int *ret_y, int redocking);
|
||||||
Bool wDockFindFreeSlot(WDock *dock, int *req_x, int *req_y);
|
Bool wDockFindFreeSlot(WDock *dock, int *req_x, int *req_y);
|
||||||
void wDockDetach(WDock *dock, WAppIcon *icon);
|
void wDockDetach(WDock *dock, WAppIcon *icon);
|
||||||
|
Bool wDockMoveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y);
|
||||||
|
void wDockReattachIcon(WDock *dock, WAppIcon *icon, int x, int y);
|
||||||
|
|
||||||
void wDockFinishLaunch(WDock *dock, WAppIcon *icon);
|
void wDockFinishLaunch(WDock *dock, WAppIcon *icon);
|
||||||
void wDockTrackWindowLaunch(WDock *dock, Window window);
|
void wDockTrackWindowLaunch(WDock *dock, Window window);
|
||||||
|
|||||||
Reference in New Issue
Block a user